From 8ef7903eacb6c3a05a182e8a24777c93c162cf35 Mon Sep 17 00:00:00 2001 From: Lucky-Pulse Date: Mon, 8 Apr 2024 12:10:06 +1200 Subject: [PATCH 1/3] This is a new template to hunt for webpack source maps. --- headless/webpack-sourcemap-hunter | 213 ++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 headless/webpack-sourcemap-hunter diff --git a/headless/webpack-sourcemap-hunter b/headless/webpack-sourcemap-hunter new file mode 100644 index 0000000000..3ef43a2acd --- /dev/null +++ b/headless/webpack-sourcemap-hunter @@ -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 From 6c34afd5b0b661080d30633a6966a9888968d439 Mon Sep 17 00:00:00 2001 From: Prince Chaddha Date: Sun, 2 Jun 2024 20:11:40 +0400 Subject: [PATCH 2/3] minor changes --- headless/webpack-sourcemap-hunter | 41 ++++++++++++++++++------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/headless/webpack-sourcemap-hunter b/headless/webpack-sourcemap-hunter index 3ef43a2acd..622ed9e967 100644 --- a/headless/webpack-sourcemap-hunter +++ b/headless/webpack-sourcemap-hunter @@ -1,37 +1,41 @@ -id: Webpack-Sourcemap +id: webpack-sourcemap + info: - name: Webpack-Sourcemap - author: lucky0x0d, PulseSecurity.co.nz + name: Webpack Sourcemap + author: lucky0x0d,PulseSecurity.co.nz + severity: low + description: | + Detects if Webpack source maps are exposed. + impact: | + Exposure of source maps can leak sensitive information about the application's source code and potentially aid attackers in identifying vulnerabilities. + remediation: | + Ensure that Webpack source maps are not exposed to the public by configuring the server to restrict access to them. 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])]; - } + () => { + 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 @@ -40,7 +44,6 @@ headless: part: extract regex: - (?i)http(.[~a-zA-Z0-9.\/\-_:]+) - flow: | headless(); http("check_base_srcmap_inline"); @@ -148,6 +151,7 @@ http: - '"version":' - '"mappings":' - '"sources":' + - type: status status: - 200 @@ -168,6 +172,7 @@ http: - '"version":' - '"mappings":' - '"sources":' + - type: status status: - 200 @@ -188,6 +193,7 @@ http: - '"version":' - '"mappings":' - '"sources":' + - type: status status: - 200 @@ -208,6 +214,7 @@ http: - '"version":' - '"mappings":' - '"sources":' + - type: status status: - 200 From 8ff3fbc3cb7a3a3972bea39a27fd0f135b106a5d Mon Sep 17 00:00:00 2001 From: Prince Chaddha Date: Sun, 2 Jun 2024 20:25:15 +0400 Subject: [PATCH 3/3] Rename webpack-sourcemap-hunter to webpack-sourcemap.yaml --- headless/{webpack-sourcemap-hunter => webpack-sourcemap.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename headless/{webpack-sourcemap-hunter => webpack-sourcemap.yaml} (100%) diff --git a/headless/webpack-sourcemap-hunter b/headless/webpack-sourcemap.yaml similarity index 100% rename from headless/webpack-sourcemap-hunter rename to headless/webpack-sourcemap.yaml