xorl %eax, %eax

Supply chain attacks, 2018 and the future

leave a comment »

It’s been a while since my last post but I thought that there is some value in this topic… Supply chain attacks are nothing new, they have been around for very long time. What is different though, is the rise of this trend this year outside the common nation-state and cyber-espionage world. Here is a high level overview of what implicit trust connections most organizations have today.



And where it gets even more complicated is that every single instance of the above diagram is also another organization. There are some unforgettable supply-chain attacks such as the RSA SecureID in March 2011 which was later used to comprise many organizations, the MeDoc in June 2017, the NSA hardware backdoors, etc. However, almost all of them were part of cyber-espionage operations, typically from nation-states. Some threat actors are more active than others but overall, it was a nation-state game.

What has changed recently is the rise of the supply-chain attacks outside the cyber-espionage world. We see non-enterprise Linux distributions being targeted such as Gentoo and Arch. Widely used open source projects such as npm modules, Docker images from official public registries, cyber-criminals hacking 3rd parties to eventually attack corporations such as Ticketmaster, backdoored WordPress plugins, browser extensions, and many more examples like these just in 2018.

And the question is, are organizations ready for this type of intrusion? Unfortunately, for the majority of the cases the answer is no. Most organizations implicitly trust what is installed on their devices, what libraries their software utilizes, what browser extensions and tools their employees install and use, etc. How can this be fixed?

The answer is not simple or easy. Everyone likes to say “trust but verify” but to what degree? Some might argue that solutions such as Google’s Titan is the way to go, but most organizations don’t have the resources and capacity to implement this. Should they fall back to the built-in TPM? Identifying all suppliers and doing risk assessments? Detecting anomalies and modifications on 3rd party components? All of them are valid options depending on the organization’s threat model.

But the answer starts with a mindset change. Organizations need to realize and accept that this is a real threat and yes, there are technical and non-technical ways to combat it but it requires conscious effort.

Based on my experience and observations I predict that this will become one of the most popular attack vectors in the near future. The reason is simple. Organizations are focusing more and more improving THEIR security but as we all know for thousands of years, security is as strong as its weakest link. You can have the best security in the world but if you include random JavaScript files without any control from 3rd parties, this is what adversaries will use. Remember this Sun Tzu quote from The Art of War?

In war, the way is to avoid what is strong, and strike at what is weak

So, identify your weak points and don’t limit your view to your organization as a standalone instance. Locate where all the components used are coming from and expand your threat model to cover those as well. As Sun Tzu said, you have to know your enemy, but you also have to know yourself.

If you know the enemy and know yourself,
you need not fear the result of a hundred battles.

If you know yourself but not the enemy,
for every victory gained you will also suffer a defeat.

If you know neither the enemy nor yourself,
you will succumb in every battle.

Advertisements

Written by xorl

July 15, 2018 at 14:20

Posted in security

CVE-2018-0739: OpenSSL ASN.1 stack overflow

leave a comment »

This was a vulnerability discovered by Google’s OSS-Fuzz project and it was fixed by Matt Caswell of the OpenSSL development team. The vulnerability affects OpenSSL releases prior to 1.0.2o and 1.1.0h and based on OpenSSL team’s assessment, this cannot be triggered via SSL/TLS but constructed ASN.1 types with support for recursive definitions, such as PKCS7 can be used to trigger it.

/*
 * Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and
 * tag mismatch return -1 to handle OPTIONAL
 */

static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
                               long len, const ASN1_ITEM *it,
                               int tag, int aclass, char opt, ASN1_TLC *ctx)
{
    const ASN1_TEMPLATE *tt, *errtt = NULL;
    const ASN1_EXTERN_FUNCS *ef;
    const ASN1_AUX *aux = it->funcs;
    ASN1_aux_cb *asn1_cb;
    const unsigned char *p = NULL, *q;
    unsigned char oclass;
    char seq_eoc, seq_nolen, cst, isopt;
    long tmplen;
    int i;
    int otag;
    int ret = 0;
    ASN1_VALUE **pchptr;
    if (!pval)
        return 0;
    if (aux && aux->asn1_cb)
        asn1_cb = aux->asn1_cb;
    else
        asn1_cb = 0;

    switch (it->itype) {
   ...
    return 0;
}

What you see above is a snippet of crypto/asn1/tasn_dec.c where the decoding ASN.1 function asn1_item_embed_d2i() is located. Neither this function nor any of its callers had any check for recursive definitions. This means that given a malicious PKCS7 file this decoding routine will keep on trying to decode them until the process will run out of stack space.

To fix this, a new error case was added in crypto/asn1/asn1.h header file named ASN1_R_NESTED_TOO_DEEP. If we have a look at crypto/asn1/asn1_err.c we can see that the new error code is equivalent to the “nested too deep” error message.

     {ERR_REASON(ASN1_R_NESTED_ASN1_STRING), "nested asn1 string"},
+    {ERR_REASON(ASN1_R_NESTED_TOO_DEEP), "nested too deep"},
     {ERR_REASON(ASN1_R_NON_HEX_CHARACTERS), "non hex characters"},

Similarly, a new constant (ASN1_MAX_CONSTRUCTED_NEST) definition was added which is used to define the maximum amount of recursive invocations of asn1_item_embed_d2i() function. You can see the new definition in crypto/asn1/tasn_dec.c.

 #include <openssl/err.h>

/*
 * Constructed types with a recursive definition (such as can be found in PKCS7)
 * could eventually exceed the stack given malicious input with excessive
 * recursion. Therefore we limit the stack depth. This is the maximum number of
 * recursive invocations of asn1_item_embed_d2i().
 */
#define ASN1_MAX_CONSTRUCTED_NEST 30

 static int asn1_check_eoc(const unsigned char **in, long len);

Lastly, the asn1_item_embed_d2i() function itself was modified to have a new integer argument “depth” which is used as a counter for each iteration. You can see how check is performed before entering the switch clause here.

        asn1_cb = 0; 

    if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { 
        ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NESTED_TOO_DEEP);
        goto err;
    }

    switch (it->itype) {
    case ASN1_ITYPE_PRIMITIVE:

Similarly, all calling functions on OpenSSL have been updated to ensure that the new argument is used as intended. The official security advisory describes the above vulnerability like this.

Constructed ASN.1 types with a recursive definition could exceed the stack (CVE-2018-0739)
==========================================================================================

Severity: Moderate

Constructed ASN.1 types with a recursive definition (such as can be found in
PKCS7) could eventually exceed the stack given malicious input with
excessive recursion. This could result in a Denial Of Service attack. There are
no such structures used within SSL/TLS that come from untrusted sources so this
is considered safe.

OpenSSL 1.1.0 users should upgrade to 1.1.0h
OpenSSL 1.0.2 users should upgrade to 1.0.2o
 
This issue was reported to OpenSSL on 4th January 2018 by the OSS-fuzz project.
The fix was developed by Matt Caswell of the OpenSSL development team.

Written by xorl

March 30, 2018 at 19:41

Posted in vulnerabilities

Fox IT Crisis Management training

leave a comment »

A couple of months ago I uploaded the following photo on my Twitter and I got a few questions about it. Short answer: No, I don’t work for Fox IT! That was a trophy for the winning team of a crisis management training delivered by Fox IT that I had attended.



I have no good experience with Fox IT’s technical services (forensics, incident response, etc.), but that might be just me so I don’t want to bias your decisions. In any case, this training was quite fun and useful. It was a full day event where you were split to teams with diverse backgrounds and you were given pieces of information about a security incident which was large enough to require crisis management procedures. The idea was that you had certain amount of time to provide your actions for each stage and then there was an overview of all the teams’ actions along with the recommended ones by Fox IT.

That kind of training can be useful for an organization for a few different reasons. Apart from the apparent knowledge sharing, it acts as a team building event, but more importantly, you can see how aligned your organization’s employees (or colleagues) are on the actions required during a crisis. Obviously, each team will have slightly different results. However, if you see a huge deviation between teams it means that you probably have serious internal issues as your employees (or colleagues) do not have he same mindset for prioritization when dealing with crisis or serious security incidents.

To conclude, although I had no good prior experiences with Fox IT’s technical departments, that training was fun and useful so… Well done guys!

Written by xorl

March 21, 2018 at 22:18

CVE-2018-7273: Linux kernel floppy information leak

leave a comment »

This was a simple information leak vulnerability in the floppy driver that was reported by Brian Belleville to the Linux kernel. Technically, an attacker could trigger show_floppy() calls in the floppy driver to reveal sensitive kernel addresses (such as global variable pointers and function addresses) which can be used to identify the required offsets and consequently, bypass protections like KASLR. You can see drivers/block/floppy.c below.

static void show_floppy(void)
{
    int i;

    pr_info("\n");
    pr_info("floppy driver state\n");
   ...
    if (delayed_work_pending(&fd_timer))
        pr_info("delayed work.function=%p expires=%ld\n",
               fd_timer.work.func,
               fd_timer.timer.expires - jiffies);
    if (delayed_work_pending(&fd_timeout))
        pr_info("timer_function=%p expires=%ld\n",
               fd_timeout.work.func,
               fd_timeout.timer.expires - jiffies);
    pr_info("cont=%p\n", cont);
   ... 
    pr_info("\n");
}

As you can see above, there are a few instances where pr_info() functions are called passing the “%p” format specifier for some function pointers. The issue is that this leaks the address of those function pointers which an attacker can use to calculate the offsets of other, more important pointers, that can later be used to effectively bypass protections like KASLR.

One of the extended format specifiers is the “%fp” which stands for “function pointer” and it ensures that it will not leak a function pointer address which can be used to bypass protections such as KASLR. This is exactly what the patch was to fix this vulnerability.

diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index eae484a..e29d417 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -1819,15 +1819,14 @@ static void show_floppy(void)
    if (work_pending(&floppy_work))
        pr_info("floppy_work.func=%pf\n", floppy_work.func);
    if (delayed_work_pending(&fd_timer))
-       pr_info("delayed work.function=%p expires=%ld\n",
+       pr_info("delayed work.function=%pf expires=%ld\n",
               fd_timer.work.func,
               fd_timer.timer.expires - jiffies);
    if (delayed_work_pending(&fd_timeout))
-       pr_info("timer_function=%p expires=%ld\n",
+       pr_info("timer_function=%pf expires=%ld\n",
               fd_timeout.work.func,
               fd_timeout.timer.expires - jiffies);

-   pr_info("cont=%p\n", cont);
    pr_info("current_req=%p\n", current_req);
    pr_info("command_status=%d\n", command_status);
    pr_info("\n");

Written by xorl

March 18, 2018 at 16:54

Posted in linux

The “Clipper” malware type

leave a comment »

With the increasing popularity of crypto-currencies we see more and more attacks focusing in this area. Some popular examples are coin miners delivered via botnets, JavaScript based miners spread via ad networks, etc. A recent addition to this list is the, so called, “Clipper” malware type.

Let’s start with the definition. Clipper is a type of software that looks at the operating system’s data buffer (commonly referred to as clipboard) for anything that resembles a crypto-currency address. If such an address is identified, it will replace it with one owned by the malware operator. I am adding a simple diagram I created to describe the attack below.



At the time of this writing, the three most prominent such malware are “CryptoShuffler”, “ComboJack” and “Project Evrial”. For the former two, Unit 42 of Palo Alto Networks recently published a blog post. “Project Evrial” started in December 2017 by threat actor “Qutra” based on “CryptoShuffler” and it was later (in January 2018) updated by threat actor “emotion” as well as “Qutra”. Both versions are very popular in underground Russian-speaking communities and their price is around $30. You can see one of the latest English advertisements of this malware below.



Based on the above in combination with the continuously growing popularity of crypto-currencies we can assume that more of these type of new malware approaches will be implemented in the future targeting specifically crypto-currencies. On the other hand, it is important to remember that the same techniques can be easily adjusted for other types of attacks and malware.

Written by xorl

March 18, 2018 at 14:25

Posted in malware

Book: Practical Malware Analysis

leave a comment »

I had this book for quite a few years and never read it cover to cover. Recently I decided to do this and this is my review. It is still a very relevant resource if you are entering the world of malware analysis and it is definitely worth reading.



The book is written by two experts in the field, Michael Sikorski and Andrew Honig. Both very experienced malware analysts and reverse engineers. It is an 800 pages long book from 2012 that starts from zero, and moves up to advanced malware analysis and reverse engineering. No Starch Press provides a full listing of contents, reviews and sample chapters online if you want to check it out.

Basically, the book is from 2012 but the vast majority of its content is applicable today too. So far it is the most complete book that I have read on the topic of malware analysis. If you want to enter this world then I definitely recommend it as a good resource. However, keep in mind that it is a book from 2012, there will definitely be a few thing that are not as common today and many newer techniques that are not included in the book. It is also worth noting that it’s written in the form of lecturing book with exercises and examples at the end of each chapter. Overall, very nice book. :)

Written by xorl

March 18, 2018 at 13:33

Posted in books

CVE-2017-12762: Linux kernel isdn_net IOCTL memory corruption

leave a comment »

Recently I came across this report which is kind of sad since this was one nice and funny 0day that had been around for very long time. However, in this post I will only talk about the vulnerability since no exploit has been publicly disclosed yet. The vulnerability is in I4L (ISDN 4 Linux) and starts with the IIOCNETASL (Create slave interface) IOCTL command which is in drivers/isdn/i4l/isdn_common.c as shown below.

static int
isdn_ioctl(struct file *file, uint cmd, ulong arg)
{
   ...
		switch (cmd) {
   ...

		case IIOCNETASL:
			/* Add a slave to a network-interface */
			if (arg) {
				if (copy_from_user(bname, argp, sizeof(bname) - 1))
					return -EFAULT;
			} else
				return -EINVAL;
			ret = mutex_lock_interruptible(&dev->mtx);
			if (ret) return ret;
			if ((s = isdn_net_newslave(bname))) {
				if (copy_to_user(argp, s, strlen(s) + 1)) {
   ...
}

Basically this is accessible via /dev/isdnctrl ISDN control device and ioctl(2) system call using IIOCNETASL command. As you can see in the above snippet, it uses copy_from_user() to get the user controlled buffer and store it in “bname” which is a stack allocated buffer that you can see how it was defined below.

	union iocpar {
		char name[10];
		char bname[22];
		isdn_ioctl_struct iocts;
		isdn_net_ioctl_phone phone;
		isdn_net_ioctl_cfg cfg;
	} iocpar;
	void __user *argp = (void __user *)arg;

#define name  iocpar.name
#define bname iocpar.bname

Later on we see that the user derived “bname” buffer is passed to isdn_net_newslave() which is a function defined in drivers/isdn/i4l/isdn_net.c. Here is this function.

char *
isdn_net_newslave(char *parm)
{
	char *p = strchr(parm, ',');
	isdn_net_dev *n;
	char newname[10];

	if (p) {
		/* Slave-Name MUST not be empty */
		if (!strlen(p + 1))
			return NULL;
		strcpy(newname, p + 1);
		*p = 0;
   ...
}

Here we can see that the only check on the user derived “p” pointer is that it is not empty. Then it uses strcpy() to copy the contents of it to “newname” which is a stack buffer with size of 10 Bytes. This is like a 90s textbook stack buffer overflow. In August 2017 it was reported and patched by Annie Cherkaev by replacing strcpy() with strscpy() which ensures that the copy will not exceed “newname” buffer’s limits. The patch is the following.

--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1379,6 +1379,7 @@  isdn_ioctl(struct file *file, uint cmd,
 			if (arg) {
 				if (copy_from_user(bname, argp, sizeof(bname) - 1))
 					return -EFAULT;
+				bname[sizeof(bname)-1] = 0;
 			} else
 				return -EINVAL;
 			ret = mutex_lock_interruptible(&dev->mtx);
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -2611,10 +2611,9 @@  isdn_net_newslave(char *parm)
 	char newname[10];
 
 	if (p) {
-		/* Slave-Name MUST not be empty */
-		if (!strlen(p + 1))
+		/* Slave-Name MUST not be empty or overflow 'newname' */
+		if (strscpy(newname, p + 1, sizeof(newname)) <= 0)
 			return NULL;
-		strcpy(newname, p + 1);
 		*p = 0;
 		/* Master must already exist */
 		if (!(n = isdn_net_findif(parm)))

This is kind of sad, not because this is a useful 0day but because it had been around for years. Me and some friends had this 0day literally from 2007 so it is kind of sad seeing it dying quietly like this. In any case, I will not go into how to exploit it but it is a nice trivial vulnerability if you want to play around and practice your Linux kernel stack memory corruption exploitation techniques.

Written by xorl

February 24, 2018 at 02:37

Posted in vulnerabilities