WEB安全基礎
作者:adrain 原文地址:WEB安全基礎 - 知乎專欄
前言
安全事件頻發,安全漏洞層出不窮,sql注入、xss跨站攻擊等各種漏洞是怎麼產生的,怎樣從根源上減少這些安全漏洞的出現,本文著重介紹了一些常見的,但是開發又很容易忽視的點。主要包括了跨域漏洞、針對伺服器的注入攻擊等,配合一些案例對漏洞產生的原因和修復方法進行了介紹。
攻擊方式
針對web的攻擊,主要分為前端攻擊方式和伺服器端攻擊方式
前端的攻擊方式比較常見的有XSS、CSRF、點擊劫持等
後端的攻擊方式比較常見的是注入類攻擊、上傳類攻擊、認證攻擊
下面分別對出現比較多的漏洞一一做下介紹
跨站攻擊
在介紹這些漏洞之前,首先說一下最重要也是最基本的安全功能——同源策略
瀏覽器的同源策略、限制了來自不同源的document或腳本,對當前的document讀取或設置某些屬性
同源的幾個因素:host、子域名、埠、協議
在web開發中經常會用到第三方域的資源,標籤<script>、<img>、<iframe>、<link>等都是可以跨域載入資源的,而不受同源策略的限制。當然也是可以用來繞過同源策略。
現在跨站攻擊並不單單是xss攻擊,還有其他很多形式的跨站攻擊類型
跨站裡面最多的就是跨站腳本也就是XSS,這個不管是多大的站點都會遇到,XSS大家都知道分為三種:反射、存儲、DOM型,之間的差別大家應該都知道了,下面說下在代碼方面形成漏洞的原因
最根本的原因就是沒有對用戶的輸入進行過濾,在防護安全方面,大家記住一點就是:永遠不要相信用戶輸入的內容
最簡單的漏洞代碼:
$input =$_GET["param"];necho "<div>".$input."</div>";n
用戶只要向param提交數據就可以展示到頁面上,那要是提交<script>腳本,那麼就能利用這個js腳本去做一些危害性的操作了
其實所有的xss歸根到底就是上面這段代碼,不管怎麼變化,用戶輸入的信息能展示到頁面上來
這裡我們從xsspayload入手,看代碼如何防範xss漏洞的發生
xsspayload 鏈接地址:HTML5 Security Cheatsheet,裡面包括了大部分的xss利用代碼
這種開發遇到的最多,對於這個也是有成熟的修復方案——轉義、編碼處理,對於常見的不再過多關注,但是要注意不同地方的xss是有不同的處理方式的,修復方案我們放到了wiki上面,大家可以參考:內部地址。。。。
下面介紹一些不常見的跨域漏洞
- flash跨域
這個在很多網站都是被忽視的,flash有個跨域策略文件crossdomain.xml
<cross-domain-policy>nhttp://www.friendOfFoo.com" />n<allow-access-from domain="*.foo.com" />n<allow-access-from domain="105.216.0.40" />n</cross-domain-policy>n
但是很多開發是很喜歡直接用成*的
- jsonp跨域
這個產生的問題也是很多的,很多直接參用callback來回調函數名,但是直接訪問這個jsonp鏈接,返回的http頭部信息是html,並且沒有對參數值做任何限制,導致直接使用callback=嵌入了第三方的js,產生了跨域
還有一種做了特殊符號的處理,但是返回的響應形式是:
<?phpn$callback = $_GET[callback];n$callback=preg_replace("/[)(<>{}]|]|[|/||"||/","",$callback);necho "<script>".$callback."()</script>";n?>n
這個也是會產生漏洞的,這個帶給大家思考下,這個會產生什麼樣的漏洞
jsonp還有個問題也是經常出現的,就是json劫持漏洞,看個代碼:
B站的json鏈接:testurl
返回的頁面內容:
call("data":"I am secret data!!!")n
A站的get代碼:
<script>nfunction hijack(data){console.log(data.data);}n</script>nn<script src="Client Validation"></script>n
這樣通過jsonp傳遞個人敏感信息的話,利用json劫持就能獲取到,導致個人敏感信息泄漏
- CORS
這個是h5最新的一個頭,主要就是通過設置相應頭中的 Access-Control-Allow-Origin 欄位。。
Access-Control-Allow-Origin 響應欄位說明了該資源或網站所允許被非同源站點訪問的站點列表,當 Access-Control-Allow-Origin 中包含網站 A 或者設置為 * 時,網站 A 即可對網站 B 上的資源進行任意訪問。
也就是利用ajax請求可以獲取到數據信息的。對於這個頭部信息對於防禦xss是很有效的,作為開發可以研究下這個
- postMessage
這裡用這個的時候,看代碼所示:
B站的data數據:
window.onload=function(){n parent.postMessage(I am secret data!!,*);n}n
- 獲取數據代碼:
http://b.test.com/H5/data.html">n<script>nwindow.addEventListener(message,function(e){n alert(e.data);n})n</script>n
這樣就能直接獲取到傳遞的敏感數據,所以在設置這個的時候不要直接設置成*,限制到自己的域下面
- iframe掛馬
很多站點,比如富文本的一些輸入允許iframe的載入,iframe是無法對宿主域進行操作的,但是可以進行掛馬,前段時間遇到一個需求,就是一個統一登入站點的背景是iframe進來的其他站點,其他站點的安全性不能保證,並且裡面有些內容是用戶可以控制到的,這樣怎麼保證我們統一登入的這個站點不受影響?(sandbox屬性)
- 後台xss
主要集中在後台接受用戶的留言反饋等地方沒有注意到防禦xss,導致攻擊者可以直接輸入xss語句進入後台中,管理員在查看到這個留言時候觸發xss,把自己的登入憑證通過第三方的xss傳遞給攻擊者,若是後台有沒有做訪問限制,則攻擊者就能登入後台
- 水坑攻擊、魚叉攻擊
也不算是新型的攻擊方式,這個攻擊是攻擊者將一些攻擊欄位放入了flash cookie、los中,需要用戶在特定的情況下才能觸發,算是留了個水坑等用戶去踩
CSRF漏洞
這裡就需要了解瀏覽器的cookie策略,cookie的幾個重要屬性:domain、path、Expires、Secure、HttpOnly。
其中domain和path保證了改cookie只能在特定的域下生效,cookie是有失效時間的,若是在失效時間之內訪問domain的path就會發送改cookie,這樣就是csrf能利用的根本原因
CSRF就是對於某些操作行為的連接,攻擊者將該鏈接利用<img><iframe>等標籤嵌入頁面中,受害者訪問該鏈接後自動觸發了改行為操作,也就是在你不知不覺中完成了某項操作
產生的原因:
- GET or POST
使用get請求完成某項的操作行為是比較危險的
使用POST請求如果沒有進行referer的驗證,自己構造一個form頁面也是可以進行攻擊的
這些都是使用的cookie的策略,訪問某個網站,改網站的cookie會自動的發送過去
- 無一次性認證token
token保證了本次請求的一次性,即使攻擊者獲取到改連接。發送過去也是失效的
- 驗證碼
這個也能很好的防止CSRF攻擊,但是犧牲的是用戶的體驗問題
這裡有個問題:
怎樣必須使用get請求而不會產生csrf呢?
注入類漏洞
- SQL注入
sql注入被譽為注入之王,不管安全技術、防禦技術怎麼發展,爆出被sql注入獲取到的數據的新聞從來沒有停止過,其中不乏比較大的公司
sql注入最簡單的一段代碼:
var shipcity;nshipcity = Request.from("shipcity");nvar sql="select * from OridersTable where shipcity="+Shipcity +"";n
SQL注入語句就不展示了,閉合單引號,插入sql語句。
現在的sql注入很多情況下是會爆出sql錯誤的,這個相對分析起來很容易知道那個點存在sql注入,但是現在很多都會把錯誤信息屏蔽掉,而且現在的sql注入不僅僅是通過伺服器sql報錯等進行判斷了
針對這種情況,攻擊者研究出了盲注的方法,伺服器沒有錯誤回顯,那麼可以通過分析返回頁面內容進行判斷
在現在的sql注入中用到的最多的就是基於時間的盲注技巧,通過sql語句的執行時間進行判斷
針對sql注入的防禦,規範的編碼規範可以很好的進行防禦
其他資料庫的sql注入問題:
大部分的資料庫大家都是使用的mysql,針對mysql的防護也是比較完善的,但是大家很少會注意到其他資料庫導致的sql注入
舉個mongodb的例子:
代碼如下:
由上圖源代碼可以知道,後台資料庫的名字是security,集合名是users。u_id 是通過GET請求傳到後台,然後傳入一個數組變數中。然後進入MongoDB的查詢。接下來,我們試試通過數組傳入運算符號。
http://localhost/mongo/show.php?u_id[$ne]=2n
傳入後的MongoDB查詢語句如下:
$qry= array(「id」 => array(「$ne」 => 2))n
結果就是MongoDB返回了除了id=2的其他所有數據。
看下MongoDB中的findOne方法:
db.collection.findOne(query, projection)代碼:
利用代碼:
http://localhost/mongo/inject.php?u_name=dummy』});return{something:1,something:2}}//&u_pass=dummyn
願意還閉合前面的語句,注入自己的語句
- 使用預編譯語句
預防sql注入的最佳方式,使用預編譯語句綁定變數
再java中:
String query = "select account from user_data where user_name=?";nPreparedStatement psmtm = connection.preparedStatement(query);npsmtm.setString(1,custname)n
不同的語言都有不同的預編譯的方法
java EE : PreparedStatement()n.NET : SqlCommand() or OleDbCommand()nPHP: bindParam()nHibernate: createQuery()nSQLite: sqlite3_prepare()n
- 使用存儲過程
- 檢查數據類型
- 使用安全的函數
每個語言中都有一些編碼的函數,可以幫助對抗sql注入
- 最小許可權原則
- xml注入
現在遇到的xml注入並不是很多,但是這個也是輸入注入攻擊裡面比較嚴重的一個
xml注入有兩種,一種實體注入,一種和sql萬能密碼一樣,繞過登入
- 代碼注入
QQ客戶端的命令執行(實例)
注入攻擊其實是違背了「數據和代碼分離的原則」,導致了用戶輸入的數據變為代碼進行了執行。
SSRF
SSRF也是現在很多開發不清楚的漏洞,這個漏洞出現的頻率還是很高的
引用網上的一段話來簡單介紹下SSRF漏洞:
SSRF(Server-Side Request Forgery:伺服器端請求偽造) 是一種由攻擊者構造形成由服務端發起請求的一個安全漏洞。一般情況下,SSRF攻擊的目標是從外網無法訪問的內部系統。(正是因為它是由服務端發起的,所以它能夠請求到與它相連而與外網隔離的內部系統)
SSRF 形成的原因大都是由於服務端提供了從其他伺服器應用獲取數據的功能且沒有對目標地址做過濾與限制。比如從指定URL地址獲取網頁文本內容,載入指定地址的圖片,下載等等。
百度命令執行漏洞:
某論壇SSRF獲取伺服器許可權
文件上傳
文件上傳這個很多時候是為了獲取伺服器操作許可權上傳php木馬文件等,但是現在很多開放都會意識到這個問題,將上傳後的目錄設置未不可執行,但是會忽略另一個問題,就是html的文件上傳
還有個經常見到的上傳方式如下:
POST /v1/soc/post HTTP/1.1nHost: sport-circle.xxx.cnnimage=data%3Atext%2Fhtml%3Bbase64%2CPD9waHAgcGhwaW5mbygpOyA/Pg==&content=<img src=x onerror=alert(21212)>n
直接使用的是data偽協議的方式+base64方式上傳圖片,開發的本意是data:image/jpeg;base64,圖片的base64編碼,但是這些數據都是可以被控制的,直接修改上傳,就會在後端形成html頁面,造成xss攻擊,若是上傳的域又是網站的主域,那麼就會威脅到主站的安全
這個比較保險的做法就是將上傳的文件放到一個靜態域下面,和主域沒有任何聯繫
其他漏洞
這些漏洞都是因為開發沒有注意到的一個點導致了很嚴重的漏洞
- cookie認證漏洞
騰訊微博任意賬戶發微博
- android泄漏信息
騰訊文件上傳漏洞
- cookie當ua傳輸
網易大批量獲取登入認證漏洞
H5裡面的一些安全設置
- iframe 中的sandbox
- Link Types中的noreferer
- webStorage
其他
- 認證繞過
這個問題也是出現很多的,很多開放喜歡使用前端獲取伺服器的返回值來判斷是否進行下一步操作或者是否認證成功。案例:
在發布二手買賣信息時候,在填寫取貨信息時有個對是否是本人手機的驗證,
在這個時候攔截網址
http://post.58.com/ajax/?action=checkmobilecodeandblind&phone=13945678910&code=123123123&userid=xxxxxx
是伺服器返回的值,一般驗證碼不對的話會返回-1或者0,修改值為1,通行,直接發布成功
- js限制登入
在js中限制登入,刪除js直接登入後台
- 表面認證
只是做了個登入頁面來做認證,後面的二級頁面沒有驗證用戶是否真的登入
案例:
直接訪問這些連接就能看到學生的所有信息
- 點擊劫持
點擊劫持,就是iframe的利用,iframe一個頁面將其設置為透明或者相應的動作模式
防禦的方法利用:X-FRAME-OPTIONS
X-FRAME-OPTIONS是微軟提出的一個http頭,專門用來防禦利用iframe嵌套的點擊劫持攻擊。
這個頭有三個值:
DENY // 拒絕任何域載入
SAMEORIGIN // 允許同源域下載入ALLOW-FROM // 可以定義允許frame載入的頁面地址php中設置:
header(「X-FRAME-OPTIONS:DENY」);
- 信息泄漏
這個漏洞也是開發很少會注意到的問題,很多人在部署代碼的時候用到的一些工具會導致一些文件的生成,若是沒有做訪問限制,就有可能導致信息泄漏
hg init的時候會生成.hg
e.g.http://www.example.com/.hg/n
git init會生成 .git
在運行git init初始化代碼庫的時候,會在當前目錄下面產生一個.git的隱藏文件,用來記錄代碼的變更記錄等等。在發布代碼的時候,把.git這個目錄沒有刪除,直接發布了。使用這個文件,可以用來恢復源代碼。
.DS_Store文件泄漏:在發布代碼時未刪除文件夾中隱藏的.DS_store,被發現後,獲取了敏感的文件名等信息
網站備份壓縮文件: 網站的備份壓縮文件沒有限制
CVS泄漏
http://url/CVS/Root 返回根信息nhttp://url/CVS/Entries 返回所有文件的結構n
SVN導致文件泄露、WEB-INF/web.xml泄露
推薦閱讀:
※如何看待張懸《玫瑰色的你》被禁封?
※睡在「棺材」里的人生。
※我們為什麼一定要變得外向?在現今社會內向真的「該死」么?
※為控制人類思想,中情局竟拿所有美國人做實驗?!
※跳樑小丑再出鏡 | 日本APA酒店社長再放厥詞,直懟村上春樹新作