Two HTTP response headers that let a vulnerability scanner tell when several different URLs are actually served by the same backend code, so it can test that code once instead of hundreds of times.
This repository is the reference implementation and the experimental setup for the paper LogicAware: Enhancing Efficiency in Continuous Vulnerability Scanning through Backend Logic Identification.
A scanner crawling a site sees URLs, not code. /article/5, /article/9, and
/category/Technology look like three separate things worth testing
separately, so it fires its full payload set at each one. If all three are
handled by the same backend function, almost all of that traffic tests code
that was already tested. On a large site this is most of the scan: time,
bandwidth, and noise spent re-testing the same handler, while genuinely
distinct endpoints wait in the queue.
The backend answers two questions in every response.
X-Logic-ID says which backend logic handled this request:
X-Logic-ID: article-list-service-v1
Two URLs carrying the same value share an implementation. A scanner that has
already tested one can skip the other. Crucially, this is not something a
scanner can work out from the URL alone, /category/Science and /page/12
share a handler despite having no path segment in common.
X-Params-Coverage says how much of that handler's input surface this
particular request exercised:
X-Params-Coverage: 5/7
so a scanner can prefer the request that reaches the handler most completely, rather than skipping to the first one it happens to see.
A third header, X-Security-Scanner-ID, is sent by the scanner. By default the
backend only emits the two headers above to callers presenting a recognized
scanner identity, so this information is not exposed to the public internet.
| Folder | What it is |
|---|---|
flask-extension/ |
The reference implementation: a pip-installable Flask extension. This is the library. |
sample-app/ |
The 1,000-article demo news site the experiments were run against, plus the scanner-side analysis scripts. |
zap-extension/ |
Two OWASP ZAP scripts (a Passive Scan script that reads the headers and flags redundancy, an HTTP Sender script that presents the scanner identity), plus the full experimental data. |
burp-extension/ |
A Burp Suite Professional extension (Montoya API) that resolves and acts on redundancy live, inside a single continuous scan. |
Each folder has its own README with setup and usage details.
Measured against the same demo application, comparing a normal scan to one that acts on the LogicAware signal:
| Scanner | Without LogicAware | With LogicAware | Reduction |
|---|---|---|---|
| OWASP ZAP (n=3) | 196,752.7 ± 647.9 requests | 1,150.0 ± 0.0 | 99.42% |
| Burp Suite Pro, two-pass bridge (n=1) | 47,309 | 5,042 | 89.34% |
| Burp Suite Pro, live extension (n=3) | 47,309 | 3,747.3 ± 329.3 | 92.08% |
Two things worth stating plainly. First, these numbers are a direct function of
how much backend logic the demo application reuses across endpoints, which was
set by construction; a real application will show a smaller or larger effect in
proportion to its own reuse. Second, roughly 95% of the redundancy in this
particular demo is simple numeric-ID repetition (/article/5 vs /article/9)
that a URL-template heuristic could plausibly also catch. The remaining 4.7% is
the part only an explicit backend signal finds. Both figures are reported in
the paper rather than just the headline reduction.
Raw per-run data, scanner configuration, and the analysis scripts are in
zap-extension/experiment_log.csv and
zap-extension/test-results/.
Install the extension and run the demo site:
pip install -e ./flask-extension
cd sample-app && pip install -r requirements.txt
python news_site.pyThen request a page and look at the response headers:
curl -sI -H "X-Security-Scanner-ID: s4e-scanner-dev-01" http://127.0.0.1:5070/To add LogicAware to your own Flask app:
from flask_logicaware import LogicAware
logicaware = LogicAware(app, trusted_scanners={"your-scanner-id"})
@app.route("/article/<int:article_id>")
@logicaware.logic("article-view-service-v1", params=["article_id"])
def article_detail(article_id):
...Backends that cannot be modified directly can use the WSGI gateway mode
instead; see flask-extension/examples/gateway_example.py.
The scanner integrations are the reproducible part. Each has its own setup instructions:
- ZAP: load the two scripts from
zap-extension/into ZAP's Script Console (one as a Passive Scan rule, one as an HTTP Sender script), then crawl and scan the demo site. The README there documents the exact ZAP configuration used, including the spider settings that matter for determinism. - Burp: build the extension from
burp-extension/src/against Burp's own bundled Montoya API and load the resulting JAR. The README there also documents two earlier extension designs that did not work and why, which is probably more useful than the final code if you are writing your own.
This is research code released alongside a paper, not a maintained product. It works, it is tested, and it is small enough to read end to end, but it makes assumptions that suit the experiment (single logic id per response path in the Burp extension, scalar coverage comparison rather than set comparison when choosing a representative request). The paper's formal model section is explicit about where the implementations approximate the model.
MIT. See LICENSE.