go-appsec/interactsh-lite

GitHub: go-appsec/interactsh-lite

Interactsh 客户端的轻量化重实现,用于安全测试中捕获带外交互以验证 SSRF、XXE 等漏洞

Stars: 1 | Forks: 2

# go-appsec/interactsh-lite [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/go-appsec/interactsh-lite/blob/main/LICENSE) [![Build Status](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/3494fb8ff9025346.svg)](https://github.com/go-appsec/interactsh-lite/actions/workflows/tests-main.yml) 一个轻量级、依赖极简的 Go 模块和独立客户端,用于 [Interactsh](https://github.com/projectdiscovery/interactsh) 服务器。该工具为安全测试提供带外(OOB / OAST)交互检测,并具有简洁的 API。 ## 功能特性 - 依赖极少,体积最小 - 具备上下文感知能力的 API,支持取消和超时 - 线程安全的客户端,拥有清晰的状态机 - 会话持久化,支持长时间运行的测试 - 兼容公共 Interactsh 服务器和自托管实例 - 独立的 CLI 工具 (`interactshlite`) ## 支持的协议 客户端可以检测以下带外交互类型: | Protocol | Description | |----------|-------------| | DNS | A, AAAA, CNAME, MX, TXT, NS, SOA 查询 | | HTTP/HTTPS | 完整的请求和响应捕获 | | SMTP/SMTPS | 电子邮件交互,包含 MAIL FROM 捕获 | | LDAP | LDAP 搜索查询交互 | ## CLI 工具 从 [最新版本](https://github.com/go-appsec/interactsh-lite/releases) 下载适用于您平台的二进制文件,或使用 `go install`: ``` go install github.com/go-appsec/interactsh-lite/cmd/interactshlite@latest ``` ### CLI 使用方法 `interactshlite` 命令提供了一个用于 OOB 交互检测的独立工具,很大程度上兼容 ProjectDiscovery 的 `interactsh-client`。 #### 基本用法 ``` # 生成 payload 并轮询交互 interactshlite # 生成多个 payload interactshlite -n 5 # 使用特定服务器 interactshlite -s alpha.oastsrv.net # 用于脚本编写的 JSON 输出 interactshlite --json # 包含完整请求/响应数据的详细输出 interactshlite -v ``` ### CLI 参数 | Flag | Description | |------|-------------| | `-s, --server` | 要使用的 Interactsh 服务器(逗号分隔) | | `-n, --number` | 要生成的 Payload 数量 | | `-t, --token` | 受保护服务器的认证 token | | `--config` | 配置文件路径 | | `--poll-interval, --pi` | 轮询间隔(秒)(默认值:5) | | `--keep-alive-interval, --kai` | 保活间隔(默认值:1m) | | `--session-file, --sf` | 用于跨重启持久化的会话文件 | | `--dns-only` | 仅显示 DNS 交互 | | `--http-only` | 仅显示 HTTP 交互 | | `--smtp-only` | 仅显示 SMTP 交互 | | `-m, --match` | 用于包含交互的正则表达式模式 | | `-f, --filter` | 用于排除交互的正则表达式模式 | | `-o, --output` | 输出文件路径 | | `--json` | 以 JSON 格式输出 | | `-v, --verbose` | 详细输出,包含请求/响应数据 | | `--payload-store, --ps` | 将生成的 Payload 存储到文件 | | `--payload-store-file, --psf` | Payload 存储文件路径(默认值:interactsh_payload.txt) | | `--health-check, --hc` | 运行诊断检查 | | `--version` | 显示版本 | ### 配置文件 创建 `~/.config/interactsh-client/config.yaml`: ``` server: "oscar.oastsrv.net,alpha.oastsrv.net,sierra.oastsrv.net,tango.oastsrv.net" token: "" poll-interval: 5 keep-alive-interval: 1m json: false verbose: false ``` CLI 参数优先级高于配置文件中的值。 ### CLI 示例 ``` # 筛选以仅显示 DNS A 记录交互 interactshlite --dns-only -v # 匹配交互中的特定模式 interactshlite -m "ssrf.*" -m "xxe.*" # 将 payload 保存到文件以供稍后使用 interactshlite -n 10 --payload-store --payload-store-file payloads.txt # 使用会话文件持久化 correlation ID interactshlite --session-file session.yaml # 运行健康检查诊断 interactshlite --health-check ``` ## 库 ### 库快速入门 ``` go get github.com/go-appsec/interactsh-lite@latest ``` ``` package main import ( "context" "fmt" "log" "time" "github.com/go-appsec/interactsh-lite/oobclient" ) func main() { ctx := context.Background() // Create client with default options (uses public servers) client, err := oobclient.New(ctx) if err != nil { log.Fatal(err) } defer client.Close() // Generate a unique payload domain payloadURL := client.Domain() fmt.Printf("Inject this URL in your target: %s\n", payloadURL) // Start polling for interactions err = client.StartPolling(5*time.Second, func(i *oobclient.Interaction) { fmt.Printf("[%s] %s from %s\n", i.Protocol, i.UniqueID, i.RemoteAddress) }) if err != nil { log.Fatal(err) } // Wait for interactions... time.Sleep(60 * time.Second) client.StopPolling() } ``` ### 使用示例 #### 自定义服务器配置 ``` client, err := oobclient.New(ctx, oobclient.Options{ ServerURLs: []string{"my-interactsh-server.example.com"}, Token: "my-auth-token", HTTPTimeout: 15 * time.Second, KeepAliveInterval: 30 * time.Second, }) ``` #### 会话持久化 保存和恢复会话,以在重启后保持相同的 correlation ID: ``` // Save session before shutdown if err := client.SaveSession("/tmp/session.yaml"); err != nil { log.Fatal(err) } // Later, restore the session (optionally pass opts to override behavioral settings) client, err := oobclient.LoadSession(ctx, "/tmp/session.yaml") if err != nil { log.Fatal(err) } defer client.Close() // Previously generated payload URLs still work ``` #### 错误处理 ``` import "errors" client, err := oobclient.New(ctx, opts) if errors.Is(err, oobclient.ErrUnauthorized) { log.Fatal("Invalid or missing authentication token") } err = client.StartPolling(interval, callback) if errors.Is(err, oobclient.ErrAlreadyPolling) { // Already polling, ignore } if errors.Is(err, oobclient.ErrClientClosed) { // Client was closed, need to create a new one } ``` #### 域名 / Payload 生成 ``` // Domain() returns a unique domain for each call, suitable for correlating // specific test cases with their interactions. url1 := client.Domain() url2 := client.Domain() // Example: "cn4h7pjqdka31f8e5g6bry8djt4un3h1x.alpha.oastsrv.net" (20-char correlation ID + 13-char nonce) // Example: "cn4h7pjqdka31f8e5g6bkne9wfg4a3mt1.alpha.oastsrv.net" // Both share the same correlation ID prefix but have unique nonces. // URL() is deprecated — use Domain() instead. URL() delegates to Domain(). ``` ### 从 ProjectDiscovery/Interactsh 迁移 该库是 [官方 Interactsh](https://github.com/projectdiscovery/interactsh) 客户端的几乎可直接替换的替代品,具有更简化的 API。 **二进制大小:** 如果您的依赖树中尚未包含 ProjectDiscovery,切换到 `interactsh-lite` 可以将编译后的二进制文件大小减少多达 20MB。 #### 导入更改 ``` import ( - "github.com/projectdiscovery/interactsh/pkg/client" - "github.com/projectdiscovery/interactsh/pkg/server" + "github.com/go-appsec/interactsh-lite/oobclient" ) ``` #### 客户端创建 ``` -opts := client.DefaultOptions -opts.ServerURL = "oast.pro" -c, err := client.New(opts) +ctx := context.Background() +c, err := oobclient.New(ctx, oobclient.Options{ + ServerURLs: []string{"oscar.oastsrv.net", "alpha.oastsrv.net", "sierra.oastsrv.net", "tango.oastsrv.net"}, +}) ``` 主要区别: - `New()` 现在将 `context.Context` 作为第一个参数 - `ServerURL` (string) 现在是 `ServerURLs` ([]string) #### Payload 生成 ``` -// GeneratePayloadURL() generated unique payload domains -url := c.GeneratePayloadURL() +// Domain() is now the primary method (each call returns a unique domain with a nonce) +domain := c.Domain() +// URL() still works but is deprecated — it delegates to Domain() ``` #### 轮询交互 ``` -c.StartPolling(interval, func(i *server.Interaction) { +c.StartPolling(interval, func(i *oobclient.Interaction) { fmt.Println(i.Protocol, i.RemoteAddress) }) ``` `Interaction` 结构体字段完全相同。 #### 关闭客户端 ``` -c.StopPolling() -c.Close() +c.Close() // Automatically stops polling ``` #### 会话持久化 ``` -c.SaveSessionTo("/path/to/session.yaml") +c.SaveSession("/path/to/session.yaml") ``` #### 模块错误处理 ``` -if err != nil && strings.Contains(err.Error(), "unauthorized") { +if errors.Is(err, oobclient.ErrUnauthorized) { // Handle auth error } ``` ### API 参考 #### 类型 | Type | Description | |------|-------------| | `Client` | 与 Interactsh 服务器交互的主客户端 | | `Options` | 客户端创建的配置选项 | | `Interaction` | 捕获的 OOB 交互数据 | | `InteractionCallback` | 用于轮询的回调函数类型 | #### 哨兵错误 | Error | Description | |-------|-------------| | `ErrSessionEvicted` | 服务器逐出了会话(未找到 correlation ID) | | `ErrUnauthorized` | 无效或缺失认证 token | | `ErrClientClosed` | 尝试对已关闭的客户端进行操作 | | `ErrAlreadyPolling` | 在已轮询时调用了 StartPolling | | `ErrNotPolling` | 在未轮询时调用了 StopPolling | ## 服务条款 使用此工具及 `*.oastsrv.net` 上的托管 OAST 服务受我们的[服务条款](TERMS-OF-SERVICE.md)约束。
标签:CISA项目, DNS交互, EVTX分析, Go语言, HTTP交互, Interactsh, IP 地址批量处理, OAST, OOB测试, ProjectDiscovery, RCE检测, SSRF检测, 安全测试, 带外检测, 攻击性安全, 数据保护, 数据展示, 日志审计, 盲注检测, 程序破解, 红队, 网络安全, 轻量级客户端, 配置审计, 隐私保护