1+ package Detect
2+
3+ import (
4+ "FastjsonScan/Utils"
5+ "fmt"
6+ "io/ioutil"
7+ "log"
8+ "net/http"
9+ "net/http/httptrace"
10+ "regexp"
11+ "strings"
12+ "time"
13+ )
14+
15+ /**
16+ *** 识别fastjson(主要通过报错回显的方式)
17+ **/
18+
19+ func DetectFastjson (url string ) (bool ,string ){
20+ fmt .Println ("[+] 正在进行报错识别" )
21+ jsonType , _ := ErrDetectVersion (url )
22+ if jsonType == "jackson" {
23+ return false ,Utils .NOT_FS
24+ }
25+ if jsonType != "" {
26+ return true ,jsonType
27+ }
28+ return false ,jsonType
29+ }
30+
31+ /**
32+ *** 探测fastjson版本,目前包括:报错探测,DNS探测和延迟探测
33+ **/
34+
35+ func DetectVersion (url string ) Utils.Result {
36+ var result Utils.Result
37+ fmt .Println ("开始检测 " + url )
38+ result .Url = url
39+ //是否出网
40+ var payloads Utils.DNSPayloads
41+ isFastjson ,jsonType := DetectFastjson (url )
42+ if jsonType == "jackson" {
43+ result .Type = jsonType
44+ return result
45+ }
46+ //出网探测
47+ fmt .Println ("[+] 正在进行出网探测" )
48+ payload , session := Utils .NET_DETECT_FACTORY ()
49+ if DnslogDetect (url , payload , session ) != "[]" {
50+ //出网
51+ fmt .Println ("[*] 目标可出网" )
52+ result .Netout = true
53+ result .Type = "Fastjson"
54+ fmt .Println ("[+] 正在进行 AutoType状态 探测" )
55+ result .AutoType = DetectAutoType (url )
56+ result .Dependency = DetectDependency (url )
57+ if isFastjson && jsonType != Utils .NOT_FS && jsonType != "" {
58+ fmt .Println ("[+] Fastjson版本为 " + jsonType )
59+ result .Version = jsonType
60+ return result
61+ }
62+ fmt .Println ("[+] 正在进行版本探测" )
63+ payloads , session = Utils .DNS_DETECT_FACTORY ()
64+ if DnslogDetect (url , payloads .Dns_48 , session ) == "48" {
65+ result .Version = Utils .FJ_UNDER_48
66+ return result
67+ }
68+ if DnslogDetect (url , payloads .Dns_68 , session ) == "68" {
69+ if result .AutoType {
70+ result .Version = Utils .FJ_BEYOND_48
71+ return result
72+ }
73+ result .Version = Utils .FJ_BETWEEN_48_68
74+ return result
75+ }
76+ if DnslogDetect (url , payloads .Dns_80 , session ) == "80" {
77+ result .Version = Utils .FJ_BETWEEN_69_80
78+ return result
79+ }
80+ if DnslogDetect (url , payloads .Dns_80 , session ) == "83" {
81+ result .Version = Utils .FS_BEYOND_80
82+ return result
83+ }
84+ } else {
85+ //不出网
86+ fmt .Println ("[-] 目标不出网" )
87+ fmt .Println ("[+] 正在进行延迟探测" )
88+ if TimeDelayCheck (url ) {
89+ result .Netout = false
90+ result .Type = "Fastjson"
91+ result .Version = Utils .FS_BETWEEN_36_62
92+ return result
93+ //fastjson > 1.2.61 且 不出网
94+
95+ }
96+ }
97+
98+ result .Type = ""
99+ return result
100+ }
101+
102+
103+ /**
104+ *** 探测java环境依赖库
105+ **/
106+
107+ func DetectDependency (target string )[]string {
108+ fmt .Println ("[+] 正在进行依赖库探测" )
109+ fmt .Println ("[+] 正在进行报错探测" )
110+ var result []string
111+ findDependency := ErrDetectDependency (target ,Utils .DEPENDENCY_ERR_DETECT_FACTORY ())
112+ //fmt.Println(findDependency)
113+ if findDependency [0 ] == "" {
114+ fmt .Println ("[-] 报错探测未发现任何依赖库" )
115+ result [0 ] = ""
116+ }else {
117+ fmt .Println ("[*] 发现依赖库如下" )
118+ for dependency := range findDependency {
119+ if findDependency [dependency ] != "" {
120+ fmt .Println (findDependency [dependency ])
121+ result = append (result ,findDependency [dependency ])
122+ }
123+
124+ }
125+ }
126+ return result
127+ }
128+
129+
130+ /**
131+ *** Autotype 开启检测,需出网
132+ *** return True 为 开启 ; False 为 关闭
133+ **/
134+
135+ func DetectAutoType (url string ) bool {
136+ dnsurl ,session := Utils .GetDnslogUrl ()
137+ var result bool
138+ payload := Utils .AUTOTYPE_DETECT_FACTORY (dnsurl )
139+ if DnslogDetect (url ,payload ,session ) == "[]" {
140+ fmt .Println ("[-] 目标没有开启 AutoType" )
141+ result = false
142+ }else {
143+ fmt .Println ("[*] 目标开启了 AutoType " )
144+ result = true
145+ }
146+ return result
147+ }
148+
149+ func DnslogDetect (target string ,payload string ,session string ) string {
150+ reqBody := strings .NewReader (payload )
151+ httpReq , err := http .NewRequest ("POST" , target , reqBody )
152+ if err != nil {
153+ err .Error ()
154+ }
155+ httpReq .Header .Add ("Content-Type" , "application/json" )
156+ httpRsp , err := http .DefaultClient .Do (httpReq )
157+ if err != nil {
158+ err .Error ()
159+ }
160+ defer httpRsp .Body .Close ()
161+ //fmt.Println(session)
162+ time .Sleep (3 * time .Second ) // 等3秒钟,防止由于网络原因误报
163+ //fmt.Println(payload+":"+ Utils.GetDnslogRecord(session))
164+ return Utils .GetDnslogRecord (session )
165+ }
166+
167+ /**
168+ *** 报错探测
169+ **/
170+
171+ func ErrDetectVersion (target string ) (string ,bool ){
172+ var version string
173+ reqBody := strings .NewReader (Utils .FS_ERR_DETECT )
174+ httpReq , err := http .NewRequest ("POST" , target , reqBody )
175+ if err != nil {
176+ err .Error ()
177+ }
178+ httpReq .Header .Add ("Content-Type" , "application/json" )
179+ httpRsp , err := http .DefaultClient .Do (httpReq )
180+ if err != nil {
181+ err .Error ()
182+ }
183+ defer httpRsp .Body .Close ()
184+ body , err := ioutil .ReadAll (httpRsp .Body )
185+ if err != nil {
186+ err .Error ()
187+ }
188+ reg := regexp .MustCompile (`fastjson-version\s\d.\d.[0-9]+` )
189+
190+ version = reg .FindString (string (body ))
191+ if version == "" {
192+ reg = regexp .MustCompile (`jackson` )
193+ version = reg .FindString (string (body ))
194+ return version ,false
195+ }else {
196+ return version [17 :],true
197+ }
198+ }
199+
200+ func ErrDetectDependency (target string , payloadsMap map [string ]string ) []string {
201+ var result = make ([]string , len (payloadsMap ))
202+ var cursor = 0
203+ for dependencyName , payload := range payloadsMap {
204+ reqBody := strings .NewReader (payload )
205+ httpReq , err := http .NewRequest ("POST" , target , reqBody )
206+ if err != nil {
207+ err .Error ()
208+ }
209+ httpReq .Header .Add ("Content-Type" , "application/json" )
210+ httpRsp , err := http .DefaultClient .Do (httpReq )
211+ if err != nil {
212+ err .Error ()
213+ }
214+ defer httpRsp .Body .Close ()
215+ body , err := ioutil .ReadAll (httpRsp .Body )
216+ //fmt.Println(string(body))
217+ if err != nil {
218+ err .Error ()
219+ }
220+ reg := regexp .MustCompile (dependencyName )
221+
222+ find := reg .FindString (string (body ))
223+ if find != "" {
224+ result [cursor ] = dependencyName
225+ cursor ++
226+ }
227+ }
228+ return result
229+ }
230+
231+ /**
232+ *** 延迟探测
233+ **/
234+
235+ func TimeDelayCheck (url string ) bool {
236+ var count int
237+ var start int64
238+ var pos int64 = 0
239+ for i := 0 ; i < 5 ; i ++ {
240+ start = pos
241+ payloads := Utils .TIME_DETECT_FACTORY (5 )
242+ pos = TimeGet (url ,payloads [i ])
243+ if pos - start > 0 {
244+ count ++
245+ }
246+ }
247+ if count > 3 {
248+ return true
249+ }
250+ return false
251+ }
252+
253+ /**
254+ *** 获取请求的时间
255+ **/
256+
257+ func TimeGet (url string ,payload string ) int64 {
258+ reqBody := strings .NewReader (payload )
259+ req , _ := http .NewRequest ("POST" , url , reqBody )
260+ var start time.Time
261+
262+ trace := & httptrace.ClientTrace {
263+ GotFirstResponseByte : func () {
264+ //fmt.Printf("Time from start to first byte: %v\n", time.Since(start))
265+ },
266+ }
267+ req = req .WithContext (httptrace .WithClientTrace (req .Context (), trace ))
268+ start = time .Now ()
269+ if _ , err := http .DefaultTransport .RoundTrip (req ); err != nil {
270+ log .Fatal (err )
271+ }
272+ //fmt.Printf("Total time: %v\n", time.Since(start))
273+ return int64 (time .Since (start ))
274+ }
0 commit comments