UofTCTF 2026
Firewall
Total Solver: 503/1736
uoftctf{f1rew4l1_Is_nOT_par7icu11rLy_R0bust_I_bl4m3_3bpf}
Overview Challenge / Idea
The objective of this challenge is to access and read the /flag.html file hosted on an Nginx server. However, the server is protected by an advanced firewall that leverages eBPF (Extended Berkeley Packet Filter) technology.
This firewall inspects all network trafficāboth ingress and egressāand blocks any packet containing the keyword "flag" or the "%" symbol. Participants must devise a method to bypass these restrictions to successfully retrieve the contents of the file.
Source Code Analysis
//firewall.c
<snippet>
#define KW_LEN 4
static const char blocked_kw[KW_LEN] = "flag";
static const char blocked_char = '%';
<snippet>
// Filter traffic
if (has_blocked_kw(skb, ETH_HLEN + ip_hdr_size, ip_tot_len - ip_hdr_size)) {
return TC_ACT_SHOT;
}
if (has_blocked_char(skb, ETH_HLEN + ip_hdr_size, ip_tot_len - ip_hdr_size)) {
return TC_ACT_SHOT;
}From this setup, it is clear that requests are limited to a maximum of three characters. Any request containing the keyword "flag" will be dropped by the firewall. Furthermore, attempts to bypass the restriction using encoding are also blocked, since encoded strings inherently include the "%" symbol, which is filtered as well
Solution
No-Quotes
uoftctf{w0w_y0u_5UcC355FU1Ly_Esc4p3d_7h3_57R1nG!}
Overview/Idea
The login mechanism is flawed: the source code reveals that SQL queries are constructed in an unsafe manner, leaving the application vulnerable to SQL Injection.
After successfully bypassing authentication, the application continues to expose insecure functionality through its template rendering engine. Improper handling of template functions introduces a Server-Side Template Injection (SSTI) vulnerability, which can be leveraged to execute arbitrary commands on the server.
Source Code Analysis
The WAF in this challenge only filters single(') and double quotes("), which can be bypassed using hex encoding, and since the SQL input is directly inserted into the query, authentication can be bypassed with a backslash escape (\) and a crafted UNION SELECT payload.
After login, insecure template rendering allows classic SSTI injection because the dot(.) operator is not blocked, so a payload such as {{ config.__class__.__init__.__globals__.os.popen('/readflag').read() }} can be used, encoded into hex to avoid quote restrictions.
Solution
Last updated