Unpatched routers bad, doubly unpatched routers worse – much, much worse!

Back in August we wrote about a security bugfix for Mikrotik routers that was reverse engineered and turned into a working exploit.

Indeed, patches that fix security vulnerabilities often end up giving away enough about the vulnerability that both good guys and bad guys alike can weaponise it from first principles – all without having to figure out the vulnerability in the first place.

In the August 2018 case, dubbed CVE-2018-14847, a crook could trick an unpatched Microtik router into coughing up the contents of any file on the device, including the password file.

Worse still, the password file included plaintext passwords, with no salting, hashing or stretching, meaning that a security bypass bug could be parlayed into a credential compromise.

Unlike a dreaded “zero-day” exploit, however, which comes out before any patch and thus gives zero days during which you could have been ahead of the game, an exploit that only comes out because of a patch is, at least in theory, easily avoided.

If you’d patched your Mikrotik router promptly, the what-were-they-thinking proof-of-concept exploit created by researchers known as @n0p and @yalpanian would have been harmless against your device.

💡 LEARN MORE: How to store your users’ passwords safely ►

The perils of late patching

What we didn’t know back then was that security researchers at Tenable had responsibly disclosed another bunch of Mikrotik router bugs at about the same time.

These bugs were serious – indeed, one of them allows a attacker to run any program of their choosing, just by making a web request to the router.

This sort of hole is known, for rather obvious reasons, as an RCE, short for Remote Code Execution.

Tenable’s bugs, however, were what’s known as “authenticated vulnerabilities”, meaning that you had to be logged in first in order to be able to exploit them.

Security holes that require pre-authentication may seem harmless at first sight – after all, if you already have a username and password, or some other access token, that gives you access to a system…

…well, you’re already in, so it sounds as though breaking in again can be dismissed as an irrelevancy.

But even vulnerabilities open only to authenticated users can be very serious, because:

  • They can often be abused for elevation of privilege, turning low-powered, read-only or guest accounts into superuser, all-powerful admin accounts.
  • They can often be chained together with with unauthenticated vulnerabilities to get that low-powered, read-only or guest access in the first place.

The good news is that Mikrotik has already patched Tenable’s now-disclosed bugs, dubbed CVE-2018-1156, -1157, -1158 and -1159.

Make sure you have the latest Mikrotik firmware updates, which are: 6.40.9, 6.42.7 or 6.43, depending on whether you’re using the current, previous or pre-previous version.

If you’re a Mikrotik user, skipping the latest patch leaves you at risk, but if you still haven’t applied the previous patch, you’re in double trouble.

With both patches missing, you’re open to an unauthenticated password disclosure bug that could then be chained with the newer authenticated remote code execution bug.

In other words, instead of anyone being able to get some access, or some people being able to get full access, anyone could get full access by pivoting from CVE-2018-14847 to CVE-2018-1156, the RCE flaw.

A reminder to programmers

By the way, the RCE hole found by Tenable involved the misuse of a C function called sprintf(), pronounced ESS-PRINT-EFF and short for “Formatted PRINT into a String”.

The word string is jargon for a memory buffer used for storing text such as prompts, log messages, usernames, error descriptions and so on.

The problem with sprintf() is that it assumes there is enough memory available in the memory buffer you’re writing into for the message that the function will create.

Consider a fragment of C like this:

   char *name;     // A memory buffer already containing a name.,  e.g. 'DUCK'
   char buff[16];  // Some space reserved for the message with the name in it

   sprintf(buff, "Hello %s", name);

This takes the text string referred to by the variable name and inserts it at the point denoted by the special marker characters %s in the second string. (Other markers such as %d and %f can be used to get neatly laid-out integer Digits and Floating point numbers, also known as decimals, respectively.)

You can see the problem here – there are only 16 characters allocated for buff, so anyone who puts in a name that’s longer than nine characters will overflow the memory buffer.

Count five characters for Hello, plus a space, plus nine characters for name, plus the zero byte (the ASCII NUL character) that C automatically adds to denote the end of a string, and you have 16 bytes. That’s already enough to fill up the 16-byte buffer, so any more than nine characters in the variable name will provoke an overflow.

If you’re a C programmer, you shouldn’t be using sprintf() any more – only use string functions that allow you to specify a maximum number of bytes to copy.

These functions typically have an -n- in their name somewhere, short for “copy at most N bytes even if there are characters left uncopied or unprinted”, or an -l- to mean “Limit the Length of the resulting string.”

For example:

   char *name;     // A memory buffer already containing a name.,  e.g. 'DUCK'
   char buff[16];  // Some space reserved for the message with the name in it

   snprintf(buff, sizeof buff, "Hello %s",name)

The C operator sizeof does what you might expect, and automatically works out how much memory space is available in buff.

The snprintf() function above copies at most (sizeof buff)-1 bytes into buff, always keeping one byte at the end spare, where it puts the NUL character that ends off the string, so you never end up with unterminated text. In the special case that the size given to snprintf() is zero, no bytes at all are written into buff – the function simply does nothing.

As an aside, even though you can control the amount of data copied, and thereby prevent buffer overflows, just using “string counting” functions such as snprintf() is not security enough.

As the Unix manual pages put it:

It may be a security concern for a string to be truncated [… T]he truncated string will not be as long as the original, [so] it may refer to a completely different resource and usage of the truncated resource could result in very incorrect behaviour.

Blindly relying on a filename from which the extension has been chopped off, for example, could have all sorts of unintended consequences.

Always check for incorrect or incomplete string operations as well as doing your best to prevent buffer overflows.

There’s not much point in suppressing one bug if, by doing so, you introduce another.

What to do?

  • Patch early, patch often. One missed patch is bad; two missed patches are worse, and may end up turning two limited-risk vulnerabilities into a combined security hole that offers crooks an all-powerful, no-holds-barred exploit.
  • Don’t use known-bad C functions in your code. Most C compilers will warn you about dangerous and deprecated functions when you build your program – heed their advice.

Articles You May Like

New ‘HrServ.dll’ Web Shell Detected in APT Attack Targeting Afghan Government
Okta: Support system breach affected all customers
Prosus slashes valuation of India’s Byju’s below $3 billion
Telekopye’s tricks of the trade – Week in security with Tony Anscombe
Experts Uncover Passive Method to Extract Private RSA Keys from SSH Connections

Leave a Reply

Your email address will not be published. Required fields are marked *