目录遍历漏洞扫描器
源代码
/**
* @description : 目录遍历漏洞扫描器
* 注意; 在输入URL时 要求必须保存 ?page= 的末尾 才能保证路径合成的有效性
*/
/**
* @description : 目录遍历漏洞扫描器
* 注意; 在输入URL时 要求必须保存 ?page= 的末尾 才能保证路径合成的有效性
*/
import java.io.*;
import java.net.*;
import java.util.*;
//导入IO,网络,集合相关的标准库
public class DirectoryTraversalScanner {
public static void main(String[] args) throws Exception {
List<String> targets = new ArrayList<>();
//存放要扫描的目标基础URL 创建了一个名为targets的空列表,用于存储字符串类型的数据
//使用ArrayList可以根据实际输入的URL数量动态增长,允许用户连续输入多个URL地址,直到输入空行结束
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
//System.in 键盘输入 InputStreamReader : 把键盘的输入转换为字符 BufferedReader 给这些字符加一个缓冲区,可以一行一行的读取
System.out.println("请输入要扫描的URL(输入空行结束):");
while (true) {
String line = reader.readLine();
if (line == null || line.trim().isEmpty()) {
break; // 输入空行则结束输入
}
targets.add(line.trim());
}
//通过while(true)创建一个循环,每次读取一行,如果读到null,或者空行则跳出循环,否则将首尾去空的添加到targets集合中
if (targets.isEmpty()) {
System.out.println("没有输入任何URL,程序退出。");
return;
}
List<String> payloads = readLinesFromFile("payloads.txt");
//readLinesFromFile()方法功能是从指定文件中读取所有行内容并返回一个字符串列表
Map<String, List<String>> signatures = loadSignatures("signatures.txt");
//从该文件中加载漏洞特征签名,该方法返回一个Map结构,其中键是签名类型,值是该类型下包含的特征字符串列表,这些签名用于后续检测HTTP响应中是否包含特定的漏洞特征
for (String base : targets) {
System.out.println("🔍 扫描目标: " + base);
for (String payload : payloads) {
String fullUrl = base + URLEncoder.encode(payload, "UTF-8");
// 将目标URL与payload进行拼接,并且将payload进行编码
try {
String response = sendRequest(fullUrl);
boolean found = false;
for (Map.Entry<String, List<String>> entry : signatures.entrySet()) {
for (String keyword : entry.getValue()) {
if (response.contains(keyword)) {
System.out.println("🚨 漏洞发现!URL: " + fullUrl);
System.out.println("👉 关键字: " + keyword);
found = true;
break;
//这个break语句跳出的是内层循环,当找到一个匹配的关键字时,就不再检查当前签名类型下的其他关键字了
}
}
if (found) break;
//这个break跳出的是外层循环,当找到匹配结果时,就不再匹配新的签名类型了
}
if (!found) {
System.out.println("✅ 安全: " + fullUrl);
}
} catch (Exception e) {
System.out.println("❌ 请求失败: " + fullUrl + " → " + e.getMessage());
}
System.out.println("-----------------------------");
}
}
System.out.println("✅ 扫描完成。");
}
public static List<String> readLinesFromFile(String filename) throws IOException {
List<String> lines = new ArrayList<>();
BufferedReader br = new BufferedReader(new FileReader(filename));
String line;
while ((line = br.readLine()) != null) {
if (!line.trim().isEmpty()) {
lines.add(line.trim());
}
}
br.close();
return lines;
}
/**
* 从指定文件加载签名信息到Map中
* @param filename 包含签名信息的文件名
* @return 包含签名信息的Map,键为签名类型,值为该类型下的特征字符串列表
* @throws IOException 当文件读取出现问题时抛出
*/
public static Map<String, List<String>> loadSignatures(String filename) throws IOException {
// 创建一个空的HashMap用于存储签名信息,键为字符串,值为字符串列表
Map<String, List<String>> sigMap = new HashMap<>();
// 创建文件读取器和缓冲读取器,用于逐行读取文件内容
BufferedReader br = new BufferedReader(new FileReader(filename));
String line;
// 逐行读取文件内容,直到文件末尾
while ((line = br.readLine()) != null) {
// 如果当前行包含冒号,则认为是有效的签名行
if (line.contains(":")) {
// 按冒号分割行内容为两部分:冒号前为键,冒号后为值
String[] parts = line.split(":");
// 冒号前的部分作为Map的键
String key = parts[0];
// 冒号后的内容再按逗号分割成多个值,形成字符串列表
List<String> values = Arrays.asList(parts[1].split(","));
// 将键值对存入Map中
sigMap.put(key, values);
}
}
// 关闭文件读取器,释放资源
br.close();
// 返回包含所有签名信息的Map
return sigMap;
}
public static String sendRequest(String targetUrl) throws Exception {
URL url = new URL(targetUrl);
// 创建URL类型的对象
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 向URL建立连接
conn.setConnectTimeout(3000);
conn.setReadTimeout(3000);
conn.setRequestMethod("GET");
// 设置请求头
int status = conn.getResponseCode();
if (status != 200) throw new IOException("状态码: " + status);
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// 获取响应体,通过InputStreamReader以字符形式读取,然后通过BufferedReader来提供高效的读取方式
StringBuilder response = new StringBuilder();
// StringBuilder是一个可变的字符序列,允许高效地拼接和修改字符串内容
String inputLine;
while ((inputLine = in.readLine()) != null)
response.append(inputLine).append("\n");
in.close();
return response.toString();
}
}
思路
一、核心功能
- 实现目录遍历漏洞扫描
- 支持多URL目标输入
- 基于payload和特征签名检测漏洞
二、依赖库
- java.io.*:文件IO操作
- java.net.*:网络请求处理
- java.util.*:集合框架(列表、映射等)
三、核心流程
目标输入
- 通过BufferedReader读取键盘输入
- 存储URL到targets列表(空行结束输入)
- 输入为空时程序退出
资源加载
- 从payloads.txt读取攻击载荷(readLinesFromFile方法)
- 从signatures.txt加载漏洞特征(loadSignatures方法)
扫描逻辑
- 遍历所有目标URL
- 拼接URL与编码后的payload
- 发送HTTP请求(sendRequest方法)
- 检测响应中是否包含漏洞特征
- 输出扫描结果(漏洞/安全/请求失败)
四、关键方法
readLinesFromFile(String filename)
- 功能:读取文件内容到字符串列表
- 逻辑:按行读取,过滤空行,返回非空行列表
loadSignatures(String filename)
- 功能:加载漏洞特征到Map
- 格式:文件行需包含冒号(键:值1,值2…)
- 结构:Map<签名类型, 特征字符串列表>
sendRequest(String targetUrl)
- 功能:发送HTTP GET请求并返回响应内容
- 设置:3秒连接超时+3秒读取超时
- 处理:仅接收200状态码的响应,拼接响应内容为字符串
五、数据结构
- List targets:存储目标URL
- List payloads:存储攻击载荷
- Map<String, List> signatures:存储漏洞特征(键-特征类型,值-关键词列表)
六、输出信息
- 扫描目标提示(🔍 扫描目标: [URL])
- 漏洞发现提示(🚨 漏洞发现!URL: [完整URL] + 关键字)
- 安全提示(✅ 安全: [完整URL])
- 请求失败提示(❌ 请求失败: [完整URL] + 错误信息)
- 扫描完成提示(✅ 扫描完成。)