使用Java通过ProcessBuilder类唤起cmd执行curl指令,拿到服务器信息后进行细粒度信息筛选从而做到一次简单的Web指纹识别,复现一下代码,原文地址:一次Web探测服务器技术学习总结
简单的HTTP编程,HTTP客户端编程:
//HTTP客户端编程
@Test
public void test1() {
try {
URL url = new URL("https://www.boc.cn/");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setUseCaches(false);
conn.setConnectTimeout(5000); // 请求超时5秒
// 设置HTTP头:
conn.setRequestProperty("Accept", "*/*");
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 11; Windows NT 5.1)");
// 连接并发送HTTP请求:
conn.connect();
// 判断HTTP响应是否200:
if (conn.getResponseCode() != 200) {
throw new RuntimeException("bad response");
}
// 获取所有响应Header:
Map<String, List<String>> map = conn.getHeaderFields();
for (String key : map.keySet()) {
System.out.println(key + ": " + map.get(key));
}
// 获取响应内容:
// BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// String line = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
使用Java11的HttpClient链式调用API,使用GET请求获取文本:
/**
* @author jinyunlong
* @date 2022/2/9 15:54
* @profession ICBC锅炉房保安
*/
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpClient.Version;
import java.time.Duration;
import java.util.*;
public class TestGet {
// 全局HttpClient:
static HttpClient httpClient = HttpClient.newBuilder().build();
public static void main(String[] args) throws Exception {
String url = "https://www.sina.com.cn/";
HttpRequest request = HttpRequest.newBuilder(new URI(url))
// 设置Header:
.header("User-Agent", "Java HttpClient").header("Accept", "*/*")
// 设置超时:
.timeout(Duration.ofSeconds(5))
// 设置版本:
.version(Version.HTTP_2).build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// HTTP允许重复的Header,因此一个Header可对应多个Value:
Map<String, List<String>> headers = response.headers().map();
for (String header : headers.keySet()) {
System.out.println(header + ": " + headers.get(header).get(0));
}
System.out.println(response.body().substring(0, 1024) + "...");
}
}
使用POST请求获取文本:
/**
* @author jinyunlong
* @date 2022/2/9 15:58
* @profession ICBC锅炉房保安
*/
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.*;
import java.net.http.HttpClient.Version;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
public class TestPost {
// 全局HttpClient:
static HttpClient httpClient = HttpClient.newBuilder().build();
public static void main(String[] args) {
try {
String url = "https://www.sina.com.cn/";
// String body = "account=bob&password=123456";
String body = "username=bob&password=123456";
HttpRequest request = HttpRequest.newBuilder(new URI(url))
// 设置Header:
.header("Accept", "*/*")
.header("Content-Type", "application/x-www-form-urlencoded")
// 设置超时:
.timeout(Duration.ofSeconds(5))
// 设置版本:
.version(Version.HTTP_2)
// 使用POST并设置Body:
.POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8)).build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
String s = response.body();
System.out.println(s);
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
使用curl命令获取服务器内容:
curl是用C写的一款互联网数据传输交互工具;官方概念:互联网传输引擎
官网地址:https://curl.se/
Github:https://github.com/curl/curl
使用Java调用curl指令,比较简单,使用ProcessBuilder类唤起cmd之后调用即可:
/*
* 功能说明
* Curl指令的java代码
* 输入函数:curl指令
* 返回参数:curl指令的返回值
* 例子:curl [option] [url]
* curl url //获取url的html
* curl -A "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0)" url //使用指定的浏览器去访问
* curl -I url //返回header信息
* */
public static String execCurl(String[] cmds,String chartname) {
ProcessBuilder process = new ProcessBuilder(cmds);
Process p;
try {
p = process.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream(),chartname));
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
return builder.toString();
} catch (IOException e) {
System.out.print("error");
e.printStackTrace();
}
return null;
}
//使用curl(clienturl)java请求web服务器
@Test
public void test2(){
String domain = "www.jinyunlong.xyz";
String charset = "UTF-8";
String[] cmds = {"curl","-A","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36","-L","-i",domain};
String result_html = CurlJavaUtil.execCurl(cmds,charset);
System.out.println(result_html);
}
这样调用服务器会将服务器非常详细的信息返回,这时候需要自定义类去进行功能的筛选,从而做到指纹识别。
具体功能实现:
定义webinfo实体,封装所需数据:
/**
* @author jinyunlong
* @date 2022/2/9 16:29
* @profession ICBC锅炉房保安
*/
public class WebInfo {
public String domain = "";
public String ip = "";
public String title = "";
public String http_server = "";
public String http_server_version = "";
public String language = "";
public String set_Cookie = "";
public String X_Powered_By = "";
//服务器加密的状态
public Boolean isServerCrypto = false;
public String charset = "";
public WebInfo() {
}
@Override
public String toString() {
String str = "";
str = str + this.domain + "\t";
str = str + this.ip + "\t";
str = str + this.title + "\t";
str = str + this.http_server + "\t";
str = str + this.http_server_version + "\t";
str = str + this.language + "\t";
return str;
}
public boolean checkComplete() {
return this.title != null && this.title.length() > 0 && this.http_server != null && this.http_server.length() > 0 && this.language != null && this.language.length() > 0;
}
}
服务器信息获取函数,包含javacurl方法:
import java.io.IOException;
/**
* @author jinyunlong
* @date 2022/2/9 16:31
* @profession ICBC锅炉房保安
*/
public class GetServiceInfo {
//使用curl获取服务器信息,输入url
public static void getServerInfo(WebInfo wi,String domain) throws IOException {
String charset = "utf-8";
charset = CurlJavaUtil.getCharset(domain);
//System.out.println("charset:"+charset);
if(!CurlJavaUtil.matcherChar(charset,"gb")){
charset = "utf-8";
}
//-L 跟随跳转 -i 打印详细信息
String[] cmds = {"curl","-A","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36","-L","-i",domain};
String result_html = CurlJavaUtil.execCurl(cmds,charset);
//获取的header和html信息
//System.out.println(result_html);
if(!result_html.isEmpty()){
wi.title = CurlJavaUtil.getTitle(result_html);
}else{
System.out.println("无法获取域名的html");
}
CurlJavaUtil.strName(wi,result_html);
CurlJavaUtil.LanguageCheck(wi);
CurlJavaUtil.NormalLanguageTest(wi);
// ExceptionCheck(wi);
// CheckStatus(wi);
}
}
最下面几个util类调用方法均为细粒度获取服务器信息方法,篇幅太长,不做展开。
测试方法:
@Test
public void test3(){
try {
WebInfo wi = new WebInfo();
GetServiceInfo.getServerInfo(wi,"http://www.jinyunlong.xyz/");
System.out.println("title:"+wi.title+"\nhttp_server:"+wi.http_server+"\nlanguage:"+wi.language+"\nhttp_server_version:"+wi.http_server_version+"\nisServerCrypto:"+wi.isServerCrypto);
System.out.println("---------------------");
// System.out.println(wi.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
综上一个简单的java实现Web指纹识别就完成了,可拓展功能还有非常多,市面上无论是开源还是付费的信息搜集工具功能也非常全面和强大,比如原文就给出了几款工具,无论是用python还是java实现,本质上还是对网页信息的获取,知道原理后在自定义此类工具方面也会有更进一步的认识。