This is a new template to hunt for webpack source maps.
parent
33207e6b48
commit
8ef7903eac
|
@ -0,0 +1,213 @@
|
|||
id: Webpack-Sourcemap
|
||||
info:
|
||||
name: Webpack-Sourcemap
|
||||
author: lucky0x0d, PulseSecurity.co.nz
|
||||
reference:
|
||||
- https://pulsesecurity.co.nz/articles/javascript-from-sourcemaps
|
||||
- https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/01-Information_Gathering/05-Review_Web_Page_Content_for_Information_Leakage
|
||||
severity: low
|
||||
tags: javascript,webpack,sourcemaps
|
||||
classification:
|
||||
cwe-id: CWE-200
|
||||
description: parses target to find scripts and then checks for a sourcemapconsumer, inline sourcemaps, if js files have map files, if sourcemap headers exists
|
||||
metadata:
|
||||
max-request: 1
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- args:
|
||||
url: "{{BaseURL}}"
|
||||
action: navigate
|
||||
- action: sleep
|
||||
args:
|
||||
duration: 10
|
||||
- action: script
|
||||
name: extract
|
||||
args:
|
||||
code: |
|
||||
() => {
|
||||
AAA = [];
|
||||
window.performance.getEntriesByType("resource").forEach((element) => { if (element.initiatorType === 'script' || element.initiatorType === 'fetch'|| element.initiatorType === 'xmlhttprequest') {AAA.push(element.name)}});
|
||||
BBB = [...new Set(Array.from(document.querySelectorAll('script')).map(i => i.src))]
|
||||
CCC = [...new Set(Array.from(document.querySelectorAll('link[as=script]')).map(i => i.href))]
|
||||
return [...new Set([...AAA, ...BBB, ...CCC])];
|
||||
}
|
||||
|
||||
extractors:
|
||||
- type: regex
|
||||
name: allscripts
|
||||
internal: true
|
||||
part: extract
|
||||
regex:
|
||||
- (?i)http(.[~a-zA-Z0-9.\/\-_:]+)
|
||||
|
||||
flow: |
|
||||
headless();
|
||||
http("check_base_srcmap_inline");
|
||||
for (let scripturi of iterate(template["allscripts"])) {
|
||||
set ("scripturi", scripturi);
|
||||
http("check_for_srcmap_header");
|
||||
http("check_for_srcmap_inline");
|
||||
http("check_for_srcmap_url");
|
||||
for (let mapuri of iterate(template["allmaps"])) {
|
||||
set ("mapuri", mapuri);
|
||||
http("fetch_absolute_srcmap");
|
||||
http("fetch_relative_srcmap");
|
||||
http("fetch_root_relative_srcmap");
|
||||
http("fetch_noscheme_srcmaps");
|
||||
};
|
||||
set ("allmaps", null);
|
||||
};
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
id: check_base_srcmap_inline
|
||||
disable-cookie: true
|
||||
redirects: true
|
||||
path:
|
||||
- '{{BaseURL}}'
|
||||
|
||||
matchers:
|
||||
- type: regex
|
||||
name: Inline_SourceMap
|
||||
regex:
|
||||
- '(?i)sourceMappingURL=.*eyJ2ZXJzaW9uIjo'
|
||||
|
||||
- type: regex
|
||||
name: SourceMapConsumer_Present
|
||||
regex:
|
||||
- '(?i)SourceMapConsumer'
|
||||
|
||||
- method: GET
|
||||
id: check_for_srcmap_url
|
||||
disable-cookie: true
|
||||
redirects: true
|
||||
path:
|
||||
- '{{scripturi}}'
|
||||
|
||||
extractors:
|
||||
- type: regex
|
||||
name: allmaps
|
||||
internal: true
|
||||
group: 1
|
||||
regex:
|
||||
- (?i)\/\/#\ssourceMappingURL=(.[~a-zA-Z0-9.\/\-_:]+)
|
||||
|
||||
- method: GET
|
||||
id: check_for_srcmap_inline
|
||||
disable-cookie: true
|
||||
redirects: true
|
||||
path:
|
||||
- '{{scripturi}}'
|
||||
|
||||
matchers:
|
||||
- type: regex
|
||||
name: Inline_SourceMap
|
||||
regex:
|
||||
- '(?i)sourceMappingURL=.*eyJ2ZXJzaW9uIjo'
|
||||
|
||||
- type: regex
|
||||
name: SourceMapConsumer_Present
|
||||
regex:
|
||||
- '(?i)SourceMapConsumer'
|
||||
|
||||
- method: GET
|
||||
id: check_for_srcmap_header
|
||||
disable-cookie: true
|
||||
redirects: true
|
||||
path:
|
||||
- '{{scripturi}}'
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
name: Source_Map_Header
|
||||
dsl:
|
||||
- "regex('(?i)SourceMap', header)"
|
||||
- "status_code != 301 && status_code != 302"
|
||||
condition: and
|
||||
|
||||
extractors:
|
||||
- type: kval
|
||||
kval:
|
||||
- X_SourceMap
|
||||
- SourceMap
|
||||
|
||||
- method: GET
|
||||
id: fetch_absolute_srcmap
|
||||
disable-cookie: true
|
||||
redirects: true
|
||||
path:
|
||||
- '{{mapuri}}'
|
||||
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
condition: and
|
||||
part: body
|
||||
words:
|
||||
- '"version":'
|
||||
- '"mappings":'
|
||||
- '"sources":'
|
||||
- type: status
|
||||
status:
|
||||
- 200
|
||||
|
||||
- method: GET
|
||||
id: fetch_relative_srcmap
|
||||
disable-cookie: true
|
||||
redirects: true
|
||||
path:
|
||||
- '{{replace_regex(scripturi,"([^/]+$)","")}}{{replace_regex(mapuri,"(^\/+)","")}}'
|
||||
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
condition: and
|
||||
part: body
|
||||
words:
|
||||
- '"version":'
|
||||
- '"mappings":'
|
||||
- '"sources":'
|
||||
- type: status
|
||||
status:
|
||||
- 200
|
||||
|
||||
- method: GET
|
||||
id: fetch_root_relative_srcmap
|
||||
disable-cookie: true
|
||||
redirects: true
|
||||
path:
|
||||
- '{{replace_regex(scripturi,replace_regex(scripturi,"http.+//[^/]+",""),"")}}{{mapuri}}'
|
||||
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
condition: and
|
||||
part: body
|
||||
words:
|
||||
- '"version":'
|
||||
- '"mappings":'
|
||||
- '"sources":'
|
||||
- type: status
|
||||
status:
|
||||
- 200
|
||||
|
||||
- method: GET
|
||||
id: fetch_noscheme_srcmaps
|
||||
disable-cookie: true
|
||||
redirects: true
|
||||
path:
|
||||
- '{{Scheme}}{{mapuri}}'
|
||||
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
condition: and
|
||||
part: body
|
||||
words:
|
||||
- '"version":'
|
||||
- '"mappings":'
|
||||
- '"sources":'
|
||||
- type: status
|
||||
status:
|
||||
- 200
|
Loading…
Reference in New Issue