摘要:攻擊實(shí)驗(yàn)攻擊涉及用戶受害者受信任的網(wǎng)站和惡意網(wǎng)站。攻擊包括一系列步驟,如下受害者用戶使用他她的用戶名和密碼登錄到可信站點(diǎn)從而創(chuàng)建一個(gè)新的會(huì)話。瀏覽器將自動(dòng)連接會(huì)話,因?yàn)樗菒阂獾囊筢槍?duì)可信站點(diǎn)。
CSRF攻擊實(shí)驗(yàn)
CSRF攻擊涉及用戶受害者,受信任的網(wǎng)站和惡意網(wǎng)站。當(dāng)受害者與受信任的站點(diǎn)擁有一個(gè)活躍的會(huì)話同時(shí),如果訪問(wèn)惡意網(wǎng)站,惡意網(wǎng)站會(huì)注入一個(gè)HTTP請(qǐng)求到為受信任的站點(diǎn),從而破話用戶的信息。
CSRF 攻擊總是涉及到三個(gè)角色:信賴的網(wǎng)站(Collabtive)、受害者的 session 或 cookie 以及一個(gè)惡意網(wǎng)站。受害者會(huì)同時(shí)訪問(wèn)惡意網(wǎng)站與受信任的站點(diǎn)會(huì)話的時(shí)候。攻擊包括一系列步驟,如下:
受害者用戶使用他/她的用戶名和密碼登錄到可信站點(diǎn),從而創(chuàng)建一個(gè)新的會(huì)話。
受信任站點(diǎn)存儲(chǔ)受害者會(huì)話的 cookie 或 session 在受害者用戶的 web 瀏覽器端。
受害者用戶在不退出信任網(wǎng)站時(shí)就去訪問(wèn)惡意網(wǎng)站。
惡意網(wǎng)站的網(wǎng)頁(yè)發(fā)送一個(gè)請(qǐng)求到受害者的受信任的站點(diǎn)用戶的瀏覽器。
web 瀏覽器將自動(dòng)連接會(huì)話 cookie,因?yàn)樗菒阂獾囊筢槍?duì)可信站點(diǎn)。
受信任的站點(diǎn)如果受到 CSRF 攻擊,攻擊者的一些惡意的請(qǐng)求會(huì)被攻擊者發(fā)送給信任站點(diǎn)。
惡意網(wǎng)站可以建立HTTP GET或POST請(qǐng)求到受信任的站點(diǎn)。一些HTML標(biāo)簽,比如img iframe,框架,形式?jīng)]有限制的URL,可以在他們的使用屬性中。
環(huán)境搭建 服務(wù)器我使用的是koa框架作為后端框架搭建的服務(wù)器,順便也算是學(xué)習(xí)一下koa框架,之前沒(méi)有學(xué)過(guò),由于是初學(xué),搭建過(guò)程有點(diǎn)漫長(zhǎng)
話不多說(shuō)上代碼:
// app.js const Koa = require("koa"); const app = new Koa(); const server = require("koa-static"); const router = require("koa-router")(); const PouchDB = require("pouchdb"); const db = new PouchDB("http://localhost:5984/csrf"); app.use(async (ctx, next) => { console.log(`Process ${ctx.request.method} ${ctx.request.url}...`); await next(); }); // add url-route: router.post("/login", async (ctx, next) => { let postData = await parsePostData( ctx ); try { let response = await db.get(`id_${postData.name}`); let exp = new Date(); ctx.cookies.set( "id", `id_${postData.name}`, { domain: "localhost", // 寫(xiě)cookie所在的域名 path: "/userInfo.html", // 寫(xiě)cookie所在的路徑 maxAge: 24*60*60*1000, // cookie有效時(shí)長(zhǎng) expires: exp.setTime(exp.getTime() + 24*60*60*1000), // cookie失效時(shí)間 httpOnly: false, // 是否只用于http請(qǐng)求中獲取 overwrite: false // 是否允許重寫(xiě) } ) if(response.password === postData.password) ctx.redirect("userInfo.html") } catch (err) { ctx.body = "登錄失敗,點(diǎn)擊這里返回
"; } }); router.post("/regist", async (ctx, next) => { let postData = await parsePostData( ctx ); postData._id = `id_${postData.name}`; try { let response = await db.put(postData); ctx.body = "注冊(cè)成功,點(diǎn)擊這里返回至登錄界面
"; } catch (err) { ctx.body = "用戶名已存在,點(diǎn)擊這里返回
"; } }); router.post("/getUserInfo", async (ctx, next) => { let postData = await parsePostDataFromAjax( ctx ); let _id = {}; _id[postData.split(":")[0]] = postData.split(":")[1]; try { let doc = await db.get(_id.id); ctx.body = doc; } catch (err) { ctx.body = "發(fā)生錯(cuò)誤"; } }); router.post("/change", async (ctx, next) => { let postData = await parsePostData( ctx ); console.log(postData); try { let doc = await db.get(postData.id); let response = await db.put({ _id: doc._id, _rev: doc._rev, name: postData.name, password: doc.password, sex: postData.sex, desc: postData.desc }); ctx.body = "修改成功,點(diǎn)擊這里返回至登錄界面
"; } catch (err) { console.log(err); } }); app.use(router.routes()); app.use(server(__dirname + "/")); app.listen(3001); /** * * 對(duì)于POST請(qǐng)求的處理,koa2沒(méi)有封裝獲取參數(shù)的方法, * 需要通過(guò)解析上下文context中的原生node.js請(qǐng)求 * 對(duì)象req,將POST表單數(shù)據(jù)解析成query string(例 * 如:a=1&b=2&c=3),再將query string 解析成 * JSON格式(例如:{"a":"1", "b":"2", "c":"3"}) */ // 解析上下文里node原生請(qǐng)求的POST參數(shù),這個(gè)是處理表單form傳入?yún)?shù) function parsePostData( ctx ) { return new Promise((resolve, reject) => { try { let postdata = ""; ctx.req.addListener("data", (data) => { postdata += data }) ctx.req.addListener("end",function(){ let parseData = parseQueryStr( postdata ) resolve( parseData ) }) } catch ( err ) { reject(err) } }) } // 解析上下文里node原生請(qǐng)求的POST參數(shù),這個(gè)是處理Ajax傳入?yún)?shù) function parsePostDataFromAjax( ctx ) { return new Promise((resolve, reject) => { try { let postdata = ""; ctx.req.addListener("data", (data) => { postdata += data }) ctx.req.addListener("end",function(){ resolve( postdata ) }) } catch ( err ) { reject(err) } }) } // 將POST請(qǐng)求參數(shù)字符串解析成JSON function parseQueryStr( queryStr ) { let queryData = {} let queryStrList = queryStr.split("&"); for ( let [ index, queryStr ] of queryStrList.entries() ) { let itemList = queryStr.split("=") queryData[ itemList[0] ] = decodeURIComponent(itemList[1]) } return queryData }
就這一個(gè)文件,里面包含了很多東西
koa-static是koa的一個(gè)中間件,用于獲取靜態(tài)文件的
koa-router是koa的一個(gè)中間件,用于路由系統(tǒng)
pouchDB是我使用的couchDB的配套使用的框架
數(shù)據(jù)庫(kù)我使用的是couchDB數(shù)據(jù)庫(kù),具體怎么使用看這里,用法很簡(jiǎn)單,他的界面是一個(gè)網(wǎng)頁(yè)
前端頁(yè)面前端頁(yè)面總共有三個(gè),分別是index.html,regist.html,userInfo.html,其作用分別是登錄,注冊(cè),展示/修改用戶信息,我這里沒(méi)有使用css樣式。。。有點(diǎn)丑
index.html注冊(cè) regist.html登錄 登錄
登錄 userInfo.html注冊(cè) 注冊(cè)
這個(gè)頁(yè)面我使用了ajax,所以引入了jQuery
用戶信息 用戶信息
姓名:性別:描述:修改信息
最后放上package.json
{ "name": "csrf", "version": "1.0.0", "description": "", "main": "app.js", "scripts": { "start": "node app.js" }, "author": "", "license": "ISC", "devDependencies": { "koa": "^2.2.0", "koa-router": "^7.2.1", "koa-static": "^3.0.0", "pouchdb": "^6.2.0" } }
命令行執(zhí)行
npm install npm startCSRF攻擊
終于到了關(guān)鍵,其實(shí)也就那么一剎那,很快我們的步驟如下:
首先我注冊(cè)了一個(gè)賬戶,然后我登錄這個(gè)賬戶查看信息,以及他的cookie參數(shù),在圖中我們發(fā)現(xiàn)cookie里面有一個(gè)重要信息是ID,這個(gè)就是當(dāng)前用戶的ID
接下來(lái)我通過(guò)瀏覽器開(kāi)發(fā)者工具查看表單數(shù)據(jù)以及請(qǐng)求的url以方便我構(gòu)造假請(qǐng)求
編寫(xiě)csrf_hack.html
攻擊頁(yè)面 這是一個(gè)攻擊頁(yè)面
``` 4. 然后在啟動(dòng)一個(gè)服務(wù),將剛才編寫(xiě)的csrf_hack.html頁(yè)面放進(jìn)去,然后訪問(wèn)這個(gè)頁(yè)面(這里我偷懶,直接把剛才的端口修改了一個(gè),然后另開(kāi)一個(gè)控制臺(tái)啟動(dòng)服務(wù),然后訪問(wèn)),接下來(lái)再次登錄剛才的賬號(hào),發(fā)現(xiàn)剛才寫(xiě)在csrf_hack.html頁(yè)面的信息更替上去了 注意事項(xiàng) 1. 如果要使用async,await這兩個(gè)node版本需要在7以上
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/11258.html
摘要:瀏覽器對(duì)這種行為進(jìn)行了限制。大多數(shù)情況下,該請(qǐng)求會(huì)失敗,因?yàn)樗蟮恼J(rèn)證信息。在請(qǐng)求頭中添加自定義例如在知乎中給文章點(diǎn)贊結(jié)合中對(duì)的的介紹,知乎的這種方式被稱為。 概念 CSRF,Cross Site Request Forgery,跨站請(qǐng)求偽造。 為什么跨站的請(qǐng)求需要偽造? 因?yàn)闉g覽器實(shí)現(xiàn)了同源策略,這里可以將站和源視為同一個(gè)概念。 同源策略 The same-origin polic...
摘要:更新嘗試了一下實(shí)現(xiàn)前后端分離,新的文章如下前后端分離之初試更新可另外用實(shí)現(xiàn)前后端分離,這篇文章可能局限性太大,只是個(gè)人的入門(mén)實(shí)踐剛剛學(xué)習(xí)前端快一年,后臺(tái)方面了解甚少,于是決定踩踩坑,學(xué)習(xí)一下。 2018.9.6更新:嘗試了一下REST framework實(shí)現(xiàn)前后端分離,新的文章如下Django前后端分離之REST framework初試 2018.8.27更新:可另外用 restful...
閱讀 2063·2021-11-24 09:38
閱讀 3404·2021-11-22 12:07
閱讀 1976·2021-09-22 16:03
閱讀 2051·2021-09-02 15:41
閱讀 2691·2021-07-24 23:28
閱讀 2292·2019-08-29 13:17
閱讀 1603·2019-08-29 12:25
閱讀 2720·2019-08-29 11:10