A Security Vulnerability in the KmsdBot Botnet

Security researchers found a software bug in the KmsdBot cryptomining botnet:

With no error-checking built in, sending KmsdBot a malformed command­—like its controllers did one day while Akamai was watching­—created a panic crash with an “index out of range” error. Because there’s no persistence, the bot stays down, and malicious agents would need to reinfect a machine and rebuild the bot’s functions. It is, as Akamai notes, “a nice story” and “a strong example of the fickle nature of technology.”

Posted on December 15, 2022 at 7:10 AM10 Comments


echo December 15, 2022 10:54 AM

Humans tend to be full of it hence Akamai’s note on the story and fickle nature of technology which are really two completely separate branches of philosophy. Humans also produce said software and technology. So we have a dialectic between the amateur and the incompetent. What fun!

The bot did what the bot does. It can do nothing else although some wiseguy could come along and comment that the map is not the territory and we’d have to endure an hour long speech on how mathematics and physics and reality are not the same thing.

I’m in a mood today aren’t I?

noop December 15, 2022 3:06 PM

Really cool research by the folks at Akamai. It’s rare we get to see a botnet fall flat on its face.

Clive Robinson December 15, 2022 3:54 PM

@ ALL,

Re : Development 101

You read,

“With no error-checking built in”

And think “For real!!!?”

As a rough rule of thumb professional educators tend in the early days of a neophyte’s divinations should be centered around

1, Exception handeling
2, Error checking
3, Error correction

Failure to do so renders the future progres of their work problematic if not void.

However, when “Example Code” goes up on one of those StackExchange type sites, it’s argued that “brevity is best” especially as “the developer should know…”.

Turns out a lot of “Example Code” becomes inadequately tested “production code”, for reasons a lot are aware of…

I guess it’s nice to know the dog craps[1] on the grass both sides of the developer fence.

[1] At one time being a dog poop collector was a proffession of sorts. Turns out “white poop” was nore valuable than other colours of dog poop… So hats are not the only occupational marker where white is prefered to black…

Ted December 15, 2022 4:01 PM

Here’s the command that crashed the botnet:

!bigdata http://www.bitcoin.com443 / 30 3 3 100

Note there’s no space between the web address and the port number. So this mis-formed C2 command did not have the correct number of arguments.

More crucially these bots did not have error handling code or persistence. So a simple typo by the botnet operators emerged as a glorious self-induced botnet knock out.

Frank Wilhoit December 15, 2022 6:15 PM

What this shows is that even in an environment such as this, where one might expect incentives for competence, those incentives are not effective; and if not here, then where?

Phillip December 16, 2022 1:48 AM

Whose panic? I am no “Rustacean” or misanthrope, though any Rust language aficionado might even use the “panic!” macro.

My point? Presumably, the tech is so smooth, one can only panic when ordered to do something “unsafe.”

Arguably, this is humor. However, even deliberate panic is etymologically confusing, lately.

Estelle December 16, 2022 3:54 PM

@Clive Robinson,

As a rough rule of thumb professional educators tend in the early days of a neophyte’s divinations should be centered around

1, Exception handeling
2, Error checking
3, Error correction

More important than all of these, I’d say, is to make people think about the ways things could go wrong. It’s an important part of engineering, but many of the people calling themselves software “engineers” have never been near an engineering class. If you’re splitting a string into words, it’s not an “error” (per point 2) to get a string without a space. Accessing a non-existent array index, in some languages, might be an error but not return or raise an error or exception. C functions such as strtol() are notoriously difficult to use correctly (set errno=0 first, check for unexpected prefixes, use ‘endptr’ to check that at least one digit was read and there were no unexpected suffixes; also pay attention to the base and the locale, and, if casting the result to a potentially smaller type—because there’s no strtoi()—check for out-of-range values first; and if using the floating-point variants, keep in mind you might get a result that’s not equal to, greater than, or less than the boundary you’re checking against).

Functions that return error codes, or for which the language requires certain exceptions be handled, should be fairly obvious (though people still get it wrong). But then there’s stuff like fwrite(), which is documented to return a short count on error… if the error’s detected, which it might not be till fflush(); or maybe not, because a kernel can cache the data and not indicate failure till fdatasync() or close() (the latter having, till recently, been underspecified by POSIX and therefore impossible to use correctly in multi-threaded code, which is already difficult to get correct; for a brief time, even errno couldn’t be safely used in multi-threaded code). mmap() can make things even more difficult, but if one’s thinking about it, it should be obvious that errors can occur, there must be some unusual mechanism for indicating them, and that such indications could be deferred when writing data. Somehow, a lot of programs get written with no handling for these things.

Clive Robinson December 16, 2022 6:34 PM

@ Estelle,

“More important than all of these, I’d say, is to make people think about the ways things could go wrong. It’s an important part of engineering,”

It’s something I’m sadly cursed with… I can not look at any system these days without subconciously thinking “how does it fail?, what are it’s weaknesses?, how could it be exploited?, and so on”

Our host @Bruce has in the past called it “thinking hinky”

And when you are good at it, it’s like being a primate on the ground your subconcious pattern recognition has sent you up the tree before your conscious mind sees the tigers stripe.

It’s a skill as an engineer you develop in two ways,

1, Testing techniques.
2, Pulling components game.

I think that the ability to test and repair a non functional system is more important than being able to design a functional system.

Because you learn from the first, but only show from the second.

The Pulling components game, or changing their value on paper and analysing what you should see is another good way to get a feel for whats close to the edge or not. You can learn a lot. Like which order two different op-amps should be put in to ensure circuit stability.

Engineers like “oak trees” and “rats teeth” have to grow continuously, trees if out on their own can be left alone, but if a rat does not gnaw away…

I can see that you’ve had the misfortune to be told to “drain the swamp” without being told “there be alligators there”… Not a nice place to be pit, but I’ve a few scars from that myself.

As for “POSIX” it often reminds me of the plot from the second “original” StarTrek film “Wrath of Khan” where the limit is not the intelligence behind the eyes, but the lack of dimensional thinking in front of the eyes[1].

Thinking about threads needs that extra dimensionality and POSIX never appeared to grasp that concept even in Real Time Extensions (for which a barge pole comes in handy). Personally for RT work I try to avoid “big system thinking” and go down a bespoke microcontroller route where possible. I’ve written so many BIOS/RTOS in even assembler I can do it almost in my sleep, but it’s not a “magic solution” by any means. Because you have to be careful you are solving the time issues as locally as possible, rather than just moving them down stream where they cause comms contention issues or worse.

With POSIX you know their thinking was always “move the checking to the left and the problem to the right” which might be fine for single threaded sequential systems with no time criticality, or reliability / availability issues, but not for most other things the modern world is more full of.

[1] My first real introduction to POSIX was writing a “terminal emulator”. Something that POSIX was really bad at was bi-directional behaviour. It assumed everything would be uni-directional from left (input) to right (output) thus “in channel” flow control was a nightmare to do in the POSIX way of the world.

lurker December 16, 2022 10:58 PM

@Clive Robinson
re, test, repair, or design

When the test shows that to repair will require changes to the design,
life gets tedious …

Clive Robinson December 17, 2022 9:31 PM

@ lurker,

“When the test shows that to repair will require changes to the design”

Is inevitable with “breaking new ground” but doing that is rare very rare in “engineering”. Because the cost any way you want to measure it is so high. Think a bridge collapsing because the bolts were insufficient for the load, or continuous flexing (metal fatigue).

For some reason whilst we have “care” with the engineering of “physical objects”, the lesson / message does not appear to have got through to the constructors of “information objects”.

Maybe because the costs of information objects breaking is all to often treated as insignificant. Or maybe it’s a “work creation scheme” of some kind.

Either way as you note,

“life gets tedious …”

Doesn’t it just…

But hey “Another day another dollar” such is the joy of “botch-jobs” that entire “consulting” empires like Anderson Consulting have been built on the idea of,

“Leave a job half done, then you get to come back for double the money.”…

“Ka-ching” or what ever other noise a modern cash register makes when stuffed full of profit these days (if any)…

Leave a comment


Allowed HTML <a href="URL"> • <em> <cite> <i> • <strong> <b> • <sub> <sup> • <ul> <ol> <li> • <blockquote> <pre> Markdown Extra syntax via https://michelf.ca/projects/php-markdown/extra/

Sidebar photo of Bruce Schneier by Joe MacInnis.