okay let's get started hope everyone had
a good weekend
so this this week we're gonna do all
stuff about server security we talked a
little bit about sequel and actually
talked a lot about sequel injection
before and and we also talked a little
bit about how to handle users who are
maybe yet hitting your site too
frequently and trying to log in too many
times and have to deal with the rate
limiting and CAPTCHAs and stuff like
that and so today is gonna be sort of an
extension of that just more kinds of
ways you can mess up on the server
different kinds of attacks and things
you can do to defend against attackers
and mostly focused on safe coding
practices so things that things that you
might be doing wrong that will encourage
sort of security issues that you know to
come up uh or stuff like that basically
yeah so let's get started so first in
admin so there's gonna be a hands-on
workshop with Pete Snyder from brave
who's our first guest lecture if you
remember and the Stanford Applied
cybersecurity Club is going to be
hosting that and that's gonna be you
guessed Thursday it's 6 to 7 in gates
174 and dinner's served right yeah also
we have some new students in class today
in the very back the two people in the
very back are some new students my
parents
they're here they were in town they're
here to watch the watch me lecture so be
nice to them
cool all right so I also want to mention
there have been three students so far
who have found security issues and
reported them and so they've received
extra credit I just wanted to call out a
couple of them that were kind of
interesting there was an XSS found in
access and since access is part of the
Stanford bug bounty program this student
I don't know if I want to say who was it
can you volunteer your own name if you
want to but anyway was was able to
report the bug to the bug bounty program
and was given a hundred dollars for that
from Stanford which is pretty cool and
another student found an XSS in a CS
course website and actually led to
potentially be able to change assignment
scores
which is not definitely not good
and then lastly someone else found an
insecure design that allowed the test
cases in a coding challenge for a job
interview to be revealed so you can sort
of see the test cases they were gonna
test your code against the latter ones
didn't receive any kind of a bug bounty
reward because they weren't covered by
as far as far as I'm concerned or aware
the CS course sites aren't covered by
the bug bounty program but maybe the
coding challenge one will get get a
reward
yeah just a reminder about this you have
a couple weeks left if you're interested
I was completely optional but it's kind
of fun so remember you can do this if
you want cool
so so first let's start with a story so
one we were trick to make 25k security
teams hey toon there's there's a story a
couple weeks ago on on all the tech news
sites that's super relevant for the the
stuff we're gonna be talking about today
so I thought I'd just go through what
this security researcher was able to do
so this is the title of the post
bypassing github so auth flow and what
this person was able to do was basically
they can make a github application which
is able to read a user's github data and
typically there's a there's a prompt
that says do you want it you know do you
agree to to give this application access
to your data and the the user is
supposed to supposed to click this
button saying that they know what what
the permissions are that this
application wants and to give their
consent he was able to find a way to
without any user interaction at all to
send a request to github with the users
cookies attached that granted his
application any permissions he wants it
on the user's github account so just by
visiting this attackers site your entire
github account is just completely owned
and the attacker can access all of the
data all of the private repositories all
the company secrets everything and this
is the highest bounty that github is
ever paid out to anybody so it's pretty
bad really bad it also affected all of
the enterprise github deployments which
are used you know but by companies
internally for it for super secret code
the cool thing is we know pretty much
from the stuff we learned in this class
so far any one of you
found this bug like it's really there
just a couple of extra things I'm gonna
explain for you to get the whole picture
but this is the kind of stuff that you
could do if you wanted to
some people do just spend full time
looking for bugs and and and make a
living from just finding bugs that's
actually how this person found this bug
was he decided he was curious could I
make a living just looking for bugs and
so he decided to spend I think was
either a week or a month just looking
for bugs and github and this was the
result of that so you know um his first
his first time trying to do such a thing
so so it's pretty cool I think I think
yeah I think it's an inspiring story
because let's before we go into how it
works let's recall a cross-site request
forgery so hopefully everyone remembers
this
so cross-site request forgery the idea
is this is an attack where an attacker
can force a user to execute actions
against a web app that they happen to be
currently authenticated with or logged
into so the way that attacker does this
is well the authentication mechanism
that the browser uses is cookies and
cookies have this what we call ambient
Authority model who remembers ambient
Authority somebody want to remind us
what's ambient Authority again come on
this is sad okay all right that's fine
did you give it a shot yeah yeah it's a
fancy word for basically once you have
this authority that you've gained by
logging in and proving yourself to the
site that you're logging into all future
requests to that site automatically have
that authority that you proved once at
the beginning by logging in so all
future requests have that same authority
as that user and that's because the
cookies are attached automatically to
those requests by the browser this is
the same thing we've been talking about
all quarters just a fancy phrase for it
okay so what does this mean this means
that if the if attacker comm is able to
cause an HTTP request to get sent to
victim comm then the browser
automatically attaches the victim comm
cookies to this request right so I
don't think I ever showed a picture
pictorial version of how this attack
works so I went ahead and whipped one of
those up just to review so we have the
client in the server this is the the
victim server here and the way CSRF
works is the user visits the site and
decides to login so a login request is
sent you can see there there's a
username and a password in that request
and then the server checks whether the
username and password is valid let's
assume that it is and so the server will
send back a response and this response
contains a set cookie header that sets a
cookie session ID equals one two three
four and tells the user you log in you
logged in successfully now some time
passes the browser is holding on to this
cookie and so maybe a day goes by or
maybe the user opens another tab while
they're while they're still logged into
the site or something like this and now
they happen to get sent a link to an
attackers web site so they go to that
site they make a request the attackers
site so my HTML gets sent back and
inside this HTML is whatever JavaScript
the attacker wants to include and so
once that page loads that page is going
to send a request not to back to the
attacker server but to the victim server
and this request is going to be to some
sensitive endpoint like safe to transfer
money and they're going to include the
parameters that they happen to know that
this endpoint is expecting so $100 and
let's send it to Malory and the browser
helpfully attaches the cookie header to
that and then the server as far as the
server is concerned it looks like this
came from from a legitimate forum
because all it can see is this request
and everything checks out in that
request so hopefully this is review and
any questions about this this is sort of
standard CSRF okay cool
okay so recall the way we fix this is
same site cookies so same site cookies
allow you to say I only want my cookies
to be attached when the request is
initiated by my own site so if the
request is coming from victim comm to
victim comm then the browser will
include the cookie header but if the
request is coming from attacker com to
victim comp then the browser doesn't
include the cookie header so you'll see
the same site comes
all the time it's a really great cookie
feature okay so now let's talk about a
new thing we haven't talked about before
and I actually wasn't planning to
discuss this at all in this class but
I'm gonna mention it here because it's
it's a requirement to understand the
attack that that this this attacker
found in in github so so the reason why
I wasn't gonna bring it up is because
CSRF tokens are actually kind of
unnecessary these days they are a way to
effectively get the behavior that we get
from same site cookies but but before
same site cookies were thing before
browsers actually supported this whole
concept so one thing we might ask is
what if what what did web sites used to
do before the same site cookie attribute
existed I guess for a long time for for
probably the majority of the web's
existence because the same cycle he's
actually a really new feature for the
majority the web's existence there was
no way to say that you wanted your
cookie to be same site so that meet what
does that mean that means that basically
it was possible for most of the web's
existence that attacker com could send a
get or a post request to your site
victim comm and your cookies would be
attached so the browser allowed this and
sites had no way to opt-out of his
behavior and yet we need some way to
prevent any sent any random site from
from being able to submit forms to our
server with cookies attached so what did
sites do any ideas anyone if you already
notice the S or F token is okay yeah I
know you know anyone have any ideas of
how how we could detect how we could
differentiate whether a request is
coming from from our site or from from
an attackers site yeah look
so you could look at the referer header
will so give you some idea that's right
not perfect for some of the reasons we
talked about in that and that lecture
about refers we're sort of there's some
ways that the attacker can kind of
disable the referer header but it is it
is something yeah there's really
originally no good way no you know
built-in mechanism in the browser or in
any web standards to enable a site to
say they wanted their cookies to behave
in the same site way until that spec was
created until browsers implemented it
and so so the answer to how we how how
we solved this problem is that every
single site had to implement this thing
called CSRF tokens so let's talk about
how that works so basically a CSRF token
is a nonce and remember a nonce is just
some secret unpredictable value
generated by the server and transmitted
to the client and the way we use this
ERF token is that the client must
include the CSRF token in all subsequent
HTTP requests that they make to the
server in order for the server to
recognize that as a valid request so if
you send a request to the server and you
don't include the CSRF token the
server's gonna say this is an invalid
request if the token is missing or if
it's wrong it's gonna be an invalid
request so it's basically some some some
the server's gonna give some value to
the client and say all your requests
that you send in the future must include
that value or I'm gonna I'm gonna reject
them ok so far so good
ok so this is how you typically include
a token so you you would include an
input element in your page and there's a
type hidden' which is kind of cool so
you can include a hidden form element in
a form and let's give it the name CSRF
token and give it the value of the of
the actual token and so because this is
an input field when our form is
submitted
all the inputs get sent to the server as
part of the form and this is going to
get included as one of the of the form
fields it's as if the user had typed
this into a form field but of course
they don't have to do that because it's
gonna be included automatically for them
and so how does the server actually
generate these tokens so there's two
approaches you might use one is you can
just sort of randomly pick up pick a
value a nonce and so you know pick it
randomly turn it into a string and then
to use that as the value or you could
generate it based off of some
information in the request itself like
the session ID okay so now we have this
token the question is how do we use it
what does it actually give us how does
it actually protect us against CSRF so
let's look at how that how CSRF token
works
this should hopefully make it clearer so
we have a client they show up to our
server and this is similar to before so
they're gonna send a login request with
a username and a password the server
checks that it's valid let's assume it's
valid so the server sends back this is
very similar to before it sends back a
set cookie header giving the user a
session and it tells them that login was
successful but you'll notice that also
included here an extra bit of HTML which
is the CSRF token that it chose for the
user in this case we chose a really
insecure one ABC but I need to save
space on my slides so so so now that
this page includes this token and so
what's gonna happen is if the client
interacts in any way with the page that
was sent back let's say it submits
another form now to do a bank transfer
write this token is going to be included
in that request right so so sometime
later the client decides to actually
submit a transfer and so you'll see here
that the browser attached that attach
the cookie like usual and then we have
the same form fields as before so we
have $100 going to Bob but now there's a
CSRF token field included which is it's
basically the client echoing back the
same token that it was given at the
beginning now the server checks that and
says is that the same as the one I gave
you before if it is then it's gonna say
this is a valid request and send back a
page saying the transfer was successful
right so so far so good right ok so now
how does this protect us against an
attacker you can imagine so this is the
same situation as before we we user logs
in with a username Alice and a password
it's valid we get back the same
pages before and now some time later
they happen to visit an attacker site
the attacker sends back some HTML and
when that page loads that that attacker
page sends a request to the server and
this request is coming from this
attacker attacker controlled this and so
the question is what does the attacker
put in here for the CSRF token field it
should be the ABC that it was sent from
before but because this form submission
that's happening here this post request
is coming from the attackers JavaScript
the attacker actually has no way to read
this input out of the victim com page in
order to do that it would need to be
able to reach into the Dom of victim com
which is a violation of the same origin
policy okay so basically this server
here the victim com server when it looks
at this request if it sees that the CSRF
token is the same as before it knows
that this request must have come from
from the HTML and the JavaScript that
it's sent down in the original page and
not from some other website that the
user happens to be on right so even
though the cookie is here is valid right
so the this attacker happened to send
this request right and the browser
attached the cookie so if the server
would just to look at the cookie you
would think that this is actually the
user because they are they are logged in
here but the CSRF token is wrong and so
it's gonna reject the request right yeah
so that's right so if if the server sees
the CSRF token coming coming back from
the client and it has ever given that
token out to the user before it we need
to like remember that and treat it as a
valid like I could open up 10 tabs on a
site so it's not enough for the server
to remember the last token it sent out
it has like remember all of them right
and so typically what we actually do is
we we don't want to we don't want to
just generate a random value so if I go
back to that slide where we were showing
the code here this is not a very good
approach because it means that the
server has to basically remember every
single CSRF token that it's ever sent to
the user for some reasonable amount of
time
and better ways you can just say look
whatever session idea I gave the user I
already set that in a cookie the user
has that in their browser right and so
when they send it back to me if I just
can compute what the token should be
based off of that and I combined it with
a secret that only the server knows and
use this H Mac function which is you can
think like a hash it's basically hashing
the session ID with some secret that the
server has and what's great about this
is all the server has to remember is
that this one secret and the client is
going to provide them a session ID in
the request as well as a token and as
long as the server runs the same
function when it's verifying the token
as it did when it's sent down the token
which is this function here then it
should check out it should be it should
be exactly the same and so the server
can actually be completely stateless it
doesn't need to remember any of these
tokens and it can still verify that
they're correct yeah that's okay yeah so
so it's true it's not completely random
from from page to page it's gonna be the
users gonna be getting the same CSRF
token as long as they have this session
ID it's okay though because we're
assuming here that the user is not going
to share this with anybody and the
attacker can't guess it and that's all
we care about yeah
it's it's it's similar you you know it
is a very similar concept the difference
is just where we're using it so the
nonce field that you're talking about is
from CSP and that's where the the server
was telling the browser in a header
don't run any scripts unless they
contain this nan says an attribute and
here it's actually the server that's
saying the server is basically saying I
won't accept any form submissions unless
they include this value that I
previously told to the client yeah but
it it's very similar concepts yeah cool
are there any questions about this this
is important to understand the github
attack which is really cool so yeah ask
questions if you if you missed anything
so the reason why I've questioned yeah
that's correct yeah so if the same site
cookie header was sent then then this
attacker requests right here that the
attacker sent wouldn't even include the
cookies and so this wouldn't do anything
yeah so you could use both together if
you're like one one actually one use
case for still using this as if you're
if you have users that are on really old
browsers like maybe you're building an
enterprise app or something like that
and you care about this the other place
where you might see this is if you're
using a web framework like Ruby on Rails
or I guess I don't think Express builds
it in but it's a it's a popular package
that people include because like I said
until recently there was no way to
protect against this so literally every
site out there on the internet had to
implement this this protection at their
in their own app code basically although
the framework might give you some
affordances for you to make it easier
but um yeah the browser didn't help you
at all here so if you're looking at code
like at a company or at an internship or
when you get a job after after college
you very well might see CSRF token still
because it's just probably in a lot of
code bases still yeah
so CEO surf tokens are perfectly
effective
yeah they completely like this basically
as long as you're choosing this token
from a big enough range and you're
choosing it completely randomly then
it's impossible for the attacker to
guess it right they can't like send like
a you know 20 billion requests with all
possible tokens it's not it's not
feasible so this is a very very
effective defense same-side cookies are
just introduced as as a way of saying
wait a minute why do we have to have all
this logic for the server to generate
this this nonce and then check it and
everybody's doing it separately and own
if you forget to do it on one endpoint
then your app whole app is vulnerable
why don't we just say add one attribute
to the cookie when we set it and just
say same site and we're done you know
like it's just a much simpler solution
much less error-prone yeah I don't think
that the attacker can control the refer
header to that degree but they can they
can omit it they can cause it to be
omitted and then the server would have
to decide what to do
is it omitted for malicious reasons or
did it did it get omitted for it because
the browser is trying to be more private
like it's unclear what the server should
do does that answer your question
cool
cool okay so so now we understand CEO
surf tokens great so let's talk about
the attack so I think I think we have
everything we need for now to explain it
okay so so this is the prompt that a
user sees when they're being asked if
they would like to give an app
permission to access their github
account and if they decide they want to
give the permission then they can click
this authorize button here and for this
demo he only chose to get like a very
minimal set of permissions but this
could have contained like a lot more
prompts potentially for more more access
okay so what is the flow like when
you're actually authorizing an
application so say that some third-party
app once access to your github account
for some legitimate purpose the way it
works is it's gonna redirect you to this
URL here github.com slash login / o auth
slash authorize and it's going to
include some information in the query
string saying what app is owned by that
developer so you're gonna get a prompt
for that app saying this app once here
once access to your account and so
you've when you when you go there you're
gonna get this authorization page that's
the page we saw before it's this page
okay so if the user chooses to grant
access to the app and they click the big
green button authorize on the page and
then the user gets redirected back to
the third party application and github
when it does that redirect back it
includes
a query something in the query string
which is basically a github token that
the application can use to then access
your data by sending requests to github
like out-of-band right so this token is
basically like the password to your
account effectively for for this app
right okay so that's the flow so how is
the authorize button implemented so it
turns out that you just did it as a form
so the entire button is just an HTML
form with one button in it when you
click the button you submit the form and
that form also happens to contain a
hidden form field with a CSRF token
inside of it okay so this is again this
ensures that a random attacker can't
just effectively click the button for
you click the authorize button for you
by by sending a post request to this URL
so when their server receives these
posts it's going to Val
that the CSRF token is correct and then
if it is it's going to assume that the
user must have clicked this button by
visiting the page directly and this
request could not have come from some
attacker site that's what the CSRF token
gives us one interesting detail is the
form actually submits to the exact same
URL that the page is loaded from does
that make sense
so you the apt redirected the user to
this URL and that loaded this sort of
form with the big green button on it and
then when you click the big green button
that also sends a request to the same
URL the only difference is that the
first request was a get request and the
form submission is a post request so the
server can look at the HTTP method and
then just do different things depending
on what the method is that's an
interesting detail to keep in mind okay
so this is the full flow so we go to an
app example outcome that we want to
authenticate with or login with login to
get hit with and it's gonna set us back
a page with a login with github button
and say the user clicks the button the
button goes to this URL here login
ooofff authorize and that request goes
to github there might also be like I
said some query parameters here that
specify exactly what app we are trying
to give access to our account but I just
I didn't room in the slides and you'll
notice here the cookies attached right
because this is a get request the
browser navigated there so of course the
cookies are gonna get attached right
okay so we're logged in to github so get
hub is now gonna be like ah okay hi for
us
would you like to authorize this app so
it sends back that page and that page
includes the CSRF token so say the user
clicks authorize now we're gonna post
the form is going to get submitted via a
post request to that same URL cookies
attached CSRF token is attached right
and so the server github can check is a
token valid look it is okay great so we
will send back a successful response to
the user and we'll redirect them with
this 302 which is a HTTP redirect will
redirect them back to example.com the
app and will include a github token XYZ
that the app can use to access this
users account now and so then the user
their browser gets redirected to the to
the to the same page but now with this
little parameter attached and that's the
whole flow so that's how you log into
github this is actually how you log into
most apps like if you ever see login
with Twitter login with it's something
like this basically right this is the
effective idea so the this this token is
sort of the key to your account that the
app can use okay so this seems fine
right like where's the problem where's
the bug seems like there's no problems
here as long as we're actually checking
the token okay so let's see what
actually what they did so so this attack
this some security researcher was able
to get a copy of the github source code
by doing an enterprise trial so he like
pretended he was a company downloaded
their source code and then it's very
it's sort of obfuscated but found he
found some code online which I office
gated it to quite a degree so he's able
to serve just like a look at the Ruby
code that they wrote and he found this
section in there and so this is the
section that implements that
authorization flow so let's see what
it's doing so it says we have this URL
here login ooofff authorize and any time
a request comes in to that URL and it's
a get or it's a post then we want it to
go to this controller and you can think
of controller is similar to handlers in
Express so it's just the function that's
gonna run to handle this request and so
and so all gets and all posts to that
URL are going to get handled by this
function here and so this particular
function happen to have an if-else check
where we checked if the request is a get
request then we're gonna serve them back
to HTML with the big green button on it
and if it's a post request then we're
gonna check the CSRF token and if it's
all valid then we're gonna grant the
permission to use to use the application
again so far so good I don't see any
problems with this does anyone see any
problems with this and problems right
yeah I don't I don't think any of this
is is bad so far okay one more thing I
need to talk about and then you'll
you'll see what the problem is so
there's this thing called an HTTP header
quest so a head request is basically
like a get request the semantics are
if you send ahead request to the server
the server is supposed to treat it like
a get request it's supposed to go and
get whatever resource you asked to get
and then before it sends back the
response to you it just omits the body
it sends all the headers and it just
doesn't send you the actual page that
you asked for so why is this useful
you'll typically see head requests he
used if like your browser before it
downloads a file maybe it wants to see
is this a huge file what's the size of
this file so it could send a head
request and then it'll get back at the
headers and not the file and to look at
the content length header and be like oh
this is a gigabyte file ok but maybe
that changes my strategy for how I'm
gonna download this or something right
so that's a common thing but it is
relatively niche and relatively obscure
most people aren't using head requests
on a regular basis and so because of
that Ruby on Rails which is the
framework that github used
it knows that most people aren't going
to bother to implement a head request
and so it's like well we can just do
that for you basically we know what to
do when there's a head request we
basically just want to run the code that
we were gonna do for get requests and
then when that code is ready to send
back the response we'll just tweak the
response we'll just get rid of the body
for them and send back just the headers
right and so the framework is basically
like we can help you out that it's so
similar to get so why don't why not just
handle it for the developer right most
developers would forget to do head
otherwise right mmm yeah that's great
yeah yeah exactly so the reason why we
can do this for head is because a get
request isn't supposed to change
anything it's not gonna make any it's
not gonna be um I'm modifying the
database it's not going to be
destructive in any way you can repeat a
get request as many times as you want
and nothing is going to happen so so
it's no big deal to send it to send a
head request whereas yeah you could not
do that with a poster with any other
method cool any questions about head
okay so that's how that's how that
request works cool so so so Ruby on
Rails like I mentioned it automatically
is going to handle head requests for us
so it does that by routing any head
request that comes in to the same place
as it was it would route get requests
and an express actually does this too so
it's not just the Ruby on Rails thing
and so it's gonna run the same
controller code that it would hand it
would run forward get requests and then
it's just gonna go ahead and delete the
response body when it sends back the
response and so this is a time-saving
feature for developers it's usually the
right behavior it's very handy that the
framework does this for you there's one
problem with it which is that it's a
slightly leaky abstraction a leaky
abstractions is just an abstraction that
doesn't perfectly hide the complexity
from the developer so most of the time
the developer doesn't have to know this
exists except for in this one case here
where in the controller which is again
the handler the function that's running
the app in a check request dot gets
question mark which is that's a ruby way
of basically saying this is a boolean
anything with a question mark on the end
of it is boolean in Ruby it's like
you're asking it sort of like is get
basically um anyway so so that actually
returns false for head requests this is
kind of unexpected because the developer
said that they wanted this controller to
only run for get requests and post
requests and so they may have made an
assumption that I'm only going to ever
get a get request for a post request and
so if they have an if statement in their
code like like this code happened to and
it's checking this then their in this
case there's going to be a third value
there's going to be head requests coming
through that same code path and so let's
see what goes wrong when we do that so
look at the code again again the
developer said I only want get requests
and post requests to go to this function
and so they thought oh okay so this is
gonna handle the gets and then the else
is gonna handle the posts right but the
head requests ended up in here as well
right does every see that okay
yes yeah so yeah this is this is only
possible because they decided to sort of
handle get and post in one controller
function basically that's a really good
point yeah this wouldn't happen
otherwise
so one important point is so you might
think okay so what's the big deal so
they're gonna somebody makes a head
request to the server okay so we end up
in this case there's still gonna be us
they're still not gonna be a valid CSRF
token right because remember the else
case this is the the case where we're
about to authorize an app so this is
definitely gonna check that the CSRF
token was included so an attacker still
can't find out what the token is because
it can't it can't violate the
same-origin policy and go and read that
input with the token in it right so so
how does this actually turn into an
attack so what happens is the CSRF token
handling wasn't actually done directly
in this else case a common thing that
frameworks will do for you and in Ruby
on Rails is is a prototypical example of
this because it sort of tries to handle
as much as possible for the developer
what it does is it says okay we know
that the user wants to validate CSRF
tokens anytime there's a post request
coming through so what it does is
basically before any of this controller
code even runs there's another function
that runs in rails that says is this a
post request if so check the CSRF token
if it's invalid return an error page
before this code would even run right
and that's how you get CSRF token
checking in rails and so the problem was
when a head request comes in that's not
going to trigger that CSRF token
checking code right it's a head request
not a post request so that's that that
gets bypassed then we end up in the
controller here and then head doesn't
match this if case so it runs this code
and then at this point we're not
checking the CSRF token we've assumed
that's already happened that rails took
care of that for us and so literally you
can omit the CSRF token and and Gabe's
gonna say oh that looks legit to me and
authorize the application so yeah I mean
basically you just send a head request
with to the app you want and then that
user just automatically accepts that
on their account one request very very
very elegant yeah so let's see what that
looks like in action so this is is now
fixed this was two weeks ago yet have
actually responded to the hacker one
report remember hacker while I was what
miles talked about last time that's
where your poor bugs they responded in
eight minutes and acknowledged it and
they were like yep yep we confirmed it
it was very easy for them to test it
they just like sent ahead it goes oh
crap
and then they acknowledged it right away
and then they had it fixed out in three
hours like there's a very very severe
issues so they were they were on it
right away but props to them for being
so fast yeah so this is fixed as of like
two weeks ago but this is how how the
attack would have worked so you visit
the attacker server again remember this
is really easy to do you just click a
link right you end up on you end up on
an attackers page you get back some HTML
and that HTML causes a request to go to
github it's a head request to authorize
and then there's a app ID attached here
to the to the URL and your cookies are
sent and there's no CSRF token in sight
and the server just doesn't doesn't
bother checking it just sends you back
your authorized and then of course
that's going to redirect you to the oh I
guess I messed this up this should say
attacker comm so it redirects you to the
attacker calm server with get up token
just like that
yeah pretty crazy interesting yeah I
mean it should I I'm not too familiar
with with the kinds of stuff that people
are using like in production in the real
world on their on their applications
like there's all kinds of there's like
hundreds or thousands of security
vendors I'm sure some vendor claims that
they can do this I don't know I'm how
effective it is I would I would guess
the hard part about that is like it
would need to you'd only catch this if
you were actually sending it with a
valid cookie so that the the fuzzer
would have to be smart enough to to to
like figure out how to send like a
mostly legit request if it could yeah we
catch this yeah did you of course Mina
so Express is very much modular so it
doesn't actually do any CSRF checking
out of the box but there's like a common
set of like five or ten packages that
everybody who's using Express pretty
much also installs and one of them is
called C surf which is I don't know some
weird plan on CSRF and and so that that
package would if you used it in this way
it would you would configure it usually
to only check against post requests so
you'd have the same problem yeah if you
were purely relying on like you know on
that check on post requests now we'll
get to it in a sec but there's other way
there's actually other reasons why this
would be less likely to happen in
Express I'll mention I'll try to mention
it at the end of the next slide so let's
think about how github could have
prevented this does anyone have some
ideas yeah yeah that's a super easy way
to do it yeah that's like a great way to
code defensively basically don't assume
that you know that though the two
options are get and post just be like
I'm paranoid I don't know what's gonna
get called here at else else if requests
post and then I would actually suggest
also throwing in and else at the end
just think I don't know if there's
actually code after this this section
here but you wouldn't want that you
wouldnt want to just skip both of these
cases and then just run like other code
afterwards in the in the head case
so I would actually say I would say do
this if it's a get do this if it's a
post throw an exception if it's anything
else this is this is a very sort of
common paradigm you'll see if you're
coding defensively you'll basically want
to say I expect this to be the case if
it is not and that would be really bad
for some reason like if the if this is
not the not what I assume to be the case
then you want to just sort of bail out
as soon as you can you want
just abort crash the process because the
nice thing is if you crash here sure
that means now that's you know some
attacker has now figured out if they
send ahead request to your server they
can cause it to crash right that's still
much better than the bug that could have
ended up with by not doing this and the
nice thing about crashes is typically in
production right you have like hundreds
or thousands of instances of your app
running and if an attacker can crash one
of them or many of them sure they affect
the availability of your site in some
way but you're going to get an email or
some kind of an alert right away saying
there was an exception in production and
you're gonna look at it and you're gonna
say this case was never supposed to run
ever and it just did ok one of our like
my assumptions were violated in a very
serious way and you'll immediately sort
of debug it and be like oh head requests
can come to this code and you
immediately then you know figure out the
problem and fix the root cause I'm so
asserting that your assumptions are true
is a really good idea like check to see
if it actually got validated yeah I
don't know if rails is gonna expose that
and enough detail to you because it is
being handled it like another level but
yeah if it did you could do that yeah
any other ideas there's other there's
many other ways we could have let me go
back to the code actually any other
ideas because it's such a sensitive
things like your entire github account
yeah there's something to that I mean
you're basically suggesting being
explicit and less magical and I'm a fan
of this as well in general I mean so
it's a trait it's always a trade-off
like if you if you require the user to
be explicit and they forget in one place
right or you you have a new developer on
your team who just joined and they don't
know like they're just learning rails
for the first time they've been coding
in something else they're gonna you know
you're more likely to make a mistake
maybe on the other hand
relying on magical behavior that you
don't fully understand can bite you as
this case has demonstrated so it's it's
a trade-off yeah mm-hmm yeah exactly
yeah so I wouldn't have tried to be so
clever and be like oh I'm gonna I mean
the nice thing about what you're
suggesting is what you're saying doesn't
even require them to require to use two
different URLs they could still do this
thing where they're they're using the
same URL for both but they they could
tell rails that they want a different
controller forget and then for post so
they have two different functions one
for get one for post and and that would
have that would have solved the problem
yeah so one of the nice things about
Express I'll mention it now since this
is actually totally relevant but with
express you usually say app get app top
post you register your method upfront
and you can only pick one you can't do
this like oh get and post and whatever
you can't mix the two um the exception
is there's this thing called app dot use
in Express and with that you're
basically saying I want all HTTP methods
to come to this function and get handled
by this function at which point you now
like all bets are off you have to
basically handle every method so an
express are either handle every method
or you handle one method and even though
it's so even though it is automatically
sending head requests to the get handler
there's nothing that can go wrong in
that case because there's no post code
in that same path that makes sense okay
keep going
oh did anybody have any other ideas for
how I could have prevented it before you
move on okay so yeah we talked about
most of these oh yeah and then obviously
the most obvious one of all that no one
said is we could just have used the same
side cookies instead of CSRF tokens and
then we wouldn't have had to deal with
any of this complexity but yeah so using
a separate controller would have worked
using separate URLs for the
authorization page and the form
submission endpoint would have prevented
this issue changing else - else--if
request posts to be very explicit and
ensure that
head or any other unexpected methods
would wouldn't be treated as post would
have worked yeah those are the things
that came up with um so yeah this is how
you would do the explicit check you just
already met kind of mention this but I
would I would recommend throwing an
exception if it's if it's not a get or a
post and just crash the app it's a
catastrophic case you're not a key
you're not you don't want to try and
recover from this that's a good question
so yes let's look at that let's look at
the legit case ok so this is the legit
case so you're saying that basically
your concern is let's see at the point
where the user clicks the login button
and this request goes to github your
concern is that the cookie wouldn't be
attached if it was the same site cookie
right
you remember same site has two modes
they were strict and lacks yeah so if
you were using the strict mode then
you're correct that because this request
was so strict basically says I don't
care what kind of request it is if if
the user ends up on my site and it came
from anywhere don't include the cookies
that's like extreme paranoia mode right
the lacs mode says if it's a if the
entire browser is getting navigated to
the page like the top-level page is
changing which is what's happening here
the user clicks the login button and the
whole browser just goes to github right
lac says it's okay to touch the cookie
in that case and that actually means
that this would work still yeah but
don't they always throw permission
probably better understand the question
oh yeah there is no way to grant
permission at all without the going to
it going to a top level Google page yeah
you're right because the cookie wouldn't
be included yeah I think you
okay so let's go back to where we were
here yeah okay so now let's think about
ways that rails could have prevented
this so we talked about how github will
get up could have done what could the
framework have done what could they
design differently to prevent this kind
of an issue I feel like they kind of
laid a trap for their for their users in
a way the ideas Oh interesting
so so if you did a token check for head
requests that means that that would mean
that that no one could send a head
request to a URL unless they had first
loaded a different URL and gotten a
token out of that response right so you
could require that of yourself your
users but it is changing the semantics a
little bit so I was like normally I
could say I could send a head request to
get the homepage of the site and I don't
have to know anything about this site I
can just say give me the homepage and if
you if you required a CSRF token in that
case then I would first have to like do
a get request for the homepage get the
response find the token include it and
then send the head which defeats the
whole point of sending the head right
yeah but it could work it's just a
complete different like set of
assumptions you're making yeah
[Music]
yeah so you think that you think
checking get directly is such an
uncommon thing that we should just
discourage it yeah I don't actually
don't know how common it is I mean from
my experience writing code in a note and
Express I do sometimes check the method
like for legit reasons so I would be
maybe a little bit annoyed if I had to
always be like writing in all caps or
something to like do it but it would
certainly they would have prevented this
case yeah you're right I agree with you
yeah did you have another one the
browser the browser consent head
requests for like its own reasons like
for before downloading a file or another
site can just cause a head request to
get sense it's similar to get so it can
just cause it question yeah you have to
talk after class but I'm not
understanding the question okay it's I
will talk about it after class yeah okay
so I had some ideas for ways rails could
prevent this so I mean one thing you can
imagine is just don't handle this
automatically for the user force them to
handle head requests themselves that's
one option I think that if you do this
then probably no one is going to be
supporting head requests and their sites
so you kind of lose lose that benefit
but that's an option another idea is you
could set request get to true even if
it's a head request and this is lying to
the developer basically the framework
could lie to the developer and tell them
it's it's a get request even though it's
a head request I would argue this is
actually fine in a way because the
developer when they wrote this
controller said I am prepared to handle
gets and posts in this controller so we
should assume their code is only going
to be checking forgets and posts so
sending them head
kind of a violation of the abstraction
that we've created here it's like
leaking out some random implementation
details that we don't want to leak out
so if instead pretended that the head
was a get then the now the we know the
developers code is gonna run correctly
because we're only giving it gets and
posts like we act like they asked for
right and then after we sort of get the
response we could then delete the body
and handle it for them and now the
abstraction isn't leaky right it's just
this do people know what I mean when I
say leaky abstraction who's heard that
term before who doesn't who doesn't know
I can explain okay so the idea of the
reason why we make abstractions is
because we're trying to hide some
complexity away from from the developer
we're trying to simplify the amount of
state they have to have in their head in
order to program something it's like the
less sort of complexity that they need
to keep in mind the more likely they are
to write correct code and so ideally
abstractions they eliminate unnecessary
complexity and they only expose the very
essential complexity that you that like
you can you can hide too much you can be
like you know you can have a class which
or a library which just is has one
function it's like do the thing right
and then well that doesn't let you
configure anything how what if I want to
do the thing differently like there's no
options - so you want to expose some
complexity but you don't want to don't
want to to expose any sort of extra
complexity that doesn't is irrelevant
for the developer to solve the problem
that they're trying to solve and so a
leaky abstraction is one where it like
mostly works it mostly hides the
unnecessary stuff away but then in some
places like bits of the implementation
or bits of details at the developer
ideally wouldn't even need to know about
leak out in in small ways and then
violate that I was like break the
abstraction make it less make it a less
useful abstraction because now that
developer has to keep these edge cases
in their head in order to use it
correctly like that's what happened here
like this abstraction was like oh it's
just you know we're gonna we're gonna do
this clever thing that the developer
won't need to think about and then
whoops actually they need to know about
it they need to know about ahead
requests so you didn't actually make
their life simpler in fact you you just
cost them 25k and potentially a lot of
you know user data lost so yeah that's
that's leaky abstraction okay so another
idea
right okay so yeah basically yeah I
already mentioned this and then here's a
crazy idea you could use a more strongly
typed language like Haskell or something
it's a part of the reason why I mean you
could argue part of the reason why this
issue happened is because there was no
way to enforce that every case that
could possibly get given to this
developer's code where there was no way
to enforce that the handle each of those
cases in a more strongly typed language
you could actually have a compiler error
if they only said case get case post and
they forgot one of the cases that you
might call their code with this slows
down like development arguably a lot and
you know people don't like it and people
people usually use these these looser
languages for a reason but that is one
solution yeah Oh like I say like like
look at the function and see if it's
English
I mean in Ruby I guess you could that it
might have some kind of introspection I
know in JavaScript you can literally to
string the function and then then you
have a string version of the function
and then you could parse it yourself
with your own JavaScript parser and see
if it actually you know accesses request
dot head or something like that I don't
recommend that there may be yeah I mean
other than that grouse approach I can't
think of a way to serve in advance know
that it's going to handle it yeah okay
so so some lessons that I think we've
based on the different possible
solutions that we've proposed I think
there's some lessons we can sort of
glean for how to how to sort of prevent
these kinds of problems in our code or
in our libraries that we write one big
common theme that you'll see all the
time in security context is that we want
to try to reduce complexity complexity
is the source of so many security issues
and when we have abstractions that we're
trying to hide complexity from the
developer and and and so yeah I guess I
already said this the more edge cases
that an abstraction has the leakier that
it is so the more complexity you have
they also have
more sort of interactions between
different components in a system and as
sort of you get like this multiplicative
effect where like if you introduce a new
component you might think I'm just
adding one thing to this system right
but if the question is not how many
things that I add to the system the
question is how many things did the
thing I just add how many things cannot
interact with in the system the system
has 500 other components and I added
this one in a way that it could
potentially interact with any of the 500
right then I've actually it's not it's a
much sort of scary or change then
something that I just added in a very
isolated way and I know it's only
talking to this one other thing so
complexity can come from like lots of
places and it's usually the enemy of
security also explicit code is better
than clever code so I think this is the
kind of thing that you get you get
better at over time in your career at
least that's how it's been for me where
um like at first it's really fun and
exciting to like try to like write like
a really clever one-liner and like I
look at all the functionality I packed
into this line like I'm such a good
coder I'm gonna impress all my
co-workers and my classmates like
because they're gonna look at it they're
not even gonna know what it's doing
aren't I so I'm so cool right I must be
more you know elite than everybody else
and as you go through your career and
then you come back to code and you're
like this is terrible who wrote this and
then you look at the get history and you
realize you wrote it and you were too
clever so that literally your self can't
understand it like a month later then
you serve after this bites you enough
times you just start saying like okay no
no no I'm just gonna unroll this code
and make it much more verbose and much
more like dumb you know just much
simpler it's gonna do this then this
then this and it's gonna look uglier but
it's gonna be understandable so yeah I
think I don't know just the thing that I
think most people tend to write less
clever code as as their career goes on
that's what I've noticed yeah and then
the other another idea is to fail early
so if an assumption that you have is I
guess this is mixing it to up fail early
the idea is basically if something is in
a state that you don't expect it to be
in then just crash or throw an exception
don't try to like
go onward don't don't try to to handle
it and like one example where this comes
up is you can you can attack you can do
this thing in nodejs where you can say
when an uncaught exception happens in my
program I want this function to run to
handle it and so what you can do is you
can sort of say I a handle it sort of
like a top-level try-catch you're like
any exception anywhere just go like if
it's not handled at a lower level I
wanted to run this function and what
people used to do is they would just log
out the error and then not crash the
process they would just keep it running
right an idea is like oh well you know
like it's probably fine like maybe that
would that was an exception that wasn't
a big deal like it was let me just log
it I'll fix it later
keep the process running problem is you
don't know where the error happened you
don't know what like multi-step process
you were in the middle of and you threw
an exception in the middle of it and now
some state that you set up and we're
expecting to get cleaned up later you
didn't you're not gonna get around to
doing that now because you bailed out
halfway through so rather than try to
resume sorry rather than assuming it's
fine to keep going you should just crash
the whole process because you don't know
what state it's in now and so crash the
process and then usually you have some
other process on the system that will
just reboot the node process or whatever
server process and start it from scratch
and you can if you have more than one of
these you can handle handle crashes
without any downtime for your users yeah
so that's it's a good idea and then
lastly code defensively so assume your
assumptions are going to be violated and
verify them upfront and and don't assume
that your function is going to be called
with the correct arguments for example
right it might not be so any questions
about these lessons didn't make sense to
people if you just you can disagree if
you want I mean they're they're not
they're not like hard and fast rules
it's a lot of it is taste and just like
trade-offs
everything is trade-offs but these are
some things that I think are useful
mm-hmm
I guess yeah
that's true yeah we call that security
through obscurity though and we don't
encourage it yeah
okay so I'll skip this I was just gonna
this is gonna go through the sort of the
things we talked about and try to
associate them with each of the lessons
but I think that's not necessary okay so
yeah the next thing I wanted to oh yeah
question hmm yeah so so that's a really
good question so I guess yeah what I
said before is is not complete so if the
error that happened is expected like you
say here's an example I'm going to make
a query to the database for a particular
user with a certain ID number right and
then I may get a user back I mean not
because maybe that ID doesn't exist as a
developer I'm actually expecting that
this may fail sometimes because say that
the ID number that I'm looking up is
provided by the user the user goes to
some URL you know slash users slash 25
that could be you know the user could
type in a tight make a typo and go to a
URL where that user ID doesn't exist so
if I'm writing code to go get that user
out of the database and and the idea I'm
looking up is provided by the user
well that user might not exist so I
should in my code expect that that may
return an error to me and say there's no
user with that ID in that in that case
because I was expecting that error it's
totally fine for for me to return like
return an error code to the user give
him a 404 error and say no one with that
idea exists and to keep the server
running I shouldn't crash you shouldn't
crash the server in that case because I
was an error you were expecting and you
wrote code to handle it right and and um
the difference between that and what I
was talking about before is if an
exception happens and you didn't expect
it to happen it's not appropriate to to
just like log that out and then keep
going because it could anything could
have gone wrong you don't know what you
weren't you actually did no code to sort
of clean up and handle that exception
you weren't expecting it
right does this thing should make some
sense okay cool cool okay so yeah so
let's talk about the next topic which is
bad API design so this is a fun one
so the idea what this is just that
there's there's so we mention all these
different ways that we could we could
try to write better code clean code and
avoid you know tricking ourselves and
being defensive and all this stuff
um but sometimes an API that you're
using is just badly designed and it's
set up in a way that is likely to
mislead you right some ways this can
happen is say that the default
parameters that the function they're
calling assumes are insecure and the
only way to use this function securely
is to actually pass in a bunch of
options to make it work the way you want
I would argue this is like this is bad
because most users if you know they're
gonna just call it without any options
and then they're going to be running it
in an unsafe way and so we want the
defaults to be secure we want the
defaults to be reasonable and so this is
one way that an API can be can be poorly
designed you'll notice that it's
possible to use it correctly you might
actually pass all the correct options
but you're just encouraging you're
making the easy path the the unsafe way
um another thing you'll may see is
polymorphic function signatures so this
is where a function takes in multiple
different types of parameters and
effectively this one function is doing
like one or two or three or four
different things and they're did it the
way that it decides what which one of
those things to do is based on the type
of the parameter like maybe you pass in
a number it does one thing you pass in a
string it does something else or if you
pass in an extra argument it there's a
completely different thing right you
don't want to bundle too much
functionality into one function I are I
would argue because it's it's harder for
the user to use correctly and especially
in a loosely typed language like
JavaScript well we'll talk about some
examples and this is a really really
wild one I've seen this before actually
expressed as this you can actually have
functions where they do a different
thing based on the number of arguments
in the callback function I'll show an
example of it it's called function arity
okay so here's a really common example
you if you've ever used jQuery this is a
jQuery is kind of old these days it's
not cool anymore but it's actually still
really we're really widely used though
still growing I think too but anyway it
has it's it's a very good example of a
very polymorphic function so depending
on what you pass in the type of what you
pass in it does a completely different
thing so if you pass in a string that is
happens to be a CSS selector to select
an element on the page like in this case
button then this will return you the it
will return you a jQuery object that
wraps that Dom node that matches that
right actually it could be it could also
return you an array of like multiple
nodes if there's multiple buttons on the
page you can also pass in an HTML
element and then it will wrap it with
the jquery wrapper you can pass in
another jquery object and then it clones
it so that's this is a copy operation or
you can pass in some HTML and then it
will parse the HTML and create a Dom
node with that HTML inside it you'll
notice here this is really wild one
because this is actually a string and
that's also up there a string so we're
actually doing two different things even
though it's exactly the same function
prototype we're actually deciding
whether it looks like HTML to us or not
and doing a different thing that's
pretty wild
also happens to be really insecure in
practice and then the other last case is
you can pass in a function and then what
this does is this actually runs this
function when the whole page is finished
loading so they've met packed all this
behavior into this like one dollar sign
function and it's it's handy for
prototyping stuff I mean it's really
fast it's like that one letter to type
it's a dollar sign you know it's like
convenient but it's doing like five
different things depending on what you
pass it this is what I'm talking about I
say polymorphic functions so oh yeah
here's the here's the Express case I was
talking about so this is really wild so
um so this is a middleware a middleware
is I guess I haven't explained this yet
in the course but basically we've been
using app get an app dot post and then
having these functions that run to sort
of handle a get or a post to a
particular URL there's this thing called
a middleware which is sort of a more
generalized version of that where what
we're saying here is just call this
function for every single request
yet posts head all of them all the
methods and all the URLs just always
call this function and this is actually
where you would do your CSRF token
validation as an example right you would
check if it's post and then do your
validation or whatever um and what's
really useful about this too is you can
call next if you don't want to actually
handle the request here so typically
what what would the way these
middlewares are used is you'll you'll do
some logging you will do some useful
operation and you'll call next and then
eventually your your different handler
will get run like yet or a post for a
different URL path am i confusing people
basically this is the way to run a
function before every request it really
is a way to do that but if you pass in a
fourth argument to the function then
this is a completely different thing it
then becomes an air handling middleware
and what this does is if an exception is
thrown in any of your handlers for any
URL that you handle then express looks
for the first time you call the app dot
use with a for argument function and
calls that and then that's supposed to
handle the error right so basically
reason why this is bad is like in this
case look I sent back a response to the
user and I didn't even use the error
object right so maybe maybe a developer
who's going through the code base will
look at this function and be like wait a
minute next isn't used error isn't used
maybe it will just delete these these
arguments because they're not used right
so you delete them and then now you've
changed this from an error handling
middleware to a normal male where so
literally the unused argument is
important here to get expressed to treat
this as an error handling middleware so
let's just just a overly fancy API
design it's bad they should have just
made it explicit I opened an issue about
it and they want to fix it but it's they
haven't done it it's been like years so
yeah yeah anyway um
okay how much time do we have well we
might have to get to this next time but
I'll start it we have ten minutes okay
so this one's really cool so this is
something I worked on so it's it's a I'm
personally invested in it I guess so
so there's this thing called the buffer
class in nodejs
and the idea is it is a server often
needs to allocate memory all programs
need to allocate memory for various
purposes and at the time JavaScript
didn't have a way to do this natively
there was no all you had was strings
basically you couldn't make an arrays
but you couldn't make like a you can say
give me a megabyte of memory and I'm
gonna put whatever I want in that in
that megabyte of memory right and so
node introduced buffer later the
JavaScript language itself eventually
got native support for this and they
introduced these other things called
typed arrays and ray buffers which give
you the same same functionality and so
the browser has these and then
eventually node also got these because
it's part of the JavaScript language now
so notice now hazard is redundant it has
two ways of doing binary data now
unfortunately but that's just the way it
is so this is how you use buffer so
there's a couple ways you can use it one
is you can pass in an array of bytes of
byte values and then you get a buffer
containing like one two and three bytes
so this is three bytes of memory right
with with three there's the three bytes
you can also pass it a string and then
it will parse this the look at the ASCII
values and then it will fill the buffer
with the ASCII values of for each of
those letters you can give it a number
and then it will make a buffer that's
ten long ten bytes long and you can also
give it another buffer and I'll copy the
buffer so this is looking a little bit
like the jQuery API right it's a little
bit of many many different things you
can pass into the buffer constructor and
you get different behavior so this
should be tricking some alarm bells
maybe did you have a question okay so
okay maybe we can end on the demo
because I have I have a demo and we have
nine minutes so I think we'll have time
so I want to show just how can go wrong
I guess so here we have ignore that
first bit so here we have a server and
what we're gonna do is some live coding
okay so so we just imported Express we
created an Express app and we're
listening on port 4000 by the way
speaking speaking of api's which are not
safe by default
you know the list and API that actually
causes us to listen on port 4000 if you
don't pass in an IP address as the
second argument to it then you're
listening for any connections to your
computer on port 4000 so what that means
is like your laptop if I didn't include
this any of your laptops in this room
right now if you knew my computer's IP
address which you could probably find
because it's just all my Stanford
Network you could you could connect to
my server right so really what this is
doing is it's saying basically only let
browsers on my same machine that connect
support 4000 actually connect don't
listen for connections from the outside
world basically that's an that's very
unsafe the fact that that's not the
default especially cuz I'm trying to
code in secure servers right now but
yeah anyway okay so let's let's see what
we can do here so I'm gonna make an API
endpoint that just takes a string and
then converts it to a hex encoding or
base64 encoding and we're let the user
specify what they want but basically
we'll take in some ASCII text and we'll
convert it to hex or bay 64 so let's
make an endpoint called a slash API
slash convert and this is the function
that will run and so let me make a
comment so this is the way I want to use
this I want the user to visit slash API
slash convert and I want them to pass in
a data query so it'll look like that
slash slash question mark data equals
and then I want them to pass in a JSON
object so it'll be like JSON will be
like stir hello and then type hex so if
they visit this URL then we're gonna
basically parse this figure out that
they want us to convert the string hello
to hex okay okay so so let's do that so
basically the main thing we need to do
here is to get the data off of the
request query object so that gives us
the that gives us this string right here
great and then now we want to actually
parse it as JSON because right now it's
just a string and I want to turn it into
a JSON object so I'll call json dot
parse and now now this data variable is
literally an object that's gonna have
two keys stir and type perfect okay so
and just to be safe here I will I will
just confirm that this actually worked
so yeah by the way if this string is not
valid JSON then this json.parse function
is going to throw an exception and
that's okay Express will actually just
deliver an error to the user in that
situation so I'm just gonna I'm not even
gonna try cat I'm not gonna put a
try-catch around that I'm just gonna let
it fail if it fails and the user will
see an error message so great so now if
we get to this point we actually have an
object so what I want to do is let's see
here I'll say if they didn't provide me
a string then I'm gonna give them an
error so I'm gonna throw an error
missing data dot stir all so I only want
the type to be hex or base64 let's see
here oh sorry so if it's not hex if it's
not hex and it's not base 64 and it's
not oops
doing this wrong sorry this okay and
it's not utf-8 which is just a plain
plain like a normal string then I'm
gonna throw a new error data dot type is
invalid okay so now if we get here I
have an object with these two things and
I think that they're I think they're in
the right state so I'm gonna actually go
ahead and send the user a response and
I'm going to convert the string to the
type and I'm going to send this back to
them and convert is not a real function
so I need to implement convert so
converts going to take a string and a
type and it's going to convert that
string to the given type and this is
very easy to implement what I do is I
return a new buffer so new new buffer
will take this string turn it into a
buffer and then buffer hasn't has a two
string method that takes a type
okay so all I'm doing is I'm taking the
string that users given me I'm turning
it into a buffer like raw bytes and then
I'm converting it into the string form
that I want okay and so then that's what
I send back to them does this code make
sense everybody any obvious security
issues okay oh thank you yeah thank you
for that okay cool
okay so let's see if this worked so I'll
go to localhost 4000 slash I guess I
already have an example here so I don't
know if it one can see this but
basically I'm just going to slash API
slash convert and then my data query
value is just stirrers hello and the
type is hex so let's see this gives me
back a hex hex value of hello I don't
know if that's correct it looks correct
to me let's just go with it let's try
base64 that looks right to me let's try
changing this to a longer string okay it
looks like it's working what happens if
I don't give it valid JSON so let's say
I add like an extra some extra braces
here so it's not valid JSON cool it
handled the error the server didn't
crash right the server the server just
printed a warning but it didn't crash
okay whatever
so this looks good okay so what is the
problem what if I told you that changing
this parameter here from a string to a
number would be disastrous
like axe absolutely catastrophic okay I
will change this to the number 100 and
it's not in quotes you'll notice the
hundred is not in quotes it's actually a
number when I do that guess I'm getting
back this is raw server memory so I like
any what this is doing is if you're
familiar with malloc in C this is
calling malloc and it's not zeroing out
the memory so what this means is it's
giving me memory that was potentially
used for other things by this process
earlier in time and so this could could
potentially include sensitive user data
like you know the users password or
anything that was ever in memory in the
process at any point in the past so it's
pretty wild and if I if I actually let's
see let me um me refresh this a few
times actually let me let me change this
to utf-8 so utf-8 is is basically
the normal human readable like Unicode
text and so if I do that most of the the
bytes you're going to look at are not
valid like they're just garbage memory
but occasionally you'll get a string of
like user data or some string that looks
like it you know this was this wasn't a
member in memory of the process at some
point in time so if i refresh this few
times let's see so far nothing that
interesting whoa was it increase the
size sure yeah oh yeah let's make it
bigger yeah sure okay so this is looks I
mean okay this is interesting there's an
Arabic characters but there's there's
also like code and some something that
was in memory at one point in time yeah
yeah so if I kept doing that oh whoa
what is this this is this is a code from
express it looks like yeah okay so see
basically there was some memory of some
point in time that contained code and
then it got freed and then we mount it
and it wasn't zeroed out so this is this
is a bad API design basically whoo this
code looked totally benign right and it
turns out we were running a server which
completely just will just print out any
any user data that was ever in memory at
any point in time this is by the way
very similar to heartbleed never heard
about the heartbleed attack it was an
attack where you could send a request to
a server and it would just print out
random memory and eventually if you did
it enough times you would get the secret
key that is used for the TLS handshake
so you'd literally have the server's
secret key and you can men in the middle
all the users of that service so anyway
we don't have time to actually go into
exactly how this works but we'll talk
about it next time
and I'll see you all on Thursday thanks