<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                在上一講中,我們已經初步接觸了 Java 安全,今天我們將一起探討更多 Java 開發中可能影響到安全的場合。很多安全問題,在特定的上下文,存在著不同的定義,盡管本質是相似或一致的,這是由于 Java 平臺自身的特性所帶來特有的問題。今天這一講我將側重于 Java 開發者的角度談代碼安全,而不是講廣義的安全風險。 今天我要問你的問題是,如何寫出安全的 Java 代碼? ## 典型回答 這個問題可能有點寬泛,我們可以用特定類型的安全風險為例,如拒絕服務(DoS)攻擊,分析 Java 開發者需要重點考慮的點。 DoS 是一種常見的網絡攻擊,有人也稱其為“洪水攻擊”。最常見的表現是,利用大量機器發送請求,將目標網站的帶寬或者其他資源耗盡,導致其無法響應正常用戶的請求。 我認為,從 Java 語言的角度,更加需要重視的是程序級別的攻擊,也就是利用 Java、JVM 或應用程序的瑕疵,進行低成本的 DoS 攻擊,這也是想要寫出安全的 Java 代碼所必須考慮的。例如: * 如果使用的是早期的 JDK 和 Applet 等技術,攻擊者構建合法但惡劣的程序就相對容易,例如,將其線程優先級設置為最高,做一些看起來無害但空耗資源的事情。幸運的是類似技術已經逐步退出歷史舞臺,在 JDK 9 以后,相關模塊就已經被移除。 * 上一講中提到的哈希碰撞攻擊,就是個典型的例子,對方可以輕易消耗系統有限的 CPU 和線程資源。從這個角度思考,類似加密、解密、圖形處理等計算密集型任務,都要防范被惡意濫用,以免攻擊者通過直接調用或者間接觸發方式,消耗系統資源。 * 利用 Java 構建類似上傳文件或者其他接受輸入的服務,需要對消耗系統內存或存儲的上限有所控制,因為我們不能將系統安全依賴于用戶的合理使用。其中特別注意的是涉及解壓縮功能時,就需要防范[Zip bomb](https://en.wikipedia.org/wiki/Zip_bomb)等特定攻擊。 * 另外,Java 程序中需要明確釋放的資源有很多種,比如文件描述符、數據庫連接,甚至是再入鎖,任何情況下都應該保證資源釋放成功,否則即使平時能夠正常運行,也可能被攻擊者利用而耗盡某類資源,這也算是可能的 DoS 攻擊來源。 所以可以看出,實現安全的 Java 代碼,需要從功能設計到實現細節,都充分考慮可能的安全影響。 ## 考點分析 關于今天的問題,以典型的 DoS 攻擊作為切入點,將問題聚焦在 Java 開發中,我介紹了 Java 應用設計、實現的注意事項,后面還會介紹更加全面的實踐。 其實安全問題實際就是軟件的缺陷,軟件安全并不存在一勞永逸的秘籍,既離不開設計、架構中的風險分析,也離不開編碼、測試等階段的安全實踐手段。對于面試官來說,考察安全問題,除了對特定安全領域知識的考察,更多是要看面試者的 Java 編程基本功和知識的積累。 所以,我會在后面會循序漸進探討 Java 安全編程,這里面沒有什么黑科技,只有規范的開發標準,很多安全問題其實是態度問題,取決于你是否真的認真對待它。 * 我將以一些典型的代碼片段為出發點,分析一些非常容易被忽略的安全風險,并介紹安全問題頻發的熱點場景,如 Java 序列化和反序列化。 * 從軟件生命周期的角度,探討設計、開發、測試、部署等不同階段,有哪些常見的安全策略或工具。 ## 知識擴展 首先,我們一起來看一段不起眼的條件判斷代碼,這里可能有什么問題嗎? ~~~ // a, b, c 都是 int 類型的數值 if (a + b < c) { // … } ~~~ 你可能會納悶,這是再常見不過的一個條件判斷了,能有什么安全隱患? 這里的隱患是數值類型需要防范溢出,否則這不僅僅可能會帶來邏輯錯誤,在特定情況下可能導致嚴重的安全漏洞。 從語言特性來說,Java 和 JVM 提供了很多基礎性的改進,相比于傳統的 C、C++ 等語言,對于數組越界等處理要完善的多,原生的避免了[緩沖區溢出](https://en.wikipedia.org/wiki/Buffer_overflow)等攻擊方式,提高了軟件的安全性。但這并不代表完全杜絕了問題,Java 程序可能調用本地代碼,也就是 JNI 技術,錯誤的數值可能導致 C/C++ 層面的數據越界等問題,這是很危險的。 所以,上面的條件判斷,需要判斷其數值范圍,例如,寫成類似下面結構。 ~~~ if (a < c – b) ~~~ 再來看一個例子,請看下面的一段異常處理代碼: ~~~ try { // 業務代碼 } catch (Exception e) { throw new RuntimeException(hostname + port + “ doesn’t response”); } ~~~ 這段代碼將敏感信息包含在異常消息中,試想,如果是一個 Web 應用,異常也沒有良好的包裝起來,很有可能就把內部信息暴露給終端客戶。古人曾經告誡我們“言多必失”是很有道理的,雖然其本意不是指軟件安全,但盡量少暴露信息,也是保證安全的基本原則之一。即使我們并不認為某個信息有安全風險,我的建議也是如果沒有必要,不要暴露出來。 這種暴露還可能通過其他方式發生,比如某著名的編程技術網站,就被曝光過所有用戶名和密碼。這些信息都是明文存儲,傳輸過程也未必進行加密,類似這種情況,暴露只是個時間早晚的問題。 對于安全標準特別高的系統,甚至可能要求敏感信息被使用后,要立即明確在內存中銷毀,以免被探測;或者避免在發生 core dump 時,意外暴露。 第三,Java 提供了序列化等創新的特性,廣泛使用在遠程調用等方面,但也帶來了復雜的安全問題。直到今天,序列化仍然是個安全問題頻發的場景。 針對序列化,通常建議: * 敏感信息不要被序列化!在編碼中,建議使用 transient 關鍵字將其保護起來。 * 反序列化中,建議在 readObject 中實現與對象構件過程相同的安全檢查和數據檢查。 另外,在 JDK 9 中,Java 引入了過濾器機制,以保證反序列化過程中數據都要經過基本驗證才可以使用。其原理是通過黑名單和白名單,限定安全或者不安全的類型,并且你可以進行定制,然后通過環境變量靈活進行配置, 更加具體的使用你可以參考[ObjectInputFilter](https://docs.oracle.com/javase/9/docs/api/java/io/ObjectInputFilter.html)。 通過前面的介紹,你可能注意到,很多安全問題都是源于非常基本的編程細節,類似 Immutable、封裝等設計,都存在著安全性的考慮。從實踐的角度,讓每個人都了解和掌握這些原則,有必要但并不太現實,有沒有什么工程實踐手段,可以幫助我們排查安全隱患呢? **開發和測試階段** 在實際開發中,各種功能點五花八門,未必能考慮的全面。我建議沒有必要所有都需要自己去從頭實現,盡量使用廣泛驗證過的工具、類庫,不管是來自于 JDK 自身,還是 Apache 等第三方組織,都在社區的反饋下持續地完善代碼安全。 開發過程中應用代碼規約標準,是避免安全問題的有效手段。我特別推薦來自孤盡的《阿里巴巴 Java 開發手冊》,以及其配套工具,充分總結了業界在 Java 等領域的實踐經驗,將規約實踐系統性地引入國內的軟件開發,可以有效提高代碼質量。 當然,凡事都是有代價的,規約會增加一定的開發成本,可能對迭代的節奏產生一定影響,所以對于不同階段、不同需求的團隊,可以根據自己的情況對規約進行適應性的調整。 落實到實際開發流程中,以 OpenJDK 團隊為例,我們應用了幾個不同角度的實踐: * 在早期設計階段,就由安全專家組對新特性進行風險評估。 * 開發過程中,尤其是 code review 階段,應用 OpenJDK 自身定制的代碼規范。 * 利用多種靜態分析工具如[FindBugs](http://findbugs.sourceforge.net/)、[Parfait](https://labs.oracle.com/pls/apex/f?p=labs:49:::::P49_PROJECT_ID:13)等,幫助早期發現潛在安全風險,并對相應問題采取零容忍態度,強制要求解決。 * 甚至 OpenJDK 會默認將任何(編譯等)警告,都當作錯誤對待,并體現在 CI 流程中。 * 在代碼 check-in 等關鍵環節,利用 hook 機制去調用規則檢查工具,以保證不合規代碼不能進入 OpenJDK 代碼庫。 關于靜態分析工具的選擇,我們選取的原則是“足夠好”。沒有什么工具能夠發現所有問題,所以在保證功能的前提下,影響更大的是分析效率,換句話說是代碼分析的噪音高低。不管分析有多么的完備,如果太多誤報,就會導致有用信息被噪音覆蓋,也不利于后續其他程序化的處理,反倒不利于排查問題。 以上這些是為了保證 JDK 作為基礎平臺的苛刻質量要求,在實際產品中,你需要斟酌具體什么程度的要求是合理的。 **部署階段** JDK 自身的也是個軟件,難免會存在實現瑕疵,我們平時看到 JDK 更新的安全漏洞補丁,其實就是在修補這些漏洞。我最近還注意到,某大廠后臺被曝出了使用的 JDK 版本存在序列化相關的漏洞。類似這種情況,大多數都是因為使用的 JDK 是較低版本,算是可以通過部署解決的問題。 如果是安全敏感型產品,建議關注 JDK 在加解密方面的[路線圖](https://java.com/en/jre-jdk-cryptoroadmap.html),同樣的標準也應用于其他語言和平臺,很多早期認為非常安全的算法,已經被攻破,及時地升級基礎軟件是安全的必要條件。 攻擊和防守是不對稱的,只要有一個嚴重漏洞,對于攻擊者就足夠了,所以,不能對黑盒形式的部署心存僥幸,這并不能保證系統的安全,攻擊者可以利用對軟件設計的猜測,結合一系列手段,探測出漏洞。 今天我以 DoS 等典型攻擊方式為例,分析了其在 Java 平臺上的特定表現,并從更多安全編碼的細節幫你體會安全問題的普遍性,最后我介紹了軟件開發周期中的安全實踐,希望能對你的工作有所幫助。 ## 一課一練 關于今天我們討論的題目你做到心中有數了嗎?你在開發中遇到過 Java 特定的安全問題嗎?是怎么解決的呢?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看