feat(security): deploy OpenCanary honeypot on VLAN 50 with Gotify and Discord alerting
This commit is contained in:
@@ -22,3 +22,4 @@ stdin, stdout, stderr = c.exec_command(f'python3 -c "{py_query}"')
|
||||
print("All NPM hosts:\n", stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
|
||||
@@ -33,3 +33,4 @@ try:
|
||||
print(f" Context: {json.dumps(context, indent=2)}")
|
||||
except Exception as e:
|
||||
print(f"Error querying Authentik: {e}")
|
||||
|
||||
|
||||
14
scripts/check_bridge_logs.py
Normal file
14
scripts/check_bridge_logs.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("docker service logs --tail 10 gotify_gotify-discord-bridge")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
15
scripts/check_bridge_map.py
Normal file
15
scripts/check_bridge_map.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("grep -n -A 10 'APP_WEBHOOK_MAP' /var/lib/docker/volumes/gotify_gotify_data/_data/discord_bridge.py")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
15
scripts/check_docker_tail.py
Normal file
15
scripts/check_docker_tail.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("docker logs --tail 20 opencanary")
|
||||
print("Docker logs:\n", stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
21
scripts/check_gotify_apps.py
Normal file
21
scripts/check_gotify_apps.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print("Gotify database check:")
|
||||
print(run("find /var/lib/docker/volumes/ -name 'gotify.db'"))
|
||||
print("\nGotify apps in SQLite:")
|
||||
print(run("sqlite3 $(find /var/lib/docker/volumes/ -name 'gotify.db') 'SELECT id, name, token FROM application;'"))
|
||||
|
||||
c.close()
|
||||
|
||||
28
scripts/check_gotify_apps_py.py
Normal file
28
scripts/check_gotify_apps_py.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_script = """
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db')
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT name FROM sqlite_master WHERE type='table'")
|
||||
print('Tables:', cur.fetchall())
|
||||
for tbl in cur.fetchall():
|
||||
pass
|
||||
cur.execute("SELECT * FROM application")
|
||||
print('Applications:', cur.fetchall())
|
||||
"""
|
||||
stdin, stdout, stderr = c.exec_command(f'python3 -c "{py_script}"')
|
||||
print(stdout.read().decode())
|
||||
err = stderr.read().decode()
|
||||
if err: print("Stderr:", err)
|
||||
|
||||
c.close()
|
||||
|
||||
18
scripts/check_gotify_data.py
Normal file
18
scripts/check_gotify_data.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print(run("ls -la /var/lib/docker/volumes/gotify_gotify_data/_data/; file /var/lib/docker/volumes/gotify_gotify_data/_data/*"))
|
||||
|
||||
c.close()
|
||||
|
||||
14
scripts/check_gotify_msgs.py
Normal file
14
scripts/check_gotify_msgs.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command('sqlite3 /var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db "SELECT id, appid, title, message FROM messages ORDER BY id DESC LIMIT 5;"')
|
||||
print("Recent messages in Gotify:\n", stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
21
scripts/check_gotify_tables.py
Normal file
21
scripts/check_gotify_tables.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print("Gotify tables:")
|
||||
print(run("sqlite3 /var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db '.tables'"))
|
||||
print("\nApplications:")
|
||||
print(run("sqlite3 /var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db 'SELECT * FROM applications;'"))
|
||||
|
||||
c.close()
|
||||
|
||||
25
scripts/check_ha_dns.py
Normal file
25
scripts/check_ha_dns.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore')
|
||||
|
||||
print("--- dig snarfhome ---")
|
||||
print(run("dig @140.44.4.36 +short snarfhome.snarfnet.net"))
|
||||
|
||||
print("--- dig homeassistant ---")
|
||||
print(run("dig @140.44.4.36 +short homeassistant.snarfnet.net"))
|
||||
|
||||
print("--- dig ha ---")
|
||||
print(run("dig @140.44.4.36 +short ha.snarfnet.net"))
|
||||
|
||||
c.close()
|
||||
|
||||
@@ -1,21 +1,43 @@
|
||||
import json
|
||||
import ssl
|
||||
import urllib.request
|
||||
import ssl
|
||||
import json
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
|
||||
req = urllib.request.Request(
|
||||
'https://authentik.snarfnet.net/api/v3/events/events/?page_size=25',
|
||||
headers={'Authorization': 'Bearer SnarfNetPermanentAutomationToken2026'}
|
||||
)
|
||||
res = json.loads(urllib.request.urlopen(req, context=ctx).read())
|
||||
print(f"Total events found: {len(res['results'])}")
|
||||
for e in res['results']:
|
||||
action = e.get('action')
|
||||
app = e.get('app')
|
||||
user = e.get('user', {}).get('username')
|
||||
created = e.get('created')
|
||||
context = json.dumps(e.get('context', {}))
|
||||
print(f"{created} | {action:25} | app: {app:20} | user: {user} | {context[:120]}")
|
||||
AK_BASE = "https://authentik.snarfnet.net"
|
||||
AK_TOKEN = "SnarfNetPermanentAutomationToken2026"
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {AK_TOKEN}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json"
|
||||
}
|
||||
|
||||
# Fetch events matching homeassistant or redirect_uri
|
||||
req = urllib.request.Request(f"{AK_BASE}/api/v3/events/events/?search=homeassistant", headers=headers)
|
||||
with urllib.request.urlopen(req, timeout=10, context=ctx) as r:
|
||||
data = json.loads(r.read().decode())
|
||||
print(f"Total matching 'homeassistant': {data.get('pagination', {}).get('count')}")
|
||||
for ev in data.get("results", []):
|
||||
created = ev.get("created")
|
||||
action = ev.get("action")
|
||||
ctx_data = ev.get("context", {})
|
||||
print(f"[{created}] Action: {action}")
|
||||
print(json.dumps(ctx_data, indent=2))
|
||||
|
||||
print("\n--- Also search for 'redirect_uri' ---")
|
||||
req2 = urllib.request.Request(f"{AK_BASE}/api/v3/events/events/?search=redirect_uri", headers=headers)
|
||||
with urllib.request.urlopen(req2, timeout=10, context=ctx) as r:
|
||||
data2 = json.loads(r.read().decode())
|
||||
print(f"Total matching 'redirect_uri': {data2.get('pagination', {}).get('count')}")
|
||||
for ev in data2.get("results", [])[:5]:
|
||||
created = ev.get("created")
|
||||
action = ev.get("action")
|
||||
ctx_data = ev.get("context", {})
|
||||
print(f"[{created}] Action: {action}")
|
||||
print(json.dumps(ctx_data, indent=2))
|
||||
|
||||
18
scripts/check_ha_homepage.py
Normal file
18
scripts/check_ha_homepage.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.41", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("k3s kubectl get cm -A | grep -i home")
|
||||
print("CMs:\n", stdout.read().decode())
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("k3s kubectl get cm -n infrastructure -o yaml | grep -A 20 -B 5 -i homeassistant")
|
||||
print("Live HA config in Homepage:\n", stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
@@ -23,3 +23,4 @@ stdin, stdout, stderr = c.exec_command(f'python3 -c "{py_query}"')
|
||||
print("Home Assistant in NPM:\n", stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
|
||||
19
scripts/check_ha_ssh.py
Normal file
19
scripts/check_ha_ssh.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
try:
|
||||
c.connect("14.4.4.20", username="root", key_filename=key_path, timeout=5)
|
||||
print("SSH root ok")
|
||||
except Exception as e:
|
||||
print("SSH root failed:", e)
|
||||
try:
|
||||
c.connect("14.4.4.20", username="snarf", key_filename=key_path, timeout=5)
|
||||
print("SSH snarf ok")
|
||||
except Exception as e2:
|
||||
print("SSH snarf failed:", e2)
|
||||
|
||||
19
scripts/check_heimdall_db.py
Normal file
19
scripts/check_heimdall_db.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore')
|
||||
|
||||
print("Heimdall volumes/data:")
|
||||
print(run("find /var/lib/docker/volumes/ -name '*heimdall*' -o -name '*app.sqlite*'"))
|
||||
|
||||
c.close()
|
||||
|
||||
15
scripts/check_heimdall_ha_item.py
Normal file
15
scripts/check_heimdall_ha_item.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.75", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command('docker exec $(docker ps -q -f name=heimdall) sqlite3 /config/www/app.sqlite "SELECT id, title, url, config FROM items WHERE title LIKE \'%home%\' OR title LIKE \'%assistant%\';"')
|
||||
print("Heimdall HA item:\n", stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
15
scripts/check_heimdall_node.py
Normal file
15
scripts/check_heimdall_node.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("docker service ps heimdall_heimdall --no-trunc")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
15
scripts/check_npm_20.py
Normal file
15
scripts/check_npm_20.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("cat /var/lib/docker/volumes/nginx-proxy-manager_nginx-data/_data/nginx/proxy_host/20.conf 2>/dev/null || echo '20.conf does not exist'")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
19
scripts/check_oc_live.py
Normal file
19
scripts/check_oc_live.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print("Container status:\n", run("docker ps -f name=opencanary"))
|
||||
print("\nRecent logs:\n", run("docker logs --tail 30 opencanary"))
|
||||
|
||||
c.close()
|
||||
|
||||
19
scripts/check_opencanary_image.py
Normal file
19
scripts/check_opencanary_image.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print("Docker image search/pull check:")
|
||||
print(run("docker pull thinkst/opencanary:latest"))
|
||||
|
||||
c.close()
|
||||
|
||||
22
scripts/check_opencanary_status.py
Normal file
22
scripts/check_opencanary_status.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print("OpenCanary container logs:")
|
||||
print(run("docker logs --tail 30 opencanary"))
|
||||
|
||||
print("\nContainer status:")
|
||||
print(run("docker ps -f name=opencanary"))
|
||||
|
||||
c.close()
|
||||
|
||||
38
scripts/check_recent_ak_events.py
Normal file
38
scripts/check_recent_ak_events.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import urllib.request
|
||||
import ssl
|
||||
import json
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
|
||||
AK_BASE = "https://authentik.snarfnet.net"
|
||||
AK_TOKEN = "SnarfNetPermanentAutomationToken2026"
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {AK_TOKEN}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json"
|
||||
}
|
||||
|
||||
req = urllib.request.Request(f"{AK_BASE}/api/v3/events/events/?page_size=40", headers=headers)
|
||||
with urllib.request.urlopen(req, timeout=10, context=ctx) as r:
|
||||
data = json.loads(r.read().decode())
|
||||
for ev in data.get("results", []):
|
||||
created = ev.get("created")
|
||||
action = ev.get("action")
|
||||
user = ev.get("user", {}).get("username")
|
||||
ctx_data = ev.get("context", {})
|
||||
if action != "secret_rotate":
|
||||
print(f"[{created}] Action: {action} | User: {user}")
|
||||
# print request details
|
||||
http_req = ctx_data.get("http_request", {})
|
||||
if http_req:
|
||||
print(f" Path: {http_req.get('path')}")
|
||||
print(f" Args: {http_req.get('args')}")
|
||||
if "message" in ctx_data:
|
||||
print(f" Message: {ctx_data.get('message')}")
|
||||
|
||||
24
scripts/check_snarfhome_response.py
Normal file
24
scripts/check_snarfhome_response.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import urllib.request
|
||||
import ssl
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
|
||||
req = urllib.request.Request("https://snarfhome.snarfnet.net/")
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=5, context=ctx) as r:
|
||||
print("Status:", r.getcode())
|
||||
print("Headers:", dict(r.headers))
|
||||
content = r.read().decode('utf-8', errors='ignore')
|
||||
print("Content preview:\n", content[:500])
|
||||
except urllib.error.HTTPError as e:
|
||||
print("HTTPError:", e.code)
|
||||
print("Headers:", dict(e.headers))
|
||||
print("Body:\n", e.read().decode('utf-8', errors='ignore')[:500])
|
||||
except Exception as e:
|
||||
print("Exception:", e)
|
||||
|
||||
21
scripts/check_watcher_logs.py
Normal file
21
scripts/check_watcher_logs.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print("Watcher status & logs:")
|
||||
print(run("systemctl status opencanary-watcher.service --no-pager"))
|
||||
print("\nJournalctl:")
|
||||
print(run("journalctl -u opencanary-watcher.service -n 30 --no-pager"))
|
||||
|
||||
c.close()
|
||||
|
||||
251
scripts/deploy_opencanary.py
Normal file
251
scripts/deploy_opencanary.py
Normal file
@@ -0,0 +1,251 @@
|
||||
import paramiko
|
||||
import sys
|
||||
import json
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
out = stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
err = stderr.read().decode('utf-8', errors='ignore').strip()
|
||||
if err:
|
||||
return f"{out}\nSTDERR: {err}"
|
||||
return out
|
||||
|
||||
print("--- Step 1: Setting up opencanary-vlan.service ---")
|
||||
vlan_svc = """[Unit]
|
||||
Description=OpenCanary VLAN 50 Subinterface
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/sbin/ip link add link eth0 name eth0.50 type vlan id 50
|
||||
ExecStart=/sbin/ip link set eth0.50 up
|
||||
ExecStop=/sbin/ip link del eth0.50
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
"""
|
||||
c.exec_command("cat << 'EOF' > /etc/systemd/system/opencanary-vlan.service\n" + vlan_svc + "\nEOF\n")
|
||||
run("systemctl daemon-reload && systemctl enable --now opencanary-vlan.service")
|
||||
print("VLAN interface status:\n", run("ip -br link show eth0.50"))
|
||||
|
||||
print("\n--- Step 2: Creating Docker macvlan network ---")
|
||||
run("docker network rm opencanary_net 2>/dev/null")
|
||||
net_create = run("docker network create -d macvlan --subnet=14.4.4.0/25 --gateway=14.4.4.1 -o parent=eth0.50 opencanary_net")
|
||||
print("Network create result:", net_create)
|
||||
|
||||
print("\n--- Step 3: Creating /opt/opencanary directories & config ---")
|
||||
run("mkdir -p /opt/opencanary/logs")
|
||||
|
||||
oc_config = {
|
||||
"device.node_id": "snarfnet-honeypot-vlan50",
|
||||
"ip.ignorelist": [],
|
||||
"logtype.ignorelist": [],
|
||||
"git.enabled": True,
|
||||
"git.port": 9418,
|
||||
"ftp.enabled": True,
|
||||
"ftp.port": 21,
|
||||
"ftp.banner": "FTP server ready",
|
||||
"http.banner": "Apache/2.4.52 (Ubuntu)",
|
||||
"http.enabled": True,
|
||||
"http.port": 80,
|
||||
"http.skin": "nasLogin",
|
||||
"httpproxy.enabled": True,
|
||||
"httpproxy.port": 8080,
|
||||
"httpproxy.skin": "squid",
|
||||
"logger": {
|
||||
"class": "PyLogger",
|
||||
"kwargs": {
|
||||
"formatters": {
|
||||
"plain": {
|
||||
"format": "%(message)s"
|
||||
}
|
||||
},
|
||||
"handlers": {
|
||||
"console": {
|
||||
"class": "logging.StreamHandler",
|
||||
"stream": "ext://sys.stdout"
|
||||
},
|
||||
"file": {
|
||||
"class": "logging.FileHandler",
|
||||
"filename": "/var/tmp/opencanary.log"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mysql.enabled": True,
|
||||
"mysql.port": 3306,
|
||||
"mysql.banner": "5.7.42-0ubuntu0.18.04.1",
|
||||
"ssh.enabled": True,
|
||||
"ssh.port": 22,
|
||||
"ssh.version": "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.10",
|
||||
"rdp.enabled": True,
|
||||
"rdp.port": 3389,
|
||||
"telnet.enabled": True,
|
||||
"telnet.port": 23,
|
||||
"telnet.banner": "\\r\\nUbuntu 22.04 LTS\\r\\nlogin: ",
|
||||
"mssql.enabled": True,
|
||||
"mssql.version": "2016",
|
||||
"mssql.port": 1433,
|
||||
"vnc.enabled": True,
|
||||
"vnc.port": 5000
|
||||
}
|
||||
|
||||
config_json = json.dumps(oc_config, indent=4)
|
||||
c.exec_command("cat << 'EOF' > /opt/opencanary/opencanary.conf\n" + config_json + "\nEOF\n")
|
||||
print("opencanary.conf written.")
|
||||
|
||||
print("\n--- Step 4: Creating Gotify Alert Watcher daemon ---")
|
||||
watcher_script = """#!/usr/bin/env python3
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
LOG_FILE = "/opt/opencanary/logs/opencanary.log"
|
||||
GOTIFY_URL = "http://127.0.0.1:8090/message?token=A9oPeNcAnArYhOnEyPoT"
|
||||
|
||||
LOGTYPE_NAMES = {
|
||||
1000: "Portscan Syn Probe",
|
||||
1001: "Portscan Nmap OS Detection",
|
||||
1002: "Portscan Null Scan",
|
||||
1003: "Portscan Xmas Scan",
|
||||
1004: "Portscan Fin Scan",
|
||||
2000: "FTP Connection",
|
||||
2001: "FTP Auth Attempt",
|
||||
3000: "HTTP Connection",
|
||||
3001: "HTTP Web Login Attempt",
|
||||
4000: "SSH Connection",
|
||||
4001: "SSH Auth Attempt",
|
||||
5000: "SMB Session Request",
|
||||
6001: "Telnet Login Attempt",
|
||||
7001: "HTTP Proxy Request",
|
||||
8001: "MySQL Login Attempt",
|
||||
9001: "MSSQL Login Attempt",
|
||||
10001: "VNC Connection",
|
||||
11001: "Git Clone / Pull Attempt",
|
||||
12001: "RDP Connection"
|
||||
}
|
||||
|
||||
def send_alert(event):
|
||||
logtype = event.get("logtype", 0)
|
||||
service_name = LOGTYPE_NAMES.get(logtype, f"Canary Event {logtype}")
|
||||
src_host = event.get("src_host", "Unknown IP")
|
||||
src_port = event.get("src_port", "Unknown Port")
|
||||
dst_port = event.get("dst_port", "")
|
||||
logdata = event.get("logdata", {})
|
||||
|
||||
title = f"🚨 [Honeypot Alert] {service_name} from {src_host}"
|
||||
|
||||
details = []
|
||||
details.append(f"• Attacker IP: {src_host}:{src_port}")
|
||||
if dst_port:
|
||||
details.append(f"• Targeted Port: {dst_port}")
|
||||
details.append(f"• Decoy IP: 14.4.4.99 (VLAN 50 Smart Home)")
|
||||
|
||||
if isinstance(logdata, dict):
|
||||
if "USERNAME" in logdata:
|
||||
details.append(f"• Username attempted: {logdata.get('USERNAME')}")
|
||||
if "PASSWORD" in logdata:
|
||||
details.append(f"• Password attempted: {logdata.get('PASSWORD')}")
|
||||
if "PATH" in logdata:
|
||||
details.append(f"• Path: {logdata.get('PATH')}")
|
||||
if "USERAGENT" in logdata:
|
||||
details.append(f"• User-Agent: {logdata.get('USERAGENT')}")
|
||||
elif logdata:
|
||||
details.append(f"• Payload: {str(logdata)[:200]}")
|
||||
|
||||
body = "\\n".join(details)
|
||||
|
||||
payload = {
|
||||
"title": title,
|
||||
"message": body,
|
||||
"priority": 8
|
||||
}
|
||||
|
||||
try:
|
||||
req = urllib.request.Request(
|
||||
GOTIFY_URL,
|
||||
data=json.dumps(payload).encode('utf-8'),
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=5) as r:
|
||||
pass
|
||||
print(f"[Alert Sent] {title}")
|
||||
except Exception as e:
|
||||
print(f"[Alert Error] {e}")
|
||||
|
||||
def main():
|
||||
print("OpenCanary Gotify Watcher started...")
|
||||
# Ensure log file exists
|
||||
if not os.path.exists(LOG_FILE):
|
||||
open(LOG_FILE, 'a').close()
|
||||
|
||||
with open(LOG_FILE, 'r') as f:
|
||||
# Seek to end on startup
|
||||
f.seek(0, os.SEEK_END)
|
||||
while True:
|
||||
line = f.readline()
|
||||
if not line:
|
||||
time.sleep(0.5)
|
||||
continue
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
try:
|
||||
event = json.loads(line)
|
||||
send_alert(event)
|
||||
except Exception as e:
|
||||
# Non-JSON log line
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
"""
|
||||
|
||||
c.exec_command("cat << 'EOF' > /opt/opencanary/alert_watcher.py\n" + watcher_script + "\nEOF\n")
|
||||
run("chmod +x /opt/opencanary/alert_watcher.py")
|
||||
|
||||
watcher_svc = """[Unit]
|
||||
Description=OpenCanary Gotify Alert Watcher
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/python3 /opt/opencanary/alert_watcher.py
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
"""
|
||||
c.exec_command("cat << 'EOF' > /etc/systemd/system/opencanary-watcher.service\n" + watcher_svc + "\nEOF\n")
|
||||
run("systemctl daemon-reload && systemctl enable --now opencanary-watcher.service")
|
||||
print("Watcher service status:\n", run("systemctl is-active opencanary-watcher.service"))
|
||||
|
||||
print("\n--- Step 5: Launching OpenCanary Docker Container ---")
|
||||
run("docker rm -f opencanary 2>/dev/null")
|
||||
docker_run_cmd = """
|
||||
docker run -d \
|
||||
--name opencanary \
|
||||
--restart unless-stopped \
|
||||
--net opencanary_net \
|
||||
--ip 14.4.4.99 \
|
||||
-v /opt/opencanary/opencanary.conf:/root/.opencanary.conf:ro \
|
||||
-v /opt/opencanary/logs:/var/tmp \
|
||||
thinkst/opencanary:latest \
|
||||
opencanaryd --dev
|
||||
"""
|
||||
container_id = run(docker_run_cmd)
|
||||
print("Container ID:", container_id)
|
||||
|
||||
c.close()
|
||||
|
||||
15
scripts/find_ha_php.py
Normal file
15
scripts/find_ha_php.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.75", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("docker exec $(docker ps -q -f name=heimdall) find / -name 'HomeAssistant.php' 2>/dev/null")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
26
scripts/find_nabu_casa.py
Normal file
26
scripts/find_nabu_casa.py
Normal file
@@ -0,0 +1,26 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("grep -rn 'nabu.casa' /var/lib/docker/volumes/nginx-proxy-manager* 2>/dev/null")
|
||||
print("Grep nabu.casa in NPM data:\n", stdout.read().decode())
|
||||
|
||||
py_query = """
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/var/lib/docker/volumes/nginx-proxy-manager_nginx-data/_data/database.sqlite')
|
||||
cur = conn.cursor()
|
||||
cur.execute('SELECT * FROM redirection_host')
|
||||
print('Redirection hosts:', cur.fetchall())
|
||||
conn.close()
|
||||
"""
|
||||
stdin, stdout, stderr = c.exec_command(f'python3 -c "{py_query}"')
|
||||
print("SQLite redirection hosts:\n", stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
18
scripts/find_opencanary_settings.py
Normal file
18
scripts/find_opencanary_settings.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print(run("docker run --rm --entrypoint python3 thinkst/opencanary:latest -c 'import opencanary.config; print(opencanary.config.SETTINGS)' 2>/dev/null || docker run --rm --entrypoint find thinkst/opencanary:latest / -name 'settings.json' 2>/dev/null"))
|
||||
|
||||
c.close()
|
||||
|
||||
40
scripts/fix_mssql_version.py
Normal file
40
scripts/fix_mssql_version.py
Normal file
@@ -0,0 +1,40 @@
|
||||
import paramiko
|
||||
import sys
|
||||
import json
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
# Fix MSSQL version in config
|
||||
with open("c:/Users/Snarf/OneDrive/Desktop/code/SnarfCode/scripts/deploy_opencanary.py", "r") as f:
|
||||
text = f.read()
|
||||
|
||||
# Read config from host, update mssql.version to "2012"
|
||||
py_fix_mssql = """
|
||||
import json
|
||||
path = '/opt/opencanary/opencanary.conf'
|
||||
with open(path, 'r') as f:
|
||||
cfg = json.load(f)
|
||||
cfg['mssql.version'] = '2012'
|
||||
with open(path, 'w') as f:
|
||||
json.dump(cfg, f, indent=4)
|
||||
print('Updated mssql.version to 2012')
|
||||
"""
|
||||
c.exec_command(f'python3 -c "{py_fix_mssql}"')
|
||||
run("docker restart opencanary")
|
||||
|
||||
import time
|
||||
time.sleep(3)
|
||||
print("Logs after restart:")
|
||||
print(run("docker logs --tail 25 opencanary"))
|
||||
|
||||
c.close()
|
||||
|
||||
36
scripts/fix_opencanary_cmd.py
Normal file
36
scripts/fix_opencanary_cmd.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print("Recreating container with correct arguments...")
|
||||
run("docker rm -f opencanary 2>/dev/null")
|
||||
run("""docker run -d \
|
||||
--name opencanary \
|
||||
--restart unless-stopped \
|
||||
--net opencanary_net \
|
||||
--ip 14.4.4.99 \
|
||||
-v /opt/opencanary/opencanary.conf:/root/.opencanary.conf:ro \
|
||||
-v /opt/opencanary/logs:/var/tmp \
|
||||
thinkst/opencanary:latest \
|
||||
--dev --allow-run-as-root
|
||||
""")
|
||||
|
||||
import time
|
||||
time.sleep(3)
|
||||
print("Logs after start:")
|
||||
print(run("docker logs --tail 30 opencanary"))
|
||||
print("\nStatus:")
|
||||
print(run("docker ps -f name=opencanary"))
|
||||
|
||||
c.close()
|
||||
|
||||
15
scripts/get_live_homepage_services.py
Normal file
15
scripts/get_live_homepage_services.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.41", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("k3s kubectl exec -n infrastructure $(k3s kubectl get pods -n infrastructure -l app.kubernetes.io/name=homepage-2-1744068158 -o jsonpath='{.items[0].metadata.name}') -- cat /app/config/services.yaml")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
18
scripts/get_opencanary_default_conf.py
Normal file
18
scripts/get_opencanary_default_conf.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print(run("docker run --rm thinkst/opencanary:latest sh -c 'opencanaryd --copyconfig && cat /etc/opencanaryd/opencanary.conf'"))
|
||||
|
||||
c.close()
|
||||
|
||||
@@ -33,3 +33,4 @@ with urllib.request.urlopen(req2, timeout=10, context=ctx) as r:
|
||||
if "home" in p.get("name", "").lower() or "snarfhome" in str(p).lower():
|
||||
print("Proxy Provider:")
|
||||
print(json.dumps(p, indent=2))
|
||||
|
||||
|
||||
21
scripts/inspect_opencanary_conf.py
Normal file
21
scripts/inspect_opencanary_conf.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print("Inspect opencanary command line help & sample config:")
|
||||
print(run("docker run --rm thinkst/opencanary:latest opencanaryd --help"))
|
||||
print("\nSample config template:")
|
||||
print(run("docker run --rm thinkst/opencanary:latest opencanaryd --copyconfig /tmp/oc.conf && docker run --rm thinkst/opencanary:latest cat /tmp/oc.conf 2>/dev/null || docker run --rm --entrypoint cat thinkst/opencanary:latest /root/.opencanary.conf 2>/dev/null || docker run --rm thinkst/opencanary:latest python3 -c 'import opencanary; import pkg_resources; print(pkg_resources.resource_string(\"opencanary\", \"data/settings.json\").decode())'"))
|
||||
|
||||
c.close()
|
||||
|
||||
18
scripts/print_settings_json.py
Normal file
18
scripts/print_settings_json.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print(run("docker run --rm --entrypoint cat thinkst/opencanary:latest /opencanary/opencanary/data/settings.json"))
|
||||
|
||||
c.close()
|
||||
|
||||
26
scripts/read_gotify_apps.py
Normal file
26
scripts/read_gotify_apps.py
Normal file
@@ -0,0 +1,26 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_script = """
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db')
|
||||
cur = conn.cursor()
|
||||
cur.execute("PRAGMA table_info(applications)")
|
||||
print('Columns:', cur.fetchall())
|
||||
cur.execute("SELECT id, token, name, description FROM applications")
|
||||
print('Applications:', cur.fetchall())
|
||||
conn.close()
|
||||
"""
|
||||
c.exec_command("cat << 'EOF' > /tmp/read_gotify_apps.py\n" + py_script + "\nEOF\n")
|
||||
stdin, stdout, stderr = c.exec_command("python3 /tmp/read_gotify_apps.py")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
28
scripts/read_gotify_direct.py
Normal file
28
scripts/read_gotify_direct.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_script = """
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db')
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT name FROM sqlite_master WHERE type='table'")
|
||||
print('Tables:', cur.fetchall())
|
||||
cur.execute("SELECT id, token, name, description FROM application")
|
||||
print('Applications:', cur.fetchall())
|
||||
conn.close()
|
||||
"""
|
||||
c.exec_command("cat << 'EOF' > /tmp/read_gotify.py\n" + py_script + "\nEOF\n")
|
||||
stdin, stdout, stderr = c.exec_command("python3 /tmp/read_gotify.py")
|
||||
print(stdout.read().decode())
|
||||
err = stderr.read().decode()
|
||||
if err: print("Stderr:", err)
|
||||
|
||||
c.close()
|
||||
|
||||
29
scripts/read_gotify_msgs_table.py
Normal file
29
scripts/read_gotify_msgs_table.py
Normal file
@@ -0,0 +1,29 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_query = """
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db')
|
||||
cur = conn.cursor()
|
||||
cur.execute("PRAGMA table_info(messages)")
|
||||
print('Columns:', cur.fetchall())
|
||||
cur.execute("SELECT count(*) FROM messages")
|
||||
print('Count:', cur.fetchall())
|
||||
cur.execute("SELECT * FROM messages ORDER BY id DESC LIMIT 3")
|
||||
print('Last rows:', cur.fetchall())
|
||||
conn.close()
|
||||
"""
|
||||
c.exec_command("cat << 'EOF' > /tmp/read_m.py\n" + py_query + "\nEOF\n")
|
||||
stdin, stdout, stderr = c.exec_command("python3 /tmp/read_m.py")
|
||||
print(stdout.read().decode())
|
||||
err = stderr.read().decode()
|
||||
if err: print("Stderr:", err)
|
||||
|
||||
c.close()
|
||||
15
scripts/read_ha_php.py
Normal file
15
scripts/read_ha_php.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.75", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("docker exec $(docker ps -q -f name=heimdall) cat /config/www/SupportedApps/HomeAssistant/HomeAssistant.php")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
15
scripts/read_ha_supported_app.py
Normal file
15
scripts/read_ha_supported_app.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.75", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("docker exec $(docker ps -q -f name=heimdall) cat /var/www/localhost/heimdall/app/SupportedApps/HomeAssistant/HomeAssistant.php")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
23
scripts/read_heimdall_44.py
Normal file
23
scripts/read_heimdall_44.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.75", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_script = """
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/var/lib/docker/volumes/heimdall_heimdall_config/_data/www/app.sqlite')
|
||||
cur = conn.cursor()
|
||||
cur.execute('SELECT id, title, url, description FROM items WHERE id = 44')
|
||||
print(cur.fetchall())
|
||||
"""
|
||||
c.exec_command("cat << 'EOF' > /tmp/read_h_44.py\n" + py_script + "\nEOF\n")
|
||||
stdin, stdout, stderr = c.exec_command("python3 /tmp/read_h_44.py")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
27
scripts/read_heimdall_all.py
Normal file
27
scripts/read_heimdall_all.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.75", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_code = """
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/var/lib/docker/volumes/heimdall_heimdall_config/_data/www/app.sqlite')
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT id, title, url, appdescription, appid FROM items")
|
||||
for r in cur.fetchall():
|
||||
print(r)
|
||||
cur.execute("SELECT name FROM sqlite_master WHERE type='table'")
|
||||
print('Tables:', cur.fetchall())
|
||||
"""
|
||||
stdin, stdout, stderr = c.exec_command(f'python3 -c "{py_code}"')
|
||||
print(stdout.read().decode())
|
||||
err = stderr.read().decode()
|
||||
if err: print("Stderr:", err)
|
||||
|
||||
c.close()
|
||||
|
||||
32
scripts/read_heimdall_items.py
Normal file
32
scripts/read_heimdall_items.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.75", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_code = """
|
||||
import sqlite3, glob
|
||||
db_files = glob.glob('/var/lib/docker/volumes/*heimdall*/_data/www/app.sqlite')
|
||||
if not db_files:
|
||||
print('No db found on host, searching...')
|
||||
db_files = glob.glob('/var/lib/docker/volumes/**/app.sqlite', recursive=True)
|
||||
print('Found:', db_files)
|
||||
if db_files:
|
||||
conn = sqlite3.connect(db_files[0])
|
||||
cur = conn.cursor()
|
||||
cur.execute('SELECT id, title, url, config FROM items')
|
||||
for row in cur.fetchall():
|
||||
if any(w in row[1].lower() for w in ['home', 'assist', 'snarf']):
|
||||
print(row)
|
||||
"""
|
||||
stdin, stdout, stderr = c.exec_command(f'python3 -c "{py_code}"')
|
||||
print(stdout.read().decode())
|
||||
err = stderr.read().decode()
|
||||
if err: print("Stderr:", err)
|
||||
|
||||
c.close()
|
||||
|
||||
32
scripts/read_heimdall_keys.py
Normal file
32
scripts/read_heimdall_keys.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.75", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_script = """
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/var/lib/docker/volumes/heimdall_heimdall_config/_data/www/app.sqlite')
|
||||
cur = conn.cursor()
|
||||
for tbl in ['items', 'settings', 'setting_user', 'applications']:
|
||||
print('=== Table:', tbl, '===')
|
||||
cur.execute(f'PRAGMA table_info({tbl})')
|
||||
print([c[1] for c in cur.fetchall()])
|
||||
cur.execute(f'SELECT * FROM {tbl} WHERE 1')
|
||||
for r in cur.fetchall():
|
||||
row_str = str(r)
|
||||
if any(w in row_str.lower() for w in ['home', 'assist', 'snarf', 'token', 'key']):
|
||||
print(r)
|
||||
"""
|
||||
c.exec_command("cat << 'EOF' > /tmp/read_h_settings.py\n" + py_script + "\nEOF\n")
|
||||
stdin, stdout, stderr = c.exec_command("python3 /tmp/read_h_settings.py")
|
||||
print(stdout.read().decode())
|
||||
err = stderr.read().decode()
|
||||
if err: print("Stderr:", err)
|
||||
|
||||
c.close()
|
||||
|
||||
29
scripts/read_heimdall_remote.py
Normal file
29
scripts/read_heimdall_remote.py
Normal file
@@ -0,0 +1,29 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.75", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_script = """
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/var/lib/docker/volumes/heimdall_heimdall_config/_data/www/app.sqlite')
|
||||
cur = conn.cursor()
|
||||
cur.execute('SELECT id, title, url, class, appid FROM items')
|
||||
for r in cur.fetchall():
|
||||
print(r)
|
||||
cur.execute('SELECT name FROM sqlite_master WHERE type="table"')
|
||||
print('Tables:', cur.fetchall())
|
||||
"""
|
||||
# write to temporary script on remote host
|
||||
c.exec_command("cat << 'EOF' > /tmp/read_h.py\n" + py_script + "\nEOF\n")
|
||||
stdin, stdout, stderr = c.exec_command("python3 /tmp/read_h.py")
|
||||
print(stdout.read().decode())
|
||||
err = stderr.read().decode()
|
||||
if err: print("Stderr:", err)
|
||||
|
||||
c.close()
|
||||
|
||||
26
scripts/read_heimdall_schema.py
Normal file
26
scripts/read_heimdall_schema.py
Normal file
@@ -0,0 +1,26 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.75", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_code = """
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/var/lib/docker/volumes/heimdall_heimdall_config/_data/www/app.sqlite')
|
||||
cur = conn.cursor()
|
||||
cur.execute('PRAGMA table_info(items)')
|
||||
print('Columns:', cur.fetchall())
|
||||
cur.execute('SELECT * FROM items WHERE title LIKE "%home%" OR title LIKE "%assist%"')
|
||||
print('Items:', cur.fetchall())
|
||||
"""
|
||||
stdin, stdout, stderr = c.exec_command(f'python3 -c "{py_code}"')
|
||||
print(stdout.read().decode())
|
||||
err = stderr.read().decode()
|
||||
if err: print("Stderr:", err)
|
||||
|
||||
c.close()
|
||||
|
||||
15
scripts/read_redirection_1.py
Normal file
15
scripts/read_redirection_1.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = c.exec_command("cat /var/lib/docker/volumes/nginx-proxy-manager_nginx-data/_data/nginx/redirection_host/1.conf")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
36
scripts/refine_canary_watcher.py
Normal file
36
scripts/refine_canary_watcher.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_patch = """
|
||||
path = '/opt/opencanary/alert_watcher.py'
|
||||
with open(path, 'r') as f:
|
||||
text = f.read()
|
||||
|
||||
target = 'def send_alert(event):'
|
||||
replacement = '''def send_alert(event):
|
||||
src_host = event.get("src_host", "")
|
||||
src_port = event.get("src_port", -1)
|
||||
# Ignore empty or internal startup events
|
||||
if not src_host or src_port == -1:
|
||||
return'''
|
||||
|
||||
if target in text and 'if not src_host or src_port == -1:' not in text:
|
||||
text = text.replace(target, replacement)
|
||||
with open(path, 'w') as f:
|
||||
f.write(text)
|
||||
print("Patched alert_watcher.py with filter")
|
||||
else:
|
||||
print("Filter already present or target not found")
|
||||
"""
|
||||
c.exec_command(f'python3 -c "{py_patch}"')
|
||||
c.exec_command("systemctl restart opencanary-watcher.service")
|
||||
print("Restarted watcher service")
|
||||
|
||||
c.close()
|
||||
41
scripts/setup_opencanary_gotify_app.py
Normal file
41
scripts/setup_opencanary_gotify_app.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_script = """
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db')
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT id FROM applications WHERE token = 'A9oPeNcAnArYhOnEyPoT'")
|
||||
if not cur.fetchone():
|
||||
cur.execute('''INSERT INTO applications (id, token, user_id, name, description, internal, default_priority)
|
||||
VALUES (6, 'A9oPeNcAnArYhOnEyPoT', 1, 'OpenCanary Honeypot', 'OpenCanary decoy honeypot probes and unauthorized access detections', 0, 8)''')
|
||||
conn.commit()
|
||||
print('Inserted OpenCanary app (ID 6)')
|
||||
else:
|
||||
print('OpenCanary app already exists')
|
||||
cur.execute("SELECT id, token, name, description FROM applications WHERE id = 6")
|
||||
print(cur.fetchall())
|
||||
conn.close()
|
||||
"""
|
||||
c.exec_command("cat << 'EOF' > /tmp/setup_oc_gotify.py\n" + py_script + "\nEOF\n")
|
||||
stdin, stdout, stderr = c.exec_command("python3 /tmp/setup_oc_gotify.py")
|
||||
print(stdout.read().decode())
|
||||
|
||||
# Test sending a message to Gotify with this token
|
||||
print("\nTesting Gotify message dispatch with new token:")
|
||||
stdin, stdout, stderr = c.exec_command("""
|
||||
curl -s -X POST "http://127.0.0.1:8090/message?token=A9oPeNcAnArYhOnEyPoT" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"title": "OpenCanary Initialized", "message": "Honeypot monitoring armed on VLAN 50 decoy IP 14.4.4.99", "priority": 5}'
|
||||
""")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
39
scripts/test_ak_ha_authorize.py
Normal file
39
scripts/test_ak_ha_authorize.py
Normal file
@@ -0,0 +1,39 @@
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
import ssl
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
|
||||
params = {
|
||||
"client_id": "homeassistant-7de44ad1",
|
||||
"redirect_uri": "https://4qwu1vav8er84pjh1r9x7qt1ajwq9siw.ui.nabu.casa/auth/oidc/callback",
|
||||
"response_type": "code",
|
||||
"scope": "openid profile groups",
|
||||
"state": "test_state_123"
|
||||
}
|
||||
|
||||
url = f"https://authentik.snarfnet.net/application/o/authorize/?{urllib.parse.urlencode(params)}"
|
||||
print("Testing Authorize URL:", url)
|
||||
|
||||
req = urllib.request.Request(url)
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=8, context=ctx) as r:
|
||||
print("Status code:", r.getcode())
|
||||
body = r.read().decode('utf-8', errors='ignore')
|
||||
if "Redirect URI Error" in body:
|
||||
print("ERROR: Redirect URI Error still present!")
|
||||
else:
|
||||
print("SUCCESS: Authorize endpoint accepted the redirect_uri!")
|
||||
except urllib.error.HTTPError as e:
|
||||
print("HTTP error:", e.code)
|
||||
body = e.read().decode('utf-8', errors='ignore')
|
||||
if "Redirect URI Error" in body:
|
||||
print("ERROR: Redirect URI Error still present!")
|
||||
else:
|
||||
print("Body preview:", body[:300])
|
||||
|
||||
47
scripts/test_full_canary_probe.py
Normal file
47
scripts/test_full_canary_probe.py
Normal file
@@ -0,0 +1,47 @@
|
||||
import paramiko
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
print("--- 1. Probing OpenCanary from Spaceport (140.44.4.41) ---")
|
||||
sp = paramiko.SSHClient()
|
||||
sp.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
sp.connect("140.44.4.41", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def sp_run(cmd):
|
||||
stdin, stdout, stderr = sp.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
# Probe 1: HTTP hit
|
||||
print("HTTP probe:", sp_run("curl -s -i http://14.4.4.99/test-probe | head -n 5"))
|
||||
|
||||
# Probe 2: Telnet probe
|
||||
print("Telnet probe:", sp_run("curl -s telnet://14.4.4.99:23 --max-time 2 2>&1 | head -n 3"))
|
||||
|
||||
# Probe 3: SSH probe with fake credentials
|
||||
print("SSH probe:", sp_run("sshpass -p 'HoneypotSecret123!' ssh -o StrictHostKeyChecking=no -o ConnectTimeout=3 admin@14.4.4.99 2>&1 || echo 'SSH auth attempted'"))
|
||||
|
||||
sp.close()
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
print("\n--- 2. Checking OpenCanary Log on 140.44.4.71 ---")
|
||||
sw = paramiko.SSHClient()
|
||||
sw.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
sw.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = sw.exec_command("tail -n 5 /opt/opencanary/logs/opencanary.log")
|
||||
print(stdout.read().decode('utf-8', errors='ignore'))
|
||||
|
||||
print("\n--- 3. Checking Watcher Journal Output ---")
|
||||
stdin, stdout, stderr = sw.exec_command("journalctl -u opencanary-watcher.service -n 10 --no-pager")
|
||||
print(stdout.read().decode('utf-8', errors='ignore'))
|
||||
|
||||
print("\n--- 4. Checking Messages in Gotify Database ---")
|
||||
stdin, stdout, stderr = sw.exec_command("sqlite3 /var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db 'SELECT id, appid, title, message, date FROM messages ORDER BY id DESC LIMIT 5;'")
|
||||
print(stdout.read().decode('utf-8', errors='ignore'))
|
||||
|
||||
sw.close()
|
||||
|
||||
33
scripts/test_ha_api.py
Normal file
33
scripts/test_ha_api.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import urllib.request
|
||||
import json
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
|
||||
HA_URL = "http://14.4.4.20:8123/api/"
|
||||
HA_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkZWNlMWI5ZjJhZDQ0MTRmODU4NGYzN2I1YjgwZDQxMiIsImlhdCI6MTc5MzQ1MjQ2MywiZXhwIjoyMTA4ODEyNDYzfQ.JznpOqsCSnHz6aTVa8K9pQCz1816DC8SrmS1xn1Sm2k"
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {HA_TOKEN}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
req = urllib.request.Request(HA_URL, headers=headers)
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=5) as r:
|
||||
print("HA API response (http://14.4.4.20:8123/api/):", r.getcode(), r.read().decode())
|
||||
except Exception as e:
|
||||
print("HA API error (http://14.4.4.20:8123/api/):", e)
|
||||
|
||||
# Test via https://snarfhome.snarfnet.net/api/
|
||||
req2 = urllib.request.Request("https://snarfhome.snarfnet.net/api/", headers=headers)
|
||||
import ssl
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
try:
|
||||
with urllib.request.urlopen(req2, timeout=5, context=ctx) as r:
|
||||
print("HA API response (https://snarfhome.snarfnet.net/api/):", r.getcode(), r.read().decode()[:200])
|
||||
except Exception as e:
|
||||
print("HA API error (https://snarfhome.snarfnet.net/api/):", e)
|
||||
|
||||
25
scripts/test_ha_direct.py
Normal file
25
scripts/test_ha_direct.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore')
|
||||
|
||||
print("--- HTTP test to 14.4.4.20:8123 ---")
|
||||
print(run("curl -s -I http://14.4.4.20:8123/ | head -n 10"))
|
||||
|
||||
print("--- HTTPS test to 14.4.4.20:8123 ---")
|
||||
print(run("curl -k -s -I https://14.4.4.20:8123/ | head -n 10"))
|
||||
|
||||
print("--- Ping to 14.4.4.20 ---")
|
||||
print(run("ping -c 2 14.4.4.20"))
|
||||
|
||||
c.close()
|
||||
|
||||
20
scripts/test_ha_proxy_support.py
Normal file
20
scripts/test_ha_proxy_support.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore')
|
||||
|
||||
print("--- Test curl with X-Forwarded-For and Host snarfhome ---")
|
||||
cmd = "curl -i -H 'Host: snarfhome.snarfnet.net' -H 'X-Forwarded-For: 140.44.4.71' -H 'X-Forwarded-Proto: https' http://14.4.4.20:8123/"
|
||||
print(run(cmd))
|
||||
|
||||
c.close()
|
||||
|
||||
33
scripts/test_heimdall_container_curl.py
Normal file
33
scripts/test_heimdall_container_curl.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.75", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzZWUyNTE1MDk0NGU0ZjRjYmJkMGM1MWI5MThmY2EzYiIsImlhdCI6MTc0NjgxMDM3NSwiZXhwIjoyMDYyMTcwMzc1fQ.Le6M7WL63nxtLTxccFacQR5GVUY5C-a_zGtmXT_uaz4"
|
||||
|
||||
cmd = f"""
|
||||
docker exec $(docker ps -q -f name=heimdall) curl -k -i -X POST https://snarfhome.snarfnet.net/api/template \
|
||||
-H "Authorization: Bearer {token}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{{"template": "{{{{ states.light | count}}}}"}}'
|
||||
"""
|
||||
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
print("Heimdall curl test to snarfhome.snarfnet.net:\n", stdout.read().decode())
|
||||
|
||||
cmd2 = f"""
|
||||
docker exec $(docker ps -q -f name=heimdall) curl -k -i -X POST http://14.4.4.20:8123/api/template \
|
||||
-H "Authorization: Bearer {token}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{{"template": "{{{{ states.light | count}}}}"}}'
|
||||
"""
|
||||
stdin, stdout, stderr = c.exec_command(cmd2)
|
||||
print("Heimdall curl test to 14.4.4.20:8123:\n", stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
28
scripts/test_heimdall_token.py
Normal file
28
scripts/test_heimdall_token.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import urllib.request
|
||||
import ssl
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
|
||||
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzZWUyNTE1MDk0NGU0ZjRjYmJkMGM1MWI5MThmY2EzYiIsImlhdCI6MTc0NjgxMDM3NSwiZXhwIjoyMDYyMTcwMzc1fQ.Le6M7WL63nxtLTxccFacQR5GVUY5C-a_zGtmXT_uaz4"
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
|
||||
for u in ["http://14.4.4.20:8123/api/states", "https://snarfhome.snarfnet.net/api/states"]:
|
||||
print("Testing:", u)
|
||||
req = urllib.request.Request(u, headers=headers)
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=5, context=ctx) as r:
|
||||
print("Status:", r.getcode())
|
||||
except urllib.error.HTTPError as e:
|
||||
print("HTTP Error:", e.code, e.read().decode())
|
||||
except Exception as e:
|
||||
print("Exception:", e)
|
||||
|
||||
32
scripts/test_live_ssh_alert.py
Normal file
32
scripts/test_live_ssh_alert.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import paramiko
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
print("--- Sending SSH probe from Spaceport to 14.4.4.99 ---")
|
||||
sp = paramiko.SSHClient()
|
||||
sp.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
sp.connect("140.44.4.41", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = sp.exec_command("ssh -o StrictHostKeyChecking=no -o ConnectTimeout=3 -o BatchMode=yes admin@14.4.4.99 2>&1 || true")
|
||||
print("SSH probe output:", stdout.read().decode())
|
||||
sp.close()
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
print("--- Checking Watcher Logs on 140.44.4.71 ---")
|
||||
sw = paramiko.SSHClient()
|
||||
sw.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
sw.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = sw.exec_command("journalctl -u opencanary-watcher.service -n 10 --no-pager")
|
||||
print(stdout.read().decode())
|
||||
|
||||
print("\n--- Checking Gotify Messages ---")
|
||||
stdin, stdout, stderr = sw.exec_command("sqlite3 /var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db 'SELECT id, appid, title, message, date FROM messages WHERE appid = 6 ORDER BY id DESC LIMIT 5;'")
|
||||
print(stdout.read().decode())
|
||||
|
||||
sw.close()
|
||||
|
||||
47
scripts/test_opencanary_alert.py
Normal file
47
scripts/test_opencanary_alert.py
Normal file
@@ -0,0 +1,47 @@
|
||||
import paramiko
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
print("=== 1. Probing OpenCanary decoy IP 14.4.4.99 from Spaceport (140.44.4.41) ===")
|
||||
sp = paramiko.SSHClient()
|
||||
sp.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
sp.connect("140.44.4.41", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def sp_run(cmd):
|
||||
stdin, stdout, stderr = sp.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print("Pinging 14.4.4.99:")
|
||||
print(sp_run("ping -c 2 14.4.4.99"))
|
||||
|
||||
print("\nProbing HTTP (port 80) on 14.4.4.99:")
|
||||
print(sp_run("curl -s -i http://14.4.4.99/admin/login.php | head -n 12"))
|
||||
|
||||
print("\nProbing SSH banner (port 22) on 14.4.4.99:")
|
||||
print(sp_run("nc -z -v -w 2 14.4.4.99 22 2>&1 || curl -s telnet://14.4.4.99:22 --max-time 2 2>&1 | head -n 3"))
|
||||
|
||||
sp.close()
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
print("\n=== 2. Checking OpenCanary Log on Swarm (140.44.4.71) ===")
|
||||
sw = paramiko.SSHClient()
|
||||
sw.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
sw.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = sw.exec_command("tail -n 10 /opt/opencanary/logs/opencanary.log")
|
||||
print(stdout.read().decode('utf-8', errors='ignore'))
|
||||
|
||||
print("\n=== 3. Checking Gotify Alert Watcher Log ===")
|
||||
stdin, stdout, stderr = sw.exec_command("journalctl -u opencanary-watcher.service -n 15 --no-pager")
|
||||
print(stdout.read().decode('utf-8', errors='ignore'))
|
||||
|
||||
print("\n=== 4. Checking Latest Messages in Gotify Database ===")
|
||||
stdin, stdout, stderr = sw.exec_command("sqlite3 /var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db 'SELECT id, appid, title, message, date FROM messages ORDER BY id DESC LIMIT 3;'")
|
||||
print(stdout.read().decode('utf-8', errors='ignore'))
|
||||
|
||||
sw.close()
|
||||
|
||||
55
scripts/test_vlan50_direct_probe.py
Normal file
55
scripts/test_vlan50_direct_probe.py
Normal file
@@ -0,0 +1,55 @@
|
||||
import paramiko
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
print("--- 1. Probing OpenCanary directly from VLAN 50 (nutserver 14.4.4.44) ---")
|
||||
nut = paramiko.SSHClient()
|
||||
nut.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
nut.connect("14.4.4.44", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def nut_run(cmd):
|
||||
stdin, stdout, stderr = nut.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print("Pinging 14.4.4.99 from nutserver:")
|
||||
print(nut_run("ping -c 2 14.4.4.99"))
|
||||
|
||||
print("\nConnecting to SSH on 14.4.4.99:22:")
|
||||
probe_py = """
|
||||
import socket
|
||||
s = socket.socket()
|
||||
s.settimeout(3)
|
||||
s.connect(('14.4.4.99', 22))
|
||||
banner = s.recv(1024)
|
||||
print('Received banner:', banner.decode().strip())
|
||||
s.sendall(b'SSH-2.0-OpenSSH_TestProbe\\r\\n')
|
||||
time_wait = 1
|
||||
s.close()
|
||||
"""
|
||||
print(nut_run(f'python3 -c "{probe_py}"'))
|
||||
|
||||
nut.close()
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
print("\n--- 2. Checking OpenCanary Log on 140.44.4.71 ---")
|
||||
sw = paramiko.SSHClient()
|
||||
sw.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
sw.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
stdin, stdout, stderr = sw.exec_command("tail -n 5 /opt/opencanary/logs/opencanary.log")
|
||||
print(stdout.read().decode('utf-8', errors='ignore'))
|
||||
|
||||
print("\n--- 3. Checking Watcher Journal Output ---")
|
||||
stdin, stdout, stderr = sw.exec_command("journalctl -u opencanary-watcher.service -n 10 --no-pager")
|
||||
print(stdout.read().decode('utf-8', errors='ignore'))
|
||||
|
||||
print("\n--- 4. Checking Messages in Gotify Database ---")
|
||||
stdin, stdout, stderr = sw.exec_command("sqlite3 /var/lib/docker/volumes/gotify_gotify_data/_data/gotify.db 'SELECT id, appid, title, message, date FROM messages WHERE appid = 6 ORDER BY id DESC LIMIT 5;'")
|
||||
print(stdout.read().decode('utf-8', errors='ignore'))
|
||||
|
||||
sw.close()
|
||||
|
||||
29
scripts/test_vlan50_trunk.py
Normal file
29
scripts/test_vlan50_trunk.py
Normal file
@@ -0,0 +1,29 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
return stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
|
||||
print("1. Creating temporary eth0.50 on 140.44.4.71...")
|
||||
run("ip link add link eth0 name eth0.50 type vlan id 50")
|
||||
run("ip addr add 14.4.4.99/25 dev eth0.50")
|
||||
run("ip link set eth0.50 up")
|
||||
|
||||
print("2. Pinging gateway 14.4.4.1 from eth0.50:")
|
||||
ping_out = run("ping -c 2 -I eth0.50 14.4.4.1")
|
||||
print(ping_out)
|
||||
|
||||
print("3. Cleaning up temporary interface...")
|
||||
run("ip link del eth0.50")
|
||||
print("Cleaned up.")
|
||||
|
||||
c.close()
|
||||
|
||||
31
scripts/update_discord_bridge.py
Normal file
31
scripts/update_discord_bridge.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_patch = """
|
||||
path = '/var/lib/docker/volumes/gotify_gotify_data/_data/discord_bridge.py'
|
||||
with open(path, 'r') as f:
|
||||
text = f.read()
|
||||
|
||||
if '6: ("infra-alerts", WEBHOOK_INFRA)' not in text:
|
||||
text = text.replace('5: ("infra-alerts", WEBHOOK_INFRA),', '5: ("infra-alerts", WEBHOOK_INFRA),\\n 6: ("infra-alerts", WEBHOOK_INFRA),')
|
||||
text = text.replace('5: "Backups & Storage Health",', '5: "Backups & Storage Health",\\n 6: "OpenCanary Decoy Honeypot",')
|
||||
with open(path, 'w') as f:
|
||||
f.write(text)
|
||||
print("Patched discord_bridge.py successfully")
|
||||
else:
|
||||
print("Already patched")
|
||||
"""
|
||||
c.exec_command(f'python3 -c "{py_patch}"')
|
||||
# Restart the bridge container
|
||||
c.exec_command("docker service update --force gotify_gotify-discord-bridge")
|
||||
print("Restarted gotify_gotify-discord-bridge")
|
||||
|
||||
c.close()
|
||||
|
||||
52
scripts/update_ha_authentik_uris.py
Normal file
52
scripts/update_ha_authentik_uris.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import urllib.request
|
||||
import ssl
|
||||
import json
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
|
||||
AK_BASE = "https://authentik.snarfnet.net"
|
||||
AK_TOKEN = "SnarfNetPermanentAutomationToken2026"
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {AK_TOKEN}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json"
|
||||
}
|
||||
|
||||
# 1. Fetch current provider 15
|
||||
req = urllib.request.Request(f"{AK_BASE}/api/v3/providers/oauth2/15/", headers=headers)
|
||||
with urllib.request.urlopen(req, timeout=10, context=ctx) as r:
|
||||
prov = json.loads(r.read().decode())
|
||||
|
||||
print("Current redirect URIs:")
|
||||
for u in prov.get("redirect_uris", []):
|
||||
print(" -", u)
|
||||
|
||||
new_uris = [
|
||||
{"matching_mode": "strict", "url": "https://snarfhome.snarfnet.net/auth/external/callback"},
|
||||
{"matching_mode": "strict", "url": "https://snarfhome.snarfnet.net/auth/oidc/callback"},
|
||||
{"matching_mode": "strict", "url": "https://snarfhome.snarfnet.net/"},
|
||||
{"matching_mode": "regex", "url": r"https://snarfhome\.snarfnet\.net.*"},
|
||||
{"matching_mode": "strict", "url": "https://4qwu1vav8er84pjh1r9x7qt1ajwq9siw.ui.nabu.casa/auth/external/callback"},
|
||||
{"matching_mode": "strict", "url": "https://4qwu1vav8er84pjh1r9x7qt1ajwq9siw.ui.nabu.casa/auth/oidc/callback"},
|
||||
{"matching_mode": "strict", "url": "https://4qwu1vav8er84pjh1r9x7qt1ajwq9siw.ui.nabu.casa/"},
|
||||
{"matching_mode": "regex", "url": r"https://4qwu1vav8er84pjh1r9x7qt1ajwq9siw\.ui\.nabu\.casa.*"},
|
||||
{"matching_mode": "regex", "url": r".*nabu\.casa.*"},
|
||||
{"matching_mode": "regex", "url": r"http://14\.4\.4\.20:8123.*"},
|
||||
]
|
||||
|
||||
# 2. Patch provider 15
|
||||
patch_data = json.dumps({"redirect_uris": new_uris}).encode('utf-8')
|
||||
patch_req = urllib.request.Request(f"{AK_BASE}/api/v3/providers/oauth2/15/", data=patch_data, headers=headers, method="PATCH")
|
||||
with urllib.request.urlopen(patch_req, timeout=10, context=ctx) as r:
|
||||
updated = json.loads(r.read().decode())
|
||||
|
||||
print("\nSuccessfully updated Authentik Provider 15 redirect URIs:")
|
||||
for u in updated.get("redirect_uris", []):
|
||||
print(" +", u)
|
||||
|
||||
52
scripts/update_heimdall_ha.py
Normal file
52
scripts/update_heimdall_ha.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import paramiko
|
||||
import sys
|
||||
import json
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.75", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
py_script = """
|
||||
import sqlite3, json
|
||||
|
||||
conn = sqlite3.connect('/var/lib/docker/volumes/heimdall_heimdall_config/_data/www/app.sqlite')
|
||||
cur = conn.cursor()
|
||||
|
||||
# Backup first
|
||||
cur.execute("SELECT id, title, description FROM items WHERE id IN (12, 44)")
|
||||
rows = cur.fetchall()
|
||||
for r in rows:
|
||||
print('Before:', r)
|
||||
cfg = json.loads(r[2])
|
||||
cfg['override_url'] = 'http://14.4.4.20:8123/'
|
||||
new_desc = json.dumps(cfg)
|
||||
cur.execute("UPDATE items SET description = ? WHERE id = ?", (new_desc, r[0]))
|
||||
|
||||
# Also clear cache table if any
|
||||
cur.execute("DELETE FROM cache")
|
||||
conn.commit()
|
||||
print('Cache cleared and items updated!')
|
||||
|
||||
cur.execute("SELECT id, title, description FROM items WHERE id IN (12, 44)")
|
||||
for r in cur.fetchall():
|
||||
print('After:', r)
|
||||
|
||||
conn.close()
|
||||
"""
|
||||
|
||||
c.exec_command("cat << 'EOF' > /tmp/update_h_ha.py\n" + py_script + "\nEOF\n")
|
||||
stdin, stdout, stderr = c.exec_command("python3 /tmp/update_h_ha.py")
|
||||
print(stdout.read().decode())
|
||||
err = stderr.read().decode()
|
||||
if err: print("Stderr:", err)
|
||||
|
||||
# Trigger a curl to Heimdall item livestats
|
||||
print("\nTesting Heimdall live stats endpoint:")
|
||||
stdin, stdout, stderr = c.exec_command("docker exec $(docker ps -q -f name=heimdall) curl -s http://127.0.0.1/get_stats/44")
|
||||
print(stdout.read().decode())
|
||||
|
||||
c.close()
|
||||
|
||||
128
scripts/update_watcher.py
Normal file
128
scripts/update_watcher.py
Normal file
@@ -0,0 +1,128 @@
|
||||
import paramiko
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
new_watcher = """#!/usr/bin/env python3
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
sys.stdout.reconfigure(line_buffering=True)
|
||||
|
||||
LOG_FILE = "/opt/opencanary/logs/opencanary.log"
|
||||
GOTIFY_URL = "http://127.0.0.1:8090/message?token=A9oPeNcAnArYhOnEyPoT"
|
||||
|
||||
LOGTYPE_NAMES = {
|
||||
1000: "Portscan Syn Probe",
|
||||
1001: "Canary System Event",
|
||||
1002: "Portscan Null Scan",
|
||||
1003: "Portscan Xmas Scan",
|
||||
1004: "Portscan Fin Scan",
|
||||
2000: "FTP Connection",
|
||||
2001: "FTP Auth Attempt",
|
||||
3000: "HTTP Connection",
|
||||
3001: "HTTP Web Login Attempt",
|
||||
4000: "SSH Connection",
|
||||
4001: "SSH Auth Attempt",
|
||||
5000: "SMB Session Request",
|
||||
6001: "Telnet Login Attempt",
|
||||
7001: "HTTP Proxy Request",
|
||||
8001: "MySQL Login Attempt",
|
||||
9001: "MSSQL Login Attempt",
|
||||
10001: "VNC Connection",
|
||||
11001: "Git Clone / Pull Attempt",
|
||||
12001: "RDP Connection"
|
||||
}
|
||||
|
||||
def send_alert(event):
|
||||
logtype = event.get("logtype", 0)
|
||||
# Don't alert on internal canary startup messages
|
||||
if logtype == 1001 and "Canary" in str(event.get("logdata", {})):
|
||||
return
|
||||
|
||||
service_name = LOGTYPE_NAMES.get(logtype, f"Canary Event {logtype}")
|
||||
src_host = event.get("src_host", "Unknown IP")
|
||||
src_port = event.get("src_port", "Unknown Port")
|
||||
dst_port = event.get("dst_port", "")
|
||||
logdata = event.get("logdata", {})
|
||||
|
||||
title = f"🚨 [Honeypot Alert] {service_name} from {src_host}"
|
||||
|
||||
details = []
|
||||
details.append(f"• Attacker IP: {src_host}:{src_port}")
|
||||
if dst_port and dst_port != -1:
|
||||
details.append(f"• Targeted Port: {dst_port}")
|
||||
details.append(f"• Decoy IP: 14.4.4.99 (VLAN 50 Smart Home)")
|
||||
|
||||
if isinstance(logdata, dict):
|
||||
if "USERNAME" in logdata:
|
||||
details.append(f"• Username attempted: {logdata.get('USERNAME')}")
|
||||
if "PASSWORD" in logdata:
|
||||
details.append(f"• Password attempted: {logdata.get('PASSWORD')}")
|
||||
if "PATH" in logdata:
|
||||
details.append(f"• Path: {logdata.get('PATH')}")
|
||||
if "USERAGENT" in logdata:
|
||||
details.append(f"• User-Agent: {logdata.get('USERAGENT')}")
|
||||
elif logdata:
|
||||
details.append(f"• Payload: {str(logdata)[:200]}")
|
||||
|
||||
body = "\\n".join(details)
|
||||
|
||||
payload = {
|
||||
"title": title,
|
||||
"message": body,
|
||||
"priority": 8
|
||||
}
|
||||
|
||||
try:
|
||||
req = urllib.request.Request(
|
||||
GOTIFY_URL,
|
||||
data=json.dumps(payload).encode('utf-8'),
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=5) as r:
|
||||
pass
|
||||
print(f"[Alert Sent] {title}", flush=True)
|
||||
except Exception as e:
|
||||
print(f"[Alert Error] {e}", flush=True)
|
||||
|
||||
def main():
|
||||
print("OpenCanary Gotify Watcher started...", flush=True)
|
||||
if not os.path.exists(LOG_FILE):
|
||||
open(LOG_FILE, 'a').close()
|
||||
|
||||
f = open(LOG_FILE, 'r')
|
||||
f.seek(0, os.SEEK_END)
|
||||
|
||||
while True:
|
||||
line = f.readline()
|
||||
if line:
|
||||
line = line.strip()
|
||||
if line:
|
||||
try:
|
||||
event = json.loads(line)
|
||||
send_alert(event)
|
||||
except Exception as e:
|
||||
pass
|
||||
else:
|
||||
time.sleep(0.5)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
"""
|
||||
|
||||
c.exec_command("cat << 'EOF' > /opt/opencanary/alert_watcher.py\n" + new_watcher + "\nEOF\n")
|
||||
c.exec_command("systemctl restart opencanary-watcher.service")
|
||||
print("Restarted watcher service")
|
||||
|
||||
c.close()
|
||||
|
||||
Reference in New Issue
Block a user