ai newsDo., 5. Nov.
EilmeldungMit KI-Agenten: OpenAI will in Linux-System fast 1.000 Root-Lücken gefunden haben

Running an AI-first external attack surface assessment with CVEngine

I spend a lot of time on the least glamorous part of security work: keeping an accurate list of everything we actually expose to the internet. This is the loop I now run end to end — scope, inventory, an AI-assisted assessment in CVEngine, then hands-on triage. A first pass takes 60 to 90 minutes a

dev.toDonnerstag 11:17 · 05.11.5 Min. Lesezeit
Bild: dev.to

Posted on Nov 5 • Originally published at ai-release.org

I spend a lot of time on the least glamorous part of security work: keeping an accurate list of everything we actually expose to the internet. This is the loop I now run end to end — scope, inventory, an AI-assisted assessment in CVEngine, then hands-on triage. A first pass takes 60 to 90 minutes and sits at intermediate level: you should be comfortable with a shell, DNS and basic HTTP.

Two things before any command. First, get written authorisation for every asset in scope — scanning hosts you do not own is illegal in most jurisdictions, and "we thought it was ours" is not a defence. Second, three terms I use throughout: the attack surface is every host, subdomain, IP address and open port you expose; ASM is the ongoing job of discovering those assets and keeping the list current; triage is deciding which findings are real and which come first.

Where I could not confirm a CVEngine-specific menu label, API path, scan-profile name or token format from the source material, I mark it <verify in documentation>. Those values vary between deployments — read the API reference of your own version rather than guessing.

sudo apt update sudo apt install -y dnsutils nmap jq curl go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest go install -v github.com/projectdiscovery/httpx/cmd/httpx@latest export PATH = " $PATH: $HOME /go/bin" Enter fullscreen mode Exit fullscreen mode That last line does more than it looks. go install drops binaries into $HOME/go/bin, which is not on PATH by default; skip the export and you get command not found, which reads like a broken install. Confirm each tool prints usage text rather than an error:

subfinder -version httpx -version nmap --version | head -n 1 Enter fullscreen mode Exit fullscreen mode Step 1: Write the scope file before you run anything Every later step inherits these assets — the CVEngine project, the AI ranking, the report. Build an inventory before writing the scope down and you will eventually scan a subsidiary nobody asked about.

mkdir -p ~/asm-run/ { raw,out } && cd ~/asm-run cat > scope.yaml << ' EOF ' organisation: Example Corp in_scope: - example.com - api.example.com - 203.0.113.0/24 out_of_scope: - billing.example.com window: "2024-01-15 02:00Z/2024-01-15 06:00Z" contact: security@example.com EOF Enter fullscreen mode Exit fullscreen mode In this example 203.0.113.0/24 is the reserved documentation range — swap in a range you actually own. billing.example.com is excluded because a payment provider hosts it and forbids third-party scanning.

dig +short example.com A subfinder -d example.com -all -o raw/subdomains.txt sort -u raw/subdomains.txt -o raw/subdomains.txt wc -l raw/subdomains.txt httpx -l raw/subdomains.txt -ports 443,80,8443 -status-code -title \ -tech-detect -json -o raw/http.json Enter fullscreen mode Exit fullscreen mode You get one JSON object per responding host:

{ "input": "api.example.com", "url": "https://api.example.com", "status_code": 401, "title": "Unauthorized", "tech":[ "nginx" ]} Enter fullscreen mode Exit fullscreen mode Sanity check: wc -l raw/subdomains.txt should be non-zero, and jq -s length raw/http.json should return fewer entries than the subdomain list. That gap is expected — only hosts answering on those ports appear. If the count is zero, DNS resolution failed.

Then flatten it into the CSV that CVEngine ingests:

jq -r -s '.[] | [.input,.url, (.status_code|tostring), (.tech // "unknown")] | @csv' \ raw/http.json > out/inventory.csv Enter fullscreen mode Exit fullscreen mode Step 3: Load the inventory into CVEngine The platform's value is correlation. A stale nginx banner on an internet-facing box is not a finding by itself; the same box with an exposed admin path and an end-of-life component is. Doing that matching by hand across hundreds of hosts does not scale.

In the UI: Projects → New project → Import targets → CSV upload, then map the columns:

If you would rather automate it, the API pattern looks like this — endpoint path, payload keys and auth header are placeholders, so confirm each one against your version's API reference ( <verify in documentation> ):

export CVENGINE_URL = "https://cvengine.example.com" # your instance export CVENGINE_TOKEN = "<token-from-your-admin>" curl -sS -X POST " $CVENGINE_URL /api/v1/projects" \ -H "Authorization: Bearer $CVENGINE_TOKEN " \ -H "Content-Type: application/json" \ -d '{"name":"external-asm-example-corp","targets_file":"out/inventory.csv","profile":"external"}' Enter fullscreen mode Exit fullscreen mode Most deployments treat this request as idempotent per project name, so a re-run after a scope change updates the target list instead of creating duplicates — verify that on your own instance rather than assuming it. Check what landed:

curl -sS " $CVENGINE_URL /api/v1/projects" -H "Authorization: Bearer $CVENGINE_TOKEN " \ | jq -r '.[] | "\(.id) \(.name) \(.targets_count)"' Enter fullscreen mode Exit fullscreen mode You want a line like 42 external-asm-example-corp 318, where 318 equals wc -l out/inventory.csv minus the header row. A 401 here means the token is wrong, not that the project is missing.

Poll until the run reaches a completed state, then pull the findings:

curl -sS " $CVENGINE_URL /api/v1/projects/42/assessments" \ -H "Authorization: Bearer $CVENGINE_TOKEN " \ | jq -r '.[] | "\(.id) \(.status) \(.started_at)"' curl -sS " $CVENGINE_URL /api/v1/assessments/<assessment-id>/findings" \ -H "Authorization: Bearer $CVENGINE_TOKEN " -o out/findings.json jq -r '.[] | [.severity,.host,.title] | @tsv' out/findings.json | sort | head -n 20 Enter fullscreen mode Exit fullscreen mode The top of that list should read like a prioritised queue — highest severity first, host and title legible:

critical api.example.com Exposed administrative interface high www.example.com Outdated TLS configuration Enter fullscreen mode Exit fullscreen mode If CVEngine runs on hardware you control, size and harden that box before the first scan. The same deployment hygiene you would apply to any self-hosted service applies here too.

AI ranking orders your queue; it does not replace confirmation. A finding that survives a five-second manual check is a finding. One that does not is noise, and noise costs you the team's trust in the tool. So open the top entries by hand — hit the endpoint, read the TLS configuration, look for that exposed admin path — and only then assign an owner.

The scanner is the cheap part. What keeps an external attack surface assessment honest is the order of operations: written scope first, inventory second, AI correlation third, human confirmation last. Get that sequence right and a 90-minute run produces a queue your team can actually act on; skip a step and you produce a large file nobody trusts.

This article was originally published on AI Release — https://ai-release.org — and the channel at https://t.me/ai_release1 has more walkthroughs like this one.

Quelle: dev.to (dev.to). Original öffnen