使用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写的一款互联网数据传输交互工具;官方概念:互联网传输引擎

1234.PNG

官网地址: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实现,本质上还是对网页信息的获取,知道原理后在自定义此类工具方面也会有更进一步的认识。


标题:基于Java的指纹识别
作者:jyl
地址:http://jinyunlong.xyz/articles/2022/02/10/1644463604219.html