From 2aa0b91a1689c341d3a09b93dd070c78bd2ef287 Mon Sep 17 00:00:00 2001 From: JoyChou Date: Mon, 6 Apr 2020 20:47:42 +0800 Subject: [PATCH] bug fix --- .../java/org/joychou/controller/SSRF.java | 258 +++++++----------- .../org/joychou/security/SecurityUtil.java | 2 +- .../joychou/security/ssrf/SSRFChecker.java | 1 - .../joychou/security/ssrf/SSRFException.java | 2 +- .../org/joychou/security/ssrf/SocketHook.java | 2 +- .../security/ssrf/SocketHookFactory.java | 7 +- .../joychou/security/ssrf/SocketHookImpl.java | 66 ++--- .../security/ssrf/SocketHookUtils.java | 17 +- src/main/java/org/joychou/util/HttpUtils.java | 189 +++++++++++++ src/main/java/org/joychou/util/WebUtils.java | 5 + src/main/resources/templates/index.html | 2 +- 11 files changed, 342 insertions(+), 209 deletions(-) create mode 100644 src/main/java/org/joychou/util/HttpUtils.java diff --git a/src/main/java/org/joychou/controller/SSRF.java b/src/main/java/org/joychou/controller/SSRF.java index e9c30d0e..12384717 100644 --- a/src/main/java/org/joychou/controller/SSRF.java +++ b/src/main/java/org/joychou/controller/SSRF.java @@ -1,19 +1,9 @@ package org.joychou.controller; -import com.squareup.okhttp.OkHttpClient; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.io.IOUtils; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.fluent.Request; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; import org.joychou.security.SecurityUtil; +import org.joychou.security.ssrf.SSRFException; +import org.joychou.util.HttpUtils; import org.joychou.util.WebUtils; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RequestMapping; @@ -21,8 +11,6 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; - -import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.*; @@ -40,58 +28,58 @@ public class SSRF { private static Logger logger = LoggerFactory.getLogger(SSRF.class); - @RequestMapping("/urlConnection") - public static String ssrf_URLConnection(@RequestParam String url) { - try { - URL u = new URL(url); - URLConnection urlConnection = u.openConnection(); - BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //send request - String inputLine; - StringBuilder html = new StringBuilder(); - while ((inputLine = in.readLine()) != null) { - html.append(inputLine); - } - in.close(); - return html.toString(); - } catch (Exception e) { - logger.error(e.toString()); - return "fail"; + @RequestMapping("/urlConnection/vuln") + public static String URLConnectionVuln(String url) { + return HttpUtils.URLConnection(url); + } + + + @RequestMapping("/urlConnection/sec") + public static String URLConnectionSec(String url) { + + // Decline not http/https protocol + if (!url.startsWith("http://") && !url.startsWith("https://")) { + return "[-] SSRF check failed"; } + + try { + SecurityUtil.startSSRFHook(); + return HttpUtils.URLConnection(url); + } catch (SSRFException | IOException e) { + return e.getMessage(); + } finally { + SecurityUtil.stopSSRFHook(); + } + } - @RequestMapping("/HttpURLConnection") + @RequestMapping("/HttpURLConnection/sec") @ResponseBody - public static String ssrf_httpURLConnection(@RequestParam String url) { + public static String httpURLConnection(@RequestParam String url) { try { - URL u = new URL(url); - URLConnection urlConnection = u.openConnection(); - HttpURLConnection httpUrl = (HttpURLConnection) urlConnection; - BufferedReader in = new BufferedReader(new InputStreamReader(httpUrl.getInputStream())); //send request - String inputLine; - StringBuilder html = new StringBuilder(); - - while ((inputLine = in.readLine()) != null) { - html.append(inputLine); - } - in.close(); - return html.toString(); - } catch (Exception e) { - logger.error(e.toString()); - return "fail"; + SecurityUtil.startSSRFHook(); + return HttpUtils.HTTPURLConnection(url); + } catch (SSRFException | IOException e) { + return e.getMessage(); + } finally { + SecurityUtil.stopSSRFHook(); } } - @RequestMapping("/Request") + // http://localhost:8080/ssrf/request/sec?url=http://www.baidu.com + @RequestMapping("/request/sec") @ResponseBody - public static String ssrf_Request(@RequestParam String url) { + public static String request(@RequestParam String url) { try { - return Request.Get(url).execute().returnContent().toString(); - } catch (Exception e) { - logger.error(e.toString()); - return "fail"; + SecurityUtil.startSSRFHook(); + return HttpUtils.request(url); + } catch (SSRFException | IOException e) { + return e.getMessage(); + } finally { + SecurityUtil.stopSSRFHook(); } } @@ -106,7 +94,7 @@ public static String ssrf_Request(@RequestParam String url) { */ @RequestMapping("/openStream") @ResponseBody - public static void ssrf_openStream(@RequestParam String url, HttpServletResponse response) throws IOException { + public static void openStream(@RequestParam String url, HttpServletResponse response) throws IOException { InputStream inputStream = null; OutputStream outputStream = null; try { @@ -136,164 +124,112 @@ public static void ssrf_openStream(@RequestParam String url, HttpServletResponse } - @RequestMapping("/ImageIO") + @RequestMapping("/ImageIO/sec") @ResponseBody - public static void ssrf_ImageIO(@RequestParam String url) { + public static String ImageIO(@RequestParam String url) { try { - URL u = new URL(url); - ImageIO.read(u); // send request - } catch (Exception e) { - logger.error(e.toString()); + SecurityUtil.startSSRFHook(); + HttpUtils.imageIO(url); + } catch (SSRFException | IOException e) { + return e.getMessage(); + } finally { + SecurityUtil.stopSSRFHook(); } + + return "ImageIO ssrf test"; } - @RequestMapping("/okhttp") + @RequestMapping("/okhttp/sec") @ResponseBody - public static void ssrf_okhttp(@RequestParam String url) throws IOException { - OkHttpClient client = new OkHttpClient(); - com.squareup.okhttp.Request ok_http = new com.squareup.okhttp.Request.Builder().url(url).build(); - client.newCall(ok_http).execute(); + public static String okhttp(@RequestParam String url) { + + try { + SecurityUtil.startSSRFHook(); + HttpUtils.okhttp(url); + } catch (SSRFException | IOException e) { + return e.getMessage(); + } finally { + SecurityUtil.stopSSRFHook(); + } + + return "okhttp ssrf test"; } /** - * http://localhost:8080/ssrf/HttpClient/sec?url=http://www.baidu.com - * - * @return The response of url param. + * http://localhost:8080/ssrf/httpclient/sec?url=http://www.baidu.com */ - @RequestMapping("/HttpClient/sec") + @RequestMapping("/httpclient/sec") @ResponseBody - public static String ssrf_HttpClient(@RequestParam String url) { - StringBuilder result = new StringBuilder(); + public static String HttpClient(@RequestParam String url) { + try { SecurityUtil.startSSRFHook(); - CloseableHttpClient client = HttpClients.createDefault(); - HttpGet httpGet = new HttpGet(url); - HttpResponse httpResponse = client.execute(httpGet); // send request - BufferedReader rd = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent())); - - String line; - while ((line = rd.readLine()) != null) { - result.append(line); - } - - // SecurityUtil.stopSSRFHook(); - return result.toString(); - - } catch (Exception e) { - return e.toString(); + return HttpUtils.httpClient(url); + } catch (SSRFException | IOException e) { + return e.getMessage(); } finally { SecurityUtil.stopSSRFHook(); } + } /** - * https://mvnrepository.com/artifact/commons-httpclient/commons-httpclient - * UserAgent: Jakarta Commons-HttpClient/3.1 (2007.08 publish) - *

* http://localhost:8080/ssrf/commonsHttpClient/sec?url=http://www.baidu.com */ @RequestMapping("/commonsHttpClient/sec") @ResponseBody public static String commonsHttpClient(@RequestParam String url) { - if (!SecurityUtil.checkSSRFByWhitehosts(url)) { - return "Bad man. I got u."; - } - - HttpClient client = new HttpClient(); - GetMethod method = new GetMethod(url); - method.setFollowRedirects(false); try { - // Send http request. - int status_code = client.executeMethod(method); - - // Only allow the url that status_code is 200. - if (status_code != HttpStatus.SC_OK) { - return "Method failed: " + method.getStatusLine(); - } - - // Read the response body. - byte[] resBody = method.getResponseBody(); - return new String(resBody); - - } catch (IOException e) { - return "Error: " + e.getMessage(); + SecurityUtil.startSSRFHook(); + return HttpUtils.commonHttpClient(url); + } catch (SSRFException | IOException e) { + return e.getMessage(); } finally { - // Release the connection. - method.releaseConnection(); + SecurityUtil.stopSSRFHook(); } - } /** - * jsoup是一款Java的HTML解析器,可直接解析某个URL地址、HTML文本内容。 - *

* http://localhost:8080/ssrf/Jsoup?url=http://www.baidu.com */ - @RequestMapping("/Jsoup") + @RequestMapping("/Jsoup/sec") @ResponseBody public static String Jsoup(@RequestParam String url) { + try { - Document doc = Jsoup.connect(url) - .userAgent( - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) " - + "Chrome/64.0.3282.167 Safari/537.36") - .timeout(3000) - .cookie("name", "joychou") // request请求带的cookie - .followRedirects(false) - .execute().parse(); - logger.info(doc.html()); - } catch (MalformedURLException e) { - return "exception: " + e.toString(); - } catch (IOException e) { - logger.error(e.toString()); - return "exception: " + e.toString(); + SecurityUtil.startSSRFHook(); + return HttpUtils.Jsoup(url); + } catch (SSRFException | IOException e) { + return e.getMessage(); + } finally { + SecurityUtil.stopSSRFHook(); } - return "Jsoup ssrf"; } /** - * 用途:IOUtils可远程获取URL图片 - * 默认重定向:是 - * 封装类:URLConnection - * http://localhost:8080/ssrf/IOUtils?url=http://www.baidu.com + * http://localhost:8080/ssrf/IOUtils/sec?url=http://www.baidu.com */ - @RequestMapping("/IOUtils") - public static String IOUtils(@RequestParam String url) { + @RequestMapping("/IOUtils/sec") + public static String IOUtils(String url) { + try { - // IOUtils.toByteArray内部用URLConnection进行了封装 - IOUtils.toByteArray(URI.create(url)); - } catch (Exception e) { - return "exception: " + e.toString(); + SecurityUtil.startSSRFHook(); + HttpUtils.IOUtils(url); + } catch (SSRFException | IOException e) { + return e.getMessage(); + } finally { + SecurityUtil.stopSSRFHook(); } - return "IOUtils ssrf"; + return "IOUtils ssrf test"; } - /** - * Safe code. - * http://localhost:8080/ssrf/ImageIO/sec?url=http://www.baidu.com - */ - @RequestMapping("/ImageIO/sec") - public static String ImageIOSec(@RequestParam String url) { - try { - URL u = new URL(url); - if (!SecurityUtil.checkSSRFWithoutRedirect(url)) { - logger.error("[-] SSRF check failed. Original Url: " + url); - return "SSRF check failed."; - } - ImageIO.read(u); // send request - } catch (Exception e) { - return e.toString(); - } - - return "ImageIO ssrf safe code."; - } } diff --git a/src/main/java/org/joychou/security/SecurityUtil.java b/src/main/java/org/joychou/security/SecurityUtil.java index a1c4cfc6..0b383f5d 100644 --- a/src/main/java/org/joychou/security/SecurityUtil.java +++ b/src/main/java/org/joychou/security/SecurityUtil.java @@ -126,7 +126,7 @@ public static boolean checkSSRFWithoutRedirect(String url) { * * @author liergou @ 2020-04-04 02:15 */ - public static void startSSRFHook() throws NoSuchFieldException, IOException { + public static void startSSRFHook() throws IOException { SocketHook.startHook(); } diff --git a/src/main/java/org/joychou/security/ssrf/SSRFChecker.java b/src/main/java/org/joychou/security/ssrf/SSRFChecker.java index 32373aff..3860cad9 100644 --- a/src/main/java/org/joychou/security/ssrf/SSRFChecker.java +++ b/src/main/java/org/joychou/security/ssrf/SSRFChecker.java @@ -132,7 +132,6 @@ static boolean isInternalIp(String strIP) { } ArrayList blackSubnets = WebConfig.getSsrfBlockIps(); - blackSubnets.add("10.0.0.0/8"); for (String subnet : blackSubnets) { SubnetUtils utils = new SubnetUtils(subnet); if (utils.getInfo().isInRange(strIP)) { diff --git a/src/main/java/org/joychou/security/ssrf/SSRFException.java b/src/main/java/org/joychou/security/ssrf/SSRFException.java index b27a970f..817c881e 100644 --- a/src/main/java/org/joychou/security/ssrf/SSRFException.java +++ b/src/main/java/org/joychou/security/ssrf/SSRFException.java @@ -6,7 +6,7 @@ * * @author JoyChou @2020-04-04 */ -class SSRFException extends RuntimeException { +public class SSRFException extends RuntimeException { SSRFException(String s) { super(s); diff --git a/src/main/java/org/joychou/security/ssrf/SocketHook.java b/src/main/java/org/joychou/security/ssrf/SocketHook.java index 92b8f496..4ce3509c 100644 --- a/src/main/java/org/joychou/security/ssrf/SocketHook.java +++ b/src/main/java/org/joychou/security/ssrf/SocketHook.java @@ -12,7 +12,7 @@ */ public class SocketHook { - public static void startHook() throws NoSuchFieldException, IOException { + public static void startHook() throws IOException { SocketHookFactory.initSocket(); SocketHookFactory.setHook(true); try{ diff --git a/src/main/java/org/joychou/security/ssrf/SocketHookFactory.java b/src/main/java/org/joychou/security/ssrf/SocketHookFactory.java index 51a278b7..dc6d951d 100644 --- a/src/main/java/org/joychou/security/ssrf/SocketHookFactory.java +++ b/src/main/java/org/joychou/security/ssrf/SocketHookFactory.java @@ -33,22 +33,23 @@ static void setHook(Boolean set) { } - /** - * initSocket - */ static void initSocket() { + if (socketConstructor != null) { return; } Socket socket = new Socket(); try { + // get impl field in Socket class Field implField = Socket.class.getDeclaredField("impl"); implField.setAccessible(true); Class clazz = implField.get(socket).getClass(); + SocketHookImpl.initSocketImpl(clazz); socketConstructor = clazz.getDeclaredConstructor(); socketConstructor.setAccessible(true); + } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException e) { throw new SSRFException("SocketHookFactory init failed!"); } diff --git a/src/main/java/org/joychou/security/ssrf/SocketHookImpl.java b/src/main/java/org/joychou/security/ssrf/SocketHookImpl.java index c3b9c28d..de244134 100644 --- a/src/main/java/org/joychou/security/ssrf/SocketHookImpl.java +++ b/src/main/java/org/joychou/security/ssrf/SocketHookImpl.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Constructor; @@ -21,21 +20,22 @@ public class SocketHookImpl extends SocketImpl implements SocketOptions { private static Boolean isInit = false; - static private SocketImpl socketImpl = null; - static private Method createImpl; - static private Method connectHostImpl; - static private Method connectInetAddressImpl; - static private Method connectSocketAddressImpl; - static private Method bindImpl; - static private Method listenImpl; - static private Method acceptImpl; - static private Method getInputStreamImpl; - static private Method getOutputStreamImpl; - static private Method availableImpl; - static private Method closeImpl; - static private Method shutdownInputImpl; - static private Method shutdownOutputImpl; - static private Method sendUrgentDataImpl; + + private static SocketImpl socketImpl = null; + private static Method createImpl; + private static Method connectHostImpl; + private static Method connectInetAddressImpl; + private static Method connectSocketAddressImpl; + private static Method bindImpl; + private static Method listenImpl; + private static Method acceptImpl; + private static Method getInputStreamImpl; + private static Method getOutputStreamImpl; + private static Method availableImpl; + private static Method closeImpl; + private static Method shutdownInputImpl; + private static Method shutdownOutputImpl; + private static Method sendUrgentDataImpl; private final Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -58,8 +58,12 @@ static void initSocketImpl(Class initSocketImpl) { throw new RuntimeException("InitSocketImpl failed! Hook stopped!"); } +// try { +// initSocketImpl = Class.forName("java.net.SocketImpl"); +// } catch (ClassNotFoundException e) { +// System.out.println(e.getMessage()); +// } if (!isInit) { - // createImpl = SocketHookUtils.findMethod(initSocketImpl, "create", new Class[]{boolean.class}); connectHostImpl = SocketHookUtils.findMethod(initSocketImpl, "connect", new Class[]{String.class, int.class}); connectInetAddressImpl = SocketHookUtils.findMethod(initSocketImpl, "connect", new Class[]{InetAddress.class, int.class}); @@ -83,7 +87,7 @@ static void initSocketImpl(Class initSocketImpl) { * socket base method impl */ @Override - protected void create(boolean stream) throws IOException { + protected void create(boolean stream) { try { createImpl.invoke(socketImpl, stream); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { @@ -94,7 +98,7 @@ protected void create(boolean stream) throws IOException { @Override - protected void connect(String host, int port) throws IOException { + protected void connect(String host, int port) { logger.info("host: " + host + "\tport: " + port); try { connectHostImpl.invoke(socketImpl, host, port); @@ -106,7 +110,7 @@ protected void connect(String host, int port) throws IOException { @Override - protected void connect(InetAddress address, int port) throws IOException { + protected void connect(InetAddress address, int port) { logger.info("InetAddress: " + address.toString()); @@ -121,14 +125,14 @@ protected void connect(InetAddress address, int port) throws IOException { } @Override - protected void connect(SocketAddress address, int timeout) throws IOException { + protected void connect(SocketAddress address, int timeout) { // convert SocketAddress to InetSocketAddress InetSocketAddress addr = (InetSocketAddress) address; String ip = addr.getAddress().getHostAddress(); String host = addr.getHostName(); - logger.info(String.format("[+]SocketAddress address's Hostname: %s IP: %s", host, ip)); + logger.info(String.format("[+] SocketAddress address's Hostname: %s IP: %s", host, ip)); try { if (SSRFChecker.isInternalIp(ip)) { @@ -143,7 +147,7 @@ protected void connect(SocketAddress address, int timeout) throws IOException { } @Override - protected void bind(InetAddress host, int port) throws IOException { + protected void bind(InetAddress host, int port) { try { bindImpl.invoke(socketImpl, host, port); } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException ex) { @@ -162,7 +166,7 @@ protected void listen(int backlog) { } @Override - protected void accept(SocketImpl s) throws IOException { + protected void accept(SocketImpl s) { try { acceptImpl.invoke(socketImpl, s); @@ -172,7 +176,7 @@ protected void accept(SocketImpl s) throws IOException { } @Override - protected InputStream getInputStream() throws IOException { + protected InputStream getInputStream() { InputStream inStream = null; try { @@ -186,7 +190,7 @@ protected InputStream getInputStream() throws IOException { } @Override - protected OutputStream getOutputStream() throws IOException { + protected OutputStream getOutputStream() { OutputStream outStream = null; try { @@ -200,7 +204,7 @@ protected OutputStream getOutputStream() throws IOException { } @Override - protected int available() throws IOException { + protected int available() { int result = -1; @@ -214,7 +218,7 @@ protected int available() throws IOException { } @Override - protected void close() throws IOException { + protected void close() { try { closeImpl.invoke(socketImpl); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { @@ -223,7 +227,7 @@ protected void close() throws IOException { } @Override - protected void shutdownInput() throws IOException { + protected void shutdownInput() { try { shutdownInputImpl.invoke(socketImpl); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { @@ -233,7 +237,7 @@ protected void shutdownInput() throws IOException { } @Override - protected void shutdownOutput() throws IOException { + protected void shutdownOutput() { try { shutdownOutputImpl.invoke(socketImpl); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { @@ -243,7 +247,7 @@ protected void shutdownOutput() throws IOException { } @Override - protected void sendUrgentData(int data) throws IOException { + protected void sendUrgentData(int data) { try { sendUrgentDataImpl.invoke(socketImpl, data); } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException ex) { diff --git a/src/main/java/org/joychou/security/ssrf/SocketHookUtils.java b/src/main/java/org/joychou/security/ssrf/SocketHookUtils.java index b94b82d9..00f6c275 100644 --- a/src/main/java/org/joychou/security/ssrf/SocketHookUtils.java +++ b/src/main/java/org/joychou/security/ssrf/SocketHookUtils.java @@ -6,23 +6,22 @@ class SocketHookUtils { /** * Poll the parent class to find the reflection method. + * SocksSocketImpl -> PlainSocketImpl -> AbstractPlainSocketImpl * * @author liergou @2020-04-04 01:43 */ - static Method findMethod(Class inputClazz, String findName, Class[] args) { + static Method findMethod(Class clazz, String findName, Class[] args) { - Class temp = inputClazz; - - while (temp != null) { + while (clazz != null) { try { - Method tmpMethod = temp.getDeclaredMethod(findName, args); - tmpMethod.setAccessible(true); - return tmpMethod; + Method method = clazz.getDeclaredMethod(findName, args); + method.setAccessible(true); + return method; } catch (NoSuchMethodException e) { - temp = temp.getSuperclass(); + clazz = clazz.getSuperclass(); } } return null; } -} +} \ No newline at end of file diff --git a/src/main/java/org/joychou/util/HttpUtils.java b/src/main/java/org/joychou/util/HttpUtils.java new file mode 100644 index 00000000..37eeb69a --- /dev/null +++ b/src/main/java/org/joychou/util/HttpUtils.java @@ -0,0 +1,189 @@ +package org.joychou.util; + +import com.squareup.okhttp.OkHttpClient; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.fluent.Request; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.imageio.ImageIO; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; + +/** + * @author JoyChou 2020-04-06 + */ +public class HttpUtils { + + private static Logger logger = LoggerFactory.getLogger(HttpUtils.class); + + + /** + * https://mvnrepository.com/artifact/commons-httpclient/commons-httpclient + * UserAgent is Jakarta Commons-HttpClient/3.1. Last publish at 2007.08. + * + * @param url http request url + * @return response + */ + public static String commonHttpClient(String url) { + + HttpClient client = new HttpClient(); + GetMethod method = new GetMethod(url); + + try { + client.executeMethod(method); // send request + byte[] resBody = method.getResponseBody(); + return new String(resBody); + + } catch (IOException e) { + return "Error: " + e.getMessage(); + } finally { + // Release the connection. + method.releaseConnection(); + } + } + + + public static String request(String url) { + try { + return Request.Get(url).execute().returnContent().toString(); + } catch (Exception e) { + return e.getMessage(); + } + } + + + public static String httpClient(String url) { + + StringBuilder result = new StringBuilder(); + + try { + + CloseableHttpClient client = HttpClients.createDefault(); + HttpGet httpGet = new HttpGet(url); + HttpResponse httpResponse = client.execute(httpGet); // send request + BufferedReader rd = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent())); + + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + + return result.toString(); + + } catch (Exception e) { + return e.getMessage(); + } + } + + + public static String URLConnection(String url) { + try { + URL u = new URL(url); + URLConnection urlConnection = u.openConnection(); + BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //send request + String inputLine; + StringBuilder html = new StringBuilder(); + + while ((inputLine = in.readLine()) != null) { + html.append(inputLine); + } + in.close(); + return html.toString(); + } catch (Exception e) { + logger.error(e.getMessage()); + return e.getMessage(); + } + } + + + public static String HTTPURLConnection(String url) { + try { + URL u = new URL(url); + URLConnection urlConnection = u.openConnection(); + HttpURLConnection httpUrl = (HttpURLConnection) urlConnection; + BufferedReader in = new BufferedReader(new InputStreamReader(httpUrl.getInputStream())); //send request + String inputLine; + StringBuilder html = new StringBuilder(); + + while ((inputLine = in.readLine()) != null) { + html.append(inputLine); + } + in.close(); + return html.toString(); + } catch (IOException e) { + logger.error(e.getMessage()); + return e.getMessage(); + } + } + + + /** + * Jsoup is a HTML parser about Java. + * + * @param url http request url + */ + public static String Jsoup(String url) { + try { + String useragent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) " + + "Chrome/64.0.3282.167 Safari/537.36"; + Document doc = Jsoup.connect(url) + .userAgent(useragent) + .timeout(3000) + .cookie("name", "joychou") // request cookies + //.followRedirects(false) + .execute().parse(); + return doc.outerHtml(); + } catch (IOException e) { + return e.getMessage(); + } + } + + + public static void okhttp(String url) throws IOException { + OkHttpClient client = new OkHttpClient(); + com.squareup.okhttp.Request ok_http = new com.squareup.okhttp.Request.Builder().url(url).build(); + client.newCall(ok_http).execute(); + } + + + public static void imageIO(String url) { + try { + URL u = new URL(url); + ImageIO.read(u); // send request + } catch (IOException e) { + logger.error(e.getMessage()); + } + + } + + + /** + * IOUtils which is wrapped by URLConnection can get remote pictures. + * The default setting of redirection is true. + * + * @param url http request url + */ + public static void IOUtils(String url) { + try { + IOUtils.toByteArray(URI.create(url)); + } catch (IOException e) { + logger.error(e.getMessage()); + } + } + + +} diff --git a/src/main/java/org/joychou/util/WebUtils.java b/src/main/java/org/joychou/util/WebUtils.java index 7cc16e84..4816df8e 100644 --- a/src/main/java/org/joychou/util/WebUtils.java +++ b/src/main/java/org/joychou/util/WebUtils.java @@ -17,6 +17,7 @@ public static String getRequestBody(HttpServletRequest request) throws IOExcepti return convertStreamToString(in); } + // https://stackoverflow.com/questions/309424/how-do-i-read-convert-an-inputstream-into-a-string-in-java public static String convertStreamToString(java.io.InputStream is) { java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A"); @@ -33,6 +34,7 @@ public static String json2Jsonp(String callback, String jsonStr) { return HtmlUtils.htmlEscape(callback) + "(" + jsonStr + ")"; } + public static String getFileExtension(String fullName) { Preconditions.checkNotNull(fullName); String fileName = (new File(fullName)).getName(); @@ -40,10 +42,13 @@ public static String getFileExtension(String fullName) { return dotIndex == -1 ? "" : fileName.substring(dotIndex + 1); } + public static String getNameWithoutExtension(String file) { Preconditions.checkNotNull(file); String fileName = (new File(file)).getName(); int dotIndex = fileName.lastIndexOf('.'); return dotIndex == -1 ? fileName : fileName.substring(0, dotIndex); } + + } diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index de32f6ee..671045d5 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -14,7 +14,7 @@ Cors   PathTraversal   SqlInject   - SSRF   + SSRF   RCE   ooxml XXE   xlsx-streamer XXE