add checkSSRF
This commit is contained in:
35
.idea/workspace.xml
generated
35
.idea/workspace.xml
generated
@@ -2,7 +2,6 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="42982c84-cdb2-4596-b4aa-818c31fc199a" name="Default" comment="">
|
<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/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" />
|
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/main/java/test.java" afterPath="$PROJECT_DIR$/src/main/java/test.java" />
|
||||||
</list>
|
</list>
|
||||||
@@ -23,7 +22,9 @@
|
|||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="289">
|
<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" />
|
<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>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
@@ -44,8 +45,8 @@
|
|||||||
<file leaf-file-name="security.java" pinned="false" current-in-tab="true">
|
<file leaf-file-name="security.java" pinned="false" current-in-tab="true">
|
||||||
<entry file="file://$PROJECT_DIR$/src/main/java/security.java">
|
<entry file="file://$PROJECT_DIR$/src/main/java/security.java">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="163">
|
<state relative-caret-position="276">
|
||||||
<caret line="10" column="0" lean-forward="true" selection-start-line="10" selection-start-column="0" selection-end-line="10" selection-end-column="0" />
|
<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>
|
<folding>
|
||||||
<element signature="n#!!doc" expanded="true" />
|
<element signature="n#!!doc" expanded="true" />
|
||||||
<element signature="imports" expanded="true" />
|
<element signature="imports" expanded="true" />
|
||||||
@@ -57,8 +58,8 @@
|
|||||||
<file leaf-file-name="test.java" pinned="false" current-in-tab="false">
|
<file leaf-file-name="test.java" pinned="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/src/main/java/test.java">
|
<entry file="file://$PROJECT_DIR$/src/main/java/test.java">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="238">
|
<state relative-caret-position="289">
|
||||||
<caret line="14" column="0" lean-forward="true" selection-start-line="14" selection-start-column="0" selection-end-line="14" selection-end-column="0" />
|
<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 />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
@@ -87,8 +88,8 @@
|
|||||||
<option value="$PROJECT_DIR$/pom.xml" />
|
<option value="$PROJECT_DIR$/pom.xml" />
|
||||||
<option value="$PROJECT_DIR$/src/main/java/main.java" />
|
<option value="$PROJECT_DIR$/src/main/java/main.java" />
|
||||||
<option value="$PROJECT_DIR$/README.md" />
|
<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/test.java" />
|
||||||
|
<option value="$PROJECT_DIR$/src/main/java/security.java" />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
@@ -99,8 +100,6 @@
|
|||||||
<sorting>DEFINITION_ORDER</sorting>
|
<sorting>DEFINITION_ORDER</sorting>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectFrameBounds">
|
<component name="ProjectFrameBounds">
|
||||||
<option name="x" value="-1280" />
|
|
||||||
<option name="y" value="214" />
|
|
||||||
<option name="width" value="1280" />
|
<option name="width" value="1280" />
|
||||||
<option name="height" value="800" />
|
<option name="height" value="800" />
|
||||||
</component>
|
</component>
|
||||||
@@ -658,15 +657,15 @@
|
|||||||
<option name="number" value="Default" />
|
<option name="number" value="Default" />
|
||||||
<option name="presentableId" value="Default" />
|
<option name="presentableId" value="Default" />
|
||||||
<updated>1504604417100</updated>
|
<updated>1504604417100</updated>
|
||||||
<workItem from="1504604422158" duration="2421000" />
|
<workItem from="1504604422158" duration="3470000" />
|
||||||
</task>
|
</task>
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TimeTrackingManager">
|
<component name="TimeTrackingManager">
|
||||||
<option name="totallyTimeSpent" value="2421000" />
|
<option name="totallyTimeSpent" value="3470000" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ToolWindowManager">
|
<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" />
|
<editor active="true" />
|
||||||
<layout>
|
<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" />
|
<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">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="289">
|
<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" />
|
<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>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
@@ -775,16 +776,16 @@
|
|||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/src/main/java/test.java">
|
<entry file="file://$PROJECT_DIR$/src/main/java/test.java">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="238">
|
<state relative-caret-position="289">
|
||||||
<caret line="14" column="0" lean-forward="true" selection-start-line="14" selection-start-column="0" selection-end-line="14" selection-end-column="0" />
|
<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 />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/src/main/java/security.java">
|
<entry file="file://$PROJECT_DIR$/src/main/java/security.java">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="163">
|
<state relative-caret-position="276">
|
||||||
<caret line="10" column="0" lean-forward="true" selection-start-line="10" selection-start-column="0" selection-end-line="10" selection-end-column="0" />
|
<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>
|
<folding>
|
||||||
<element signature="n#!!doc" expanded="true" />
|
<element signature="n#!!doc" expanded="true" />
|
||||||
<element signature="imports" expanded="true" />
|
<element signature="imports" expanded="true" />
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
* Date: 2017.09.05
|
* Date: 2017.09.05
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import com.google.common.net.InternetDomainName;
|
import com.google.common.net.InternetDomainName;
|
||||||
|
|
||||||
@@ -13,7 +16,7 @@ public class security {
|
|||||||
* 检测传入的URL是否在白名单的域名里
|
* 检测传入的URL是否在白名单的域名里
|
||||||
* url:需要检测的URL
|
* url:需要检测的URL
|
||||||
* urlWList: 一级域名的域名列表,比如String[] urlWList = {"joychou.com", "joychou.me"};
|
* urlWList: 一级域名的域名列表,比如String[] urlWList = {"joychou.com", "joychou.me"};
|
||||||
* 合法URL返回true,非法URL返回false
|
* 返回值:合法URL返回true,非法URL返回false
|
||||||
*/
|
*/
|
||||||
public static Boolean checkUrlWlist(String url, String[] urlWList) {
|
public static Boolean checkUrlWlist(String url, String[] urlWList) {
|
||||||
try {
|
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 {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,16 @@
|
|||||||
|
|
||||||
public class test {
|
public class test {
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
// URL白名单组件测试
|
||||||
security checkUrl = new security();
|
security checkUrl = new security();
|
||||||
String[] urlWList = {"joychou.com", "joychou.me"};
|
String[] urlWList = {"joychou.com", "joychou.me"};
|
||||||
Boolean ret = checkUrl.checkUrlWlist("http://test.joychou.me", urlWList);
|
Boolean ret = checkUrl.checkUrlWlist("http://test.joychou.me", urlWList);
|
||||||
System.out.println(ret);
|
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.
Reference in New Issue
Block a user