2017-02-01 4 views
0

ESAPI 유효성 검사를 사용하여 URL 유효성을 검사하려고하지만 유효성 검사가 실패했습니다 (&lang). 언어 매개 변수를 제거하면 유효성 검사가 성공적입니다. 내 URL 패턴을 확인하고이 패턴이 실패한 이유를 알려주십시오.& 언어 매개 변수로 인해 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 프로젝트 코드에서 많이 테스트되었지만 한 두 가지 방법을 잊어 버렸을 수 있습니다. 있는 그대로의 esapi 프로젝트를 복제하고 컴파일 할 수 있지만 일부 조직에서는 출혈이 아닌 비 릴리스 바이너리를 사용할 수 없습니다.

+0

고마워, 나는 ESAPI 클래스를 확인하고 똑같은 것을 발견했다. 이제 나는 String에 존재하는 것을 검증 할 새로운 요구 사항을 가지고있다. 그것은 독일어, 프랑스어, 숫자, 특수 문자를 가질 수 있습니다 ... 나는 [. *]와 다른 reg 표현식으로 시도했지만 아무 것도 작동하지 않습니다. 유효한 reg 식을 제안하십시오 – Venkat

+0

@Venkat "SafeString?"에 대한 유효성 검사 호출을 사용하면 어떻게됩니까? – avgvstvs

+0

@Venkat'[. *]'는 아마도 기본적으로 정규 표현식이 ASCII 범위에서만 작동하기 때문에 작동하지 않을 것입니다. 유니 코드 이스케이프를 사용하거나 유니 코드 검사를 켜려면 정규 표현식에'(? u)'를 접두사로 사용해야합니다. – avgvstvs

관련 문제