掌握XSS與CSFR,我也可以是個黑客

2019-09-30     指尖上的代碼



今天呀,我想當一名黑客,去黑別人的網站!我有兩三技能,獨樂不如眾樂樂,今天我也把這個幾個攻擊手段教給你,咱們一起搞事情去。

首先我們來了解一下攻擊手段,也是比較常見的兩種攻擊手段了:

  • CSRF
  • XSS

CSRF

全稱:Cross-site request forgery,跨站請求偽造。原理是:通過偽裝成受信任用戶的請求來攻擊受信任的網站。

如何偽裝?如何才算攻擊?

生活中其實我們不缺這種例子,比如說我們經常接收到一些來歷不明的垃圾簡訊,簡訊內容裡面有個url連結,有些人手賤點開了連結,然後就發現錢不見了!!

我們從技術角度來復原一下這個過程,首先設定一些基礎:

  • 垃圾簡訊里的連結(垃圾網):http://www.lajiwang.com/pianqian
  • 存了錢的網站(存錢網):http://www.cunqianwang.com/

然後用戶動作是:點開了垃圾網的連結,但是存錢網裡帳戶的錢不見了。既然是自己帳戶的錢不見了,所以這裡其實有個前提:用戶已經登錄了存錢網!所以準確來說用戶的動作是這樣的:點開了垃圾網的連結,但是之前登錄過的存錢網裡帳戶的錢不見了!

兩個網站毫無關聯,為啥會造成這個讓人意想不到的後果呢?

其實呀,垃圾網的人為了達到攻擊的目的,偷偷在網頁上嵌入了存錢網的連結,所以打開垃圾網時候順便也觸發了存錢網的轉帳的連結,整體邏輯如下:

  • 1、用戶登錄成功存錢網,於是瀏覽器中產生了網站cookie
  • 2、用戶在沒有退出存錢網的情況下,訪問了垃圾網
  • 3、垃圾網要求訪問存錢網的轉帳url,轉帳url帶上存錢網的cookie去訪問伺服器
  • 4、存錢網伺服器驗證轉帳url確認是用戶在轉帳,轉帳成功!

說到這裡,你發現漏洞在哪裡沒有?大家都知道cookie代表用戶身份,每次發起請求,請求頭裡都會附上用戶的cookie信息,既然cookie是存在瀏覽器的,我偷不到你的cookie,那麼我就讓你在不知道到的情況下讓你自己去操作。

舉個例子:假如一家銀行轉帳操作的URL地址如下:

http:
//www.cunqianwang.com/zhuanzhang?account=A&for=B&amount=500

那麼,一個垃圾網中可以放置如下代碼

 
src
=
"http://www.cunqianwang.com/zhuanzhang?account=A&for=B&amount=500"
>

好了,原理和攻擊手段我們都懂了,那麼我們來說說幾種常見的預防手段:

1、檢查referer欄位

HTTP頭中有一個Referer欄位,這個欄位是用來標明請求來源於哪一個網址。當網站A去訪問網站B的資源時候,連結上的請求頭上就會有Referer欄位。注意是在不同域名下才有。

我隨意打開hao123.com的首頁,一些圖片不是放在hao123.com域名下的,所以會在header中帶上Referer欄位表示請求源是hao123.com。

那麼伺服器可以通過判斷Referer欄位來判斷請求的來源。所以在垃圾網站里訪問存錢網,Referer的值就是垃圾網的域名,就能判斷是不是合法的操作啦。

java代碼里獲取Referer欄位值代碼是:

String
referer = request.getHeader(
"Referer"
);

這種方法簡單易行,但也有其局限性。http協議無法保證來訪的瀏覽器的具體實現,可以通過篡改Referer欄位的方式來進行攻擊,所以就要看你用的瀏覽器高級不高級了,如果你用的瀏覽剛好是騙子開發的瀏覽器,嘿嘿~~

2、Token 驗證

既然我們要判定用戶行為的合法性,那麼我就給用戶頒發一個合法token,除了帶上cookie,還得帶上token才行,token在前一個步驟中獲取。

邏輯如下:

  • 伺服器發送給客戶端一個token;
  • 客戶端提交的表單中帶著這個token。
  • 如果這個 token 不合法,那麼伺服器拒絕這個請求。

3、添加圖片驗證碼、簡訊驗證等

重要步驟添加驗證碼認證後才能操作。腦補,略略略略~

學會攻擊

好了,作為一名出色的黑客,必須要知道自己攻擊手段的漏洞在哪,怎麼防禦,絕不做無用功!既然預防手段我知道了,那麼接下來就是我展現真正技術的時候了。

嘿嘿,很多公司在一開始的時候為了節約成本,選擇用開源項目作為基礎,然後再二次開發。雖說開發快,但其實未必安全,一些開源項目如果沒有做csrf的預防,那麼漏洞就一直存在。

經過我多天的研究,終於發現了某個商城用的是開源項目二次開發的,沒有csrf預防。商城的積分可以直接贈送給別人,我立馬搞了個網頁,嵌入網站贈送積分的連結。

於是有了我和我朋友的對白。

  • 我:小明呀,你的A商城還有多少積分呀?
  • 小明:2000多吧?
  • 我:這麼多?我不信!你登錄讓我看看!
  • 小明去登錄A網站給我看積分,果然2000多。
  • 我:小明呀,我開發了個網站,我發給你看看能不能打開
  • 小明打開網站,小明的積分到我帳戶了~

當黑客感覺真好,小明,你是個好人~

XSS

全程:Cross Site Scripting,中文:跨域腳本攻擊。原理:不需要你做任何的登錄認證,通過合法的操作(比如在url中輸入、在評論框中輸入),向你的頁面注入腳本(可能是js、hmtl代碼塊等),類似於SQL注入。

通俗點講就是:惡意攻擊者往Web頁面里插入惡意html代碼,當用戶瀏覽該頁之時,嵌入其中Web裡面的html代碼會被執行,從而達到惡意用戶的特殊目的。

講再細點其實就是:利用輸入內容來閉合對應的html標籤,從而執行輸入內容的腳本。

攻擊形態

xss有兩種形態(網友總結):

  • 1、反射型


發出請求時,XSS代碼出現在url中,作為輸入提交到伺服器端,伺服器端解析後響應,XSS代碼隨響應內容一起傳回給瀏覽器,最後瀏覽器解析執行XSS代碼。這個過程像一次反射,所以叫反射型XSS。

  • 2、存儲型


存儲型XSS和反射型XSS的差別在於,提交的代碼會存儲在伺服器端(資料庫、內存、文件系統等),下次請求時目標頁面時不用再提交XSS代碼。

攻擊手段

不管是什麼類型,你get到關鍵點沒有?關鍵點以及技術難點其實在於如何往頁面中嵌入惡意的代碼。

下面我們來寫個例子模擬一下:首先我頁面寫了個form表單:

  • index.ftl
 
action
=
"/submit"

method
=
"post"
>
名稱:

name
=
"name"

value
=
"${name}"
>


type
=
"submit"
>

controller中有個基本跳轉,還有form表單的提交:

  • com.example.IndexController#index
@GetMapping
(
""
)
public

String
index(
HttpServletRequest
request) {
request.setAttribute(
"name"
,
"公眾號:java思維導圖"
);

return

"index"
;
}
@PostMapping
(
"/submit"
)
public

String
submit(
HttpServletRequest
request) {

String
name = request.getParameter(
"name"
);

System
.
out
.println(
"name---------->"
+ name);

// 假裝只有名字為「求關注」才能通過

if
(!name.equals(
"求關注"
)) {
request.setAttribute(
"name"
, name);
}

return

"index"
;
}

初始效果如下:

ok,基本邏輯也寫好了,一個簡單的表單提交,提交之後如果數據不對,或格式不對就會返回表單頁面,同時回顯表單數據。

加入我想嵌入腳本如下:


那麼我該怎麼樣才能往這個頁面上嵌入代碼呢?我打開F12,研究一下

要是這個這個腳本能提到input的外面,value能提前結束就好了。嘿嘿,突然想到,既然我改不了原來的,那麼我就創造一個。

於是我改了一下輸入的值成:

">

這">不就跑到前面了嘛,哈哈哈,天才,我趕緊試試。谷歌瀏覽器測試結果如下:

腳本的確跑到外面了,但是alert(1)怎麼不見了呀,我趕緊調試一下:

不是後端在搞事情,那麼真相就只有一個,谷歌瀏覽器在搞事情,谷歌果然強大,還能辨別我的腳本並和諧掉。

我換個Edge瀏覽器再試試:

哇,果然Edge你最帥,我想要的你都給我~ F12看下:

沒毛病,原聲原味的alert(1);

好了上面我們已經弄懂了xss的嵌入腳本的方式,我們輸入是合法的,只是內容有點取巧,這就是xss的攻擊手段。

除了這個input標籤,其實還有很多標籤比較常用,比如title、a、img、script等。

上面這個一般都是反射性的xss攻擊,我們再來看看一個存儲類型的title的例子。

在很多博客中,我們都可以發布文章,我們需要寫文章標題,文章內容等,文章標題一般我們還會放在我們的head的title中,用於標籤展示當前瀏覽文章標題。

加入說,我們的頁面是這樣展示的:

  • title.ftl




<br>${title}<br>


這是內容 - ${content}


而controller中傳過來的內容如下:

  • IndexController
@GetMapping
(
"/title"
)
public

String
title(
HttpServletRequest
request) {
request.setAttribute(
"title"
,
""
);
request.setAttribute(
"content"
,
"內容是關注公眾號:java思維導圖"
);

return

"title"
;
}

最後我們的得到的頁面展示這樣子:加載時候先執行彈窗:alert("公眾號java思維導圖");然後再加載內容。

因為一般我們文章標題內容都是保存到資料庫的,所以每次渲染都會執行腳本,所以是個存儲型xss攻擊。

解決方法

好了,看了我們的例子項目,我們已經意識到了xss攻擊的可怕性,一單發布文章都可以寫腳本,那麼所有的用戶打開這篇文章都會被執行腳本,影響可就大了。那麼有什麼好的解決方法嗎?

這裡給大家介紹幾個解決方法。我們先來看renren-fast項目是怎麼解決這個問題的:

  • renren-fast
#識別攻擊腳本、並刪掉對應可執行腳本的標籤
HTMLFilter
#全局過濾器,包裝request
XssFilter
#包裝request,重寫request的幾個重要方法,比如getParameter等
XssHttpServletRequestWrapper

所以renren-fast項目的設計邏輯是加入一個全局過濾器,然後通過包裝請求的request,重寫request的getParameter、getHeader、getInputStream等方法,在這些方法裡面都進行一遍過濾,從而去掉所有的攻擊腳本。看看重要代碼:

  • io.renren.common.xss.XssFilter
public

class

XssFilter

implements

Filter
{

public

void
doFilter(
ServletRequest
request,
ServletResponse
response,
FilterChain
chain)

throws

IOException
,
ServletException
{

XssHttpServletRequestWrapper
xssRequest =
new

XssHttpServletRequestWrapper
(
(
HttpServletRequest
) request);
chain.doFilter(xssRequest, response);
}
...
}
  • io.renren.common.xss.XssHttpServletRequestWrapper
public

class

XssHttpServletRequestWrapper

extends

HttpServletRequestWrapper
{

@Override

public

String
getParameter(
String
name) {

String
value =
super
.getParameter(xssEncode(name));

if
(
StringUtils
.isNotBlank(value)) {
value = xssEncode(value);
}

return
value;
}
...
}

可以看到上面的xssEncode就是進行過濾腳本的方法;xssEncode方法代碼如下:

private

String
xssEncode(
String
input) {

return
htmlFilter.filter(input);
}

ok,相信你已經弄明白了。

我們來看看另一個博客項目mblog的解決方法:

  • mblog
#通用控制器
BaseController
#自定義編輯器
StringEscapeEditor

mblog項目其實是通過註冊所有controller的自定義編輯器,在提交表單時候對所有欄位都進行一層get和set,在set的過程中對輸入內容進行一番檢查,如果有腳本就進行替換等操作。

詳細代碼如下:

  • BaseController
@InitBinder
public

void
initBinder(
ServletRequestDataBinder
binder) {

/**
* 防止XSS攻擊
*/
binder.registerCustomEditor(
String
.
class
,
new

StringEscapeEditor
(
true
,
false
));
...
}

@InitBinder用於表單到方法的數據綁定的,這裡綁定了一個自定義編輯器StringEscapeEditor。

  • StringEscapeEditor


可以看到setAsText中就是對腳本進行過濾等操作的。

這兩種方法都學會了嗎?其實邏輯都是對腳本進行過濾替換刪除等操作。

學會攻擊

好了,又到了黑客show time,某個知名博客平台沒防禦xss攻擊,這時候我發布了一篇文章,title中包含了腳本


文章來源: https://twgreatdaily.com/zh-tw/kg1ugm0BMH2_cNUgisnF.html