Releases: sshpie/galleria
Release list
v0.37.0 — source analysis research published
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 of0x42,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
666in ParameterStatus messages (postgres_simulator.rb). - Dionaea — SIP digest nonce hardcoded to
foobar123across all deployments. - Conpot — SNMP
sysLocationhardcoded to"Venus"; Guardian AST station name hardcoded to"STATOIL STATION". - OpenCanary — MSSQL NTLM challenge blob contains the string
thinkst.comverbatim. - elastichoney / elasticpot — node UUID, MAC address, and build hash identical across every deployment worldwide.
- Lophiid —
SendStatusexplicitly documented as unauthenticated in source (backend.go:626):// SendStatus is not authenticated.
Behavioral bugs — implementation errors detectable via protocol-level dialog:
- Dionaea Memcache —
SET foo bar→GET fooreturnsENDinstead ofVALUE foo. FreshFakeRedisinstance created per data event; state never persists. - Dionaea MQTT —
CONNECTwith garbage credentials returnsCONNACK 0x00(accepted). Real brokers return0x05(refused). - Dionaea SIP —
INVITEwithoutAuthorizationaccepted unconditionally. Real SIP servers challenge with407. - nosqlpot —
AUTHmissing from Redis dispatch table entirely (redisdeploy.py:75). Returnsunknown command 'auth'; real Redis returns-NOAUTH Authentication required. - MongoDB-HoneyProxy — no OP_MSG handler; messages silently dropped. Real MongoDB responds.
- OpenCanary MSSQL —
bytes.find(str)raisesTypeErrorin Python 3 on the first valid TDS PRELOGIN packet (mssql.py:129). Handler crashes before logging anything. - sticky_elephant —
authenticate()callssend_authentication_okwithout checking the password. Every credential, including random garbage, is accepted. - Honeyd FTP —
SYSTreturnsWindows_NTon Linux hosts.
Full architecture and competitive comparison vs. honeyscore, nmap NSE, and nuclei templates: docs/ARCHITECTURE.md.
Install
go install github.com/sshpie/galleria@latestv0.36.0
v0.35.0
v0.34.0 — elasticpot (standalone)
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
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
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
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
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
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 —
AUTHreturns-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=666hardcoded 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)
Adds fingerprinting for RedisHoneyPot (cypwnpwnsocute/RedisHoneyPot).
Four-probe chain — all probes at the RESP protocol layer, no auth required:
- 99% —
AUTH xreturns-ERR unknown commandAUTH`` — nocase "auth"in dispatch; real Redis 6.x always handles AUTH - 99% —
INFO serverreturns staticrun_id:41be2f14e917b27b95ab0fe58f90d9521661dcd1(redis.conf:18 — hardcoded; real Redis regenerates on every startup) - 99% —
INFO replicationreturns staticmaster_replid:e8ab6fdf17602f25e3aee87612ddaa3919502761(redis.conf:124 — hardcoded; real Redis regenerates after restart or simulated failover) - 90% —
GET nonexistentreturns+(nil)simple string instead of$-1bulk null (RESP type mismatch in server.go)
Wired before the generic Redis depth test in the verdict.go Redis dispatch.