網絡安全:攻擊和防御練習(全戰課), DDos壓力測試


XSS 跨站腳本攻擊:

Cross-site scripting(簡稱xss)跨站腳本。

一種網站的安全漏洞的攻擊,代碼注入攻擊的一種。XSS攻擊通常指的是通過利用網頁開發時留下的漏洞,通過巧妙的方法注入惡意指令代碼到網頁,使用戶加載並執行攻擊者惡意制造的網頁程序。這些惡意網頁程序通常是JavaScript,但實際上也可以包括JavaVBScriptActiveXFlash或者甚至是普通的HTML。攻擊成功后,攻擊者可能得到更高的權限(如執行一些操作)、私密網頁內容、會話cookie等各種內容。

 

例子:

<script>
$.ajax({
  url: $(location).attr('href') + "/comments",
  method: "POST",
  data: {  comment : { content: "啊哈哈哈~你看看你! (σ゚∀゚)σ゚∀゚)σ゚∀゚)σ" } },
  dataType: "JSON"
})
</script>

 

url: window.location.href + "/comments" 生成"http://localhost:3000/events/1/comments"

 

這主要是因為在views/events/show.html.erb中:

<% raw comment.content%>這行代碼中有raw()方法

這個方法會輸出所有字符,不會放過tag標簽。去掉raw()后,content兩邊加上引號變為字符串。

但這樣就不能插入img等有用的tag了。這時可以使用sanitize()方法。

 

str.html_safe方法

讓字符串不會被檢查,即字符串中的特殊字符如tag,不會被脫逸,這樣黑客可能利用這點插入<script>腳本。
因此需要謹慎使用html_safe()。
 
向div標簽就會被脫逸,使用content_tag()可以指定某個標簽不被脫逸。

 



 

跨站請求偽造 Cross-site request forgery

 

也稱為one-click attack, 簡稱CSRF或XSRF.

是攻擊者通過一些技術手段欺騙用戶的瀏覽器去訪問一個自己曾經認證過的網站並執行一些操作(如發郵件,發消息,甚至財產操作如轉賬和購買商品)。由於瀏覽器曾經認證過,所以被訪問的網站會認為是真正的用戶操作而去執行。這利用了web中用戶身份驗證的一個漏洞:簡單的身份驗證只能保證請求發自某個用戶的瀏覽器,卻不能保證請求本身是用戶自願發出的

 

例子:

在任意位置插入惡意代碼:如

<img src="/events/92/comments/522/highlight"> 偽裝成是用戶發送的請求。

防御方法:添加校驗token

token是在非get請求中使用。因此需要看代碼中關於修改數據庫的請求,是否是用了get請求,如果是必須改成非get請求。這樣img就不能攻擊了。

 

Rails默認帶了protect_from_forgery with: :exception ,⚠️5.2隱藏了這行code。

1. 這樣在 Rails 產生的表單form中,就有帶這個參數 authenticity_token。表單的提交就會進行token驗證

<form class="new_comment" id="new_comment" action="/events/2/comments" accept-charset="UTF-8" method="post">

  <input name="utf8" type="hidden" value="✓">

  <input type="hidden" name="authenticity_token" value="fMv3c2b177kqsy/LuDIARp+RaQWJtBHwfQkbEV8j5wqNVFFSBqvcotvkeV07hiQpWsQY1RIEdpVMvE4vysEHiA==">
  <div class="form-group">
    <label for="comment_content">Content</label>
    <textarea class="form-control" name="comment[content]" id="comment_content"></textarea>
  </div>

  <div class="form-group">
    <input type="submit" name="commit" value="Comment" class="btn btn-primary" data-disable-with="Comment">
  </div>
</form>

 

2. 如果是Rails.ajax中的請求:就會抓 meta 中的 csrf-token 參數附加到請求中。和form中的value是一樣的。

Rails.ajax()方法,會抓取csrfToken。校驗token。

在csrf.coffee中:

csrfToken = Rails.csrfToken = ->
   meta = document.querySelector('meta[name=csrf-token]')
 meta and meta.content

得到:

<meta name="csrf-token" content="fMv3c2b177kqsy/LuDIARp+RaQWJtBHwfQkbEV8j5wqNVFFSBqvcotvkeV07hiQpWsQY1RIEdpVMvE4vysEHiA==">

 

這樣,黑客在其他網站上挖的坑因為沒有這個authenticity_token或csrf-token(兩者值一樣),他發送的請求就會被擋住。

 



 

 

SQL Injection 數據庫注入攻擊structured query language.

 

@comments = @comments.where( "comments.content LIKE '%#{params[:keyword]}%'")

轉換:

SELECT "comments".* FROM "comments" WHERE "comments"."event_id" = ? AND (comments.content LIKE '%這是搜尋關鍵字%') [["event_id", 95]]

 

如果收到的參數是

sorry'); DELETE * FROM comments; --

轉換為sql就成了3句代碼:

SELECT "comments".* FROM "comments" WHERE "comments"."event_id" = ? AND (comments.content LIKE '%sorry'); DELETE * FROM comments;   --%') [["event_id", 95]]

第一句是查詢,第二句就成了刪除了!!, --后面代表了注釋。

 

問題的原因:是查詢語法使用string造成的。

這樣單引號,\backslash就會起到了它的作用。

可以使用quote_string(s)方法來給一個string逸出單引號和反斜杠。

keyword = ActiveRecord::Base::connection.quote_string( params[:keyword] )

又因為查詢語法where經常用到,所以增加了簡單的寫法, 自動逸出:

@comments = @comments.where( "comments.content LIKE ?", "%#{params[:keyword]}%")
@registrations = Registraion.where( :status => params[:status] ) # Hash 寫法,這是安全的
@registrations = Registraion.where( "status = ?", params[:status] ) # Array 寫法,這是安全的

 

但order等語法,沒做自動逸出: (點擊查看所有需要注意的sql語法)

可以使用白名單:

app/views/events/show.html.erb

<p>
<%= link_to "新留言在上", event_path(@event, :sort => "id DESC") %>
<%= link_to "舊留言在上", event_path(@event, :sort => "id ASC") %>
</p>

app/controllers/events_controller.rb

-  if params[:sort] # 本來這樣有漏洞,你太相信用戶傳進來的參數了
+ if params[:sort] && ["id DESC", "id ASC"].include?(params[:sort]) # 只有白名單內的參數可以用 @comments = @comments.order(params[:sort]) end 

 

Delete_all和 Destroy_all

都要小心使用!。它們都接受和find()方法相同的條件參數。參數可以是string, array, hash。但Strings不會被脫逸, 所以安全的寫法是只用array, hash做參數。

Destroy_all因為會實例化記錄並調用destroy方法並調用callbacks,相對比delete_all安全。

params[:admin] = "') OR 1=1--'"
User.destroy_all(["id = ? AND admin = '#{params[:admin]}", params[:id]])

生成:SELECT "users".* FROM "users" WHERE (id = NULL AND admin = '') OR 1=1--')

這會刪除所有users。

 

Exists?()方法。

他用來判斷一條記錄是否存在。參數一般是一個主鍵。如果參數是array或hash,它被當成一個條件option。

為了安全,參數最好是一個integer或string。

 

Group()方法

他可以接受任意的SQL string。因此

params[:group] = "name UNION SELECT * FROM users"
User.where(:admin => false).group(params[:group])

生成 :

SELECT "users".* FROM "users" WHERE "users"."admin" = ? GROUP BY name UNION SELECT * FROM users

因為union了另外一條sql,因此返回所有的users。

 

Having()方法

容易遭到Sql injection攻擊,因為它一般在一條rails查詢語句的最后。

 

Joins方法

它可以接收一個關聯數組或直接的SQl string。因此也可能會遭到注入攻擊。

 

Select(*fields)方法

因為select子句一般在一個查詢的開頭,所以幾乎任何sql都可以注入並生效。

params[:column] = "* FROM users WHERE admin = 't' ;"
User.select(params[:column])

Query

SELECT * FROM users WHERE admin = 't' ; FROM "users"

Result:返回的是一個關系對象。

#<ActiveRecord::Relation [#<User id: 84, name: "Admin", password: "supersecretpass", age: 45, admin: true, created_at: "2016-11-11 18:51:41", updated_at: "2016-11-11 18:51:41">]>

 

select有2種用法:

  1. 修改select聲明,檢索指定的fields。返回一個對象關系a relation object。可以在后面添加其他查詢方法。
  2. 接受一個塊{}, 類似Array#select。從數據庫中得到一個array對象的集合。

 

Pluck(*column_names)

從一個table中選擇指定的column。接受任何Sql。所以容易收到注入攻擊。返回一個array對象集合。

 



 

 

大量賦值(Mass Assignment)的漏洞

rails5增加了strong parameters

params.require(:XXX).permit(:column_name, ...)限定了可以傳入什么參數。

但也要謹慎使用。關鍵的列,即使隱藏,也可以通過url修改。所以應該留意一個column是否是要傳入的,如果不是,就別加入白名單。

如果hacker在chrome瀏覽器的inspect上修改參數,

log上會顯示:Unpermitted parameter: role



 

 

破解加密 Cookie-based Session(太復雜,只了解了一下)

 

 密匙不能外泄,如果外泄,必須馬上更換。rails可以更換session的存儲方法。


 

 Module: Base64 (defined in lib/base64.rb)

這個模塊提供了binary data的編碼和解碼。

require "base64" enc = Base64.encode64('Send reinforcements') # -> "U2VuZCByZWluZm9yY2VtZW50cw==\n" plain = Base64.decode64(enc) # -> "Send reinforcements"

 

Module OpenSSl

這個模塊提供了生成密碼的算法。它包裹了OpenSSL library.


 


 

 

 DoS 拒絕服務攻擊

 

denial of service attack, distributed denial of service attack分布拒絕服務攻擊。

對自己的網站叫做壓力測試

安裝wrk:(https://github.com/wg/wrk)

執行 brew install wrk

執行 wrk -t12 -c400 -d30s http://localhost:3000/products

t:thread

c: connection, HTTP連接的總數,每個thread處理 connections/threads個連接。

d: duration of the test 例子: 2s, 2m, 2h

 

如何防御ddos攻擊:

可以使用gem 'rack-attack'

# In config/application.rb config.middleware.use Rack::Attack

然后新建config/initializers/rack_attack.rb

把這個網址的案例代碼粘體過來https://github.com/kickstarter/rack-attack/wiki/Example-Configuration

還有很多具體設置。如果真的面料大量ddos攻擊,必須購買專業的網絡防火牆。百度安全,雲盾ddos高防IP.


 

安全分析工具

 

gem 'brakeman'(4800✨) 一個靜態分享工具。檢查Rails程序的安全弱點。

group :development do
  gem 'brakeman'
end

然后在程序根目錄執行brakeman, 或者在非根目錄執行 brakeman /path/to/rails/application

結果是參考,不代表一定是漏洞。需要逐條檢查。

 

另外gem 也可能有安全漏洞,gem 'bundler-audit'可以檢查(1700✨)


 

 

密碼是如何存儲的?

散列函數是一種能將數據變成摘要(digest)的算法,Hash function,散列算法,哈希函數。
通過把數據壓縮成小的數字,讓數據量變小,將數據的格式固定下來。

執行 irb,然后輸入以下代碼實驗看看:

require 'digest'
Digest::SHA1.hexdigest '12345678'

得到 "7c222fb2927d828af22f592134e8932480637c0d"

散列函數有一些特性:

  1. 相同的數據,每次都會得到一樣的摘要
  2. 是單向的,無法逆推:只知道摘要的話,沒有辦法能夠透過計算知道本來的數據長怎樣。例如給你 7c222fb2927d828af22f592134e8932480637c0d,沒有算法可以逆推回來。除非有一個對照的字典

 

散列函數的用途:

可以用來比較兩個文檔是否相同,而無需實際比較文檔內容:

1.git commit每次都會產生digest。不同的digest代表了不同的內容。

2.網絡傳檔,也可以透過比較digest,看是否下載了完整的檔案。

3.Rails中,Asset pipeline會將CSS和javascript壓縮。檔案就是透過散列函數產生的。

4.devise中的密碼,也是使用散列函數生成的.

User model中,users table的實際字段是 t.string "encrypted_password"。用戶注冊時輸入的密碼在儲存入數據庫時會先變為散列函數,digest。數據庫並不儲存明碼。

因此,數據庫管理員也不會知道用戶的真正密碼。一旦數據庫泄露,密碼也安全。

判斷一個網站是否使用明碼做密碼,可以請求忘記密碼,看是否是郵寄給你源碼還是重設。


 

推薦閱讀阿里巴巴的網絡安全專家所寫的入門書:白帽子講Web安全這本書

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM