Reverse Engineering a Custom Python Web Server: HackTheBox Obscurity Deep Dive

CTF Writeups Advanced 📅 Published: 30/08/2025

A comprehensive analysis of a vulnerable Python web server: from code review to exploitation, examining dangerous coding patterns and reverse engin...

Reverse Engineering a Custom Python Web Server: HackTheBox Obscurity Deep Dive

A comprehensive analysis of a vulnerable Python web server: from code review to exploitation, examining dangerous coding patterns and reverse engineering techniques.


The Art of Code Analysis: What Makes a Secure Application Vulnerable

When security researchers encounter a custom application, the first question isn't "How do I hack this?" but rather "How does this work, and where might the developer have made mistakes?" This mindset shift from pure exploitation to analytical thinking is what separates script kiddies from professional security researchers.

The HackTheBox "Obscurity" machine presents us with a perfect case study: a custom Python web server that, on the surface, appears functional but harbors critical security flaws. Let's walk through a systematic approach to analyzing unknown applications and identifying vulnerabilities through code review and dynamic analysis.

Learning Objectives: In this analysis, you'll learn how to approach unknown applications, perform effective code review, identify dangerous programming patterns, and understand the methodology behind responsible security research.

Phase 1: Reconnaissance and Information Gathering

Every security analysis begins with understanding your target. Like a detective examining a crime scene, we need to catalog what we're dealing with before we can understand how it might be vulnerable.

Network Service Discovery

Our first step is mapping the attack surface. Using network scanning tools, we identify what services are exposed:

nmap -sC -sV -oA nmap/initial 10.10.10.168
# Results: Port 22 (SSH) and Port 8080 (HTTP-like service)

The interesting finding here is port 8080 running what appears to be a custom Python web server. This immediately raises our interest because:

  • Custom implementations often lack the security scrutiny of established web servers
  • Python web servers can be vulnerable to code injection if not properly sanitized
  • Non-standard ports sometimes indicate development or testing environments with relaxed security

Application Fingerprinting

When we navigate to the web service, we discover something unusual in the page footer: "This server is running a custom Python script." This is a goldmine for security researchers because it tells us:

  1. We're dealing with custom code (higher likelihood of vulnerabilities)
  2. It's Python-based (suggests certain vulnerability classes)
  3. The developers are being transparent about their implementation (might provide more clues)

Research Methodology: Always examine page sources, HTTP headers, and any publicly disclosed information about the application. Developers sometimes inadvertently leak valuable information about their implementation choices.

Phase 2: Static Code Analysis - Deconstructing the Application

The breakthrough comes when we discover a link to the server's source code: SuperSecureServer.py. This is relatively rare in real-world penetration testing, but it provides us with an excellent opportunity to demonstrate static code analysis techniques.

Source Code Review Methodology

When analyzing any application source code, security researchers follow a systematic approach:

  1. Understand the architecture: How does data flow through the application?
  2. Identify entry points: Where does user input enter the system?
  3. Trace data paths: How is user input processed and used?
  4. Look for dangerous functions: Are there high-risk operations on user data?
  5. Check validation: How is input sanitized and validated?

The Critical Vulnerability: Understanding eval() Dangers

Our analysis reveals the application's fatal flaw in this code snippet:

# The vulnerable code pattern in SuperSecureServer.py
info = eval(f"'{path}'.format(path=path)")

This single line represents a catastrophic security failure. Let's break down why this is so dangerous:

Understanding the eval() Function

The eval() function in Python executes arbitrary Python code from a string. It's essentially giving the application the ability to run any Python command that an attacker can craft. This is like giving someone direct access to your Python interpreter.

The Format String Component

The format string operation (.format()) allows for complex string substitution. When combined with eval(), it creates a pathway for code injection. An attacker can craft URLs that result in arbitrary Python code execution.

Security Principle: Never use eval() on user-controlled input. This is considered one of the most dangerous anti-patterns in secure coding. Always look for safer alternatives like explicit parsing or whitelisting approaches.

Threat Modeling: What Can Go Wrong?

With this vulnerability identified, we can model potential attack scenarios:

  • Remote Code Execution: Arbitrary Python code execution on the server
  • File System Access: Reading sensitive files, configuration data
  • Network Pivoting: Using the server as a jumping point for internal networks
  • Privilege Escalation: If the service runs with elevated privileges
  • Data Exfiltration: Stealing databases, user information, or application data

Phase 3: Exploit Development - From Theory to Practice

Understanding a vulnerability theoretically is one thing; crafting a working exploit is another. Let's walk through the thought process of converting our static analysis findings into a practical attack.

Exploit Construction Methodology

Developing exploits requires understanding both the vulnerability and the constraints of the target environment. Our approach follows these steps:

Step 1: Understanding the Attack Vector

We know that the application uses eval() on a format string that includes the URL path. This means we need to craft a URL that, when processed, results in Python code execution. The challenge is bypassing any potential input validation and ensuring our payload executes correctly.

Step 2: Payload Design Principles

Our payload needs to:

  • Be valid within the context of a Python format string
  • Execute system commands without triggering errors
  • Be URL-encodable for web transmission
  • Provide a reliable way to receive command output

Step 3: Command Injection Techniques

For Python code injection, we have several approaches. One reliable method is using the __import__ builtin to access the os module:

# Basic command execution payload
__import__('os').system('ls -la')
# More sophisticated approach using subprocess for better output control
__import__('subprocess').check_output(['id'], shell=True)

Step 4: Format String Exploitation

The format string vulnerability allows us to break out of the intended string context. We craft a URL like:

# Conceptual payload structure
http://target:8080/{{payload}}
# Where payload becomes:
'{path}'.format(path=our_malicious_input)

This requires careful escaping and understanding of Python's string formatting mechanics.

Establishing Persistent Access

Once we achieve command execution, the next step is establishing a reliable shell. This involves:

  1. Setting up a listener: Preparing our attack machine to receive connections
  2. Crafting a reverse shell payload: Code that connects back to our listener
  3. Ensuring payload stability: Handling potential issues with shell connectivity

Ethical Note: This analysis is for educational purposes and authorized penetration testing only. Understanding these techniques helps developers write more secure code and helps defenders recognize attack patterns.

Phase 4: Post-Exploitation Analysis - Understanding System Internals

Once we establish initial access, the learning continues. Post-exploitation analysis teaches us about system administration practices, privilege models, and common security misconfigurations.

Local Privilege Escalation Research

With user-level access established, we now shift our analysis to understanding the local security model. This involves:

System Enumeration Methodology

  • User and Group Analysis: Understanding our current privileges and group memberships
  • SUID/SGID Binary Discovery: Finding executables that run with elevated privileges
  • Scheduled Task Analysis: Identifying automated processes that might be exploitable
  • Configuration File Review: Looking for hardcoded credentials or misconfigurations

Critical Discovery: The BetterSSH.py Script

Our enumeration reveals a custom script called BetterSSH.py with SUID permissions. This is significant because:

  1. SUID Execution: The script runs with root privileges regardless of who executes it
  2. Custom Implementation: Like our initial target, custom scripts often contain vulnerabilities
  3. Log File Dependencies: The script reads from log files, creating potential attack vectors

Advanced Attack Vector: Log Injection

The BetterSSH.py script demonstrates another dangerous programming pattern: trusting the integrity of log files. By analyzing the script's logic, we discover that it reads authentication attempts from a log file and uses this data to make security decisions.

This creates a log injection vulnerability where we can manipulate the log file to influence the script's behavior, ultimately leading to privilege escalation.

Security Lesson: Log files should never be trusted as authoritative sources for security decisions. Logs can be manipulated, corrupted, or forged by attackers with sufficient access.

Key Learning Outcomes and Defensive Strategies

This analysis demonstrates several critical security principles that apply far beyond this specific scenario:

For Developers: Secure Coding Practices

  • Never use eval() on user input: Always prefer explicit parsing and validation
  • Implement input sanitization: Validate and sanitize all user-provided data
  • Principle of least privilege: Run services with minimal required permissions
  • Secure logging practices: Don't make security decisions based on log file contents
  • Code review processes: Implement peer review to catch dangerous patterns

For Security Professionals: Analysis Methodology

  • Systematic approach: Follow a consistent methodology for application analysis
  • Static and dynamic analysis: Combine code review with runtime testing
  • Threat modeling: Understand potential attack scenarios before testing
  • Documentation: Maintain detailed records of findings and methodologies
  • Responsible disclosure: Report vulnerabilities through appropriate channels

For System Administrators: Hardening Strategies

  • Regular security audits: Periodically review custom applications and scripts
  • Privilege separation: Minimize the use of SUID/SGID executables
  • Log integrity: Implement log monitoring and integrity checking
  • Network segmentation: Isolate custom applications from critical systems
  • Security monitoring: Deploy intrusion detection for unusual activity

Conclusion: From Exploitation to Education

The "Obscurity" analysis demonstrates that security vulnerabilities often stem from fundamental misunderstandings of secure programming practices. The combination of eval() misuse and insecure privilege escalation patterns created multiple attack vectors that a skilled attacker could chain together for complete system compromise.

More importantly, this case study illustrates the methodology that security professionals use to analyze unknown applications systematically. By understanding these approaches, developers can think like attackers when reviewing their own code, and security professionals can improve their analysis techniques.

The goal of security research isn't just to break things—it's to understand why they break and how to build better, more secure systems. Every vulnerability discovered and responsibly disclosed makes the entire ecosystem more secure.

Remember: The techniques demonstrated here should only be used for authorized security testing, educational purposes, and improving defensive capabilities. Responsible security research helps make the digital world safer for everyone.