diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..3ba13e0ce --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index fb999dd62..b1c75fe0b 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the git repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Log in to Docker Hub uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f36813a6..439af90e8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,7 +2,7 @@ name: Build Docker image on: push: - branches: [ master] + branches: [ master ] schedule: - cron: '0 18 * * 5' @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the git repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Log in to Docker Hub uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d99c6b168..cc50ad1f6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -20,16 +20,16 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/Makefile b/Makefile index f1b8d1d1d..b6cb7cfba 100644 --- a/Makefile +++ b/Makefile @@ -13,48 +13,48 @@ SERVICES := db web proxy redis celery celery-beat .PHONY: setup certs up build username pull down stop restart rm logs certs: ## Generate certificates. - @${COMPOSE_PREFIX_CMD} docker-compose -f docker-compose.setup.yml run --rm certs + @${COMPOSE_PREFIX_CMD} docker compose -f docker-compose.setup.yml run --rm certs setup: ## Generate certificates. @make certs up: ## Build and start all services. - ${COMPOSE_PREFIX_CMD} docker-compose ${COMPOSE_ALL_FILES} up -d --build ${SERVICES} + ${COMPOSE_PREFIX_CMD} docker compose ${COMPOSE_ALL_FILES} up -d --build ${SERVICES} build: ## Build all services. - ${COMPOSE_PREFIX_CMD} docker-compose ${COMPOSE_ALL_FILES} build ${SERVICES} + ${COMPOSE_PREFIX_CMD} docker compose ${COMPOSE_ALL_FILES} build ${SERVICES} username: ## Generate Username (Use only after make up). - ${COMPOSE_PREFIX_CMD} docker-compose ${COMPOSE_ALL_FILES} exec web python3 manage.py createsuperuser + ${COMPOSE_PREFIX_CMD} docker compose ${COMPOSE_ALL_FILES} exec web python3 manage.py createsuperuser pull: ## Pull Docker images. docker login docker.pkg.github.com - ${COMPOSE_PREFIX_CMD} docker-compose ${COMPOSE_ALL_FILES} pull + ${COMPOSE_PREFIX_CMD} docker compose ${COMPOSE_ALL_FILES} pull down: ## Down all services. - ${COMPOSE_PREFIX_CMD} docker-compose ${COMPOSE_ALL_FILES} down + ${COMPOSE_PREFIX_CMD} docker compose ${COMPOSE_ALL_FILES} down stop: ## Stop all services. - ${COMPOSE_PREFIX_CMD} docker-compose ${COMPOSE_ALL_FILES} stop ${SERVICES} + ${COMPOSE_PREFIX_CMD} docker compose ${COMPOSE_ALL_FILES} stop ${SERVICES} restart: ## Restart all services. - ${COMPOSE_PREFIX_CMD} docker-compose ${COMPOSE_ALL_FILES} restart ${SERVICES} + ${COMPOSE_PREFIX_CMD} docker compose ${COMPOSE_ALL_FILES} restart ${SERVICES} rm: ## Remove all services containers. - ${COMPOSE_PREFIX_CMD} docker-compose $(COMPOSE_ALL_FILES) rm -f ${SERVICES} + ${COMPOSE_PREFIX_CMD} docker compose $(COMPOSE_ALL_FILES) rm -f ${SERVICES} test: - ${COMPOSE_PREFIX_CMD} docker-compose $(COMPOSE_ALL_FILES) exec celery python3 -m unittest tests/test_scan.py + ${COMPOSE_PREFIX_CMD} docker compose $(COMPOSE_ALL_FILES) exec celery python3 -m unittest tests/test_scan.py logs: ## Tail all logs with -n 1000. - ${COMPOSE_PREFIX_CMD} docker-compose $(COMPOSE_ALL_FILES) logs --follow --tail=1000 ${SERVICES} + ${COMPOSE_PREFIX_CMD} docker compose $(COMPOSE_ALL_FILES) logs --follow --tail=1000 ${SERVICES} images: ## Show all Docker images. - ${COMPOSE_PREFIX_CMD} docker-compose $(COMPOSE_ALL_FILES) images ${SERVICES} + ${COMPOSE_PREFIX_CMD} docker compose $(COMPOSE_ALL_FILES) images ${SERVICES} prune: ## Remove containers and delete volume data. @make stop && make rm && docker volume prune -f help: ## Show this help. - @echo "Make application docker images and manage containers using docker-compose files." + @echo "Make application docker images and manage containers using docker compose files." @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m (default: help)\n\nTargets:\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-12s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST) diff --git a/README.md b/README.md index c0af47891..1d5e0d238 100644 --- a/README.md +++ b/README.md @@ -272,7 +272,7 @@ vulnerability_scan: { 'timeout': 5, 'fetch_gpt_report': true, 'nuclei': { - 'use_conf': false, + 'use_nuclei_config': false, 'severities': [ 'unknown', 'info', diff --git a/install.sh b/install.sh index bf745da91..679173a82 100755 --- a/install.sh +++ b/install.sh @@ -63,15 +63,15 @@ fi echo " " tput setaf 4; echo "#########################################################################" -echo "Installing docker-compose" +echo "Installing docker compose" echo "#########################################################################" -if [ -x "$(command -v docker-compose)" ]; then - tput setaf 2; echo "docker-compose already installed, skipping." +if [ -x "$(command -v docker compose)" ]; then + tput setaf 2; echo "docker compose already installed, skipping." else curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose - tput setaf 2; echo "docker-compose installed!!!" + tput setaf 2; echo "docker compose installed!!!" fi echo " " diff --git a/make.bat b/make.bat index 0a99cb6cb..20d93c716 100644 --- a/make.bat +++ b/make.bat @@ -6,30 +6,30 @@ set COMPOSE_ALL_FILES = -f docker-compose.yml set SERVICES = db web proxy redis celery celery-beat :: Generate certificates. -if "%1" == "certs" docker-compose -f docker-compose.setup.yml run --rm certs +if "%1" == "certs" docker compose -f docker-compose.setup.yml run --rm certs :: Generate certificates. -if "%1" == "setup" docker-compose -f docker-compose.setup.yml run --rm certs +if "%1" == "setup" docker compose -f docker-compose.setup.yml run --rm certs :: Build and start all services. -if "%1" == "up" docker-compose %COMPOSE_ALL_FILES% up -d --build %SERVICES% +if "%1" == "up" docker compose %COMPOSE_ALL_FILES% up -d --build %SERVICES% :: Build all services. -if "%1" == "build" docker-compose %COMPOSE_ALL_FILES% build %SERVICES% +if "%1" == "build" docker compose %COMPOSE_ALL_FILES% build %SERVICES% :: Generate Username (Use only after make up). -if "%1" == "username" docker-compose %COMPOSE_ALL_FILES% exec web python3 manage.py createsuperuser +if "%1" == "username" docker compose %COMPOSE_ALL_FILES% exec web python3 manage.py createsuperuser :: Pull Docker images. -if "%1" == "pull" docker login docker.pkg.github.com & docker-compose %COMPOSE_ALL_FILES% pull +if "%1" == "pull" docker login docker.pkg.github.com & docker compose %COMPOSE_ALL_FILES% pull :: Down all services. -if "%1" == "down" docker-compose %COMPOSE_ALL_FILES% down +if "%1" == "down" docker compose %COMPOSE_ALL_FILES% down :: Stop all services. -if "%1" == "stop" docker-compose %COMPOSE_ALL_FILES% stop %SERVICES% +if "%1" == "stop" docker compose %COMPOSE_ALL_FILES% stop %SERVICES% :: Restart all services. -if "%1" == "restart" docker-compose %COMPOSE_ALL_FILES% restart %SERVICES% +if "%1" == "restart" docker compose %COMPOSE_ALL_FILES% restart %SERVICES% :: Remove all services containers. -if "%1" == "rm" docker-compose %COMPOSE_ALL_FILES% rm -f %SERVICES% +if "%1" == "rm" docker compose %COMPOSE_ALL_FILES% rm -f %SERVICES% :: Tail all logs with -n 1000. -if "%1" == "logs" docker-compose %COMPOSE_ALL_FILES% logs --follow --tail=1000 %SERVICES% +if "%1" == "logs" docker compose %COMPOSE_ALL_FILES% logs --follow --tail=1000 %SERVICES% :: Show all Docker images. -if "%1" == "images" docker-compose %COMPOSE_ALL_FILES% images %SERVICES% +if "%1" == "images" docker compose %COMPOSE_ALL_FILES% images %SERVICES% :: Remove containers and delete volume data. -if "%1" == "prune" docker-compose %COMPOSE_ALL_FILES% stop %SERVICES% & docker-compose %COMPOSE_ALL_FILES% rm -f %SERVICES% & docker volume prune -f +if "%1" == "prune" docker compose %COMPOSE_ALL_FILES% stop %SERVICES% & docker compose %COMPOSE_ALL_FILES% rm -f %SERVICES% & docker volume prune -f :: Show this help. -if "%1" == "help" @echo Make application docker images and manage containers using docker-compose files only for windows. +if "%1" == "help" @echo Make application docker images and manage containers using docker compose files only for windows. diff --git a/web/Dockerfile b/web/Dockerfile index ff1665768..60054aaaf 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -1,5 +1,5 @@ # Base image -FROM ubuntu:22.04 +FROM --platform=linux/amd64 ubuntu:22.04 # Labels and Credits LABEL \ @@ -67,7 +67,6 @@ ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 # Download Go packages -RUN go install -v -v github.com/bp0lr/gauplus@latest RUN go install -v github.com/jaeles-project/gospider@latest RUN go install -v github.com/tomnomnom/gf@latest RUN go install -v github.com/tomnomnom/unfurl@latest diff --git a/web/art/reNgine.txt b/web/art/reNgine.txt index f887773bd..d815af892 100644 --- a/web/art/reNgine.txt +++ b/web/art/reNgine.txt @@ -3,6 +3,6 @@ _ __ ___| \| | __ _ _ _ __ ___ | '__/ _ \ . ` |/ _` | | '_ \ / _ \ | | | __/ |\ | (_| | | | | | __/ - |_| \___|_| \_|\__, |_|_| |_|\___| v2.0.0-jasper + |_| \___|_| \_|\__, |_|_| |_|\___| v2.0.2-jasper __/ | |___/ diff --git a/web/dashboard/templates/dashboard/admin.html b/web/dashboard/templates/dashboard/admin.html index 269586230..31c754a88 100644 --- a/web/dashboard/templates/dashboard/admin.html +++ b/web/dashboard/templates/dashboard/admin.html @@ -279,6 +279,13 @@

Users

var create_username = document.getElementById('create_username').value; var role_selected = document.getElementById('create_user_role').value; var create_password = document.getElementById('create_password').value; + if (!create_password) { + Swal.fire({ + title: "Oops! Passwords can't be empty!", + icon: 'error', + }) + return + } const data = { 'username': create_username, 'role': role_selected, diff --git a/web/dashboard/views.py b/web/dashboard/views.py index d54ce1d74..11c688bfc 100644 --- a/web/dashboard/views.py +++ b/web/dashboard/views.py @@ -220,8 +220,8 @@ def admin_interface_update(request, slug): try: user.delete() messages.add_message( - request, - messages.INFO, + request, + messages.INFO, f'User {user.username} successfully deleted.' ) messageData = {'status': True} @@ -245,6 +245,9 @@ def admin_interface_update(request, slug): elif mode == 'create': try: response = json.loads(request.body) + if not response.get('password'): + messageData = {'status': False, 'error': 'Empty passwords are not allowed'} + return JsonResponse(messageData) UserModel = get_user_model() user = UserModel.objects.create_user( username=response.get('username'), diff --git a/web/fixtures/default_scan_engines.yaml b/web/fixtures/default_scan_engines.yaml index a2c88e607..f79cf0994 100644 --- a/web/fixtures/default_scan_engines.yaml +++ b/web/fixtures/default_scan_engines.yaml @@ -30,7 +30,7 @@ \ 'run_nuclei': true,\r\n 'run_dalfox': true,\r\n 'run_crlfuzz': true,\r\n \ 'enable_http_crawl': true,\r\n 'concurrency': 50,\r\n 'intensity': 'normal',\r\n \ 'rate_limit': 150,\r\n 'retries': 1,\r\n 'timeout': 5,\r\n 'fetch_gpt_report': - true,\r\n 'nuclei': {\r\n 'use_conf': false,\r\n 'severities': ['unknown', + true,\r\n 'nuclei': {\r\n 'use_nuclei_config': false,\r\n 'severities': ['unknown', 'info', 'low', 'medium', 'high', 'critical']\r\n }\r\n}\r\nwaf_detection: {\r\n\r\n}\r\nscreenshot: {\r\n 'enable_http_crawl': true,\r\n 'intensity': 'normal',\r\n 'timeout': 10,\r\n 'threads': 40\r\n}\r\n\r\n# custom_header: \"Cookie: Test\"" @@ -72,7 +72,7 @@ {\r\n 'run_nuclei': true,\r\n 'run_dalfox': true,\r\n 'run_crlfuzz': true,\r\n \ 'enable_http_crawl': true,\r\n 'concurrency': 50,\r\n 'intensity': 'normal',\r\n \ 'rate_limit': 150,\r\n 'retries': 1,\r\n 'timeout': 5,\r\n 'fetch_gpt_report': - true,\r\n 'nuclei': {\r\n 'use_conf': false,\r\n 'severities': ['unknown', + true,\r\n 'nuclei': {\r\n 'use_nuclei_config': false,\r\n 'severities': ['unknown', 'info', 'low', 'medium', 'high', 'critical']\r\n }\r\n}" default_engine: true - model: scanEngine.enginetype @@ -99,6 +99,6 @@ {\r\n 'run_nuclei': true,\r\n 'run_dalfox': true,\r\n 'run_crlfuzz': true,\r\n \ 'enable_http_crawl': false,\r\n 'concurrency': 50,\r\n 'intensity': 'normal',\r\n \ 'rate_limit': 150,\r\n 'retries': 1,\r\n 'timeout': 5,\r\n 'fetch_gpt_report': - true,\r\n 'nuclei': {\r\n 'use_conf': false,\r\n 'severities': ['low', + true,\r\n 'nuclei': {\r\n 'use_nuclei_config': false,\r\n 'severities': ['low', 'medium', 'high', 'critical']\r\n }\r\n}" default_engine: true diff --git a/web/fixtures/external_tools.yaml b/web/fixtures/external_tools.yaml index a5435cd3a..0c2994b64 100644 --- a/web/fixtures/external_tools.yaml +++ b/web/fixtures/external_tools.yaml @@ -70,7 +70,7 @@ version_lookup_command: naabu -version update_command: go install -v github.com/projectdiscovery/naabu/v2/cmd/naabu@latest install_command: go install -v github.com/projectdiscovery/naabu/v2/cmd/naabu@latest - version_match_regex: ' (\d+\.)?(\d+\.)?(\*|\d+)' + version_match_regex: '(\b\d+\.\d+\.\d+\b)' is_default: true is_subdomain_gathering: false is_github_cloned: false @@ -171,40 +171,23 @@ subdomain_gathering_command: null - model: scanEngine.installedexternaltool pk: 10 - fields: - logo_url: null - name: gauplus - description: Get all URLs - github_url: https://github.com/bp0lr/gauplus - license_url: https://github.com/bp0lr/gauplus/blob/main/LICENSE - version_lookup_command: gauplus -version - update_command: go install -v -v github.com/bp0lr/gauplus@latest - install_command: go install -v -v github.com/bp0lr/gauplus@latest - version_match_regex: '[vV]*(\d+\.)?(\d+\.)?(\*|\d+)' - is_default: true - is_subdomain_gathering: false - is_github_cloned: true - github_clone_path: /usr/src/github/gauplus - subdomain_gathering_command: null -- model: scanEngine.installedexternaltool - pk: 11 fields: logo_url: null name: OneForAll description: A powerful subdomain integration tool. github_url: https://github.com/shmilylty/OneForAll license_url: https://github.com/shmilylty/OneForAll/blob/master/LICENSE - version_lookup_command: python3 /usr/src/github/OneForAll/oneforall.py version + version_lookup_command: cat /usr/src/github/OneForAll/oneforall.py update_command: git pull install_command: git clone https://github.com/shmilylty/OneForAll - version_match_regex: 'v(\d+\.)?(\d+\.)?(\*|\d+)' + version_match_regex: v\d+\.\d+\.\d+\b is_default: true is_subdomain_gathering: true is_github_cloned: true github_clone_path: /usr/src/github/OneForAll subdomain_gathering_command: null - model: scanEngine.installedexternaltool - pk: 12 + pk: 11 fields: logo_url: https://raw.githubusercontent.com/laramies/theHarvester/master/theHarvester-logo.png name: theHarvester @@ -215,17 +198,17 @@ names, subdomains, IPs and URLs using multiple public data sources. github_url: https://github.com/laramies/theHarvester license_url: https://github.com/laramies/theHarvester/blob/master/README/LICENSES - version_lookup_command: null + version_lookup_command: cat /usr/src/github/theHarvester/theHarvester/lib/version.py update_command: git pull install_command: git clone https://github.com/laramies/theHarvester - version_match_regex: (\d+\.)?(\d+\.)?(\*|\d+) + version_match_regex: \b\d+\.\d+\.\d+\b is_default: true is_subdomain_gathering: false is_github_cloned: true github_clone_path: /usr/src/github/theHarvester subdomain_gathering_command: null - model: scanEngine.installedexternaltool - pk: 13 + pk: 12 fields: logo_url: null name: ctfr @@ -244,7 +227,7 @@ github_clone_path: /usr/src/github/ctfr subdomain_gathering_command: null - model: scanEngine.installedexternaltool - pk: 14 + pk: 13 fields: logo_url: https://user-images.githubusercontent.com/8293321/174841003-01a62bad-2ecf-4874-89c4-efa53dd56884.png name: tlsx @@ -261,14 +244,14 @@ github_clone_path: null subdomain_gathering_command: null - model: scanEngine.installedexternaltool - pk: 15 + pk: 14 fields: logo_url: https://avatars.githubusercontent.com/u/79084675?v=4 name: netlas description: Non-intrusive Internet Scanner. github_url: https://github.com/netlas-io/netlas-python license_url: https://github.com/netlas-io/netlas-python/blob/master/LICENSE - version_lookup_command: null + version_lookup_command: pip3 show netlas update_command: pip3 install netlas --update install_command: pip3 install netlas version_match_regex: (\d+\.)?(\d+\.)?(\*|\d+) @@ -278,7 +261,7 @@ github_clone_path: null subdomain_gathering_command: null - model: scanEngine.installedexternaltool - pk: 16 + pk: 15 fields: logo_url: https://github.githubassets.com/images/icons/emoji/unicode/1f98a.png name: dalfox @@ -296,7 +279,7 @@ github_clone_path: null subdomain_gathering_command: null - model: scanEngine.installedexternaltool - pk: 17 + pk: 16 fields: logo_url: https://user-images.githubusercontent.com/8293321/196779266-421c79d4-643a-4f73-9b54-3da379bbac09.png name: katana @@ -313,7 +296,7 @@ github_clone_path: null subdomain_gathering_command: null - model: scanEngine.installedexternaltool - pk: 18 + pk: 17 fields: logo_url: https://user-images.githubusercontent.com/25837540/90128972-fc3bdf00-dd91-11ea-8c3b-0d6f4e8c6ba3.png name: crlfuzz @@ -330,7 +313,7 @@ github_clone_path: null subdomain_gathering_command: null - model: scanEngine.installedexternaltool - pk: 19 + pk: 18 fields: logo_url: null name: gau @@ -345,4 +328,4 @@ is_subdomain_gathering: false is_github_cloned: false github_clone_path: null - subdomain_gathering_command: null \ No newline at end of file + subdomain_gathering_command: null diff --git a/web/reNgine/definitions.py b/web/reNgine/definitions.py index cdca7304e..7034fbca8 100644 --- a/web/reNgine/definitions.py +++ b/web/reNgine/definitions.py @@ -72,7 +72,7 @@ TIMEOUT = 'timeout' USE_AMASS_CONFIG = 'use_amass_config' USE_NAABU_CONFIG = 'use_naabu_config' -USE_CONFIG = 'use_config' +USE_NUCLEI_CONFIG = 'use_nuclei_config' USE_SUBFINDER_CONFIG = 'use_subfinder_config' USES_TOOLS = 'uses_tools' VULNERABILITY_SCAN = 'vulnerability_scan' @@ -83,6 +83,7 @@ DALFOX = 'dalfox' S3SCANNER = 's3scanner' NUCLEI = 'nuclei' +NMAP = 'nmap' CRLFUZZ = 'crlfuzz' WAF_EVASION = 'waf_evasion' BLIND_XSS_SERVER = 'blind_xss_server' diff --git a/web/reNgine/tasks.py b/web/reNgine/tasks.py index 048dc5048..613293f86 100644 --- a/web/reNgine/tasks.py +++ b/web/reNgine/tasks.py @@ -1759,7 +1759,6 @@ def fetch_url(self, urls=[], ctx={}, description=None): # Tools cmds cmd_map = { 'gau': f'gau', - 'gauplus': f'gauplus -random-agent', 'hakrawler': 'hakrawler -subs -u', 'waybackurls': 'waybackurls', 'gospider': f'gospider -S {input_path} --js -d 2 --sitemap --robots -w -r', @@ -1767,13 +1766,11 @@ def fetch_url(self, urls=[], ctx={}, description=None): } if proxy: cmd_map['gau'] += f' --proxy "{proxy}"' - cmd_map['gauplus'] += f' -p "{proxy}"' cmd_map['gospider'] += f' -p {proxy}' cmd_map['hakrawler'] += f' -proxy {proxy}' cmd_map['katana'] += f' -proxy {proxy}' if threads > 0: cmd_map['gau'] += f' --threads {threads}' - cmd_map['gauplus'] += f' -t {threads}' cmd_map['gospider'] += f' -t {threads}' cmd_map['katana'] += f' -c {threads}' if custom_header: @@ -2291,7 +2288,7 @@ def nuclei_scan(self, urls=[], ctx={}, description=None): should_fetch_gpt_report = config.get(FETCH_GPT_REPORT, DEFAULT_GET_GPT_REPORT) proxy = get_random_proxy() nuclei_specific_config = config.get('nuclei', {}) - use_nuclei_conf = nuclei_specific_config.get(USE_CONFIG, False) + use_nuclei_conf = nuclei_specific_config.get(USE_NUCLEI_CONFIG, False) severities = nuclei_specific_config.get(NUCLEI_SEVERITY, NUCLEI_DEFAULT_SEVERITIES) tags = nuclei_specific_config.get(NUCLEI_TAGS, []) tags = ','.join(tags) @@ -3233,8 +3230,9 @@ def parse_nmap_results(xml_file, output_file=None): else: logger.warning(f'Script output parsing for script "{script_id}" is not supported yet.') - # Add URL to vuln + # Add URL & source to vuln for vuln in url_vulns: + vuln['source'] = NMAP # TODO: This should extend to any URL, not just HTTP vuln['http_url'] = url if 'http_path' in vuln: diff --git a/web/scanEngine/models.py b/web/scanEngine/models.py index ce8a3cf4b..89a7cbb31 100644 --- a/web/scanEngine/models.py +++ b/web/scanEngine/models.py @@ -34,6 +34,8 @@ def get_number_of_steps(self): @hybrid_property def tasks(self): + if not self.yaml_configuration or not yaml.safe_load(self.yaml_configuration): + return [] return list(yaml.safe_load(self.yaml_configuration).keys()) class Wordlist(models.Model): diff --git a/web/scanEngine/templates/scanEngine/add_engine.html b/web/scanEngine/templates/scanEngine/add_engine.html index 11be40d16..53551ca52 100644 --- a/web/scanEngine/templates/scanEngine/add_engine.html +++ b/web/scanEngine/templates/scanEngine/add_engine.html @@ -170,7 +170,7 @@

Scan Engines

# 'tags': [], # 'templates': [], # 'custom_templates': [], - 'use_conf': false, + 'use_nuclei_config': false, 'severities': [ 'unknown', 'info', diff --git a/web/scanEngine/templates/scanEngine/settings/hackerone.html b/web/scanEngine/templates/scanEngine/settings/hackerone.html index 8f74fcfcb..1cbd18142 100644 --- a/web/scanEngine/templates/scanEngine/settings/hackerone.html +++ b/web/scanEngine/templates/scanEngine/settings/hackerone.html @@ -77,7 +77,7 @@

Vulnerability Report Template

  • {vulnerable_url} Vulnerable URL.
  • {vulnerability_severity} Vulnerability Severity.
  • {vulnerability_description} Description of vulnerability generated by Nuclei.
  • -
  • {vulnerability_extracted_results} Vulnerabty Results extracted by Nuclei.
  • +
  • {vulnerability_extracted_results} Vulnerability Results extracted by Nuclei.
  • {vulnerability_reference} Additional Reference to vulnerability.
  • diff --git a/web/startScan/models.py b/web/startScan/models.py index 5423a28a6..e1d9c57d2 100644 --- a/web/startScan/models.py +++ b/web/startScan/models.py @@ -262,6 +262,13 @@ def get_vulnerabilities(self): vulns = vulns.filter(scan_history=self.scan_history) return vulns + @property + def get_vulnerabilities_without_info(self): + vulns = Vulnerability.objects.filter(subdomain__name=self.name).exclude(severity=0) + if self.scan_history: + vulns = vulns.filter(scan_history=self.scan_history) + return vulns + @property def get_directories_count(self): subdomains = ( diff --git a/web/startScan/templates/startScan/detail_scan.html b/web/startScan/templates/startScan/detail_scan.html index 4a80d23ed..b24d1bb86 100644 --- a/web/startScan/templates/startScan/detail_scan.html +++ b/web/startScan/templates/startScan/detail_scan.html @@ -1785,7 +1785,7 @@

    Directory Scan has been performed ${data.length} times.

    `; } - html_treeview += `
      `; + html_treeview += `
        `; var item_pos = 0; data.forEach(function(item){ var aria_expanded = 'false'; @@ -1934,12 +1934,12 @@

        No Directories Discovered during the Scan Performed on ${item.scanned_date}`; - html_treeview += `
        `; + html_treeview += `
      • No Directories Discovered during the Scan Performed on ${item.scanned_date}
      • `; + html_treeview += `
        `; } else{ - html_treeview += `
        Directory Scan Performed on ${item.scanned_date}`; - html_treeview += `
        `; + html_treeview += `
      • ${item['directory_files'].length} found on ${item.scanned_date}
      • `; + html_treeview += `
        `; var interesting_badge = ''; // console.log(item['directory_files'][i]['name']); item['directory_files'].forEach(function(file){ diff --git a/web/startScan/views.py b/web/startScan/views.py index 182aaffb6..32d27547f 100644 --- a/web/startScan/views.py +++ b/web/startScan/views.py @@ -908,6 +908,7 @@ def create_report(request, id): 'scan_object': scan, 'unique_vulnerabilities': unique_vulns, 'all_vulnerabilities': vulns, + 'all_vulnerabilities_count': vulns.count(), 'subdomain_alive_count': subdomain_alive_count, 'interesting_subdomains': interesting_subdomains, 'subdomains': subdomains, @@ -915,6 +916,7 @@ def create_report(request, id): 'show_recon': show_recon, 'show_vuln': show_vuln, 'report_name': report_name, + 'is_ignore_info_vuln': is_ignore_info_vuln, } # Get report related config diff --git a/web/targetApp/forms.py b/web/targetApp/forms.py index c2aad7449..0f1b1c257 100644 --- a/web/targetApp/forms.py +++ b/web/targetApp/forms.py @@ -38,7 +38,7 @@ class AddOrganizationForm(forms.Form): def __init__(self, *args, **kwargs): project = kwargs.pop('project') super(AddOrganizationForm, self).__init__(*args, **kwargs) - self.fields['domains'].choices = [(domain.id, domain.name) for domain in Domain.objects.filter(project__slug=project)] + self.fields['domains'].choices = [(domain.id, domain.name) for domain in Domain.objects.filter(project__slug=project) if not domain.get_organization()] name = forms.CharField( required=True, diff --git a/web/templates/report/template.html b/web/templates/report/template.html index aa1ceff8a..9f353658b 100644 --- a/web/templates/report/template.html +++ b/web/templates/report/template.html @@ -514,7 +514,7 @@

        Reconnaissance

        Vulnerabilities
        - {{scan_object.get_vulnerability_count}} + {{all_vulnerabilities_count}}

        @@ -563,7 +563,11 @@

        Vulnerability Summary

        Info
        - {{scan_object.get_info_vulnerability_count}} + {% if is_ignore_info_vuln %} + 0 + {% else %} + {{scan_object.get_info_vulnerability_count}} + {% endif %}

        @@ -834,11 +838,11 @@

        Reconnaissance Findings

        {% endif %} - {% if subdomain.get_vulnerabilities %} + {% if subdomain.get_vulnerabilities_without_info %} Vulnerabilities - {% regroup subdomain.get_vulnerabilities by name as vuln_list %} + {% regroup subdomain.get_vulnerabilities_without_info by name as vuln_list %}
          {% for vulnerability in vuln_list %}
        • @@ -864,7 +868,7 @@

          Vulnerabilities Discovere {{scan_object.get_critical_vulnerability_count}} of them were Critical, {{scan_object.get_high_vulnerability_count}} of them were High Severity, {{scan_object.get_medium_vulnerability_count}} of them were Medium severity, - {{scan_object.get_low_vulnerability_count}} of them were Low severity, and + {% if is_ignore_info_vuln %}0{% else %}{{scan_object.get_info_vulnerability_count}}{% endif %} of them were Low severity, and {{scan_object.get_info_vulnerability_count}} of them were Informational. {{scan_object.get_unknown_vulnerability_count}} of them were Unknown Severity.

          @@ -906,7 +910,11 @@

          Vulnerability Breakdown by Severity

          Info
          - {{scan_object.get_info_vulnerability_count}} + {% if is_ignore_info_vuln %} + 0 + {% else %} + {{scan_object.get_info_vulnerability_count}} + {% endif %}

          @@ -926,106 +934,106 @@

          Vulnerability Breakdown by Severity

          {% if show_vuln %}
          {% regroup all_vulnerabilities by get_path as grouped_vulnerabilities %} - {% for vulnerability in grouped_vulnerabilities %} -
          -

          - {{vulnerability.list.0.name}} -
          in {{vulnerability.grouper}}
          - {% if vulnerability.list.0.severity == -1 %} - Unknown -
          - {% elif vulnerability.list.0.severity == 0 %} - INFO -
          - {% elif vulnerability.list.0.severity == 1 %} - LOW -
          - {% elif vulnerability.list.0.severity == 2 %} - MEDIUM -
          - {% elif vulnerability.list.0.severity == 3 %} - HIGH -
          - {% elif vulnerability.list.0.severity == 4 %} - CRITICAL -
          + {% for vulnerabilities in grouped_vulnerabilities %} + {% for vulnerability in vulnerabilities.list %} +
          +

          + {{vulnerability.name}} +
          in {{vulnerabilities.grouper}}
          + {% if vulnerability.severity == -1 %} + Unknown +
          + {% elif vulnerability.severity == 0 %} + INFO +
          + {% elif vulnerability.severity == 1 %} + LOW +
          + {% elif vulnerability.severity == 2 %} + MEDIUM +
          + {% elif vulnerability.severity == 3 %} + HIGH +
          + {% elif vulnerability.severity == 4 %} + CRITICAL +
          + {% endif %} +

          + + Vulnerability Source: {{vulnerability.source|upper}}
          + {% if vulnerability.cvss_metrics or vulnerability.cvss_score or vulnerability.cve_ids.all or vulnerability.cve_ids.all %} + Vulnerability Classification
          + {% if vulnerability.cvss_metrics %} + CVSS Metrics: {{vulnerability.cvss_metrics}} + {% endif %} + {% if vulnerability.cvss_score %} +
          + CVSS Score: {{vulnerability.cvss_score}} + {% endif %} + {% if vulnerability.cve_ids.all %} +
          + CVE IDs
          +     {% for cve in vulnerability.cve_ids.all %} {{cve}}{% if not forloop.last %}, {% endif %} {% endfor %} + {% endif %} + {% if vulnerability.cwe_ids.all %} +
          + CWE IDs
          +     {% for cwe in vulnerability.cwe_ids.all %} {{cwe}}{% if not forloop.last %}, {% endif %} {% endfor %} + {% endif %} +
          {% endif %} -

          - - Vulnerability Source: {{vulnerability.list.0.source|upper}}
          - {% if vulnerability.list.0.cvss_metrics or vulnerability.list.0.cvss_score or vulnerability.list.0.cve_ids.all or vulnerability.list.0.cve_ids.all %} - Vulnerability Classification
          - {% if vulnerability.list.0.cvss_metrics %} - CVSS Metrics: {{vulnerability.list.0.cvss_metrics}} + {% if vulnerability.description %} +
          + Description
          + {{vulnerability.description|linebreaks}} {% endif %} - {% if vulnerability.list.0.cvss_score %} -
          - CVSS Score: {{vulnerability.list.0.cvss_score}} + {% if vulnerability.impact %} +
          + Impact
          + {{vulnerability.impact|linebreaks}} {% endif %} - {% if vulnerability.list.0.cve_ids.all %} -
          - CVE IDs
          -     {% for cve in vulnerability.list.0.cve_ids.all %} {{cve}}{% if not forloop.last %}, {% endif %} {% endfor %} + {% if vulnerability.remediation %} +
          + Remediation
          + {{vulnerability.remediation|linebreaks}} {% endif %} - {% if vulnerability.list.0.cwe_ids.all %}
          - CWE IDs
          -     {% for cwe in vulnerability.list.0.cwe_ids.all %} {{cwe}}{% if not forloop.last %}, {% endif %} {% endfor %} + Vulnerable URL(s)
          + + + + {% if vulnerability.references.all %} + References
          +
            + {% for ref in vulnerability.references.all %} +
          • + {{ref}} +
          • + {% endfor %} +
          {% endif %}
          - {% endif %} - {% if vulnerability.list.0.description %} -
          - Description
          - {{vulnerability.list.0.description|linebreaks}} - {% endif %} - {% if vulnerability.list.0.impact %} -
          - Impact
          - {{vulnerability.list.0.impact|linebreaks}} - {% endif %} - {% if vulnerability.list.0.remediation %}
          - Remediation
          - {{vulnerability.list.0.remediation|linebreaks}} - {% endif %} -
          - Vulnerable URL(s)
          -
            - {% for vuln in vulnerability.list %} -
          • {{vuln.http_url}}
          • - {% endfor %} -
          - - - {% if vulnerability.list.0.references.all %} - References
          -
            - {% for ref in vulnerability.list.0.references.all %} -
          • - {{ref}} -
          • - {% endfor %} -
          - {% endif %} -
          -
          -
          +
        + {% endfor %} {% endfor %} {% endif %}