[OpenWrt-Devel] CVE-2019-15513 analysis

Hauke Mehrtens hauke at hauke-m.de
Fri Nov 1 09:23:19 EDT 2019


Hi,

At the prpl Summit 2019 I saw a slide with 4 CVEs which are filled
against OpenWrt and there was one listed I was not aware of at that
time, CVE-2019-15513.

According to the CVE details page it was filled against OpenWrt on
23.8.2019 and OpenWrt was not informed before or after this was filled
against OpenWrt, we only saw this by luck.
https://www.cvedetails.com/cve/CVE-2019-15513/

The details are "described" in this pdf file which is partly in Mandarin:
https://github.com/TeamSeri0us/pocs/blob/master/iot/morouter/motorola%E8%B7%AF%E7%94%B1%E5%99%A8%E6%96%87%E4%BB%B6%E8%A7%A3%E9%94%81%E6%BC%8F%E6%B4%9E.pdf
This paper only looks at the disassembled binary even when the source is
open source.
Petr (ynezz) tried to reproduce this, but was not able to do so with a
recent OpenWrt. Later we found that this problem was fixed in OpenWrt
15.05.1 and later more than 4 years ago.

The problem was already reported here, but not as a security problem:
https://github.com/openwrt/packages/issues/1231

This problem was fixed by Yousong in this commits over 4 years ago:
https://git.openwrt.org/?p=project/uci.git;a=commitdiff;h=19e29ffc15dbd958e8e6a648ee0982c68353516f

This commit allows longer lines:
https://git.openwrt.org/?p=project/uci.git;a=commitdiff;h=4b52bdbdbec3c84afeab5c3167e69f7c6012b2f3


The problem was that uci_open_stream() opens the given filename and also
locks it with flock() so that other processes can not use it. In this
case the lock on the file is not released which causes a dead lock in
uci and something hangs, no code executing or something similar
possible, just one process hangs. This can normally only be called by root.

UCI makes use of setjmp() and longjmp() for error handling. When an
error occurs it jumps back to the save point. This is encapsulated in
UCI_TRAP_SAVE() and UCI_THROW(). longjmp() saves all the registers, so
variables which are stored in memory are not restored, but variables
stored in registers are restored to their old values.

When uci_getln() is called with a string of more than 4096 bytes it runs
into an error case and calls UCI_THROW() which jumps back to the last
save point, in this case to uci_load_delta_file(). In this description
it gets called in this way:
uci_load_delta_file() -> uci_parse_delta() -> uci_getln()

uci_load_delta_file() looked liked this:
---------------------------------------------------------------
/* returns the number of changes that were successfully parsed */
static int uci_load_delta_file(struct uci_context *ctx, struct
uci_package *p, char *filename, FILE **f, bool flush)
{
	FILE *stream = NULL;
	int changes = 0;

	UCI_TRAP_SAVE(ctx, done);
	stream = uci_open_stream(ctx, filename, NULL, SEEK_SET, flush, false);
	if (p)
		changes = uci_parse_delta(ctx, stream, p);
	UCI_TRAP_RESTORE(ctx);
done:
	if (f)
		*f = stream;
	else if (stream)
		uci_close_stream(stream);
	return changes;
}
---------------------------------------------------------------
https://git.openwrt.org/?p=project/uci.git;a=blob;f=delta.c;h=459d2c7ddfd5d4443c24c02a76952d40319bb871;hb=556215152a216c179fe2ca7db9b1de7036ceda60#l289

When uci_parse_delta() calls UCI_THROW() it jumps to done. The problem
is that stream is stored in a register and not on the stack because the
compiler thinks this is ok. Then stream will be restored to the original
value which is NULL and we loose the reference to the original stream
file pointer. uci_close_stream() will not be called and the file pointer
is not unlocked and also not closed.


This problem was fixed in OpenWrt 15.05.1.
The CVE says it does not need authentication, as far as I understand
this root permissions are needed to exploit this problem, it could also
be possible over Luci.

It could be that these Motorola CX2L MWR04L and MWR03 devices where this
problem was found use UCI in a different way in their vendor FW which
forked OpenWrt, but I do not have these devices, the source code or the
binaries of these devices.

If you find a security problem in OpenWrt please get in contact with us
at contact at openwrt.org preferable before publishing it, but at least
after you published it. I do not like it, when a CVE is just filled
without informing us. Do not assume that some random vendor in which
firmware you found this problem reports the problem back to us, normally
they only fork OpenWrt and do not care about upstream OpenWrt. If you
find a problem in OpenWrt please talk to OpenWrt!

If you see a CVE against OpenWrt and there is no communication on the
normal OpenWrt mailings about it, please ask on the public mailling list
if someone knows about this, this is already the 2. CVE filled against
OpenWrt where we did not got informed at all.

Hauke

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/openwrt-devel/attachments/20191101/f2cae799/attachment.sig>
-------------- next part --------------
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel


More information about the openwrt-devel mailing list