mirror of
https://github.com/trufflesecurity/xsshunter
synced 2024-11-10 06:44:13 +00:00
Merge branch 'main' into cors-check
This commit is contained in:
commit
46a861ed9c
35 changed files with 20301 additions and 13372 deletions
58
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
58
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ""
|
||||
labels: bug, needs triage
|
||||
assignees: trufflesecurity/skunkworks
|
||||
---
|
||||
|
||||
### Community Note
|
||||
|
||||
* Please vote on this issue by adding a 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to the original issue to help the community and maintainers prioritize this request
|
||||
* Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
|
||||
* If you are interested in working on this issue or have submitted a pull request, please leave a comment
|
||||
|
||||
### TruffleHog Version
|
||||
<!--- Please run `trufflehog --version` to show the version. If you are not running the latest version, please upgrade because your issue may have already been fixed. --->
|
||||
|
||||
### Trace Output
|
||||
|
||||
<!---
|
||||
Please provide a link to a GitHub Gist containing the complete debug output. Please do NOT paste the debug output in the issue; just paste a link to the Gist.
|
||||
|
||||
To obtain the trace output, run trufflehog with the --trace flag.
|
||||
--->
|
||||
|
||||
### Expected Behavior
|
||||
|
||||
<!--- What should have happened? --->
|
||||
|
||||
### Actual Behavior
|
||||
|
||||
<!--- What actually happened? --->
|
||||
|
||||
### Steps to Reproduce
|
||||
|
||||
<!--- Please list the steps required to reproduce the issue. --->
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
## Environment
|
||||
* OS: [e.g. iOS]
|
||||
* Version [e.g. 22]
|
||||
|
||||
## Additional Context
|
||||
<!--- Add any other context about the problem here. --->
|
||||
|
||||
### References
|
||||
|
||||
<!---
|
||||
Information about referencing Github Issues: https://help.github.com/articles/basic-writing-and-formatting-syntax/#referencing-issues-and-pull-requests
|
||||
|
||||
Are there any other GitHub issues (open or closed) or pull requests that should be linked here? Vendor documentation? For example:
|
||||
--->
|
||||
|
||||
* #0000
|
||||
|
38
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ""
|
||||
labels: enhancement, needs triage
|
||||
assignees: trufflesecurity/skunkworks
|
||||
---
|
||||
|
||||
### Community Note
|
||||
|
||||
* Please vote on this issue by adding a 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to the original issue to help the community and maintainers prioritize this request
|
||||
* Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
|
||||
* If you are interested in working on this issue or have submitted a pull request, please leave a comment
|
||||
|
||||
### Description
|
||||
|
||||
<!--- Please leave a helpful description of the feature request here. --->
|
||||
|
||||
## Problem to be Addressed
|
||||
<!--- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] --->
|
||||
|
||||
## Description of the Preferred Solution
|
||||
<!--- A clear and concise description of what you want to happen. What
|
||||
information may be required and what would be the preferred way to provide it?
|
||||
What should the output include? --->
|
||||
|
||||
## Additional Context
|
||||
<!--- Add any other context or screenshots about the feature request here. --->
|
||||
|
||||
### References
|
||||
|
||||
<!---
|
||||
Information about referencing Github Issues: https://help.github.com/articles/basic-writing-and-formatting-syntax/#referencing-issues-and-pull-requests
|
||||
|
||||
Are there any other GitHub issues (open or closed) or pull requests that should be linked here? Vendor blog posts or documentation? For example:
|
||||
--->
|
||||
|
||||
* #0000
|
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
<!--
|
||||
Please create an issue to collect feedback prior to feature additions. Please also reference that issue in any PRs.
|
||||
If possible try to keep PRs scoped to one feature, and add tests for new features.
|
||||
-->
|
16
.github/dependabot.yml
vendored
Normal file
16
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
# Check for updates to GitHub Actions every weekday
|
||||
interval: "weekly"
|
70
.github/workflows/codeql-analysis.yml
vendored
Normal file
70
.github/workflows/codeql-analysis.yml
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '35 11 * * 2'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
29
.github/workflows/secrets.yml
vendored
Normal file
29
.github/workflows/secrets.yml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
|
||||
name: Scan for secrets
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18'
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.head_ref }}
|
||||
- name: TruffleHog
|
||||
uses: ./
|
||||
with:
|
||||
path: ./
|
||||
base: ${{ github.event.repository.default_branch }}
|
||||
head: HEAD
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,5 +1,5 @@
|
|||
*.env
|
||||
node_modules/*
|
||||
node_modules
|
||||
*.bak
|
||||
postgres-db-data/*
|
||||
dev.sh
|
||||
|
@ -12,3 +12,4 @@ ssldata/*
|
|||
config.env
|
||||
payload-fire-images/*.gz
|
||||
payload-fire-images/*.png
|
||||
deploy.sh
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
FROM node:12
|
||||
FROM node:16
|
||||
|
||||
# Set up directory for the server
|
||||
RUN mkdir /app/
|
||||
WORKDIR /app/
|
||||
|
||||
# Copy front-end over
|
||||
COPY front-end/ /app/front-end/
|
||||
WORKDIR /app/front-end/
|
||||
RUN npm install
|
||||
|
@ -27,9 +25,7 @@ COPY docker-entrypoint.sh /app/
|
|||
RUN chmod +x /app/docker-entrypoint.sh
|
||||
COPY templates /app/templates
|
||||
|
||||
# Expose both HTTP and HTTPS ports
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
USER 1111
|
||||
|
||||
# Start the server
|
||||
ENTRYPOINT ["/app/docker-entrypoint.sh"]
|
||||
|
|
8
api.js
8
api.js
|
@ -5,7 +5,7 @@ const cors = require('cors');
|
|||
const path = require('path');
|
||||
const uuid = require('uuid');
|
||||
const asyncfs = require('fs').promises;
|
||||
const sessions = require('@nvanexan/node-client-sessions');
|
||||
const sessions = require('@truffledustin/node-client-sessions');
|
||||
const favicon = require('serve-favicon');
|
||||
const database = require('./database.js');
|
||||
const Users = database.Users;
|
||||
|
@ -24,7 +24,7 @@ const {OAuth2Client} = require('google-auth-library');
|
|||
|
||||
|
||||
const SCREENSHOTS_DIR = path.resolve(process.env.SCREENSHOTS_DIR);
|
||||
const client = new OAuth2Client(process.env.CLIENT_ID, process.env.CLIENT_SECRET, `https://${process.env.HOSTNAME}/oauth-login`);
|
||||
const client = new OAuth2Client(process.env.CLIENT_ID, process.env.CLIENT_SECRET, process.env.NODE_ENV == 'production' ? `https://${process.env.HOSTNAME}/oauth-login` : `http://${process.env.HOSTNAME}/oauth-login`);
|
||||
const SCREENSHOT_FILENAME_REGEX = new RegExp(/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}\.png$/i);
|
||||
|
||||
|
||||
|
@ -35,7 +35,7 @@ var sessions_settings_object = {
|
|||
activeDuration: 1000 * 60 * 5, // Extend for five minutes if actively used
|
||||
cookie: {
|
||||
httpOnly: true,
|
||||
secure: true
|
||||
secureProxy: process.env.NODE_ENV == 'production'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ async function set_up_api_server(app) {
|
|||
|
||||
app.get('/login', (req, res) => {
|
||||
const authUrl = client.generateAuthUrl({
|
||||
redirect_uri: `https://${process.env.HOSTNAME}/oauth-login`,
|
||||
redirect_uri: process.env.NODE_ENV == 'production' ? `https://${process.env.HOSTNAME}/oauth-login` : `http://${process.env.HOSTNAME}/oauth-login`,
|
||||
access_type: 'offline',
|
||||
scope: ['email', 'profile'],
|
||||
prompt: 'select_account'
|
||||
|
|
4
app.js
4
app.js
|
@ -51,6 +51,8 @@ const SCREENSHOT_FILENAME_REGEX = new RegExp(/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]
|
|||
|
||||
async function get_app_server() {
|
||||
const app = express();
|
||||
app.set('trust proxy', true);
|
||||
app.disable('x-powered-by');
|
||||
|
||||
// I have a question for Express:
|
||||
// https://youtu.be/ZtjFsQBuJWw?t=4
|
||||
|
@ -262,7 +264,7 @@ async function get_app_server() {
|
|||
id: payload_fire_id,
|
||||
user_id: userID,
|
||||
url: req.body.uri,
|
||||
ip_address: req.connection.remoteAddress.toString(),
|
||||
ip_address: req.ip,
|
||||
referer: req.body.referrer,
|
||||
user_agent: req.body['user-agent'],
|
||||
cookies: req.body.cookies,
|
||||
|
|
40
database.js
40
database.js
|
@ -13,7 +13,10 @@ const sequelize = new Sequelize(
|
|||
host: process.env.DATABASE_HOST,
|
||||
dialect: 'postgres',
|
||||
benchmark: true,
|
||||
logging: true
|
||||
logging: false,
|
||||
dialectOptions: {
|
||||
socketPath: process.env.NODE_ENV == 'production' ? process.env.DATABASE_HOST : null,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -374,36 +377,6 @@ InjectionRequests.init({
|
|||
]
|
||||
});
|
||||
|
||||
|
||||
function get_banner() {
|
||||
return `
|
||||
============================================================================
|
||||
█████╗ ████████╗████████╗███████╗███╗ ██╗████████╗██╗ ██████╗ ███╗ ██╗
|
||||
██╔══██╗╚══██╔══╝╚══██╔══╝██╔════╝████╗ ██║╚══██╔══╝██║██╔═══██╗████╗ ██║
|
||||
███████║ ██║ ██║ █████╗ ██╔██╗ ██║ ██║ ██║██║ ██║██╔██╗ ██║
|
||||
██╔══██║ ██║ ██║ ██╔══╝ ██║╚██╗██║ ██║ ██║██║ ██║██║╚██╗██║
|
||||
██║ ██║ ██║ ██║ ███████╗██║ ╚████║ ██║ ██║╚██████╔╝██║ ╚████║
|
||||
╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
|
||||
|
||||
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
Hi. I love you.
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
█████╗ ████████╗████████╗███████╗███╗ ██╗████████╗██╗ ██████╗ ███╗ ██╗
|
||||
██╔══██╗╚══██╔══╝╚══██╔══╝██╔════╝████╗ ██║╚══██╔══╝██║██╔═══██╗████╗ ██║
|
||||
███████║ ██║ ██║ █████╗ ██╔██╗ ██║ ██║ ██║██║ ██║██╔██╗ ██║
|
||||
██╔══██║ ██║ ██║ ██╔══╝ ██║╚██╗██║ ██║ ██║██║ ██║██║╚██╗██║
|
||||
██║ ██║ ██║ ██║ ███████╗██║ ╚████║ ██║ ██║╚██████╔╝██║ ╚████║
|
||||
╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
|
||||
|
||||
============================================================================
|
||||
`;
|
||||
}
|
||||
|
||||
async function print_banner() {
|
||||
console.log(get_banner());
|
||||
}
|
||||
|
||||
|
||||
async function database_init() {
|
||||
const force = false;
|
||||
|
||||
|
@ -415,11 +388,6 @@ async function database_init() {
|
|||
CollectedPages.sync({ force: force }),
|
||||
InjectionRequests.sync({ force: force }),
|
||||
]);
|
||||
|
||||
await Promise.all([
|
||||
// Set up admin panel user if not already set up.
|
||||
print_banner(),
|
||||
]);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -3,86 +3,28 @@ services:
|
|||
# XSS Hunter Express service
|
||||
xsshunterexpress:
|
||||
build: .
|
||||
environment:
|
||||
# [REQUIRED] The hostname/domain pointed to
|
||||
# the IP of the server running this service.
|
||||
# SSL will automatically be set up and
|
||||
# renewed with LetsEncrypt.
|
||||
- HOSTNAME=your.host.name
|
||||
# THis hostname is where your JS is served out of
|
||||
- XSS_HOSTNAME=your.xss.domain
|
||||
# [REQUIRED] Email for SSL
|
||||
- SSL_CONTACT_EMAIL=YourEmail@gmail.com
|
||||
# Maximum XSS callback payload size
|
||||
# This includes the webpage screenshot, DOM HTML,
|
||||
# page text, and other metadata. Note that if the
|
||||
# payload is above this limit, you won't be notified
|
||||
# of the XSS firing.
|
||||
- MAX_PAYLOAD_UPLOAD_SIZE_MB=50
|
||||
# Whether or not to enable the web control panel
|
||||
# Set to "false" or remove to disable the web UI.
|
||||
# Useful for minimizing attack surface.
|
||||
- CONTROL_PANEL_ENABLED=true
|
||||
# Whether or not to enable email notifications via
|
||||
# SMTP for XSS payload fires.
|
||||
- SMTP_EMAIL_NOTIFICATIONS_ENABLED=true
|
||||
- SMTP_HOST=smtp.gmail.com
|
||||
- SMTP_PORT=465
|
||||
- SMTP_USE_TLS=true
|
||||
- SMTP_USERNAME=YourEmail@gmail.com
|
||||
- SMTP_PASSWORD=YourEmailPassword
|
||||
- SMTP_FROM_EMAIL=YourEmail@gmail.com
|
||||
- SMTP_RECEIVER_EMAIL=YourEmail@gmail.com
|
||||
# CLIENT ID FOR OAUTH LOGIN
|
||||
- CLIENT_ID=your_client_id
|
||||
- CLIENT_SECRET=your_client_secret
|
||||
# GENERATE A RANDOM LONG STRING FOR THIS
|
||||
- SESSION_SECRET_KEY=
|
||||
# THERE IS NO NEED TO MODIFY BELOW THIS LINE
|
||||
# ------------------------------------------
|
||||
# FEEL FREE, BUT KNOW WHAT YOU'RE DOING.
|
||||
# Where XSS screenshots are stored
|
||||
- SCREENSHOTS_DIR=/app/payload-fire-images
|
||||
- DATABASE_NAME=xsshunterexpress
|
||||
- DATABASE_USER=xsshunterexpress
|
||||
- DATABASE_PASSWORD=xsshunterexpress
|
||||
- DATABASE_HOST=postgresdb
|
||||
- NODE_ENV=production
|
||||
- USE_CLOUD_STORAGE=true
|
||||
- BUCKET_NAME=YourBucket
|
||||
env_file:
|
||||
- dev.env
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "127.0.0.1:8080:8080"
|
||||
volumes:
|
||||
# Stores the SSL/TLS certificates and keys
|
||||
# in the "ssldata" directory.
|
||||
# Your certificates are automatically renewed
|
||||
# via LetsEncrypt, no extra work needed!
|
||||
- ./ssldata:/app/greenlock.d
|
||||
# Directory where payload fire images are stored.
|
||||
- ./payload-fire-images:/app/payload-fire-images
|
||||
# Comment out if you're using an external SQL
|
||||
# server and have commented out the DB section.
|
||||
depends_on:
|
||||
- postgresdb
|
||||
# Postgres server to store injection data (not including
|
||||
# screenshots which are stored separately).
|
||||
# NOTE: If you're using an external SQL server, you can comment
|
||||
# out this service.
|
||||
# WARNING: This database gives the "postgres" user admin priveleges
|
||||
# with a default password of "xsshunterexpress". Do not expose it
|
||||
# externally. If you do, be sure to change the password.
|
||||
postgresdb:
|
||||
condition: service_healthy
|
||||
postgresdb:
|
||||
image: postgres
|
||||
restart: always
|
||||
user: postgres
|
||||
environment:
|
||||
# This is a volume mounted into the container
|
||||
# (see the directory ./postgres-db-data)
|
||||
# So the database will be persisted across
|
||||
# container deletion.
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
POSTGRES_USER: xsshunterexpress
|
||||
POSTGRES_DB: xsshunterexpress
|
||||
POSTGRES_PASSWORD: xsshunterexpress
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready"]
|
||||
interval: 3s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
volumes:
|
||||
- ./postgres-db-data:/var/lib/postgresql/data/pgdata
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
echo "Initializing SSL/TLS..."
|
||||
# Set up Greenlock
|
||||
# Test if --maintainer-email is required, we can set it via environment variables...
|
||||
npx greenlock init --config-dir /app/greenlock.d --maintainer-email $SSL_CONTACT_EMAIL
|
||||
npx greenlock add --subject $HOSTNAME --altnames "$HOSTNAME,$XSS_HOSTNAME"
|
||||
|
||||
echo "Starting server..."
|
||||
node server.js
|
||||
|
|
30483
front-end/package-lock.json
generated
30483
front-end/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -15,7 +15,7 @@
|
|||
"dependencies": {
|
||||
"@deveodk/vue-toastr": "^1.1.0",
|
||||
"chart.js": "^2.9.3",
|
||||
"eslint": "^7.23.0",
|
||||
"eslint": "^7.32.0",
|
||||
"i": "^0.3.6",
|
||||
"moment": "^2.29.1",
|
||||
"npm": "^7.15.0",
|
||||
|
@ -34,13 +34,15 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^4.5.7",
|
||||
"@vue/cli-plugin-eslint": "^4.4.6",
|
||||
"@vue/cli-plugin-eslint": "^5.0.8",
|
||||
"@vue/cli-plugin-pwa": "^4.4.6",
|
||||
"@vue/cli-service": "^4.4.6",
|
||||
"node-sass": "^4.14.1",
|
||||
"sass-loader": "^8.0.2",
|
||||
"cache-loader": "^4.1.0",
|
||||
"sass": "1.56.2",
|
||||
"sass-loader": "10.1.1",
|
||||
"vue-cli-plugin-i18n": "^1.0.1",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpack": "^4.46.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<!-- Login modal if not authenticated -->
|
||||
<modal class="show d-block" body-classes="p-0" modal-classes="modal-dialog-centered modal-sm ]" v-if="show_login_prompt">
|
||||
<card type="secondary" header-classes="bg-white pb-5" body-classes="px-lg-5 py-lg-5" class="border-0 mb-0" style="text-align: center">
|
||||
<h3>XSS Hunter<br />
|
||||
<h3 style="margin-bottom: 0; color: #2e5543;">XSS Hunter<br />
|
||||
<i>Please login to continue.</i></h3>
|
||||
</card>
|
||||
</modal>
|
||||
|
|
|
@ -103,8 +103,7 @@
|
|||
|
||||
// Apply the mixin to the buttons
|
||||
// .btn-default { @include btn-styles($default-color, $default-states-color); }
|
||||
.btn-primary { @include btn-styles($primary, $primary-states);
|
||||
|
||||
.btn-primary { @include btn-styles($default, $default-states);
|
||||
}
|
||||
.btn-success { @include btn-styles($success, $success-states);
|
||||
|
||||
|
|
|
@ -4,11 +4,12 @@
|
|||
position: relative;
|
||||
width: 100%;
|
||||
margin-bottom: 30px;
|
||||
box-shadow: $box-shadow;
|
||||
|
||||
background: #e7e0d8;
|
||||
background: transparent;
|
||||
color: black;
|
||||
|
||||
label{
|
||||
color: rgba($white, 0.6);
|
||||
color: rgba(black, 0.6);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
|
@ -18,6 +19,24 @@
|
|||
.card-body{
|
||||
padding: 15px;
|
||||
|
||||
.card {
|
||||
border: 1px solid #ae8c57;
|
||||
color: black;
|
||||
background: #f4efe9;
|
||||
|
||||
.card-title {
|
||||
color: black;
|
||||
font-weight: 500;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.card-subtitle {
|
||||
margin-top: 0.4rem;
|
||||
color: #5a5a5a !important;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.table-full-width{
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.footer{
|
||||
padding: 24px 0 24px 250px;
|
||||
padding: 24px 0 24px 320px;
|
||||
|
||||
[class*="container-"] {
|
||||
padding: 0;
|
||||
|
|
|
@ -2,15 +2,23 @@
|
|||
@include form-control-placeholder(#6c757c, 1);
|
||||
|
||||
.form-control{
|
||||
border-color: lighten($black,5%);
|
||||
border-radius: $border-radius-lg;
|
||||
font-size: $font-size-sm;
|
||||
font-size: $font-size-base;
|
||||
@include transition-input-focus-color();
|
||||
|
||||
font-family: monospace;
|
||||
border-color: #dfd3b0;
|
||||
color: #5a5a5a;
|
||||
background-color: white;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
&:focus{
|
||||
border-color: $primary;
|
||||
background-color: $input-bg;
|
||||
border-color: #ae8c57;
|
||||
background-color: rgba(white, 0.8);
|
||||
color: #5a5a5a;
|
||||
|
||||
@include box-shadow(none);
|
||||
|
||||
& + .input-group-append .input-group-text,
|
||||
|
|
|
@ -179,7 +179,10 @@ a[data-toggle="collapse"][aria-expanded="true"] .caret,
|
|||
}
|
||||
|
||||
code {
|
||||
color: $pink;
|
||||
color: #5bb381;
|
||||
font-weight: bold;
|
||||
background: #ffffffcc;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 991px){
|
||||
|
|
|
@ -100,6 +100,8 @@
|
|||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-family: $font-family-primary;
|
||||
display: none;
|
||||
position: fixed;
|
||||
padding-top: .3125rem;
|
||||
padding-bottom: .3125rem;
|
||||
|
@ -107,7 +109,18 @@
|
|||
margin-left: 17px;
|
||||
margin-top: 3px;
|
||||
text-transform: uppercase;
|
||||
font-size: $font-paragraph;
|
||||
font-size: $font-size-xl;
|
||||
font-weight: bold;
|
||||
|
||||
small {
|
||||
font-size: $font-paragraph;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 991px){
|
||||
.navbar-brand {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-toggle button:focus, .navbar-toggler{
|
||||
|
|
|
@ -18,9 +18,8 @@
|
|||
}
|
||||
.sidebar,
|
||||
.off-canvas-sidebar{
|
||||
@include linear-gradient($primary-states, $primary);
|
||||
height: calc(100vh - 90px);
|
||||
width: 230px;
|
||||
height: 100vh;
|
||||
width: 280px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -28,10 +27,8 @@
|
|||
background-size: cover;
|
||||
background-position: center center;
|
||||
display: block;
|
||||
box-shadow: 0px 0px 45px 0px rgba(0,0,0,0.6);
|
||||
margin-top: 80px;
|
||||
margin-left: 20px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 0px 20px 0px rgba(0,0,0,0.4);
|
||||
background: #2e5543;
|
||||
|
||||
.sidebar-wrapper{
|
||||
width: $full-width;
|
||||
|
@ -182,22 +179,11 @@
|
|||
}
|
||||
|
||||
&.active > a:not([data-toggle="collapse"]){
|
||||
background: transparent;
|
||||
background: rgba(0, 0, 0, 0.15);
|
||||
|
||||
i,p{
|
||||
color: white;
|
||||
}
|
||||
|
||||
&:before{
|
||||
content: " ";
|
||||
position: absolute;
|
||||
height: 6px;
|
||||
width: 6px;
|
||||
top: 22px;
|
||||
left: -4px;
|
||||
background: $white;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
&.active > a[data-toggle="collapse"]{
|
||||
|
@ -250,6 +236,7 @@
|
|||
display: block;
|
||||
height: auto;
|
||||
white-space: nowrap;
|
||||
font-size: $font-size-base;
|
||||
@extend .animation-transition-general;
|
||||
}
|
||||
|
||||
|
@ -266,6 +253,7 @@
|
|||
}
|
||||
|
||||
.logo{
|
||||
font-size: $font-size-xl;
|
||||
position: relative;
|
||||
padding: $padding-base-vertical $padding-base-horizontal;
|
||||
z-index: 4;
|
||||
|
@ -302,6 +290,7 @@
|
|||
}
|
||||
|
||||
a.logo-normal{
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
opacity: 1;
|
||||
@include transform-translate-x(0px);
|
||||
|
@ -460,7 +449,7 @@
|
|||
width: $full-width;
|
||||
min-height: 100vh;
|
||||
border-top: 2px solid $primary;
|
||||
background: linear-gradient($background-black, $background-states-black);
|
||||
background: none;
|
||||
|
||||
@include transitions (0.50s, cubic-bezier(0.685, 0.0473, 0.346, 1));
|
||||
|
||||
|
@ -481,7 +470,7 @@
|
|||
}
|
||||
|
||||
> .content {
|
||||
padding: 78px 30px 30px 280px;
|
||||
padding: 30px 30px 30px 320px;
|
||||
min-height: calc(100vh - 70px);
|
||||
}
|
||||
|
||||
|
@ -682,6 +671,7 @@
|
|||
width: 100%;
|
||||
.content {
|
||||
padding-left: 30px;
|
||||
padding-top: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -99,28 +99,28 @@ $colors: map-merge((
|
|||
$default-color-opacity: rgba(182, 182, 182, .6) !default;
|
||||
$orange-color: #f96332 !default;
|
||||
|
||||
$default: #344675 !default;
|
||||
$primary: #e14eca !default;
|
||||
$default: #89553d !default;
|
||||
$primary: #2e5543 !default;
|
||||
$secondary: #f4f5f7 !default;
|
||||
$success: #00f2c3 !default;
|
||||
$success: #5bb381 !default;
|
||||
$info: #1d8cf8 !default;
|
||||
$warning: #ff8d72 !default;
|
||||
$danger: #fd5d93 !default;
|
||||
$danger: #c15750 !default;
|
||||
$black: #222a42 !default;
|
||||
$vue: #42b883 !default;
|
||||
|
||||
// gradient
|
||||
$default-states: #263148 !default;
|
||||
$primary-states: #ba54f5 !default;
|
||||
$default-states: #5b3524 !default;
|
||||
$primary-states: #111513 !default;
|
||||
$success-states: #0098f0 !default;
|
||||
$info-states: #3358f4 !default;
|
||||
$warning-states: #ff6491 !default;
|
||||
$danger-states: #ec250d !default;
|
||||
$danger-states: #662019 !default;
|
||||
$black-states: #1d253b !default;
|
||||
$vue-states: #389466 !default;
|
||||
|
||||
$background-black: #1e1e2f !default;
|
||||
$background-states-black: #1e1e24 !default;
|
||||
$background-black: #323232 !default;
|
||||
$background-states-black: #1c1a1a !default;
|
||||
|
||||
// opacity
|
||||
$default-opacity: rgba(182, 182, 182, .6) !default;
|
||||
|
@ -379,7 +379,7 @@ $general-transition-time: 300ms !default;
|
|||
|
||||
|
||||
// Fonts
|
||||
|
||||
$font-family-primary: 'Poppins', sans-serif !default;
|
||||
$font-family-base: 'Poppins', sans-serif !default;
|
||||
$font-family-alt: 'Poppins', sans-serif !default;
|
||||
|
||||
|
@ -899,7 +899,7 @@ $card-border-color: rgba($black, .05);
|
|||
$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width});
|
||||
$card-cap-bg: $gray-100 !default;
|
||||
$card-bg: $white !default;
|
||||
$card-black-background: #27293d !default;
|
||||
$card-black-background: #463727 !default;
|
||||
$card-img-overlay-padding: 1.25rem !default;
|
||||
|
||||
//$card-group-margin: ($grid-gutter-width / 2);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
@mixin btn-styles($btn-color, $btn-states-color) {
|
||||
@include diagonal-gradient($btn-color, $btn-states-color);
|
||||
background-color: $btn-color;
|
||||
transition: all 0.15s ease;
|
||||
box-shadow: none;
|
||||
|
@ -18,10 +17,6 @@
|
|||
&.active:hover
|
||||
{
|
||||
background-color: $btn-states-color !important;
|
||||
background-image: linear-gradient(to bottom left, $btn-color, $btn-states-color, $btn-color) !important;
|
||||
background-image: -webkit-linear-gradient(to bottom left, $btn-color, $btn-states-color, $btn-color) !important;
|
||||
background-image: -o-linear-gradient(to bottom left, $btn-color, $btn-states-color, $btn-color) !important;
|
||||
background-image: -moz-linear-gradient(to bottom left, $btn-color, $btn-states-color, $btn-color) !important;
|
||||
color: $white;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
@ -165,10 +160,6 @@
|
|||
&:not(:disabled):not(.disabled):active{
|
||||
color: $white;
|
||||
border-color: $btn-color;
|
||||
background-image: linear-gradient(to bottom left, $btn-color, $btn-states-color, $btn-color) !important;
|
||||
background-image: -webkit-linear-gradient(to bottom left, $btn-color, $btn-states-color, $btn-color) !important;
|
||||
background-image: -o-linear-gradient(to bottom left, $btn-color, $btn-states-color, $btn-color) !important;
|
||||
background-image: -moz-linear-gradient(to bottom left, $btn-color, $btn-states-color, $btn-color) !important;
|
||||
background-color: $btn-states-color !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
<p>Github Repo</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item mt-5">
|
||||
<a target="_blank" href="https://trufflesecurity.com/" class="nav-link">
|
||||
<i class="fas fab fa-power-off"></i>
|
||||
<p>Powered by TruffleSec</p>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
</side-bar>
|
||||
<div class="main-panel">
|
||||
|
|
|
@ -13,18 +13,8 @@
|
|||
<span class="navbar-toggler-bar bar3"></span>
|
||||
</button>
|
||||
</div>
|
||||
<a class="navbar-brand" href="#pablo">{{routeName}}</a>
|
||||
<a class="navbar-brand" href="#pablo">XSS HUNTER | <small>{{routeName}}</small></a>
|
||||
</div>
|
||||
<button class="navbar-toggler" type="button"
|
||||
@click="toggleMenu"
|
||||
data-toggle="collapse"
|
||||
data-target="#navigation"
|
||||
aria-controls="navigation-index"
|
||||
aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-bar navbar-kebab"></span>
|
||||
<span class="navbar-toggler-bar navbar-kebab"></span>
|
||||
<span class="navbar-toggler-bar navbar-kebab"></span>
|
||||
</button>
|
||||
|
||||
<collapse-transition>
|
||||
<div class="collapse navbar-collapse show" v-show="showMenu">
|
||||
|
|
|
@ -317,7 +317,6 @@ export default {
|
|||
}
|
||||
|
||||
.xss-card-container {
|
||||
max-width: 1000px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,29 +5,32 @@
|
|||
<card class="xss-card-container">
|
||||
<div class="row pl-4 pr-4 p-2" style="display: block;">
|
||||
<div>
|
||||
<h1><i class="fas fa-cogs"></i>User Settings</h1>
|
||||
<h1><i class="fas fa-cogs"></i> User Settings</h1>
|
||||
</div>
|
||||
<card>
|
||||
<h4 class="card-title">Injection Correlation API Key</h4>
|
||||
<h6 class="card-subtitle mb-2 text-muted">Use with an XSS Hunter compatible client to track which injection caused a payload fire.</h6>
|
||||
<h6 class="card-subtitle mb-2 text-muted">Use with an XSS Hunter-compatible client to track which injection caused a payload fire.</h6>
|
||||
<p class="card-text">
|
||||
<base-input v-bind:value="correlation_api_key" type="text" placeholder="..." ></base-input>
|
||||
</p>
|
||||
<base-button class="mr-1" type="primary" v-clipboard:copy="correlation_api_key" >
|
||||
<i class="far fa-copy"></i> Copy API Key
|
||||
<span style="display: inline-block; margin-right: 6px;"><i class="far fa-copy"></i></span>
|
||||
Copy API Key
|
||||
</base-button>
|
||||
<base-button type="danger" v-on:click="generate_new_correlation_api_key">
|
||||
<i class="fas fa-sync-alt"></i> Rotate API Key
|
||||
<span style="display: inline-block; margin-right: 6px;"><i class="fas fa-sync-alt"></i></span>
|
||||
Rotate API Key
|
||||
</base-button>
|
||||
</card>
|
||||
<card>
|
||||
<h4 class="card-title">XSSHunter Path</h4>
|
||||
<h6 class="card-subtitle mb-2 text-muted">This unique path ties injection payloads back to you. You can set it to something shorter (it defaults to 20 chars).</h6>
|
||||
<h6 class="card-subtitle mb-2 text-muted">Unique path that ties injection payloads back to you. Can be set to something shorter. (defaults to 20 chars)</h6>
|
||||
<p class="card-text">
|
||||
<base-input v-model:value="user_path" type="text" placeholder="..."></base-input>
|
||||
</p>
|
||||
<base-button type="primary" v-on:click="update_path">
|
||||
<i class="fas fa-lock"></i> Update Path
|
||||
<span style="display: inline-block; margin-right: 6px;"><i class="fas fa-lock"></i></span>
|
||||
Update Path
|
||||
</base-button>
|
||||
</card>
|
||||
<card>
|
||||
|
@ -37,25 +40,28 @@
|
|||
<base-input v-model="chainload_uri" type="text" placeholder="https://example.com/remote.js"></base-input>
|
||||
</p>
|
||||
<base-button type="primary" v-on:click="update_chainload_uri">
|
||||
<i class="far fa-save"></i> Save JavaScript URL
|
||||
<span style="display: inline-block; margin-right: 6px;"><i class="far fa-save"></i></span>
|
||||
Save JavaScript URL
|
||||
</base-button>
|
||||
</card>
|
||||
<card>
|
||||
<h4 class="card-title">Miscellaneous Options</h4>
|
||||
<div v-if="send_alert_emails">
|
||||
<base-button type="primary" v-on:click="set_email_reporting">
|
||||
<i class="far fa-bell-slash"></i> Disable Email Reporting
|
||||
<span style="display: inline-block; margin-right: 6px;"><i class="far fa-bell-slash"></i></span>
|
||||
Disable Email Reporting
|
||||
</base-button>
|
||||
<h6 class="mt-2 text-muted">
|
||||
Disable the sending of XSS payload fire reports to the specified email address.
|
||||
Disable sending XSS payload fire reports to the specified email address.
|
||||
</h6>
|
||||
</div>
|
||||
<div v-if="!send_alert_emails">
|
||||
<base-button type="primary" v-on:click="set_email_reporting">
|
||||
<i class="far fa-bell"></i> Enable Email Reporting
|
||||
<span style="display: inline-block; margin-right: 6px;"><i class="far fa-bell"></i></span>
|
||||
Enable Email Reporting
|
||||
</base-button>
|
||||
<h6 class="mt-2 text-muted">
|
||||
Enable the sending of XSS payload fire reports to the specified email address.
|
||||
Enable sending XSS payload fire reports to the specified email address.
|
||||
</h6>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
<card class="xss-card-container">
|
||||
<div class="row pl-4 pr-4 p-2" style="display: block;">
|
||||
<div>
|
||||
<h1><i class="fas fa-fire"></i> XSS Payload Fire Reports ({{format_with_commas(report_count)}} Total)</h1>
|
||||
<h1><i class="fas fa-fire"></i> XSS Payload Fire Reports ({{format_with_commas(report_count)}} total)</h1>
|
||||
<hr />
|
||||
<div v-for="report in payload_fire_reports">
|
||||
<div v-if="report_count === 0" style="color: white;">No reports!</div>
|
||||
<div v-else v-for="report in payload_fire_reports">
|
||||
<card class="mb-0">
|
||||
<div class="screenshot-image-container mb-2">
|
||||
<a v-bind:href="base_api_path + '/screenshots/' + report.screenshot_id + '.png'" target="_blank">
|
||||
|
@ -210,7 +211,7 @@
|
|||
<hr />
|
||||
</div>
|
||||
<!-- Pagination -->
|
||||
<div class="text-center pagination-div">
|
||||
<div v-if="report_count !== 0" class="text-center pagination-div">
|
||||
<base-pagination v-bind:page-count="total_pages" v-model="page"></base-pagination>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -507,7 +508,6 @@ export default {
|
|||
}
|
||||
|
||||
.xss-card-container {
|
||||
max-width: 1000px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
@ -808,7 +808,7 @@ a.badge-dark:focus {
|
|||
}
|
||||
|
||||
hr {
|
||||
background-color: #344675;
|
||||
background-color: #ae8c57;
|
||||
}
|
||||
|
||||
.corner-loader {}
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
<p class="card-text">
|
||||
<base-input type="text" v-bind:value="payload.func()" placeholder="..."></base-input>
|
||||
</p>
|
||||
<base-button type="primary" v-clipboard:copy="payload.func()"><i class="far fa-copy"></i> Copy Payload</base-button>
|
||||
<base-button type="primary" v-clipboard:copy="payload.func()">
|
||||
<span style="display: inline-block; margin-right: 6px;"><i class="far fa-copy"></i></span>
|
||||
Copy Payload</base-button>
|
||||
</card>
|
||||
</div>
|
||||
</card>
|
||||
|
|
|
@ -12,12 +12,12 @@ const routes = [
|
|||
children: [
|
||||
{
|
||||
path: "",
|
||||
name: "XSS Payload Fire Reports",
|
||||
name: "Payload Fire Reports",
|
||||
component: XSSPayloadFireReports
|
||||
},
|
||||
{
|
||||
path: "/xsspayloads",
|
||||
name: "XSS Payloads",
|
||||
name: "Payloads",
|
||||
component: XSSPayloads
|
||||
},
|
||||
{
|
||||
|
|
2591
package-lock.json
generated
2591
package-lock.json
generated
File diff suppressed because it is too large
Load diff
13
package.json
13
package.json
|
@ -11,17 +11,19 @@
|
|||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@deveodk/vue-toastr": "^1.1.0",
|
||||
"@nvanexan/node-client-sessions": "^0.8.0",
|
||||
"@truffledustin/node-client-sessions": "^0.8.0",
|
||||
"bcrypt": "^5.0.1",
|
||||
"body-parser": "^1.20.1",
|
||||
"cors": "^2.8.5",
|
||||
"@google-cloud/storage": "^6.9.0",
|
||||
"express": "^4.17.1",
|
||||
"express-jsonschema": "^1.1.6",
|
||||
"greenlock-express": "^4.0.3",
|
||||
"google-auth-library": "^8.7.0",
|
||||
"googleapis": "^110.0.0",
|
||||
"keygrip": "^1.1.0",
|
||||
"memorystore": "^1.6.6",
|
||||
"moment": "^2.29.1",
|
||||
"multer": "^1.4.2",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"mustache": "^4.1.0",
|
||||
"nodemailer": "^6.5.0",
|
||||
"pg": "^8.5.1",
|
||||
|
@ -29,9 +31,6 @@
|
|||
"sequelize": "^6.5.0",
|
||||
"serve-favicon": "^2.5.0",
|
||||
"uuid": "^8.3.2",
|
||||
"vue-moment": "^4.1.0",
|
||||
"body-parser": "^1.20.1",
|
||||
"google-auth-library": "^8.7.0",
|
||||
"googleapis": "^110.0.0"
|
||||
"vue-moment": "^4.1.0"
|
||||
}
|
||||
}
|
||||
|
|
11
server.js
11
server.js
|
@ -16,10 +16,9 @@ if(!process.env.SSL_CONTACT_EMAIL) {
|
|||
|
||||
const app = await get_app_server();
|
||||
|
||||
require('greenlock-express').init({
|
||||
packageRoot: __dirname,
|
||||
configDir: './greenlock.d',
|
||||
cluster: false,
|
||||
maintainerEmail: process.env.SSL_CONTACT_EMAIL,
|
||||
}).serve(app);
|
||||
const port = process.env.PORT;
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`XSS Hunter listening on port ${port}`)
|
||||
});
|
||||
})();
|
||||
|
|
Loading…
Reference in a new issue