Skip to content

Releases: sshpie/galleria

v0.37.0 — source analysis research published

Choose a tag to compare

@sshpie sshpie released this 29 Aug 08:28

Source analysis research published

All 30 honeypot detection signatures in galleria trace back to bugs and hardcoded values found during direct source code audits. The full research is now in the repo at docs/honeypot-research/ — 29 files, one per honeypot, each covering 5 parallel audit lanes (injection/auth, protocol correctness, fingerprint/evasion surface, logging, coding errors).

What the audits found

Every fingerprint is sourced from one of two bug classes:

Hardcoded values — single-packet, pre-auth identification, near-zero false-positive rate:

  • MysqlPot — auth scramble is always BBBBBBBBBBBB (12 bytes of 0x42, MysqlDefs.cs). Real MySQL generates a random 20-byte nonce.
  • Cowrie — SSH banner hardcoded to SSH-2.0-OpenSSH_6.0p1 Debian-4+deb7u2 (2012). KEXINIT packets null-padded; real OpenSSH pads with random bytes. Detectable passively before any auth attempt.
  • pghoney — MD5 auth salt identical across every connection and every deployment (serverutils.go:67).
  • sticky_elephant — backend PID always reported as 666 in ParameterStatus messages (postgres_simulator.rb).
  • Dionaea — SIP digest nonce hardcoded to foobar123 across all deployments.
  • Conpot — SNMP sysLocation hardcoded to "Venus"; Guardian AST station name hardcoded to "STATOIL STATION".
  • OpenCanary — MSSQL NTLM challenge blob contains the string thinkst.com verbatim.
  • elastichoney / elasticpot — node UUID, MAC address, and build hash identical across every deployment worldwide.
  • LophiidSendStatus explicitly documented as unauthenticated in source (backend.go:626): // SendStatus is not authenticated.

Behavioral bugs — implementation errors detectable via protocol-level dialog:

  • Dionaea MemcacheSET foo barGET foo returns END instead of VALUE foo. Fresh FakeRedis instance created per data event; state never persists.
  • Dionaea MQTTCONNECT with garbage credentials returns CONNACK 0x00 (accepted). Real brokers return 0x05 (refused).
  • Dionaea SIPINVITE without Authorization accepted unconditionally. Real SIP servers challenge with 407.
  • nosqlpotAUTH missing from Redis dispatch table entirely (redisdeploy.py:75). Returns unknown command 'auth'; real Redis returns -NOAUTH Authentication required.
  • MongoDB-HoneyProxy — no OP_MSG handler; messages silently dropped. Real MongoDB responds.
  • OpenCanary MSSQLbytes.find(str) raises TypeError in Python 3 on the first valid TDS PRELOGIN packet (mssql.py:129). Handler crashes before logging anything.
  • sticky_elephantauthenticate() calls send_authentication_ok without checking the password. Every credential, including random garbage, is accepted.
  • Honeyd FTPSYST returns Windows_NT on Linux hosts.

Full architecture and competitive comparison vs. honeyscore, nmap NSE, and nuclei templates: docs/ARCHITECTURE.md.

Install

go install github.com/sshpie/galleria@latest

v0.36.0

Choose a tag to compare

@sshpie sshpie released this 26 Aug 01:01

fix: MysqlHoneypotd godoc correction (N→N+1 sequential check)

v0.35.0

Choose a tag to compare

@sshpie sshpie released this 26 Aug 00:49

fix: MysqlHoneypotd sequential thread_id check; README word counts

v0.34.0 — elasticpot (standalone)

Choose a tag to compare

@sshpie sshpie released this 26 Aug 00:40

elasticpot (bontchev/elasticpot) — also covered in v0.31.0 alongside elastichoney.

Python/Twisted Elasticsearch honeypot. Distinct from elastichoney via build hash b88f43fc40b0bcd7f173a1f9ee2e97816de80b21 and instance_name "Green Goblin" in cluster settings. Shares node UUID x1JG6g9PRHy6ClCOO2-C4g with elastichoney.

Signal: GET /_cluster/settings → "Green Goblin" (99%).

v0.33.0 — mysql-honeypotd

Choose a tag to compare

@sshpie sshpie released this 26 Aug 00:40

mysql-honeypotd (sjinks/mysql-honeypotd)

C MySQL honeypot daemon. Uses srand(time(NULL)) seeded once at startup (globals.c:17) and a connection counter starting at 0. thread_id=0 for first connection, 1 for second. Real MySQL thread IDs are non-sequential, start above 1, and vary across restarts.

Signals:

  • Two consecutive connections: thread_id = 0, then 1 (95%)
  • server_version "8.0.19" + thread_id = 0 (80%)

v0.32.0 — MysqlPot

Choose a tag to compare

@sshpie sshpie released this 26 Aug 00:40

MysqlPot (schmalle/MysqlPot)

C# MySQL honeypot. Hardcodes SCRAMBLE = "BBBBBBBBBBBB" (12 bytes of 0x42) in MysqlDefs.cs. First 8 bytes appear in HandshakeV10 auth-plugin-data-part-1 — all 0x42. Real MySQL generates a random 20-byte challenge per connection.

Signal: HandshakeV10 → 8 consecutive 0x42 bytes in auth challenge (99%).

v0.31.0 — elastichoney + elasticpot

Choose a tag to compare

@sshpie sshpie released this 26 Aug 00:40

elastichoney (jordan-wright/elastichoney) and elasticpot (bontchev/elasticpot)

Both hardcode node UUID x1JG6g9PRHy6ClCOO2-C4g and MAC 08:01:c7:3F:15:DD. Build hash distinguishes them:

  • elastichoney: 89d3241d670db65f994242c8e838b169779e2d4 (main.go:75) — static PID=2039
  • elasticpot: b88f43fc40b0bcd7f173a1f9ee2e97816de80b21 (core/protocol.py) — instance_name "Green Goblin"

Signal: GET /_nodes → shared node UUID + build hash (99% each).

v0.30.0 — MongoDB-HoneyProxy

Choose a tag to compare

@sshpie sshpie released this 26 Aug 00:40

MongoDB-HoneyProxy (Plazmaz/MongoDB-HoneyProxy)

Node.js transparent MongoDB proxy. No handler for OP_MSG (opcode 2013) — used by all MongoDB 3.6+ drivers since 2017. Port open to MongoDB connections returns no response to OP_MSG isMaster; real MongoDB always responds within milliseconds.

Signal: OP_MSG → zero bytes returned from open port (75%).

v0.27.0 — pghoney + nosqlpot + sticky_elephant

Choose a tag to compare

@sshpie sshpie released this 26 Aug 00:29

Adds PostgreSQL and NoSQL honeypot fingerprinting. Three new detections:

pghoney (betheroot/pghoney) — Go PostgreSQL honeypot:

  • 99% — MD5 auth salt 0x336FBFD2 hardcoded in serverutils.go:67 — same bytes on every connection/restart; real PostgreSQL generates a random salt per connection

nosqlpot (torque59/nosqlpot) — Python 2 Redis+CouchDB honeypot:

  • 99% Redis — AUTH returns -ERR unknown command 'auth' (lowercase single-quote; distinguishes from RedisHoneyPot's backtick-uppercase format and real Redis -NOAUTH/-WRONGPASS)
  • 99% Redis — INFO returns static process_id=30064 (never changes)
  • 99% CouchDB — welcome JSON body has trailing semicolon (invalid JSON)
  • 95% CouchDB — Content-Type: charset=utf-7 (real CouchDB always uses utf-8)

sticky_elephant (betheroot/sticky_elephant) — Ruby PostgreSQL honeypot:

  • 90% — cleartext auth (type 3) + AuthOk for any submitted password (authenticate() unconditional)
  • 99% — BackendKeyData pid=666 hardcoded in postgres_simulator.rb (real PostgreSQL sends actual OS PID)

Port 5432 fast-path added for pghoney/sticky_elephant. Nosqlpot Redis probes wired into the 6379/6380 dispatch.

v0.26.0 — RedisHoneyPot (cypwnpwnsocute/RedisHoneyPot)

Choose a tag to compare

@sshpie sshpie released this 26 Aug 00:22

Adds fingerprinting for RedisHoneyPot (cypwnpwnsocute/RedisHoneyPot).

Four-probe chain — all probes at the RESP protocol layer, no auth required:

  • 99%AUTH x returns -ERR unknown command AUTH`` — no case "auth" in dispatch; real Redis 6.x always handles AUTH
  • 99%INFO server returns static run_id:41be2f14e917b27b95ab0fe58f90d9521661dcd1 (redis.conf:18 — hardcoded; real Redis regenerates on every startup)
  • 99%INFO replication returns static master_replid:e8ab6fdf17602f25e3aee87612ddaa3919502761 (redis.conf:124 — hardcoded; real Redis regenerates after restart or simulated failover)
  • 90%GET nonexistent returns +(nil) simple string instead of $-1 bulk null (RESP type mismatch in server.go)

Wired before the generic Redis depth test in the verdict.go Redis dispatch.