@@ -9,10 +9,10 @@ import (
9
9
"github.com/GhostTroops/scan4all/lib/util"
10
10
"github.com/GhostTroops/scan4all/pkg/fingerprint"
11
11
"github.com/antlabs/strsim"
12
- "io/ioutil"
13
12
"log"
14
13
"mime"
15
14
"net/url"
15
+ "os"
16
16
"path/filepath"
17
17
"regexp"
18
18
"strings"
@@ -123,14 +123,14 @@ var regs []string
123
123
var (
124
124
regsMap = make (map [string ]* regexp.Regexp ) // fuzz 正则库
125
125
disabledFileFuzz = false // 是否开启fuzz
126
- NoDoPath = sync.Map {}
126
+ NoDoPath sync.Map
127
127
NoDoPathInit = false
128
128
)
129
129
130
130
func DoInitMap () {
131
131
if NoDoPathInit == false && "" != fingerprint .FgDictFile {
132
132
NoDoPathInit = true
133
- if data , err := ioutil .ReadFile (fingerprint .FgDictFile ); nil == err {
133
+ if data , err := os .ReadFile (fingerprint .FgDictFile ); nil == err {
134
134
a := strings .Split (strings .TrimSpace (string (data )), "\n " )
135
135
for _ , k := range a {
136
136
NoDoPath .Store (k , true )
@@ -181,13 +181,23 @@ type FuzzData struct {
181
181
}
182
182
183
183
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
184
- var r001 = regexp .MustCompile (`\.(aac)|(abw)|(arc)|(avif)|(avi)|(azw)|(bin)|(bmp)|(bz)|(bz2)|(cda)|(csh)|(css)|(csv)|(doc)|(docx)|(eot)|(epub)|(gz)|(gif)|(ico)|(ics)|(jar)|(jpeg)|(jpg)|(js)|(json)|(jsonld)|(mid)|(midi)|(mjs)|(mp3)|(mp4)|(mpeg)|(mpkg)|(odp)|(ods)|(odt)|(oga)|(ogv)|(ogx)|(opus)|(otf)|(png)|(pdf)|(php)|(ppt)|(pptx)|(rar)|(rtf)|(sh)|(svg)|(tar)|(tif)|(tiff)|(ts)|(ttf)|(txt)|(vsd)|(wav)|(weba)|(webm)|(webp)|(woff)|(woff2)|(xhtml)|(xls)|(xlsx)|(xml)|(xul)|(zip)|(3gp)|(3g2)|(7z)$` )
184
+ var (
185
+ r001 = regexp .MustCompile (`\.(aac)|(abw)|(arc)|(avif)|(avi)|(azw)|(bin)|(bmp)|(bz)|(bz2)|(cda)|(csh)|(css)|(csv)|(doc)|(docx)|(eot)|(epub)|(gz)|(gif)|(ico)|(ics)|(jar)|(jpeg)|(jpg)|(js)|(json)|(jsonld)|(mid)|(midi)|(mjs)|(mp3)|(mp4)|(mpeg)|(mpkg)|(odp)|(ods)|(odt)|(oga)|(ogv)|(ogx)|(opus)|(otf)|(png)|(pdf)|(php)|(ppt)|(pptx)|(rar)|(rtf)|(sh)|(svg)|(tar)|(tif)|(tiff)|(ts)|(ttf)|(txt)|(vsd)|(wav)|(weba)|(webm)|(webp)|(woff)|(woff2)|(xhtml)|(xls)|(xlsx)|(xml)|(xul)|(zip)|(3gp)|(3g2)|(7z)$` )
186
+ cT1 = make (chan struct {}, 1 ) // 每次只允许1个url fuzz
187
+ )
185
188
186
189
// 重写了fuzz:优化流程、优化算法、修复线程安全bug、增加智能功能
187
190
//
188
191
// 两次 ioutil.ReadAll(resp.Body),第二次就会 Read返回EOF error
189
192
// 去除指纹请求的路径,避免重复
190
193
func FileFuzz (u string , indexStatusCode int , indexContentLength int , indexbody string ) ([]string , []string ) {
194
+ if util .TestRepeat (u ) {
195
+ return []string {}, []string {}
196
+ }
197
+ cT1 <- struct {}{}
198
+ defer func () {
199
+ <- cT1
200
+ }()
191
201
if disabledFileFuzz {
192
202
return []string {}, []string {}
193
203
}
@@ -233,7 +243,9 @@ func FileFuzz(u string, indexStatusCode int, indexContentLength int, indexbody s
233
243
}
234
244
var wg sync.WaitGroup
235
245
// 中途控制关闭当前目标所有fuzz
246
+ // 终止fuzz任务
236
247
ctx , stop := context .WithCancel (util .Ctx_global )
248
+ // 终止 接收结果任务
237
249
ctx2 , stop2 := context .WithCancel (util .Ctx_global )
238
250
// 控制 fuzz 线程数
239
251
var ch = make (chan struct {}, util .Fuzzthreads )
@@ -245,6 +257,7 @@ func FileFuzz(u string, indexStatusCode int, indexContentLength int, indexbody s
245
257
if strings .HasPrefix (url404req .Protocol , "HTTP/2" ) || strings .HasPrefix (url404req .Protocol , "HTTP/3" ) {
246
258
MaxErrorTimes = int32 (len (filedic ))
247
259
}
260
+ //var MaxErrorTimes int32 = 100
248
261
if c1 := util .GetClient (u , map [string ]interface {}{"Timeout" : 15 * time .Second , "ErrLimit" : MaxErrorTimes }); nil != c1 {
249
262
util .PutClientCc (u , c1 )
250
263
}
@@ -258,7 +271,9 @@ func FileFuzz(u string, indexStatusCode int, indexContentLength int, indexbody s
258
271
var lst200 * util.Response
259
272
t001 := time .NewTicker (3 * time .Second )
260
273
var nCnt int32 = 0
274
+ // 异步 接收 fuzz 结果
261
275
go func () {
276
+ defer stop ()
262
277
for {
263
278
select {
264
279
case <- ctx2 .Done ():
@@ -288,8 +303,6 @@ func FileFuzz(u string, indexStatusCode int, indexContentLength int, indexbody s
288
303
} else {
289
304
return
290
305
}
291
- default :
292
- time .Sleep (33 * time .Second )
293
306
// <-time.After(time.Duration(100) * time.Millisecond)
294
307
}
295
308
}
@@ -304,135 +317,133 @@ BreakAll:
304
317
continue
305
318
}
306
319
// 接收到停止信号
307
- if atomic .LoadInt32 (& errorTimes ) >= MaxErrorTimes {
320
+ if errorTimes >= MaxErrorTimes {
321
+ stop ()
308
322
break
309
323
}
310
324
select {
311
325
case <- ctx .Done ():
312
326
break BreakAll
313
327
default :
314
328
{
315
- //log.Println(u, " ", payload)
316
329
endP := u [len (u )- 1 :] == "/"
317
330
ch <- struct {}{}
318
331
wg .Add (1 )
319
332
go func (payload string ) {
320
333
payload = strings .TrimSpace (payload )
321
334
defer func () {
322
- wg . Done () // 控制所有线程结束
323
- <- ch // 并发控制
335
+ <- ch // 并发控制
336
+ wg . Done ()
324
337
}()
325
338
atomic .AddInt32 (& nCnt , 1 )
326
- for {
327
- select {
328
- case <- ctx .Done (): // 00-捕获所有线程关闭信号,并退出,close for all
329
- atomic .AddInt32 (& errorTimes , MaxErrorTimes )
339
+ select {
340
+ case <- ctx .Done (): // 00-捕获所有线程关闭信号,并退出,close for all
341
+ atomic .AddInt32 (& errorTimes , MaxErrorTimes )
342
+ return
343
+ default :
344
+ //if _, ok := noRpt.Load(szKey001Over); ok {
345
+ // stop()
346
+ // return
347
+ //}
348
+ // 01-异常>20关闭所有fuzz
349
+ if errorTimes >= MaxErrorTimes {
350
+ stop () //发停止指令
330
351
return
331
- default :
332
- //if _, ok := noRpt.Load(szKey001Over); ok {
333
- // stop()
334
- // return
352
+ }
353
+ // 修复url,默认 认为 payload 不包含/
354
+ szUrl := u + payload
355
+ if strings .HasPrefix (payload , "/" ) && endP {
356
+ szUrl = u + payload [1 :]
357
+ }
358
+ //log.Printf("start fuzz: [%s]", szUrl)
359
+ if fuzzPage , req , err := reqPage (szUrl ); err == nil && nil != req && 0 < len (req .Body ) {
360
+ if 200 == req .StatusCode {
361
+ if nil == lst200 {
362
+ lst200 = req
363
+ } else if lst200 .Body == req .Body { // 无意义的 200
364
+ return
365
+ }
366
+ if oU1 , err := url .Parse (szUrl ); nil == err {
367
+ a50 := r001 .FindStringSubmatch (oU1 .Path )
368
+ if 0 < len (a50 ) {
369
+ s2 := mime .TypeByExtension (filepath .Ext (a50 [0 ]))
370
+ ct := (* req ).Header .Get ("Content-Type" )
371
+ if "" != ct && "" != s2 && strings .Contains (ct , s2 ) {
372
+ return
373
+ }
374
+ }
375
+ }
376
+ //log.Printf("%d : %s \n", req.StatusCode, szUrl)
377
+ if IsLoginPage (szUrl , req .Body , req .StatusCode ) {
378
+ technologies = append (technologies , "loginpage" )
379
+ }
380
+ }
381
+ go util .CheckHeader (req .Header , u )
382
+ // 02-状态码和req1相同,且与req1相似度>9.5,关闭所有fuzz
383
+ fXsd := strsim .Compare (url404req .Body , req .Body )
384
+ bBig95 := 0.95 < fXsd
385
+ //if "/bea_wls_internal/classes/mejb@/org/omg/stub/javax/management/j2ee/_ManagementHome_Stub.class" == payload {
386
+ // log.Println("start debug")
335
387
//}
336
- // 01-异常>20关闭所有fuzz
337
- if atomic .LoadInt32 (& errorTimes ) >= MaxErrorTimes {
388
+ if url404 .StatusCode == fuzzPage .StatusCode && bBig95 {
338
389
stop () //发停止指令
390
+ atomic .AddInt32 (& errorTimes , MaxErrorTimes )
339
391
return
340
392
}
341
- // 修复url,默认 认为 payload 不包含/
342
- szUrl := u + payload
343
- if strings .HasPrefix (payload , "/" ) && endP {
344
- szUrl = u + payload [1 :]
345
- }
346
- //log.Printf("start fuzz: [%s]", szUrl)
347
- if fuzzPage , req , err := reqPage (szUrl ); err == nil && nil != req && 0 < len (req .Body ) {
348
- if 200 == req .StatusCode {
349
- if nil == lst200 {
350
- lst200 = req
351
- } else if lst200 .Body == req .Body { // 无意义的 200
352
- continue
353
- }
354
- if oU1 , err := url .Parse (szUrl ); nil == err {
355
- a50 := r001 .FindStringSubmatch (oU1 .Path )
356
- if 0 < len (a50 ) {
357
- s2 := mime .TypeByExtension (filepath .Ext (a50 [0 ]))
358
- ct := (* req ).Header .Get ("Content-Type" )
359
- if "" != ct && "" != s2 && strings .Contains (ct , s2 ) {
360
- continue
361
- }
362
- }
363
- }
364
- //log.Printf("%d : %s \n", req.StatusCode, szUrl)
365
- if IsLoginPage (szUrl , req .Body , req .StatusCode ) {
366
- technologies = append (technologies , "loginpage" )
367
- }
393
+ var path1 , technologies1 = []string {}, []string {}
394
+ // 03-异常页面(>400),或相似度与404匹配
395
+ if fuzzPage .StatusCode >= 400 || bBig95 || fuzzPage .StatusCode != 200 {
396
+ // 03.01-异常页面指纹匹配
397
+ technologies = Addfingerprints404 (technologies , req , fuzzPage ) //基于404页面文件扫描指纹添加
398
+ // 03.02-与绝对404相似度低于0.8,添加body 404 body list
399
+ // 03.03-添加404titlelist
400
+ if 0.8 > fXsd && fuzzPage .StatusCode != 200 && fuzzPage .StatusCode != url404 .StatusCode {
401
+ StudyErrPageAI (req , fuzzPage , "" ) // 异常页面学习
368
402
}
369
- go util .CheckHeader (req .Header , u )
370
- // 02-状态码和req1相同,且与req1相似度>9.5,关闭所有fuzz
371
- fXsd := strsim .Compare (url404req .Body , req .Body )
372
- bBig95 := 9.5 < fXsd
373
- //if "/bea_wls_internal/classes/mejb@/org/omg/stub/javax/management/j2ee/_ManagementHome_Stub.class" == payload {
374
- // log.Println("start debug")
375
- //}
376
- if url404 .StatusCode == fuzzPage .StatusCode && bBig95 {
377
- stop () //发停止指令
378
- atomic .AddInt32 (& errorTimes , MaxErrorTimes )
379
- return
380
- }
381
- var path1 , technologies1 = []string {}, []string {}
382
- // 03-异常页面(>400),或相似度与404匹配
383
- if fuzzPage .StatusCode >= 400 || bBig95 || fuzzPage .StatusCode != 200 {
384
- // 03.01-异常页面指纹匹配
385
- technologies = Addfingerprints404 (technologies , req , fuzzPage ) //基于404页面文件扫描指纹添加
386
- // 03.02-与绝对404相似度低于0.8,添加body 404 body list
387
- // 03.03-添加404titlelist
388
- if 0.8 > fXsd && fuzzPage .StatusCode != 200 && fuzzPage .StatusCode != url404 .StatusCode {
389
- StudyErrPageAI (req , fuzzPage , "" ) // 异常页面学习
390
- }
391
- // 04-403: 403 by pass
392
- if fuzzPage .Is403 && ! url404 .Is403 {
393
- a11 := ByPass403 (& u , & payload , & wg )
394
- // 表示 ByPass403 成功了, 结果、控制台输出点什么?
395
- if 0 < len (a11 ) {
396
- async_data <- & FuzzData {Path : & a11 , Req : fuzzPage }
397
- }
403
+ // 04-403: 403 by pass
404
+ if fuzzPage .Is403 && ! url404 .Is403 {
405
+ a11 := ByPass403 (& u , & payload , & wg )
406
+ // 表示 ByPass403 成功了, 结果、控制台输出点什么?
407
+ if 0 < len (a11 ) {
408
+ async_data <- & FuzzData {Path : & a11 , Req : fuzzPage }
398
409
}
399
- return
400
- }
401
- // 当前和绝对404不等于404,后续的比较也没有意义了,都等于[200,301,302]都没有意义了,都说明没有fuzz成功
402
- if url404 .StatusCode != 404 && url404 .StatusCode == fuzzPage .StatusCode {
403
- return
404
410
}
411
+ return
412
+ }
413
+ // 当前和绝对404不等于404,后续的比较也没有意义了,都等于[200,301,302]都没有意义了,都说明没有fuzz成功
414
+ if url404 .StatusCode != 404 && url404 .StatusCode == fuzzPage .StatusCode {
415
+ return
416
+ }
405
417
406
- // 05-跳转检测,即便是跳转,如果和绝对404不一样,说明检测成功
407
- //if CheckDirckt(fuzzPage, req) && url404.StatusCode != fuzzPage.StatusCode {
408
- // return
418
+ // 05-跳转检测,即便是跳转,如果和绝对404不一样,说明检测成功
419
+ //if CheckDirckt(fuzzPage, req) && url404.StatusCode != fuzzPage.StatusCode {
420
+ // return
421
+ //}
422
+ // 1、状态码和绝对404一样 2、智能识别算出来
423
+ is404Page := url404 .StatusCode == fuzzPage .StatusCode || CheckIsErrPageAI (req , fuzzPage )
424
+ // 06-成功页面, 非异常页面
425
+ if ! is404Page || 200 == fuzzPage .StatusCode && url404 .StatusCode != fuzzPage .StatusCode {
426
+ // 1、指纹匹配
427
+ technologies1 = Addfingerprintsnormal (payload , technologies1 , req , fuzzPage ) // 基于200页面文件扫描指纹添加
428
+ // 2、成功fuzz路径结果添加
429
+ path1 = append (path1 , * fuzzPage .Url )
430
+ }
431
+ if 0 < len (path1 ) {
432
+ async_data <- & FuzzData {Path : & path1 , Req : fuzzPage }
433
+ }
434
+ if 0 < len (technologies1 ) {
435
+ async_technologies <- technologies1
436
+ }
437
+ } else { // 这里应该元子操作
438
+ if nil != err {
439
+ //if nil != client && strings.Contains(err.Error(), " connect: connection reset by peer") {
440
+ // client.Client = client.GetClient(nil)
409
441
//}
410
- // 1、状态码和绝对404一样 2、智能识别算出来
411
- is404Page := url404 .StatusCode == fuzzPage .StatusCode || CheckIsErrPageAI (req , fuzzPage )
412
- // 06-成功页面, 非异常页面
413
- if ! is404Page || 200 == fuzzPage .StatusCode && url404 .StatusCode != fuzzPage .StatusCode {
414
- // 1、指纹匹配
415
- technologies1 = Addfingerprintsnormal (payload , technologies1 , req , fuzzPage ) // 基于200页面文件扫描指纹添加
416
- // 2、成功fuzz路径结果添加
417
- path1 = append (path1 , * fuzzPage .Url )
418
- }
419
- if 0 < len (path1 ) {
420
- async_data <- & FuzzData {Path : & path1 , Req : fuzzPage }
421
- }
422
- if 0 < len (technologies1 ) {
423
- async_technologies <- technologies1
424
- }
425
- } else { // 这里应该元子操作
426
- if nil != err {
427
- //if nil != client && strings.Contains(err.Error(), " connect: connection reset by peer") {
428
- // client.Client = client.GetClient(nil)
429
- //}
430
- //log.Printf("file fuzz %s is err %v\n", szUrl, err)
431
- }
432
- atomic .AddInt32 (& errorTimes , 1 )
442
+ //log.Printf("file fuzz %s is err %v\n", szUrl, err)
433
443
}
434
- return
444
+ atomic . AddInt32 ( & errorTimes , 1 )
435
445
}
446
+ return
436
447
}
437
448
}(payload )
438
449
}
0 commit comments