參考
Web安全之SQL注入攻擊技巧與防范
總結(jié) XSS 與 CSRF 兩種跨站攻擊
CSRF的攻擊與防御
CSRF 攻擊的應(yīng)對(duì)之道
一陨亡、SQL注入
用Web網(wǎng)站中常用的會(huì)員登錄系統(tǒng)來做一個(gè)場(chǎng)景實(shí)例。如果輸入正確的用戶名 plhwin 和密碼 123456楞艾,執(zhí)行的SQL語句為:SELECT uid,username FROM user WHERE username='plhwin' AND password='...'
但如果有搗蛋鬼輸入的用戶名為 plhwin' AND 1=1-- hack诅愚,密碼隨意輸入李破,比如aaaaaa,那么拼接之后的SQL查詢語句就變成了如下內(nèi)容:SELECT uid,username FROM user WHERE username='plhwin' AND 1=1-- hack' AND password='...'
垫蛆。執(zhí)行上面的SQL語句禽最,因?yàn)?=1是永遠(yuǎn)成立的條件,這意味著黑客只需要知道別人的會(huì)員名袱饭,無需知道密碼就能順利登錄到系統(tǒng)弛随。
解決方式:
- 檢查變量數(shù)據(jù)類型和格式
- 過濾特殊符號(hào)
- 參數(shù)化查詢,使用預(yù)編譯語句
二宁赤、XSS
XSS 全稱“跨站腳本”舀透,是注入攻擊的一種。其特點(diǎn)是不對(duì)服務(wù)器端造成任何傷害决左,而是通過一些正常的站內(nèi)交互途徑愕够,例如發(fā)布評(píng)論走贪,提交含有 JavaScript 的內(nèi)容文本。這時(shí)服務(wù)器端如果沒有過濾或轉(zhuǎn)義掉這些腳本惑芭,作為內(nèi)容發(fā)布到了頁面上坠狡,其他用戶訪問這個(gè)頁面的時(shí)候就會(huì)運(yùn)行這些腳本。
運(yùn)行預(yù)期之外的腳本帶來的后果有很多中遂跟,可能只是簡(jiǎn)單的惡作劇——一個(gè)關(guān)不掉的窗口:
while (true) {
alert("你關(guān)不掉我~");
}
也可以是盜號(hào)或者其他未授權(quán)的操作逃沿。每個(gè)訪問到含有該評(píng)論的頁面的用戶都會(huì)遇到麻煩——他們不知道背后正悄悄的發(fā)起了一個(gè)請(qǐng)求,是他們所看不到的幻锁。而這個(gè)請(qǐng)求凯亮,會(huì)把包含了他們的帳號(hào)和其他隱私的信息發(fā)送到收集服務(wù)器上。
解決方式:過濾輸入和轉(zhuǎn)義輸出哄尔。
三假消、CSRF
CSRF攻擊原理比較簡(jiǎn)單,如圖1所示岭接。其中Web A為存在CSRF漏洞的網(wǎng)站富拗,Web B為攻擊者構(gòu)建的惡意網(wǎng)站,User C為Web A網(wǎng)站的合法用戶鸣戴。
- 用戶C打開瀏覽器啃沪,訪問受信任網(wǎng)站A,輸入用戶名和密碼請(qǐng)求登錄網(wǎng)站A窄锅;
- 在用戶信息通過驗(yàn)證后谅阿,網(wǎng)站A產(chǎn)生Cookie信息并返回給瀏覽器,此時(shí)用戶登錄網(wǎng)站A成功酬滤,可以正常發(fā)送請(qǐng)求到網(wǎng)站A;
- 用戶未退出網(wǎng)站A之前寓涨,在同一瀏覽器中盯串,打開一個(gè)TAB頁訪問網(wǎng)站B;
- 網(wǎng)站B接收到用戶請(qǐng)求后戒良,返回一些攻擊性代碼体捏,并發(fā)出一個(gè)請(qǐng)求要求訪問第三方站點(diǎn)A;
- 瀏覽器在接收到這些攻擊性代碼后糯崎,根據(jù)網(wǎng)站B的請(qǐng)求几缭,在用戶不知情的情況下攜帶Cookie信息,向網(wǎng)站A發(fā)出請(qǐng)求沃呢。網(wǎng)站A并不知道該請(qǐng)求其實(shí)是由B發(fā)起的年栓,所以會(huì)根據(jù)用戶C的Cookie信息以C的權(quán)限處理該請(qǐng)求,導(dǎo)致來自網(wǎng)站B的惡意代碼被執(zhí)行薄霜。
再舉個(gè)例子某抓,一論壇網(wǎng)站的發(fā)貼是通過 GET 請(qǐng)求訪問纸兔,點(diǎn)擊發(fā)貼之后 JS 把發(fā)貼內(nèi)容拼接成目標(biāo) URL 并訪問: http://example.com/bbs/create_post.php?title=標(biāo)題&content=內(nèi)容
那么,我只需要在論壇中發(fā)一帖否副,包含一鏈接: http://example.com/bbs/create_post.php?title=我是腦殘&content=哈哈
只要有用戶點(diǎn)擊了這個(gè)鏈接汉矿,那么他們的帳戶就會(huì)在不知情的情況下發(fā)布了這一帖子”纲鳎可能這只是個(gè)惡作劇洲拇,但是既然發(fā)貼的請(qǐng)求可以偽造,那么刪帖曲尸、轉(zhuǎn)帳赋续、改密碼、發(fā)郵件全都可以偽造队腐。
如何解決這個(gè)問題蚕捉,我們是否可以效仿上文應(yīng)對(duì) XSS 的做法呢?過濾用戶輸入柴淘, 不允許發(fā)布這種含有站內(nèi)操作 URL 的鏈接迫淹。這么做可能會(huì)有點(diǎn)用,但阻擋不了 CSRF为严,因?yàn)楣粽呖梢酝ㄟ^ QQ 或其他網(wǎng)站把這個(gè)鏈接發(fā)布上去敛熬,為了偽裝可能還使用 bit.ly 壓縮一下網(wǎng)址,這樣點(diǎn)擊到這個(gè)鏈接的用戶還是一樣會(huì)中招第股。所以對(duì)待 CSRF 应民,我們的視角需要和對(duì)待 XSS 有所區(qū)別。CSRF 并不一定要有站內(nèi)的輸入夕吻,因?yàn)樗⒉粚儆谧⑷牍艋迩拢钦?qǐng)求偽造。被偽造的請(qǐng)求可以是任何來源涉馅,而非一定是站內(nèi)归园。所以我們唯有一條路可行,就是過濾請(qǐng)求的處理者稚矿。
比較頭痛的是庸诱,因?yàn)檎?qǐng)求可以從任何一方發(fā)起,而發(fā)起請(qǐng)求的方式多種多樣晤揣,可以通過 iframe桥爽、ajax(這個(gè)不能跨域,得先 XSS)昧识、Flash 內(nèi)部發(fā)起請(qǐng)求(總是個(gè)大隱患)钠四。由于幾乎沒有徹底杜絕 CSRF 的方式,我們一般的做法跪楞,是以各種方式提高攻擊的門檻形导。
首先可以提高的一個(gè)門檻环疼,就是改良站內(nèi) API 的設(shè)計(jì)。對(duì)于發(fā)布帖子這一類創(chuàng)建資源的操作朵耕,應(yīng)該只接受 POST 請(qǐng)求炫隶,而 GET 請(qǐng)求應(yīng)該只瀏覽而不改變服務(wù)器端資源。當(dāng)然阎曹,最理想的做法是使用REST 風(fēng)格 的 API 設(shè)計(jì)伪阶,GET、POST处嫌、PUT栅贴、DELETE 四種請(qǐng)求方法對(duì)應(yīng)資源的讀取、創(chuàng)建熏迹、修改檐薯、刪除。現(xiàn)在的瀏覽器基本不支持在表單中使用 PUT 和 DELETE 請(qǐng)求方法注暗,我們可以使用 ajax 提交請(qǐng)求(例如通過 jquery-form 插件坛缕,我最喜歡的做法),也可以使用隱藏域指定請(qǐng)求方法捆昏,然后用 POST 模擬 PUT 和 DELETE (Ruby on Rails 的做法)赚楚。這么一來,不同的資源操作區(qū)分的非常清楚骗卜,我們把問題域縮小到了非 GET 類型的請(qǐng)求上——攻擊者已經(jīng)不可能通過發(fā)布鏈接來偽造請(qǐng)求了宠页,但他們?nèi)钥梢园l(fā)布表單,或者在其他站點(diǎn)上使用我們?nèi)庋鄄豢梢姷谋韱慰懿郑诤笈_(tái)用 js 操作举户,偽造請(qǐng)求。
接下來我們就可以用比較簡(jiǎn)單也比較有效的方法來防御 CSRF遍烦,這個(gè)方法就是“請(qǐng)求令牌”俭嘁。讀過《J2EE 核心模式》的同學(xué)應(yīng)該對(duì)“同步令牌”應(yīng)該不會(huì)陌生,“請(qǐng)求令牌”和“同步令牌”原理是一樣的乳愉,只不過目的不同,后者是為了解決 POST 請(qǐng)求重復(fù)提交問題屯远,前者是為了保證收到的請(qǐng)求一定來自預(yù)期的頁面蔓姚。實(shí)現(xiàn)方法非常簡(jiǎn)單,首先服務(wù)器端要以某種策略生成隨機(jī)字符串慨丐,作為令牌(token)坡脐,保存在 Session 里。然后在發(fā)出請(qǐng)求的頁面房揭,把該令牌以隱藏域一類的形式备闲,與其他信息一并發(fā)出晌端。在接收請(qǐng)求的頁面,把接收到的信息中的令牌與 Session 中的令牌比較恬砂,只有一致的時(shí)候才處理請(qǐng)求咧纠,否則返回 HTTP 403 拒絕請(qǐng)求或者要求用戶重新登錄驗(yàn)證身份。
以下參考我想知道token和sessionid的區(qū)別是什么
PrideChung 2013-08-23 15:41:03 +08:00
搞清楚CSRF攻擊的原理就行了泻骤。session id能夠標(biāo)識(shí)一個(gè)用戶漆羔,卻無法知道該用戶提交的表單是自愿主動(dòng)提交的,還是被騙去點(diǎn)了個(gè)鏈接狱掂,被惡意的JS提交的演痒,所以才需要CSRF token。
zzNucker 2013-08-25 13:51:17 +08:00
@leonwong 就算是CSRF劫持的請(qǐng)求也會(huì)帶上網(wǎng)站的cookie的趋惨,所以光驗(yàn)證session并不能避免CSRF鸟顺。 token的關(guān)鍵是在于你在發(fā)送請(qǐng)求的時(shí)候一定要保證你是讀取了這個(gè)頁面的。器虾。 而不是憑空就發(fā)送請(qǐng)求
etata 40 天前
@binux
還是沒說為什么用 token 讯嫂,不用 sessionid 啊。既然唯一 id 曾撤,放在 cookies 也是放端姚,放在 hidden 里也是放。再說 sessionid 在 cookies 禁止的時(shí)候也是放在 url 中或者表單中啊挤悉。 為什么不統(tǒng)一用一個(gè)呢渐裸?
binux 40 天前
@etata 唯一 id 一般是固定的, token 可以不是固定的装悲,而是每次訪問隨機(jī)生成的昏鹃。當(dāng)然你要把 seesionid 用作 token 也不是不可以。