Skip to content

Commit

Permalink
bug fix
Browse files Browse the repository at this point in the history
  • Loading branch information
JoyChou93 committed Apr 6, 2020
1 parent 335bfef commit 2aa0b91
Show file tree
Hide file tree
Showing 11 changed files with 342 additions and 209 deletions.
258 changes: 97 additions & 161 deletions src/main/java/org/joychou/controller/SSRF.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,16 @@
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;
import org.springframework.web.bind.annotation.RequestParam;
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.*;
Expand All @@ -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();
}
}

Expand All @@ -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 {
Expand Down Expand Up @@ -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)
* <p>
* 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文本内容。
* <p>
* 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.";
}
}
2 changes: 1 addition & 1 deletion src/main/java/org/joychou/security/SecurityUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down
1 change: 0 additions & 1 deletion src/main/java/org/joychou/security/ssrf/SSRFChecker.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ static boolean isInternalIp(String strIP) {
}

ArrayList<String> blackSubnets = WebConfig.getSsrfBlockIps();
blackSubnets.add("10.0.0.0/8");
for (String subnet : blackSubnets) {
SubnetUtils utils = new SubnetUtils(subnet);
if (utils.getInfo().isInRange(strIP)) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/joychou/security/ssrf/SSRFException.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*
* @author JoyChou @2020-04-04
*/
class SSRFException extends RuntimeException {
public class SSRFException extends RuntimeException {

SSRFException(String s) {
super(s);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/joychou/security/ssrf/SocketHook.java
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
Loading

0 comments on commit 2aa0b91

Please sign in to comment.