ESAPI學習筆記

     ESAPI是owasp提供的一套API級別的web應用解決方案,本人經過對ESAPI和其提供的demo源碼學習發現,關鍵的不是對其所提供的API的使用,而是其web應用安全防護體系的構建的思想。好比,您不必定要使用ESAPI去實現日誌系統,而是應該明白,一套好的日誌系統應該是怎麼樣子的,應具有什麼樣的特性等。

此外,在引入使用時可能會遇到很多麻煩,因此讀者應根據自身的業務特性和需求進行整合,而不是一味的去粘貼和拼接。

1Authentication

測試用於登陸認證的ESAPI接口的步驟:html

1.1、建立用戶(方法的實現請參考FileBasedAuthenticator .javajava

         1.1.1Authenticator instance = ESAPI.authenticator(); //實例化mysql

         1.1.2User user = instance.createUser(accountName, password, password);  //users.txt         中建立一個新用戶,【遺留問題:在createUser()中並未發現是寫到users.txt文件】web

         1.1.3instance.getUser(accountName).enable(); //使能帳戶正則表達式

         1.1.4instance.getUser(accountName).unlock(); //解鎖帳戶算法

1.2、用戶登陸(方法的實現請參考AbstractAuthenticator .javasql

/*shell

         1.2.1、必須預先在ESAPI.properties文件中設置UsernameParameterNamePasswordParameterName參數,由於login()會使用這兩個參數的值去http請求中獲取用戶輸入的用戶名和密碼。好比說,若是UsernameParameterName的值爲username,那麼login()會在http請求中去找username字段並獲取其值(用戶名)。數據庫

         1.2.2、該函數用來檢查發送該請求的用戶是否已登陸,若是沒有就重定向讓其登陸,內部實現的具體步驟以下:apache

         1) 檢查用戶是否已登陸並存在會話中

             a. 若是是,確認會話最長時間和閒置操做時間是否到達

             b. 若是步驟1知足條件則步驟可跳過

    2) 若是不知足步驟1,則須要對用戶的憑證(用戶名和密碼)進行有效驗證

             a.建議使用ESAPI接口

                       loginWithUsernameAndPassword(HttpServletRequest, HttpServletResponse)

                            接口來驗證用戶憑證

    3) 記錄用戶本次登陸的主機IP

    4) 驗證本次請求的方式是不是安全的(好比POST+SSL

    5) 驗證用戶帳戶是否容許登陸

             a. 驗證用戶沒有被禁用、過時和鎖定等

    6) 將用戶分配到會話變量中 

*/

【遺留問題:同一個用戶重複登陸時,是否只建立一個user對象再綁定多個session?】

User user = ESAPI.authenticator().login(HTTPServletRequest, HTTPServletResponse);

         DefaultUser user = (DefaultUser) getUserFromSession();//檢查用戶是否已登陸

                   HttpSession session = ESAPI.httpUtilities().getCurrentRequest().getSession(false);

        if (session == null) return null;

        return ESAPI.httpUtilities().getSessionAttribute(USER);

         user = getUserFromRememberToken();//【遺留問題:選記住我纔會用到,未理解】

         user = (DefaultUser) loginWithUsernameAndPassword(request);//若是沒登陸則要求用戶進行認證(hash[username+id]值和users.txt對比),並返回user對象

         user.setLastHostAddress(request.getRemoteHost());//記錄用戶最後一次成功登陸的主機IP

         ESAPI.httpUtilities().assertSecureRequest(ESAPI.currentRequest());//驗證請求是否使用POST+SSL方式傳輸

         if (user.isAnonymous()||!user.isEnabled()||user.isLocked()||user.isExpired()||user.isSessionTimeout()||user.isSessionAbsoluteTimeout())//各類用戶狀態條件判斷

                   user.logout();//強制用戶註銷

         user.setLocale(request.getLocale());//【遺留問題:未理解】

         /* 爲用戶建立會話 */

    HttpSession session = request.getSession();//若是當前請求不存在有效session則建立一個,若是存在就返回當前的

    user.addSession(session);//將會話綁定到user對象中,一個用戶可能有多個session

    session.setAttribute(USER, user);//user對象存儲到USER

setCurrentUser(user);//將用戶設置爲當前登陸用戶

 

1.3、用戶註銷

User user = ESAPI.authenticator().logout;

1.4、關於ESAPI.authenticator().login(HTTPServletRequest, HTTPServletResponse)對每一個請求的處理邏輯。

clip_image001

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


2Session Management

2.1、用戶登陸後更新session id的接口(防止會話定置攻擊):

javax.servlet.http.HttpSession ESAPI.httpUtilities().changeSessionIdentifier(javax.servlet.http.HttpServletRequest request);

接口內部實現說明:將當前session數據拷貝到新session,並使當前session失效,並將新session綁定到當前user對象中,並返回新的session

2.2、爲URL增長CSRF token

2.2.1、爲指定URL增長CSRF TOKEN

String transferFundsHref = "/SwingSet/main?function=TransferFunds&lab";

<a href='<%=ESAPI.httpUtilities().addCSRFToken(transferFundsHref)%>' >Transfer Funds</a>

說明:在url末尾添加的csrftoken值等於user.getCSRFToken()

2.2.2、在transferFundsHref的頁面裏驗證request攜帶的和userCSRF token是否一致。

ESAPI.httpUtilities().verifyCSRFToken();

         if ( !user.getCSRFToken().equals( token ) ) {   //驗證二者是否一致

                            throw new IntrusionException("Authentication failed",

3AccessControl

3.1、角色權限驗證:

3.1.1、接口:ESAPI.accessController().assertAuthorizedForURL(java.lang.String url)

3.1.2、說明:檢查當前用戶對應的角色是否有權限訪問url,權限的定義在esapi\fbac-policies\URLAccessRules.txt文件中。

3.1.3、接口源碼分析:

ESAPI.accessController().assertAuthorizedForURL(string url)

         this.assertAuthorized("AC 1.0 URL", new Object[] {url});

/*

         esapi\ESAPI-AccessControlPolicy.xml文件中獲取name「AC 1.0 URL」的訪問控制信息:

clip_image003

*/

                   AccessControlRule rule = (AccessControlRule)ruleMap.get(key);

/*

    key對應的(此例key等於"AC 1.0 URL")對應的訪問控制信息(如上圖)做爲     AccessControlRule接口的構造函數的入參(參考   AccessControlRule.java),   即順序調用瞭如下3個函數:

    void setPolicyParameters(P policyParameter);//P爲訪問控制信息

    P getPolicyParameters();//該函數未重寫,默認爲空,故不執行

    boolean isAuthorized(R runtimeParameter)//此處R爲空,故在下面調用

*/

       isAuthorized = rule.isAuthorized(runtimeParameter);

/*

    此處runtimeParameter等於string url,通過setPolicyParameters()的設置,此  處調用isAuthorized()實際上等於調用FileBaseACRs.java中定義的   isAuthorizedForURL()即實際效果等於isAuthorizedForURL(string url)請參   考第45點的分析。

*/

 

3.1.4void setPolicyParameters()的分析(源碼在DelegatingACR.java):

void setPolicyParameters(DynaBeanACRParameter policyParameter)

    delegateClassName =

       policyParameter.getString("delegateClass", "").trim()

    methodName =

       policyParameter.getString("delegateMethod", "").trim();

    parameterClassNames =

       policyParameter.getStringArray("parameterClasses");

/*

    由以上截圖可知,此例的delegateClassName爲:

    org.owasp.esapi.reference.accesscontrol.FileBasedACRs

    methodName爲:isAuthorizedForURL

    parameterClassNames爲:java.lang.String

*/

    Class delegateClass = getClass(delegateClassName, "delegate");

    Class parameterClasses[] = getParameters(parameterClassNames);

/*

    經過getClass獲取FileBasedACRs類,【疑問:parameterClasses[]是什麼呢?】

*/

         this.delegateMethod = delegateClass.getMethod(methodName, parameterClasses);

/*

    根據方法名來從FileBasedACRs類中獲取方法,此例實際爲isAuthorizedForURL()

*/

 

3.1.5boolean isAuthorized ()的源碼分析

boolean isAuthorized(Object[] runtimeParameters)

         return ((Boolean)delegateMethod.invoke(delegateInstance,

                                               runtimeParameters)).booleanValue();

/*

    調用FileBasedACRs類中定義的回調函數,此例實際爲isAuthorizedForURL()   runtimeParameters爲要檢查的內容,好比要訪問的URLservicefunctionfile等, 此列爲URL

*/

 

3.1.6boolean isAuthorizedForURL()的源碼分析

    urlMap = loadRules("URLAccessRules.txt");

/*

    故實際定義URL訪問控制權限的文件是URLAccessRules.txt,其它相似的還有 FunctionAccessRules.txtDataAccessRules.txt等等,由以上的分析可知,實 

    際上最終會對哪一個權限控制文件作檢查是由void assertAuthorized(Object key,  

    Object runtimeParameter)key決定的,key的值都在ESAPI-AccessControlPolicy.xml 文件中定義了,目前可能的值爲"AC 1.0 Data""AC 1.0 File""AC 1.0 Function""AC 1.0   Service""AC 1.0 URL"

    補充說明: ESAPI提供的頂層接口(好比assertAuthorizedForURL())已經幫咱們定義  好了要調用的key值了(如本例),所以實際上只須要修改權限控制文件  URLAccessRules.txtFunctionAccessRules.txt等)就能夠了。

*/

                   return matchRule(urlMap, url);

/*

         URLAccessRules.txt檢查當前用戶的角色以及該角色是否有訪問url的權限,

    URLAccessRules.txt內容以下圖所示:

    clip_image005

*/    

【遺留問題】:

         是否是在過濾器中設置ESAPIESAPI.authenticator().login()ESAPI.accessController().assertAuthorizedForURL()就能夠解決每個請求的認證和權限驗證問題了?

3.2、直接對象引用:

3.2.1、使用隨機映射表對象的樣例代碼:

<%@ page import="org.owasp.esapi.reference.RandomAccessReferenceMap"%>

<%

         Set fileSet = new HashSet();

         ArrayList list = new ArrayList();

         list.add(msgID0);     //將須要映射的資源的直接引用名(此處爲message id)添加到list

         list.add(msgID1);

         ……

         fileSet.addAll(list);

         RandomAccessReferenceMap MsgIDMap = new RandomAccessReferenceMap(fileSet);

         /*調用ESAPI接口生成隨機映射表對象*/

         HttpSession sess =          ESAPI.httpUtilities().getCurrentRequest().getSession(false);

    sess.setAttribute("MsgIDMap ", MsgIDMap);

         /*

                   此時應將映射表對象存放到安全的地方,好比:session

         */

         String indirect = instance.getIndirectReference(msgID0));

         /*

                   獲取要被訪問的資源的間接引用值,該值由ESAPI接口隨機生成,而且每次進行映        射時值都會動態產生變化,所以,若是用戶每次登陸時進行重映射,那麼用戶在瀏                   覽器端看到的間接引用值也會每次都不同,也大大增長了防護CSRF攻擊的能力。

         */

         String href = "http://www.test.com?messageid=";

%>

        

         <a href="<%=href + indirect %>">點擊讀取消息;

         /*

                   將提供給用戶讀取消息的連接返回給用戶,用戶最終看到的連接將帶上間接引用值。

                   例如:http://www.test.com?messageid=DfDsQK

         */

【說明】:當要映射的資源較多時,使用資源映射表可能會消耗較多的內存。

【遺留問題】:同一個用戶重複登陸都要從新映射?不一樣類型的資源(好比消息id、用戶id和設備id等等)應當映射到不一樣的表中仍是能夠所有映射到一個表中?

 

3.2.2、處理來自用戶請求的樣例代碼:

<%

         HttpSession sess =          ESAPI.httpUtilities().getCurrentRequest().getSession(false);

    RandomAccessReferenceMap MsgIDMap =

    (RandomAccessReferenceMap) sess.getAttribute("MsgIDMap ");

         /*

                   從當前登陸用戶的session中還原出資源的隨機映射表對象。

         */

         String indMsgID = request.getParameter( " messageid " );

        String directMsgID = (String) MsgIDMap.getDirectReference(indMsgID);

         /*

                   獲取客戶端傳過來的間接索引值,再經過間接索引值獲得直接引用對象的值,若是                   該值爲空,表示用戶傳過來了一個非法的間接索引值,此時getDirectReference                          拋出一個AccessControlException異常,應用系統應在異常中作適當處理,好比將                            該異常行爲記錄到日誌中。

         */

%>

3.2.3、服務器處理攜帶用戶資源標籤請求的流程圖

 

clip_image006

 

 


4Input Validation

4.1、使用自定義的正則表達式規則驗證用戶的輸入數據。

4.1.1、接口說明:

接口1

java.lang.String getValidInput(java.lang.String context, java.lang.String input, java.lang.String type, int maxLength, boolean allowNull)

功能說明:使用esapi/validation.properties文件中定義的正則表達式去驗證用戶的輸入數據。

參數說明:

context:任意定義的字符串,主要用於日誌打印信息。

Input:須要驗證的輸入字符。

Type:選擇須要使用的一種正則表達式(見4.1.2)。

MaxLenth:容許輸入字符的最大長度。

AllowNull:是否容許輸入空字符(true爲容許,false爲不容許)。

返回:通過規範化和驗證過濾後的字符串【遺留問題:實際驗證時好像未返回字符串】

 

接口2

isValidInput(java.lang.String context, java.lang.String input, java.lang.String type, int maxLength, boolean allowNull)

功能與getValidInput()同樣,但不返回字符串,僅驗證經過時返回true,不然返回false

4.1.2validation.properties文件的正則表達式定義以下:

clip_image008

4.1.3、樣例代碼:

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

type = "SafeString"; //使用validation.properties文件定義的SafeString正則表達式規則

         try {

                   ESAPI.validator().getValidInput(

                                     "Swingset Validation Secure Exercise", input, type,

                                     200, false);

         } catch (ValidationException e) {

                   /*當檢測到輸入字符串不匹配正則表達式時產生該異常,應進行適當處理*/

                   input = "Validation attack detected";

                   request.setAttribute("userMessage", e.getUserMessage());

                   request.setAttribute("logMessage", e.getLogMessage());

         } catch (Exception e) {

                   input = "exception thrown";

                   request.setAttribute("logMessage", e.getMessage());

         }

 

接口3void assertValidFileUpload(java.lang.String context,

java.lang.String filepath, java.lang.String filename, java.io.File parent, byte[] content, int maxBytes, java.util.List<java.lang.String> allowedExtensions, boolean allowNull)

功能說明:對上傳文件的路徑、文件名、擴展名和文件大小進行檢查。

參數說明:略。

函數分析:

void assertValidFileUpload(String context, String directorypath, String filename, File parent, byte[] content, int maxBytes, List<String> allowedExtensions, boolean allowNull)

                  getValidFileName( context, filename, allowedExtensions, allowNull );

                            getValidInput( context, input, "FileName", 255, true );

                   getValidDirectoryPath( context, directorypath, parent, allowNull );

                            fileValidator.getValidInput( context, canonicalPath, "DirectoryName", 255, false);

                   getValidFileContent( context, content, maxBytes, allowNull );

                            esapiMaxBytes = ESAPI.securityConfiguration().getAllowedFileUploadSize();

                   /* FileNameDirectoryName 正則表達式都在ESAPI.properties全局文件中定義*/

 

注意事項:若是沒有canonicalize參數,表示該API默認對輸入數據進行canonicalize,不然須要使用canonicalize參數去指定是否須要對輸入數據進行canonicalize通常狀況下,咱們都默認使用不帶canonicalize參數的API,表示默認對輸入數據進行canonicalize

更多owasp數據驗證API請參考在線官方文檔:

URLhttp://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/index.html

接口路徑:org.owasp.esapi->Validator->Method Summary

4.2、在富文本應用系統中防護XSS攻擊。

應用系統容許用戶輸入自定義的html代碼,咱們稱之爲「富文本」,此類系統允許相似<,>之類的危險標籤的存在(即輸出時原樣攜帶<,>這樣的標籤),此場景下咱們須要如下API

java.lang.String getValidSafeHTML(java.lang.String context, java.lang.String input, int maxLength, boolean allowNull)

功能說明:對用戶輸入的富文本數據進行有效過濾,防止XSS

參數說明:

context:任意定義的字符串,主要用於日誌打印信息。

Input:須要驗證的富文本輸入數據。

maxLenth:容許輸入字符的最大長度。

AllowNull:是否容許輸入空字符(true爲容許,false爲不容許)。

返回:通過規範化和驗證的安全的html內容,該內容中的bodyattributesCSSURLs等都不會包含惡意的腳步代碼。

樣例:

輸入:<p>test <b>this</b> <script>alert(document.cookie)</script><i>right</i> now</p>

輸出:<p>test <b>this</b> alert(document.cookie)<i>right</i> now</p>

若是此時對<,>標籤進行html編碼再輸出就會改變原意,達不到想要的顯示效果:&lt;p&gt;test &lt;b&gt;this&lt;&#x2f;b&gt; &lt;i&gt;right&lt;&#x2f;i&gt; now&lt;&#x2f;p&gt;

5Output Encoding/Escaping

5.1Canonicalize

術語解釋:canonicalize是指將數據轉換或解碼成一個常見字符集的過程。這裏的數據能夠是通過多重混合編碼的。好比:%3cscript%3ealert(%22xss%22)%3c%2fscript%3e還原成<script>alert("xss")</script>在對輸入數據進行過濾以前應進行規範化!

接口1java.lang.String

canonicalize(java.lang.String input, boolean strict)

功能說明:將編碼過的數據還原爲其最簡化的形式。

參數說明:

Input:輸入數據。

strict:指定是否對輸入數據進行多重和混合編碼的檢測,true時將觸發IntrusionException,但不返回數據,而false將直接返回canonicalize後的數據。

返回:canonicalize後的數據。

 

5.2、對輸出到瀏覽器的數據進行編碼/轉義

如下內容摘自《web安全開發規範v1.1à反射型、存儲型XSS安全規則:

將用戶數據輸出到html body某處時,必須通過html轉義,好比:

<body>...【用戶數據】...</body>

<div>...【用戶數據】...</div>

以及其它普通的html標籤,好比p, b, td等等。

ESAPI sample

String safe =

ESAPI.encoder().encodeForHTML( request.getParameter( "input" ) );

將用戶數據輸出到html 標籤的屬性時,必須通過標籤屬性的轉義。

注意:不包含href, src, style和事件處理函數屬性(好比onmouseover)。

<div attr=...【用戶數據】...>content</div>    //數據不在引號內

<div attr='... 【用戶數據】...'>content</div>  //數據在單引號內

<div attr="...【用戶數據】...">content</div>  //數據在雙引號內

ESAPI sample

String safe =

ESAPI.encoder().encodeForHTMLAttribute( request.getParameter( "input" ) );

將用戶數據輸出到JavaScript數據域時,必須通過JavaScript轉義。

注意:用戶數據必須在引號內,不然轉義後數據仍然是不安全的。

<script>alert('... 【用戶數據】...')</script>   //數據在帶引號的字符串內

<script>x='... 【用戶數據】...'</script>  //數據在帶引號的表達式內

<div onmouseover="x='... 【用戶數據】...'"</div>

ESAPI sample

String safe =

ESAPI.encoder().encodeForJavaScript( request.getParameter( "input" ) );

將用戶數據輸出到URL的參數時,必須通過URL轉義。

<a href="http://www.somesite.com/x/y/z?test=...【用戶數據】...">link</a >

ESAPI sample

String safe =

ESAPI.encoder().encodeForURL( request.getParameter( "input" ) );

注意:全部基於URL的標籤屬性(好比href,src等),若是其整個或相對的URL被用戶數據控制,好比:

<a href=」 ...【用戶數據】...」>link</a>

則應先驗證URL的有效性,再進行html標籤屬性的轉義:

String userURL = request.getParameter( "userURL" )

 boolean isValidURL = ESAPI.validator().isValidInput("URLContext", userURL, "URL", 255, false);

 if (isValidURL) { 

     <a href="<%=encoder.encodeForHTMLAttribute(userURL)%>">link</a>

 }

除了以上4條規則定義的安全上下文之外,其它上下文都是沒法安全地轉義的,應避免出現,好比:

<script>...【用戶數據】...</script>  //直接輸出到js標籤內

<!--...【用戶數據】...-->           //直接輸出到註釋內

<div ... 【用戶數據】...=test />     //直接輸出到標籤屬性名

<..【用戶數據】... href="/test" />   //做爲標籤名使用

<style>...【用戶數據】...</style>    //直接輸出到CSS

……

5.3、對輸出到解析器的數據進行編碼/轉義:

接口1java.lang.String encodeForSQL(Codec codec, java.lang.String input)

功能說明:對SQL查詢語句中用戶控制的輸入數據進行編碼/轉義。

參數說明:

codec:編碼器,編碼器的種類請參考在線接口文檔àorg.owasp.esapi.codecs,針對數據查詢的編碼器有MySQLCodecOracleCodec,故目前只支持mysqloracle數據庫。

inputSQL查詢輸入數據

返回:編碼/轉義後的數據

樣例代碼:

如下內容摘自《web安全開發規範v1.1

Codec MYSQL_CODEC = new MySQLCodec ();//實例化編碼器()

String query = "SELECT user_id FROM user_data WHERE user_name = '" +

ESAPI.encoder().encodeForSQL(MYSQL_CODEC,req.getParameter("userID"))+"'and user_password = '"+ ESAPI.encoder().encodeForSQL(MYSQL_CODEC, req.getParameter("pwd")) +"'";

編碼結果樣例:

         輸入:foo" and 1 = 2

         輸出:foo\" and 1 \= 2

 

接口2java.lang.String encodeForOS(Codec codec, java.lang.String input)

功能說明:對傳遞給OS shell的輸入數據進行編碼/轉義。

參數說明:

codec:編碼器,編碼器的種類請參考在線接口文檔àorg.owasp.esapi.codecs,針對OS command shell的編碼器有WindowsCodecUnixCodec,故目前只支持mysqloracle數據庫。

input:要傳遞給OS shell的輸入數據

返回:編碼/轉義後的數據

樣例代碼:須要開發人員提供。

 

接口3java.lang.String encodeForLDAP(java.lang.String input)

功能說明:對LDAP查詢數據的編碼/轉義。

參數說明:LDAP查詢輸入數據

 

更多API請參考在線接口文檔:org.owasp.esapiàEncoder

6Cryptography

6.1、加、解密

接口1CipherText encrypt(PlainText plaintext)

功能說明:對plaintext數據進行加密,加密的算法/模式/填充方式和加密密鑰在ESAPI.properties文件中定義(默認AES128/CBC/PKCS5Padding)。

參數說明:

plaintext:須要加密的明文數據

返回:加密後的數據

樣例代碼:

String decryptedStr = request.getParameter("decrypted");

encrypted = ESAPI.encryptor().encrypt(decryptedStr);

注意事項:該接口在對須要加密的明文添加當前時間信息,所以每次加密出來的密文都不相同,在解密時將時間信息刪除便可獲得原始明文。【遺留問題:添加時間信息能加強安全性?】

 

接口2PlainText decrypt(CipherText ciphertext)

功能說明:對ciphertext數據進行解密。

參數說明:

ciphertext:須要解密的密文

返回:解密後的明文數據

樣例代碼:

String encryptedStr = request.getParameter("encrypted");

decrypted = ESAPI.encryptor().decrypt(encryptedStr);

 

接口3java.lang.String hash(java.lang.String plaintext,java.lang.String salt,int iterations)

功能說明:對數據進行哈希。

參數說明:

plaintext:須要hash的數據

Salt:用於hashsalt

Iterations:要迭代的次數【遺留問題:迭代是指重複哈希?若是是,每次都須要加salt嗎?】。

返回:hash

樣例代碼:

String hashStr = request.getParameter("hash");

hashVal = ESAPI.encryptor().hash(hashStr,」ABCDEFG」,3);

 

更多加密解密API請參考在線官方文檔:org.owasp.esapiàEncryptor

6.2、隨機數

接口1:獲取隨機字符串:

如下參考《web安全開發指南v1.1

接口:java.lang.String  ESAPI.randomizer().getRandomString(int length,char[] characterSet)

說明:從固定字符數組characterset中獲取長度爲length的隨機字符串,本接口可用於生成各類自定義長度和複雜度的隨機token,好比CSRF同步token等。

樣例代碼:

    char[] CHAR_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8'};

    char[] CHAR_LETTERS = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'};

    char[] CHAR_ALPHANUMERICS = StringUtilities.union(CHAR_LETTERS,           CHAR_DIGITS);

         ESAPI.randomizer().getRandomString(6,CHAR_ALPHANUMERICS);

執行結果樣例:0edec6cjefic6位隨機字符串。

 

接口2:獲取隨機GUID

接口:java.lang.String ESAPI.randomizer().getRandomGUID()

說明:產生32位的GUID格式的隨機字符串。

樣例代碼:略

執行結果樣例:53110e13-804a-4041-a547-09399c2791ea

 

接口3:獲取隨機整數:

接口:int ESAPI.randomizer().getRandomInteger(int min,int max)

說明:獲取minmax範圍的隨機整數。

樣例代碼:ESAPI.randomizer().getRandomInteger(-100,100)

執行結果樣例:-1155等。

 

接口4:獲取隨機文件名:

接口:java.lang.String  getRandomFilename(java.lang.String extension)

說明:生成隨機字符串做爲文件名,並添加extension做爲文件擴展名。

樣例代碼:ESAPI.randomizer().getRandomFilename("exe")

執行結果樣例:X4f0cafF0Mkj.exeCzkmUsLKFx7c.exe等。

 

接口5:獲取隨機長整數:

接口:long ESAPI.randomizer().getRandomLong()

說明:獲取隨機長整數。

樣例代碼:略

執行結果樣例:87129107706847262256703356794875845559等。

 

更多隨機函數接口請參考:

http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/index.html

org.owasp.esapiàRandomizer

7Error Handling and Logging

7.1、日誌記錄

7.1.1、日誌接口說明:        

ESAPI日誌接口定義了6個級別的日誌等級:

  • fatal (highest value)
  • error
  • warning
  • info
  • debug
  • trace (lowest value)

同時也預約義了4類日誌事件:SECURITY_SUCCESS, SECURITY_FAILURE, EVENT_SUCCESS, EVENT_FAILURE,用於區分安全相關的事件和普通事件。

和日誌相關的配置參數在ESAPI.properties設置,可配置參數:

Logger.ApplicationName:應用程序名,表示日誌是哪一個應用程序產生的。

Logger.LogEncodingRequiredtrue表示當日志包含特殊字符時自動進行轉義後再記錄。

Logger.LogApplicationNametrue表示在日誌中記錄應用程序嗎。

Logger.LogServerIPtrue表示在日誌中記錄服務器的IP

Logger.LogFileName:日誌的名稱(必須預先在存在)。

Logger.MaxLogFileSize:單個日誌文件的最大容量,超過期自動切到另一個日誌文件。

7.1.2、接口:

原型:

         Logger  getLogger(java.lang.String moduleName)

參數說明:

         moduleNamelogger使用來標記該日誌是應用程序的哪一個模塊產生的。

原型:

         Void fatal(Logger.EventType type, java.lang.String message)

參數說明:

Type:事件類型。

Message:要記錄的日誌信息。

logger相關的方法和參數請參考ESAPI在線幫忙文檔:

org.owasp.esapiàlogger

7.1.2、樣例代碼:

         WriterAppender appender = new WriterAppender(new SimpleLayout(), out);

         org.apache.log4j.Logger.getRootLogger().addAppender(appender);

 

         Logger logger = ESAPI.getLogger("LoggingTutorialModule");

         logger.fatal(Logger.SECURITY_FAILURE, " <script>alert('123')</script>");

         logger.debug(Logger.EVENT_SUCCESS, " <scr<script>ipt>alert('abc')</script> ");

 

         org.apache.log4j.Logger.getRootLogger().removeAppender(appender);

 

7.1.3、輸出結果:

181681687 [http-8443-2] FATAL SwingSetInteractive:LoggingTutorialModule  - [SECURITY FAILURE Anonymous:308755@unknown -> /SwingSetInteractive/LoggingTutorialModule] &lt;script&gt;alert&#x28;&#x27;123&#x27;&#x29;&lt;&#x2f;script&gt; (Encoded)

 

181681687 [http-8443-2] DEBUG SwingSetInteractive:LoggingTutorialModule  - [EVENT SUCCESS Anonymous:308755@unknown -> /SwingSetInteractive/LoggingTutorialModule] &lt;scr&lt;script&gt;ipt&gt;alert&#x28;&#x27;abc&#x27;&#x29;&lt;&#x2f;script&gt;  (Encoded)

 

在與具體業務相結合時,應提供足夠的信息做爲回溯的依據,應提供的信息以下:

致使事件發生的源對象(好比用戶id,用戶名等);

         對事件的描述;

         事件的結果(成功或失敗);

         事件的嚴重等級(在具體的業務事件中定義,而後調用ESAPI接口執行);

         事件的類型(在具體的業務事件中定義,而後調用ESAPI接口執行);

         發生事件的源IP和目標主機IP

         發生事件的時間。

7.2、錯誤處理

8Data Protection

8.1、數據緩存

接口:

void setNoCacheHeaders(javax.servlet.http.HttpServletResponse response)

功能說明:爲指定的response設置Cache-ControlExpires header

參數說明:

response:指定的http response,當該參數爲空時表示當前request的對應的response

返回:無

樣例代碼:

<%

         ESAPI.httpUtilities().setNoCacheHeaders();

%>

返回的http response中包含的緩存控制header以下:

Cache-Control: no-store, no-cache, must-revalidate

Pragma: no-cache

Expires: Wed, 31 Dec 1969 23:59:59 GMT

更多和數據安全相關的接口請參考:

org.owasp.esapià HTTPUtilities

 

9Http Security

9.1URL重定向

9.1.1、接口:

void sendRedirect(javax.servlet.http.HttpServletResponse response,java.lang.String location)

功能說明:對須要重定向的參數進行判斷,若是重定向的URL不符合"Redirect"正則表達式的要求,則觸發異常,並重定向回主頁。

參數說明:

response:指定的http response,當該參數爲空時表示當前request的對應的response

location:重定向的URL

樣例代碼:

<%

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

         if (redirect != null){

                 //response.sendRedirect(redirect);

                 ESAPI.httpUtilities().sendRedirect(redirect);

         }

%>

9.1.2、對sendRedirect的源代碼分析:

void sendRedirect(javax.servlet.http.HttpServletResponse response,java.lang.String location)

         ESAPI.validator().isValidRedirectLocation("Redirect", location, false)

                   ESAPI.validator().isValidInput( context, input, "Redirect", 512, allowNull);

                            /*經過ESAPI.properties文件中的Redirect正則表達式進行過濾判斷:

                            Validator.Redirect=^/SwingSet/.+,此處使用的是相對路徑,表示ESAPI只容許                                重定向到當前站點的URL*/

    response.sendRedirect(location);

 

10Interface HTTPUtilities

接口1

void addCookie(javax.servlet.http.Cookie cookie)

功能描述:添加新的cookie,併爲新cookie設置http onlysecure屬性。

 

接口2void addHeader(java.lang.String name,java.lang.String value)

功能描述:爲當前response添加新的header

 

接口3void assertSecureRequest() throws AccessControlException

功能描述:檢查當前request是不是安全的(ssl+post),若是不是則產生異常,服務器應調用該接口對全部包含敏感數據的request作檢查,保證敏感數據不會被嗅探、記錄到日誌。

 

接口4void assertSecureChannel() throws AccessControlException

功能描述:檢查當前request是不是經過SSL傳輸,若是不是則產生異常,服務器應調用該接口對全部包含敏感數據的request作檢查,保證敏感數據不會被嗅探。

 

接口5java.lang.String getCookie(java.lang.String name)

功能描述:根據cookie name來獲取cookie的值。

 

接口6java.lang.String getHeader(java.lang.String name)

功能描述:根據header name獲取當前requestheader

相關文章
相關標籤/搜索