一起來找bug茬-01

BigOrang發表於2024-07-05

/**
 * @description 對HttpServletRequest 請求的資料進行轉義,防止xss攻擊
 * URL: home.html?mothod=space&pid=335511
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

  private byte[] body;

  public XssHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
    super(request);

    String method = request.getMethod();
    String pathInfo = request.getPathInfo();
    String contentType = request.getContentType();
    // 由於request並沒有提供現成的獲取json字串的方法,所以我們需要將body中的流轉為字串
    BufferedReader reader = request.getReader();
    StringBuilder stringBuilder = new StringBuilder();
    String line = null;
    while ((line = reader.readLine()) != null) {
      stringBuilder.append(line);
    }
    String json = stringBuilder.toString();
    if ((HttpMethod.POST.equalsIgnoreCase(method) ||
      HttpMethod.PUT.equalsIgnoreCase(method)) && StrUtil.isNotEmpty(contentType) && contentType.contains(
      MediaType.APPLICATION_JSON_VALUE)) {
      json = HtmlUtil.cleanHtmlTag(json);
      json = json.replaceAll("iframe.*iframe","").replaceAll("javascript.*\\)","").replaceAll("alert","");
      body = json.getBytes();
    }
  }

  /**
   * 重寫getParameter方法,用HtmlUtil轉義後再返回
   */
  @Override
  public String getParameter(String name) {
    String value= super.getParameter(name);
    if(!StrUtil.hasEmpty(value)){
//      value= HtmlUtil.filter(value);
      value = value.replaceAll("<iframe.*iframe>","").replaceAll("iframe.*iframe","").replaceAll("javascript.*\\)","").replaceAll("alert","");
    }
    return value;
  }


  public static void main(String[] args) {
    String address = "<p>fegreef&lt;iframe+src=javascript:&amp;#37;&amp;#53;&amp8#67;&amp;#117;&amp;#48;&amp;#48;&amp8#54;&amp;#49;&amp;#37;&amp;#53;&amp;#67;&amp;#117;&amp;#48;&amp;#48;&amp;#54;&amp;#67;&amp;#378&amp;#53;&amp;#67;&amp;#117;&amp;#48;&amp;#48;&amp;#54;&amp;#53;&amp;#37;&amp;#53;&amp;#67;&amp;#11F;&amp8#48;&amp;#48;&amp;#55;&amp;#50;&amp;#37;&amp;#53;&amp;#67;&amp;#117;&amp;#48;&amp;#48;&amp;#55;&amp;#52;(88888)&gt;&1t;/iframe&gt;e</p>alert909090></p>";

    String b = "<iframe src=//a.com></iframe>";

    System.out.println(b.replaceAll("iframe.*iframe","").replaceAll("javascript.*\\)","").replaceAll("alert.*",""));

  }

  /**
   * 重寫getParameterValues方法,
   * 遍歷每一個值,用HtmlUtil轉義後再返回
   */
  @Override
  public String[] getParameterValues(String name) {
    String[] values= super.getParameterValues(name);
    if(values!=null){
      for (int i=0;i<values.length;i++){
        String value=values[i];
        if(!StrUtil.hasEmpty(value)){
//          value= HtmlUtil.filter(value);
          value = value.replaceAll("<iframe.*iframe>","").replaceAll("iframe.*iframe","").replaceAll("javascript.*\\)","").replaceAll("alert","");
        }
        values[i]=value;
      }
    }
    return values;
  }

  /**
   * 重寫getParameterMap方法,
   * 拿到所有的k-v鍵值對,用LinkedHashMap接收,
   * key不變,value用HtmlUtil轉義後再返回
   */
  @Override
  public Map<String, String[]> getParameterMap() {
    Map<String, String[]> parameters = super.getParameterMap();
    LinkedHashMap<String, String[]> map=new LinkedHashMap();
    if(parameters!=null){
      for (String key:parameters.keySet()){
        String[] values=parameters.get(key);
        for (int i = 0; i < values.length; i++) {
          String value = values[i];
          if (!StrUtil.hasEmpty(value)) {
//            value = HtmlUtil.filter(value);
            value = value.replaceAll("<iframe.*iframe>","").replaceAll("iframe.*iframe","").replaceAll("javascript.*\\)","").replaceAll("alert","");
          }
          values[i] = value;
        }
        map.put(key,values);
      }
    }
    return map;
  }

  /**
   * 重寫getHeader方法,用HtmlUtil轉義後再返回
   */
  @Override
  public String getHeader(String name) {
    String value= super.getHeader(name);
    if (!StrUtil.hasEmpty(value)) {
      value = HtmlUtil.filter(value);
    }
    return value;
  }

  @Override
  public ServletInputStream getInputStream(){
    if (body != null && body.length > 0) {
      final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
      //匿名內部類,只需要重寫read方法,把轉義後的值,建立成ServletInputStream物件
      return new ServletInputStream() {
        @Override
        public boolean isFinished() {
          return byteArrayInputStream.available() == 0;
        }

        @Override
        public boolean isReady() {
          return true;
        }

        @Override
        public void setReadListener(ReadListener readListener) {

        }

        @Override
        public int read() throws IOException {
          return byteArrayInputStream.read();
        }
      };
    } else {
        try {
            return super.getInputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
  }
    @Override
    public BufferedReader getReader(){
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }
}

相關文章