Add libssh2 CVE-2026-55200 trigger and local RCE scaffold
This commit is contained in:
118
libssh2-cve-2026-55200-poc/poc/libpwn_local_rce_harness.c
Normal file
118
libssh2-cve-2026-55200-poc/poc/libpwn_local_rce_harness.c
Normal file
@@ -0,0 +1,118 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LIBSSH2_PACKET_MAXPAYLOAD 35000u
|
||||
|
||||
struct target_object {
|
||||
unsigned char payload[19];
|
||||
void (*callback)(const char *);
|
||||
char command[320];
|
||||
};
|
||||
|
||||
static void safe_callback(const char *command)
|
||||
{
|
||||
printf("safe_callback command=%s\n", command);
|
||||
}
|
||||
|
||||
static void exec_callback(const char *command)
|
||||
{
|
||||
int rc;
|
||||
|
||||
printf("exec_callback command=%s\n", command);
|
||||
fflush(stdout);
|
||||
rc = system(command);
|
||||
printf("system_rc=%d\n", rc);
|
||||
}
|
||||
|
||||
static int read_exact(unsigned char *buf, size_t len)
|
||||
{
|
||||
size_t got = fread(buf, 1, len, stdin);
|
||||
return got == len ? 0 : -1;
|
||||
}
|
||||
|
||||
static uint32_t load_be32(const unsigned char *buf)
|
||||
{
|
||||
return ((uint32_t)buf[0] << 24) |
|
||||
((uint32_t)buf[1] << 16) |
|
||||
((uint32_t)buf[2] << 8) |
|
||||
(uint32_t)buf[3];
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned char hdr[8];
|
||||
unsigned char *body = NULL;
|
||||
struct target_object *obj = NULL;
|
||||
uint32_t packet_length;
|
||||
uint32_t body_len;
|
||||
unsigned int auth_len = 16;
|
||||
int mac_len = 0;
|
||||
size_t total_num = 4;
|
||||
size_t copy_len;
|
||||
|
||||
obj = (struct target_object *)calloc(1, sizeof(*obj));
|
||||
if(!obj) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
obj->callback = safe_callback;
|
||||
strcpy(obj->command, "not executed");
|
||||
|
||||
printf("LEAK exec_callback=%p callback_offset=%zu command_offset=%zu ptr_size=%zu\n",
|
||||
(void *)exec_callback,
|
||||
offsetof(struct target_object, callback),
|
||||
offsetof(struct target_object, command),
|
||||
sizeof(void *));
|
||||
fflush(stdout);
|
||||
|
||||
if(read_exact(hdr, sizeof(hdr))) {
|
||||
free(obj);
|
||||
return 2;
|
||||
}
|
||||
|
||||
packet_length = load_be32(hdr);
|
||||
body_len = load_be32(hdr + 4);
|
||||
|
||||
if(packet_length < 1u) {
|
||||
free(obj);
|
||||
return 3;
|
||||
}
|
||||
|
||||
total_num += packet_length + (mac_len ? mac_len : 0) + auth_len;
|
||||
|
||||
if(total_num > LIBSSH2_PACKET_MAXPAYLOAD || total_num == 0u) {
|
||||
free(obj);
|
||||
return 4;
|
||||
}
|
||||
|
||||
body = (unsigned char *)malloc(body_len ? body_len : 1);
|
||||
if(!body) {
|
||||
free(obj);
|
||||
return 5;
|
||||
}
|
||||
|
||||
if(read_exact(body, body_len)) {
|
||||
free(body);
|
||||
free(obj);
|
||||
return 6;
|
||||
}
|
||||
|
||||
copy_len = packet_length - 1u;
|
||||
if(copy_len > body_len) {
|
||||
copy_len = body_len;
|
||||
}
|
||||
|
||||
printf("accepted packet_length=0x%08x allocation=%zu copy_len=%zu body_len=%u\n",
|
||||
packet_length, total_num, copy_len, body_len);
|
||||
fflush(stdout);
|
||||
|
||||
memcpy(obj->payload, body, copy_len);
|
||||
obj->callback(obj->command);
|
||||
|
||||
free(body);
|
||||
free(obj);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user