all right so this is actually pretty
surprising we have a uh security uh rce
in open SSH going on here uh CSV was
filed this is CSV uh CV CSV cve 2024
6387 are you ready for some remote code
execution open SSH let's go preliminary
note open SSH is one of the most secure
software in the world this vulnerability
is one slip up in an otherwise near
Flawless implementation is defense
in-depth design and code are a model and
an inspiration and we should thank open
s's Developers for their exemplary work
agreed absolutely uh we discovered a
vulnerability a signal Handler raise
condition in open SSH server sshd if a
client does not authenticate within
login grace Time seconds 120 by default
600 in old old open SSH versions then
SD's Sig alarm Handler is called
asynchronously but this signal Handler
calls various functions that are not
async signal safe
for example CIS log this race condition
affects sshd in its default
configuration oh man this is one of
those this is one of those attacks that
are just crazy these are one of those
attacks that I just don't even have the
skills to understand but let's go
through let's see what we got here our
investigation we realized that this
vulnerability is in fact a regression of
cve 2006 5051 signal Handler raise
condition and open SSH 4 4.4 allows
remote attackers to cause a denial of
service service crash and possibly known
execute uh execute arbitrary code this
was reported in 2006 by Mark Dow oh man
all right we're getting deep here this
regression was introduced in October
2020 open SSH 8.5 P1 by Commit This
revised log infrastructure for open SSH
which accidentally removed an ifdef do
log safe in Sig hand from sigai a
function that is directly called an SD's
Sig arm Handler in other words open SSH
before 4.1 or 4.4 P1 is vulnerable to
the signal Handler race condition if not
backport patched against CV 2006 5051 or
not patched against CV 2008 4109 which
was an incorrect fix for 2006 5051 wow
4.4 4.4 P1 less than open SSH and up to
8.5 P1 is not vulnerable to the signal
Handler race condition because the ifdef
do log safe in Sig
hand which is Sig Handler by the way I
know I know things uh that was added to
Sig die by this patch for 2006 5051
transformed this unsafe function into a
safe exit one
call everything that's less than this
everything between these two is
vulnerable again to the signal Handler
race condition because of the if def do
log safe Sig hand was accidentally
removed from Sig die oh so 9.8 is fine
are they saying this must have been that
um responsible disclosure this
vulnerability is exploited remotely on
gpsy based Linux systems where Cy log
itself calls async signal unsafe
function for example malakin free an
unauthenticated remote code execution as
root because it affects SD's privilege
code which is not sandbox and runs with
full privileges we have not investigated
any other libc or operating system but
open BSD is notably not vulnerable
because its Sig alarm Handler call CIS
log R an asynchronous signal safer
version of CIS log which was invented by
BSD in 2001
okay I want to see some examples here I
I think I think I think we see what's
happening here uh open BSD Chad yep okay
uh security vulnerability introduced by
unnecessary complexity I'm not sure if
it's unnecessary complexity it sounds
like it's perfect complex complexity
right when you're unable to be logged in
after the after the timeout period you
go into this little logging thing and
then you die and then somebody removed
an if def for when you're in a specific
case and then this causes a problem
nevertheless we immediately faced three
major problems uh from a theoretical
point of view we must find a useful code
path that if interrupted at the right
time by Sig alarm leaves SD in
inconsistent State and we must then
exploit this inconsistent State instead
of Cal arm
Handler is this okay so what I'm now
reading is this is a theoretical bug not
a
practical boots on the ground bug is
that safe to say cuz we've been hearing
a lot about this where we get a we get a
ton of like uh a lot of Open Source uh
things are getting a ton of information
in in which may or may not be super
useful from a particular let's see from
a practical point of view we must find a
way to reach this useful code path in
sshd and maximize our chances of
interrupting it at the right time from a
timing point of view we must find a way
to further increase our chances of
interrupting this useful code path at
the right time remotely all right so
let's see I just checked yuntu 20 uh
2204 and 2404 and they are using SSH
version 8.9 which is Tech or 9.8 or 8.9
okay so this this sounds like it it may
not be as big of a problem as we see we
may not be able to take advantage of it
okay 8.9 so in other words uh 2020 uh
2204 and 2404 both are technically
vulnerable to this bug to focus on these
uh three problems without having to
immediately fight against all modern
operating system Protections in
particular aslr and NX we decided to
exploit old op SSH versions first on
i386 and then based on that experience
recent versions first uh SSH 2.0 open
SSH 34 P1 Debian 31 okay a lot of this
Woody uh from this one right here uh
this is the first Debian version that
has privileged separation enabled by
default and that is patched against all
critical vulnerabilities of that era all
right to remotely exploit this version
We interrupt a call to free with a Sig
alarm inside SD's public key Parson code
then Le let's see leave the Heap in an
inconsistent State and exploit this
inconsistent State during another call
to free in side Sig alarm Handler our
experiments takes uh 10,000 tries on
average to win this race condition oh
okay so it's not purely theoretical they
are able to do it on the older versions
okay with 10 connections Max startups
accepting uh accepted per 600 seconds it
takes one week on average to obtain a
remote root shell okay I mean that's
still real that's that's definitely real
I mean this is obviously a very old
version of it right cuz they said uh uh
Debian version Woody I don't even know
what version Woody is but Woody had to
be a a long time ago uh second ssh2 this
big thing right here from Ubuntu this
big thing uh this is the last Ubuntu
version that still had vulnerable to
2006 -51 signal Handler race condition
right so this is before 4.4 so this is
before
2006 um to remotely exploit this version
We interrupt a call to Pam start with
Sig alarm leave one Pam's instructions
in an inconsistent state and exploit
inconsistent State during a call to Pam
end inside a Sig arm Handler our
experiments it takes 10,000 tries on
average to win this race condition IE 10
connections okay and at 120 seconds it
takes one to two days to uh remain a
remote uh remote
shell okay
okay all right here we go we're on this
version of deian uh this is the current
deian stable version and it is
vulnerable to the regression of CV 20
65055 to remotely exploit this version
we uh interrupt a call to Malik with Sig
alarm inside SD's public key parsing
code leave the Heap in an inconsistent
State and exploit this inconsistent
State during another call to Malik
inside Sig alarm Handler more precisely
inside CIS log in our experiments it
takes up to 10,000 tries on average to
win this race condition so 3 to four
hours with 100 connections Max startups
accepted 100 let's see 120 seconds
ultimately it takes 68 hours on average
to obtain remote shell uh pig as we only
guess the lib uh lib the G lib C's
address correctly half of the time a
aslr is where they uh they effectively
take uh in program memory pointers and
sanitize them right it's definitely this
definitely does not uh this is
definitely not
um uh this is no longer theoretical it
sounds like right it randomizes it right
I know it's randomized but it's it's
yeah it's address uh layout
randomization yeah okay that's what I
thought okay
address space layout randomization yes
I've heard about this I've heard about
this thing I'm just a dumb programmer
aren't we all this research is still a
work in progress we have targeted
virtual machines only not bare metal
servers on a mostly stable Network to
link 10 milliseconds package Jitter okay
so not not not a not a lot of uh not a
lot of time right here we are con we are
convinced that various aspects of our
exploits can greatly improve we have
started to work on an amd64 exploit
which is much harder because of the
stronger
aslr interesting a few days after we
started our work on amd64 we noticed the
following bug report in open SSH
bugzilla about deadlock and sshd S uh
sigal arm Handler all right uh we
therefore decided to contact op s's
developers immediately to let them know
that this deadlock is caused by an
exploit exploitable vulnerability we put
our AMD work on hold and we started to
write this advisory this is actually
pretty
cool this is uh this is actually really
really wild so this is from 2005 version
Theory I do like that they have a little
quote every single time they have a
little quote upon every single little
section okay Theory but that's but
that's not like me I'm breaking free the
interruptor okay what are the interrupts
I don't know this
reference I I assumed it was a band yeah
it is new album completely reasonable I
knew it I knew it all right the S alarm
Handler of this open SSH version calls
packet close which calls buffer free
which calls x free and hence free which
is not a sync signal safe okay so Grace
alarm Handler
dang man what what a code what a code
threading going on here so you have to
hit it you have to hit a signal uh uh
some sort of signal while calling this
so that's why it takes like one in
10,000 tries cuz you're trying to do a
timing attack and that's why was so
important where they mentioned packet um
packet distribution right so a big thing
about packet distribution is often
you'll see something like that right
where whoopsies that was a terrible one
I hit my mouse next to me right where
you're going to
see something like this right this is a
zero over here which virtually no
packets go right here and then you have
really fast packets then you have the
majority of packets Landing right here
and then you have this really long tail
of possible packets so for you to be
able to cause this cant you have to land
and sending packets my assumption is
that they have the 120 seconds is when
it's closing they use that as a as a
means to try to timeout packets being
sent to hit this and that's why it only
works with default configuration because
they can figure out that I guess you
could technically run enough sessions
you can figure out the uh configuration
you can figure out the default or the
configuration for timeouts I assume this
is how they're doing it and so if you
send a packet if you expect Clos down to
happen in 120 seconds and you're sting
measuring latency and latency varies
between 10 milliseconds to 100
milliseconds you're trying to land a
packet is my assumption of what's going
on here is you're trying to land a
packet right here at this perfect moment
I think that's what they're trying to
say so that way it's calling and it's
doing it's it's calling it's it's being
interrupted during the
middle of a free that's way smarter than
I am yeah I this is vastly outside of my
my understanding but I think that's what
I'm reading right now yeah dude it's
like seriously way way smarter than me
that is incredible research consequently
we started to read the Malik code of
this uh Debian dude when you're reading
Malik you are deep the see uh if a first
uh if the first call to free can be
interrupted by Sig alarm and exported
during a second call to free inside the
sigle arm Handler at lines this right
here above because the lib G the the G
libc Malik is not hardened against the
unlink technique pioneered by solar
designer in 2000 we quickly spotted an
interesting code path in chunk free okay
so we have a Malik right so we have our
pointer we have our internal size all
that if I'm not mistaken if I'm not
mistaken how Malik effectively works in
the simplest part is that when you ask
for a chunk of memory it gives you a
pointer to this part of the memory but
behind it is a header and so if you just
go to this pointer and walk backwards
you effectively get to the header size
if I'm not mistaken that's like the
basics of how Malik worked that's why
when you free a pointer it knows how to
free the pointer because it has it has
it has this right here it effectively
has a header hidden behind the memory
chunk all right so this is just code I
don't quite understand here so we got
ourselves a structure we got ourselves
an unlink which Just Hits it with the
old P dude nothing like a macro quick
macro unlink with the BK PK FD file
descriptor maybe file descriptor BK BK
yeah oh okay so this is unlinking okay
this looks like a two-way this looks
like some sort of linked list going on
here right because we have the K and we
have the
FD and we're pointing them at each
other I don't know what it's doing all
right I can't read this code I'm not
smart enough here all right so there we
go here we go to exploit this code path
we arranged for SD's Heap to have the
following
layout are all maloc chunks of memory PS
F and B are their previous size are
their previous size size FD and BK
Fields I don't know what BK stands for
okay so you have chunk X chunk Y and
chunk Z so how do you how do you arrange
the Heap to look like this is it just
sending in three packets it must be
sending in three
packets Burger King
obviously
back BK
back it's so
simple it's so simple it's like right
there bger King uh first if the call to
free chunk Y is interrupted by sarm
after line this but before Line This
Then chunk Y is already marked as free
because chunk Z's previous uh pre inuse
bit is cleared at line this okay okay so
there must be some sort of Arena
allocator that's using a linked list to
walk the Arenas is that's what it is uh
but it is not yet linked into the doubly
uh its doubly linked list at line 3 uh
3251 in other words the chunk wise uh FD
and or forward yeah that's forward and
backp pointers still contain user data
attack Control Data
okay okay welcome to the arena yeah
second if inside sigle arm Handler
packet clo calls free chunk X then the
code block at lines these ones right
here is entered because y chunk is Mark
free and chunk Y is
unlined and so the so-called aa4 [ __ ]
primitive almost arbitrary 4 byte mired
overwrite what a name man this is wildly
low uh because chunk wise FD uh back or
for and back pointers are still attacker
controlled for more information on the
unlink technique and uh primitive check
out this one okay so this is the jpeg
interesting now I want to learn more
about this dang it I just want to learn
about all of
them last with the aa4 BM Prim [ __ ]
primitive we overwrite the uh gbc's free
hook function pointer this old Dean
version does not have aslr nor NX with
with the addresses of our Shell Code in
the Heap thus Achi remote code execution
during the next Call of free dang okay
so that's why it was so simple to do
woody is because since you didn't have
this it was really easy to uh you could
just had a defined address in which was
free hook so you never really had to
okay okay so that's why they started on
Woody just to verify that it
worked this makes more sense uh for the
for the link it's right here okay
practice they're taking over uh now they
are taking over and they got complete
control the interrupts Liberty again
beautiful to mount this attack against
sshd we interrupted a call to free
inside SD's parsing code of the DSA
public key I.E line 144 below is our
free chunk Y and exploit uh it during
one of the free calls in packet close
one of the lines 341 to 344 above is our
free chunk okay buffer get big numb too
damn I I don't even know what's going on
here so get a buffer get string must be
some sort of uh here's the buffer you
must get some sort of length that I'm
not really sure what I'm not even sure
what's going on
here b b binary to big number then free
the bin then free bin initially however
we were never able to win this race
condition uh interrupt the free call
with uh at line 144 this one right here
okay at the right time eventually we
realized that we could greatly improve
our chances of winning this race
condition uh the DSA public key Parson
code allows us to call free four times
at lines 704 through 707 below and
furthermore sshd allows us to attempt
six user
authentications uh if any one of these
24 free calls is interrupted at the
right time then uh then we later achieve
remote code execution in Sig alarm
Handler oh because it does it like look
at that it just does it back to back to
back to back oh so that's how they're
doing is they're waiting for the most
like something that just has such a
large chunk of freeze happening that all
they have to do is just keep on tossing
things in there and interrupt it okay uh
with this Improvement we finally won the
race condition after one month wow we
were happy and it did a root shell dance
uh but we also felt that there is still
room for improvement timing don't worry
just wait and see the interruptor
Haven't Seen the Last of Me therefore
again I love I am dude I am in absolute
love with the fact that they keep
quoting a single band called The
interrupts in an attack that it's all
about interrupting program flow this is
just so good I can't imagine I can I
cannot fathom fighting a race condition
for that long well especially since they
said the following phrase that they
tried to do this one for a long time and
figured out they just couldn't make it
happen so how long was this running
where they were trying to interrupt this
before they found this and then tried
that which this then ran for one
month right like how long has this
research been going on
we therefore implemented the following
three-fold timing strategy we do not
wait until the last moment to send our
rather large DSA public key ah uh to
sshd instead we send the entire packet
minus one bite the last bite long before
the login Grace time okay okay so oh yes
so they're hanging it because it's minus
one bite so it's waiting for that last
bite before it sends it off as a
complete packet okay we're starting to
take shape here and then send off the
very last bite at the very last moment
to minimize the effects of network
delays yes cuz if you have one one
packet there's like this weird thing
that happens in networks where one
packet is vastly faster than two
packets like the the the difference
between one and two is vast I've heard
numbers tossed out you're going to have
to get uh some coding guy from Netflix
to talk about this but he mentioned one
time to me that one packet versus two
packets
um is something along the same lines as
one packet versus 20
like the timing difference is not that
much
difference it's like vastly different
one is extremely fast versus two or more
is just like a huge window for like
problems I've heard that before too yeah
I don't know the exact amount but I
heard there's just like this there's
just a whole problem set once you send
more than one packet so this makes
perfect sense if you want to really time
the attack you have a singular packet
that you
send we keep track of the median round
trip time by regularly sending packets
that produce responses from
sshd called it called it called it okay
this makes sense this makes sense H and
keep track of the difference between the
moment we are expecting our connection
to be closed by sshd essentially the
moment we received the first bite of the
sshd banner plus the login Grace time
and the moment our connection is really
closed by sshd according and adjusted
our timing I.E the moment we send the
last bite of our DSA
packet Dam
dang okay so they are trying to they
they're they're literally trying to get
something to start running the DSA
packet and then using that 1202 login
Grace time to then interrupt it and call
free okay these times are interrupt free
call with the Sig Handler with the Sig
Sig
abort uh these time differences allow us
to track clock skews and network delays
which show predictable patterns over
time we experimented with linear and
spline regressions but in the end
nothing worked better than simply
reusing the most recent measurements
let's go that's that's because like I
mean the problem about networks is
networks aren't like what happened one
hour ago isn't really an indication of
what is going to be happening now even
what happened 10 minutes ago may not be
an indication to what's happening now
like there's just so much variation in
in in in networks possibly deep learning
might yield even better results a calman
filter uh this is left as an exercise
for the interested reader uh more more
importantly we further increased our
chances of winning this race condition
by slowly adjusting our timing through
involuntary feedback from sshd if you
receive a response S2 message user off
filed to our DSA public key packet then
we sent it off then we sent it too early
SD had time to receive our packet in an
unprivileged child parse it and send it
to the privileged child parse it there
and send the response all the way back
to us if we cannot even send the last
bite of our DSA packet then we waited
too long sshd received a s alarm and
closed our con connection if we can send
the last bite of our DSA packet and
receive no response before sshd closes
our connection then our timing was
reasonably accurate interesting okay
yeah because you're you're not only not
only are you facing Network variations
you're also facing CPU stuff just
assuming that you may not you may have
all sorts of different problems right
what happen if they're in what happen if
they're in a shared environment right
there's all sorts of then variations of
timing on top of
this that's crazy this is crazy
crazy this feedback allow man this is so
cool this feedback allows us to Target
what we call the large race condition
window hitting it does not guarantee
what we win uh that we win the race
condition but inside this large window
there are 25 small race
windows it's so smart inside the 24 free
calls that if hit guarantee that we do
win the race condition with these
improvements it takes 10,000 tries
approximately 10,000 tries on average to
win this race condition I.E 10
connections 600 seconds log and grace
Time one week but the new ones are much
smaller it's only 120 seconds which cuts
it down to one to two days all right
Theory take one I sleep when the Sun
starts to rise the interruptor
alien the Sig alarm handles uh Handler
of this open SSH version does not call
packet close anymore moreover this
Ubuntu uh glibc 236 always takes a
mandatory lock when entering the
functions of the Malik family even if a
single thread like SSH which prevents us
from interrupting a call to one of the
Malo functions and later exploding it
during another call to these functions
they would always deadlock we must find
another
solution oh this is exciting hey I'm
gonna get a quick hey flip take this
part out I'm gonna get a quick drink of
water flip take it out cve 20 uh 2006
I'm just going to call uh 20 I'm just
going to call it by the year because it
looks like there's one per year so we
should be just fine so 2006 cve mentions
a double free in gssapi but gssapi or uh
cerberos is not enabled by default so
this does not sound very appealing on
the other hand Pam is enabled by default
and Pam end is called by sshd sigle arm
Handler and is of course not async
signal safe we therefore searched a uh
for a few or oh my goodness we searched
for a Pam function that if interrupted
by Sig alarm uh at the right time would
leave Pam's internal structures in an
inconsistent State exploitable during
Pam end in the sigal arm Handler and we
found Pam set data all right what do we
got here so is it the Malo is is that
what they're trying to do is they're
trying to during Malik stuff but I
thought Mal I thought all the Malik
stuff is is thread safe so it must be
something else that I do not understand
if this function is interrupted by Sig
alarm after line 66 but before line 74
then the data entry is already linked
into Pam's structure Pam H but is
cleaned up let's see but it's cleanup
field a function pointer is not yet
initialized since the Malik on 57 does
not initialize its memory if we are able
to control cleanup through leftovers
from previous Heap allocations then we
can uh execute arbitrary code when Pam
end oh calls Pam free data so there okay
so if I'm reading this correctly they
want to cause the abort to happen here
to call a cleanup somewhere else but
before that happens this value needs to
be set to a specific different function
pointer so that when it calls cleanup it
calls cleanup on the function they
control okay okay
clever I literally have have no
idea how they set this
value okay uh Pam free data uh Handler
tpam struct let's see let's see this one
we have the data last data equals the
data while last um this yep there it
goes it it calls the cleanup this would
have been extremely simple exploit
unfortunately we completely overlooked
that Pam set data can only be called
from Pam modules if we interrupt it with
Sig alarm then Pam caller is or Pam
caller is is still Pam called from
module in which case Pam end returns
immediately without ever calling Pam
free data back to the drawing board okay
Theory take two not giving up is not
what we do the interruptor title
holder we noticed that I dude they must
have been jamming to the interrupts for
months straight for literal months
straight we notice that at line 601
below sshd passes a pointer to its
Global SSH Pam Handler pointer directly
at p uh to Pam start which is called
once per connection static Pam handle
uh-oh
uhoh shapam handle goes in here error
okay we set this thing
therefore we therefore decided to look
into pamart itself if interrupted by
sigal arm we might leave the structure
pointed uh to by spam Handler in an
inconsistent state which could then be
exploited inside the Sig alarm Handler
when Pam and SSH handle or SSH Pam
handle yep is called okay Pam start
all right there it is so there we go so
we have a CAC and we have an init our
handlers uh we have an init handlers
which has we read from a config file we
have config file which adds Pam Handler
we have add Pam Handler which grabs
these
handlers sees if it's uh authenticated
and we Malo the size of the structure
and we set the next and all I think
I barely understand this code dude I
don't know why I'm so bad at reading C
can we just get this in Zig
already can we just get this in Zig uh
at line 32 Pam start immediately sets
sshds SSH Pam handle to a cated uh chunk
of memory this is safe because calic
initializes this memory to zero that's
right uh on the other hand if Pam ad
Handler which is called multiple times
by Pam start is interrupted by Sig alarm
after line 874 but before line 886 the
maloc structure is l linked into Pam but
its next field is not yet initialized if
we were able to control next through
leftovers from previous Heap allocations
then we can pass an arbitrary pointer to
free during the call to Pam end I still
don't understand how they pass this
arbitrary pointer that's what confuses
me how does it how do they set it up in
such a way that they can do
this okay
so is it is it something where they are
able to allocate memory
from the Heap then they know that this
memory is freed and then they know that
this memory is somehow reallocated with
something that's smaller and thus its
offset is something they set earlier to
point to a certain address is that like
is that what this is
going it reuses noers okay okay so am I
understanding this correctly cuz that
way then this handle because they know
the size of this so if they can just get
the correct thing in place here and then
when it's re when it's that's how I
understand it
yeah yes people are saying yes but I
think people say yes to whatever I say
sometimes that's that is kind of where
it goes yeah I think sometimes people
say yes to whatever I say no yes they're
trying yes yes yes yes okay so yes
someone said it correctly yes that's the
whole point of the interrupt is that
they're trying to they're trying to grab
the freed memory before it gets clear
and redirected yes they're trying to
call a a second they're trying to
interrupt during a read or during a free
process to leave it in a specific state
that would then be called into something
remotely and then if you could just set
that address so my my assumption of how
this is works is that what this is is
that uh here I'm going to redraw this so
this is how it this is how this quote
unquote Works in my head Let's Pretend
the size of this thing is like this big
and they have a chunk that they can
override so if they can call it before
fors freed and then this Handler gets
called if they set this address to be
like say right here and then this is the
actual code execution right I just drew
an American flag [ __ ] yeah Eagles yeah
yeah Eagles
Eagles Eagles hell yeah hell yeah look
at that eagle America yeah get
guns yeah this is shotgun hell
yeah um
yeah there you go what the [ __ ] is a
kilometer right and so then then they
execute then they just effectively
offset this into the struct further
where they can execute the code I think
that's what I'm understanding because
they also said a rather large DS DSA DS
something dsse uh encryption I don't
know that I don't know the encryptions
very well I don't know these things
right I think that's what I'm I'm seeing
or
understanding well Malik will get a
pointer um well Malik will get a will
get a pointer to the Heap that will not
be uh that will not be cleared so if it
has data it will still be there yes so
did I think I I think I effectively am
understanding how this is working in a
very very very primitive childish
way all right so there we go see we call
the free Handler and the free Handler
calls the auxiliary free Handler which
then calls this Pam drop then we have
the mem set then we just set a bunch of
zeros and then we then we last okay so
what is going on here so what is this
because of the Malik and ubuntu's lib GC
already hardened against the old
unleaked Technique we decided to
transform our arbitrary free into a
Malik uh baleric com's House of
mind this must be some really
well-known
thing is a heap exploitation technique
detailed in the Malik uh Mala facet
fium document which is a renowned
resource in the field of computer
security and exploitation this document
was created in 2002 and explores various
methods to exploit ganu C libraries uh
GBC Malik implementation for arbitrary
code execution and other Mal malicious
Activities The House of the Mind
techniques specifically involves
manipulating the program's memory
allocation process to write a large
value a heap pointer to an arbitary
address this is typically done by
exploding a single bite override to
influence the arena handling in lib G uh
gbc's Malik system the primary goal is
to cont uh to control the arena
structure to facilitate further
exploitation however this technique and
several others describe in the Malik uh
malarum I think I'm saying that micerium
I don't know how to say that word uh
have been migrated to more recent
versions of lib due to Integrity checks
okay we free our uh our own non-main
area chunk point to our fake uh Arena to
S sshds got LT the Ubuntu sshd has aslr
but not uh pi and overwrite and
overwrite exits entry with the address
inside our Shell Code in the Heap this
ubuntu's Heap is still executable by
default and more information of malx Mal
okay right here practice I have learned
everything the hard way the interruptor
the hard way to mount this attack
against sshd we initial we initially
faced three problems the house of the
Mind requires us to store a pointer to
our fake Arena right here in the Heap
but we are able to store attacker
controlled data uh at such a high
address because sshd calls Pam start at
the very beginning of the user
authentication we do not control
anything except the username itself
luckily a username of length 128
KB who's who's allowing that well
there's your problem uh shorter than the
default M mmap threshold allows us to
store our own data at this address the
size of the field of our fake non-main
area chunk must not be too large to pass
free security checks I.E it must contain
null bites but are long oh yeah you
contain null bites to like think that
there's nothing left in the string but
our long username is null terminated
string that cannot contain null bites
luckily we remember that Pam free
handlers auxiliary zero the structure uh
that it frees yes yes right here here we
remember reading that one okay yeah yeah
yeah yeah yeah yeah we therefore Patch
the size field of our fake chunk with
the uh with such a memet zero and only
then free it we must let's see wow okay
I'm perplexed at this point of what
they're doing and now I can't I can't
understand what's happening so during
the initialization they set up a a fake
memory Arena by overriding the username
due to the hard requirement of the
threshold and then somehow they get it
to point in there in which then they can
actually make it so that it looks like
it's been faked and then they can Zer
out specific parts to make it so that
this one doesn't acally erase into stuff
they don't want to erase into we must
survive several calls to free right here
and above before free of our fake
non-main area Chunk we transform these
frees into no Ops by pointing them to
fake is is mapped chunks free calls
munmap chunk which call calls mmap which
fails because these these fake is mapped
chunks are misaligned effectively and no
op because assertion failures are not
enforced in this
ubuntu's
GBC yeah fix user name can be no longer
than 50 characters and shut the hell up
uh finally our long username allows us
to control the potentially uninitialized
next field of the 20 different
structures although leftovers from
temporary copies for a long username
because Pam start calls Pam ad Handler
multiple times I.E our large race window
contains 20 small race Windows timing
the same tricks they used before the
interruptor Divide us I can tell what
kind of band The interruptor is based on
these little quotes okay I'm getting I'm
getting definitely some Anti
Flag Vibes going on right
now uh for this attack against you the
definitely a punk rock band I would say
the interrupts have to be a punk rock
punk rock band at this point just based
on this some 70s 80s punk rock band how
do people find this
depression Anti Flag yeah SCA Punk yeah
he is literally showing you yeah looks
like an indie band okay could be Indie
yeah I could see that for this attack
against Ubuntu 606 wow that's an that's
old ass Ubuntu we simply reused the
timing strategy we used against Debian
30 R6 it takes a 10,000 tries on average
to win this race condition with 10
connections so that's 1 to two days okay
okay note because of this Ubuntu uh GBC
always takes a mandatory lock when
entering a function of Malik family an
unlucky attack or might deadlock all 10
Max startup connections before obtaining
a root shell we have not tried to work
around this problem because our ultimate
goal was to exploit modern open SSH
anyways okay good next section so this
is modern SSH right this is okay so now
we're on to
Modern now that you're ready take the
Demon's head on let's go let's go
interrupter what a quote what a quote
the signal alarm Handler to this SSH
version does not call packet closed nor
Pam end in fact it only calls one
interesting function CIS log Sig die SSH
remote IP add Port oh it is this is this
SSH remote IP Adder the same one of node
IP do they not know there's an S the cve
against it shut up don't worry I'm just
being stupid um all right we got some
code let's see sigai is a def don't you
just love macros
can we all agree macros are just
beautiful all
right let's see Sig SSH Sig die uh con
Char file const Char function line show
function all this kind of stuff then we
do a little log right here beautiful
okay that just grabs a bunch of these
magic macro values let's go uh SSH login
right here uh for those that don't know
when you compile your pre-processor
Macros get turned into code underscore
underscore file underscore underscore
then gets turned into the literal file
uh file name right and Funk gets turned
into literal function name line gets
turned into literal line number
right he's being I hope he's being
sarcastic macros are evil no macros are
actually evil I I know very little about
them because they are just they they're
gosh darn dang evil right they are
difficult to deal with uh we're going to
do some log we're going to do some logs
let's do some logs so we got this thing
going on here with the format buff okay
our two key questions are does the CIS
log of this Debian uh gpsy to 236 call
async signal unsafe functions as such as
Malik and free and if yes does this
glibc still take a mandatory lock when
entering the functions of the Malo
family luckily for us attackers the
answer to our first question is yes if
and only if the CIS log and size sigal
arm Handler is the very first call to
CIS log then local time 64r which is
called by CIS log calls Malik 304 to
allocate a file structure at line 166
and then calls Malik two to the 12 to
allocate the internal read buffer at
line 186 let's go we got two malx let's
go local time R man I've never been more
scared of malx now in my entire lifetime
oh my gosh all right so we got our local
time R we get this thing a TZ convert
which does this TZ set internal uh TZ
set internal does this TZ uh TZ file
read TZ file read does an F open file
rce let's go um all right there we go
note because we do not control anything
about malic uh dude I love that malic uh
nor their order uh not let's see not
their order not their size nor our
contents we took rce at line 166 as a
much needed good
omen dude sometimes fate is too nice
sometimes fate is just beautiful right
it just it you can't even you can't even
believe it and luckily for us the answer
to our second question is no since
October 2017 the gpsy malic functions do
not take any lock anymore since single
threaded uh when single threaded like
sshd so it's a re-entrant bug is that is
that is that what that says to me due to
the fact that it's due to the fact that
it's single threaded it makes the
assumption that it can effectively not
be um interrupted or you can't have
re-entrancy and since you can't have
re-entrancy you can use an interrupt to
effectively create re-entrancy
for those that don't know what
re-entrance is uh it's a it's a it means
that your function effectively can be
called while executing right so you can
imagine you have Foo and Fu has a bunch
of code that has things being called and
somewhere within Fu recalls Foo and if
you're so recursion is re-entered
effectively uh but if you set up state
right so Foo at the very very top sets
up a bunch of state that needs to be
unset at the bottom effectively you have
code up here and then you have a defer
statement if if you will if this was Zig
or go you a defer statement which needs
to be executed at the end you could
imagine that an interrupt would pause
right here no defer would be executed
and then you could re-enter into Fu thus
clobbering your setup so that's called
re-entrance right a re-entrance problem
is
that okay wow I didn't know I didn't
dude none of this this stuff is all
completely new to
me except for like the basic ideas the
basic ideas I I understand moreover this
deban verion suffers from the aslr
weakness described in the following
great blog post by Justin Miller and
Maas Krauss respectively all right
they're right here uh tool chain
necromancy past mistakes Haunting aslr
concretely in this case sshd on I uh i38
uh i386 gosh I can't even read anymore
too much reading
today I can feel the dyslexia really
starting to want to come out I'm
refusing it uh re-entry is that other
processes can fub our registers that are
uh that aren't saved during interrupts
yep
concretely in the case of sshd I uh i386
every memory mapping is randomized
normally sshd is pi the Heap most
libraries the stack but uh glibc itself
is always mapped to either the address
this or at this in other words we can
correctly guess gipsy's address half the
time a small price to pay for defeating
aslr in our exploit we assume that gpsy
is mapped to address this because it is
slightly more common than that
our next question is which code paths
inside gli's Malik function if
interrupted by Sig arm at the right time
leave the Heap in an inconsistent State
exploitable during one of the Malik
calls inside of Sig arm Handler we found
several interesting and surprising code
paths but the one we CHS involves only
relative sizes not absolute addresses
unlike various code paths inside unlink
chunk for example the difference might
prove crucial for our future amd64
exploit this code path inside Malik
splits a large free chunk victim into
two smaller chunks the first chunk is
returned to malx caller at line this and
the second chunk remainder is linked
into an unsorted list of free
chunks okay so this is the back forward
this is the doubly linked list Arena
whatever allocation something something
something we're looking at we're looking
at Malik time all right in int Malik
let's go uh if this code path is
interrupted by Sig alarm after line 4327
so let's look at 4327 so when we set the
remainder we've set the we've set the uh
back and forth to be pointing to the
same
thing but before three uh
4339 which sets the
head uh then the remainder chunk of this
split is already linked into the
unsorted list of free chunks lying right
here but its size field M chunk is not
yet
initialized if we're able to control its
size field through leftovers from
previous Heap allocations then we can
make this remainder chunk larger and
overlap with other chunks and therefore
corrupt Heap memory when this enlarged
overlapping remainder chunk is
eventually maloc and written two inside
Sig arm
Handler let's
go our last question then is given that
we do not control anything by the way
Matt I am reading your you I hope you
guys know I do read
chat this is the evil uh Heap allocation
fragmentation engine yeah this is wild
this it makes perfect sense I just can't
believe someone can do this like right
like it makes sense from a theoretical
standpoint but from a practical
standpoint this seems effectively
impossible in my
head our last especially since you get a
chance once every 120 seconds which just
seems
crazy our last question then is given
that we do not control anything about
Malak calls inside of Sig arm Handler
what can we overwrite in the Heap uh to
achieve arbitrary code execution before
SSA HD calls exit because TZ file read
inside of CLE arm Handler malates a file
structure in the Heap at line 166 and
because file structures have a long
history of abuse for arbitrary code
execution we decided to aim our Heap
corruption at this file structure this
is however easier said than done just
like the rest of this article uh our
Heap corruption is very limited and the
file structure has been significantly
hardened over the years by IO validate
vtables and pointer demangle for example
eventually we devis the following
technique which seems to be specific to
the I uh the i386 gpy the amd4 amd64 gpy
does not seem to use vable offset at all
with our limited Heap corruption we
overwrite the vtable offset field a
single signed Char of the TZ file read
structure the gpsy liio functions will
therefore look for this file structure
vtable pointer a pointer to an array of
function pointers at a nonzero offset
our overr overwritten vtable offset
instead of the default Z
offset nice so they offset it into their
own little beautiful code and then they
let that be executed absolutely
brilliant we we attackers can easily
control this fake vtable pointers
through leftovers from previous Heap
allocations because the file structure
around this offset is not explicitly
initialized by fopen to pass the glips
security checks our fake vtable pointer
must Point somewhere into the uh libc IO
table section we decided to pointed to
the V table for wide character streams
IO W file jumps I.E that exact number we
uh we assume that the gpsy is mapped to
this address right here okay yep yep as
a result F read unlocked at line 186
calls the F the io wri underflow instead
of IO instead of underscore IO file
underflow which calls a function pointer
function control I that's how I've
always read it fun function uh that
basically comes from the structure whose
pointer code CVT is yet another field in
the file
structure we attackers can easily
control this uh code CVT pointer through
leftovers from previous Heap allocations
I like they use the word easily uh
because this field is also a file
structure is not explicitly initialized
by fopen which also allows us to control
the function function
pointer okay okay so this must be
pointing into the above I assume their
name space the 128k of name space they
are able to have their own code passed
into that and that's what's happening in
summary by overwriting a single bite
vtable offset of the file structure
maloc by fopen we can call our own uh
function function pointer and execute
arbitrary code during uh freed unlock
practice I wanted it perfect no wrinkles
in it okay yeah yeah to mount this uh to
mount this attack against sshd
privileged child let us first imagine
the following Heap layout oh we're
getting into the juice now this is the
juice let's go this is going to be a
good one the X's are barrier chunks that
allow us to make holes in the Heap for
example small memory leaked
chunks all right shortly before sshd
receives the Sig alarm we mated a 4K uh
chunk that splits uh the large AK KB
chunks into two smaller chunks all right
so they're messing with Malik at this
point if this uh but if this Malo is
interrupted by Sig alarm after line 43
but before this line then the remainder
chunk of this split is already linked
into the unsorted list of free chunks
but its size field is under our control
through leftovers of the previous Heap
allocations and is artificially enlarged
to the remainder of the
chunks I know a lot of men that would be
very happy if they could be artificially
enlarged all right so this that is cool
so they get one large chunk they
actually get a real remainder chunk and
then artificially increase this to
exceed over into the small hole
okay okay when Sig alarm handle calls Cy
log and hence TZ file read F open
malates the small hole for its file
structure and f f read unlock malates
the 4K uh read buffer thereby splitting
the enlarged remainder chunk into two
the 4K read buffer and small remainder
chunk there's the file offset right
there look at that there's the hole like
that's the separation so they separate
past the separ and they're able to go
into the next one we therefore override
parts of the file structure with our
internal header of this small remainder
chunk more precisely we override the
files V table offset with the third bite
of the header's Back Field which is a
pointer to an unsorted list of free
chunks right here yeah then as we
explained in the theory section freed
unlock calls IO uh WF or W file
underflow instead of IO underflow yep
which calls our own function function
pointer through our own code CV PT
pointer and executes arbitrary code note
we have not yet explained how reliable
go uh how reliably go from controlled
this pointer to controlled function
pointer we will do so but we must first
solve the more pressing
problem nonzero value skill issues dude
this the skill issue in this is so
incredible it's incredible uh indeed we
learned from our work an older SSH
version that we will uh never win this
signal Handler race condition if our
large race WI window contains only one
small race window yeah I well I mean you
would probably win but the I'd assume
that the the chance of winning is so
large that it's impractical so if we
went like what he's saying there is that
if you remember the very beginning one
they had a single call that they were
trying to uh break into a single line or
a single couple lines that they were
trying to break into but they realized
if they used a different spot they could
get up to 24 of these same
calls that happened over a larger race
window so that they had this exploitable
window which was much larger
compared to much smaller and if this
took approximately 10,000
times which takes one to two days
theoretically you could say this would
take 240,000
times or in other words like you know
one to two
months you would assume that this could
theoretically at some
point be exploitable it's just so much
larger and if this thing has a default
600 second timeout then this thing is
like a year before you can get to it
the last packet that we should uh by the
way that's also statistics statistics
have no bearing into reality in some
sense just because it's supposed to be
one to two months does not mean it
wouldn't take six months
right it's it's the funny thing about
statistics when somebody says one in a
million it does not mean one in a
million right it's just that's that's
just never what that actually
means right I know people say this all
the time and your head thinks of that
way but that doesn't mean it's
real it's just not how you math but
people's brain thinks like that so
you're saying there's a chance yes uh
all right let's look at this the last
packet we send uh into sshd shortly
before the delivery of the sigal arm
this would be like the last bite right
of the de encryption right forces sshd
to perform the following sequence of
Malik Malik 4K Malik 304 Malik 4K Malik
304 Etc our first uh 4K splits uh the
large hole one into two uh if this first
split is interrupted by Sig arm at the
right time then the F open inside SIG
arms Handler malates the small hole one
for the file structure and we have
achieved arbitrary code execution as
explained above if not then we maloc the
small hole ourselves uh with our first
Malo 30 uh 304 then our second maloc of
4K splits two larger holes into two if
this second split is interrupted by Sig
alarm at the right time then F open
inside of Sig arm malates the small hole
too for its file structure and we have
achieved arbitrary code execution wow if
not then we malate the small hole our
small hole tool ourselves with our
second malach 304 we are able to make 27
pairs of such large and small holes into
ssht Heap 28 would exceed packet uh Max
size of 256 KB our large race window now
contains 27 small race Windows achieving
this complex Heap layout was extremely
painful and timec consuming
writing
about it feels extremely painful I
cannot imagine writing the thing
itself uh but the two highlights are we
abuse s's public key Parson code to
perform arbitrary sequences of malx and
free calls
yep uh C parse right here all right it
must be in which one uh SE free yep so
we where's the CT free right there okay
yeah yeah we were unable to find memory
leaks for our small chunks instead we
used tach chunks which are never really
freed because their inuse bit is never
cleared to makeshift barrier
chunks to reliably achieve this Heap
layout we sent five different public key
packets to sshd packets a uh to D can be
sent long before Sig alarm most of
packet e can also be sent long before
Sig alarm but its very last bite must be
sent at the very last moment okay there
we go a we maloc and freed a variety of
teach chunks to ensure that the Heap
allocations we that we do not control
end up in these tcache chunks and we do
not interfere with our carefully crafted
lay Heap layout B we malate in free
chunks of various sizes to make our 27
pairs of large and small holes and
corresponding barrier chunks C we maloc
and freed four cage uh four 4 kilobyte
chunks and 320 byte chunks too right the
fake header to the large size field and
our potentially en llarge remainder
chunk into the middle of our large holes
write our fake footer into the
potentially enlarged remainder chunk to
the uh end of our small holes to pass
the gpsy security checks we write our
fake V table and code CVT pointers uh
into the small holes which are
potentially file structures D we maloc
and freed one very large string nearly
256 KBS to ensure that our large and
small holes are removed from the
unsorted list of free chunks and placed
into their respective Malik
bins e we force sshd to perform our
final sequence of malic calls right here
to open our 27 small race windows
good good goodness
gracious man ATT tenative readers may
have noticed that we still have not
addressed literally and figuratively the
problem of yes in fact code a CVT is a
pointer to a structure IO uh is it IO
convert that contains a pointer to a
structure a g convert step that uh
contains the function uh pointer that
allows us to execute arbitrary code to
reliably Control Function through uh
code convert we simply L Point code
convert to one of the libg Malik bins
which conveniently contain a pointer to
one of our free chunks uh in the Heap
which contains our own function function
pointer to arbitrary gpsy code all of
these gpsy addresses are known to us
because we assume that gpsy is mapped to
this
address let's go let's
go so this is how it does it yeah this
is the one that I mean this is the one
they save to the end the the the the
very ending like you said like it like
that guy said
all right timing we are running out of
time the interrupts as we live uh as we
implement this third exploit it it
became clear that we could not simply
reuse the timing strategy that we had
used against uh two older s open SSH
versions We were never winning this new
race condition eventually we understood
why it takes a long time 10 milliseconds
for sshd to parse our fifth and last
public key yeah because it's okay yeah
in other words our large race window is
too large our 27 small race windows are
like needles in a hay stack the user
specified delay that was introduced uh
recently open SSH 7.8 uh P1 delays sshd
responds to our last public key packet
by up to 9 milliseconds and therefore
destroys our feedback based timing
strategy as a result we developed a
completely different timing strategy
from time to time we send our last
public key packet with a little mistake
that produces an error response okay
right before the call to SSH key from
blob that uh that parses our public key
from time to time we send our last
public key packet with another little
mistake that produces an error response
right here right after the call to SSH
key from blad that parses out our public
key the difference between those two
response times is the time that it takes
for the sshd to parse the our last
public key and this allows us to
precisely time the transmission of our
last packet to ensure that sshd has time
to parse our public key in the
unprivileged child and then send it to
the privileged child and start uh to
parse it uh there let's see before we
deliver the Sig
alarm yep remember I I I believe I did I
did not too recently uh
mention this whole problem you're going
to have this thing also fall into
this this is good this is
great mention mentioned oh yeah we
mentioned mentioned man this makes
perfect sense oh my gosh so they're
actually using this as a timing since
they could send a bad thing they would
know exactly how long this takes and
they can kind of build up the the time
these things
take dude C exploits are always nice
dude they're they're brilliant with this
change in Strat dude if they would have
just wrote this with JavaScript there
would have been garbage collection and
thus you would have never you would have
added a sto stochastic nature to this
thus never being able to actually be
exploited duh
forehead with this change in strategy it
takes uh 10,000 tries on average to to
win this race condition with 100
connections Max let's see Max accepted
per 120 seconds login Grace time it
takes 3 to 4 hours on average to win the
race condition in six to eight hours to
obtain a remote route
shell JS Heap spring mentioned
absolutely how about rust uh to let's
see towards an AMD 64 exploit what's
your plan for tomorrow that's right take
back the power this is such dude this
band
this band is ridiculous uh we decided to
Target Rocky Linux everybody's favorite
Linux everybody's favorite Linux Rocky
Linux uh a red hat Enterprise Linux 9
derivative by the
way didn't Red Hat recently get Dunked
On by
Oracle I'm correct on that
right
yeah yeah yeah I am
yeah but they got dunked On by
Oracle or is it IBM either way they got
dunked On by either IBM or Oracle I
can't remember who owns Red Hat I think
it's Oracle that owns Red Hat so it
would have been IBM that does the
dunking but either way imagine getting
Dunked On by either IBM or
Oracle it doesn't really matter which
which one that you get dunked on okay
IBM owns redhead okay so then Oracle did
the dunking okay so so Oracle did the
dunking I was right in the to begin with
okay but either
way imagine getting Dunked On by Oracle
all right Rocky Linux it's open SSH
version uh uh 8.7 P1 is uh vulnerable to
the signal Handler race condition and
it's lib gpsy is always mapped to the
multiples of 2 megabytes because of aslr
weakness discussed in the previous
Theory subsection which makes uh partial
pointer overwrites much more powerful
the CIS log function which is async
signal unsafe but is called by sshd Sig
alarm Handler of the gpsy version 234
internally calls open mream which
malates a file structure in the Heap
which also calls calic and realic and
free which gives us much needed Freedom
with the Heap corruption as a primitive
two file structure maloc in the Heap and
21 fixed bits in the gpsy addresses we
believe that the signal Handler race
condition is exploitable on amd64
probably not in 68 hours but hopefully
in less than one week only time will
tell side note we rediscovered the
Ubuntu 2404 does not randomize the aslr
of its sshd children it is randomized
only once at boot time we tracked this
down uh to patch below which turns off
the SD's re EXA flag this is generally a
bad idea but in the particular case of
this signal Handler race condition it
prevents sshd from being exploitable the
Cy log inside the Sig alarm Handler does
not call any of the Malik functions
because it is never the very first call
to CIS
log defeated by lack of
security let's go let's go the double
defeat going on
here that's pretty cool patches in
mitigation uh the storm has come and
gone the interrupts good things on June
6th 2024 the signal Handler race
condition was fixed by a commit this uh
added to sd8 to penalized particular
problematic client behaviors which moved
the acing signal unsafe code from Sig
Sig D's Sig alarm Handler to Sig D's
listener process where it can be handled
synchronously nice because this fix is a
part of a large commit on top of an even
larger defense in-depth commit start the
process of splitting sshd into separate
binaries it might prove difficult the
backport in that case the signal Handler
race condition itself can be fixed by
removing the commented out async Handler
unsafe code from the Sig the SSH Sig die
function so all you have to
do all you have to do is just patched
open
SSH just handroll your vendor and just
uncommented it there we go uh finally if
sshd cannot be updated or recompiled the
signal hand the signal Handler race
condition can be fixed by simply setting
login Grace time to zero in the
configuration file this makes sshd
vulnerable to deal with the uh with
denial of service the exhaustion of all
Mac startup connections but it makes it
safe from the remote code execution
sucks to
suck uh uh we thank op s's Developers
for their outstanding work and close
collaboration on this release we also
thank drro open wall finally for the
dedic uh we dedicate this advisory to
Sophia D Anan I don't even know who that
is is this a famous person is it this is
she passed away CEO of margin yeah yeah
she died from getting hit by an SUV
dang dang that
sucks well there you go Sophia all right
timeline uh we contacted open s's
developers successful iterations of the
patches and Patch reviews followed we
contacted drro open wall uh coordinated
release date let's
go rip yeah dude rip
damn well that's nice that they have i d
it's very sweet of them to do a nice
little dedication like
that well dang that was a an incredible
read and just an amazing walk through
you know whenever I read these things it
it just highlights one exceptionally
important
thing how dumb I am that's what I feel
like you know I'm out here writing basic
Network protocols doing asky and using
Zig and these people are hand rolling
Heap configurations for Malik and
offsetting into the sshd and trying to
time single bite packets to cause sick
handlers to interrupt the free and Malik
calls dang like I mean Mor of the story
Pamela is not to be trusted never trust
Pam same here I'm so dumb dude it just
makes me
have it just like we've been doing a lot
of security reading Lately from poly
kill this last one with the the the um
the distributed uh harassment of service
yeah a
deos now I now you know how how we feel
watching you program yeah yeah I'm very
fast at Vim maybe I understand this Vim
different differentiation hey if pound
me too dumb yeah I know pound me too
dumb oh [ __ ] you know I'm not sure flip
if you can keep that one in you know
like what I really think about it this
article was brunch for us key sheers
this article was
brunch we just got brunched up pound you
to hey pound you to oh my gosh I guess
that's it take that leave it in or take
it out flip up to you the name hi
YouTube a Jen