国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

[譯] Martin Fowler - Web 應用安全基礎

yanest / 1227人閱讀

摘要:瀏覽器的同源策略并不能夠避免來自于惡意站點的提交。為了保證輸入數據的完整性,服務器端務必要進行數據校驗。輸入驗證即是保證實際輸入與應用預期的輸入的一致性。因此驗證輸入時保證系統安全性與防衛危險的第一道防線。

Github Repo:https://github.com/wxyyxc1992/infosecurity-handbook/blob/master/Reinforce/WebSecurity/basics-of-web-application-security.md
原文:The Basics of Web Application Security

現代的軟件開發者已經有點像瑞士軍刀了,首先,你需要來保證完成用戶的功能或者業務需求,并且要保證又快又好地完成。其次,你希望你的代碼能夠擁有充分的可理解性或者可擴展性:能夠隨著IT需求的快速變遷而有著充分的擴展空間,與此同時還需要穩定與可用。開發者必須列舉出有用的接口,優化數據庫,以及頻繁地建立或者維護一個交付渠道。不過,當我們審視這長長的需求列表的時候,在快速、低成本以及靈活可擴展之下的,即是安全性。或許直到一些東西出了問題,或者你構建的系統被攻擊了之后才能深刻感受到安全才是最重要的。安全這個概念有點像性能,是個泛化的跨越了多個領域的概念。所以一個開發者怎么才能在模糊的安全需求與未知的風險面前選擇合適的開發規劃呢?當然如果能夠明確這些安全需求與定位到威脅的話毫無疑問非常值得推薦,但是這個準備本身就需要耗費大量的時間與金錢。

Trust(信賴)

首先,在討論具體的輸入輸出之前,我們需要來強調下自認為安全中最重要也是最根本的原則:Trust。作為一個開發者,也需要不斷地問自己,我們相信來自于用戶瀏覽器的請求嗎?我們相信上游系統正常工作來保證了我們數據的干凈與安全嗎?我們相信服務器與瀏覽器之間的信道就不會被監聽或者偽造嗎?我們相信我們系統本身依賴的服務或者數據存儲嗎?呵呵,都不可信。

當然,就像安全一樣,Trust也不是一個雙選題,非黑即白。我們需要明白系統的風險忍受力與數據的安全邊界。為了能夠正確的、基于某個統一規則的預估,我們需要審視威脅與風險,這個評估方法與標準會在另一篇文章中講解。

Reject Unexpected Form Input(拒絕未知的表單輸入)

HTML表單本身就可能帶來些好像很安全的錯覺,表單的構建者肯定覺得他們限制了輸入類型、做了數據校驗,這樣整個表單輸入就是安全的。但確信無疑的是,這只是個錯覺,盡管客戶端地JavaScript腳本可以從安全地角度來說提供完整的校驗。

Untrusted Input

無論我們是否在客戶端提供了表單驗證或者是否使用了HTTPs連接,我們能夠信賴來自用戶瀏覽器的連接的比例都是0。用戶可以輕易地在發送之前修改標記,或者使用類似于curl這樣的命令行來提交沒有經過校驗的數據。乃至于一個不明所以的用戶可能在一個懷有惡意的網站莫名其妙地添了些內容。瀏覽器的同源策略并不能夠避免來自于惡意站點的提交。為了保證輸入數據的完整性,服務器端務必要進行數據校驗。

不過估計有人有疑問了,為啥說這個畸形的數據就會導致安全問題呢?這往往取決于你的應用業務邏輯與輸出的編碼,為了避免不可預知的行為、數據泄露與潛在攻擊,需要在輸入的數據與可執行代碼之間架構一個過濾層。譬如,我們的表單里有一個選擇的按鈕來允許用戶選擇合適的通信類型,我們的業務邏輯代碼可能是這樣的:

final String communicationType = req.getParameter("communicationType");
if ("email".equals(communicationType)) {
    sendByEmail();
} else if ("text".equals(communicationType)) {
    sendByText();
} else {
    sendError(resp, format("Can"t send by type %s", communicationType));
}

上面代碼危不危險取決于sendError這個方法是怎么定義的,而我們肯定無法確定下游的代碼就一定是安全的。最好的選擇就是我們在控制流中移除這個危險,而使用的方法就是輸入驗證。

Input Validation

輸入驗證即是保證實際輸入與應用預期的輸入的一致性。超出預期的輸入數據會導致我們系統拋出未知的結果,譬如邏輯崩壞、觸發錯誤乃至于允許攻擊者控制系統的一部分。其中像數據庫查詢這樣的能夠在服務端作為可執行代碼的輸入與JavaScript這樣在客戶端能夠被執行的代碼更是特別的危險。因此驗證輸入時保證系統安全性與防衛危險的第一道防線。

開發者們在構建應用系統的過程中會進行一些基本的驗證,譬如判斷值是否為空或者是否為正數。而從安全的角度考慮,我們需要將輸入限定到系統允許的最小集合中,譬如數值型值可以被限定在某個特定的范圍內。譬如,系統不會允許用戶將一個負值添加到購物車中。這種限制性的驗證手段就是所謂的positive validation或者whitelisting。一個白名單可以用于限定某個具體的URL或者yyyy/mm/dd這樣的時間日期。它可以限制輸入的長度、單個字符的編碼規范或者上面例子中的只有給定值可以被接受。

另外一種考慮輸入驗證的思維角度就是把它當做服務端與消費者之間簽訂的一種協議,任何違背了這個協議的請求都是無效的并且被拒絕。你的這個協議越嚴格,你的系統在未知情況下遭受的風險就會越小。而當對于某個輸入驗證失敗之后,開發者也要好好考慮應該如何反饋。最嚴格,也是最有爭議的辦法就是全部拒絕,并且沒有任何反饋,不過要注意將這個事情通過日志或者監控記錄下來。不過為啥一點反饋都沒有呢?我們需要提供給用戶哪些信息是無效的嗎?這一點還是要取決于你的約定。在上面的例子中,如果你接收到了除了email或者text之外的內容,那你有可能被攻擊了。不過如果你進行了反饋,可能正中全套。譬如如果開發者直接返回:俺們并不認識你傳入的communicationType,可能這個還無傷大雅,但是如果是這樣的呢:

這種情況下你就會面臨一個用來盜取你的Cookies的XSS攻擊代碼,如果你一定要給用戶反饋,你必須保證不會把不受信任的用戶內容直接返回,而應該使用固定的提示信息。如果你不可避免地要把用戶的輸入反饋回去,你要保證它是被編碼的。

In Practice

實踐中,我們經常要通過過濾

為了便于分析這個漫畫所要表達的含義,我們假設這個成績追蹤系統有一個用于增加新的學生信息的函數:

void addStudent(String lastName, String firstName) {
        String query = "INSERT INTO students (last_name, first_name) VALUES (""
                + lastName + "", "" + firstName + "")";
        getConnection().createStatement().execute(query);
}

如果輸入的參數是"Fowler"與"Martin",那么最終構造出的SQL語句為:

INSERT INTO students (last_name, first_name) VALUES ("Fowler", "Martin")

不過如果輸入的是上面那娃的名字,那么整個待執行的SQL語句就變成了:

INSERT INTO students (last_name, first_name) VALUES ("XKCD", "Robert’); DROP TABLE Students;-- ")

實際上,這個SQL語句一共執行了兩個操作:

INSERT INTO students (last_name, first_name) VALUES ("XKCD", "Robert")

DROP TABLE Students

最后的--注釋是為了屏蔽余下的內容,保證整個SQL語句能夠穩定執行。類似于這樣的攻擊載荷能夠執行任意的SQL語句,換言之,攻擊者能夠在數據庫內像這個應用系統一樣做任何事情。

采用參數綁定來解決這個問題

對于上文描述的這種場景,如果只是依賴于簡單的清洗過濾,肯定無法應付所有的攻擊載荷,這也不是一個正道。基本上能夠采取的方法就是所謂的參數綁定,譬如JDBC中提供的PreparedStatement.setXXX()方法,參數綁定可以將像SQL這樣的可執行代碼與需要進行編碼、過濾的內容區分開來:

void addStudent(String lastName, String firstName) {
        PreparedStatement stmt = getConnection().prepareStatement("INSERT INTO students (last_name, first_name) VALUES (?, ?)");
        stmt.setString(1, lastName);
        stmt.setString(2, firstName);
        stmt.execute();
 }

一般來說,一個功能比較全面地數據訪問層都會提供這種參數綁定的功能,開發者在開發的時候就要注意將所有的不受信任的輸入通過參數綁定生成SQL語句。

Clean and Safe Code

有時候我們開發時會遇到一個兩難的問題,即是好的安全性與干凈整潔的代碼之間的沖突。為了保證安全性往往需要我們增加些額外的代碼,不過在上面的例子中我們還是同時達成了較高的安全性與好的代碼設計。使用綁定的參數不僅能使應用系統免于注入攻擊,還能通過在代碼與內容之間構建清晰的邊界來增加整個代碼的可讀性,并且與手動拼接相比還能大大簡化構造可用的SQL的過程。當你用參數綁定來代替原本的格式化字符串或者字符串拼接來構造SQL的時候,你會發現還能用全局的綁定方程來完成這一工作,這又會大大增加整個代碼的整潔度與安全性。

Common Misconceptions

有一個常見的錯誤思維就是覺得存儲過程能夠避免SQL注入攻擊,但是這個只有在你是通過參數綁定的方式傳入參數的情況下。如果存儲過程本身也是用的字符串連接的方式,那么同樣存在SQL注入攻擊的風險。類似的,像ActiveRecord、Hibernate或者.Net Entity這樣的框架,也是只有在用參數綁定來構造SQL的情況下才會進行SQL注入清洗。

最后,還有一個常見的錯覺就是NoSQL數據庫不會被SQL注入攻擊影響。這肯定是不對的,所有的查詢語言,無論是不是SQL都需要在可執行代碼與輸入的內容之間劃定明晰的邊界來防止參數混淆可執行的命令。攻擊者會不停尋找能夠在運行時打破這種邊界隔離的方法從而進行潛在的攻擊。即使是Mongodb,采用了二進制的協議與多種語言特定的API都會存在被注入的風險,譬如$where這個操作符。

Parameter Binding Functions
Framework Encoded Dangerous
Raw JDBC Connection.prepareStatement() used with setXXX() methods and bound parameters for all input. Any query or update method called with string concatenation rather than binding.
PHP / MySQLi prepare() used with bind_param for all input. Any query or update method called with string concatenation rather than binding.
MongoDB Basic CRUD operations such as find(), insert(), with BSON document field names controlled by application. Operations, including find, when field names are allowed to be determined by untrusted data or use of Mongo operations such as "$where" that allow arbitrary JavaScript conditions.
Cassandra Session.prepare used with BoundStatement and bound parameters for all input. Any query or update method called with string concatenation rather than binding.
Hibernate / JPA Use SQL or JPQL/OQL with bound parameters via setParameter Any query or update method called with string concatenation rather than binding.
ActiveRecord Condition functions (find_by, where) if used with hashes or bound parameters, eg: where (foo: bar)where ("foo = ?", bar) Condition functions used with string concatenation or interpolation: where("foo = "#{bar}"")where("foo = "" + bar + """)
In Summary

避免直接從用戶的輸入中構建出SQL或者等價的NoSQL查詢語句

在查詢語句與存儲過程中都使用參數綁定

盡可能使用框架提供好的原生的綁定方法而不是用你自己的編碼方法

不要覺得存儲過程或者ORM框架可以幫到你,你還是需要手動調用存儲過程

NoSQL 也存在著注入的危險

Protect Data in Transit

當我們著眼于系統的輸入輸出的時候,還有另一個重要的店需要考慮進去,就是傳輸過程中數據的保密性與完整性。在使用原始的HTTP連接的時候,因為服務器與用戶之間是直接進行的明文傳輸,導致了用戶面臨著很多的風險與威脅。攻擊者可以用中間人攻擊來輕易的截獲或者篡改傳輸的數據。攻擊者想要做些什么并沒有任何的限制,包括竊取用戶的Session信息、注入有害的代碼等,乃至于修改用戶傳送至服務器的數據。

我們并不能替用戶選擇所使用的網絡,他們很有可能使用一個開放的,任何人都可以竊聽的網絡,譬如一個咖啡館或者機場里面的開放WiFi網絡。普通的用戶很有可能被欺騙地隨便連上一個叫免費熱點的網絡,或者使用一個可以隨便被插入廣告的網路當中。如果攻擊者會竊聽或者篡改網路中的數據,那么用戶與服務器交換的數據就好不可信了,幸好我們還可以使用HTTPS來保證傳輸的安全性。

HTTPS and Transport Layer Security

HTTPS最早主要用于類似于經融這樣的安全要求較高的敏感網絡,不過現在日漸被各種各樣的網站鎖使用,譬如我們常用的社交網絡或者搜索引擎。HTTPS協議使用的是TLS協議,一個優于SSL協議的標準來保障通信安全。只要配置與使用得當,就能有效抵御竊聽與篡改,從而有效保護我們將要去訪問的網站。用更加技術化的方式說,HTTPS能夠有效保障數據機密性與完整性,并且能夠完成用戶端與客戶端的雙重驗證。

隨著面臨的風險日漸增多,我們應該將所有的網絡數據當做敏感數據并且進行加密傳輸。已經有很多的瀏覽器廠商宣稱要廢棄所有的非HTTPS的請求,乃至于當用戶訪問非HTTPS的網站的時候給出明確的提示。很多基于HTTP/2的實現都只支持基于TLS的通信,所以我們現在更應當在全部地方使用HTTPS。

目前如果要大范圍推廣使用HTTPS還是有一些障礙的,在一個很長的時間范圍內使用HTTPS會被認為造成很多的計算資源的浪費,不過隨著現代硬件與瀏覽器的發展,這點計算資源已經不足為道。早期的SSL協議與TLS協議只支持一個IP地址分配一個整數,不過現在這種限制所謂的SNI的協議擴展來解決。另外,從一個證書認證機構獲取證書也會打消一些用戶使用HTTPS的念頭,不過下面我們介紹的像Let"s Encrypt這樣的免費的服務就可以打破這種障礙。

Get a Server Certificate

對于網站的安全認證依賴于TLS的底層的支持,如果客戶端只是根據網站說它自己是誰就是誰,那么攻擊者可以輕易的使用中間人攻擊來模擬站點,從而繞過所有協議提供的安全機制。在使用了TLS協議之后,一個網站可以用它的公鑰證書來證明它自己是誰。在某些系統中客戶端也需要用公鑰證書證明自己是誰,不過大部分情況下受限于為用戶管理證書的復雜性,這個并沒有廣泛使用。除非一個網站證書的真實性已經經過了驗證,不然客戶端在收到一個證書的時候也要通過一定的手段來驗證證書的真實性。而在Web瀏覽器或者其他的應用中,往往是通過一個第三方的稱作CA的機構來管理證書并且提供驗證功能,包括驗證這個證書與證書所屬網站的真實性。

如果我們通過其他渠道已經能夠提前得知某個證書是否可信,那也就沒必要再經過第三方機構進行仲裁。譬如一個移動APP或者其他應用在分發的時候就會內置一些證書從而在使用時來驗證站點是否真實可信。大部分關于HTTPS是否可信的指示會在瀏覽器訪問某個HTTPS的站點的時候顯示出來,如果沒有的話瀏覽器會顯示一個告警信息來警告用戶不要訪問不可信的站點。

在測試的時候我們可以自己創建配置一個證書用于HTTPS認證,不過如果你要提供服務給普通用戶使用,那么還是需要從可信的第三方CA機構來獲取可信的證書。對于很多開發者而言,一個免費的CA證書是個不錯的選擇。當你搜索CA的時候,你可能會遇到幾個不同等級的證書。最常見的就是Domain Validation(DV),用于認證一個域名的所有者。再往上就是所謂的Organization Validation(OV)與Extended Validation(EV),包括了驗證這些證書的請求機構的信息。雖然高級別的證書需要額外的消耗,不過還是很值得的。

Configure Your Server

當你申請到了證書之后,你就可以開始配置你的服務器支持HTTPS了。雖然HTTPS啊,包括TLS/SSL的原理好像要個密碼學的PHD學位才能理解,但是要把他們配置著用起來還是很容易的呦。不同的加密算法與站點使用的協議的版本差異會大大影響到它能夠提供的通信的安全級別。所以咋才能一方面保證我們站點的安全性另一方面又保證那些使用老版本的瀏覽器的用戶也能正常使用網站服務呢?這里要推薦下Mozilla提供的Security/Server Side TLS工具,可以協助來自動創建適用的Web服務器的配置。

Use HTTPS for Everything

現在我們經常碰到一些網站僅僅只用HTTPS來保護部分資源,有些情況下只會保護一些對于敏感資源的提交操作。另一些情況下,部分網站只會將HTTPS用于自認為敏感的資源上,譬如一個用戶登錄之后才能見到的東西往往是HTTPS加密的。而現在的麻煩事還有很多站點并未使用HTTPS來保護自己,導致整個網站還處于被中間人攻擊的危險之下。筆者很是建議這類網站應該直接關閉掉HTTP端口從而強制性讓用戶轉到HTTPS,雖然這并不是一個理想的解決方案,不過估計是最好的解決方法。

如果是在Web瀏覽器中呈現的資源,那可以添加一個HTTP請求轉發的配置,來將所有的HTTP請求轉發到HTTPS端口上,譬如:

# Redirect requests to /content to use HTTPS (mod_rewrite is required)
RewriteEngine On
RewriteCond %{HTTPS} != on [NC]
RewriteCond %{REQUEST_URI} ^/content(/.*)?
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
Use HSTS

讓用戶從HTTP遷移到HTTPS可以來避免使用原始的HTTP請求帶來的風險。為了幫助站點把用戶從HTTP遷移到HTTPS,現代的瀏覽器支持一個非常強力的安全特征叫做HSTS(HTTP Strict Transport Security),來告訴瀏覽器我這個站點只會接收來自于HTTPS的請求。這個特性最早來自于2009年的Moxie Marlinspike"s提出的一個用于演示基于HTTP的潛在危險的SSL剝離攻擊。可以用如下的設置來啟用這個特性:

Strict-Transport-Security: max-age=15768000

上述的設置會告訴瀏覽器只和使用HTTPS的站點進行交互,HSTS是一個非常重要的強制使用HTTPS的特性。一旦開啟之后,瀏覽器會自動把不安全的HTTP請求切換到HTTPS,盡管用戶沒有顯式的輸入"https://"。而在瀏覽器端開啟HSTS特性只需要添加如下的一行代碼:


    ...

    # HSTS (mod_headers is required) (15768000 seconds = 6 months)
    Header always set Strict-Transport-Security "max-age=15768000"

不過現在并不是所有的瀏覽器都支持HSTS特性,你可以通過訪問 Can I use. 來看看你面向的用戶常用的瀏覽器能不能使用。

Protect Cookies

瀏覽器目前有內建的安全機制來避免包含敏感信息的Cookie暴露出來。在Cookie中設置secure標識位能夠強制讓瀏覽器只會用HTTPS來傳遞Cookie,如果你已經使用了HSTS也要記得這樣設置來保護Cookie。

Other Risks

即使你全站都用了HTTPS,也還是有幾個地方可能導致敏感信息的泄露的。譬如如果你直接把敏感數據放在URL里面,然后這個敏感的URL又被緩存在了瀏覽器的歷史記錄里。除此之后,如果包含了敏感信息的站點被鏈接到了其他的網站中,那么在用戶點擊鏈接之后整個敏感數據就會被放在Referer Header中然后傳送過去,然后就呵呵了。另外,有時候因為大家都懂的原因我們會使用一些代理然后允許他們監控HTTPS的流量,也是有危險地,這個時候就要在Header中來關閉緩存從而降低風險。筆者建議你可以參考OWASP Transport Protection Layer Cheat Sheet 來收獲一些有用的建議。

Verify Your Configuration

最后一步,你要仔細驗證你的配置是否有效。有很多的在線工具可以幫你做這件事,譬如SSL Lab的SSL Server Test能夠幫你深度分析你的HTTPS的配置,再看看是不是有啥地方配錯了。這個工具會在發現了新的攻擊手段與協議更新之后實時更新,所以多用用它還是個很不錯的事情嗷。

In Summary

啥地方都要用HTTPS

采用HSTS來強制使用HTTPS

別忘了從可信的證書機構中請求可信證書

不要亂放你的私鑰

用合理的配置工具來生成可靠地HTTPS配置

在Cookie中設置"secure"標識

不要把敏感的數據放在URL中

隔一段時間就要好好看看你的HTTPS的配置,表過時了

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/11163.html

相關文章

  • PHPer書單

    摘要:想提升自己,還得多看書多看書多看書下面是我收集到的一些程序員應該看得書單及在線教程,自己也沒有全部看完。共勉吧當然,如果你有好的書想分享給大家的或者覺得書單不合理,可以去通過進行提交。講師溫銘,軟件基金會主席,最佳實踐作者。 想提升自己,還得多看書!多看書!多看書!下面是我收集到的一些PHP程序員應該看得書單及在線教程,自己也沒有全部看完。共勉吧!當然,如果你有好的書想分享給大家的或者...

    jimhs 評論0 收藏0
  • 】《精通使用AngularJS開發Web App》(二) --- 框架概覽,雙向數據綁定,MVC

    摘要:本書的這一部分將為隨后的章節打下基礎,會涵蓋模板,模塊化,和依賴注入。本書的小例子中我們會使用未經壓縮的,開發友好的版本,在的上。作用域也可以針對特定的視圖來擴展數據和特定的功能。 上一篇:【譯】《精通使用AngularJS開發Web App》(一) 下一篇:【譯】《精通使用AngularJS開發Web App》(三) 原版書名:Mastering Web Application D...

    geekidentity 評論0 收藏0
  • 2017-07-06 前端日報

    摘要:前端日報精選專題之類型判斷下百度生態構建發布基于的解決方案將全面支持從綁定,看語言發展和框架設計掘金譯機器學習與一付費問答上線,向你心目中的大牛提問吧產品技術日志中文第期團隊技術信息流建設翻譯基于路由的異步組件加載個必備的裝逼 2017-07-06 前端日報 精選 JavaScript專題之類型判斷(下) · Issue #30 · mqyqingfeng/Blog 百度Web生態構...

    shiguibiao 評論0 收藏0
  • 微服務簡介

    摘要:微服務簡介微服務架構是一種架構概念,旨在通過將功能分解到各個離散的服務中以實現對解決方案的解耦。每個微服務僅關注于完成一件任務并很好地完成該任務。服務異常自動隔離。微服務架構挑戰服務規模大,部署運維管理難度大。 微服務簡介 微服務架構(Microservice Architecture)是一種架構概念,旨在通過將功能分解到各個離散的服務中以實現對解決方案的解耦。 微服務是一種架構風格,...

    darcrand 評論0 收藏0
  • 網絡與安全

    摘要:面試網絡了解及網絡基礎對端傳輸詳解與攻防實戰本文從屬于筆者的信息安全實戰中滲透測試實戰系列文章。建議先閱讀下的網絡安全基礎。然而,該攻擊方式并不為大家所熟知,很多網站都有的安全漏洞。 面試 -- 網絡 HTTP 現在面試門檻越來越高,很多開發者對于網絡知識這塊了解的不是很多,遇到這些面試題會手足無措。本篇文章知識主要集中在 HTTP 這塊。文中知識來自 《圖解 HTTP》與維基百科,若...

    Integ 評論0 收藏0

發表評論

0條評論

yanest

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<