├── .gitignore
├── Dockerfile
├── LICENSE.md
├── README.md
├── cmd
└── wafme0w
│ ├── main.go
│ └── resources
│ └── waf-fingerprints.json
├── go.mod
├── go.sum
└── pkg
├── utils
├── http
│ ├── httputil.go
│ └── httputil_test.go
└── strings
│ ├── strings.go
│ └── strings_test.go
└── wafme0w
├── banner.go
├── generic_detection.go
├── http.go
├── identify.go
├── options.go
├── output.go
├── request.go
└── runner.go
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | vendor/
3 | .idea
4 | .devcontainer
5 |
6 |
7 | # Binaries for programs and plugins
8 | *.exe
9 | *.exe~
10 | *.dll
11 | *.so
12 | *.dylib
13 |
14 | # Test binary, built with `go test -c`
15 | *.test
16 |
17 | # Output of the go coverage tool, specifically when used with LiteIDE
18 | *.out
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:1.19.5-alpine as build-env
2 | RUN apk add build-base
3 | RUN go install -v github.com/Lu1sDV/wafme0w/cmd/wafme0w@latest
4 |
5 | FROM alpine:3.17.1
6 | RUN apk add --no-cache bind-tools ca-certificates
7 | COPY --from=build-env /go/bin/wafme0w /usr/local/bin/wafme0w
8 | ENTRYPOINT ["wafme0w"]
9 |
10 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Luis Di Vittorio
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | Wafme0w
4 |
5 |
6 | Fast and lightweight Web Application Firewall fingerprinting tool.
7 |
8 | # Features
9 |
10 | Based on Wafw00f, its features are:
11 |
12 | - Can detect **153** different Firewalls
13 | - Concurrent fingerprinting
14 | - **STDIN** supported
15 | - Fast detection mode for huge target lists
16 | - Multiple output formats supported (JSON, file, stdout)
17 |
18 | # Benchmark
19 |
20 | Scanned Alexa top 100 domains. Running on i7-7700K CPU @ 4.20GHz × 4 (8 Threads)
21 |
22 |
23 |
24 |
25 | tool |
26 | flags |
27 | Time elapsed |
28 | Wafs found |
29 | Generic Wafs found |
30 | Diff |
31 |
32 |
33 |
34 |
35 |
36 | wafme0w |
37 | --fast --concurrency 30 |
38 | 1min 37s (Best) |
39 | 20 |
40 | 11 |
41 | +0% |
42 |
43 |
44 | wafme0w |
45 | --concurrency 30 |
46 | 3min 51s |
47 | 22 (Best) |
48 | 16 |
49 | +138% |
50 |
51 |
52 | wafw00f |
53 | |
54 | 13min 3s |
55 | 20 |
56 | 16 |
57 | +707% |
58 |
59 |
60 | wafw00f |
61 | -a |
62 | 15min 8s |
63 | 20 |
64 | 23 (Best) |
65 | +836% |
66 |
67 |
68 |
69 |
70 |
71 | # Getting started
72 | ## Installation
73 | `wafme0w` requires **go >= 1.19** to install successfully. Run the following command to install the latest version:
74 |
75 | ```sh
76 | go install -v github.com/Lu1sDV/wafme0w/cmd/wafme0w@latest
77 | ```
78 | ## Building Docker image
79 | ```sh
80 | git clone https://github.com/Lu1sDV/wafme0w.git
81 | cd wafme0w
82 | docker build -t wafme0w:latest .
83 | ```
84 |
85 | ## Running Docker container
86 | ```
87 | docker run --rm -it wafme0w:latest -t https://canva.com
88 |
89 |
90 | /\_/\ ___
91 | = o_o =_______ \ \
92 | __^ __( \.__) )
93 | <_____>__(_____)____/
94 |
95 | Wafme0w v1.0.0
96 |
97 | Fast Web Application Firewall Fingerprinting tool
98 |
99 | [+] https://canva.com is behind Cloudflare (Cloudflare Inc.)
100 |
101 | ```
102 |
103 | ## Running Wafme0w
104 |
105 | To run the tool on a target, just use the following command.
106 |
107 | ```console
108 | cat /tmp/alexa-top-30.txt | wafme0w --concurrency 30 --no-warning --no-generic
109 |
110 |
111 | /\_/\ ___
112 | = o_o =_______ \ \
113 | __^ __( \.__) )
114 | <_____>__(_____)____/
115 |
116 | Wafme0w v1.0.0
117 |
118 | Fast Web Application Firewall Fingerprinting tool
119 |
120 | [~] https://microsoftonline.com no WAFs have been found
121 | [~] https://reddit.com no WAFs have been found
122 | [+] https://canva.com is behind Cloudflare (Cloudflare Inc.)
123 | [~] https://whatsapp.com no WAFs have been found
124 | [~] https://microsoft.com no WAFs have been found
125 | [~] https://live.com no WAFs have been found
126 | [~] https://163.com no WAFs have been found
127 | [~] https://yandex.ru no WAFs have been found
128 | [~] https://zhihu.com no WAFs have been found
129 | [~] https://taobao.com no WAFs have been found
130 | [~] https://wikipedia.org no WAFs have been found
131 | [~] https://qq.com no WAFs have been found
132 | [~] https://bilibili.com no WAFs have been found
133 | [~] https://bing.com no WAFs have been found
134 | [~] https://vk.com no WAFs have been found
135 | [~] https://facebook.com no WAFs have been found
136 | [~] https://twitch.tv no WAFs have been found
137 | [~] https://google.com no WAFs have been found
138 | [~] https://yahoo.com no WAFs have been found
139 | [~] https://linkedin.com no WAFs have been found
140 | [~] https://twitter.com no WAFs have been found
141 | [~] https://office.com no WAFs have been found
142 | [+] https://zoom.us is behind Cloudflare (Cloudflare Inc.)
143 | [~] https://csdn.net no WAFs have been found
144 | [~] https://github.com no WAFs have been found
145 | [~] https://baidu.com no WAFs have been found
146 | [~] https://netflix.com no WAFs have been found
147 | [+] https://amazon.com is behind Cloudfront (Amazon)
148 | [~] https://instagram.com no WAFs have been found
149 | [~] https://youtube.com no WAFs have been found
150 |
151 | ```
152 |
153 |
154 |
155 |
156 | ## Wafme0w Go library
157 |
158 | Usage Example:
159 | ```go
160 | package main
161 |
162 | import (
163 | "bytes"
164 | "fmt"
165 | "github.com/Lu1sDV/wafme0w/pkg/wafme0w"
166 | "os"
167 | )
168 |
169 | func main() {
170 | targets := []byte("https://google.com\nhttps://paypal.com\n")
171 | targetsReader := bytes.NewReader(targets)
172 | /*
173 | Otherwise you can also load your targets from a file
174 | targetsReader, err := os.Open("/tmp/alexa-top-20.txt")
175 | if err != nil {
176 | panic(err)
177 | }
178 | */
179 | fingerPrintsFile, err := os.Open("/PATH/TO/wafme0w/cmd/wafme0w/resources/waf-fingerprints.json")
180 | //fingerprints at https://github.com/Lu1sDV/wafme0w/blob/main/cmd/wafme0w/resources/waf-fingerprints.json
181 | opts := &wafme0w.Options{Inputs: targetsReader,
182 | FingerPrints: fingerPrintsFile,
183 | Silent: true,
184 | Concurrency: 10,
185 | //FastMode: true,
186 | //OutputFile: "myout.json",
187 | }
188 | runner := wafme0w.NewRunner(opts)
189 | result, err := runner.Scan()
190 | if err != nil {
191 | panic(err)
192 | }
193 | fmt.Printf("%#v\n", result)
194 | }
195 |
196 | ```
197 | |
198 |
199 |
200 |
201 | # Thanks
202 | People who contributed
203 |
204 | [@Fibonaccispiralz](https://github.com/Fibonaccispiralz)
205 |
206 | # Contact
207 |
208 | divittorioluis **AT** gmail **DOT** com
209 |
210 | Project Link: [https://github.com/Lu1sDV/wafme0w](https://github.com/Lu1sDV/wafme0w)
211 |
212 |
213 |
--------------------------------------------------------------------------------
/cmd/wafme0w/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | _ "embed"
6 | "github.com/Lu1sDV/wafme0w/pkg/wafme0w"
7 | "github.com/jessevdk/go-flags"
8 | "github.com/logrusorgru/aurora/v4"
9 | "os"
10 | "strings"
11 | )
12 |
13 | //go:embed resources/waf-fingerprints.json
14 | var embeddedFingerPrints []byte
15 |
16 | func main() {
17 | opts := wafme0w.NewOptions()
18 |
19 | args := os.Args
20 |
21 | _, err := flags.ParseArgs(opts, args)
22 | if err != nil {
23 | os.Exit(0)
24 | }
25 |
26 | if hasStdin() {
27 | opts.StdIn = true
28 | opts.Inputs = os.Stdin
29 | }
30 |
31 | if !opts.StdIn && len(args) < 2 {
32 | args = []string{"--help"}
33 | }
34 |
35 | au := aurora.New(aurora.WithColors(!opts.NoColors))
36 | if !opts.Silent {
37 | wafme0w.PrintBanner()
38 | }
39 |
40 | if opts.Silent && opts.OutputFile == "" {
41 | wafme0w.PrintError("You must provide a valid output file when Silent mode is enabled", au)
42 | os.Exit(1)
43 | }
44 |
45 | //check if target input has been provided
46 | if opts.InputFile == "" && opts.Target == "" && !opts.StdIn && !opts.ListWAFS {
47 | wafme0w.PrintError("No targets provided", au)
48 | os.Exit(1)
49 | }
50 |
51 | //parse inputs if provided by command line arguments
52 | if !opts.StdIn {
53 | if opts.Target != "" {
54 | opts.Inputs = strings.NewReader(opts.Target)
55 | }
56 | if opts.InputFile != "" {
57 | //input file shadows target option
58 | file, err := os.Open(opts.InputFile)
59 | if err != nil {
60 | errText := "error reading input file: " + err.Error()
61 | wafme0w.PrintError(errText, au)
62 | }
63 | opts.Inputs = file
64 | }
65 | }
66 | fingerPrints, err := readFingerPrints(opts.FingerPrintFile)
67 | if err != nil {
68 | errText := "Error reading fingerprints: " + err.Error()
69 | wafme0w.PrintError(errText, au)
70 | }
71 | opts.FingerPrints = bytes.NewReader(fingerPrints)
72 |
73 | runner := wafme0w.NewRunner(opts)
74 | runner.Aurora = au
75 |
76 | if opts.ListWAFS {
77 | wafs, err := runner.GetAllWAFs()
78 | if err != nil {
79 | wafme0w.PrintError("Error displaying firewalls", au)
80 | os.Exit(1)
81 | }
82 | wafme0w.PrintAllWafs(wafs, au)
83 | os.Exit(0)
84 | }
85 |
86 | _, err = runner.Scan()
87 | if err != nil {
88 | errorString := "Scan error: " + err.Error()
89 | wafme0w.PrintError(errorString, au)
90 | os.Exit(1)
91 | }
92 | }
93 |
94 | func hasStdin() bool {
95 | stat, err := os.Stdin.Stat()
96 | if err != nil {
97 | return false
98 | }
99 |
100 | isPipedFromChrDev := (stat.Mode() & os.ModeCharDevice) == 0
101 | isPipedFromFIFO := (stat.Mode() & os.ModeNamedPipe) != 0
102 |
103 | return isPipedFromChrDev || isPipedFromFIFO
104 | }
105 |
106 | func readFingerPrints(fingerPrintsFile string) ([]byte, error) {
107 | if fingerPrintsFile == "" {
108 | return embeddedFingerPrints, nil
109 | }
110 |
111 | dat, err := os.ReadFile(fingerPrintsFile)
112 | if err != nil {
113 | return nil, err
114 | }
115 | return dat, nil
116 | }
117 |
--------------------------------------------------------------------------------
/cmd/wafme0w/resources/waf-fingerprints.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "Expression Engine (EllisLab)",
4 | "schemas": [
5 | {
6 | "fingerprints": [
7 | {
8 | "type": "Cookie",
9 | "pattern": "(?i)^exp_track.+?="
10 | },
11 | {
12 | "type": "Cookie",
13 | "pattern": "(?i)^exp_last_.+?=",
14 | "attack": true
15 | },
16 | {
17 | "type": "Content",
18 | "pattern": "(?i)invalid get data"
19 | }
20 | ],
21 | "any": true
22 | }
23 | ]
24 | },
25 | {
26 | "name": "NetScaler AppFirewall (Citrix Systems)",
27 | "schemas": [
28 | {
29 | "fingerprints": [
30 | {
31 | "type": "Header",
32 | "header_key": "Via",
33 | "header_value": "(?i)NS\\-CACHE"
34 | },
35 | {
36 | "type": "Cookie",
37 | "pattern": "(?i)^(ns_af=|citrix_ns_id|NSC_)"
38 | },
39 | {
40 | "type": "Content",
41 | "pattern": "(?i)(NS Transaction|AppFW Session) id"
42 | },
43 | {
44 | "type": "Content",
45 | "pattern": "(?i)Violation Category.{0,5}?APPFW_"
46 | },
47 | {
48 | "type": "Content",
49 | "pattern": "(?i)Citrix\\|NetScaler"
50 | },
51 | {
52 | "type": "Header",
53 | "header_key": "Cneonction",
54 | "header_value": "(?i)^(keep alive|close)",
55 | "attack": true
56 | },
57 | {
58 | "type": "Header",
59 | "header_key": "nnCoection",
60 | "header_value": "(?i)^(keep alive|close)",
61 | "attack": true
62 | }
63 | ],
64 | "any": true
65 | }
66 | ]
67 | },
68 | {
69 | "name": "Beluga CDN (Beluga)",
70 | "schemas": [
71 | {
72 | "fingerprints": [
73 | {
74 | "type": "Header",
75 | "header_key": "Server",
76 | "header_value": "(?i)Beluga"
77 | },
78 | {
79 | "type": "Cookie",
80 | "pattern": "(?i)^beluga_request_trail="
81 | }
82 | ],
83 | "any": true
84 | }
85 | ]
86 | },
87 | {
88 | "name": "Shieldon Firewall (Shieldon.io)",
89 | "schemas": [
90 | {
91 | "fingerprints": [
92 | {
93 | "type": "Content",
94 | "pattern": "(?i)Please solve CAPTCHA"
95 | },
96 | {
97 | "type": "Content",
98 | "pattern": "(?i)shieldon_captcha"
99 | },
100 | {
101 | "type": "Content",
102 | "pattern": "(?i)Unusual behavior detected"
103 | },
104 | {
105 | "type": "Content",
106 | "pattern": "(?i)status-user-info"
107 | }
108 | ]
109 | },
110 | {
111 | "fingerprints": [
112 | {
113 | "type": "Content",
114 | "pattern": "(?i)Access denied"
115 | },
116 | {
117 | "type": "Content",
118 | "pattern": "(?i)The IP address you are using has been blocked."
119 | },
120 | {
121 | "type": "Content",
122 | "pattern": "(?i)status-user-info"
123 | }
124 | ]
125 | },
126 | {
127 | "fingerprints": [
128 | {
129 | "type": "Content",
130 | "pattern": "(?i)Please line up"
131 | },
132 | {
133 | "type": "Content",
134 | "pattern": "(?i)This page is limiting the number of people online. Please wait a moment."
135 | }
136 | ]
137 | }
138 | ]
139 | },
140 | {
141 | "name": "RequestValidationMode (Microsoft)",
142 | "schemas": [
143 | {
144 | "fingerprints": [
145 | {
146 | "type": "Content",
147 | "pattern": "(?i)Request Validation has detected a potentially dangerous client input"
148 | },
149 | {
150 | "type": "Content",
151 | "pattern": "(?i)ASP\\.NET has detected data in the request"
152 | },
153 | {
154 | "type": "Content",
155 | "pattern": "(?i)HttpRequestValidationException"
156 | }
157 | ],
158 | "any": true
159 | }
160 | ]
161 | },
162 | {
163 | "name": "URLMaster SecurityCheck (iFinity/DotNetNuke)",
164 | "schemas": [
165 | {
166 | "fingerprints": [
167 | {
168 | "type": "Header",
169 | "header_key": "X-UrlMaster-Debug",
170 | "header_value": "(?i).+"
171 | },
172 | {
173 | "type": "Header",
174 | "header_key": "X-UrlMaster-Ex",
175 | "header_value": "(?i).+"
176 | }
177 | ],
178 | "any": true
179 | },
180 | {
181 | "fingerprints": [
182 | {
183 | "type": "Content",
184 | "pattern": "(?i)Ur[li]RewriteModule"
185 | },
186 | {
187 | "type": "Content",
188 | "pattern": "(?i)SecurityCheck"
189 | }
190 | ]
191 | }
192 | ]
193 | },
194 | {
195 | "name": "Teros (Citrix Systems)",
196 | "schemas": [
197 | {
198 | "fingerprints": [
199 | {
200 | "type": "Cookie",
201 | "pattern": "(?i)^st8id="
202 | }
203 | ],
204 | "any": true
205 | }
206 | ]
207 | },
208 | {
209 | "name": "CdnNS Application Gateway (CdnNs/WdidcNet)",
210 | "schemas": [
211 | {
212 | "fingerprints": [
213 | {
214 | "type": "Content",
215 | "pattern": "(?i)cdnnswaf application gateway"
216 | }
217 | ],
218 | "any": true
219 | }
220 | ]
221 | },
222 | {
223 | "name": "Cloudbric (Penta Security)",
224 | "schemas": [
225 | {
226 | "fingerprints": [
227 | {
228 | "type": "Content",
229 | "pattern": "(?i)\u003ctitle\u003eCloudbric.{0,5}?ERROR!"
230 | },
231 | {
232 | "type": "Content",
233 | "pattern": "(?i)Your request was blocked by Cloudbric"
234 | },
235 | {
236 | "type": "Content",
237 | "pattern": "(?i)please contact Cloudbric Support"
238 | },
239 | {
240 | "type": "Content",
241 | "pattern": "(?i)cloudbric\\.zendesk\\.com"
242 | },
243 | {
244 | "type": "Content",
245 | "pattern": "(?i)Cloudbric Help Center"
246 | },
247 | {
248 | "type": "Content",
249 | "pattern": "(?i)malformed request syntax.{0,4}?invalid request message framing.{0,4}?or deceptive request routing"
250 | }
251 | ],
252 | "any": true
253 | }
254 | ]
255 | },
256 | {
257 | "name": "Incapsula (Imperva Inc.)",
258 | "schemas": [
259 | {
260 | "fingerprints": [
261 | {
262 | "type": "Cookie",
263 | "pattern": "(?i)^incap_ses.*?="
264 | },
265 | {
266 | "type": "Cookie",
267 | "pattern": "(?i)^visid_incap.*?="
268 | },
269 | {
270 | "type": "Content",
271 | "pattern": "(?i)incapsula incident id"
272 | },
273 | {
274 | "type": "Content",
275 | "pattern": "(?i)powered by incapsula"
276 | },
277 | {
278 | "type": "Content",
279 | "pattern": "(?i)/_Incapsula_Resource"
280 | }
281 | ],
282 | "any": true
283 | }
284 | ]
285 | },
286 | {
287 | "name": "Reblaze (Reblaze)",
288 | "schemas": [
289 | {
290 | "fingerprints": [
291 | {
292 | "type": "Cookie",
293 | "pattern": "(?i)^rbzid"
294 | },
295 | {
296 | "type": "Header",
297 | "header_key": "Server",
298 | "header_value": "(?i)Reblaze Secure Web Gateway"
299 | }
300 | ],
301 | "any": true
302 | },
303 | {
304 | "fingerprints": [
305 | {
306 | "type": "Content",
307 | "pattern": "(?i)current session has been terminated"
308 | },
309 | {
310 | "type": "Content",
311 | "pattern": "(?i)do not hesitate to contact us"
312 | },
313 | {
314 | "type": "Content",
315 | "pattern": "(?i)access denied \\(\\d{3}\\)"
316 | }
317 | ]
318 | }
319 | ]
320 | },
321 | {
322 | "name": "Yunjiasu (Baidu Cloud Computing)",
323 | "schemas": [
324 | {
325 | "fingerprints": [
326 | {
327 | "type": "Header",
328 | "header_key": "Server",
329 | "header_value": "(?i)Yunjiasu(.+)?"
330 | }
331 | ],
332 | "any": true
333 | }
334 | ]
335 | },
336 | {
337 | "name": "Sitelock (TrueShield)",
338 | "schemas": [
339 | {
340 | "fingerprints": [
341 | {
342 | "type": "Content",
343 | "pattern": "(?i)SiteLock will remember you"
344 | },
345 | {
346 | "type": "Content",
347 | "pattern": "(?i)Sitelock is leader in Business Website Security Services"
348 | },
349 | {
350 | "type": "Content",
351 | "pattern": "(?i)sitelock[_\\-]shield([_\\-]logo|[\\-_]badge)?"
352 | },
353 | {
354 | "type": "Content",
355 | "pattern": "(?i)SiteLock incident ID"
356 | }
357 | ],
358 | "any": true
359 | }
360 | ]
361 | },
362 | {
363 | "name": "NinjaFirewall (NinTechNet)",
364 | "schemas": [
365 | {
366 | "fingerprints": [
367 | {
368 | "type": "Content",
369 | "pattern": "(?i)\u003ctitle\u003eNinjaFirewall.{0,10}?\\d{3}.forbidden"
370 | },
371 | {
372 | "type": "Content",
373 | "pattern": "(?i)For security reasons?.{0,10}?it was blocked and logged"
374 | }
375 | ]
376 | }
377 | ]
378 | },
379 | {
380 | "name": "eEye SecureIIS (BeyondTrust)",
381 | "schemas": [
382 | {
383 | "fingerprints": [
384 | {
385 | "type": "Content",
386 | "pattern": "(?i)SecureIIS is an internet security application"
387 | },
388 | {
389 | "type": "Content",
390 | "pattern": "(?i)Download SecureIIS Personal Edition"
391 | },
392 | {
393 | "type": "Content",
394 | "pattern": "(?i)https?://www\\.eeye\\.com/Secure\\-?IIS"
395 | }
396 | ],
397 | "any": true
398 | }
399 | ]
400 | },
401 | {
402 | "name": "Secure Entry (United Security Providers)",
403 | "schemas": [
404 | {
405 | "fingerprints": [
406 | {
407 | "type": "Header",
408 | "header_key": "Server",
409 | "header_value": "(?i)Secure Entry Server"
410 | }
411 | ],
412 | "any": true
413 | }
414 | ]
415 | },
416 | {
417 | "name": "Jiasule (Jiasule)",
418 | "schemas": [
419 | {
420 | "fingerprints": [
421 | {
422 | "type": "Header",
423 | "header_key": "Server",
424 | "header_value": "(?i)jiasule\\-waf"
425 | },
426 | {
427 | "type": "Cookie",
428 | "pattern": "(?i)^jsl_tracking(.+)?="
429 | },
430 | {
431 | "type": "Cookie",
432 | "pattern": "(?i)__jsluid="
433 | },
434 | {
435 | "type": "Content",
436 | "pattern": "(?i)notice\\-jiasule"
437 | },
438 | {
439 | "type": "Content",
440 | "pattern": "(?i)static\\.jiasule\\.com"
441 | }
442 | ],
443 | "any": true
444 | }
445 | ]
446 | },
447 | {
448 | "name": "DDoS-GUARD (DDOS-GUARD CORP.)",
449 | "schemas": [
450 | {
451 | "fingerprints": [
452 | {
453 | "type": "Cookie",
454 | "pattern": "(?i)^__ddg1.*?="
455 | },
456 | {
457 | "type": "Cookie",
458 | "pattern": "(?i)^__ddg2.*?="
459 | },
460 | {
461 | "type": "Cookie",
462 | "pattern": "(?i)^__ddgid.*?="
463 | },
464 | {
465 | "type": "Cookie",
466 | "pattern": "(?i)^__ddgmark.*?="
467 | },
468 | {
469 | "type": "Header",
470 | "header_key": "Server",
471 | "header_value": "(?i)ddos-guard"
472 | }
473 | ],
474 | "any": true
475 | }
476 | ]
477 | },
478 | {
479 | "name": "TransIP Web Firewall (TransIP)",
480 | "schemas": [
481 | {
482 | "fingerprints": [
483 | {
484 | "type": "Header",
485 | "header_key": "X-TransIP-Backend",
486 | "header_value": "(?i).+"
487 | },
488 | {
489 | "type": "Header",
490 | "header_key": "X-TransIP-Balancer",
491 | "header_value": "(?i).+"
492 | }
493 | ],
494 | "any": true
495 | }
496 | ]
497 | },
498 | {
499 | "name": "Tencent Cloud Firewall (Tencent Technologies)",
500 | "schemas": [
501 | {
502 | "fingerprints": [
503 | {
504 | "type": "Content",
505 | "pattern": "(?i)waf\\.tencent\\-?cloud\\.com/"
506 | }
507 | ],
508 | "any": true
509 | }
510 | ]
511 | },
512 | {
513 | "name": "NetContinuum (Barracuda Networks)",
514 | "schemas": [
515 | {
516 | "fingerprints": [
517 | {
518 | "type": "Cookie",
519 | "pattern": "(?i)^NCI__SessionId="
520 | }
521 | ],
522 | "any": true
523 | }
524 | ]
525 | },
526 | {
527 | "name": "Fastly (Fastly CDN)",
528 | "schemas": [
529 | {
530 | "fingerprints": [
531 | {
532 | "type": "Header",
533 | "header_key": "X-Fastly-Request-ID",
534 | "header_value": "(?i)\\w+"
535 | }
536 | ],
537 | "any": true
538 | }
539 | ]
540 | },
541 | {
542 | "name": "Astra (Czar Securities)",
543 | "schemas": [
544 | {
545 | "fingerprints": [
546 | {
547 | "type": "Cookie",
548 | "pattern": "(?i)^cz_astra_csrf_cookie"
549 | },
550 | {
551 | "type": "Content",
552 | "pattern": "(?i)astrawebsecurity\\.freshdesk\\.com"
553 | },
554 | {
555 | "type": "Content",
556 | "pattern": "(?i)www\\.getastra\\.com/assets/images"
557 | }
558 | ],
559 | "any": true
560 | }
561 | ]
562 | },
563 | {
564 | "name": "ASP.NET Generic (Microsoft)",
565 | "schemas": [
566 | {
567 | "fingerprints": [
568 | {
569 | "type": "Content",
570 | "pattern": "(?i)iis (\\d+.)+?detailed error"
571 | },
572 | {
573 | "type": "Content",
574 | "pattern": "(?i)potentially dangerous request querystring"
575 | },
576 | {
577 | "type": "Content",
578 | "pattern": "(?i)application error from being viewed remotely (for security reasons)?"
579 | },
580 | {
581 | "type": "Content",
582 | "pattern": "(?i)An application error occurred on the server"
583 | }
584 | ],
585 | "any": true
586 | }
587 | ]
588 | },
589 | {
590 | "name": "Oracle Cloud (Oracle)",
591 | "schemas": [
592 | {
593 | "fingerprints": [
594 | {
595 | "type": "Content",
596 | "pattern": "(?i)\u003ctitle\u003efw_error_www"
597 | },
598 | {
599 | "type": "Content",
600 | "pattern": "(?i)src=\\\"/oralogo_small\\.gif\\\""
601 | },
602 | {
603 | "type": "Content",
604 | "pattern": "(?i)www\\.oracleimg\\.com/us/assets/metrics/ora_ocom\\.js"
605 | }
606 | ],
607 | "any": true
608 | }
609 | ]
610 | },
611 | {
612 | "name": "Trafficshield (F5 Networks)",
613 | "schemas": [
614 | {
615 | "fingerprints": [
616 | {
617 | "type": "Cookie",
618 | "pattern": "(?i)^ASINFO="
619 | },
620 | {
621 | "type": "Header",
622 | "header_key": "Server",
623 | "header_value": "(?i)F5-TrafficShield"
624 | }
625 | ],
626 | "any": true
627 | }
628 | ]
629 | },
630 | {
631 | "name": "Shadow Daemon (Zecure)",
632 | "schemas": [
633 | {
634 | "fingerprints": [
635 | {
636 | "type": "Content",
637 | "pattern": "(?i)\u003ch\\d{1}\u003e\\d{3}.forbidden\u003c.h\\d{1}\u003e"
638 | },
639 | {
640 | "type": "Content",
641 | "pattern": "(?i)request forbidden by administrative rules"
642 | }
643 | ]
644 | }
645 | ]
646 | },
647 | {
648 | "name": "ISA Server (Microsoft)",
649 | "schemas": [
650 | {
651 | "fingerprints": [
652 | {
653 | "type": "Content",
654 | "pattern": "(?i)The.{0,10}?(isa.)?server.{0,10}?denied the specified uniform resource locator \\(url\\)"
655 | }
656 | ],
657 | "any": true
658 | }
659 | ]
660 | },
661 | {
662 | "name": "StackPath (StackPath)",
663 | "schemas": [
664 | {
665 | "fingerprints": [
666 | {
667 | "type": "Content",
668 | "pattern": "(?i)\u003ctitle\u003eStackPath[^\u003c]+\u003c/title\u003e"
669 | },
670 | {
671 | "type": "Content",
672 | "pattern": "(?i)Protected by \u003ca href=\"https?:\\/\\/(?:www\\.)?stackpath\\.com\\/\"[^\u003e]+\u003eStackPath"
673 | }
674 | ],
675 | "any": true
676 | },
677 | {
678 | "fingerprints": [
679 | {
680 | "type": "Content",
681 | "pattern": "(?i)is using a security service for protection against online attacks"
682 | },
683 | {
684 | "type": "Content",
685 | "pattern": "(?i)An action has triggered the service and blocked your request"
686 | }
687 | ]
688 | }
689 | ]
690 | },
691 | {
692 | "name": "HyperGuard (Art of Defense)",
693 | "schemas": [
694 | {
695 | "fingerprints": [
696 | {
697 | "type": "Cookie",
698 | "pattern": "(?i)^WODSESSION="
699 | }
700 | ],
701 | "any": true
702 | }
703 | ]
704 | },
705 | {
706 | "name": "Qrator (Qrator)",
707 | "schemas": [
708 | {
709 | "fingerprints": [
710 | {
711 | "type": "Header",
712 | "header_key": "Server",
713 | "header_value": "(?i)QRATOR"
714 | }
715 | ],
716 | "any": true
717 | }
718 | ]
719 | },
720 | {
721 | "name": "SecKing (SecKing)",
722 | "schemas": [
723 | {
724 | "fingerprints": [
725 | {
726 | "type": "Header",
727 | "header_key": "Server",
728 | "header_value": "(?i)secking(.?waf)?"
729 | }
730 | ],
731 | "any": true
732 | }
733 | ]
734 | },
735 | {
736 | "name": "WebARX (WebARX Security Solutions)",
737 | "schemas": [
738 | {
739 | "fingerprints": [
740 | {
741 | "type": "Content",
742 | "pattern": "(?i)WebARX.{0,10}?Web Application Firewall"
743 | },
744 | {
745 | "type": "Content",
746 | "pattern": "(?i)www\\.webarxsecurity\\.com"
747 | },
748 | {
749 | "type": "Content",
750 | "pattern": "(?i)/wp\\-content/plugins/webarx/includes/"
751 | }
752 | ],
753 | "any": true
754 | }
755 | ]
756 | },
757 | {
758 | "name": "BIG-IP AP Manager (F5 Networks)",
759 | "schemas": [
760 | {
761 | "fingerprints": [
762 | {
763 | "type": "Cookie",
764 | "pattern": "(?i)^LastMRH_Session"
765 | },
766 | {
767 | "type": "Cookie",
768 | "pattern": "(?i)^MRHSession"
769 | }
770 | ]
771 | },
772 | {
773 | "fingerprints": [
774 | {
775 | "type": "Cookie",
776 | "pattern": "(?i)^MRHSession"
777 | },
778 | {
779 | "type": "Header",
780 | "header_key": "Server",
781 | "header_value": "(?i)Big([-_])?IP",
782 | "attack": true
783 | }
784 | ]
785 | },
786 | {
787 | "fingerprints": [
788 | {
789 | "type": "Cookie",
790 | "pattern": "(?i)^F5_fullWT"
791 | },
792 | {
793 | "type": "Cookie",
794 | "pattern": "(?i)^F5_fullWT"
795 | },
796 | {
797 | "type": "Cookie",
798 | "pattern": "(?i)^F5_HT_shrinked"
799 | }
800 | ],
801 | "any": true
802 | }
803 | ]
804 | },
805 | {
806 | "name": "Qcloud (Tencent Cloud)",
807 | "schemas": [
808 | {
809 | "fingerprints": [
810 | {
811 | "type": "Content",
812 | "pattern": "(?i)腾讯云Web应用防火墙"
813 | },
814 | {
815 | "type": "Status",
816 | "pattern": "403"
817 | }
818 | ]
819 | }
820 | ]
821 | },
822 | {
823 | "name": "NevisProxy (AdNovum)",
824 | "schemas": [
825 | {
826 | "fingerprints": [
827 | {
828 | "type": "Cookie",
829 | "pattern": "(?i)^Navajo"
830 | },
831 | {
832 | "type": "Cookie",
833 | "pattern": "(?i)^NP_ID"
834 | }
835 | ],
836 | "any": true
837 | }
838 | ]
839 | },
840 | {
841 | "name": "Comodo cWatch (Comodo CyberSecurity)",
842 | "schemas": [
843 | {
844 | "fingerprints": [
845 | {
846 | "type": "Header",
847 | "header_key": "Server",
848 | "header_value": "(?i)Protected by COMODO WAF(.+)?"
849 | }
850 | ],
851 | "any": true
852 | }
853 | ]
854 | },
855 | {
856 | "name": "NexusGuard Firewall (NexusGuard)",
857 | "schemas": [
858 | {
859 | "fingerprints": [
860 | {
861 | "type": "Content",
862 | "pattern": "(?i)Powered by Nexusguard"
863 | },
864 | {
865 | "type": "Content",
866 | "pattern": "(?i)nexusguard\\.com/wafpage/.+#\\d{3};"
867 | }
868 | ],
869 | "any": true
870 | }
871 | ]
872 | },
873 | {
874 | "name": "Chuang Yu Shield (Yunaq)",
875 | "schemas": [
876 | {
877 | "fingerprints": [
878 | {
879 | "type": "Content",
880 | "pattern": "(?i)www\\.365cyd\\.com"
881 | },
882 | {
883 | "type": "Content",
884 | "pattern": "(?i)help\\.365cyd\\.com/cyd\\-error\\-help.html\\?code=403"
885 | }
886 | ],
887 | "any": true
888 | }
889 | ]
890 | },
891 | {
892 | "name": "Safedog (SafeDog)",
893 | "schemas": [
894 | {
895 | "fingerprints": [
896 | {
897 | "type": "Cookie",
898 | "pattern": "(?i)^safedog\\-flow\\-item="
899 | },
900 | {
901 | "type": "Header",
902 | "header_key": "Server",
903 | "header_value": "(?i)Safedog"
904 | },
905 | {
906 | "type": "Content",
907 | "pattern": "(?i)safedogsite/broswer_logo\\.jpg"
908 | },
909 | {
910 | "type": "Content",
911 | "pattern": "(?i)404\\.safedog\\.cn/sitedog_stat.html"
912 | },
913 | {
914 | "type": "Content",
915 | "pattern": "(?i)404\\.safedog\\.cn/images/safedogsite/head\\.png"
916 | }
917 | ],
918 | "any": true
919 | }
920 | ]
921 | },
922 | {
923 | "name": "Approach (Approach)",
924 | "schemas": [
925 | {
926 | "fingerprints": [
927 | {
928 | "type": "Content",
929 | "pattern": "(?i)approach.{0,10}?web application (firewall|filtering)"
930 | },
931 | {
932 | "type": "Content",
933 | "pattern": "(?i)approach.{0,10}?infrastructure team"
934 | }
935 | ],
936 | "any": true
937 | }
938 | ]
939 | },
940 | {
941 | "name": "Azure Front Door (Microsoft)",
942 | "schemas": [
943 | {
944 | "fingerprints": [
945 | {
946 | "type": "Header",
947 | "header_key": "X-Azure-Ref",
948 | "header_value": "(?i).+?"
949 | }
950 | ],
951 | "any": true
952 | }
953 | ]
954 | },
955 | {
956 | "name": "BlockDoS (BlockDoS)",
957 | "schemas": [
958 | {
959 | "fingerprints": [
960 | {
961 | "type": "Header",
962 | "header_key": "Server",
963 | "header_value": "(?i)blockdos\\.net"
964 | }
965 | ],
966 | "any": true
967 | }
968 | ]
969 | },
970 | {
971 | "name": "SEnginx (Neusoft)",
972 | "schemas": [
973 | {
974 | "fingerprints": [
975 | {
976 | "type": "Content",
977 | "pattern": "(?i)SENGINX\\-ROBOT\\-MITIGATION"
978 | }
979 | ],
980 | "any": true
981 | }
982 | ]
983 | },
984 | {
985 | "name": "UEWaf (UCloud)",
986 | "schemas": [
987 | {
988 | "fingerprints": [
989 | {
990 | "type": "Header",
991 | "header_key": "Server",
992 | "header_value": "(?i)uewaf(/[0-9\\.]+)?"
993 | },
994 | {
995 | "type": "Content",
996 | "pattern": "(?i)/uewaf_deny_pages/default/img/"
997 | },
998 | {
999 | "type": "Content",
1000 | "pattern": "(?i)ucloud\\.cn"
1001 | }
1002 | ],
1003 | "any": true
1004 | }
1005 | ]
1006 | },
1007 | {
1008 | "name": "URLScan (Microsoft)",
1009 | "schemas": [
1010 | {
1011 | "fingerprints": [
1012 | {
1013 | "type": "Content",
1014 | "pattern": "(?i)Rejected[-_]By[_-]UrlScan"
1015 | },
1016 | {
1017 | "type": "Content",
1018 | "pattern": "(?i)A custom filter or module.{0,4}?such as URLScan"
1019 | }
1020 | ],
1021 | "any": true
1022 | }
1023 | ]
1024 | },
1025 | {
1026 | "name": "NAXSI (NBS Systems)",
1027 | "schemas": [
1028 | {
1029 | "fingerprints": [
1030 | {
1031 | "type": "Header",
1032 | "header_key": "X-Data-Origin",
1033 | "header_value": "(?i)^naxsi(.+)?"
1034 | },
1035 | {
1036 | "type": "Header",
1037 | "header_key": "Server",
1038 | "header_value": "(?i)naxsi(.+)?"
1039 | },
1040 | {
1041 | "type": "Content",
1042 | "pattern": "(?i)blocked by naxsi"
1043 | },
1044 | {
1045 | "type": "Content",
1046 | "pattern": "(?i)naxsi blocked information"
1047 | }
1048 | ],
1049 | "any": true
1050 | }
1051 | ]
1052 | },
1053 | {
1054 | "name": "ACE XML Gateway (Cisco)",
1055 | "schemas": [
1056 | {
1057 | "fingerprints": [
1058 | {
1059 | "type": "Header",
1060 | "header_key": "Server",
1061 | "header_value": "(?i)ACE XML Gateway"
1062 | }
1063 | ],
1064 | "any": true
1065 | }
1066 | ]
1067 | },
1068 | {
1069 | "name": "SonicWall (Dell)",
1070 | "schemas": [
1071 | {
1072 | "fingerprints": [
1073 | {
1074 | "type": "Header",
1075 | "header_key": "Server",
1076 | "header_value": "(?i)SonicWALL"
1077 | },
1078 | {
1079 | "type": "Content",
1080 | "pattern": "(?i)\u003c(title|h\\d{1})\u003eWeb Site Blocked"
1081 | },
1082 | {
1083 | "type": "Content",
1084 | "pattern": "(?i)\\+?nsa_banner"
1085 | }
1086 | ],
1087 | "any": true
1088 | }
1089 | ]
1090 | },
1091 | {
1092 | "name": "Squarespace (Squarespace)",
1093 | "schemas": [
1094 | {
1095 | "fingerprints": [
1096 | {
1097 | "type": "Header",
1098 | "header_key": "Server",
1099 | "header_value": "(?i)Squarespace"
1100 | },
1101 | {
1102 | "type": "Cookie",
1103 | "pattern": "(?i)^SS_ANALYTICS_ID="
1104 | },
1105 | {
1106 | "type": "Cookie",
1107 | "pattern": "(?i)^SS_MATTR="
1108 | },
1109 | {
1110 | "type": "Cookie",
1111 | "pattern": "(?i)^SS_MID="
1112 | },
1113 | {
1114 | "type": "Cookie",
1115 | "pattern": "(?i)SS_CVT="
1116 | },
1117 | {
1118 | "type": "Content",
1119 | "pattern": "(?i)status\\.squarespace\\.com"
1120 | },
1121 | {
1122 | "type": "Content",
1123 | "pattern": "(?i)BRICK\\-\\d{2}"
1124 | }
1125 | ],
1126 | "any": true
1127 | }
1128 | ]
1129 | },
1130 | {
1131 | "name": "VirusDie (VirusDie LLC)",
1132 | "schemas": [
1133 | {
1134 | "fingerprints": [
1135 | {
1136 | "type": "Content",
1137 | "pattern": "(?i)cdn\\.virusdie\\.ru/splash/firewallstop\\.png"
1138 | },
1139 | {
1140 | "type": "Content",
1141 | "pattern": "(?i)copy.{0,10}?Virusdie\\.ru"
1142 | }
1143 | ],
1144 | "any": true
1145 | }
1146 | ]
1147 | },
1148 | {
1149 | "name": "SiteGuard (Sakura Inc.)",
1150 | "schemas": [
1151 | {
1152 | "fingerprints": [
1153 | {
1154 | "type": "Content",
1155 | "pattern": "(?i)Powered by SiteGuard"
1156 | },
1157 | {
1158 | "type": "Content",
1159 | "pattern": "(?i)The server refuse to browse the page"
1160 | }
1161 | ],
1162 | "any": true
1163 | }
1164 | ]
1165 | },
1166 | {
1167 | "name": "SecuPress WP Security (SecuPress)",
1168 | "schemas": [
1169 | {
1170 | "fingerprints": [
1171 | {
1172 | "type": "Content",
1173 | "pattern": "(?i)\u003c(title|h\\d{1})\u003eSecuPress"
1174 | }
1175 | ],
1176 | "any": true
1177 | }
1178 | ]
1179 | },
1180 | {
1181 | "name": "GoDaddy Website Protection (GoDaddy)",
1182 | "schemas": [
1183 | {
1184 | "fingerprints": [
1185 | {
1186 | "type": "Content",
1187 | "pattern": "(?i)GoDaddy (security|website firewall)"
1188 | }
1189 | ],
1190 | "any": true
1191 | }
1192 | ]
1193 | },
1194 | {
1195 | "name": "Varnish (OWASP)",
1196 | "schemas": [
1197 | {
1198 | "fingerprints": [
1199 | {
1200 | "type": "Content",
1201 | "pattern": "(?i)Request rejected by xVarnish\\-WAF"
1202 | }
1203 | ],
1204 | "any": true
1205 | }
1206 | ]
1207 | },
1208 | {
1209 | "name": "Airlock (Phion/Ergon)",
1210 | "schemas": [
1211 | {
1212 | "fingerprints": [
1213 | {
1214 | "type": "Cookie",
1215 | "pattern": "(?i)^al[_-]?(sess|lb)="
1216 | },
1217 | {
1218 | "type": "Content",
1219 | "pattern": "(?i)server detected a syntax error in your request"
1220 | }
1221 | ],
1222 | "any": true
1223 | }
1224 | ]
1225 | },
1226 | {
1227 | "name": "SquidProxy IDS (SquidProxy)",
1228 | "schemas": [
1229 | {
1230 | "fingerprints": [
1231 | {
1232 | "type": "Header",
1233 | "header_key": "Server",
1234 | "header_value": "(?i)squid(/[0-9\\.]+)?"
1235 | },
1236 | {
1237 | "type": "Content",
1238 | "pattern": "(?i)Access control configuration prevents your request"
1239 | }
1240 | ]
1241 | }
1242 | ]
1243 | },
1244 | {
1245 | "name": "Huawei Cloud Firewall (Huawei)",
1246 | "schemas": [
1247 | {
1248 | "fingerprints": [
1249 | {
1250 | "type": "Cookie",
1251 | "pattern": "(?i)^HWWAFSESID="
1252 | },
1253 | {
1254 | "type": "Header",
1255 | "header_key": "Server",
1256 | "header_value": "(?i)HuaweiCloudWAF"
1257 | },
1258 | {
1259 | "type": "Content",
1260 | "pattern": "(?i)hwclouds\\.com"
1261 | },
1262 | {
1263 | "type": "Content",
1264 | "pattern": "(?i)hws_security@"
1265 | }
1266 | ],
1267 | "any": true
1268 | }
1269 | ]
1270 | },
1271 | {
1272 | "name": "Profense (ArmorLogic)",
1273 | "schemas": [
1274 | {
1275 | "fingerprints": [
1276 | {
1277 | "type": "Header",
1278 | "header_key": "Server",
1279 | "header_value": "(?i)Profense"
1280 | },
1281 | {
1282 | "type": "Cookie",
1283 | "pattern": "(?i)^PLBSID="
1284 | }
1285 | ],
1286 | "any": true
1287 | }
1288 | ]
1289 | },
1290 | {
1291 | "name": "LiteSpeed (LiteSpeed Technologies)",
1292 | "schemas": [
1293 | {
1294 | "fingerprints": [
1295 | {
1296 | "type": "Header",
1297 | "header_key": "Server",
1298 | "header_value": "(?i)LiteSpeed"
1299 | },
1300 | {
1301 | "type": "Status",
1302 | "pattern": "403"
1303 | }
1304 | ]
1305 | },
1306 | {
1307 | "fingerprints": [
1308 | {
1309 | "type": "Content",
1310 | "pattern": "(?i)Proudly powered by litespeed web server"
1311 | },
1312 | {
1313 | "type": "Content",
1314 | "pattern": "(?i)www\\.litespeedtech\\.com/error\\-page"
1315 | }
1316 | ],
1317 | "any": true
1318 | }
1319 | ]
1320 | },
1321 | {
1322 | "name": "KeyCDN (KeyCDN)",
1323 | "schemas": [
1324 | {
1325 | "fingerprints": [
1326 | {
1327 | "type": "Header",
1328 | "header_key": "Server",
1329 | "header_value": "(?i)KeyCDN"
1330 | }
1331 | ],
1332 | "any": true
1333 | }
1334 | ]
1335 | },
1336 | {
1337 | "name": "Yunsuo (Yunsuo)",
1338 | "schemas": [
1339 | {
1340 | "fingerprints": [
1341 | {
1342 | "type": "Cookie",
1343 | "pattern": "(?i)^yunsuo_session="
1344 | },
1345 | {
1346 | "type": "Content",
1347 | "pattern": "(?i)class=\\\"yunsuologo\\\""
1348 | }
1349 | ],
1350 | "any": true
1351 | }
1352 | ]
1353 | },
1354 | {
1355 | "name": "AppWall (Radware)",
1356 | "schemas": [
1357 | {
1358 | "fingerprints": [
1359 | {
1360 | "type": "Content",
1361 | "pattern": "(?i)CloudWebSec\\.radware\\.com"
1362 | },
1363 | {
1364 | "type": "Header",
1365 | "header_key": "X-SL-CompState",
1366 | "header_value": "(?i).+"
1367 | }
1368 | ],
1369 | "any": true
1370 | },
1371 | {
1372 | "fingerprints": [
1373 | {
1374 | "type": "Content",
1375 | "pattern": "(?i)because we have detected unauthorized activity"
1376 | },
1377 | {
1378 | "type": "Content",
1379 | "pattern": "(?i)\u003ctitle\u003eUnauthorized Request Blocked"
1380 | },
1381 | {
1382 | "type": "Content",
1383 | "pattern": "(?i)if you believe that there has been some mistake"
1384 | },
1385 | {
1386 | "type": "Content",
1387 | "pattern": "(?i)\\?Subject=Security Page.{0,10}?Case Number"
1388 | }
1389 | ]
1390 | }
1391 | ]
1392 | },
1393 | {
1394 | "name": "WP Cerber Security (Cerber Tech)",
1395 | "schemas": [
1396 | {
1397 | "fingerprints": [
1398 | {
1399 | "type": "Content",
1400 | "pattern": "(?i)your request looks suspicious or similar to automated"
1401 | },
1402 | {
1403 | "type": "Content",
1404 | "pattern": "(?i)our server stopped processing your request"
1405 | },
1406 | {
1407 | "type": "Content",
1408 | "pattern": "(?i)We.re sorry.{0,10}?you are not allowed to proceed"
1409 | },
1410 | {
1411 | "type": "Content",
1412 | "pattern": "(?i)requests from spam posting software"
1413 | },
1414 | {
1415 | "type": "Content",
1416 | "pattern": "(?i)\u003ctitle\u003e403 Access Forbidden"
1417 | }
1418 | ]
1419 | }
1420 | ]
1421 | },
1422 | {
1423 | "name": "ChinaCache Load Balancer (ChinaCache)",
1424 | "schemas": [
1425 | {
1426 | "fingerprints": [
1427 | {
1428 | "type": "Header",
1429 | "header_key": "Powered-By-ChinaCache",
1430 | "header_value": "(?i).+"
1431 | }
1432 | ],
1433 | "any": true
1434 | }
1435 | ]
1436 | },
1437 | {
1438 | "name": "BIG-IP Local Traffic Manager (F5 Networks)",
1439 | "schemas": [
1440 | {
1441 | "fingerprints": [
1442 | {
1443 | "type": "Cookie",
1444 | "pattern": "(?i)^bigipserver"
1445 | },
1446 | {
1447 | "type": "Header",
1448 | "header_key": "X-Cnection",
1449 | "header_value": "(?i)close",
1450 | "attack": true
1451 | }
1452 | ],
1453 | "any": true
1454 | }
1455 | ]
1456 | },
1457 | {
1458 | "name": "AnYu (AnYu Technologies)",
1459 | "schemas": [
1460 | {
1461 | "fingerprints": [
1462 | {
1463 | "type": "Content",
1464 | "pattern": "(?i)anyu.{0,10}?the green channel"
1465 | },
1466 | {
1467 | "type": "Content",
1468 | "pattern": "(?i)your access has been intercepted by anyu"
1469 | }
1470 | ],
1471 | "any": true
1472 | }
1473 | ]
1474 | },
1475 | {
1476 | "name": "CrawlProtect (Jean-Denis Brun)",
1477 | "schemas": [
1478 | {
1479 | "fingerprints": [
1480 | {
1481 | "type": "Cookie",
1482 | "pattern": "(?i)^crawlprotecttag="
1483 | },
1484 | {
1485 | "type": "Content",
1486 | "pattern": "(?i)\u003ctitle\u003ecrawlprotect"
1487 | },
1488 | {
1489 | "type": "Content",
1490 | "pattern": "(?i)this site is protected by crawlprotect"
1491 | }
1492 | ],
1493 | "any": true
1494 | }
1495 | ]
1496 | },
1497 | {
1498 | "name": "WebLand (WebLand)",
1499 | "schemas": [
1500 | {
1501 | "fingerprints": [
1502 | {
1503 | "type": "Header",
1504 | "header_key": "Server",
1505 | "header_value": "(?i)protected by webland"
1506 | }
1507 | ],
1508 | "any": true
1509 | }
1510 | ]
1511 | },
1512 | {
1513 | "name": "Open-Resty Lua Nginx (FLOSS)",
1514 | "schemas": [
1515 | {
1516 | "fingerprints": [
1517 | {
1518 | "type": "Header",
1519 | "header_key": "Server",
1520 | "header_value": "(?i)^openresty/[0-9\\.]+?"
1521 | },
1522 | {
1523 | "type": "Status",
1524 | "pattern": "403"
1525 | }
1526 | ]
1527 | },
1528 | {
1529 | "fingerprints": [
1530 | {
1531 | "type": "Content",
1532 | "pattern": "(?i)openresty/[0-9\\.]+?"
1533 | },
1534 | {
1535 | "type": "Status",
1536 | "pattern": "406"
1537 | }
1538 | ]
1539 | }
1540 | ]
1541 | },
1542 | {
1543 | "name": "Kona SiteDefender (Akamai)",
1544 | "schemas": [
1545 | {
1546 | "fingerprints": [
1547 | {
1548 | "type": "Header",
1549 | "header_key": "Server",
1550 | "header_value": "(?i)AkamaiGHost"
1551 | },
1552 | {
1553 | "type": "Header",
1554 | "header_key": "Server",
1555 | "header_value": "(?i)AkamaiGHost",
1556 | "attack": true
1557 | }
1558 | ],
1559 | "any": true
1560 | }
1561 | ]
1562 | },
1563 | {
1564 | "name": "Wordfence (Defiant)",
1565 | "schemas": [
1566 | {
1567 | "fingerprints": [
1568 | {
1569 | "type": "Header",
1570 | "header_key": "Server",
1571 | "header_value": "(?i)wf[_\\-]?WAF"
1572 | },
1573 | {
1574 | "type": "Content",
1575 | "pattern": "(?i)Generated by Wordfence"
1576 | },
1577 | {
1578 | "type": "Content",
1579 | "pattern": "(?i)broke one of (the )?Wordfence (advanced )?blocking rules"
1580 | },
1581 | {
1582 | "type": "Content",
1583 | "pattern": "(?i)/plugins/wordfence"
1584 | }
1585 | ],
1586 | "any": true
1587 | }
1588 | ]
1589 | },
1590 | {
1591 | "name": "Sucuri CloudProxy (Sucuri Inc.)",
1592 | "schemas": [
1593 | {
1594 | "fingerprints": [
1595 | {
1596 | "type": "Header",
1597 | "header_key": "X-Sucuri-ID",
1598 | "header_value": "(?i).+?"
1599 | },
1600 | {
1601 | "type": "Header",
1602 | "header_key": "X-Sucuri-Cache",
1603 | "header_value": "(?i).+?"
1604 | },
1605 | {
1606 | "type": "Header",
1607 | "header_key": "Server",
1608 | "header_value": "(?i)Sucuri(\\-Cloudproxy)?"
1609 | },
1610 | {
1611 | "type": "Header",
1612 | "header_key": "X-Sucuri-Block",
1613 | "header_value": "(?i).+?",
1614 | "attack": true
1615 | },
1616 | {
1617 | "type": "Content",
1618 | "pattern": "(?i)Access Denied.{0,6}?Sucuri Website Firewall"
1619 | },
1620 | {
1621 | "type": "Content",
1622 | "pattern": "(?i)\u003ctitle\u003eSucuri WebSite Firewall.{0,6}?(CloudProxy)?.{0,6}?Access Denied"
1623 | },
1624 | {
1625 | "type": "Content",
1626 | "pattern": "(?i)sucuri\\.net/privacy\\-policy"
1627 | },
1628 | {
1629 | "type": "Content",
1630 | "pattern": "(?i)cdn\\.sucuri\\.net/sucuri[-_]firewall[-_]block\\.css"
1631 | },
1632 | {
1633 | "type": "Content",
1634 | "pattern": "(?i)cloudproxy@sucuri\\.net"
1635 | }
1636 | ],
1637 | "any": true
1638 | }
1639 | ]
1640 | },
1641 | {
1642 | "name": "Sabre Firewall (Sabre)",
1643 | "schemas": [
1644 | {
1645 | "fingerprints": [
1646 | {
1647 | "type": "Content",
1648 | "pattern": "(?i)dxsupport\\.sabre\\.com"
1649 | }
1650 | ],
1651 | "any": true
1652 | },
1653 | {
1654 | "fingerprints": [
1655 | {
1656 | "type": "Content",
1657 | "pattern": "(?i)\u003ctitle\u003eApplication Firewall Error"
1658 | },
1659 | {
1660 | "type": "Content",
1661 | "pattern": "(?i)add some important details to the email for us to investigate"
1662 | }
1663 | ]
1664 | }
1665 | ]
1666 | },
1667 | {
1668 | "name": "Bekchy (Faydata Technologies Inc.)",
1669 | "schemas": [
1670 | {
1671 | "fingerprints": [
1672 | {
1673 | "type": "Content",
1674 | "pattern": "(?i)Bekchy.{0,10}?Access Denied"
1675 | },
1676 | {
1677 | "type": "Content",
1678 | "pattern": "(?i)bekchy\\.com/report"
1679 | }
1680 | ],
1681 | "any": true
1682 | }
1683 | ]
1684 | },
1685 | {
1686 | "name": "BitNinja (BitNinja)",
1687 | "schemas": [
1688 | {
1689 | "fingerprints": [
1690 | {
1691 | "type": "Content",
1692 | "pattern": "(?i)Security check by BitNinja"
1693 | },
1694 | {
1695 | "type": "Content",
1696 | "pattern": "(?i)Visitor anti-robot validation"
1697 | }
1698 | ],
1699 | "any": true
1700 | }
1701 | ]
1702 | },
1703 | {
1704 | "name": "WTS-WAF (WTS)",
1705 | "schemas": [
1706 | {
1707 | "fingerprints": [
1708 | {
1709 | "type": "Header",
1710 | "header_key": "Server",
1711 | "header_value": "(?i)wts/[0-9\\.]+?"
1712 | },
1713 | {
1714 | "type": "Content",
1715 | "pattern": "(?i)\u003c(title|h\\d{1})\u003eWTS\\-WAF"
1716 | }
1717 | ],
1718 | "any": true
1719 | }
1720 | ]
1721 | },
1722 | {
1723 | "name": "Greywizard (Grey Wizard)",
1724 | "schemas": [
1725 | {
1726 | "fingerprints": [
1727 | {
1728 | "type": "Header",
1729 | "header_key": "Server",
1730 | "header_value": "(?i)greywizard"
1731 | },
1732 | {
1733 | "type": "Content",
1734 | "pattern": "(?i)\u003c(title|h\\d{1})\u003eGrey Wizard"
1735 | },
1736 | {
1737 | "type": "Content",
1738 | "pattern": "(?i)contact the website owner or Grey Wizard"
1739 | },
1740 | {
1741 | "type": "Content",
1742 | "pattern": "(?i)We.ve detected attempted attack or non standard traffic from your ip address"
1743 | }
1744 | ],
1745 | "any": true
1746 | }
1747 | ]
1748 | },
1749 | {
1750 | "name": "Puhui (Puhui)",
1751 | "schemas": [
1752 | {
1753 | "fingerprints": [
1754 | {
1755 | "type": "Header",
1756 | "header_key": "Server",
1757 | "header_value": "(?i)Puhui[\\-_]?WAF"
1758 | }
1759 | ],
1760 | "any": true
1761 | }
1762 | ]
1763 | },
1764 | {
1765 | "name": "Cloudfloor (Cloudfloor DNS)",
1766 | "schemas": [
1767 | {
1768 | "fingerprints": [
1769 | {
1770 | "type": "Header",
1771 | "header_key": "Server",
1772 | "header_value": "(?i)CloudfloorDNS(.WAF)?"
1773 | },
1774 | {
1775 | "type": "Content",
1776 | "pattern": "(?i)\u003c(title|h\\d{1})\u003eCloudfloorDNS.{0,6}?Web Application Firewall Error"
1777 | },
1778 | {
1779 | "type": "Content",
1780 | "pattern": "(?i)www\\.cloudfloordns\\.com/contact"
1781 | }
1782 | ],
1783 | "any": true
1784 | }
1785 | ]
1786 | },
1787 | {
1788 | "name": "RSFirewall (RSJoomla!)",
1789 | "schemas": [
1790 | {
1791 | "fingerprints": [
1792 | {
1793 | "type": "Content",
1794 | "pattern": "(?i)com_rsfirewall_(\\d{3}_forbidden|event)?"
1795 | }
1796 | ],
1797 | "any": true
1798 | }
1799 | ]
1800 | },
1801 | {
1802 | "name": "Safe3 Web Firewall (Safe3)",
1803 | "schemas": [
1804 | {
1805 | "fingerprints": [
1806 | {
1807 | "type": "Header",
1808 | "header_key": "Server",
1809 | "header_value": "(?i)Safe3 Web Firewall"
1810 | },
1811 | {
1812 | "type": "Header",
1813 | "header_key": "X-Powered-By",
1814 | "header_value": "(?i)Safe3WAF/[\\.0-9]+?"
1815 | },
1816 | {
1817 | "type": "Content",
1818 | "pattern": "(?i)Safe3waf/[0-9\\.]+?"
1819 | }
1820 | ],
1821 | "any": true
1822 | }
1823 | ]
1824 | },
1825 | {
1826 | "name": "Zenedge (Zenedge)",
1827 | "schemas": [
1828 | {
1829 | "fingerprints": [
1830 | {
1831 | "type": "Header",
1832 | "header_key": "Server",
1833 | "header_value": "(?i)ZENEDGE"
1834 | },
1835 | {
1836 | "type": "Header",
1837 | "header_key": "X-Zen-Fury",
1838 | "header_value": "(?i).+?"
1839 | },
1840 | {
1841 | "type": "Content",
1842 | "pattern": "(?i)/__zenedge/"
1843 | }
1844 | ],
1845 | "any": true
1846 | }
1847 | ]
1848 | },
1849 | {
1850 | "name": "Newdefend (NewDefend)",
1851 | "schemas": [
1852 | {
1853 | "fingerprints": [
1854 | {
1855 | "type": "Header",
1856 | "header_key": "Server",
1857 | "header_value": "(?i)Newdefend"
1858 | },
1859 | {
1860 | "type": "Content",
1861 | "pattern": "(?i)www\\.newdefend\\.com/feedback"
1862 | },
1863 | {
1864 | "type": "Content",
1865 | "pattern": "(?i)/nd\\-block/"
1866 | }
1867 | ],
1868 | "any": true
1869 | }
1870 | ]
1871 | },
1872 | {
1873 | "name": "pkSecurity IDS (pkSec)",
1874 | "schemas": [
1875 | {
1876 | "fingerprints": [
1877 | {
1878 | "type": "Content",
1879 | "pattern": "(?i)pk.?Security.?Module"
1880 | },
1881 | {
1882 | "type": "Content",
1883 | "pattern": "(?i)Security.Alert"
1884 | }
1885 | ]
1886 | },
1887 | {
1888 | "fingerprints": [
1889 | {
1890 | "type": "Content",
1891 | "pattern": "(?i)As this could be a potential hack attack"
1892 | },
1893 | {
1894 | "type": "Content",
1895 | "pattern": "(?i)A safety critical (call|request) was (detected|discovered) and blocked"
1896 | },
1897 | {
1898 | "type": "Content",
1899 | "pattern": "(?i)maximum number of reloads per minute and prevented access"
1900 | }
1901 | ],
1902 | "any": true
1903 | }
1904 | ]
1905 | },
1906 | {
1907 | "name": "DOSarrest (DOSarrest Internet Security)",
1908 | "schemas": [
1909 | {
1910 | "fingerprints": [
1911 | {
1912 | "type": "Header",
1913 | "header_key": "X-DIS-Request-ID",
1914 | "header_value": "(?i).+"
1915 | },
1916 | {
1917 | "type": "Header",
1918 | "header_key": "Server",
1919 | "header_value": "(?i)DOSarrest(.*)?"
1920 | }
1921 | ],
1922 | "any": true
1923 | }
1924 | ]
1925 | },
1926 | {
1927 | "name": "Qiniu (Qiniu CDN)",
1928 | "schemas": [
1929 | {
1930 | "fingerprints": [
1931 | {
1932 | "type": "Header",
1933 | "header_key": "X-Qiniu-CDN",
1934 | "header_value": "(?i)\\d+?"
1935 | }
1936 | ],
1937 | "any": true
1938 | }
1939 | ]
1940 | },
1941 | {
1942 | "name": "BinarySec (BinarySec)",
1943 | "schemas": [
1944 | {
1945 | "fingerprints": [
1946 | {
1947 | "type": "Header",
1948 | "header_key": "Server",
1949 | "header_value": "(?i)BinarySec"
1950 | },
1951 | {
1952 | "type": "Header",
1953 | "header_key": "x-binarysec-via",
1954 | "header_value": "(?i).+"
1955 | },
1956 | {
1957 | "type": "Header",
1958 | "header_key": "x-binarysec-nocache",
1959 | "header_value": "(?i).+"
1960 | }
1961 | ],
1962 | "any": true
1963 | }
1964 | ]
1965 | },
1966 | {
1967 | "name": "WebTotem (WebTotem)",
1968 | "schemas": [
1969 | {
1970 | "fingerprints": [
1971 | {
1972 | "type": "Content",
1973 | "pattern": "(?i)The current request was blocked.{0,8}?\u003eWebTotem"
1974 | }
1975 | ],
1976 | "any": true
1977 | }
1978 | ]
1979 | },
1980 | {
1981 | "name": "Imunify360 (CloudLinux)",
1982 | "schemas": [
1983 | {
1984 | "fingerprints": [
1985 | {
1986 | "type": "Header",
1987 | "header_key": "Server",
1988 | "header_value": "(?i)imunify360.{0,10}?"
1989 | },
1990 | {
1991 | "type": "Content",
1992 | "pattern": "(?i)protected.by.{0,10}?imunify360"
1993 | },
1994 | {
1995 | "type": "Content",
1996 | "pattern": "(?i)powered.by.{0,10}?imunify360"
1997 | },
1998 | {
1999 | "type": "Content",
2000 | "pattern": "(?i)imunify360.preloader"
2001 | }
2002 | ],
2003 | "any": true
2004 | }
2005 | ]
2006 | },
2007 | {
2008 | "name": "Anquanbao (Anquanbao)",
2009 | "schemas": [
2010 | {
2011 | "fingerprints": [
2012 | {
2013 | "type": "Header",
2014 | "header_key": "X-Powered-By-Anquanbao",
2015 | "header_value": "(?i).+?"
2016 | },
2017 | {
2018 | "type": "Content",
2019 | "pattern": "(?i)aqb_cc/error/"
2020 | }
2021 | ],
2022 | "any": true
2023 | }
2024 | ]
2025 | },
2026 | {
2027 | "name": "AliYunDun (Alibaba Cloud Computing)",
2028 | "schemas": [
2029 | {
2030 | "fingerprints": [
2031 | {
2032 | "type": "Content",
2033 | "pattern": "(?i)error(s)?\\.aliyun(dun)?\\.(com|net)?"
2034 | },
2035 | {
2036 | "type": "Cookie",
2037 | "pattern": "(?i)^aliyungf_tc="
2038 | },
2039 | {
2040 | "type": "Content",
2041 | "pattern": "(?i)cdn\\.aliyun(cs)?\\.com"
2042 | },
2043 | {
2044 | "type": "Status",
2045 | "pattern": "405"
2046 | }
2047 | ]
2048 | }
2049 | ]
2050 | },
2051 | {
2052 | "name": "PowerCDN (PowerCDN)",
2053 | "schemas": [
2054 | {
2055 | "fingerprints": [
2056 | {
2057 | "type": "Header",
2058 | "header_key": "Via",
2059 | "header_value": "(?i)(.*)?powercdn.com(.*)?"
2060 | },
2061 | {
2062 | "type": "Header",
2063 | "header_key": "X-Cache",
2064 | "header_value": "(?i)(.*)?powercdn.com(.*)?"
2065 | },
2066 | {
2067 | "type": "Header",
2068 | "header_key": "X-CDN",
2069 | "header_value": "(?i)PowerCDN"
2070 | }
2071 | ],
2072 | "any": true
2073 | }
2074 | ]
2075 | },
2076 | {
2077 | "name": "Distil (Distil Networks)",
2078 | "schemas": [
2079 | {
2080 | "fingerprints": [
2081 | {
2082 | "type": "Content",
2083 | "pattern": "(?i)cdn\\.distilnetworks\\.com/images/anomaly\\.detected\\.png"
2084 | },
2085 | {
2086 | "type": "Content",
2087 | "pattern": "(?i)distilCaptchaForm"
2088 | },
2089 | {
2090 | "type": "Content",
2091 | "pattern": "(?i)distilCallbackGuard"
2092 | }
2093 | ],
2094 | "any": true
2095 | }
2096 | ]
2097 | },
2098 | {
2099 | "name": "West263 CDN (West263CDN)",
2100 | "schemas": [
2101 | {
2102 | "fingerprints": [
2103 | {
2104 | "type": "Header",
2105 | "header_key": "X-Cache",
2106 | "header_value": "(?i)WS?T263CDN"
2107 | }
2108 | ],
2109 | "any": true
2110 | }
2111 | ]
2112 | },
2113 | {
2114 | "name": "Instart DX (Instart Logic)",
2115 | "schemas": [
2116 | {
2117 | "fingerprints": [
2118 | {
2119 | "type": "Header",
2120 | "header_key": "X-Instart-Request-ID",
2121 | "header_value": "(?i).+"
2122 | },
2123 | {
2124 | "type": "Header",
2125 | "header_key": "X-Instart-Cache",
2126 | "header_value": "(?i).+"
2127 | },
2128 | {
2129 | "type": "Header",
2130 | "header_key": "X-Instart-WL",
2131 | "header_value": "(?i).+"
2132 | }
2133 | ],
2134 | "any": true
2135 | },
2136 | {
2137 | "fingerprints": [
2138 | {
2139 | "type": "Content",
2140 | "pattern": "(?i)the requested url was rejected"
2141 | },
2142 | {
2143 | "type": "Content",
2144 | "pattern": "(?i)please consult with your administrator"
2145 | },
2146 | {
2147 | "type": "Content",
2148 | "pattern": "(?i)your support id is"
2149 | }
2150 | ]
2151 | }
2152 | ]
2153 | },
2154 | {
2155 | "name": "PerimeterX (PerimeterX)",
2156 | "schemas": [
2157 | {
2158 | "fingerprints": [
2159 | {
2160 | "type": "Content",
2161 | "pattern": "(?i)www\\.perimeterx\\.(com|net)/whywasiblocked"
2162 | },
2163 | {
2164 | "type": "Content",
2165 | "pattern": "(?i)client\\.perimeterx\\.(net|com)"
2166 | },
2167 | {
2168 | "type": "Content",
2169 | "pattern": "(?i)denied because we believe you are using automation tools"
2170 | }
2171 | ],
2172 | "any": true
2173 | }
2174 | ]
2175 | },
2176 | {
2177 | "name": "XLabs Security WAF (XLabs)",
2178 | "schemas": [
2179 | {
2180 | "fingerprints": [
2181 | {
2182 | "type": "Header",
2183 | "header_key": "X-CDN",
2184 | "header_value": "(?i)XLabs Security"
2185 | },
2186 | {
2187 | "type": "Header",
2188 | "header_key": "Secured",
2189 | "header_value": "(?i)^By XLabs Security"
2190 | },
2191 | {
2192 | "type": "Header",
2193 | "header_key": "Server",
2194 | "header_value": "(?i)XLabs[-_]?.?WAF",
2195 | "attack": true
2196 | }
2197 | ],
2198 | "any": true
2199 | }
2200 | ]
2201 | },
2202 | {
2203 | "name": "YXLink (YxLink Technologies)",
2204 | "schemas": [
2205 | {
2206 | "fingerprints": [
2207 | {
2208 | "type": "Cookie",
2209 | "pattern": "(?i)^yx_ci_session="
2210 | },
2211 | {
2212 | "type": "Cookie",
2213 | "pattern": "(?i)^yx_language="
2214 | },
2215 | {
2216 | "type": "Header",
2217 | "header_key": "Server",
2218 | "header_value": "(?i)Yxlink([\\-_]?WAF)?"
2219 | }
2220 | ],
2221 | "any": true
2222 | }
2223 | ]
2224 | },
2225 | {
2226 | "name": "Armor Defense (Armor)",
2227 | "schemas": [
2228 | {
2229 | "fingerprints": [
2230 | {
2231 | "type": "Content",
2232 | "pattern": "(?i)blocked by website protection from armor"
2233 | },
2234 | {
2235 | "type": "Content",
2236 | "pattern": "(?i)please create an armor support ticket"
2237 | }
2238 | ],
2239 | "any": true
2240 | }
2241 | ]
2242 | },
2243 | {
2244 | "name": "wpmudev WAF (Incsub)",
2245 | "schemas": [
2246 | {
2247 | "fingerprints": [
2248 | {
2249 | "type": "Content",
2250 | "pattern": "(?i)href=\"http(s)?.\\/\\/wpmudev.com\\/.{0,15}?"
2251 | },
2252 | {
2253 | "type": "Content",
2254 | "pattern": "(?i)Click on the Logs tab, then the WAF Log."
2255 | },
2256 | {
2257 | "type": "Content",
2258 | "pattern": "(?i)Choose your site from the list"
2259 | },
2260 | {
2261 | "type": "Status",
2262 | "pattern": "403"
2263 | }
2264 | ]
2265 | },
2266 | {
2267 | "fingerprints": [
2268 | {
2269 | "type": "Content",
2270 | "pattern": "(?i)\u003ch1\u003eWhoops, this request has been blocked!"
2271 | },
2272 | {
2273 | "type": "Content",
2274 | "pattern": "(?i)This request has been deemed suspicious"
2275 | },
2276 | {
2277 | "type": "Content",
2278 | "pattern": "(?i)possible attack on our servers."
2279 | },
2280 | {
2281 | "type": "Status",
2282 | "pattern": "403"
2283 | }
2284 | ]
2285 | }
2286 | ]
2287 | },
2288 | {
2289 | "name": "SecureSphere (Imperva Inc.)",
2290 | "schemas": [
2291 | {
2292 | "fingerprints": [
2293 | {
2294 | "type": "Content",
2295 | "pattern": "(?i)\u003c(title|h2)\u003eError"
2296 | },
2297 | {
2298 | "type": "Content",
2299 | "pattern": "(?i)The incident ID is"
2300 | },
2301 | {
2302 | "type": "Content",
2303 | "pattern": "(?i)This page can't be displayed"
2304 | },
2305 | {
2306 | "type": "Content",
2307 | "pattern": "(?i)Contact support for additional information"
2308 | }
2309 | ]
2310 | }
2311 | ]
2312 | },
2313 | {
2314 | "name": "Eisoo Cloud Firewall (Eisoo)",
2315 | "schemas": [
2316 | {
2317 | "fingerprints": [
2318 | {
2319 | "type": "Header",
2320 | "header_key": "Server",
2321 | "header_value": "(?i)EisooWAF(\\-AZURE)?/?"
2322 | },
2323 | {
2324 | "type": "Content",
2325 | "pattern": "(?i)\u003clink.{0,10}?href=\\\"/eisoo\\-firewall\\-block\\.css"
2326 | },
2327 | {
2328 | "type": "Content",
2329 | "pattern": "(?i)www\\.eisoo\\.com"
2330 | },
2331 | {
2332 | "type": "Content",
2333 | "pattern": "(?i)\u0026copy; \\d{4} Eisoo Inc"
2334 | }
2335 | ],
2336 | "any": true
2337 | }
2338 | ]
2339 | },
2340 | {
2341 | "name": "DataPower (IBM)",
2342 | "schemas": [
2343 | {
2344 | "fingerprints": [
2345 | {
2346 | "type": "Header",
2347 | "header_key": "X-Backside-Transport",
2348 | "header_value": "(?i)(OK|FAIL)"
2349 | }
2350 | ],
2351 | "any": true
2352 | }
2353 | ]
2354 | },
2355 | {
2356 | "name": "WatchGuard (WatchGuard Technologies)",
2357 | "schemas": [
2358 | {
2359 | "fingerprints": [
2360 | {
2361 | "type": "Header",
2362 | "header_key": "Server",
2363 | "header_value": "(?i)WatchGuard"
2364 | },
2365 | {
2366 | "type": "Content",
2367 | "pattern": "(?i)Request denied by WatchGuard Firewall"
2368 | },
2369 | {
2370 | "type": "Content",
2371 | "pattern": "(?i)WatchGuard Technologies Inc\\."
2372 | }
2373 | ],
2374 | "any": true
2375 | }
2376 | ]
2377 | },
2378 | {
2379 | "name": "Safeline (Chaitin Tech.)",
2380 | "schemas": [
2381 | {
2382 | "fingerprints": [
2383 | {
2384 | "type": "Content",
2385 | "pattern": "(?i)safeline|\u003c!\\-\\-\\sevent id:"
2386 | }
2387 | ],
2388 | "any": true
2389 | }
2390 | ]
2391 | },
2392 | {
2393 | "name": "Mission Control Shield (Mission Control)",
2394 | "schemas": [
2395 | {
2396 | "fingerprints": [
2397 | {
2398 | "type": "Header",
2399 | "header_key": "Server",
2400 | "header_value": "(?i)Mission Control Application Shield"
2401 | }
2402 | ],
2403 | "any": true
2404 | }
2405 | ]
2406 | },
2407 | {
2408 | "name": "AireeCDN (Airee)",
2409 | "schemas": [
2410 | {
2411 | "fingerprints": [
2412 | {
2413 | "type": "Header",
2414 | "header_key": "Server",
2415 | "header_value": "(?i)Airee"
2416 | },
2417 | {
2418 | "type": "Header",
2419 | "header_key": "X-Cache",
2420 | "header_value": "(?i)(\\w+\\.)?airee\\.cloud"
2421 | },
2422 | {
2423 | "type": "Content",
2424 | "pattern": "(?i)airee\\.cloud"
2425 | }
2426 | ],
2427 | "any": true
2428 | }
2429 | ]
2430 | },
2431 | {
2432 | "name": "Viettel (Cloudrity)",
2433 | "schemas": [
2434 | {
2435 | "fingerprints": [
2436 | {
2437 | "type": "Content",
2438 | "pattern": "(?i)Access Denied.{0,10}?Viettel WAF"
2439 | },
2440 | {
2441 | "type": "Content",
2442 | "pattern": "(?i)cloudrity\\.com\\.(vn)?/"
2443 | },
2444 | {
2445 | "type": "Content",
2446 | "pattern": "(?i)Viettel WAF System"
2447 | }
2448 | ],
2449 | "any": true
2450 | }
2451 | ]
2452 | },
2453 | {
2454 | "name": "AWS Elastic Load Balancer (Amazon)",
2455 | "schemas": [
2456 | {
2457 | "fingerprints": [
2458 | {
2459 | "type": "Header",
2460 | "header_key": "X-AMZ-ID",
2461 | "header_value": "(?i).+?"
2462 | },
2463 | {
2464 | "type": "Header",
2465 | "header_key": "X-AMZ-Request-ID",
2466 | "header_value": "(?i).+?"
2467 | },
2468 | {
2469 | "type": "Cookie",
2470 | "pattern": "(?i)^aws.?alb="
2471 | },
2472 | {
2473 | "type": "Header",
2474 | "header_key": "Server",
2475 | "header_value": "(?i)aws.?elb",
2476 | "attack": true
2477 | }
2478 | ],
2479 | "any": true
2480 | }
2481 | ]
2482 | },
2483 | {
2484 | "name": "UTM Web Protection (Sophos)",
2485 | "schemas": [
2486 | {
2487 | "fingerprints": [
2488 | {
2489 | "type": "Content",
2490 | "pattern": "(?i)www\\.sophos\\.com"
2491 | },
2492 | {
2493 | "type": "Content",
2494 | "pattern": "(?i)Powered by.?(Sophos)? UTM Web Protection"
2495 | }
2496 | ],
2497 | "any": true
2498 | },
2499 | {
2500 | "fingerprints": [
2501 | {
2502 | "type": "Content",
2503 | "pattern": "(?i)\u003ctitle\u003eAccess to the requested URL was blocked"
2504 | },
2505 | {
2506 | "type": "Content",
2507 | "pattern": "(?i)Access to the requested URL was blocked"
2508 | },
2509 | {
2510 | "type": "Content",
2511 | "pattern": "(?i)incident was logged with the following log identifier"
2512 | },
2513 | {
2514 | "type": "Content",
2515 | "pattern": "(?i)Inbound Anomaly Score exceeded"
2516 | },
2517 | {
2518 | "type": "Content",
2519 | "pattern": "(?i)Your cache administrator is"
2520 | }
2521 | ]
2522 | }
2523 | ]
2524 | },
2525 | {
2526 | "name": "Malcare (Inactiv)",
2527 | "schemas": [
2528 | {
2529 | "fingerprints": [
2530 | {
2531 | "type": "Content",
2532 | "pattern": "(?i)firewall.{0,15}?powered.by.{0,15}?malcare.{0,15}?pro"
2533 | },
2534 | {
2535 | "type": "Content",
2536 | "pattern": "(?i)blocked because of malicious activities"
2537 | }
2538 | ],
2539 | "any": true
2540 | }
2541 | ]
2542 | },
2543 | {
2544 | "name": "NullDDoS Protection (NullDDoS)",
2545 | "schemas": [
2546 | {
2547 | "fingerprints": [
2548 | {
2549 | "type": "Header",
2550 | "header_key": "Server",
2551 | "header_value": "(?i)NullDDoS(.System)?"
2552 | }
2553 | ],
2554 | "any": true
2555 | }
2556 | ]
2557 | },
2558 | {
2559 | "name": "Bluedon (Bluedon IST)",
2560 | "schemas": [
2561 | {
2562 | "fingerprints": [
2563 | {
2564 | "type": "Header",
2565 | "header_key": "Server",
2566 | "header_value": "(?i)BDWAF"
2567 | },
2568 | {
2569 | "type": "Content",
2570 | "pattern": "(?i)bluedon web application firewall"
2571 | }
2572 | ],
2573 | "any": true
2574 | }
2575 | ]
2576 | },
2577 | {
2578 | "name": "Shield Security (One Dollar Plugin)",
2579 | "schemas": [
2580 | {
2581 | "fingerprints": [
2582 | {
2583 | "type": "Content",
2584 | "pattern": "(?i)You were blocked by the Shield"
2585 | },
2586 | {
2587 | "type": "Content",
2588 | "pattern": "(?i)remaining transgression\\(s\\) against this site"
2589 | },
2590 | {
2591 | "type": "Content",
2592 | "pattern": "(?i)Something in the URL.{0,5}?Form or Cookie data wasn\\'t appropriate"
2593 | }
2594 | ],
2595 | "any": true
2596 | }
2597 | ]
2598 | },
2599 | {
2600 | "name": "Cloudflare (Cloudflare Inc.)",
2601 | "schemas": [
2602 | {
2603 | "fingerprints": [
2604 | {
2605 | "type": "Header",
2606 | "header_key": "server",
2607 | "header_value": "(?i)cloudflare"
2608 | },
2609 | {
2610 | "type": "Header",
2611 | "header_key": "server",
2612 | "header_value": "(?i)cloudflare[-_]nginx"
2613 | },
2614 | {
2615 | "type": "Header",
2616 | "header_key": "cf-ray",
2617 | "header_value": "(?i).+?"
2618 | },
2619 | {
2620 | "type": "Cookie",
2621 | "pattern": "(?i)__cfduid"
2622 | }
2623 | ],
2624 | "any": true
2625 | }
2626 | ]
2627 | },
2628 | {
2629 | "name": "Barikode (Ethic Ninja)",
2630 | "schemas": [
2631 | {
2632 | "fingerprints": [
2633 | {
2634 | "type": "Content",
2635 | "pattern": "(?i)\u003cstrong\u003ebarikode\u003c.strong\u003e"
2636 | }
2637 | ],
2638 | "any": true
2639 | }
2640 | ]
2641 | },
2642 | {
2643 | "name": "DynamicWeb Injection Check (DynamicWeb)",
2644 | "schemas": [
2645 | {
2646 | "fingerprints": [
2647 | {
2648 | "type": "Header",
2649 | "header_key": "X-403-Status-By",
2650 | "header_value": "(?i)dw.inj.check",
2651 | "attack": true
2652 | },
2653 | {
2654 | "type": "Content",
2655 | "pattern": "(?i)by dynamic check(.{0,10}?module)?"
2656 | }
2657 | ],
2658 | "any": true
2659 | }
2660 | ]
2661 | },
2662 | {
2663 | "name": "PT Application Firewall (Positive Technologies)",
2664 | "schemas": [
2665 | {
2666 | "fingerprints": [
2667 | {
2668 | "type": "Content",
2669 | "pattern": "(?i)\u003ch1.{0,10}?Forbidden"
2670 | },
2671 | {
2672 | "type": "Content",
2673 | "pattern": "(?i)\u003cpre\u003eRequest.ID:.{0,10}?\\d{4}\\-(\\d{2})+.{0,35}?pre\u003e"
2674 | }
2675 | ]
2676 | }
2677 | ]
2678 | },
2679 | {
2680 | "name": "OnMessage Shield (BlackBaud)",
2681 | "schemas": [
2682 | {
2683 | "fingerprints": [
2684 | {
2685 | "type": "Header",
2686 | "header_key": "X-Engine",
2687 | "header_value": "(?i)onMessage Shield"
2688 | },
2689 | {
2690 | "type": "Content",
2691 | "pattern": "(?i)Blackbaud K\\-12 conducts routine maintenance"
2692 | },
2693 | {
2694 | "type": "Content",
2695 | "pattern": "(?i)onMessage SHEILD"
2696 | },
2697 | {
2698 | "type": "Content",
2699 | "pattern": "(?i)maintenance\\.blackbaud\\.com"
2700 | },
2701 | {
2702 | "type": "Content",
2703 | "pattern": "(?i)status\\.blackbaud\\.com"
2704 | }
2705 | ],
2706 | "any": true
2707 | }
2708 | ]
2709 | },
2710 | {
2711 | "name": "LimeLight CDN (LimeLight)",
2712 | "schemas": [
2713 | {
2714 | "fingerprints": [
2715 | {
2716 | "type": "Cookie",
2717 | "pattern": "(?i)^limelight"
2718 | },
2719 | {
2720 | "type": "Cookie",
2721 | "pattern": "(?i)^l[mg]_sessid="
2722 | }
2723 | ],
2724 | "any": true
2725 | }
2726 | ]
2727 | },
2728 | {
2729 | "name": "Janusec Application Gateway (Janusec)",
2730 | "schemas": [
2731 | {
2732 | "fingerprints": [
2733 | {
2734 | "type": "Content",
2735 | "pattern": "(?i)janusec application gateway"
2736 | }
2737 | ],
2738 | "any": true
2739 | }
2740 | ]
2741 | },
2742 | {
2743 | "name": "WebSEAL (IBM)",
2744 | "schemas": [
2745 | {
2746 | "fingerprints": [
2747 | {
2748 | "type": "Header",
2749 | "header_key": "Server",
2750 | "header_value": "(?i)WebSEAL"
2751 | },
2752 | {
2753 | "type": "Content",
2754 | "pattern": "(?i)This is a WebSEAL error message template file"
2755 | },
2756 | {
2757 | "type": "Content",
2758 | "pattern": "(?i)WebSEAL server received an invalid HTTP request"
2759 | }
2760 | ],
2761 | "any": true
2762 | }
2763 | ]
2764 | },
2765 | {
2766 | "name": "Palo Alto Next Gen Firewall (Palo Alto Networks)",
2767 | "schemas": [
2768 | {
2769 | "fingerprints": [
2770 | {
2771 | "type": "Content",
2772 | "pattern": "(?i)Download of virus.spyware blocked"
2773 | },
2774 | {
2775 | "type": "Content",
2776 | "pattern": "(?i)Palo Alto Next Generation Security Platform"
2777 | }
2778 | ],
2779 | "any": true
2780 | }
2781 | ]
2782 | },
2783 | {
2784 | "name": "PentaWAF (Global Network Services)",
2785 | "schemas": [
2786 | {
2787 | "fingerprints": [
2788 | {
2789 | "type": "Header",
2790 | "header_key": "Server",
2791 | "header_value": "(?i)PentaWaf(/[0-9\\.]+)?"
2792 | },
2793 | {
2794 | "type": "Content",
2795 | "pattern": "(?i)Penta.?Waf/[0-9\\.]+?.server"
2796 | }
2797 | ],
2798 | "any": true
2799 | }
2800 | ]
2801 | },
2802 | {
2803 | "name": "BIG-IP AppSec Manager (F5 Networks)",
2804 | "schemas": [
2805 | {
2806 | "fingerprints": [
2807 | {
2808 | "type": "Content",
2809 | "pattern": "(?i)the requested url was rejected"
2810 | },
2811 | {
2812 | "type": "Content",
2813 | "pattern": "(?i)please consult with your administrator"
2814 | }
2815 | ]
2816 | },
2817 | {
2818 | "fingerprints": [
2819 | {
2820 | "type": "Cookie",
2821 | "pattern": "(?i)^TS.+?"
2822 | }
2823 | ]
2824 | }
2825 | ]
2826 | },
2827 | {
2828 | "name": "ZScaler (Accenture)",
2829 | "schemas": [
2830 | {
2831 | "fingerprints": [
2832 | {
2833 | "type": "Header",
2834 | "header_key": "Server",
2835 | "header_value": "(?i)ZScaler"
2836 | },
2837 | {
2838 | "type": "Content",
2839 | "pattern": "(?i)Access Denied.{0,10}?Accenture Policy"
2840 | },
2841 | {
2842 | "type": "Content",
2843 | "pattern": "(?i)policies\\.accenture\\.com"
2844 | },
2845 | {
2846 | "type": "Content",
2847 | "pattern": "(?i)login\\.zscloud\\.net/img_logo_new1\\.png"
2848 | },
2849 | {
2850 | "type": "Content",
2851 | "pattern": "(?i)Zscaler to protect you from internet threats"
2852 | },
2853 | {
2854 | "type": "Content",
2855 | "pattern": "(?i)Internet Security by ZScaler"
2856 | },
2857 | {
2858 | "type": "Content",
2859 | "pattern": "(?i)Accenture.{0,10}?webfilters indicate that the site likely contains"
2860 | }
2861 | ],
2862 | "any": true
2863 | }
2864 | ]
2865 | },
2866 | {
2867 | "name": "AzionCDN (AzionCDN)",
2868 | "schemas": [
2869 | {
2870 | "fingerprints": [
2871 | {
2872 | "type": "Header",
2873 | "header_key": "Server",
2874 | "header_value": "(?i)Azion([-_]CDN)?"
2875 | }
2876 | ],
2877 | "any": true
2878 | }
2879 | ]
2880 | },
2881 | {
2882 | "name": "BulletProof Security Pro (AITpro Security)",
2883 | "schemas": [
2884 | {
2885 | "fingerprints": [
2886 | {
2887 | "type": "Content",
2888 | "pattern": "(?i)\\+?bpsMessage"
2889 | },
2890 | {
2891 | "type": "Content",
2892 | "pattern": "(?i)403 Forbidden Error Page"
2893 | },
2894 | {
2895 | "type": "Content",
2896 | "pattern": "(?i)If you arrived here due to a search"
2897 | }
2898 | ]
2899 | }
2900 | ]
2901 | },
2902 | {
2903 | "name": "FortiWeb (Fortinet)",
2904 | "schemas": [
2905 | {
2906 | "fingerprints": [
2907 | {
2908 | "type": "Cookie",
2909 | "pattern": "(?i)^FORTIWAFSID="
2910 | },
2911 | {
2912 | "type": "Content",
2913 | "pattern": "(?i).fgd_icon"
2914 | }
2915 | ],
2916 | "any": true
2917 | },
2918 | {
2919 | "fingerprints": [
2920 | {
2921 | "type": "Content",
2922 | "pattern": "(?i)fgd_icon"
2923 | },
2924 | {
2925 | "type": "Content",
2926 | "pattern": "(?i)web.page.blocked"
2927 | },
2928 | {
2929 | "type": "Content",
2930 | "pattern": "(?i)url"
2931 | },
2932 | {
2933 | "type": "Content",
2934 | "pattern": "(?i)attack.id"
2935 | },
2936 | {
2937 | "type": "Content",
2938 | "pattern": "(?i)message.id"
2939 | },
2940 | {
2941 | "type": "Content",
2942 | "pattern": "(?i)client.ip"
2943 | }
2944 | ]
2945 | }
2946 | ]
2947 | },
2948 | {
2949 | "name": "DotDefender (Applicure Technologies)",
2950 | "schemas": [
2951 | {
2952 | "fingerprints": [
2953 | {
2954 | "type": "Header",
2955 | "header_key": "X-dotDefender-denied",
2956 | "header_value": "(?i).+?",
2957 | "attack": true
2958 | },
2959 | {
2960 | "type": "Content",
2961 | "pattern": "(?i)dotdefender blocked your request"
2962 | },
2963 | {
2964 | "type": "Content",
2965 | "pattern": "(?i)Applicure is the leading provider of web application security"
2966 | }
2967 | ],
2968 | "any": true
2969 | }
2970 | ]
2971 | },
2972 | {
2973 | "name": "KS-WAF (KnownSec)",
2974 | "schemas": [
2975 | {
2976 | "fingerprints": [
2977 | {
2978 | "type": "Content",
2979 | "pattern": "(?i)/ks[-_]waf[-_]error\\.png"
2980 | }
2981 | ],
2982 | "any": true
2983 | }
2984 | ]
2985 | },
2986 | {
2987 | "name": "Cloud Protector (Rohde \u0026 Schwarz CyberSecurity)",
2988 | "schemas": [
2989 | {
2990 | "fingerprints": [
2991 | {
2992 | "type": "Content",
2993 | "pattern": "(?i)Cloud Protector.*?by Rohde.{3,8}?Schwarz Cybersecurity"
2994 | },
2995 | {
2996 | "type": "Content",
2997 | "pattern": "(?i)\u003ca href='https?:\\/\\/(?:www\\.)?cloudprotector\\.com\\/'\u003eR.{1,6}?S.Cloud Protector"
2998 | }
2999 | ],
3000 | "any": true
3001 | }
3002 | ]
3003 | },
3004 | {
3005 | "name": "ServerDefender VP (Port80 Software)",
3006 | "schemas": [
3007 | {
3008 | "fingerprints": [
3009 | {
3010 | "type": "Header",
3011 | "header_key": "X-Pint",
3012 | "header_value": "(?i)p(ort\\-)?80"
3013 | }
3014 | ],
3015 | "any": true
3016 | }
3017 | ]
3018 | },
3019 | {
3020 | "name": "Alert Logic (Alert Logic)",
3021 | "schemas": [
3022 | {
3023 | "fingerprints": [
3024 | {
3025 | "type": "Content",
3026 | "pattern": "(?i)\u003c(title|h\\d{1})\u003erequested url cannot be found"
3027 | },
3028 | {
3029 | "type": "Content",
3030 | "pattern": "(?i)we are sorry.{0,10}?but the page you are looking for cannot be found"
3031 | },
3032 | {
3033 | "type": "Content",
3034 | "pattern": "(?i)back to previous page"
3035 | },
3036 | {
3037 | "type": "Content",
3038 | "pattern": "(?i)proceed to homepage"
3039 | },
3040 | {
3041 | "type": "Content",
3042 | "pattern": "(?i)reference id"
3043 | }
3044 | ]
3045 | }
3046 | ]
3047 | },
3048 | {
3049 | "name": "Cloudfront (Amazon)",
3050 | "schemas": [
3051 | {
3052 | "fingerprints": [
3053 | {
3054 | "type": "Header",
3055 | "header_key": "Server",
3056 | "header_value": "(?i)Cloudfront"
3057 | },
3058 | {
3059 | "type": "Header",
3060 | "header_key": "Via",
3061 | "header_value": "(?i)([0-9\\.]+?)? \\w+?\\.cloudfront\\.net \\(Cloudfront\\)"
3062 | },
3063 | {
3064 | "type": "Header",
3065 | "header_key": "X-Amz-Cf-Id",
3066 | "header_value": "(?i).+?",
3067 | "attack": true
3068 | },
3069 | {
3070 | "type": "Header",
3071 | "header_key": "X-Cache",
3072 | "header_value": "(?i)Error from Cloudfront",
3073 | "attack": true
3074 | },
3075 | {
3076 | "type": "Content",
3077 | "pattern": "(?i)Generated by cloudfront \\(CloudFront\\)"
3078 | }
3079 | ],
3080 | "any": true
3081 | }
3082 | ]
3083 | },
3084 | {
3085 | "name": "Xuanwudun (Xuanwudun)",
3086 | "schemas": [
3087 | {
3088 | "fingerprints": [
3089 | {
3090 | "type": "Content",
3091 | "pattern": "(?i)admin\\.dbappwaf\\.cn/(index\\.php/Admin/ClientMisinform/)?"
3092 | },
3093 | {
3094 | "type": "Content",
3095 | "pattern": "(?i)class=.(db[\\-_]?)?waf(.)?([\\-_]?row)?\u003e"
3096 | }
3097 | ],
3098 | "any": true
3099 | }
3100 | ]
3101 | },
3102 | {
3103 | "name": "Wallarm (Wallarm Inc.)",
3104 | "schemas": [
3105 | {
3106 | "fingerprints": [
3107 | {
3108 | "type": "Header",
3109 | "header_key": "Server",
3110 | "header_value": "(?i)nginx[\\-_]wallarm"
3111 | }
3112 | ],
3113 | "any": true
3114 | }
3115 | ]
3116 | },
3117 | {
3118 | "name": "DenyALL (Rohde \u0026 Schwarz CyberSecurity)",
3119 | "schemas": [
3120 | {
3121 | "fingerprints": [
3122 | {
3123 | "type": "Status",
3124 | "pattern": "200"
3125 | },
3126 | {
3127 | "type": "Reason",
3128 | "pattern": "(?i)Condition Intercepted"
3129 | }
3130 | ]
3131 | }
3132 | ]
3133 | },
3134 | {
3135 | "name": "Yundun (Yundun)",
3136 | "schemas": [
3137 | {
3138 | "fingerprints": [
3139 | {
3140 | "type": "Header",
3141 | "header_key": "Server",
3142 | "header_value": "(?i)YUNDUN"
3143 | },
3144 | {
3145 | "type": "Header",
3146 | "header_key": "X-Cache",
3147 | "header_value": "(?i)YUNDUN"
3148 | },
3149 | {
3150 | "type": "Cookie",
3151 | "pattern": "(?i)^yd_cookie="
3152 | },
3153 | {
3154 | "type": "Content",
3155 | "pattern": "(?i)Blocked by YUNDUN Cloud WAF"
3156 | },
3157 | {
3158 | "type": "Content",
3159 | "pattern": "(?i)yundun\\.com/yd[-_]http[_-]error/"
3160 | },
3161 | {
3162 | "type": "Content",
3163 | "pattern": "(?i)www\\.yundun\\.com/(static/js/fingerprint\\d{1}?\\.js)?"
3164 | }
3165 | ],
3166 | "any": true
3167 | }
3168 | ]
3169 | },
3170 | {
3171 | "name": "360WangZhanBao (360 Technologies)",
3172 | "schemas": [
3173 | {
3174 | "fingerprints": [
3175 | {
3176 | "type": "Header",
3177 | "header_key": "Server",
3178 | "header_value": "(?i)qianxin\\-waf"
3179 | },
3180 | {
3181 | "type": "Header",
3182 | "header_key": "WZWS-Ray",
3183 | "header_value": "(?i).+?"
3184 | },
3185 | {
3186 | "type": "Header",
3187 | "header_key": "X-Powered-By-360WZB",
3188 | "header_value": "(?i).+?"
3189 | },
3190 | {
3191 | "type": "Content",
3192 | "pattern": "(?i)wzws\\-waf\\-cgi/"
3193 | },
3194 | {
3195 | "type": "Content",
3196 | "pattern": "(?i)wangshan\\.360\\.cn"
3197 | },
3198 | {
3199 | "type": "Status",
3200 | "pattern": "493"
3201 | }
3202 | ],
3203 | "any": true
3204 | }
3205 | ]
3206 | },
3207 | {
3208 | "name": "ModSecurity (SpiderLabs)",
3209 | "schemas": [
3210 | {
3211 | "fingerprints": [
3212 | {
3213 | "type": "Header",
3214 | "header_key": "Server",
3215 | "header_value": "(?i)(mod_security|Mod_Security|NOYB)"
3216 | },
3217 | {
3218 | "type": "Content",
3219 | "pattern": "(?i)This error was generated by Mod.?Security"
3220 | },
3221 | {
3222 | "type": "Content",
3223 | "pattern": "(?i)rules of the mod.security.module"
3224 | },
3225 | {
3226 | "type": "Content",
3227 | "pattern": "(?i)mod.security.rules triggered"
3228 | },
3229 | {
3230 | "type": "Content",
3231 | "pattern": "(?i)Protected by Mod.?Security"
3232 | },
3233 | {
3234 | "type": "Content",
3235 | "pattern": "(?i)/modsecurity[\\-_]errorpage/"
3236 | },
3237 | {
3238 | "type": "Content",
3239 | "pattern": "(?i)modsecurity iis"
3240 | }
3241 | ],
3242 | "any": true
3243 | },
3244 | {
3245 | "fingerprints": [
3246 | {
3247 | "type": "Reason",
3248 | "pattern": "(?i)ModSecurity Action"
3249 | },
3250 | {
3251 | "type": "Status",
3252 | "pattern": "403"
3253 | }
3254 | ]
3255 | },
3256 | {
3257 | "fingerprints": [
3258 | {
3259 | "type": "Reason",
3260 | "pattern": "(?i)ModSecurity Action"
3261 | },
3262 | {
3263 | "type": "Status",
3264 | "pattern": "406"
3265 | }
3266 | ]
3267 | }
3268 | ]
3269 | },
3270 | {
3271 | "name": "RayWAF (WebRay Solutions)",
3272 | "schemas": [
3273 | {
3274 | "fingerprints": [
3275 | {
3276 | "type": "Header",
3277 | "header_key": "Server",
3278 | "header_value": "(?i)WebRay\\-WAF"
3279 | },
3280 | {
3281 | "type": "Header",
3282 | "header_key": "DrivedBy",
3283 | "header_value": "(?i)RaySrv.RayEng/[0-9\\.]+?"
3284 | }
3285 | ],
3286 | "any": true
3287 | }
3288 | ]
3289 | },
3290 | {
3291 | "name": "Barracuda (Barracuda Networks)",
3292 | "schemas": [
3293 | {
3294 | "fingerprints": [
3295 | {
3296 | "type": "Cookie",
3297 | "pattern": "(?i)^barra_counter_session="
3298 | },
3299 | {
3300 | "type": "Cookie",
3301 | "pattern": "(?i)^BNI__BARRACUDA_LB_COOKIE="
3302 | },
3303 | {
3304 | "type": "Cookie",
3305 | "pattern": "(?i)^BNI_persistence="
3306 | },
3307 | {
3308 | "type": "Cookie",
3309 | "pattern": "(?i)^BN[IE]S_.*?="
3310 | },
3311 | {
3312 | "type": "Content",
3313 | "pattern": "(?i)Barracuda.Networks"
3314 | }
3315 | ],
3316 | "any": true
3317 | }
3318 | ]
3319 | },
3320 | {
3321 | "name": "aeSecure (aeSecure)",
3322 | "schemas": [
3323 | {
3324 | "fingerprints": [
3325 | {
3326 | "type": "Header",
3327 | "header_key": "aeSecure-code",
3328 | "header_value": "(?i).+?"
3329 | },
3330 | {
3331 | "type": "Content",
3332 | "pattern": "(?i)aesecure_denied\\.png"
3333 | }
3334 | ],
3335 | "any": true
3336 | }
3337 | ]
3338 | },
3339 | {
3340 | "name": "FirePass (F5 Networks)",
3341 | "schemas": [
3342 | {
3343 | "fingerprints": [
3344 | {
3345 | "type": "Cookie",
3346 | "pattern": "(?i)^VHOST"
3347 | },
3348 | {
3349 | "type": "Header",
3350 | "header_key": "Location",
3351 | "header_value": "(?i)\\/my\\.logon\\.php3"
3352 | }
3353 | ]
3354 | },
3355 | {
3356 | "fingerprints": [
3357 | {
3358 | "type": "Cookie",
3359 | "pattern": "(?i)^F5_fire.+?"
3360 | },
3361 | {
3362 | "type": "Cookie",
3363 | "pattern": "(?i)^F5_passid_shrinked"
3364 | }
3365 | ]
3366 | }
3367 | ]
3368 | },
3369 | {
3370 | "name": "CacheWall (Varnish)",
3371 | "schemas": [
3372 | {
3373 | "fingerprints": [
3374 | {
3375 | "type": "Header",
3376 | "header_key": "Server",
3377 | "header_value": "(?i)Varnish"
3378 | },
3379 | {
3380 | "type": "Header",
3381 | "header_key": "X-Varnish",
3382 | "header_value": "(?i).+"
3383 | },
3384 | {
3385 | "type": "Header",
3386 | "header_key": "X-Cachewall-Action",
3387 | "header_value": "(?i).+?"
3388 | },
3389 | {
3390 | "type": "Header",
3391 | "header_key": "X-Cachewall-Reason",
3392 | "header_value": "(?i).+?"
3393 | },
3394 | {
3395 | "type": "Content",
3396 | "pattern": "(?i)security by cachewall"
3397 | },
3398 | {
3399 | "type": "Content",
3400 | "pattern": "(?i)403 naughty.{0,10}?not nice!"
3401 | },
3402 | {
3403 | "type": "Content",
3404 | "pattern": "(?i)varnish cache server"
3405 | }
3406 | ],
3407 | "any": true
3408 | }
3409 | ]
3410 | },
3411 | {
3412 | "name": "ASPA Firewall (ASPA Engineering Co.)",
3413 | "schemas": [
3414 | {
3415 | "fingerprints": [
3416 | {
3417 | "type": "Header",
3418 | "header_key": "Server",
3419 | "header_value": "(?i)ASPA[\\-_]?WAF"
3420 | },
3421 | {
3422 | "type": "Header",
3423 | "header_key": "ASPA-Cache-Status",
3424 | "header_value": "(?i).+?"
3425 | }
3426 | ],
3427 | "any": true
3428 | }
3429 | ]
3430 | },
3431 | {
3432 | "name": "Nemesida (PentestIt)",
3433 | "schemas": [
3434 | {
3435 | "fingerprints": [
3436 | {
3437 | "type": "Content",
3438 | "pattern": "(?i)@?nemesida(\\-security)?\\.com"
3439 | },
3440 | {
3441 | "type": "Content",
3442 | "pattern": "(?i)Suspicious activity detected.{0,10}?Access to the site is blocked"
3443 | },
3444 | {
3445 | "type": "Content",
3446 | "pattern": "(?i)nwaf@"
3447 | },
3448 | {
3449 | "type": "Status",
3450 | "pattern": "222"
3451 | }
3452 | ],
3453 | "any": true
3454 | }
3455 | ]
3456 | },
3457 | {
3458 | "name": "Edgecast (Verizon Digital Media)",
3459 | "schemas": [
3460 | {
3461 | "fingerprints": [
3462 | {
3463 | "type": "Header",
3464 | "header_key": "Server",
3465 | "header_value": "(?i)^ECD(.+)?"
3466 | },
3467 | {
3468 | "type": "Header",
3469 | "header_key": "Server",
3470 | "header_value": "(?i)^ECS(.*)?"
3471 | }
3472 | ],
3473 | "any": true
3474 | }
3475 | ]
3476 | },
3477 | {
3478 | "name": "CacheFly CDN (CacheFly)",
3479 | "schemas": [
3480 | {
3481 | "fingerprints": [
3482 | {
3483 | "type": "Header",
3484 | "header_key": "BestCDN",
3485 | "header_value": "(?i)Cachefly"
3486 | },
3487 | {
3488 | "type": "Cookie",
3489 | "pattern": "(?i)^cfly_req.*="
3490 | }
3491 | ],
3492 | "any": true
3493 | }
3494 | ]
3495 | },
3496 | {
3497 | "name": "WebKnight (AQTRONIX)",
3498 | "schemas": [
3499 | {
3500 | "fingerprints": [
3501 | {
3502 | "type": "Status",
3503 | "pattern": "999"
3504 | },
3505 | {
3506 | "type": "Reason",
3507 | "pattern": "(?i)No Hacking"
3508 | },
3509 | {
3510 | "type": "Status",
3511 | "pattern": "404"
3512 | },
3513 | {
3514 | "type": "Reason",
3515 | "pattern": "(?i)Hack Not Found"
3516 | }
3517 | ]
3518 | },
3519 | {
3520 | "fingerprints": [
3521 | {
3522 | "type": "Content",
3523 | "pattern": "(?i)WebKnight Application Firewall Alert"
3524 | },
3525 | {
3526 | "type": "Content",
3527 | "pattern": "(?i)What is webknight\\?"
3528 | },
3529 | {
3530 | "type": "Content",
3531 | "pattern": "(?i)AQTRONIX WebKnight is an application firewall"
3532 | },
3533 | {
3534 | "type": "Content",
3535 | "pattern": "(?i)WebKnight will take over and protect"
3536 | },
3537 | {
3538 | "type": "Content",
3539 | "pattern": "(?i)aqtronix\\.com/WebKnight"
3540 | },
3541 | {
3542 | "type": "Content",
3543 | "pattern": "(?i)AQTRONIX.{0,10}?WebKnight"
3544 | }
3545 | ],
3546 | "any": true
3547 | }
3548 | ]
3549 | },
3550 | {
3551 | "name": "ArvanCloud (ArvanCloud)",
3552 | "schemas": [
3553 | {
3554 | "fingerprints": [
3555 | {
3556 | "type": "Header",
3557 | "header_key": "Server",
3558 | "header_value": "(?i)ArvanCloud"
3559 | }
3560 | ],
3561 | "any": true
3562 | }
3563 | ]
3564 | },
3565 | {
3566 | "name": "MaxCDN (MaxCDN)",
3567 | "schemas": [
3568 | {
3569 | "fingerprints": [
3570 | {
3571 | "type": "Header",
3572 | "header_key": "X-CDN",
3573 | "header_value": "(?i)maxcdn"
3574 | }
3575 | ],
3576 | "any": true
3577 | }
3578 | ]
3579 | },
3580 | {
3581 | "name": "SiteGround (SiteGround)",
3582 | "schemas": [
3583 | {
3584 | "fingerprints": [
3585 | {
3586 | "type": "Content",
3587 | "pattern": "(?i)Our system thinks you might be a robot!"
3588 | },
3589 | {
3590 | "type": "Content",
3591 | "pattern": "(?i)access is restricted due to a security rule"
3592 | }
3593 | ],
3594 | "any": true
3595 | }
3596 | ]
3597 | },
3598 | {
3599 | "name": "NSFocus (NSFocus Global Inc.)",
3600 | "schemas": [
3601 | {
3602 | "fingerprints": [
3603 | {
3604 | "type": "Header",
3605 | "header_key": "Server",
3606 | "header_value": "(?i)NSFocus"
3607 | }
3608 | ],
3609 | "any": true
3610 | }
3611 | ]
3612 | },
3613 | {
3614 | "name": "IndusGuard (Indusface)",
3615 | "schemas": [
3616 | {
3617 | "fingerprints": [
3618 | {
3619 | "type": "Header",
3620 | "header_key": "Server",
3621 | "header_value": "(?i)IF_WAF"
3622 | },
3623 | {
3624 | "type": "Content",
3625 | "pattern": "(?i)This website is secured against online attacks. Your request was blocked"
3626 | }
3627 | ],
3628 | "any": true
3629 | }
3630 | ]
3631 | }
3632 | ]
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/Lu1sDV/wafme0w
2 |
3 | go 1.19
4 |
5 | require (
6 | github.com/jessevdk/go-flags v1.5.0
7 | github.com/logrusorgru/aurora/v4 v4.0.0
8 | )
9 |
10 | require golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 // indirect
11 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2 | github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
3 | github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
4 | github.com/logrusorgru/aurora/v4 v4.0.0 h1:sRjfPpun/63iADiSvGGjgA1cAYegEWMPCJdUpJYn9JA=
5 | github.com/logrusorgru/aurora/v4 v4.0.0/go.mod h1:lP0iIa2nrnT/qoFXcOZSrZQpJ1o6n2CUf/hyHi2Q4ZQ=
6 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
7 | github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
8 | golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 h1:EZ2mChiOa8udjfp6rRmswTbtZN/QzUQp4ptM4rnjHvc=
9 | golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
10 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
11 |
--------------------------------------------------------------------------------
/pkg/utils/http/httputil.go:
--------------------------------------------------------------------------------
1 | package httputil
2 |
3 | import (
4 | strutils "github.com/Lu1sDV/wafme0w/pkg/utils/strings"
5 | "net/http"
6 | "net/url"
7 | "strings"
8 | )
9 |
10 | func ParseURI(uri string) (*url.URL, error) {
11 |
12 | lowerUri := strings.ToLower(uri)
13 | hasScheme := strings.HasPrefix(lowerUri, "http://") || strings.HasPrefix(lowerUri, "https://")
14 | if !hasScheme {
15 | lowerUri = "https://" + lowerUri
16 | }
17 |
18 | parsed, err := url.ParseRequestURI(lowerUri)
19 | if err != nil {
20 | return &url.URL{}, err
21 | }
22 | return parsed, nil
23 | }
24 |
25 | func IsValidHTTPURL(uri string) bool {
26 | var allowedSchemes = []string{"http", "https"}
27 |
28 | if uri == "" {
29 | return false
30 | }
31 |
32 | splitScheme := strings.Split(uri, "://")
33 | if len(splitScheme) > 1 {
34 | scheme := splitScheme[0]
35 | if !strutils.StringInSlice(scheme, allowedSchemes) {
36 | return false
37 | }
38 | } else {
39 | uri = "https://" + uri
40 | }
41 |
42 | _, err := url.ParseRequestURI(uri)
43 | return err == nil
44 | }
45 |
46 | // GetHTTPHeaderByName returns the value of provided header.
47 | // It accepts headers list (http.Header) and header's name
48 | // It returns the value if header is found. Otherwise, returns an empty string
49 | func GetHTTPHeaderByName(headers http.Header, headerName string) string {
50 | if headerName == "" {
51 | return ""
52 | }
53 | for header, headerValue := range headers {
54 | if strings.EqualFold(header, headerName) {
55 | return headerValue[0]
56 | }
57 | }
58 | return ""
59 | }
60 |
--------------------------------------------------------------------------------
/pkg/utils/http/httputil_test.go:
--------------------------------------------------------------------------------
1 | package httputil
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestIsValidURI(t *testing.T) {
8 |
9 | tests := []struct {
10 | name string
11 | args string
12 | want bool
13 | }{
14 | {"Valid www.google.it", "google.it", true},
15 | {"Valid localhost", "localhost", true},
16 | {"Invalid scheme", "wisjj://localhost", false},
17 | {"Invalid scheme", "ftp://localhost", false},
18 | {"Invalid empty", "", false},
19 | //{"InValid url", "!", false}, TODO
20 | // {"InValid url", "http:::/not.valid/a//a", false}, TODO
21 | }
22 | for _, tt := range tests {
23 | t.Run(tt.name, func(t *testing.T) {
24 | if got := IsValidHTTPURL(tt.args); got != tt.want {
25 | t.Errorf("IsValidURI() = %v, want %v", got, tt.want)
26 | }
27 | })
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/pkg/utils/strings/strings.go:
--------------------------------------------------------------------------------
1 | package strutil
2 |
3 | import (
4 | "strings"
5 | "unicode"
6 | )
7 |
8 | func SubStringBetweenDelimiters(s string, firstDelimiter string, secondDelimiter string) string {
9 | i := strings.Index(s, firstDelimiter)
10 | if i >= 0 {
11 | j := strings.Index(s, secondDelimiter)
12 | if j >= 0 {
13 | return s[i+1 : j]
14 | }
15 | }
16 | return ""
17 | }
18 |
19 | func StringInSlice(str string, list []string) bool {
20 | for _, b := range list {
21 | if b == str {
22 | return true
23 | }
24 | }
25 | return false
26 | }
27 |
28 | // SplitAtUpperCases splits a string every time it finds an uppercase
29 | func SplitAtUpperCases(str string) []string {
30 | var words []string
31 | l := 0
32 | for s := str; s != ""; s = s[l:] {
33 | l = strings.IndexFunc(s[1:], unicode.IsUpper) + 1
34 | if l <= 0 {
35 | l = len(s)
36 | }
37 | words = append(words, s[:l])
38 | }
39 | return words
40 | }
41 |
--------------------------------------------------------------------------------
/pkg/utils/strings/strings_test.go:
--------------------------------------------------------------------------------
1 | package strutil
2 |
3 | import (
4 | "reflect"
5 | "testing"
6 | )
7 |
8 | func TestStringInSlice(t *testing.T) {
9 | type args struct {
10 | str string
11 | list []string
12 | }
13 | tests := []struct {
14 | name string
15 | args args
16 | want bool
17 | }{
18 | {name: "Match", args: args{str: "foo", list: []string{"foo", "bar"}}, want: true},
19 | {name: "No match", args: args{str: "foo", list: []string{"ez", "bar"}}, want: false},
20 | }
21 | for _, tt := range tests {
22 | t.Run(tt.name, func(t *testing.T) {
23 | if got := StringInSlice(tt.args.str, tt.args.list); got != tt.want {
24 | t.Errorf("StringInSlice() = %v, want %v", got, tt.want)
25 | }
26 | })
27 | }
28 | }
29 |
30 | func TestSubStringBetweenDelimiters(t *testing.T) {
31 | type args struct {
32 | s string
33 | firstDelimiter string
34 | secondDelimiter string
35 | }
36 | tests := []struct {
37 | name string
38 | args args
39 | want string
40 | }{
41 | {name: "Get \"Bar\" substring", args: args{s: "Foo(Bar)", firstDelimiter: "(", secondDelimiter: ")"}, want: "Bar"},
42 | {name: "No substring found", args: args{s: "Foo[Bar]", firstDelimiter: "(", secondDelimiter: ")"}, want: ""},
43 | }
44 | for _, tt := range tests {
45 | t.Run(tt.name, func(t *testing.T) {
46 | if got := SubStringBetweenDelimiters(tt.args.s, tt.args.firstDelimiter, tt.args.secondDelimiter); got != tt.want {
47 | t.Errorf("SubStringBetweenDelimiters() = %v, want %v", got, tt.want)
48 | }
49 | })
50 | }
51 | }
52 |
53 | func TestSplitAtUpperCases(t *testing.T) {
54 | type args struct {
55 | str string
56 | }
57 | tests := []struct {
58 | name string
59 | args args
60 | want []string
61 | }{
62 | {name: "Split MyString", args: args{str: "MyString"}, want: []string{"My", "String"}},
63 | {name: "Nothing to split", args: args{str: "alllowercase"}, want: []string{"alllowercase"}},
64 | }
65 | for _, tt := range tests {
66 | t.Run(tt.name, func(t *testing.T) {
67 | if got := SplitAtUpperCases(tt.args.str); !reflect.DeepEqual(got, tt.want) {
68 | t.Errorf("SplitAtUpperCases() = %v, want %v", got, tt.want)
69 | }
70 | })
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/pkg/wafme0w/banner.go:
--------------------------------------------------------------------------------
1 | package wafme0w
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | const version = "v0.2.0"
8 |
9 | const cat = `
10 | /\_/\ ___
11 | = o_o =_______ \ \
12 | __^ __( \.__) )
13 | <_____>__(_____)____/` + "\n"
14 |
15 | const whatIs = `
16 | Wafme0w ` + version + "\n"
17 | const explain = `
18 | Fast Web Application Firewall Fingerprinting tool`
19 |
20 | func PrintBanner() {
21 |
22 | banner := cat + whatIs + explain + "\n\n"
23 | fmt.Print(banner)
24 | }
25 |
--------------------------------------------------------------------------------
/pkg/wafme0w/generic_detection.go:
--------------------------------------------------------------------------------
1 | package wafme0w
2 |
3 | import (
4 | "fmt"
5 | strutil "github.com/Lu1sDV/wafme0w/pkg/utils/strings"
6 | "strings"
7 | )
8 |
9 | var genericWAFHeaders = []string{"X-WAF-Protection",
10 | "X-Web-Application-Firewall"}
11 |
12 | type GenericDetection struct {
13 | Reason string
14 | Mode GenericDetectionMode
15 | BeforeStatus int
16 | AfterStatus int
17 | BeforeHeader string
18 | AfterHeader string
19 | RequestType string
20 | GenericWAFHeader string
21 | GenericWAFHeaderValue string
22 | }
23 |
24 | type GenericDetectionMode int
25 |
26 | const (
27 | ChangeInHeader GenericDetectionMode = iota
28 | ChangeInStatus
29 | WAFHeaderDetected
30 | )
31 |
32 | func (g GenericDetectionMode) String() string {
33 | return [...]string{"header changed",
34 | "status changed",
35 | "generic WAF header detected"}[g]
36 | }
37 |
38 | func (g *GenericDetection) generateReason() {
39 |
40 | var tmplTxt string
41 |
42 | //prettify RequestType for output
43 | //eg. From XssAttack to Xss Attack
44 | splitRequestType := strutil.SplitAtUpperCases(g.RequestType)
45 | prettyRequestType := strings.Join(splitRequestType, " ")
46 |
47 | switch g.Mode {
48 | case ChangeInHeader:
49 | tmplTxt = fmt.Sprintf(`The server header is different when the following request was tried: %s
50 | Normal Server header is: "%s" while response's header is: "%s"`, prettyRequestType, g.BeforeHeader, g.AfterHeader)
51 |
52 | case ChangeInStatus:
53 | tmplTxt = fmt.Sprintf(`Server returned a different response when the following request was tried: %s
54 | Normal response code is "%d" while response's status code is "%d"`, prettyRequestType, g.BeforeStatus, g.AfterStatus)
55 |
56 | case WAFHeaderDetected:
57 | tmplTxt = fmt.Sprintf(`The Web Application has a Generic WAF header when the following request was tried: %s
58 | The header is: "%s" and its value is: "%s"`, prettyRequestType, g.GenericWAFHeader, g.GenericWAFHeaderValue)
59 |
60 | }
61 | g.Reason = tmplTxt
62 | }
63 |
--------------------------------------------------------------------------------
/pkg/wafme0w/http.go:
--------------------------------------------------------------------------------
1 | package wafme0w
2 |
3 | import (
4 | "compress/flate"
5 | "compress/gzip"
6 | "fmt"
7 | "io"
8 | "net/http"
9 | "net/url"
10 | "time"
11 | )
12 |
13 | var defaultHeaders = map[string]string{
14 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
15 | "Accept-Encoding": "gzip, deflate",
16 | "Accept-Language": "en-US,en;q=0.9",
17 | "DNT": "1", // Do Not Track request header
18 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
19 | "Upgrade-Insecure-Requests": "1",
20 | "Referer": "https://www.google.com/",
21 | }
22 |
23 | const timeOut = 5 * time.Second
24 |
25 | type RequestResponse struct {
26 | Target string
27 | Type string
28 | Data *http.Response
29 | Body []byte
30 | Error error
31 | }
32 |
33 | type HTTPRequest struct {
34 | Options RequestOpts
35 | Client http.Client
36 | }
37 |
38 | func NewHTTPRequest(options RequestOpts, client http.Client) HTTPRequest {
39 | return HTTPRequest{Options: options, Client: client}
40 | }
41 |
42 | func NewHTTPClient() http.Client {
43 | return http.Client{
44 | Timeout: timeOut,
45 | }
46 | }
47 |
48 | func (h HTTPRequest) Send() (response RequestResponse, err error) {
49 | var reader io.ReadCloser
50 | endPoint := h.Options.Target + h.Options.Path
51 |
52 | if len(h.Options.Params) != 0 {
53 | baseUrl, err := url.Parse(endPoint)
54 | if err != nil {
55 | return RequestResponse{}, fmt.Errorf("error parsing endpoint. %w", err)
56 | }
57 |
58 | params := url.Values{}
59 |
60 | for param, value := range h.Options.Params {
61 | params.Add(param, value)
62 | }
63 | baseUrl.RawQuery = params.Encode()
64 | endPoint = baseUrl.String()
65 | }
66 |
67 | req, err := http.NewRequest(h.Options.Method, endPoint, h.Options.PostBody)
68 | if err != nil {
69 | return RequestResponse{}, fmt.Errorf("error creating request: %w", err)
70 | }
71 |
72 | //set headers
73 | for header, value := range h.Options.Headers {
74 | req.Header.Set(header, value)
75 | }
76 |
77 | resp, err := h.Client.Do(req)
78 | if err != nil {
79 | return RequestResponse{}, fmt.Errorf("error sending request to endpoint. %w", err)
80 | }
81 | switch resp.Header.Get("Content-Encoding") {
82 | case "gzip":
83 | reader, err = gzip.NewReader(resp.Body)
84 | if err != nil {
85 | return RequestResponse{}, fmt.Errorf("error reading body: %w", err)
86 | }
87 | case "deflate":
88 | reader = flate.NewReader(resp.Body)
89 | default:
90 | reader = resp.Body
91 | }
92 |
93 | body, err := io.ReadAll(reader)
94 |
95 | if err != nil {
96 | return RequestResponse{}, fmt.Errorf("error reading body: %w", err)
97 | }
98 | defer reader.Close()
99 |
100 | return RequestResponse{Target: h.Options.Target, Data: resp, Body: body}, nil
101 | }
102 |
--------------------------------------------------------------------------------
/pkg/wafme0w/identify.go:
--------------------------------------------------------------------------------
1 | package wafme0w
2 |
3 | import (
4 | httputil "github.com/Lu1sDV/wafme0w/pkg/utils/http"
5 | "regexp"
6 | "strconv"
7 | )
8 |
9 | type WAF struct {
10 | Name string `json:"name"` //WAF NAME
11 | Schemas []Scheme `json:"schemas"`
12 | }
13 |
14 | type Scheme struct {
15 | FingerPrints []FingerPrint `json:"fingerprints,omitempty"`
16 | Any bool `json:"any,omitempty"` //If any fingerprint should be present or if all of them
17 | }
18 |
19 | type FingerPrint struct {
20 | Type string `json:"type,omitempty"` // Header or Content or Cookie or Status or Reason
21 | HeaderKey string `json:"header_key,omitempty"` // Only for header type
22 | HeaderValue string `json:"header_value,omitempty"` // Only for header type
23 | Pattern string `json:"pattern,omitempty"` // Fingerprint for other types
24 | Attack bool `json:"attack,omitempty"`
25 | }
26 |
27 | type FingerPrintDetection struct {
28 | WafName string
29 | }
30 |
31 | type Identify struct {
32 | Responses []RequestResponse
33 | Wafs []WAF
34 | }
35 |
36 | func NewIdentifier(responses []RequestResponse, wafs []WAF) *Identify {
37 | return &Identify{Responses: responses, Wafs: wafs}
38 | }
39 |
40 | // DoAll does WAF fingerprint on all received http responses
41 | func (i *Identify) DoAll() []FingerPrintDetection {
42 | var fingerPrintPattern string
43 | var responseHeader string
44 | var responses = i.Responses
45 | emptyRequest := &RequestResponse{}
46 | var results []FingerPrintDetection
47 |
48 | WAFSLOOP:
49 | for _, waf := range i.Wafs {
50 | for _, schema := range waf.Schemas {
51 | matchingFingerPrints := 0
52 | fingerPrintsCount := len(schema.FingerPrints)
53 | FINGERLOOP:
54 | for _, fingerPrint := range schema.FingerPrints {
55 | for _, r := range responses {
56 | requestName := r.Type
57 | response := getResponseByType(&responses, requestName)
58 |
59 | if response == emptyRequest {
60 | continue
61 | }
62 |
63 | if response.Data == nil {
64 | continue
65 | }
66 | switch fingerPrint.Type {
67 | case "Cookie":
68 | fingerPrintPattern = fingerPrint.Pattern
69 | for _, cookie := range response.Data.Cookies() {
70 | if matched, _ := regexp.MatchString(fingerPrintPattern, cookie.String()); matched {
71 | //add to waf
72 | matchingFingerPrints++
73 | continue FINGERLOOP
74 | }
75 | }
76 |
77 | case "Header":
78 | fingerPrintPattern = fingerPrint.HeaderValue
79 | responseHeader = response.Data.Header.Get(fingerPrint.HeaderKey)
80 | if matched, _ := regexp.MatchString(fingerPrintPattern, responseHeader); matched {
81 | //add to waf
82 | matchingFingerPrints++
83 | continue FINGERLOOP
84 | }
85 | case "Content":
86 | if matched, _ := regexp.MatchString(fingerPrint.Pattern, string(response.Body)); matched {
87 | //add to waf
88 | matchingFingerPrints++
89 | continue FINGERLOOP
90 | }
91 | case "Status":
92 | responseStatusCode := response.Data.StatusCode
93 | fingerPrintStatusCode, err := strconv.Atoi(fingerPrint.Pattern)
94 | if err != nil {
95 | continue
96 | }
97 | if responseStatusCode == fingerPrintStatusCode {
98 | matchingFingerPrints++
99 | continue FINGERLOOP
100 | }
101 | case "Reason":
102 | //TODO
103 | }
104 | }
105 | }
106 |
107 | if matchingFingerPrints != 0 {
108 | if !schema.Any {
109 | //All fingerprints in schema must match
110 | if matchingFingerPrints != fingerPrintsCount {
111 | continue
112 | }
113 | }
114 | results = append(results, FingerPrintDetection{WafName: waf.Name})
115 | continue WAFSLOOP
116 | }
117 | }
118 | }
119 | return results
120 | }
121 |
122 | // GenericDetect detects generic firewall activities
123 | func (i *Identify) GenericDetect() GenericDetection {
124 | responses := i.Responses
125 | var detection GenericDetection
126 | emptyDetection := GenericDetection{}
127 |
128 | normalResponse := getResponseByType(&responses, "Normal")
129 | if normalResponse.Data == nil {
130 | return emptyDetection
131 | }
132 | normalStatusCode := normalResponse.Data.StatusCode
133 | normalServerHeader := normalResponse.Data.Header.Get("Server")
134 |
135 | OUTERLOOP:
136 | for _, resp := range responses {
137 | if resp.Type == "Normal" || resp.Data == nil {
138 | continue
139 | }
140 | responseServerHeader := resp.Data.Header.Get("Server")
141 | responseStatusCode := resp.Data.StatusCode
142 | //check if any generic WAF header is thrown
143 | for _, wafHeader := range genericWAFHeaders {
144 | headerValue := httputil.GetHTTPHeaderByName(resp.Data.Header, wafHeader)
145 | if headerValue == "" {
146 | //header not found
147 | continue
148 | }
149 | detection = GenericDetection{Mode: WAFHeaderDetected,
150 | GenericWAFHeader: wafHeader,
151 | GenericWAFHeaderValue: headerValue,
152 | RequestType: resp.Type,
153 | }
154 | break OUTERLOOP
155 | }
156 | //check if any different status code is thrown
157 | if normalStatusCode != responseStatusCode {
158 | //skip not found
159 | if responseStatusCode == 404 {
160 | continue
161 | }
162 | detection = GenericDetection{Mode: ChangeInStatus,
163 | BeforeStatus: normalStatusCode,
164 | AfterStatus: responseStatusCode,
165 | RequestType: resp.Type,
166 | }
167 | break OUTERLOOP
168 | }
169 | //check any change in Server Header
170 | if normalServerHeader != responseServerHeader {
171 | //skip not found
172 | detection = GenericDetection{Mode: ChangeInHeader,
173 | BeforeHeader: normalServerHeader,
174 | AfterHeader: responseServerHeader,
175 | RequestType: resp.Type,
176 | }
177 | break OUTERLOOP
178 | }
179 | }
180 |
181 | if detection != emptyDetection {
182 | detection.generateReason()
183 | return detection
184 | }
185 | return emptyDetection
186 | }
187 |
--------------------------------------------------------------------------------
/pkg/wafme0w/options.go:
--------------------------------------------------------------------------------
1 | package wafme0w
2 |
3 | import "io"
4 |
5 | type Options struct {
6 | Inputs io.Reader
7 | FingerPrints io.Reader
8 | Headers []string
9 | StdIn bool
10 | Target string `short:"t" long:"target" description:"Your Web Application target"`
11 | InputFile string `short:"I" long:"input" description:"Your input file with a list of targets"`
12 | OutputFile string `short:"O" long:"output" description:"Output file, will be JSON CSV or TXT depending on extension"`
13 | HeadersFile string `short:"H" long:"headers" description:"File containing custom headers, will replace default ones"`
14 | FingerPrintFile string `long:"fingerprints" description:"File containing the JSON-formatted fingerprints"`
15 | Concurrency int `short:"c" long:"concurrency" description:"Number of concurrent workers" default:"20"`
16 | FastMode bool `long:"fast" description:"Enable Fast Mode, blazing fast but less precise. Sends less requests more concurrently"`
17 | ExcludeGeneric bool `long:"no-generic" description:"Exclude generic WAF check"`
18 | ListWAFS bool `long:"list" description:"List all detectable WAFs"`
19 | Silent bool `long:"silent" description:"Enable silent mode to disable console output"`
20 | NoColors bool `long:"no-colors" description:"Disable colored output"`
21 | SuppressWarnings bool `long:"no-warning" description:"Suppress console scan warnings"`
22 | //Verbose bool `short:"v" long:"verbose" description:"Show verbose debug information"` TODO
23 | //Payload string `long:"payload" description:"Payload to send along with default attack vectors"` TODO
24 |
25 | }
26 |
27 | func NewOptions() *Options {
28 | return &Options{}
29 | }
30 |
--------------------------------------------------------------------------------
/pkg/wafme0w/output.go:
--------------------------------------------------------------------------------
1 | package wafme0w
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "github.com/logrusorgru/aurora/v4"
7 | "strings"
8 | )
9 |
10 | func printResult(result Result, au *aurora.Aurora) {
11 | var wafs []string
12 | var foundBrackets = "[" + au.Bold(au.BrightGreen("+")).String() + "]"
13 | var informativeBrackets = "[" + au.Bold(au.BrightBlue("*")).String() + "]"
14 | var notFoundBrackets = "[" + au.Bold(au.Yellow("~")).String() + "]"
15 | var colouredTarget = au.BrightCyan(result.Target).Hyperlink(result.Target).String()
16 | //var line string
17 |
18 | for _, finger := range result.FingerPrint {
19 | if finger.WafName != "" {
20 | colouredWafName := au.Bold(au.BrightMagenta(finger.WafName)).String()
21 | wafs = append(wafs, colouredWafName)
22 | }
23 | }
24 |
25 | if len(wafs) > 0 {
26 | fingerResult := colouredTarget + " is behind " + strings.Join(wafs, " AND ")
27 | line := foundBrackets + " " + fingerResult
28 | fmt.Println(line)
29 | }
30 |
31 | if result.Generic.Reason != "" {
32 | formattedReason := strings.Replace(result.Generic.Reason, "\n", "\n ", -1)
33 | genericResult := foundBrackets + " " + colouredTarget + " seems to be behind a WAF or some sort of security solution"
34 | genericReason := informativeBrackets + " Reason: " + formattedReason
35 | line := genericResult + "\n" + genericReason
36 | fmt.Println(line)
37 | }
38 |
39 | if len(wafs) == 0 && result.Generic.Reason == "" {
40 | line := notFoundBrackets + " " + colouredTarget + " no WAFs have been found"
41 | fmt.Println(line)
42 | }
43 | }
44 |
45 | func prepareJSONOutput(results []Result) ([]byte, error) {
46 | var validResults []Result
47 | var jsonOutput []byte
48 |
49 | for _, res := range results {
50 | if res.Generic.Reason != "" || len(res.FingerPrint) != 0 {
51 | validResults = append(validResults, res)
52 | }
53 | }
54 |
55 | if len(validResults) == 0 {
56 | return jsonOutput, nil
57 | }
58 |
59 | jsonOutput, err := json.MarshalIndent(validResults, "", "\t")
60 | if err != nil {
61 | return nil, err
62 | }
63 |
64 | return jsonOutput, nil
65 | }
66 |
67 | func prepareTXTOutput(results []Result) []byte {
68 | var output string
69 | var emptyGeneric = GenericDetection{}
70 |
71 | for _, res := range results {
72 | var line = res.Target
73 |
74 | fingerPrintsFound := len(res.FingerPrint)
75 | var fingerPrints []string
76 |
77 | if fingerPrintsFound == 0 && res.Generic == emptyGeneric {
78 | continue
79 | }
80 | if fingerPrintsFound > 0 {
81 | for _, f := range res.FingerPrint {
82 | fingerPrints = append(fingerPrints, f.WafName)
83 | }
84 | line = line + ":" + strings.Join(fingerPrints, ", ")
85 | }
86 |
87 | if res.Generic != emptyGeneric {
88 | genericNoNewline := strings.Replace(res.Generic.Reason, "\n", " ", -1)
89 | line = line + ":" + genericNoNewline
90 | }
91 |
92 | line = line + "\n"
93 | output = output + line
94 | }
95 |
96 | return []byte(output)
97 | }
98 |
99 | func PrintError(error string, au *aurora.Aurora) {
100 | var errorBrackets = "[" + au.Bold(au.BrightRed("!!")).String() + "]"
101 | line := errorBrackets + " " + error
102 | fmt.Println(line)
103 | }
104 |
105 | func PrintWarning(warning string, au *aurora.Aurora) {
106 | var warningBrackets = "[" + au.Bold(au.BrightYellow("!")).String() + "]"
107 | line := warningBrackets + " " + warning
108 | fmt.Println(line)
109 | }
110 |
111 | func PrintAllWafs(wafs map[string]string, au *aurora.Aurora) {
112 | for waf, manufacturer := range wafs {
113 | colouredWaf := au.Bold(au.BrightMagenta(waf)).String()
114 | colouredManufacturer := au.BrightCyan(manufacturer).String()
115 |
116 | line := "\t" + colouredWaf + " BY " + colouredManufacturer
117 | fmt.Println(line)
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/pkg/wafme0w/request.go:
--------------------------------------------------------------------------------
1 | package wafme0w
2 |
3 | import (
4 | "errors"
5 | "io"
6 | "math/rand"
7 | "net/http"
8 | "reflect"
9 | "strconv"
10 | "sync"
11 | "time"
12 | )
13 |
14 | const (
15 | xssString = ""
16 | sqliString = "UNION SELECT ALL FROM information_schema AND ' or SLEEP(5) or '"
17 | lfiString = "../../../../etc/passwd"
18 | rceString = "/bin/cat /etc/passwd; ping 127.0.0.1; curl google.com"
19 | xxeString = "]>&hack;"
20 | )
21 |
22 | const requestsDelay = 50 * time.Millisecond
23 |
24 | var basicRequestsTypes = []string{"Normal", "NoUserAgent", "CentralAttack"}
25 |
26 | type RequestOpts struct {
27 | Method string
28 | Target string
29 | Path string
30 | Headers map[string]string
31 | Params map[string]string
32 | Type string
33 | PostBody io.Reader
34 | }
35 |
36 | type RequestTypes struct {
37 | Normal RequestOpts
38 | NoUserAgent RequestOpts
39 | NonExistent RequestOpts
40 | XssAttack RequestOpts
41 | XxeAttack RequestOpts
42 | LfiAttack RequestOpts
43 | CentralAttack RequestOpts
44 | SqliAttack RequestOpts
45 | RceAttack RequestOpts
46 | }
47 |
48 | func newTypeOptions(target string) RequestTypes {
49 |
50 | //create random path
51 | rand.Seed(time.Now().UnixNano())
52 | minInt := 100000
53 | maxInt := 1000000
54 | randomInt := rand.Intn(maxInt-minInt+1) + minInt
55 | randomPath := "/" + strconv.Itoa(randomInt) + ".html"
56 |
57 | headersNoUA := make(map[string]string, 5)
58 | for key, value := range defaultHeaders {
59 | if key == "User-Agent" {
60 | continue
61 | }
62 | headersNoUA[key] = value
63 | }
64 |
65 | var normal = RequestOpts{
66 | Method: "GET",
67 | Target: target,
68 | Path: "/",
69 | Headers: defaultHeaders,
70 | }
71 |
72 | var noUserAgent = RequestOpts{
73 | Method: "GET",
74 | Target: target,
75 | Path: "/",
76 | Headers: headersNoUA,
77 | }
78 |
79 | var nonExistent = RequestOpts{
80 | Method: "GET",
81 | Target: target,
82 | Path: randomPath,
83 | Headers: defaultHeaders,
84 | }
85 | var xssAttack = RequestOpts{
86 | Method: "GET",
87 | Target: target,
88 | Path: "/",
89 | Params: map[string]string{"p": xssString},
90 | Headers: defaultHeaders,
91 | }
92 | var xxeAttack = RequestOpts{
93 | Method: "GET",
94 | Target: target,
95 | Path: "/",
96 | Params: map[string]string{"p": xxeString},
97 | Headers: defaultHeaders,
98 | }
99 | var sqliAttack = RequestOpts{
100 | Method: "GET",
101 | Target: target,
102 | Path: "/",
103 | Params: map[string]string{"p": sqliString},
104 | Headers: defaultHeaders,
105 | }
106 | var centralAttack = RequestOpts{
107 | Method: "GET",
108 | Target: target,
109 | Path: "/",
110 | Params: map[string]string{
111 | "l": lfiString,
112 | "d": xssString,
113 | "v": sqliString,
114 | },
115 | Headers: defaultHeaders,
116 | }
117 | var lfiAttack = RequestOpts{
118 | Method: "GET",
119 | Target: target,
120 | Path: "/",
121 | Headers: defaultHeaders,
122 | Params: map[string]string{"p": lfiString},
123 | }
124 | var rceAttack = RequestOpts{
125 | Method: "GET",
126 | Target: target,
127 | Path: "/",
128 | Params: map[string]string{"p": rceString},
129 | Headers: defaultHeaders,
130 | }
131 |
132 | return RequestTypes{
133 | Normal: normal,
134 | NoUserAgent: noUserAgent,
135 | NonExistent: nonExistent,
136 | XssAttack: xssAttack,
137 | XxeAttack: xxeAttack,
138 | LfiAttack: lfiAttack,
139 | CentralAttack: centralAttack,
140 | SqliAttack: sqliAttack,
141 | RceAttack: rceAttack,
142 | }
143 | }
144 |
145 | func (t RequestTypes) GetByType(requestType string) (*RequestOpts, error) {
146 | reqOpts := &RequestOpts{}
147 |
148 | s := reflect.ValueOf(&t).Elem()
149 | typeField := s.FieldByName(requestType).Addr()
150 |
151 | rv := reflect.ValueOf(&reqOpts).Elem()
152 | rv.Set(typeField)
153 |
154 | reqOpts.Type = requestType
155 |
156 | return reqOpts, nil
157 | }
158 |
159 | func getResponseByType(responses *[]RequestResponse, requestType string) *RequestResponse {
160 | for _, request := range *responses {
161 | if request.Type == requestType {
162 | return &request
163 | }
164 | }
165 | return &RequestResponse{}
166 | }
167 |
168 | func sendBasicRequests(target string) []RequestResponse {
169 | var wg sync.WaitGroup
170 |
171 | client := NewHTTPClient()
172 |
173 | basicRequestsLen := len(basicRequestsTypes)
174 | responses := make([]RequestResponse, basicRequestsLen)
175 | wg.Add(basicRequestsLen)
176 |
177 | for i, requestType := range basicRequestsTypes {
178 | if i != 0 {
179 | time.Sleep(requestsDelay)
180 | }
181 | go func(i int, requestType string) {
182 | defer wg.Done()
183 | resp := sendRequest(target, requestType, client)
184 | if requestType == "Normal" && resp.Data == nil {
185 | errText := target + " does not seem to be alive"
186 | err := errors.New(errText)
187 | resp.Error = err
188 | }
189 | responses[i] = resp
190 | }(i, requestType)
191 | }
192 |
193 | wg.Wait()
194 | return responses
195 | }
196 |
197 | func sendAllTypesRequests(target string) []RequestResponse {
198 | var responses []RequestResponse
199 |
200 | client := NewHTTPClient()
201 | typeOpts := newTypeOptions(target)
202 |
203 | val := reflect.ValueOf(&typeOpts).Elem()
204 |
205 | for i := 0; i < val.NumField(); i++ {
206 | typeName := val.Type().Field(i).Name
207 | resp := sendRequest(target, typeName, client)
208 | if typeName == "Normal" && resp.Data == nil {
209 | errText := target + " does not seem to be alive"
210 | err := errors.New(errText)
211 | resp.Error = err
212 | responses = []RequestResponse{resp}
213 | break
214 | }
215 | responses = append(responses, resp)
216 | }
217 |
218 | return responses
219 | }
220 |
221 | func sendRequest(target string, requestType string, client http.Client) RequestResponse {
222 | typeOpts := newTypeOptions(target)
223 | requestOpts, err := typeOpts.GetByType(requestType)
224 | if err != nil {
225 | return RequestResponse{Error: err}
226 | }
227 | httpRequest := NewHTTPRequest(*requestOpts, client)
228 |
229 | resp, err := httpRequest.Send()
230 | if err != nil {
231 | return RequestResponse{Error: err}
232 | }
233 | resp.Type = requestType
234 | return resp
235 | }
236 |
237 | // ConcurrentSendAllTypesRequests TODO may be implemented, very fast, very intrusive
238 | func concurrentSendAllTypesRequests(target string) []RequestResponse {
239 | var responses []RequestResponse
240 | var wg sync.WaitGroup
241 |
242 | client := NewHTTPClient()
243 | typeOpts := newTypeOptions(target)
244 |
245 | val := reflect.ValueOf(&typeOpts).Elem()
246 |
247 | for i := 0; i < val.NumField(); i++ {
248 | wg.Add(1)
249 | go func(val reflect.Value, i int) {
250 | defer wg.Done()
251 | typeName := val.Type().Field(i).Name
252 | requestOpts, err := typeOpts.GetByType(typeName)
253 | if err != nil {
254 | return
255 | }
256 | httpRequest := NewHTTPRequest(*requestOpts, client)
257 |
258 | req, err := httpRequest.Send()
259 | if err != nil {
260 | return
261 | }
262 | req.Type = typeName
263 |
264 | responses = append(responses, req)
265 | }(val, i)
266 | }
267 | wg.Wait()
268 |
269 | return responses
270 | }
271 |
--------------------------------------------------------------------------------
/pkg/wafme0w/runner.go:
--------------------------------------------------------------------------------
1 | package wafme0w
2 |
3 | import (
4 | "bufio"
5 | "context"
6 | "encoding/json"
7 | "errors"
8 | "fmt"
9 | httputil "github.com/Lu1sDV/wafme0w/pkg/utils/http"
10 | strutils "github.com/Lu1sDV/wafme0w/pkg/utils/strings"
11 | "github.com/logrusorgru/aurora/v4"
12 | "io"
13 | "os"
14 | "path/filepath"
15 | "strings"
16 | "sync"
17 | )
18 |
19 | type Runner struct {
20 | Options *Options
21 | Wafs []WAF
22 | Aurora *aurora.Aurora
23 | }
24 |
25 | func NewRunner(options *Options) *Runner {
26 | return &Runner{Options: options, Aurora: aurora.New(aurora.WithColors(false))}
27 | }
28 |
29 | type Result struct {
30 | Target string
31 | FingerPrint []FingerPrintDetection
32 | Generic GenericDetection
33 | Errors []error
34 | }
35 |
36 | func (r *Runner) Scan() ([]Result, error) {
37 | var results []Result
38 |
39 | if r.Options.InputFile == "" && r.Options.Target == "" && r.Options.Inputs == nil {
40 | return results, errors.New("no target provided")
41 | }
42 |
43 | if r.Options.HeadersFile != "" {
44 | var headers []string
45 | headersFileName := r.Options.HeadersFile
46 |
47 | headersFile, err := os.Open(headersFileName)
48 | if err != nil {
49 | return []Result{}, err
50 | }
51 |
52 | scanner := bufio.NewScanner(headersFile)
53 | for scanner.Scan() {
54 | headers = append(headers, scanner.Text())
55 | }
56 | r.Options.Headers = headers
57 | }
58 |
59 | if err := r.getWAFsFromFingerPrints(); err != nil {
60 | return []Result{}, err
61 | }
62 |
63 | if r.Options.Concurrency > 1 {
64 | //concurrent
65 | ctx, cancel := context.WithCancel(context.Background())
66 | defer cancel()
67 |
68 | urls := urlStream(ctx, r.Options.Inputs)
69 |
70 | workers := make([]<-chan Result, r.Options.Concurrency)
71 | for i := 0; i < r.Options.Concurrency; i++ {
72 | workers[i] = concurrentScan(ctx, urls, i, &r.Wafs, r.Options)
73 | }
74 |
75 | for result := range mergeResults(ctx, workers...) {
76 | if !r.Options.Silent {
77 | r.outputResult(result)
78 | }
79 | results = append(results, result)
80 | }
81 | } else {
82 | //non concurrent
83 | scanner := bufio.NewScanner(r.Options.Inputs)
84 | for scanner.Scan() {
85 | target := scanner.Text()
86 | result := sequentialFingerPrint(target, r.Wafs, r.Options.FastMode, !r.Options.ExcludeGeneric)
87 | if !r.Options.Silent {
88 | r.outputResult(result)
89 | }
90 | results = append(results, result)
91 | }
92 | }
93 |
94 | //Eventually, write results to output
95 | if r.Options.OutputFile != "" && len(results) > 0 {
96 | var output []byte
97 | fileExt := strings.ToLower(filepath.Ext(r.Options.OutputFile))
98 |
99 | if fileExt == ".json" {
100 | var err error
101 | output, err = prepareJSONOutput(results)
102 | if err != nil {
103 | return []Result{}, err
104 | }
105 | } else {
106 | output = prepareTXTOutput(results)
107 | }
108 | if len(output) != 0 {
109 | err := os.WriteFile(r.Options.OutputFile, output, 0644)
110 | if err != nil {
111 | return []Result{}, err
112 | }
113 | }
114 | }
115 | return results, nil
116 | }
117 |
118 | func (r *Runner) getWAFsFromFingerPrints() error {
119 | var wafs []WAF
120 |
121 | if r.Options.FingerPrints == nil {
122 | return errors.New("no JSON-formatted fingerprints provided")
123 | }
124 |
125 | byt, err := io.ReadAll(r.Options.FingerPrints)
126 | if err != nil {
127 | return err
128 | }
129 | if err := json.Unmarshal(byt, &wafs); err != nil {
130 | return err
131 | }
132 | r.Wafs = wafs
133 | return nil
134 | }
135 |
136 | // GetAllWAFs gets all wafs and returns a map waf=>manufacturer
137 | func (r *Runner) GetAllWAFs() (map[string]string, error) {
138 |
139 | r.getWAFsFromFingerPrints()
140 | result := make(map[string]string, len(r.Wafs))
141 |
142 | for _, waf := range r.Wafs {
143 | wafName := strings.Split(waf.Name, " (")[0]
144 | manufacturer := strutils.SubStringBetweenDelimiters(waf.Name, "(", ")")
145 | result[wafName] = manufacturer
146 | }
147 | return result, nil
148 | }
149 |
150 | func (r *Runner) outputResult(result Result) {
151 | if !r.Options.SuppressWarnings {
152 | if len(result.Errors) > 0 {
153 | for _, err := range result.Errors {
154 | PrintWarning(err.Error(), r.Aurora)
155 | }
156 | }
157 | }
158 | printResult(result, r.Aurora)
159 | }
160 |
161 | func sequentialFingerPrint(target string, wafs []WAF, fastMode bool, withGeneric bool) Result {
162 |
163 | var fingErrors []error
164 | var responses []RequestResponse
165 | var generic = GenericDetection{}
166 |
167 | if !httputil.IsValidHTTPURL(target) {
168 | err := fmt.Errorf("invalid url: %v", target)
169 | fingErrors = append(fingErrors, err)
170 | return Result{Target: target, Errors: fingErrors}
171 | }
172 |
173 | parsedUrl, _ := httputil.ParseURI(target)
174 | urlNoPath := parsedUrl.Scheme + "://" + parsedUrl.Host
175 |
176 | if fastMode {
177 | responses = sendBasicRequests(parsedUrl.String())
178 | } else {
179 | responses = sendAllTypesRequests(parsedUrl.String())
180 | }
181 |
182 | for _, resp := range responses {
183 | if resp.Error != nil {
184 | fingErrors = append(fingErrors, resp.Error)
185 | }
186 | }
187 | identify := NewIdentifier(responses, wafs)
188 | results := identify.DoAll()
189 |
190 | if withGeneric && len(results) == 0 {
191 | generic = identify.GenericDetect()
192 | }
193 |
194 | return Result{Target: urlNoPath, FingerPrint: results, Generic: generic, Errors: fingErrors}
195 | }
196 |
197 | // read urls from buffered file and send them to channel
198 | func urlStream(ctx context.Context, reader io.Reader) <-chan string {
199 |
200 | scanner := bufio.NewScanner(reader)
201 | stream := make(chan string)
202 | go func() {
203 | for scanner.Scan() {
204 | uri := scanner.Text()
205 | select {
206 | case <-ctx.Done():
207 | return
208 | case stream <- uri:
209 | }
210 | }
211 | close(stream)
212 | }()
213 | return stream
214 | }
215 |
216 | func concurrentScan(ctx context.Context, urls <-chan string, workerID int, wafs *[]WAF, options *Options) <-chan Result {
217 |
218 | results := make(chan Result)
219 | go func() {
220 | for url := range urls {
221 | result := sequentialFingerPrint(url, *wafs, options.FastMode, !options.ExcludeGeneric)
222 | select {
223 | case <-ctx.Done():
224 | return
225 | case results <- result:
226 | }
227 | }
228 | close(results)
229 | }()
230 | return results
231 | }
232 |
233 | func mergeResults(ctx context.Context, channels ...<-chan Result) <-chan Result {
234 | var wg sync.WaitGroup
235 |
236 | wg.Add(len(channels))
237 | outgoingResults := make(chan Result)
238 | multiplex := func(c <-chan Result) {
239 | defer wg.Done()
240 | for i := range c {
241 | select {
242 | case <-ctx.Done():
243 | return
244 | case outgoingResults <- i:
245 | }
246 | }
247 | }
248 | for _, c := range channels {
249 | go multiplex(c)
250 | }
251 | go func() {
252 | wg.Wait()
253 | close(outgoingResults)
254 | }()
255 | return outgoingResults
256 | }
257 |
--------------------------------------------------------------------------------