Python安全开发之简易目录扫描器(含详细注释)

核心代码

python 复制代码
import requests  # 导入requests库,用于发送HTTP请求,比urllib更简洁易用
import argparse  # 用于解析命令行参数
import threading  # 导入线程模块,用于创建锁对象
from concurrent.futures import ThreadPoolExecutor  # 导入线程池,用于管理多个线程并发执行
import time  # 导入时间模块,用于获取当前时间
from urllib.parse import urljoin  # 从urllib库导入urljoin函数,用于智能拼接URL

# 创建一个线程锁对象,用于在多线程环境中控制打印输出,避免多个线程同时打印造成混乱
print_lock = threading.Lock()

def dir_scan(url, path, user_agent):
    """
    目录扫描函数:检查指定URL路径是否存在
    
    参数:
    url: 目标基础URL
    path: 要测试的路径
    user_agent: 用户代理字符串,用于伪装浏览器请求
    
    功能:
    使用HEAD请求检测路径是否存在,避免下载完整内容,提高扫描效率
    """
    # 使用urljoin安全地拼接基础URL和相对路径
    # urljoin能正确处理各种情况,如基础URL末尾是否有斜杠,路径是否有前导斜杠等
    url = urljoin(url, path)
    
    # 设置HTTP请求头,伪装成真实的浏览器访问
    headers = {"User-Agent": user_agent}

    try:
        # 发送HEAD请求(只获取响应头,不下载响应体)
        # allow_redirects=True表示自动跟随重定向
        # timeout=5设置5秒超时,避免长时间等待无响应的服务器
        response = requests.head(url, headers=headers, allow_redirects=True, timeout=5)
        
        # 获取HTTP状态码
        status_code = response.status_code
        
        # 检查常见表示资源存在的状态码
        # 200: OK,资源存在
        # 301/302: 重定向,资源存在但被移动
        # 401: 需要身份验证,资源存在
        # 403: 禁止访问,资源存在但权限不足
        if status_code in [200, 301, 302, 401, 403]:
            # 使用线程锁确保打印操作的原子性,避免输出混乱
            with print_lock:
                print(f"[+] Found: {url},[status_code: {status_code}]")

    except requests.exceptions.RequestException:
        # 捕获所有requests库可能抛出的异常(如连接超时、DNS解析失败等)
        # 使用pass忽略异常,继续尝试下一个路径
        pass

def main():
    """
    主函数:解析命令行参数并启动目录扫描
    """
    # 创建命令行参数解析器
    parser = argparse.ArgumentParser(description="DirScan")
    
    # 添加必需的参数
    parser.add_argument("-u", "--url", help="目标URL")
    parser.add_argument("-w", "--wordlist", required=True, help="字典文件")
    
    # 添加可选参数,默认值为5个线程
    parser.add_argument("-t", "--threads", default=5, type=int, help="线程数")
    
    # 解析命令行参数
    args = parser.parse_args()

    # 获取解析后的参数值
    base_url = args.url
    wordlist_path = args.wordlist
    num_threads = args.threads

    # 设置用户代理字符串,伪装成Chrome浏览器
    user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"

    # 打印扫描信息
    print("-" * 60)
    print(f"[*] Target URL: {base_url}")
    print(f"[*] Wordlist: {wordlist_path}")
    print(f"[*] Threads: {num_threads}")
    print(f"[*] Start Time: {time.strftime('%Y-%m-%d %H:%M:%S')}")
    print("-" * 60)

    # 尝试读取字典文件
    try:
        with open(wordlist_path, "r", errors="ignore") as f:
            # 读取文件所有行,去除空白字符,并过滤空行
            paths = [line.strip() for line in f if line.strip()]
        print(f"[+] Total paths: {len(paths)}")
    except FileNotFoundError:
        print(f"[-] Error: File '{wordlist_path}' not found.")
        return

    # 使用线程池并发执行目录扫描
    # max_workers设置最大线程数
    with ThreadPoolExecutor(max_workers=num_threads) as executor:
        # 使用map方法将dir_scan函数应用到paths列表中的每个路径
        # lambda函数用于传递额外的参数(base_url和user_agent)
        executor.map(lambda path: dir_scan(base_url, path, user_agent), paths)

    # 打印扫描完成信息
    print("-" * 60)
    print(f"[*] Finished at: {time.strftime('%Y-%m-%d %H:%M:%S')}")
    print("scan complete")
    print("-" * 60)

if __name__ == "__main__":
    main()

requests库

用途: Python中最流行的HTTP客户端库,用于发送各种HTTP请求

特点: API简洁易用,功能强大,支持会话、cookies、文件上传等

常用方法:

  • requests.get(): 发送GET请求
  • requests.post(): 发送POST请求
  • requests.head(): 发送HEAD请求(只获取响应头)
  • requests.put(): 发送PUT请求
  • requests.delete(): 发送DELETE请求

urllib库

用途: Python标准库中的URL处理模块

组成:

  • urllib.request: 用于打开和读取URL
  • urllib.parse: 用于解析URL
  • urllib.error: 包含由urllib.request引发的异常
  • urllib.robotparser: 用于解析robots.txt文件

特点: 是Python内置库,无需安装,但API相对复杂

urljoin函数

用途: 安全地拼接基础URL和相对路径

优势:

  • 自动处理各种边界情况
  • 正确处理基础URL末尾的斜杠
  • 正确处理相对路径的前导斜杠
  • 处理相对路径中的..和.符号
示例:
python 复制代码
  from urllib.parse import urljoin
  
  # 各种情况都能正确处理
  urljoin('http://example.com/base/', 'path')  # -> http://example.com/base/path
  urljoin('http://example.com/base', 'path')   # -> http://example.com/path
  urljoin('http://example.com/base/', '/path') # -> http://example.com/path
  
相关推荐
坐吃山猪2 分钟前
Python27_协程游戏理解
开发语言·python·游戏
gCode Teacher 格码致知2 分钟前
Javascript提高:小数精度和随机数-由Deepseek产生
开发语言·javascript·ecmascript
Polar__Star3 分钟前
Redis如何利用位图快速判断数据存在性
jvm·数据库·python
2301_8176722617 分钟前
CSS如何实现优雅的间距_使用CSS Grid控制盒模型间隙
jvm·数据库·python
你说咋整就咋整17 分钟前
openGauss6.0.3 一主二从集群安装手册
数据库·python·gaussdb
Shorasul17 分钟前
JavaScript中显式创建包装对象的后果与性能损耗
jvm·数据库·python
椰猫子37 分钟前
Javaweb(Filter、Listener、AJAX、JSON)
java·开发语言
吕源林41 分钟前
C#怎么实现EF Core迁移 C#如何用Entity Framework Core进行数据库迁移和更新表结构【数据库】
jvm·数据库·python
qq_206901391 小时前
JavaScript中箭头函数在对象字面量方法中的潜在错误
jvm·数据库·python
盛世宏博北京1 小时前
以太网温湿度传感器运维技巧,提升设备稳定性与使用寿命
开发语言·php·以太网温湿度传感器