Final Report · Multi-Protocol Honeypot · Decommissioned
HACKTRAP listened on six protocols from a single unremarkable IP address. It advertised nothing, was linked from nowhere, and had no users. Everything below arrived unprompted. The figures are counts of logged events, not of distinct intrusion attempts: one botnet session can be dozens of events, and the overwhelming majority of them are one machine reciting a script into a socket that answers politely.
The first thing the data says is that the internet's background radiation is not evenly spread. Telnet alone accounted for — of — events — — of everything. That is not attackers preferring Telnet; it is the IoT botnet population, which is enormous, fully automated, and still hunting for the same consumer routers and cameras it was hunting a decade ago. SSH, the protocol a human being would actually try, came second — and came second by a factor of eighty. Every protocol below Telnet is, statistically, a rounding error — and every one of them was more interesting to read.
Traffic was not steady. A honeypot's address propagates through scanner target lists over weeks, and a single botnet deciding to sweep a netblock can multiply a day's volume without warning — the busiest day, —, carried — events on its own. The three series are the classification the honeypot assigned in real time: a scanner connects and leaves, a prober authenticates or fingerprints, an exploiter attempts something that would cause harm on a real host. Note how rarely the exploiter line sits at zero.
By hour of day the pattern is flatter than a human schedule would be, but not flat. The peak hour UTC was —, which is the start of the working morning in the country that supplied two thirds of the traffic. Automation has a timezone, because the people who start it do.
Geolocation here is country-level and derived from the connecting address, which is the address of a compromised device rather than of an operator. Read the table as a census of infected hardware, not of intent. — countries appear at least once; the top three supplied — of all events between them.
This is the finding worth the 110 days. A honeypot that only refuses logins learns very little; HACKTRAP instead leaked plausible fiction. Its MySQL and PostgreSQL personalities named accounts and databases in error text and handshake metadata, and its Redis personality behaved like a box worth persisting on. The attackers read the fiction and used it.
The database names below are the proof. meridian_prod,
carbonitex_prod and carbonitex_staging do not exist and
never did — they were invented for this trap. They are the three most-queried databases
on the honeypot, ahead of mysql and information_schema, which are
the names a scanner would try blind. Something in the loop read the bait and came back for it,
which means the automation that hits an unknown host is more adaptive than the phrase
"credential stuffing" suggests.
Nothing here was ever a valid credential, so all of it is guesswork captured verbatim. Two
distinct populations are visible. Telnet guesses are vendor defaults —
juantech, bluehorse, 20080826 are factory passwords
for specific camera and DVR firmware, and a botnet carrying them is looking for hardware,
not for you. SSH guesses are a mix of the same tired list and something stranger, which the
callout explains.
Both shells were emulated: commands were parsed, answered with convincing output, and discarded. The SSH list is short and deliberate; the Telnet list is a machine gun. The single most common SSH command is worth reading twice.
The Telnet commands read as one long fingerprinting ritual: shell,
enable, system, linuxshell and su are
attempts to escape a vendor menu shell into something POSIX, and the repeated
/bin/busybox invocations against /bin/ls are a well-known
Mirai-lineage check: read the first 52 bytes of a known binary, parse the ELF header, learn
the CPU architecture, then request the matching malware build. busybox appears
in — of all parsed Telnet command tokens.
Session shape separates the two populations more cleanly than any other measure. SSH sessions are short and mostly end because the honeypot decided it had seen enough. Telnet sessions are long, enormous in command count, and almost never give up early.
Once a botnet believes it has a shell it tries to fetch a binary. HACKTRAP recorded
— download attempts from
— distinct loader hosts, and fetched none of them.
The filenames are the interesting part: the per-architecture variants
(tarm, tarm5, tarm7, tmips,
tmpsl) appear in near-identical counts, which is a single loader script trying
every build in sequence because it could not determine the CPU. The one-letter i
and the wget.sh/curl.sh pair are the standard shape of a
second-stage dropper.
Loader hosts are overwhelmingly the same machine that just connected, serving the payload from a high ephemeral port — a compromised device acting as its own distribution point. Addresses below are masked and defanged; filenames and ports are verbatim.
The MySQL query log is not what a hand-driven attack looks like. The top entries are the
introspection queries that a connector library emits on connect — INFORMATION_SCHEMA
lookups, optimizer_switch, SET SQL_QUOTE_SHOW_CREATE — which
means the attackers were pointing real ORMs and admin tools at the honeypot rather than raw
sockets. PostgreSQL was quieter and more purposeful: the second most common statement resets
the password on an attacker-controlled superuser role, and the third strips superuser from
postgres itself. That is a lockout rather than a smash-and-grab — whoever
ran it intended to still own the database next week. Literal values are normalised to
? by the parser.
Sitting inside that same PostgreSQL stream is the most serious technique attempted against the honeypot on any protocol: — attempts at direct command execution through the database engine.
It is worth being explicit about why this had to be dug out. The honeypot classified each
statement by its opening keyword, and none of these open with COPY — they
open with DROP. The dedicated POSTGRES_COPY event therefore never
fired once in 110 days, and the technique was invisible in the event stream while sitting
complete and verbatim in the query stream the entire time. The figures below are counted from
the statement text instead. They are a subset of the PostgreSQL statement list above rather
than a separate population, so the two totals should not be added together.
Redis produced — events, roughly a four-thousandth of
Telnet's volume, and by some distance the highest quality. An unauthenticated Redis instance
can be turned into arbitrary file write, and the attackers who found this one knew exactly
how: repoint the working directory at a location that something else will execute, set the
dump filename to a file that location expects, disable RDB compression so the dump is
readable as plain text, then SAVE.
The chain table below is the reconstructed command sequence per session, which shows the
technique end to end and shows it being retried against three different targets in one
session: the crontab directory, the root SSH authorized_keys file, and a
loadable module in /tmp. The MODULE LOAD /tmp/exp.so path is the
more modern variant — write a shared object, load it, and get a
system.exec command that runs shell directly.
Nothing was ever written. The honeypot acknowledged every
CONFIG SET and every SAVE with the response a real server gives,
and persisted none of it; the file paths below are statements of intent, not of outcome.
One more Redis curiosity: the pre-authentication channel collected
— lines of traffic that are not Redis at all. HTTP
request headers, TLS ClientHello fragments rendered as mojibake, and the
MGLNDD_ marker that a well-known internet-wide scanner leaves behind. Port
6379 gets sprayed by everything, not only by things that speak the protocol.
Two smaller findings that both say something about motive. The crontab writes are almost
entirely firewall manipulation rather than payload scheduling —
iptables -F flushes every rule, which is a botnet clearing the field before
installing itself and, incidentally, locking out competitors' defensive rules. The tunnel
requests are more explicit still.
The web listener existed to see which vulnerabilities are currently in fashion. The answer
is the same one it has been for years: WordPress. /xmlrpc.php and
/wp-login.php dominate, and the trap categories confirm it — every other
class of bait, from Docker's API socket to Kubernetes to a deliberately named Forgejo
instance, drew a fraction of WordPress's attention. The user agent list is honest about who
is asking: SSH client banners outnumber browsers, and the browser strings that do appear are
mostly a Chrome 95 that stopped existing in 2021.
— distinct sources were seen. Attribution is not attempted and IP addresses are not published: each source carries an opaque sequential label assigned in order of total volume. The distribution is brutally uneven — the single busiest source, —, produced — events in — days and then stopped, which is what a rented botnet segment finishing a contract looks like. The most persistent source returned on — separate days out of 110.
The extremes, including the longest single command the honeypot ever received: a base64
dropper of nearly two thousand characters that writes itself to /tmp/.e one
echo at a time before executing. Decoded, it announces itself as a "VisionC2
loader" that auto-detects architecture and downloads a matching bot binary. It is reproduced
here as captured, defanged only by being inert text on a page.