Skip to content

mew-sh/oast-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OAST Server

A self-hosted Out-of-Band Application Security Testing server written in Rust. It combines a DNS server, HTTP server, and SMTP server into a single binary — all interactions are forwarded to you as Telegram notifications in real time.

Typical use cases: detecting blind SSRF, blind XXE, blind SQL injection, command injection with out-of-band callbacks, and any other vulnerability class where the target application reaches out to an attacker-controlled domain.


Features

  • DNS — authoritative wildcard DNS server; every query to *.yourdomain.com is answered with your VPS IP and reported via Telegram.
  • HTTP — catches every HTTP request to your domain; method, path, headers, and body are forwarded to Telegram.
  • SMTP — listens on port 25 and captures email interactions (EHLO/MAIL FROM/RCPT TO/DATA); reports sender, recipient, and message body.
  • IP-domain encoding — special subdomain format where the label is a hex-encoded IP string (e.g. 31302e31302e39302e323036.i.yourdomain.com10.10.90.206). Useful for SSRF bypasses that require a DNS-resolvable hostname pointing to an internal address.
  • Hot-reload config — the config file is watched for changes; the server reloads it live without a restart.
  • Telegram notifications — all captured events are pushed to a Telegram chat with timestamps.

Architecture

┌─────────────────────────────────────────────────┐
│                  oast-server                    │
│                                                 │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐   │
│  │  DNS     │  │  HTTP    │  │    SMTP      │   │
│  │  :53/UDP │  │  :80/TCP │  │    :25/TCP   │   │
│  └────┬─────┘  └────┬─────┘  └──────┬───────┘   │
│       └─────────────┴───────────────┘           │
│                      │                          │
│           ┌──────────▼──────────┐               │
│           │  TelegramNotifier   │               │
│           └─────────────────────┘               │
└─────────────────────────────────────────────────┘

Requirements

  • Rust 1.75+ (uses Tokio async runtime)
  • A VPS with a public IP
  • A domain you control
  • A Telegram bot token and chat ID

Building

cargo build --release
# binary: target/release/oast-server

DNS Setup

Register your domain and add the following records at your registrar:

Type Name Value
A ns1.c.yourdomain <VPS IP>
A ns2.c.yourdomain <VPS IP>
NS c.yourdomain ns1.c.yourdomain
NS c.yourdomain ns2.c.yourdomain

If you also want the IP-domain feature on a second subdomain (e.g. i.yourdomain), point its NS records to the same nameservers:

Type Name Value
NS i.yourdomain ns1.c.yourdomain
NS i.yourdomain ns2.c.yourdomain

Disable the system stub resolver (Linux)

Port 53 is occupied by systemd-resolved on most modern Linux distributions. Free it before starting the server:

sudo nano /etc/systemd/resolved.conf
# Set: DNSStubListener=no

sudo systemctl restart systemd-resolved
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

Configuration

Copy the example and edit it:

cp config.yaml.example config.yaml
# config.yaml

# Primary wildcard OAST domain  (*.c.yourdomain.com → VPS IP)
domain: "c.yourdomain.com"

# Public IP of your VPS
ip: "1.2.3.4"

dns:
  port: 53
  ttl: 60

  # Additional domains served by this server (same wildcard behaviour)
  extra_domains: []

  # Hex-encoded IP domains:
  #   hex("10.10.90.206") = "31302e31302e39302e323036"
  #   → 31302e31302e39302e323036.i.yourdomain.com resolves to 10.10.90.206
  ip_domains:
    - "i.yourdomain.com"

  # Glue / static records
  records:
    - name: "ns1"
      ip: "1.2.3.4"
    - name: "ns2"
      ip: "1.2.3.4"

http:
  port: 80
  enabled: true

smtp:
  port: 25
  enabled: true

telegram:
  bot_token: "123456789:AAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  chat_id: "your_chat_id"

The config file is watched at runtime — any save triggers a live reload.


Running

# Uses config.yaml in the current directory by default
./target/release/oast-server

# Or specify a custom config path
./target/release/oast-server /etc/oast/config.yaml

The server requires permission to bind to privileged ports (80, 25, 53). Either run as root or grant the binary the CAP_NET_BIND_SERVICE capability:

sudo setcap 'cap_net_bind_service=+ep' ./target/release/oast-server

Systemd service (optional)

[Unit]
Description=OAST Server
After=network.target

[Service]
ExecStart=/opt/oast-server/oast-server /opt/oast-server/config.yaml
Restart=on-failure
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

Telegram Notifications

Create a Telegram bot via @BotFather, obtain the token, then retrieve your chat ID by messaging the bot and calling:

https://api.telegram.org/bot<TOKEN>/getUpdates

Example notifications:

DNS hit

🔔 DNS
🌍 abc123.c.yourdomain.com
🔍 Type: A
🌐 From: 203.0.113.42:54321
⏰ 2026-03-25 10:00:00 UTC

HTTP hit

🔔 HTTP
🌍 abc123.c.yourdomain.com
🔍 GET /callback?token=secret
🌐 From: 203.0.113.42:12345
⏰ 2026-03-25 10:00:01 UTC
📋 Headers: ...
📦 Body: ...

SMTP hit

🔔 SMTP
📤 From: attacker@evil.com
📥 To: test@abc123.c.yourdomain.com
🌐 From IP: 203.0.113.42:25
⏰ 2026-03-25 10:00:02 UTC

IP-Domain Feature

The ip_domains option enables a special DNS mode where the subdomain label is the hex encoding of an IP address string. This is useful for SSRF exploits that need a DNS name resolving to an internal address.

Encoding an IP:

"10.10.90.206".encode().hex()  # → "31302e31302e39302e323036"

Query:

31302e31302e39302e323036.i.yourdomain.com  →  A  10.10.90.206

No Telegram notification is sent for IP-domain queries (they are infrastructure queries, not out-of-band callbacks).


Environment Variables

Variable Description Default
RUST_LOG Log level filter (info, debug, …) oast_server=info
RUST_LOG=debug ./oast-server

License

MIT

About

A self-hosted OAST server written in Rust

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages