2017-02-01 14 views
0

ESAPI検証を使用してURLを検証しようとしていますが、&langのために検証に失敗しています。言語パラメータを削除すると、検証は成功します。 URLパターンを確認して、このパターンが失敗した理由を教えてください。&languageパラメータのためにESAPIの検証URLが失敗しました

String url="http://google.com:000/menu.jsp?userid=test&age=22&language=hindi"; 

ESAPI.validator().getValidInput("URL", url,"URL",100000,false); 

レッグ式

Validator.URL=^(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\:\\'\\/\\\\\\+=&%\\&language\\$#_]*)?$ 

答えて

0

これは仕様によるものです。ここでは、URIが両方のURIエンコーディングとHTMLエンティティエンコーディングを含んでいることを検出しているESAPIの正規化メソッドによって入力が捕捉されているということです。

次のリリースのESAPIには、このための便利な方法が含まれていますが、いくつかの手順が必要です。

簡易メソッド:

/** 
    * {@inheritDoc} 
    */ 
    public boolean isValidURI(String context, String input, boolean allowNull) { 
     boolean isValid = false; 
     URI compliantURI = this.getRfcCompliantURI(input); 

     try{ 
      if(null != compliantURI){ 
       String canonicalizedURI = getCanonicalizedURI(compliantURI); 
       //if getCanonicalizedURI doesn't throw an IntrusionException, then the URI contains no mixed or 
       //double-encoding attacks. 
       logger.info(Logger.SECURITY_SUCCESS, "We did not detect any mixed or multiple encoding in the uri:[" + input + "]"); 
       Validator v = ESAPI.validator(); 
       //This part will use the regex from validation.properties. This regex should be super-simple, and 
       //used mainly to restrict certain parts of a URL. 
       Pattern p = ESAPI.securityConfiguration().getValidationPattern("URL"); 
       //We're doing this instead of using the normal validator API, because it will canonicalize the input again 
       //and if the URI has any queries that also happen to match HTML entities, like ¶ 
       //it will cease conforming to the regex we now specify for a URL. 
       isValid = p.matcher(canonicalizedURI).matches(); 
      } 

     }catch (IntrusionException e){ 
      logger.error(Logger.SECURITY_FAILURE, e.getMessage()); 
      isValid = false; 
     } 


     return isValid; 
    } 

    /** 
    * This does alot. This will extract each piece of a URI according to parse zone, and it will construct 
    * a canonicalized String representing a version of the URI that is safe to run regex against to it. 
    * 
    * @param dirtyUri 
    * @return 
    * @throws IntrusionException 
    */ 
    public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ 

//  From RFC-3986 section 3  
//  URI   = scheme ":" hier-part [ "?" query ] [ "#" fragment ] 
// 
//    hier-part = "//" authority path-abempty 
//       /path-absolute 
//       /path-rootless 
//       /path-empty 

//   The following are two example URIs and their component parts: 
// 
//    foo://example.com:8042/over/there?name=ferret#nose 
//    \_/ \______________/\_________/ \_________/ \__/ 
//    |   |   |   |  | 
//    scheme  authority  path  query fragment 
//    | _____________________|__ 
//    /\/      \ 
//    urn:example:animal:ferret:nose 
     Map<UriSegment, String> parseMap = new EnumMap<UriSegment, String>(UriSegment.class); 
     parseMap.put(UriSegment.SCHEME, dirtyUri.getScheme()); 
     //authority = [ userinfo "@" ] host [ ":" port ] 
     parseMap.put(UriSegment.AUTHORITY, dirtyUri.getRawAuthority()); 
     parseMap.put(UriSegment.SCHEMSPECIFICPART, dirtyUri.getRawSchemeSpecificPart()); 
     parseMap.put(UriSegment.HOST, dirtyUri.getHost()); 
     //if port is undefined, it will return -1 
     Integer port = new Integer(dirtyUri.getPort()); 
     parseMap.put(UriSegment.PORT, port == -1 ? "": port.toString()); 
     parseMap.put(UriSegment.PATH, dirtyUri.getRawPath()); 
     parseMap.put(UriSegment.QUERY, dirtyUri.getRawQuery()); 
     parseMap.put(UriSegment.FRAGMENT, dirtyUri.getRawFragment()); 

     //Now we canonicalize each part and build our string. 
     StringBuilder sb = new StringBuilder(); 

     //Replace all the items in the map with canonicalized versions. 

     Set<UriSegment> set = parseMap.keySet(); 

     SecurityConfiguration sg = ESAPI.securityConfiguration(); 
//  boolean restrictMixed = sg.getBooleanProp("AllowMixedEncoding"); 
//  boolean restrictMultiple = sg.getBooleanProp("AllowMultipleEncoding"); 
     boolean allowMixed = sg.getAllowMixedEncoding(); 
     boolean allowMultiple = sg.getAllowMultipleEncoding(); 
     for(UriSegment seg: set){ 
      String value = encoder.canonicalize(parseMap.get(seg), allowMultiple, allowMixed); 
      value = value == null ? "" : value; 
      //In the case of a uri query, we need to break up and canonicalize the internal parts of the query. 
      if(seg == UriSegment.QUERY && null != parseMap.get(seg)){ 
       StringBuilder qBuilder = new StringBuilder(); 
       try { 
        Map<String, List<String>> canonicalizedMap = this.splitQuery(dirtyUri); 
        Set<Entry<String, List<String>>> query = canonicalizedMap.entrySet(); 
        Iterator<Entry<String, List<String>>> i = query.iterator(); 
        while(i.hasNext()){ 
         Entry<String, List<String>> e = i.next(); 
         String key = (String) e.getKey(); 
         String qVal = ""; 
         List<String> list = (List<String>) e.getValue(); 
         if(!list.isEmpty()){ 
          qVal = list.get(0); 
         } 
         qBuilder.append(key) 
         .append("=") 
         .append(qVal); 

         if(i.hasNext()){ 
          qBuilder.append("&"); 
         } 
        } 
        value = qBuilder.toString(); 
       } catch (UnsupportedEncodingException e) { 
        logger.debug(Logger.EVENT_FAILURE, "decoding error when parsing [" + dirtyUri.toString() + "]"); 
       } 
      } 
      //Check if the port is -1, if it is, omit it from the output. 
      if(seg == UriSegment.PORT){ 
       if("-1" == parseMap.get(seg)){ 
        value = ""; 
       } 
      } 
      parseMap.put(seg, value); 
     } 

     return buildUrl(parseMap); 
    } 

    /** 
    * The meat of this method was taken from StackOverflow: http://stackoverflow.com/a/13592567/557153 
    * It has been modified to return a canonicalized key and value pairing. 
    * 
    * @param java URI 
    * @return a map of canonicalized query parameters. 
    * @throws UnsupportedEncodingException 
    */ 
     public Map<String, List<String>> splitQuery(URI uri) throws UnsupportedEncodingException { 
      final Map<String, List<String>> query_pairs = new LinkedHashMap<String, List<String>>(); 
      final String[] pairs = uri.getQuery().split("&"); 
      for (String pair : pairs) { 
      final int idx = pair.indexOf("="); 
      final String key = idx > 0 ? encoder.canonicalize(pair.substring(0, idx)) : pair; 
      if (!query_pairs.containsKey(key)) { 
       query_pairs.put(key, new LinkedList<String>()); 
      } 
      final String value = idx > 0 && pair.length() > idx + 1 ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8") : null; 
      query_pairs.get(key).add(encoder.canonicalize(value)); 
      } 
      return query_pairs; 
     } 

     public enum UriSegment { 
      AUTHORITY, SCHEME, SCHEMSPECIFICPART, USERINFO, HOST, PORT, PATH, QUERY, FRAGMENT 
     } 

参照コードがhere.

に住んカノニカル化の方法が適切にそこ属するとしてこの部分は、DefaultEncoderクラスにリファクタリングされますのでご注意ください。

書かれたコードは、ESAPIプロジェクトコードで大きくテストされていますが、1つまたは2つの方法を忘れている可能性があります。このesapiプロジェクトをそのままクローンしてコンパイルすることもできますが、一部の組織では、最先端の非リリースのバイナリを使用することはできません。

+0

リプレイのおかげで、ESAPIクラスをチェックしても同じことがわかりました。今、新しい問題があります。ストリングに存在するものを検証する必要があります。それは、ドイツ語、フランス語、数字、特殊文字を持つことができます...私は[。*]といくつかの他のreg式を試してみましたが、何も動作していません。有効なreg式をお勧めしますか? – Venkat

+0

@Venkat "SafeString?"のバリデーター呼び出しを使用するとどうなりますか? – avgvstvs

+0

@Venkat '[。*]'はおそらく動作していません。これは、デフォルトでは、正規表現はASCII範囲に対してのみ機能するからです。ユニコードエスケープを使うか、正規表現に '(?u)'をつけてユニコードチェックをオンにする必要があります。 – avgvstvs

関連する問題