Skill: szzg007/agent-p-web-recon (version 1.0.0)

--- name: web-recon description: 网站内容侦察技能。无需登录即可获取网站公开/半公开内容。使用场景：(1) 竞品分析收集公开信息，(2) 安全评估未授权访问点，(3) OSINT 情报收集，(4) 网站内容存档，(5) 监控页面变化。合法用途仅限：授权渗透测试、公开信息收集、自有系统审计。 --- # Web Recon - 网站内容侦察 ## 角色设定 **P 的侦察模式** - 用黑客思维发现暴露面，用红客原则保护边界。 ## 核心原则 1. **合法合规** - 仅用于授权测试/公开信息/自有系统 2. **被动优先** - 优先无接触方式（快照/缓存/搜索引擎） 3. **不留痕迹** - OSINT 手段不接触目标服务器 4. **道德边界** - 不绕过付费墙、不窃取敏感数据 --- ## 技术方法库 ### 方法 1: 搜索引擎快照（被动，无痕迹） ```bash # Google 缓存 https://webcache.googleusercontent.com/search?q=cache:TARGET_URL # Wayback Machine 历史快照 https://web.archive.org/web/*/TARGET_URL # 搜索引擎 site: 语法 site:target.com inurl:admin site:target.com filetype:pdf ``` **优点:** 完全被动，不留痕迹 **局限:** 依赖搜索引擎索引 ### 方法 2: 爬虫模拟（半被动） 某些网站对爬虫开放内容（SEO 需求）： ```python # 修改 User-Agent 伪装爬虫 headers = { "User-Agent": "Googlebot/2.1 (+http://www.google.com/bot.html)" } ``` **识别信号:** - 同一 URL，不同 User-Agent 返回不同内容 - robots.txt 允许爬虫访问的路径 ### 方法 3: 公共 API 探测（主动） 很多网站有未授权或弱授权的 API： ```bash # 常见 API 端点 /api/v1/posts /api/v1/users /graphql /api/feed /rss /atom.xml ``` **工具:** ```bash # 使用 gau 获取已知 URL gau target.com | grep api # 使用 waybackurls 获取历史 URL waybackurls target.com | grep -E "\.json|xml|rss" ``` ### 方法 4: 前端逻辑绕过（主动，需授权） 针对初级程序员的伪防护： ```javascript // 禁用 JavaScript 绕过登录弹窗 // 方法：浏览器 DevTools → Settings → Disable JavaScript // 直接访问渲染后的内容 // 某些 SPA 应用内容已加载，只是被遮罩层挡住 // 查看网络请求 // DevTools → Network → 查找 API 响应中的完整数据 ``` ### 方法 5: 目录扫描（主动，需授权） 发现未授权访问的路径： ```bash # 使用 dirsearch dirsearch -u https://target.com -e php,html,js,json # 使用 gobuster gobuster dir -u https://target.com -w common.txt ``` **常见暴露路径:** ``` /admin /dashboard /api/v1/export /backup/ /.git/ /config.php ``` ### 方法 6: RSS/Atom 订阅（被动） 很多网站提供公开 RSS： ```bash # 常见位置 /rss /rss.xml /feed /atom.xml /blog/rss ``` --- ## 工作流程 ### 阶段 1: 被动收集（推荐优先） ``` 1. 搜索引擎查询（site: / inurl: / filetype:） 2. Wayback Machine 历史快照 3. Google Cache 缓存 4. 检查 RSS/Atom 订阅 ``` ### 阶段 2: 半主动探测（需谨慎） ``` 1. 修改 User-Agent 测试爬虫权限 2. 探测公共 API 端点 3. 检查 robots.txt 配置 ``` ### 阶段 3: 主动扫描（仅限授权） ``` 1. 目录扫描（dirsearch/gobuster） 2. 前端逻辑测试（禁用 JS） 3. 网络请求分析（DevTools） ``` --- ## 输出格式 ```markdown ## 侦察报告：TARGET_URL ### 发现内容 | 路径 | 内容类型 | 访问方式 | 风险等级 | |------|----------|----------|----------| | /api/posts | JSON | 公开 | 中 | | /admin | HTML | 未授权 | 高 | ### 敏感暴露 - [ ] 用户数据泄露 - [ ] 内部路径暴露 - [ ] 配置文件可访问 - [ ] 备份文件未保护 ### 建议修复 1. ... 2. ... ``` --- ## 安全与合规 ### 合法用途 ✅ - 授权渗透测试 - 自有系统安全审计 - 公开信息收集（OSINT） - 竞品公开信息分析 ### 非法用途 ❌ - 未授权访问付费内容 - 窃取用户隐私数据 - 绕过商业系统的访问控制 - 恶意信息收集 ### 风险评估 | 方法 | 法律风险 | 技术风险 | 建议 | |------|----------|----------|------| | 搜索引擎快照 | 无 | 无 | 安全 | | Wayback Machine | 无 | 无 | 安全 | | 爬虫模拟 | 低 | 低 | 注意 robots.txt | | API 探测 | 中 | 中 | 仅限授权 | | 目录扫描 | 高 | 高 | 必须授权 | --- ## 参考资源 - **OWASP 测试指南** → `references/owasp-testing.md` - **OSINT 框架** → `references/osint-framework.md` - **工具脚本** → `scripts/` 目录 --- *P 注：技术无罪，关键在用途。永远站在防御者一边。*

path: references/tools.md
content: # Web Recon 工具清单

## 被动收集（无痕迹）

### 搜索引擎
| 工具 | 用途 | 链接 |
|------|------|------|
| Google | 通用搜索 + 缓存 | `site:domain.com` |
| Bing | 备用搜索引擎 | `site:domain.com` |
| DuckDuckGo | 隐私搜索 | - |
| Shodan | IoT/服务器搜索 | shodan.io |
| Censys | 证书/主机搜索 | censys.io |

### 历史快照
| 工具 | 用途 | 链接 |
|------|------|------|
| Wayback Machine | 网页历史存档 | web.archive.org |
| Archive.today | 网页快照 | archive.today |
| Google Cache | 搜索引擎缓存 | `cache:url` |

### URL 发现
| 工具 | 安装 | 用途 |
|------|------|------|
| gau | `go install github.com/lc/gau` | 获取已知 URL |
| waybackurls | `go install github.com/tomnomnom/waybackurls` | 历史 URL |
| hakrawler | `go install github.com/hakluke/hakrawler` | 爬虫发现 |

---

## 半主动探测（低风险）

### 爬虫模拟
```bash
# 修改 User-Agent
curl -A "Googlebot/2.1" https://target.com

# 常见爬虫 UA
Googlebot/2.1 (+http://www.google.com/bot.html)
Bingbot/2.0 (+http://www.bing.com/bingbot.htm)
Mozilla/5.0 (compatible; YandexBot/3.0)
```

### RSS/Feed 发现
```bash
# 常见位置
/rss /rss.xml /feed /atom.xml /blog/rss

# 使用 hurl 测试
hurl --head https://target.com/rss
```

### 公共 API 探测
```bash
# 使用 gau + grep
gau target.com | grep -E "api|json|xml"

# 使用 httpx 探测
echo target.com | httpx -path /api/v1 -status-code
```

---

## 主动扫描（需授权）

### 目录扫描
| 工具 | 安装 | 特点 |
|------|------|------|
| dirsearch | `pip install dirsearch` | 经典，速度快 |
| gobuster | `go install github.com/OJ/gobuster` | Go 编写，稳定 |
| ffuf | `go install github.com/ffuf/ffuf` | 高度可配置 |
| feroxbuster | `cargo install feroxbuster` | Rust 编写，极速 |

### 常用字典
- `common.txt` - 通用路径
- `directory-list-2.3-medium.txt` - 中等规模
- `raft-medium-words.txt` - 综合字典
- 自定义字典 - 针对特定技术栈

### 前端分析
```bash
# 使用 browser 工具
# DevTools → Network → 分析 API 请求
# DevTools → Application → 查看 LocalStorage/SessionStorage
# DevTools → Sources → 查看 JS 源码
```

---

## 自动化脚本

### 内置脚本
| 脚本 | 用途 |
|------|------|
| `scripts/recon.sh` | 综合侦察（被动 + 主动） |
| `scripts/cache_viewer.py` | 缓存/快照查看器 |
| `scripts/scaffold.py` | 项目脚手架生成 |

### 快速命令
```bash
# 被动侦察
./recon.sh https://target.com --passive

# 主动侦察（需授权）
./recon.sh https://target.com --active

# 查看历史快照
python cache_viewer.py https://target.com --wayback
```

---

## 输出示例

### 报告结构
```markdown
## 侦察报告：target.com

### 发现内容
| 路径 | 内容 | 访问方式 | 风险 |
|------|------|----------|------|
| /api/posts | JSON | 公开 | 中 |
| /admin | HTML | 未授权 | 高 |

### 敏感暴露
- [ ] 用户数据
- [ ] 内部路径
- [ ] 配置文件
- [ ] 备份文件

### 修复建议
1. 添加鉴权中间件
2. 配置 robots.txt
3. 移除敏感路径
```

---

*P 注：工具是手段，不是目的。理解原理比记住命令更重要。*


path: scripts/cache_viewer.py
content: #!/usr/bin/env python3
"""
缓存/快照查看器
用法：python cache_viewer.py <url> [--wayback|--google|--archive]
"""

import sys
import webbrowser
import requests
import json
from datetime import datetime

def get_wayback_snapshots(url):
    """获取 Wayback Machine 历史快照"""
    cdx_url = f"http://web.archive.org/cdx/search/cdx?url={url}&output=json&limit=20"
    try:
        resp = requests.get(cdx_url, timeout=10)
        data = resp.json()
        if len(data) <= 1:
            print("未找到历史快照")
            return []
        
        print(f"\n📦 Wayback Machine - 找到 {len(data)-1} 个快照:\n")
        snapshots = []
        for row in data[1:]:  # 跳过表头
            timestamp = row[1]
            original = row[2]
            status = row[4]
            archive_url = f"https://web.archive.org/web/{timestamp}/{original}"
            snapshots.append({
                'time': timestamp,
                'url': original,
                'status': status,
                'archive_url': archive_url
            })
            print(f"  [{timestamp}] {status} - {archive_url}")
        
        return snapshots
    except Exception as e:
        print(f"错误：{e}")
        return []

def get_google_cache_url(url):
    """生成 Google Cache 链接"""
    return f"https://webcache.googleusercontent.com/search?q=cache:{url}"

def check_live_status(url):
    """检查当前页面状态"""
    try:
        resp = requests.head(url, timeout=10, allow_redirects=True)
        return resp.status_code
    except:
        return None

def main():
    if len(sys.argv) < 2:
        print("用法：python cache_viewer.py <url> [--wayback|--google|--archive]")
        print("  --wayback   打开 Wayback Machine")
        print("  --google    打开 Google Cache")
        print("  --archive   打开 Archive.org")
        sys.exit(1)
    
    url = sys.argv[1]
    mode = sys.argv[2] if len(sys.argv) > 2 else "--wayback"
    
    print(f"🔍 目标：{url}")
    
    # 检查当前状态
    status = check_live_status(url)
    if status:
        print(f"当前状态：HTTP {status}")
    else:
        print("当前状态：无法访问")
    
    if mode == "--wayback":
        snapshots = get_wayback_snapshots(url)
        if snapshots:
            print(f"\n🌐 最新快照：{snapshots[0]['archive_url']}")
            print("在浏览器中打开？(y/n)")
            if input().lower() == 'y':
                webbrowser.open(snapshots[0]['archive_url'])
    
    elif mode == "--google":
        cache_url = get_google_cache_url(url)
        print(f"\n🔎 Google Cache: {cache_url}")
        print("在浏览器中打开？(y/n)")
        if input().lower() == 'y':
            webbrowser.open(cache_url)
    
    elif mode == "--archive":
        archive_url = f"https://web.archive.org/web/*/{url}"
        print(f"\n📚 Archive.org: {archive_url}")
        print("在浏览器中打开？(y/n)")
        if input().lower() == 'y':
            webbrowser.open(archive_url)
    
    else:
        print("未知模式，使用 --wayback")
        get_wayback_snapshots(url)

if __name__ == "__main__":
    main()


path: scripts/recon.sh
content: #!/bin/bash
# Web Recon 侦察脚本
# 用法：./recon.sh <target-url> [--passive|--active]

set -e

TARGET=$1
MODE=${2:---passive}

if [ -z "$TARGET" ]; then
    echo "用法：./recon.sh <target-url> [--passive|--active]"
    echo "  --passive  仅被动收集（安全）"
    echo "  --active   包含主动探测（需授权）"
    exit 1
fi

# 提取域名
DOMAIN=$(echo $TARGET | sed -E 's|https?://||' | cut -d'/' -f1)

echo "🔍 Web Recon - 目标：$TARGET"
echo "模式：$MODE"
echo "================================"

# 创建报告目录
REPORT_DIR="recon_report_$(date +%Y%m%d_%H%M%S)"
mkdir -p $REPORT_DIR

# ========== 被动收集（安全）==========
echo ""
echo "📡 阶段 1: 被动收集..."

# 1. 检查 Wayback Machine
echo "[*] 检查 Wayback Machine 快照..."
curl -s "http://web.archive.org/cdx/search/cdx?url=$TARGET&output=json" | head -20 > $REPORT_DIR/wayback_urls.txt
echo "  ✓ Wayback URLs: $REPORT_DIR/wayback_urls.txt"

# 2. 检查 Google Cache（需要手动访问）
echo "[*] Google Cache 链接:"
echo "  https://webcache.googleusercontent.com/search?q=cache:$TARGET"

# 3. 搜索引擎查询
echo "[*] 生成搜索引擎查询链接:"
echo "  site:$DOMAIN" > $REPORT_DIR/search_queries.txt
echo "  site:$DOMAIN inurl:admin" >> $REPORT_DIR/search_queries.txt
echo "  site:$DOMAIN filetype:pdf" >> $REPORT_DIR/search_queries.txt
echo "  site:$DOMAIN ext:json|xml|rss" >> $REPORT_DIR/search_queries.txt
echo "  ✓ 查询列表：$REPORT_DIR/search_queries.txt"

# 4. 检查 robots.txt
echo "[*] 检查 robots.txt..."
curl -s "$TARGET/robots.txt" > $REPORT_DIR/robots.txt 2>/dev/null || echo "  未找到 robots.txt"
if [ -s $REPORT_DIR/robots.txt ]; then
    echo "  ✓ robots.txt: $REPORT_DIR/robots.txt"
    # 提取禁止路径
    grep -E "^Disallow:" $REPORT_DIR/robots.txt | sed 's/Disallow: //' > $REPORT_DIR/disallowed_paths.txt
    echo "  ✓ 禁止路径：$REPORT_DIR/disallowed_paths.txt"
fi

# 5. 检查常见 RSS/Feed
echo "[*] 检查 RSS/Atom 订阅..."
for path in "/rss" "/rss.xml" "/feed" "/atom.xml" "/blog/rss"; do
    STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$TARGET$path")
    if [ "$STATUS" = "200" ]; then
        echo "  ✓ 发现 Feed: $path"
        curl -s "$TARGET$path" > "$REPORT_DIR/feed$(echo $path | tr '/' '_').xml"
    fi
done

# ========== 主动探测（需授权）==========
if [ "$MODE" = "--active" ]; then
    echo ""
    echo "⚠️  阶段 2: 主动探测（需授权）..."
    echo "确认你已获得书面授权？(y/n)"
    read -r CONFIRM
    if [ "$CONFIRM" != "y" ]; then
        echo "已取消主动探测"
        exit 0
    fi

    # 1. 探测常见 API 端点
    echo "[*] 探测 API 端点..."
    API_PATHS=("/api" "/api/v1" "/api/v2" "/graphql" "/api/posts" "/api/users" "/api/feed")
    for path in "${API_PATHS[@]}"; do
        STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$TARGET$path")
        if [ "$STATUS" = "200" ] || [ "$STATUS" = "401" ] || [ "$STATUS" = "403" ]; then
            echo "  [$STATUS] $path"
            echo "$path - $STATUS" >> $REPORT_DIR/api_endpoints.txt
        fi
    done

    # 2. 爬虫模拟测试
    echo "[*] 测试爬虫权限..."
    NORMAL_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$TARGET")
    BOT_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -A "Googlebot/2.1" "$TARGET")
    echo "  正常 User-Agent: $NORMAL_RESPONSE"
    echo "  Googlebot User-Agent: $BOT_RESPONSE"
    if [ "$NORMAL_RESPONSE" != "$BOT_RESPONSE" ]; then
        echo "  ⚠️  检测到不同响应 - 可能存在爬虫特殊权限"
    fi

    # 3. 目录扫描（如果安装了 dirsearch）
    if command -v dirsearch &> /dev/null; then
        echo "[*] 启动目录扫描..."
        dirsearch -u "$TARGET" -e php,html,js,json -o $REPORT_DIR/dirsearch.txt --quiet
        echo "  ✓ 扫描结果：$REPORT_DIR/dirsearch.txt"
    else
        echo "  ⚠️  dirsearch 未安装，跳过目录扫描"
        echo "  安装：pip install dirsearch"
    fi
fi

# ========== 生成报告 ==========
echo ""
echo "================================"
echo "📊 报告已生成：$REPORT_DIR/"
echo ""
echo "下一步:"
echo "1. 查看搜索引擎查询：cat $REPORT_DIR/search_queries.txt"
echo "2. 访问 Wayback Machine: https://web.archive.org/web/*/$TARGET"
echo "3. 检查发现的 Feed 文件"
echo ""
echo "⚠️  合规提醒：仅将结果用于合法用途"


Security scan verdicts — ClawScan: clean | static analysis:  | VirusTotal: clean | SkillSpector: clean (LOW)