Skip to content

Commit 2aa0b91

Browse files
committed
bug fix
1 parent 335bfef commit 2aa0b91

11 files changed

+342
-209
lines changed
+97-161
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,16 @@
11
package org.joychou.controller;
22

3-
import com.squareup.okhttp.OkHttpClient;
4-
import org.apache.commons.httpclient.HttpClient;
5-
import org.apache.commons.httpclient.methods.GetMethod;
6-
import org.apache.commons.io.IOUtils;
7-
import org.apache.http.HttpResponse;
8-
import org.apache.http.HttpStatus;
9-
import org.apache.http.client.fluent.Request;
10-
import org.apache.http.client.methods.HttpGet;
11-
import org.apache.http.impl.client.CloseableHttpClient;
12-
import org.apache.http.impl.client.HttpClients;
133
import org.joychou.security.SecurityUtil;
4+
import org.joychou.security.ssrf.SSRFException;
5+
import org.joychou.util.HttpUtils;
146
import org.joychou.util.WebUtils;
15-
import org.jsoup.Jsoup;
16-
import org.jsoup.nodes.Document;
177
import org.slf4j.Logger;
188
import org.slf4j.LoggerFactory;
199
import org.springframework.web.bind.annotation.RequestMapping;
2010
import org.springframework.web.bind.annotation.RequestParam;
2111
import org.springframework.web.bind.annotation.ResponseBody;
2212
import org.springframework.web.bind.annotation.RestController;
2313

24-
25-
import javax.imageio.ImageIO;
2614
import javax.servlet.http.HttpServletResponse;
2715
import java.io.*;
2816
import java.net.*;
@@ -40,58 +28,58 @@ public class SSRF {
4028

4129
private static Logger logger = LoggerFactory.getLogger(SSRF.class);
4230

43-
@RequestMapping("/urlConnection")
44-
public static String ssrf_URLConnection(@RequestParam String url) {
45-
try {
46-
URL u = new URL(url);
47-
URLConnection urlConnection = u.openConnection();
48-
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //send request
49-
String inputLine;
50-
StringBuilder html = new StringBuilder();
5131

52-
while ((inputLine = in.readLine()) != null) {
53-
html.append(inputLine);
54-
}
55-
in.close();
56-
return html.toString();
57-
} catch (Exception e) {
58-
logger.error(e.toString());
59-
return "fail";
32+
@RequestMapping("/urlConnection/vuln")
33+
public static String URLConnectionVuln(String url) {
34+
return HttpUtils.URLConnection(url);
35+
}
36+
37+
38+
@RequestMapping("/urlConnection/sec")
39+
public static String URLConnectionSec(String url) {
40+
41+
// Decline not http/https protocol
42+
if (!url.startsWith("http://") && !url.startsWith("https://")) {
43+
return "[-] SSRF check failed";
6044
}
45+
46+
try {
47+
SecurityUtil.startSSRFHook();
48+
return HttpUtils.URLConnection(url);
49+
} catch (SSRFException | IOException e) {
50+
return e.getMessage();
51+
} finally {
52+
SecurityUtil.stopSSRFHook();
53+
}
54+
6155
}
6256

6357

64-
@RequestMapping("/HttpURLConnection")
58+
@RequestMapping("/HttpURLConnection/sec")
6559
@ResponseBody
66-
public static String ssrf_httpURLConnection(@RequestParam String url) {
60+
public static String httpURLConnection(@RequestParam String url) {
6761
try {
68-
URL u = new URL(url);
69-
URLConnection urlConnection = u.openConnection();
70-
HttpURLConnection httpUrl = (HttpURLConnection) urlConnection;
71-
BufferedReader in = new BufferedReader(new InputStreamReader(httpUrl.getInputStream())); //send request
72-
String inputLine;
73-
StringBuilder html = new StringBuilder();
74-
75-
while ((inputLine = in.readLine()) != null) {
76-
html.append(inputLine);
77-
}
78-
in.close();
79-
return html.toString();
80-
} catch (Exception e) {
81-
logger.error(e.toString());
82-
return "fail";
62+
SecurityUtil.startSSRFHook();
63+
return HttpUtils.HTTPURLConnection(url);
64+
} catch (SSRFException | IOException e) {
65+
return e.getMessage();
66+
} finally {
67+
SecurityUtil.stopSSRFHook();
8368
}
8469
}
8570

8671

87-
@RequestMapping("/Request")
72+
// http://localhost:8080/ssrf/request/sec?url=http://www.baidu.com
73+
@RequestMapping("/request/sec")
8874
@ResponseBody
89-
public static String ssrf_Request(@RequestParam String url) {
75+
public static String request(@RequestParam String url) {
9076
try {
91-
return Request.Get(url).execute().returnContent().toString();
92-
} catch (Exception e) {
93-
logger.error(e.toString());
94-
return "fail";
77+
SecurityUtil.startSSRFHook();
78+
return HttpUtils.request(url);
79+
} catch (SSRFException | IOException e) {
80+
return e.getMessage();
81+
} finally {
82+
SecurityUtil.stopSSRFHook();
9583
}
9684
}
9785

@@ -106,7 +94,7 @@ public static String ssrf_Request(@RequestParam String url) {
10694
*/
10795
@RequestMapping("/openStream")
10896
@ResponseBody
109-
public static void ssrf_openStream(@RequestParam String url, HttpServletResponse response) throws IOException {
97+
public static void openStream(@RequestParam String url, HttpServletResponse response) throws IOException {
11098
InputStream inputStream = null;
11199
OutputStream outputStream = null;
112100
try {
@@ -136,164 +124,112 @@ public static void ssrf_openStream(@RequestParam String url, HttpServletResponse
136124
}
137125

138126

139-
@RequestMapping("/ImageIO")
127+
@RequestMapping("/ImageIO/sec")
140128
@ResponseBody
141-
public static void ssrf_ImageIO(@RequestParam String url) {
129+
public static String ImageIO(@RequestParam String url) {
142130
try {
143-
URL u = new URL(url);
144-
ImageIO.read(u); // send request
145-
} catch (Exception e) {
146-
logger.error(e.toString());
131+
SecurityUtil.startSSRFHook();
132+
HttpUtils.imageIO(url);
133+
} catch (SSRFException | IOException e) {
134+
return e.getMessage();
135+
} finally {
136+
SecurityUtil.stopSSRFHook();
147137
}
138+
139+
return "ImageIO ssrf test";
148140
}
149141

150142

151-
@RequestMapping("/okhttp")
143+
@RequestMapping("/okhttp/sec")
152144
@ResponseBody
153-
public static void ssrf_okhttp(@RequestParam String url) throws IOException {
154-
OkHttpClient client = new OkHttpClient();
155-
com.squareup.okhttp.Request ok_http = new com.squareup.okhttp.Request.Builder().url(url).build();
156-
client.newCall(ok_http).execute();
145+
public static String okhttp(@RequestParam String url) {
146+
147+
try {
148+
SecurityUtil.startSSRFHook();
149+
HttpUtils.okhttp(url);
150+
} catch (SSRFException | IOException e) {
151+
return e.getMessage();
152+
} finally {
153+
SecurityUtil.stopSSRFHook();
154+
}
155+
156+
return "okhttp ssrf test";
157157
}
158158

159159

160160
/**
161-
* http://localhost:8080/ssrf/HttpClient/sec?url=http://www.baidu.com
162-
*
163-
* @return The response of url param.
161+
* http://localhost:8080/ssrf/httpclient/sec?url=http://www.baidu.com
164162
*/
165-
@RequestMapping("/HttpClient/sec")
163+
@RequestMapping("/httpclient/sec")
166164
@ResponseBody
167-
public static String ssrf_HttpClient(@RequestParam String url) {
168-
StringBuilder result = new StringBuilder();
165+
public static String HttpClient(@RequestParam String url) {
166+
169167
try {
170168
SecurityUtil.startSSRFHook();
171-
CloseableHttpClient client = HttpClients.createDefault();
172-
HttpGet httpGet = new HttpGet(url);
173-
HttpResponse httpResponse = client.execute(httpGet); // send request
174-
BufferedReader rd = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
175-
176-
String line;
177-
while ((line = rd.readLine()) != null) {
178-
result.append(line);
179-
}
180-
181-
// SecurityUtil.stopSSRFHook();
182-
return result.toString();
183-
184-
} catch (Exception e) {
185-
return e.toString();
169+
return HttpUtils.httpClient(url);
170+
} catch (SSRFException | IOException e) {
171+
return e.getMessage();
186172
} finally {
187173
SecurityUtil.stopSSRFHook();
188174
}
175+
189176
}
190177

191178

192179
/**
193-
* https://mvnrepository.com/artifact/commons-httpclient/commons-httpclient
194-
* UserAgent: Jakarta Commons-HttpClient/3.1 (2007.08 publish)
195-
* <p>
196180
* http://localhost:8080/ssrf/commonsHttpClient/sec?url=http://www.baidu.com
197181
*/
198182
@RequestMapping("/commonsHttpClient/sec")
199183
@ResponseBody
200184
public static String commonsHttpClient(@RequestParam String url) {
201-
if (!SecurityUtil.checkSSRFByWhitehosts(url)) {
202-
return "Bad man. I got u.";
203-
}
204-
205-
HttpClient client = new HttpClient();
206-
GetMethod method = new GetMethod(url);
207-
method.setFollowRedirects(false);
208185

209186
try {
210-
// Send http request.
211-
int status_code = client.executeMethod(method);
212-
213-
// Only allow the url that status_code is 200.
214-
if (status_code != HttpStatus.SC_OK) {
215-
return "Method failed: " + method.getStatusLine();
216-
}
217-
218-
// Read the response body.
219-
byte[] resBody = method.getResponseBody();
220-
return new String(resBody);
221-
222-
} catch (IOException e) {
223-
return "Error: " + e.getMessage();
187+
SecurityUtil.startSSRFHook();
188+
return HttpUtils.commonHttpClient(url);
189+
} catch (SSRFException | IOException e) {
190+
return e.getMessage();
224191
} finally {
225-
// Release the connection.
226-
method.releaseConnection();
192+
SecurityUtil.stopSSRFHook();
227193
}
228194

229-
230195
}
231196

232197
/**
233-
* jsoup是一款Java的HTML解析器,可直接解析某个URL地址、HTML文本内容。
234-
* <p>
235198
* http://localhost:8080/ssrf/Jsoup?url=http://www.baidu.com
236199
*/
237-
@RequestMapping("/Jsoup")
200+
@RequestMapping("/Jsoup/sec")
238201
@ResponseBody
239202
public static String Jsoup(@RequestParam String url) {
203+
240204
try {
241-
Document doc = Jsoup.connect(url)
242-
.userAgent(
243-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) "
244-
+ "Chrome/64.0.3282.167 Safari/537.36")
245-
.timeout(3000)
246-
.cookie("name", "joychou") // request请求带的cookie
247-
.followRedirects(false)
248-
.execute().parse();
249-
logger.info(doc.html());
250-
} catch (MalformedURLException e) {
251-
return "exception: " + e.toString();
252-
} catch (IOException e) {
253-
logger.error(e.toString());
254-
return "exception: " + e.toString();
205+
SecurityUtil.startSSRFHook();
206+
return HttpUtils.Jsoup(url);
207+
} catch (SSRFException | IOException e) {
208+
return e.getMessage();
209+
} finally {
210+
SecurityUtil.stopSSRFHook();
255211
}
256212

257-
return "Jsoup ssrf";
258213
}
259214

260215

261216
/**
262-
* 用途:IOUtils可远程获取URL图片
263-
* 默认重定向:是
264-
* 封装类:URLConnection
265-
* http://localhost:8080/ssrf/IOUtils?url=http://www.baidu.com
217+
* http://localhost:8080/ssrf/IOUtils/sec?url=http://www.baidu.com
266218
*/
267-
@RequestMapping("/IOUtils")
268-
public static String IOUtils(@RequestParam String url) {
219+
@RequestMapping("/IOUtils/sec")
220+
public static String IOUtils(String url) {
221+
269222
try {
270-
// IOUtils.toByteArray内部用URLConnection进行了封装
271-
IOUtils.toByteArray(URI.create(url));
272-
} catch (Exception e) {
273-
return "exception: " + e.toString();
223+
SecurityUtil.startSSRFHook();
224+
HttpUtils.IOUtils(url);
225+
} catch (SSRFException | IOException e) {
226+
return e.getMessage();
227+
} finally {
228+
SecurityUtil.stopSSRFHook();
274229
}
275230

276-
return "IOUtils ssrf";
231+
return "IOUtils ssrf test";
277232
}
278233

279234

280-
/**
281-
* Safe code.
282-
* http://localhost:8080/ssrf/ImageIO/sec?url=http://www.baidu.com
283-
*/
284-
@RequestMapping("/ImageIO/sec")
285-
public static String ImageIOSec(@RequestParam String url) {
286-
try {
287-
URL u = new URL(url);
288-
if (!SecurityUtil.checkSSRFWithoutRedirect(url)) {
289-
logger.error("[-] SSRF check failed. Original Url: " + url);
290-
return "SSRF check failed.";
291-
}
292-
ImageIO.read(u); // send request
293-
} catch (Exception e) {
294-
return e.toString();
295-
}
296-
297-
return "ImageIO ssrf safe code.";
298-
}
299235
}

src/main/java/org/joychou/security/SecurityUtil.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public static boolean checkSSRFWithoutRedirect(String url) {
126126
*
127127
* @author liergou @ 2020-04-04 02:15
128128
*/
129-
public static void startSSRFHook() throws NoSuchFieldException, IOException {
129+
public static void startSSRFHook() throws IOException {
130130
SocketHook.startHook();
131131
}
132132

src/main/java/org/joychou/security/ssrf/SSRFChecker.java

-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ static boolean isInternalIp(String strIP) {
132132
}
133133

134134
ArrayList<String> blackSubnets = WebConfig.getSsrfBlockIps();
135-
blackSubnets.add("10.0.0.0/8");
136135
for (String subnet : blackSubnets) {
137136
SubnetUtils utils = new SubnetUtils(subnet);
138137
if (utils.getInfo().isInRange(strIP)) {

src/main/java/org/joychou/security/ssrf/SSRFException.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* @author JoyChou @2020-04-04
88
*/
9-
class SSRFException extends RuntimeException {
9+
public class SSRFException extends RuntimeException {
1010

1111
SSRFException(String s) {
1212
super(s);

src/main/java/org/joychou/security/ssrf/SocketHook.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*/
1313
public class SocketHook {
1414

15-
public static void startHook() throws NoSuchFieldException, IOException {
15+
public static void startHook() throws IOException {
1616
SocketHookFactory.initSocket();
1717
SocketHookFactory.setHook(true);
1818
try{

0 commit comments

Comments
 (0)