{"id":337,"date":"2024-09-09T16:06:17","date_gmt":"2024-09-09T22:06:17","guid":{"rendered":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/?p=337"},"modified":"2024-09-09T16:06:23","modified_gmt":"2024-09-09T22:06:23","slug":"regresshion-remote-code-execution-in-openssh","status":"publish","type":"post","link":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/2024\/09\/09\/regresshion-remote-code-execution-in-openssh\/","title":{"rendered":"RegreSSHion: Remote Code Execution in OpenSSH"},"content":{"rendered":"\n<p class=\"has-small-font-size\">On July 1st, 2024, the security firm Qualys published their discovery of a vulnerability within the OpenSSH daemon that allowed for unauthenticated, network-exploitable, remote code execution [1]. As a ubiquitous means of secure access to remote servers, the vulnerability allowed for attackers to gain unfettered, superuser access to a majority of servers running Linux, which makes up of 60% of all servers [2]. With a severity of 8.1 out of 10 [3], RegreSSHion was one of the most significant vulnerabilities of 2024, but who was affected, how did it work, and how severe was it in practice?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">OpenSSH<\/h2>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-src=\"https:\/\/www.openssh.com\/images\/openssh.gif\" alt=\"\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" class=\"lazyload\" \/><\/figure>\n<\/div>\n\n\n<p class=\"has-small-font-size\">OpenSSH is an implementation of the SSH protocol, allowing for users to securely connect to a remote environment. Unlike Telnet, communication in SSH is done over an encrypted channel, mediated through a public-private key scheme. Authentication can be done either through providing a username and password of a Unix User on the server, or by sharing the public component of a trusted key (Usually via the <code>ssh-add<\/code> command). Users can then copy files via <code>scp<\/code>, setup a file share via <code>sftp<\/code>, or access a remote shell environment to run commands on the server via <code>ssh<\/code> [8].<\/p>\n\n\n\n<p class=\"has-small-font-size\">With server management dominated by cloud platforms like AWS and Azure, OpenSSH is a pivotal component to allow server administrators access to their remote servers, and OpenSSH is the default implementation for Linux systems and OpenBSD.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Who is Affected?<\/h2>\n\n\n\n<p class=\"has-small-font-size\">The name of the vulnerability: <em>RegreSSHion<\/em> is in reference to the fact that this vulnerability is actually a regression: the exploit was previous discovered, patched, and then reintroduced in later versions. Therefore, all versions of OpenSSH before version 4.4p1, and those versions after 8.5p1 and before 9.8p1 are considered vulnerable [4].<\/p>\n\n\n\n<p class=\"has-small-font-size\">While OpenSSH is available for most major Operating System platforms, the RegreSSHion vulnerability targets a weakness specific to the <code>glibc<\/code> implementation of the C language and standard library: narrowing down affected systems exclusively to Linux.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Does it Work?<\/h2>\n\n\n\n<p class=\"has-small-font-size\">To understand how RegreSSHion was able to achieve remote code execution, we must first understand the concepts that were exploited: <em>Process Signals<\/em>, and <em>Dynamic Memory Allocation<\/em>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Process Signals<\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-src=\"https:\/\/devopedia.org\/images\/article\/197\/5091.1562685662.png\" alt=\"\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" class=\"lazyload\" \/><\/figure>\n\n\n\n<p class=\"has-small-font-size\">In Unix based systems, the <em>Signal<\/em> is an essential aspect of IPC, or inter-process communication. It allows for a process, such as a task manager, to issue a signal to another process, such as instructing the process to die [5]. Signals are very similar to the concept of <em>Exceptions<\/em> or <em>Interrupts<\/em>, where the logical flow of a program is interrupted, moved to a special region of code known as the <em>Interrupt Handler<\/em>, and handles the interrupt before returning to where execution branched off [6].<\/p>\n\n\n\n<p class=\"has-small-font-size\">In higher level languages, such as C++ or Python, exceptions are managed by the language, but when dealing with raw Assembly, care needs to be taken to ensure that the state of the CPU is <em>identical<\/em> to that before the Interrupt Handler was invoked. Because Interrupts and Exceptions can occur at any time, a program can be interrupted in the middle of an important operation that relies on values being in certain locations, values that an Interrupt Handler may change.<\/p>\n\n\n\n<p class=\"has-small-font-size\">Signals, like Exceptions and Interrupts, cause a branch in the normal flow of program execution, but rather than being handled on the CPU level, are instead handled by the Kernel [5]. While some Signals, particularly <code>SIGKILL<\/code> (Forcefully kills the program), cannot be caught or ignored, most Signals allow for the application to handle the request through a <em>Signal Handler<\/em>. For example, consider a program that writes data to files, where an interruption of that process could lead to corruption. If a user wants to stop the process prematurely by sending <code>SIGINT<\/code> (<code>Ctrl+C<\/code> in the terminal), the process will want to catch that signal, and then close the file gracefully. By using the <code>signal<\/code> function, we can trivially set a function that should be run when a process receives a signal:<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:12px\"><code>#include &lt;signal.h&gt;\n#include &lt;iostream&gt;\n\nstatic void cleanup(int signo) {\n\tstd::cout &lt;&lt; \"Cleanup!\" &lt;&lt; std::endl;\n\t\/\/ Handle any cleanup related steps.\n\texit(1);\n}\n\nint main() {\n\t\/\/ Set cleanup to be the SIGIINT Signal Handler.\n\tsignal(SIGINT, cleanup);\n\t\/\/ Do work.\n}<\/code><\/pre>\n\n\n\n<p class=\"has-small-font-size\">However, a <strong><em>very important<\/em><\/strong> thing to understand about Signal Handlers is that because they branch execution at any point, a Signal Handler must act like an Interrupt Handler in that it must ensure that, when the signal handler resumes normal execution, that state must not be modified. Consider a rather trivial example:<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:12px\"><code>#include &lt;signal.h&gt;  \n#include &lt;iostream&gt;  \n#include &lt;chrono&gt;  \n#include &lt;thread&gt;  \n  \nint a = 2;  \n  \nstatic void handle(int signo) {  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a = 3;  \n}  \n  \nint main() {  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/ Set handle to be the SIGIINT Signal Handler.  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGINT, handle);  \n  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/ Do work  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::this_thread::sleep_for(std::chrono::seconds(5));  \n  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout &lt;&lt; a * a &lt;&lt; std::endl;  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;  \n}\n<\/code><\/pre>\n\n\n\n<p class=\"has-small-font-size\">If we do not send an signal interrupt, we get the expected output: 4, but if we <em>do<\/em> send the <code>SIGINT<\/code> signal, then we return 9. The key takeaway is that <strong>Signal Handlers must take extreme precaution to ensure they do not modify the state in a way the returning function may not expect.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Dynamic Memory Allocation<\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"956\" height=\"772\" data-src=\"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-content\/uploads\/sites\/119\/2024\/09\/image.jpeg\" alt=\"\" class=\"wp-image-344 lazyload\" data-srcset=\"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-content\/uploads\/sites\/119\/2024\/09\/image.jpeg 956w, https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-content\/uploads\/sites\/119\/2024\/09\/image-300x242.jpeg 300w, https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-content\/uploads\/sites\/119\/2024\/09\/image-768x620.jpeg 768w\" data-sizes=\"(max-width: 956px) 100vw, 956px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 956px; --smush-placeholder-aspect-ratio: 956\/772;\" \/><\/figure>\n\n\n\n<p class=\"has-small-font-size\">A key concept of both Assembly and C\/C++ is the two core data structures of the <em>Stack<\/em>, and the <em>Heap<\/em>. The <em>Stack<\/em> is a logically structured set of values, which typically \u201cgrows\u201d from the top of an application\u2019s allocated memory downward. The Stack follows a Last-In-First-Out scheme, as opposed to a First-In-First-Out structure like a queue. C\/C++ compilers use the Stack to store local variables [9].<\/p>\n\n\n\n<p class=\"has-small-font-size\">The <em>Heap<\/em> is an unorganized set of memory used for <em>dynamically allocated data<\/em> [9]. Specific functions are needed to manage this memory, to which the C language mandates the class of memory allocators <code>malloc<\/code>, <code>calloc<\/code>, <code>realloc<\/code>, and the deallocator <code>free<\/code>. To effectively manage this Heap space, the allocators are complicated functions (The <code>glibc<\/code> implementation of <code>malloc<\/code> is over 6000 lines of code [7]), and there are numerous ways to misuse them, causing issues like Double Frees, Segmentation Faults, and Memory Leaks. The follow example shows values being initialized on both the Stack and Heap:<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:12px\"><code>#include &lt;string&gt;  \n#include &lt;stdlib.h&gt;  \n  \nint main() {  \n       \/\/ Allocated on the stack.  \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int a = 2;\n\n       \/\/ Allocated on the stack.  \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0char str&#091;] = \"Hello, World!\"; \n\n       \/\/ Out-Of-Bounds indexing will cause the program to crash due to Stack-Smashing Detection.  \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0str&#091;99] = '.';\n\n       \/\/ The std::string manages its own memory on the heap.  \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0std::string str2 = \"Hello, again!\";\n\n        \/\/ Allocate 4 integers on the heap.  \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int* int_array = reinterpret_cast&lt;int*&gt;(calloc(4, sizeof(int)));\n\n       \/\/ Failure to check for a successful allocation will dereference a null pointer. \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (int_array == NULL) return -1; \n\n       \/\/ No error will occur, but Valgrind will report an Invalid-Read as an out-of-bounds index. \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int_array&#091;99] = 1; \n\n       \/\/ Failure to manually free the allocated memory will cause a Memory Leak. \u00a0  \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0free(int_array);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return 0;  \n}\n<\/code><\/pre>\n\n\n\n<p class=\"has-small-font-size\">Importantly, and the takeaway of this section is that: <strong>Dynamic Allocation Functions must be handled with caution. They are not thread safe, and should not be used in a Signal Handler because interrupting the allocation process can easily corrupt the Heap.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Exploit<\/h3>\n\n\n\n<p class=\"has-small-font-size\">Now that we understand Signals and Dynamically Allocated Memory, we can dive into the exploit itself. OpenSSH has a function to timeout a connection when a user takes excessively long to provide credentials. This function is exposed in a <code>LoginGraceTime<\/code> parameter, which defaults to 120 seconds [10]. In order to handle this timeout period, OpenSSH uses the <code>SIGALRM<\/code> to wake the process up after the specified period, which would then trigger its <code>SIGALRM<\/code> handler [4]. This is not out of the ordinary for applications; however, OpenSSH logs this timeout using the <code>syslog()<\/code> function, which in the <code>glibc<\/code> implementation in not safe for use in a signal handler. If <code>syslog()<\/code> is being called for the first time, then it invokes the <code>__localtime64_r()<\/code> function, which calls <code>malloc()<\/code>. Insidiously, the <code>syslog()<\/code> call itself is buried in a call chain, from the <code>grace_alarm_handler<\/code> function to the <code>sigdie<\/code> macro to the <code>sshsigdie<\/code> function to the <code>sshlogv<\/code> function before finally arriving at <code>do_log()<\/code> [4]:<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:12px\"><code>do_log(LogLevel level, int force, const char *suffix, const char *fmt, va_list args) {\n\tsyslog(pri, \"%.500s\", fmtbuf);<\/code><\/pre>\n\n\n\n<p class=\"has-small-font-size\">Qualys found that if this <code>SIGALRM<\/code> handler interrupted a <code>malloc<\/code> call within OpenSSH\u2019s public-key parsing code, then the <code>syslog()<\/code> call to <code>malloc<\/code> within the handler would cause corruption to the heap when execution was returned back from the handler:<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:10px\"><code>Main Execution        |---&gt; grace_alarm_handler:\n...                   |      \/\/ The state of the heap is now unstable as malloc did not finish.\n...                   |      syslog(\"Timeout\") -&gt; malloc() -&gt; Updates the heap.\nmalloc(X) -&gt; SIGALRM -| &lt;--- return\n\/\/ When this malloc resumes, the state of the heap has changed, and causes corruption.\n...<\/code><\/pre>\n\n\n\n<p class=\"has-small-font-size\">Eventually, the researchers were able to corrupt memory that would write code into the heap, and then they could overwrite <code>glibc<\/code>\u2019s <code>__free_hook<\/code> function pointer to the address of the code that they had written, which would then grant them remote code execution during the next call to <code>free()<\/code> [4]. The researchers explain the process of corrupting the heap:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"has-small-font-size\">If [\u2026] <code>malloc()<\/code> is interrupted by <code>SIGALRM<\/code> <em>after<\/em> line 4327 but <em>before<\/em> line 4339, then the [allocated] chunk [\u2026] is already linked into the unsorted list of free chunks, but its size field is under our control, [\u2026] and this artificially enlarged [\u2026] chunk overlaps with the following small hole. [\u2026] [W]hen the <code>SIGALRM<\/code> handler calls <code>syslog()<\/code>, [<code>malloc()<\/code> allocates] the small hole for its FILE structure, and [<code>malloc()<\/code> allocates] a 4KB read buffer. [\u2026] [W]e therefore overwrite parts of the FILE structure with the internal header of this small remainder chunk.<\/p>\n\n\n\n<p class=\"has-small-font-size\">We were able to make 27 pairs of such large and small holes in [the] heap [\u2026]: Achieving this complex heap layout was extremely painful and time-consuming, but the [highlights is]: We abuse [OpenSSH\u2019s] public-key parsing code to perform arbitrary sequences of <code>malloc()<\/code> and <code>free()<\/code> calls.<\/p>\n\n\n\n<p class=\"has-small-font-size\">[4]<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">How Severe Was It?<\/h2>\n\n\n\n<p class=\"has-small-font-size\">A unauthenticated, superuser privilege, network-exploitable remote code execution vulnerability is exceedingly severe. However, despite having an 8.1 out of 10 severity score, RegreSSHion only had a 2.2 out of 10 for an Exploitability Score [3]. Why was this? In short, RegreSSHion took a considerable amount of time to successfully carry out, and could only be done so on specific architectures [4].<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Luck and Patience<\/h3>\n\n\n\n<p class=\"has-small-font-size\">There was a lot of luck involved, as the exploiters had to perfectly time the <code>SIGALRM<\/code> handler within a narrow range of 12 lines of code within the <code>malloc<\/code> of OpenSSH\u2019s public-private parsing code. Coupled with the default 120 second timeout for each <code>SIGALRM<\/code>, the authors remark that it took ~10,000 tries to win the race condition and cause the intended Heap corruption. This translated to 3-4 hours for remote code execution with 100 active connections to the server [4].<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">ASLR<\/h3>\n\n\n\n<p class=\"has-small-font-size\">A security feature that severely hindered the exploit was ASLR, or Address Space Layout Randomization. The Linux Kernel will automatically randomize the location of key parts of the program, specifically <code>glibc<\/code>. When attacking a 32 bit machine (With 4 byte memory addresses), this caused the <code>_free_hook<\/code> function in <code>glibc<\/code> to randomly be at either address <code>0xb07400000<\/code> or <code>0xb07200000<\/code>, to which the attackers had a 50% of guessing correctly. This alone effectively doubles the time needed to exploit RegreSSHion, up to 6-8 hours. [4]<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">AMD64<\/h3>\n\n\n\n<p class=\"has-small-font-size\">The most important factor as to why RegreSSHion was not easily exploitable was due to the significant improvements to ASLR from the 4 byte memory addresses of 32 bit machines to the 8 byte memory addresses of modern 64 bit machines. The authors of the paper were unable to use this exploit on a 64 bit computer, but estimated that the time required was upward of an entire <em>week<\/em> [4]. Given that this entire exploit uses a vulnerability in <code>syslog()<\/code>, the function that logs these timeouts, any astute server administrator would quickly notice these floods of timeouts, and every one of the 100 permitted connections being utilized, and a simple restart of the server or OpenSSH daemon would reset the Heap to a safe state undoing all of the attacker\u2019s work. With 64 bit computers as the dominant computer architecture, long since overtaking the previous 32 bit, and the inability for the researchers to exploit 64 bit computers in any reasonable time, the scope of the exploit is reduced significantly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"has-small-font-size\">RegreSSHion revealed a significant vulnerability in the ubiquitous OpenSSH, where by abusing a Signal Handler tied to a timeout, which used the thread-unsafe <code>glibc<\/code> implementation of <code>syslog()<\/code>, attackers could methodically corrupt the heap of a privileged child and eventually achieve arbitrary code execution, exploitable from the network, and at superuser privilege. While newer versions of the software have since patched the vulnerability, its emergence as a regression from a prior vulnerability reveals the critical importance of testing and stringent code review for any application that users and administrators rely on for security, for even minor issues\u2014such as using a standard library function that that just so happens to use a dynamic memory allocator in a Signal Handler\u2014can be exploited through patience and ingenuity.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">References<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"has-small-font-size\">1: https:\/\/blog.qualys.com\/vulnerabilities-threat-research\/2024\/07\/01\/regresshion-remote-unauthenticated-code-execution-vulnerability-in-openssh-server<\/li>\n\n\n\n<li class=\"has-small-font-size\">2: https:\/\/www.fortunebusinessinsights.com\/server-operating-system-market-106601<\/li>\n\n\n\n<li class=\"has-small-font-size\">3: https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2024-6387<\/li>\n\n\n\n<li class=\"has-small-font-size\">4: https:\/\/www.qualys.com\/2024\/07\/01\/cve-2024-6387\/regresshion.txt<\/li>\n\n\n\n<li class=\"has-small-font-size\">5: https:\/\/www.man7.org\/linux\/man-pages\/man7\/signal.7.html<\/li>\n\n\n\n<li class=\"has-small-font-size\">6: https:\/\/tldp.org\/LDP\/lkmpg\/2.6\/html\/x1256.html<\/li>\n\n\n\n<li class=\"has-small-font-size\">7: https:\/\/github.com\/kraj\/glibc\/blob\/master\/malloc\/malloc.c<\/li>\n\n\n\n<li class=\"has-small-font-size\">8: https:\/\/www.openssh.com\/<\/li>\n\n\n\n<li class=\"has-small-font-size\">9: https:\/\/www.learncpp.com\/cpp-tutorial\/the-stack-and-the-heap\/<\/li>\n\n\n\n<li class=\"has-small-font-size\">10: https:\/\/www.man7.org\/linux\/man-pages\/man5\/sshd_config.5.html<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Image References:<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"has-small-font-size\">Featured Image: <a href=\"https:\/\/www.securityweek.com\/wp-content\/uploads\/2024\/07\/regreSSHion.jpg\">https:\/\/www.securityweek.com\/wp-content\/uploads\/2024\/07\/regreSSHion.jpg<\/a><\/li>\n\n\n\n<li class=\"has-small-font-size\">OpenSSH: <a href=\"https:\/\/www.openssh.com\/images\/openssh.gif\">https:\/\/www.openssh.com\/images\/openssh.gif<\/a><\/li>\n\n\n\n<li class=\"has-small-font-size\">Process Signals: <a href=\"https:\/\/devopedia.org\/images\/article\/197\/5091.1562685662.png\">https:\/\/devopedia.org\/images\/article\/197\/5091.1562685662.png<\/a><\/li>\n\n\n\n<li class=\"has-small-font-size\">Dynamic Memory Allocation: <a href=\"https:\/\/cdn-images-1.medium.com\/max\/1200\/1*8b9-Z3FV6X9SP9We8gSC3Q.jpeg\">https:\/\/cdn-images-1.medium.com\/max\/1200\/1*8b9-Z3FV6X9SP9We8gSC3Q.jpeg<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>On July 1st, 2024, the security firm Qualys published their discovery of a vulnerability within the OpenSSH daemon that allowed for unauthenticated, network-exploitable, remote code execution [1]. As a ubiquitous means of secure access to remote servers, the vulnerability allowed for attackers to gain unfettered, superuser access to a majority of servers running Linux, which &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/2024\/09\/09\/regresshion-remote-code-execution-in-openssh\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;RegreSSHion: Remote Code Execution in OpenSSH&#8221;<\/span><\/a><\/p>\n","protected":false},"author":660,"featured_media":339,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[1],"tags":[9,10,11,12],"class_list":["post-337","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-openssh","tag-regresshion","tag-security","tag-vulnerability","entry"],"featured_image_src":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-content\/uploads\/sites\/119\/2024\/09\/regreSSHion-600x400.jpg","featured_image_src_square":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-content\/uploads\/sites\/119\/2024\/09\/regreSSHion-600x600.jpg","author_info":{"display_name":"Kyle Kernick","author_link":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/author\/kyle-kernick\/"},"_links":{"self":[{"href":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-json\/wp\/v2\/posts\/337","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-json\/wp\/v2\/users\/660"}],"replies":[{"embeddable":true,"href":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-json\/wp\/v2\/comments?post=337"}],"version-history":[{"count":6,"href":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-json\/wp\/v2\/posts\/337\/revisions"}],"predecessor-version":[{"id":345,"href":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-json\/wp\/v2\/posts\/337\/revisions\/345"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-json\/wp\/v2\/media\/339"}],"wp:attachment":[{"href":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-json\/wp\/v2\/media?parent=337"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-json\/wp\/v2\/categories?post=337"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpsites.ucalgary.ca\/jacobson-cpsc\/wp-json\/wp\/v2\/tags?post=337"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}