go-appsec/interactsh-lite
GitHub: go-appsec/interactsh-lite
Interactsh 客户端的轻量化重实现,用于安全测试中捕获带外交互以验证 SSRF、XXE 等漏洞
Stars: 1 | Forks: 2
# go-appsec/interactsh-lite
[](https://github.com/go-appsec/interactsh-lite/blob/main/LICENSE)
[](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检测, 安全测试, 带外检测, 攻击性安全, 数据保护, 数据展示, 日志审计, 盲注检测, 程序破解, 红队, 网络安全, 轻量级客户端, 配置审计, 隐私保护