zoukankan      html  css  js  c++  java
  • 以一道CTF题目看无参数RCE

    0x00 前言

    前几天做到了一些无参数RCE的题目,自己记性不行,这里总结一下,方便以后随时捡起来看看.


    0x01 源码特点分析

    1. 源码中过滤了常用伪协议,用正则表达式规定只可以使用无参数函数进行RCE,具体可以看下段代码:

      第一个if过滤掉了常用的伪协议,无法直接使用伪协议读取文件.

      第二个if用了一个比较复杂的正则表达式,对输入的exp参数进行匹配,把匹配到的字符串全部替换为NULL(不改变exp的值),然后检测替换之后的字符串是否只剩一个分号.

      来分析一下那个奇怪的正则表达式,[a-z,_]限制了只可以是小写字母以及下划线,(?R)是引用当前表达式的意思,就是把当前的整个表达式替换到(?R)的位置,(?R)?这里最后一个?表示这个引用可有可无,就是说,可以匹配,也可以不匹配.也就是说这个正则只可以匹配到无参数的函数,如a(),a(b()),a(b(c())).

      第三个if过滤了一些函数的关键字,需要构造别的方法去绕过.

    1. 无参数RCE,具体怎么解释呢?

      var_dump(scandir()); //可以使用

      var_dump(scandir('.')) //不可以使用

      也就是说,我们可以使用函数套娃的形式,来逐层实现我们RCE的命令.


    0x02 以一道题目来看无参数RCE

      [GXYCTF2019]禁止套娃

      题目存在git泄露,这里有一个问题就是用dirsearch扫会导致访问过快从而扫不到./git,不知道是扫描工具原因还是题目问题.

    1. 来看源码

      传入exp参数,经过三个if函数判断后,如果满足条件会执行exp参数.

      eval($_GET['exp']); 典型的无参数RCE.

    1. 这中过滤条件,想要getshell没戏了,从源码中得知flag应该就在flag.php中,那么这道题目的意思就是使用无参数RCE来读取到flag.php中的内容.

    2. 具体改怎么做呢?下面看几个函数:

      scandir():扫描当前目录下的文件,并以数组的形式返回

      localeconv():返回一个包含本地数字及货币格式信息的数组,该数组的第一项就是'.'

      current():返回当前数组的当前单元,默认值是第一个

      pos():同current()

      组合拳1:获取当前目录下的文件

        要获取当前目录下的文件,应该想到scandir('.'),知道上面的三个函数,就可以把它构造出来了.

        payload:var_dump(scandir(current(localeconv())); //别忘了加分号

        用current(localeconv())代替了'.'

    1. 要读取的flag.php在数组中的索引值是3,也就是在第4个位置,问题就是该怎么读取到呢?好在php为我们提供了这些函数:

      array_reverse():以相反的顺序返回数组

      next():将数组中的内部指着指向下一个元素并输出

      array_rand():从数组中随机获取一个或多个单元

      组合拳2:读取到flag.php的内容

        payload1:readfile(next(array_reverse(scandir(current(localeconv())))));

        因为flag.php是在数组中的倒数第二个位置,所以将数组倒置之后变成了第二个位置,用next()函数将数组内部指针位置指向第二个元素,成功读取flag.php

        payload2:readfile(array_rand(scandir(current(localeconv()))));

        多刷新几次,即可读取到flag.php

    5.另一种解法:

      session_id():可以获取到当前的会话ID.

      session_start():会创建新会话或者重用现有会话。如果通过 GET 或者 POST 方式,或者使用 cookie 提交了会话 ID, 则会重用现有会话。

      因为SessionID是存放在客户端的cookie中的,所以我们可以手动设置会话ID为flag.php来读取到其中的内容

      payload:readfile(session_id(session_start())); //注意一点,session_start()必须在session_id()之前调用,使服务器端使用我们cookie提交的会话ID.


    0x03 后话

      可以使用函数还有很多,以后再另写一篇文章总结吧.

  • 相关阅读:
    设计模式课程 设计模式精讲 11-2 装饰者模式coding
    设计模式课程 设计模式精讲 10-3 外观模式源码解析
    设计模式课程 设计模式精讲 11-1 装饰者模式讲解
    设计模式课程 设计模式精讲 10-2 外观模式coding
    设计模式课程 设计模式精讲 10-1 外观模式讲解
    设计模式课程 设计模式精讲 重点
    设计模式课程 设计模式精讲 9-4 原型模式源码解析
    设计模式课程 设计模式精讲 9-3 原型模式-克隆破坏单例
    iframe平铺到浏览器
    密码输入框
  • 原文地址:https://www.cnblogs.com/hello-there/p/12880566.html
Copyright © 2011-2022 走看看