0x0 Introduction
We just developed a new anti-virus called ShamAV. Have fun!
Connect via
socat FILE:tty
,raw,echo=0 TCP:shamav.sdc.tf:1337
Flag path (Unix permission of flag is intended)
/home/antivirus/flag.txt
Note
Ignore directory /home/user, you don't need to access anything under it to get the flag
By k3v1n
0x1 Vulnerability
this challenge is basically manipulating with symbolic links.
First bug is os.lstat(path).st_uid != USER_UID
in server.py
.
According to man page, lstate()
will return the property of symbolic not the real file.
lstat() is identical to stat(), except that if pathname is a symbolic link, then it returns information about the link itself, not the file that the link refers to.
We can bypass this check by creating a symbolic link to the file that is not owned by us.
Second vuln is also related to symbolic links
if we have symbolic link point to anther file, overwrite this symbolic link would actually overwrite the real file.
Combine those two vuln, we can get seed
first, then predict next filename, create symbolic link point to server.py
.
Then, we scan our new file, which will overwrite server.py
.
After than, we crash server.py
, let launcher.sh
to restart server.py
and execute our code.
0x3 Walk through
first glance
challenge only provide a host and port, no other thing. But I can get everything I need through the shell.
connect to server, firstly I checked the permission of the flag.txt. flag.txt is owned by antivirus, but didn't have any permission. So, I need find a way to change the permission and read the flag.
1 | ctf@SHAMAV:~$ whoami |
then I looked at the scan
file under /home/ctf/bin. uhhh, its just a script, and how scan
works is sending file path to a socket, then retrieve result from that socket.
1 | # basically this file |
if we scan a file, the file will be copy to /home/antivirus/quarantine
with a random generated name. Moreover, this file is owned by antivirus
!
1 | ctf@SHAMAV:~/virus-samples$ scan phishing.py |
analysis
lets analysis two file that are responsible for the antivirus system. server.py
and launcher.sh
- check if file is owned by
ctf
,os.lstat(path).st_uid != USER_UID
- copy file to
/home/antivirus/quarantine
usingshutil.copyfile(path, target_path)
. target name is determined by a seed
the check can be easily bypassed by creating a symbolic link as i mentioned in the vulnerability section
- start server.py
- restart server.py if server.py crash.
filename is generate by following function, so if I know the seed, I can predict the filename that will be generated in the future.
1 | def genrandom(): |
the idea
I come up with following basic idea
- modify
server.py
so that it executechmod 777 flag.txt
- find way to crash
server.py
launcher.sh
will executechmod 777 flag.txt
and I can cat flag
crash server.py
is pretty easy, we create a symlink to flag.txt
, and pass flag.txt
to the server. since flag.txt
is not readable, the program will throw an exception and crash.
modify server.py
is bit tricky.
In server.py, we have shutil.copyfile(path, target_path)
that copy file. If the target_path
exists and it is a symbolic link, this will overwrite the real file. Using this, I can overwrite server.py
But how can i predict the filename, I need seed to do that.
Obtain seed
is also easy.
although ctf user don't have read permission on seed
file, I can "scan" seed
file and obtain seed from the file copied by server.py
final idea
- create symlink to
seed
, sendseed
to server and get seed - predict next filename, create symlink point to
server.py
using that name - create a file and execute
chmod 777 flag.txt
, scan this file and overwriteserver.py
- create symlink to
flag.txt
, sendflag.txt
to server and crash the server launcher.sh
will execute code and I can cat flag.
0x4 Exploit
file_name_predict.py
1 | #! /usr/bin/env python3 |
exploit
1 | ln -s /home/antivirus/seed /home/ctf/seed |
0x4 Flag
sdctf{5ymL1Nks_ar3_4_curs3d_f3a7uRe_0f_*NIX}