LFImap tests file-inclusion inputs using a prepared URL, URL list or HTTP request. The useful work starts before the scan: identify the actual parameter, preserve the legitimate request and understand what the application does with the value.
This guide combines the tool reference with the existing local lfi-basic comparison. A readable file, interpreted PHP and a network callback are separate outcomes; do not infer one from another.
Tool setup and support status
The upstream README describes LFImap as pre-alpha and marks CSRF support as beta/testing. Pin the checkout you evaluate and record its revision. The repository layout matters: the current script lives under lfimap/.
git clone https://github.com/hansmach1ne/LFImap.git
cd LFImap
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python lfimap/lfimap.py --help
git rev-parse HEADThe options here were checked against upstream source. Dependency installation and an actual scan are separate checks; the example does not guarantee compatibility with every Python release.
Quick reference
| Task | Option | Constraint |
|---|---|---|
| Single URL | -U | Uppercase |
| URL list | -F | One prepared URL per line |
| Raw HTTP request | -R | Save a real HTTP request, not a shell cURL command |
| Cookie header | -C | Use a disposable authorized session |
| Form data | -D | Preserve required fields |
| Extra header | -H | Repeatable in the current parser |
| Method | -M | Match the endpoint's legitimate request |
| Proxy | -P | Inspect local request construction |
| User-Agent / Referer | --useragent, --referer | Request values, not proof of authorization |
| Input marker | --placeholder | Default marker is PWN |
| Delay | --delay | Milliseconds between requests |
| Response timeout | --max-timeout | Seconds; documented default 5 |
| Expected status | --http-ok | Does not make a response a confirmed finding |
| Quick mode | -q | Fewer payloads, reduced coverage |
| Request log | --log | Treat the output as potentially sensitive |
| Verbose output | -v | Useful for diagnosing request preparation |
The upstream options also distinguish individual technique flags: filter (-f), input (-i), data (-d), expect (-e), file (-file), traversal (-t), remote inclusion (-r), command injection (-c) and heuristics (-heur). -a selects all supported techniques. A narrower local check is easier to interpret than treating every technique as interchangeable.
Request preparation
A PWN marker makes the intended position explicit. The implementation can also discover parameters without that marker; it is not a universal requirement for every input mode. Before any scan, ensure the request works normally with a known, permitted page value.
A raw local request has a method line, headers, a blank line and any body. For example, the existing lab's raw include endpoint can be represented as:
GET /view-raw.php?page=PWN HTTP/1.1
Host: 127.0.0.1:8084
Connection: close
For a POST endpoint, preserve its content type and required fields. A request copied as cURL must be converted into raw HTTP before being used with -R; the two formats are not interchangeable.
When a local request behaves unexpectedly, inspect what was sent and what the endpoint received. URL encoding, a missing field or a changed session can explain a difference without a vulnerability.
Authentication and prerequisites
A cookie captures session state, not the login process. If the session expires, refresh it legitimately in the disposable lab environment. Avoid putting production credentials into command history or request files. Restrict permissions on captured requests and logs, and remove them when the exercise is finished.
The CSRF flags describe token URL, method, parameter and optional data. Upstream implements token handling with assumptions about the request and response; beta support is not a guarantee that every rotating token, JavaScript login or multi-step workflow works. Inspect the resulting requests before drawing conclusions.
Second-order request options identify a follow-up URL, method and data. They matter only when the application's own flow stores input and renders it later. Do not assume a second request is necessary for an ordinary include endpoint.
Existing local-lab walkthrough
The LFI-basic lab source contains two different sinks:
| Endpoint | Application behavior | Why the difference matters |
|---|---|---|
/view.php?page=pages/about | Appends .php before including | A supplied path resolves with that suffix |
/view-raw.php?page=pages/about.php | Includes the supplied value | No fixed suffix is appended |
Start the existing lab with its loopback binding:
git clone https://github.com/ishankaru/techearl-labs.git
cd techearl-labs
docker compose up lfi-basicObserve the intended page in each route first:
curl -s 'http://127.0.0.1:8084/view.php?page=pages/about'
curl -s 'http://127.0.0.1:8084/view-raw.php?page=pages/about.php'Read the endpoint source alongside the responses. A path that the raw route can resolve may fail when the other route appends .php. This difference explains a result; it does not establish that the suffix-appended endpoint is safe.
The existing tutorial's bounded filter-wrapper check can be run from the LFImap repository:
python lfimap/lfimap.py \
-U 'http://127.0.0.1:8084/view.php?page=PWN' -fRecord the request, response and exact versions from your own run. This guide does not present an invented HIT/FAIL transcript. Verify that any reported content belongs to the disposable lab before describing it as source disclosure.
What the PHP behavior means
include() evaluates PHP blocks in a readable file; text outside those blocks can appear in output. php://filter applies a stream filter to the resource being read. A base64-encoded response can preserve source bytes as data instead of having include() interpret those bytes as PHP. PHP include, PHP stream wrappers.
Do not generalize a working wrapper to every parser configuration. The local lab intentionally enables settings that ordinary applications should not need. allow_url_include controls relevant URL-style includes; switching it off does not repair arbitrary local-path inclusion. File permissions and the exact include expression still matter. PHP filesystem configuration.
The old tutorial also discussed log inclusion. Preserve the prerequisite: the web process must be able to read the log, and the include path must reach it. Giving the web user log-reader group membership expands that exposure. A readable log or a matched scanner signature does not, by itself, establish code execution.
Finish the exercise
Stop and remove only this disposable lab container:
docker compose stop lfi-basic
docker compose rm -f lfi-basicKeep your written observations, not secrets or captured session files. No remote target or callback service is needed to understand the two local path-resolution cases.
Limitations and manual verification
LFImap's result is constrained by its input, techniques and classification. A timeout, generic error or reflected marker can produce an ambiguous signal. A scan that finds nothing may have exercised the wrong parameter or an unauthenticated page.
Use manual HTTP requests to understand one known input/output pair. Use a request inspector when headers or tokens are complex. Use the scanner for a defined set of checks after the baseline is understood. A fixed scan-duration promise is not useful: request count, endpoint behavior and environment all change it.
Keep evidence of the legitimate response, the tested request and the observed difference. For a source-backed finding, identify the exact include statement and the permissions/configuration that made the result possible.
Repair the include boundary
Map a small set of public page identifiers to fixed application-owned paths. Do not put the client's path directly into include():
$pages = [
'about' => __DIR__ . '/pages/about.php',
'help' => __DIR__ . '/pages/help.php',
];
$page = $_GET['page'] ?? 'about';
if (!is_string($page) || !isset($pages[$page])) {
http_response_code(404);
exit;
}
require $pages[$page];This example changes the public input to a page identifier. Apply authorization before selecting restricted pages. Keep upload and log directories outside this map, keep the web process's filesystem privileges narrow, and remove unnecessary URL-inclusion features.
For regression tests, assert that known IDs render, unknown IDs are rejected and request values never choose arbitrary filesystem paths. The path traversal guide covers the conceptual issue; the separate filter-wrapper, input-wrapper and log-inclusion guides describe their distinct prerequisites.
Sources
Authoritative references this article was fact-checked against.
- LFImap — upstream READMEgithub.com
- LFImap — argument definitionsgithub.com
- LFImap — parameter selection and request flowgithub.com
- PHP — include behaviorphp.net
- PHP — stream wrappersphp.net
- PHP — filesystem configurationphp.net
- LFI-basic — local teaching labgithub.com





