add checkSSRF

This commit is contained in:
JoyChou
2017-09-05 20:51:25 +08:00
parent c7f1291eb2
commit f65a696286
5 changed files with 148 additions and 18 deletions

35
.idea/workspace.xml generated
View File

@@ -2,7 +2,6 @@
<project version="4">
<component name="ChangeListManager">
<list default="true" id="42982c84-cdb2-4596-b4aa-818c31fc199a" name="Default" comment="">
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/main/java/security.java" afterPath="$PROJECT_DIR$/src/main/java/security.java" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/main/java/test.java" afterPath="$PROJECT_DIR$/src/main/java/test.java" />
</list>
@@ -23,7 +22,9 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="289">
<caret line="17" column="10" lean-forward="false" selection-start-line="17" selection-start-column="10" selection-end-line="17" selection-end-column="10" />
<folding />
<folding>
<marker date="1504604535000" expanded="true" signature="89:618" ph="..." />
</folding>
</state>
</provider>
</entry>
@@ -44,8 +45,8 @@
<file leaf-file-name="security.java" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/src/main/java/security.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="163">
<caret line="10" column="0" lean-forward="true" selection-start-line="10" selection-start-column="0" selection-end-line="10" selection-end-column="0" />
<state relative-caret-position="276">
<caret line="66" column="59" lean-forward="false" selection-start-line="66" selection-start-column="59" selection-end-line="66" selection-end-column="59" />
<folding>
<element signature="n#!!doc" expanded="true" />
<element signature="imports" expanded="true" />
@@ -57,8 +58,8 @@
<file leaf-file-name="test.java" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/main/java/test.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="238">
<caret line="14" column="0" lean-forward="true" selection-start-line="14" selection-start-column="0" selection-end-line="14" selection-end-column="0" />
<state relative-caret-position="289">
<caret line="17" column="50" lean-forward="false" selection-start-line="17" selection-start-column="50" selection-end-line="17" selection-end-column="50" />
<folding />
</state>
</provider>
@@ -87,8 +88,8 @@
<option value="$PROJECT_DIR$/pom.xml" />
<option value="$PROJECT_DIR$/src/main/java/main.java" />
<option value="$PROJECT_DIR$/README.md" />
<option value="$PROJECT_DIR$/src/main/java/security.java" />
<option value="$PROJECT_DIR$/src/main/java/test.java" />
<option value="$PROJECT_DIR$/src/main/java/security.java" />
</list>
</option>
</component>
@@ -99,8 +100,6 @@
<sorting>DEFINITION_ORDER</sorting>
</component>
<component name="ProjectFrameBounds">
<option name="x" value="-1280" />
<option name="y" value="214" />
<option name="width" value="1280" />
<option name="height" value="800" />
</component>
@@ -658,15 +657,15 @@
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1504604417100</updated>
<workItem from="1504604422158" duration="2421000" />
<workItem from="1504604422158" duration="3470000" />
</task>
<servers />
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="2421000" />
<option name="totallyTimeSpent" value="3470000" />
</component>
<component name="ToolWindowManager">
<frame x="-1280" y="214" width="1280" height="800" extended-state="6" />
<frame x="0" y="0" width="1280" height="800" extended-state="0" />
<editor active="true" />
<layout>
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
@@ -750,7 +749,9 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="289">
<caret line="17" column="10" lean-forward="false" selection-start-line="17" selection-start-column="10" selection-end-line="17" selection-end-column="10" />
<folding />
<folding>
<marker date="1504604535000" expanded="true" signature="89:618" ph="..." />
</folding>
</state>
</provider>
</entry>
@@ -775,16 +776,16 @@
</entry>
<entry file="file://$PROJECT_DIR$/src/main/java/test.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="238">
<caret line="14" column="0" lean-forward="true" selection-start-line="14" selection-start-column="0" selection-end-line="14" selection-end-column="0" />
<state relative-caret-position="289">
<caret line="17" column="50" lean-forward="false" selection-start-line="17" selection-start-column="50" selection-end-line="17" selection-end-column="50" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/main/java/security.java">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="163">
<caret line="10" column="0" lean-forward="true" selection-start-line="10" selection-start-column="0" selection-end-line="10" selection-end-column="0" />
<state relative-caret-position="276">
<caret line="66" column="59" lean-forward="false" selection-start-line="66" selection-start-column="59" selection-end-line="66" selection-end-column="59" />
<folding>
<element signature="n#!!doc" expanded="true" />
<element signature="imports" expanded="true" />

View File

@@ -4,6 +4,9 @@
* Date: 2017.09.05
*/
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import com.google.common.net.InternetDomainName;
@@ -13,7 +16,7 @@ public class security {
* 检测传入的URL是否在白名单的域名里
* url需要检测的URL
* urlWList: 一级域名的域名列表比如String[] urlWList = {"joychou.com", "joychou.me"};
* 合法URL返回true非法URL返回false
* 返回值:合法URL返回true非法URL返回false
*/
public static Boolean checkUrlWlist(String url, String[] urlWList) {
try {
@@ -39,6 +42,125 @@ public class security {
}
}
/*
* 判断一个URL的IP是否是内网IP
* 如果是内网IP返回true
* 非内网IP返回false
*/
public static boolean isInnerIpFromUrl(String url) throws Exception {
String domain = getUrlDomain(url);
if (domain.equals("")) {
return true; // 异常URL当成内网IP等非法URL处理
}
String ip = DomainToIP(domain);
if(ip.equals("")){
return true; // 如果域名转换为IP异常则认为是非法URL
}
return isInnerIp(ip);
}
/*
* check SSRF (判断逻辑为判断URL的IP是否是内网IP)
* 如果是内网IP返回false表示checkSSRF不通过。否则返回true。即合法返回true
* URL只支持HTTP协议
* 设置了访问超时时间为3s
*/
public static Boolean checkSSRF(String url) {
HttpURLConnection connection;
String finalUrl = url;
try {
do {
// 判断当前请求的URL是否是内网ip
Boolean bRet = isInnerIpFromUrl(finalUrl);
if (bRet) {
return true;
}
connection = (HttpURLConnection) new URL(finalUrl).openConnection();
connection.setInstanceFollowRedirects(false);
connection.setUseCaches(false); // 设置为false手动处理跳转可以拿到每个跳转的URL
connection.setConnectTimeout(3*1000); // 设置连接超时时间为3s
//connection.setRequestMethod("GET");
connection.connect(); // 会解析dns
int responseCode = connection.getResponseCode(); // 发起网络请求
if (responseCode >= 300 && responseCode < 400) {
String redirectedUrl = connection.getHeaderField("Location");
if (null == redirectedUrl)
break;
finalUrl = redirectedUrl;
System.out.println("redirected url: " + finalUrl);
} else
break;
} while (connection.getResponseCode() != HttpURLConnection.HTTP_OK);
connection.disconnect();
} catch (Exception e) {
return false;
}
return false;
}
/*
内网IP
10.0.0.1 - 10.255.255.254 (10.0.0.0/8)
192.168.0.1 - 192.168.255.254 (192.168.0.0/16)
127.0.0.1 - 127.255.255.254 (127.0.0.0/8)
172.16.0.1 - 172.31.255.254 (172.16.0.0/12)
*/
public static boolean isInnerIp(String strIP) throws IOException {
try{
String[] ipArr = strIP.split("\\.");
if (ipArr.length != 4){
return false;
}
int ip_split1 = Integer.parseInt(ipArr[1]);
return (ipArr[0].equals("10") ||
ipArr[0].equals("127") ||
(ipArr[0].equals("172") && ip_split1 >= 16 && ip_split1 <=31) ||
(ipArr[0].equals("192") && ipArr[1].equals("168")));
}catch (Exception e) {
return false;
}
}
/*
* 域名转换为IP
* 会将各种进制的ip转为正常ip
* 167772161转换为10.0.0.1
* 127.0.0.1.xip.io转换为127.0.0.1
*/
public static String DomainToIP(String domain) throws IOException{
try {
InetAddress IpAddress = InetAddress.getByName(domain);
return IpAddress.getHostAddress();
}
catch (Exception e) {
return "";
}
}
/*
从URL中获取域名
限制为http/https协议
*/
public static String getUrlDomain(String url) throws IOException{
try {
URL u = new URL(url);
if (!u.getProtocol().startsWith("http") && !u.getProtocol().startsWith("https")) {
throw new IOException("Protocol error: " + u.getProtocol());
}
return u.getHost();
} catch (Exception e) {
return "";
}
}
public static void main(String[] args) throws Exception {
}

View File

@@ -6,9 +6,16 @@
public class test {
public static void main(String[] args) throws Exception {
// URL白名单组件测试
security checkUrl = new security();
String[] urlWList = {"joychou.com", "joychou.me"};
Boolean ret = checkUrl.checkUrlWlist("http://test.joychou.me", urlWList);
System.out.println(ret);
// SSRF组件测试
ret = checkUrl.checkSSRF("http://127.0.0.1");
System.out.println(ret);
}
}

Binary file not shown.

Binary file not shown.