Graph Writeup - Proving Grounds
Created October 7, 2026 • Last updated October 7, 2026 • 3 min read
Graph exposes a GraphQL API backed by SQLite. A searchTerm argument is injectable, which dumps user password hashes to crack for SSH access as jane. A custom pass-gen binary runnable via sudo writes to /etc/shadow without stripping newlines, so a newline injection adds a controlled account, leads to the shadow group, and ends in cracking the root hash.
Reconnaissance
Nmap
Scan all TCP ports and fingerprint the services.
PORT STATE SERVICE 22/tcp open ssh 80/tcp open http
Explain command
| -p- | Scan all 65535 TCP ports. |
| -sCV | Run the default scripts and probe service versions. |
SSH and a blog on port 80. Fuzz for content.
Content discovery
Brute force directories.
/graphql (Status: 200)
A /graphql endpoint is exposed.
Exploitation
GraphQL SQL injection
Introspect the schema with inql. The users query takes a searchTerm argument that is passed into a SQLite query without validation, so a single quote triggers an error.
{"data":{"users":["admin","jane"]}}
# single quote triggers a SQLite error:
{"errors":[{"message":"SQLITE_ERROR: unrecognized token: \"'\""}]}
Confirm the injection, then UNION-dump the user hashes from the users table.
{"data":{"users":["admin:$6$PRyGjElQ$unCSC...","jane:$6$4BlcfbYDsQp3BMG$vwPo...","josh:$6$g744Ii0AvY$Oce4..."]}}
Crack the SHA-512 hashes with hashcat.
$6$4BlcfbYDsQp3BMG$vwPo...:$JANE_PASSWORD
Explain command
| -m 1800 | sha512crypt hash mode. |
jane's password is recovered. Log in over SSH.
jane@graph:~$ id uid=1000(jane) gid=1000(jane) groups=1000(jane)
Shell as jane. Check the sudo rights.
Privilege Escalation
Newline injection in sudo pass-gen
List the sudo rights.
User jane may run the following commands on graph:
(ALL : ALL) /usr/local/bin/pass-gen
pass-gen runs as root and updates /etc/shadow without stripping newlines, so its argument can inject a whole new shadow line. Generate a hash, then add a shadow entry for josh (a member of the shadow group).
Switch to josh, who is in the shadow group, read /etc/shadow, and crack the root hash with hashcat. The recovered root password then lets su return a root shell.
josh@graph:/$ su Password: root@graph:/# id uid=0(root) gid=0(root) groups=0(root)
Cracking the root hash read via the shadow group gives the root password and a root shell.