CppCon 2018: “Secure Coding Best Practices: Your First Line Is The Last Line Of Defense (1 of 2)”

CppCon 2018: “Secure Coding Best Practices: Your First Line Is The Last Line Of Defense (1 of 2)”


– Okay so I thought I would
start this out by a story of something that
happened to me when I was a senior software engineer and I was also managing a network. And we wound up getting penetrated by two different nation states. One at the top end of the month, one at the bottom end of the month. Strange enough, it was
actually the same engineer that got us penetrated. I could never convince
him that going to places, since we’re a defense contractor, there are some places
you don’t want to go. So the FBI was very
understanding for the first time. The second time I called the FBI, there was this moment of um, are you trying to win the award for the most hacked small
business in America? And my response at the time was, “You have that?” (crowd laughs) Which was not the right
answer for the FBI. That was unfiltered thoughts. You can read that or not. You’ve been staring at my
name for a half an hour. One of the things I wanna ask, and I always ask at the beginning of this, how many of you have some sort of secure coding standards,
secure programming penetration something? Okay, some. Yeah, usually most of the people don’t. So, this is I think our problem. We have a tendency to
sort of look at security as one of those things that we really can’t sell as a feature, which is for the most part true. You can’t sell it as a feature. But we also have a tendency to sort of ignore the implications of not putting that into our systems. And so today what we’re
gonna talk about is, one is how we got where we are, and the second thing
we’re gonna talk about is, how do we get out of where we are to someplace better. And while we’re on our path, we’ll do a couple of exploits, the classic buffer overflow and then we’ll do an exploit that is actually in the Linux kernel up
until a couple of years ago. So, the most dangerous place on earth is not a war-torn country. It’s not Syria. It’s not the Korean Peninsula. it’s not anyplace that
you would think it is. The most dangerous place on earth today is the internet. We have gone just in my lifetime from 300-baud modems with DDS to now we have cars that drive themselves, we have everything talking to everything. We have all of these heterogeneous systems that really don’t need
to talk to each other, talking to each other. And what we’re finding
out in the infosec world is that perimeter security
is not gonna protect you. If it was going to protect you, it would be doing a
great job at this point, but it’s not. There’s too many ways past it, it’s too porous, there are easy ways to get beyond the security networks because we always had this idea that everything inside is trusted, everything outside is untrusted, and that as long as you have
your perimeter security, you’re good. The problem is it doesn’t
work out that way. What we’re finding out and what’s sort of becoming the mainstay is this concept of zero-trust environments. And that is, the environment
inside your network is every bit as dangerous as the environment outside your network. It’s too easy for a phishing
exploit to get people into your network, and in this case I had a network that somebody
was able to penetrate twice in the same month simply because somebody did something they
shouldn’t have been doing. The most disturbing part of those is when I was coming up,
it was Matthew Broderick. I wanna change my grades,
I wanna play games, yes, I may have destroyed the world getting into the wrong computer
to play the wrong game, but it was mainly about people just hacking into systems. And then it migrated from well now it’s about money, I can get
into your bank account, I can get into your financial records, I can get into anything that I need in order to make money off of you. Where we’re going now and probably the most
disturbing part of it is, and why all of these linkages, and all of these systems
talking to each other is such a problem, is
because we’re starting to see hackers going after things like critical infrastructure. Going after things like our power grid. So if you’ve ever looked at
how the power grid works, it’s all connected. In fact, from the
northern hemisphere of the United States and Canada,
it’s all connected. You take down one power
grid, it puts a strain on the rest of the power grid. And in this case, we’ve seen people going after power grids and they’re not in there to get money, they’re in there to destroy equipment, which means, if you could
imagine what would happen if the east coast went down? Which is actually, there
is a major power grid especially New York, what does it do to our financial institutions? How are you going to do your banking? When someone has taken down the power grid and it’s days or weeks to
get the power grid back up. Then you’re talking
about loss of human life because hospitals can
only run without power for so long. Then there are the things that we are putting, for example, aircraft, are now in the air,
they’re fully automated and they’re talking to an upstream server all the time. We have cars that drive themselves and are constantly talking
to an upstream server. So we have all of these
pieces going together. And Elon Musk even admits that’s one of his biggest concerns besides the SEC and all the other stuff he’s got going on. He’s concerned about a fleet-wide hack. It’s not unthinkable. In 2007, DHS managed to penetrate a 757. They got into the flight controls just with it sitting on the ground, it wasn’t in flight. But they still got in. Those should have been air-gapped. The systems they came in on and the systems that fly that plane should never have any conversations at all yet they managed to do it. If you have a breach like that, what you’re talking about is having people being able to control aircraft, cars, things that can do serious
damage to human beings. So one of the things we find, especially when I talk to CEOs, we tend to have these three
lies we tell each other, we tell ourselves really. We’re behind firewalls. Right, every company that’s been breached in the last 10 years had firewalls. That’s just the way it is. The firewall didn’t keep them out, and it’s not, it’ll slow them down but it won’t keep them out. We talk about, well,
it’s been code reviewed, it’s been tested. You know, there’s this sort of moment of, well how can this possibly have happened, look at all the testing that were done, the problem is we’re
not testing it correctly and we’re not code entering it correctly. The things you look for in a vulnerability are gonna be very different than the things you’re gonna
look for in performance. It’s just a different set of patterns that you’re gonna be looking for. And then of course there’s the
we’re too fill in the blank, we’re too small, we’re too large, we don’t have anything anybody wants. The bottom line is, everybody’s got money and software scales really well. The same zero-day exploit that I can run against this company is the same that I can run
against any other company. And once I’m inside, I can do pretty much anything that I want with that company. So let’s talk about who the they are that we deal with. First is, it started out as script kiddies back in the ’70s and ’80s. And you did have some state actors, but now nation states
actually have offensive teams that do nothing more than
to take an operating system, tear it apart whether they
got the source code or not, find the vulnerabilities, and create what are known
as zero-day exploits. Those are exploits nobody has
seen, we call those equities. So if they find 20 equities and they save them back for a rainy day, and unfortunately it
always seems to be raining, because we see a lot of these
coming out of nation states. That filters down to the next group which is the group that are
the criminal organizations which take those, weaponize them, put them out on the dark
web, or the dark net, whatever it is that you call it. And those become, and if you’ve ever gone to anything like Dream Markets,
you can find an exploit for almost anything, and
they’re really cheap too, I mean they’re really
inexpensive, they’re like $300. And if you wanna spend
more and get support, you could do that. We take what a nation state can give us, which is scale and money, and then that begins to filter
down to criminal enterprises and then that comes down to corporations. Corporate spying now is rampant, probably one of the most notable what we call advanced persistent threats, which is somebody who was
penetrated for a long time and they didn’t know
it, was Nortel Networks. And Nortel Networks wound up being penetrated for almost a decade and they could never figure out why it is they would lose bid, after bid, after bid, to this one particular company. Well, the reason why is they were working with a nation state which penetrated their systems, they were into the email,
their bidding strategies, the contracts, everything,
they knew everything that was going on in Nortel Networks, and they knew exactly how to react to that in the marketplace. So they wound up declaring bankruptcy. So we have companies that are now taking what comes down
from the higher levels and have started using. Oddly enough, insiders are actually still the largest, in terms
of just exfiltration of data, insiders are still our biggest threat. I was talking to a gentleman the other day who said that he had had engineers take source code out of
their environment twice, so that’s twice their code
base walked out the door, and these were insiders. One of the things we find a lot though is the weakest point in security
is not just the insiders but it’s also the people
who don’t patch boxes. Equifax is a perfect example, this was a case of a
contractor that they dismissed, we don’t need you anymore,
he hadn’t patched the boxes, so they were penetrated
by known vulnerabilities that had been out there for
at least a couple of months and it was a couple months
after that they find out that they had been penetrated. So in order to talk
about software security, we need to talk about
what is a critical system. So there’s some terminology
we’re gonna use. The first thing is,
what’s a critical system? Now, we tend to think of critical systems as just simply being systems that we own, it’s the thing holding our snowflake, whether it’s data, or
some other capability, but that’s what we own. The problem is is that it’s not just that, so minimally it’s the system itself but it’s anything else
that can interact with it. And I actually had personal
experience with this one time, I had my wife call me, she
had been doing research at a university, it wasn’t sketchy, it was a normal university, and suddenly the printer was acting up. So I didn’t think anything
of it, I came home, the printer wasn’t acting correctly, so when I checked her machine, I found that there was
all sorts of redirects going out to a proxy server that I later found out was for a nation state. Somebody had run a water holing attack against this university,
she went to the university, it came down, it actually wound up installing firmware on the printer ’cause it got out of the stand box. And when I turned the printer off, all the redirects stopped. Turned it back on, the redirects
start right back up again. So somebody had managed to get to a low priority system,
which was a printer, to go after a high priority
system, which was the data that was on her pc. So one of the things we talk
about is attack vectors. Attack vectors are what we do. It’s a buffer overflow, it’s some sort of a denial of service,
and denial of service tends to be things where we’re making
use of, especially in C++ we’re making use of undefined behavior. I send you something into
your system, you choke on it, the system crashes, you
have a denial of service. We also have privilege escalation, which we’re gonna do today, and then some others are
things like SQL injection which we won’t cover today, but if you’ve ever seen the OWASP Top 20, the SQL Injection’s been at the top of OWASP Top 20 for 15 years? And there’s sort of this moment of, why can’t we solve this problem? And it’s because of the
bad programming habits that we get into with SQL
Injection where we’re not using, you’re not validating the data, you’re not using stored procedures and things that’ll allow
you to filter out bad code. So attack surfaces are really
any surface that I can get to. If you’re listening on a
port, if you’ve got a website, anything that I can get to from the outside is an attack surface. But attack surfaces are also the inside. How many people have IPC mechanisms because you have multiple processes and you’re talking across
different processes? Yeah, so if you work
in the embedded world, you probably have a lot of that,
and they’re across the die, which probably means your
using something like sockets, we don’t secure those. We don’t secure CLI’s for
example, so I’ve worked for companies where we produced hardware and one of the things we do is we drop a series of CLI’s on there to make it easier for the field engineers to be able to access the software but we do nothing to
authenticate what the CLI’s- So if I’m in the wire, if
I’ve gotten to the box, I can use those things and
what’s the first thing you do when you type a command line interface? It gives you a nice readout of
all the options that you have and so you go, Oh, I
didn’t know that I could go and use this to reset the system so now I have an instant
denial of service. So, I picked the title very
specifically for this talk because when I talk about
your first line of code is the last line of defense, the reality is, it is
the last line of defense. Every system that we
write is going to wind up being on the front lines
of this undeclared war that is on our system. So I picked some examples,
and I didn’t pick them, they’re not meant to be
hard, they’re examples that I picked out of the
vulnerability databases that I wanted to be able
to tell a story with. So let’s start here. What’s wrong with this code? And don’t raise your
hand, just shout it out. (audience member speaking faintly) How can it be overflowed? (audience member speaking faintly) It might be null
terminated, the problem is, (audience member speaking faintly) Exactly, you’re not checking that length. – [Audience Member] Yes. It may be null terminated,
everything may be fine, but the advice we tell everybody
is don’t use string copy. Okay, I’m not using string
copy, I’m using string end copy. The problem is, is that
string end copy has almost the same vulnerabilities
as string copy except that we don’t ever talk about it, so in this case I’ve sent in a file name with some arbitrary length,
that may or may not be right, that’s going into a buffer
that’s a fixed size. So this is a classic buffer overflow. The panel on the right
actually comes from CERT, the top one is, how bad is this vulnerability? The middle box is how
likely are you to make it to do something like this? And the bottom is what
are the remediation costs? Now, I don’t really
always agree with them, but I put what’s in there
simply because when I, it makes it for a standard language. So we fix this, standard shrink. Good, problem solved? (audience member speaking faintly) Do what? (audience member speaking faintly) Yeah, see that’s the problem,
the advice that gets given to people is, we’ll just
use standard string, it makes it all good, well
you have a couple of problems that one is standard string
performs very poorly, anything over on a 64-bit machine, I think it’s 24 characters,
becomes heap allocated, so if you’ve got all these
heap allocated strings, you’re gonna have disastrous performance, but the other thing is,
you’re not doing anything to verify or validate this data. Who sent it to you? How big is the data? What you’re doing is,
you’re using a buffer in order to hold it and then
you’re sending that buffer, you’re actually sending the raw string into another function call
’cause that’s what it takes. So the simplest solution to this is just check the
length, it’s very simple, that’s why I don’t really
agree that this is medium, this is actually pretty trivial. If you check the length
and make sure that, that length is appropriate
for the buffer, you’re done. You’ve solved the problem, you don’t have to change psychology. The other problem with
using standard strings there’s a lot of things you
can’t do with standard string. If anybody here uses Google V8. So I tend to do JavaScript and C++, so I’m forever sending
things back and forth. You cannot use standard string
for that, so you’re down to, you know the first thing,
you may send in the string the first thing happens is
it rips the guts out of it and converts it to something else. Same things like if you’re doing
UTF 8 to UTF 32 conversions you cannot do that with standard string. So getting people out of the habit of using a piece of technology means when they come back to using that, they’ve sort of forgotten how it is that they should be using this. In this case it’s very
simple just check the length, and this is probably one of
the things that gets us both, if there is one thing that you
do nothing else after today is that you verify and
validate every piece of data that comes into your system
through the external interfaces or wherever you’ve, we’ll
talk about trust boundaries here in a little bit. Maintain situational
awareness on your data. That right there is the
biggest problem we face when it comes to our software. How ’bout this one? It’s a bit different. So sort of the same deal,
the problem is here. I’m taking in something and
I’m just static casting it directly into a enumeration. What if that is not in
bounds for that enumeration? In C++ 14 and before,
that was an undefined, or basically it’s an invalid value. So you’re okay with that,
maybe you check it later, so you check it afterwards. The problem is the C++ 17 that becomes an undefined behavior, an
undefined behavior is the point at which we talk about denial
of service, software crashing, the kinds of things that make
you incredibly vulnerable. So the solution to this, comes from the language itself, we have strongly typed enumerations and the reason why we have these is, as long as you’ve got the types correct, once you static cast that in
there it may be out of range, but what you’re not gonna get
because of two’s complement, is you’re not going to
get undefined behavior and crash your application. So look at the standard. I’ve tried reading the
Standard, I’m not a lawyer, apparently it’s written by
one, because there is a lot of very dense text there,
but I just did a sweep through the Standard and I found something on the order of 269 places where we have undefined something. Those are the sharp edges of the language. If you don’t know where the
sharp edges of the language are, you’re going to wind up running into one of those sharp edges
at a time you really don’t- So I think for the Standards committee there’s gotta be a way to do something besides 1500 pages of legalese,
there’s gotta be a way that we can go and do something that gives people the
ability to understand this without having to become
the language lawyer. How ’bout this one? (audience member speaking faintly) Yeah, so I’m hearing different
variations of the same thing. Standard copy does not allocate memory. Standard copy will just simply
take the place you started, the place you’re gonna wanna come to, and it’s just going to copy it. So this is a heap overflow. So I didn’t know that until
I actually ran across this, and there are other ones
like, I think translate, there’s at least two others,
that have this problem, but you won’t know that
unless you really study what standard copy does and in this case standard
copy doesn’t allocate memory. So the solution for this one
is, just use back inserter. So each time you do a back insert it’s gonna wind up allocating
the memory it needs, copy everything over,
and everything is fine. Probably a little simpler way is just use direct instruction, just pass it to the constructor and let the Standard template libraries do what the Standard template
libraries do correctly. So one of the things you
probably won’t see on there, is this case I don’t even
think it warns you that that’s a problem, because
it doesn’t really know it. But warnings are in the same way that pain in our body tells
us something is wrong. Warnings in our code tell us
that something is inconsistent. It may be okay to ignore that warning, but in reality it’s probably
not going to be okay. So one of the things we
need to strive for is, eliminating warnings from our code. You’re not going to do this overnight. I mean I’ve seen products
where I’ve got 1500 warnings and we’re not going to get
them out in the next release. But as you begin to get
rid of those warnings, those warnings are there
to tell you something and we need to listen to them. Let’s try this one. (audience member speaks faintly) Why is it going to give
me a warning to while int? (audience member speaking faintly) Yeah. (audience member speaking faintly) When does this loop exit? Exactly, well not exactly but, (audience member speaking faintly) There you go. There’s no guarantee that
we’re ever going to pass a zero into this, which means
this could go on forever, and ever, and ever, and it
just simply keeps going. So there’s a couple
ways, to solve this one. There’s variadic templates,
which I don’t know about the rest of you but I find these a
little difficult to read. But this basically does the same thing. One of the other things we can do is brace the initalizer list. So using this allows you, to ensure that you’re
only consuming the data that’s being passed it. And that leads to the
fourth best practices, complexity is the enemy. If you’ve ever studied metallurgy,
especially when it comes to airline crashes, the reason
we have fatigue cracking, is because when you put
the system under stress, the energy will all begin to coalesce around weaknesses in the metal. The same thing goes on with
complexity in our code. When you, you will find the easy ones, the ones in the non-complex
parts of the code. But vulnerabilities within ours and bugs, vulnerabilities inside our
code will begin to migrate to the complex areas of our code, simply because it’s hard to reason without those pieces of code, that’s where we begin
to miss these things. So one of the things we need to do is begin eliminating
complexity out of our code. This is the last one. (audience member speaks faintly) Which part? (audience member speaking faintly) – [Audience Member] Below the grid? – Yep. So we don’t know, when that’s
actually gonna be used. So we’re passing
something in by reference, which may not ever get called, until after what was being
referenced is now out of scope. So simple way to do it
is capture by value, make it mutable, in this case
it really doesn’t matter, this is a trivial example
which we really don’t care if it’s not gonna return anything. So grow bug bounty hunters, and this is a, has anybody ever done bug bounty hunting? You have? Oh actually a couple of people, excellent. So, large companies will
create bug bounty programs and that is, you can go and
you can earn anywhere from, you know, a few hundred
dollars to a few thousand by finding a defect in their code. So Apple does it,
Microsoft does it, there’s, a lot of this is penetration
testing from the outside, it’s especially popular with
websites, because websites tend to be the most
heavily targeted systems that we see in the industry, they’re just, they’re easy pray. So bug bounty hunters, a
bug bounty hunter program, would simply look like this,
that if you are a developer and you find a vulnerability
that is exploitable, something you can get from the outside, you wind up getting paid by your company. Now if it’s your bug,
okay, you wrote the bug, you find the bug, you
fix the bug, it’s not, it’s not something that we
wind up getting paid for the same code twice. But a bug bounty hunter program
does a couple of things, one is, it teaches you, you’re
engineers, if there’s money on the table you’re
engineers are gonna go out and they’re gonna figure
out how to find these kind of vulnerabilities, they’ll
take training like this, they’ll go other places and get training, they will figure out
what the patterns are. Because one of the things as you saw in all of these
examples, there is a pattern to the way defects get put into our code. They’re little tiny mistakes. One of the things that
vulnerabilities have and that being able to
breach a company has with airline disasters
right, is that we always in an airline disaster
is it’s never one thing that brings the jet down. So it’s always a series of mistakes and you have a chain of events, that if you break the chain,
you avert the disaster. So in software it’s the same thing. There’s rarely ever one thing, it’s going to be a combination
of, I didn’t patch a system, I have a zero day I
didn’t realize was there, I’ve got weak security
controls around the software that should be protecting
my little snowflake. But bounty programs are designed, internal programs are
designed to teach people how to be able to go and find these, and when they do find them
they get rewarded for it. So it does a couple things, one is you will ship with
fewer vulnerabilities, the second thing is you will wind up learning how to do this, so you’re going to write fewer
vulnerabilities yourself, and then the third thing is you’re gonna find more in code reviews. And we’ll talk about code
reviews in the next session but in this case, a
lot of companies in my, advocate when I talk to CEO’s, you know, put a $10,000 check on the table, somebody finds a verifiable exploit that they can be exploited in your code, and they say well, 10 grand that’s huge. Yes, but the over and
under on your stock drop when you do get breached is
gonna make that look cheap and yes, unfortunately, most companies do, their stock will recover. So you know, maybe the CEO gets fired, the CTO gets fired, there are people, but the bug bounty programs
begins to bring that in-house. We tend to see a lot of people coming and doing penetration
testing from the outside, but nobody that really does a
lot of bringing that in-house and those skill sets in-house. So what do I look for
when I penetrate a system? The first thing is any
time you copy memory, because you’re likely to get it wrong. That first example was a good example of you getting it wrong. Anytime you don’t validate and verify who you’re getting your data from, that is the easiest way
to penetrate a system is me being able to send you information that you’re not expecting,
you haven’t decided, you haven’t figured out who I am, so you don’t even know
if I’m a threat actor, or I’m somebody who should
be sending you data, you just simply processed the data. So denial of services, or in DDoS which is
dynamic denial of services, are usually where you have, you’re getting data from somebody but you haven’t verified
that it’s somebody that you care about getting data to. Open source libraries,
their weaknesses are yours. When you use an open source library, one of the things I always coach people to do is prefer libraries to
where you have the source code, and they’re going through a continuing set of security checks. So when we get into the
next hour, we’re gonna look at something that was fixed, then it was broken when they
went to fix a different bug and then it got fixed
again nine years later. So what you don’t want
is to just say okay, we’ve blessed this, this is good, because then every time
you change the code, you may be introducing
some other vulnerability that you don’t realize is there. Internal interfaces, IPC
interfaces, USB interfaces, if I can get you to let me put
something into your system, if I can get you to, if you’re expecting that what is inside is safe and what is outside is not, it’s not. What is inside is just as dangerous, because once that, once I’m inside, I can now go after anything that I want and if you’re expecting
the perimeter security to protect you, it won’t. And then again, any place I
find complexity in the design, and I’m gonna come back to
this, over and over again, because I see so many times
where we have vulnerabilities in code that has nothing to do
with people making a mistake it’s just, it is so
complex that they wind up not seeing the bug simply because you can’t see
the forest for the trees. So how many people have ever
run a buffer flow exploit? A few people. Does anybody not know what they are? Cause that’s what we’re gonna do. So a buffer overflow exploit, this is sort of where it all began. Back in the 90’s and the
2000’s when people began to find ways to penetrate system. So this code is actually
the same code we use. We saw this just a minute ago. We have a buffer flow exploit,
we’re using string end copy, we’re passing in a link
we’re not validating. So there’s a couple of
things we can do with this, one is, I can crash the
application just by writing a ton of data in there,
or I can do something that will be a little more helpful and that is execute arbitrary code. So this is one of the things
we would want to execute. Up there on the top left,
this is for a Linux system, I just want to run a shell. You can do the same thing with windows, you’re just gonna run a command. Over here on the right hand side, that’s just the assembly code for that. It’s just a few registers and then a call. So it’s very simple, this is
a very trivial piece of code. So here we have the model for an X86, you’ve got a program space on the bottom, the kernels on the top, the data heap is on the
bottom which grows upward, the stack is on the top
and grows downwards. No matter what memory you’re accessing, you always access it from low to high. So I pulled out a piece of
what a stack would look like. So the gold on the right hand side is the stack frame that’s above, and I removed some of
the things we don’t need, there’s actually more in here. The return, that is just the, when you make a function call, that return value is going to be where the function comes,
the next instruction comes when you return from that function call. So every time you hit, you
create a new stack frame, you need a way to go back to the line of code that called you. So EBP-RPB, that is just
the stack frame pointer, and then we have our buffer and loop. What we have here that’s useful to us is the return and the buffer. So we have two pieces
that we can play with and what would be really nice is instead of that return going back to where it’s supposed to go, it would be nice if I could put it into some place that I control. So what we do is we do
what’s known as a NOP-sled. Now there’s a couple
of different NOP codes, there’s the long version which nobody uses and the short version which
is the 0x90’s you see here. What we want to do is we
want to take that return and replace it with a return
that goes back into our buffer, that’s the overflow, we’re
overflowing the buffer, we don’t care about the frame pointer, by the time the frame
pointer figures out it’s bad, it will be all over. What we want here, is we don’t want to have to be precise about this, we want to be able to
cover that return code to come somewhere back into our buffer, hit a nice big landing pad and then have the NOP’s, the NOP slide bring it down to our code. So you see this code here,
which is what it would look like what the payload would look like. You see it’s got all those
0x90’s, that’s the slide, then you get down here to line about 190 and you see some more 0x90’s
but then you begin to see some what looks like code, and
then a couple lines down you see the same address repeated over and over, and over again. What you’re trying to do here
is, you’re trying to be able to take that return address
and sort of slide it over the top of the return,
but that return address is gonna be somewhere in your buffer. Hit the NOP-slide go
down, execute your code. So we’re gonna do one, and
what we’re gonna do is, we are going to start from a
buffer that’s in a small buffer we’ll overflow or own stack space and then we’ll overflow into
the stack space above us, so the calling function. Does anybody have any
questions at this point? ‘Cause I’m well ahead
of schedule, go ahead. (audience member speaking faintly) Actually they do. I’ll have to work on the slides. – [Audience Member] Are
the videos available with the slides? – Oh yeah, the videos come
out every about a month, yeah? (audience member speaking faintly) Absolutely, so the question
was is that your comment about libraries is true for any library and not just open source. So here’s the thing about
open source libraries, with an open source library
I get the source code. If I’m gonna hack into a system the thing I want is the source code, because that’s where I’m gonna
go find my vulnerabilities. We’ll talk about that in the second talk, because there’s this,
it’s a Linux vulnerability but it’s open source, so one of the things I always
want in the source code is I wanna go get some idea where I think the vulnerabilities are and then I can go ahead
and start testing around that area and see if I
can make something happen. So you’re right it’s any
library, it’s the libraries as a, that I consume I want to know that they’re undergoing
periodic security reviews, but I also want to know, I’d like to have the
source code so I can look, but it becomes one of those
things you do not want libraries that somebody has said, okay
I’ve put together my libraries, it’s never been reviewed,
it’s not under ongoing review, so just use it, because the
problem is you don’t know where those vulnerabilities are and because you don’t
have the source code, you can’t find those vulnerabilities. Anybody else? (audience member speaking faintly) Is this what for ALS live? (audience member speaking faintly) Yes, so, we’re gonna talk about
ASLR here in just a minute. This box has ASLR turned off,
and the reason why I turned, so the question was does this have to do, does this assume ASLR? The reason why I turn
ASLR off in this kind, is because if I had to do an
exploit where ASLR is active, it would take most of an hour
just to explain the exploit because it is very complicated and it’s not something that’s gonna, you’re not going to get
it to work the first time, you’re gonna have to work through some of where the address shifts are, and we’ll talk about
ASLR here in a minute. Anybody else? Yeah. – [Audience Member] So
the NOP-slide is there because you don’t know the
exact place to return specific? – So the question is,
the NOP-slide is there because you don’t know the exact address that you need to hit. The NOP-slide is there so I don’t have to know the exact address. I can just put in an area of the code, some index off of where it is and I don’t have to be precise. It makes it much easier to
be able to a buffer overflow. Anybody else? Uh, yeah. (audience member speaking faintly) Buffer overflows? So the question is, how do
you test for buffer overflows? – [Audience Member] Yes. – We’re gonna talk a lot about
testing in the second talk but minimally, you’re going
to be doing code reviews. So when engineers are young, they go in they find out that the microwave didn’t
want to cook their lunch, they find out that the
microwave is broken, they pull the microwave apart,
they go in, they fix it, they put it back together,
cook their lunch, and they go on about their day. Hackers are a little bit different, they go in the microwave
is working just fine, cook their lunch, and then they sit there watching the microwave thinking, how can I make this microwave do something it’s not supposed to, how
can I make it blow up, how can I make it do something
other than what they expect. It’s a different train of thought. We go and we look at, how
can I take these pieces and how can I build this
beautiful algorithm, how can I have this extremely, excellent performing data structure. Hackers are, how can I
go and I take something that somebody’s built
and turn it inside out, and turn it into a weapon. It’s just a very
different way of thinking. So when you find these things, when you’re looking for
these things in source code, what you want to do is
you want to begin thinking about how can I break this? And I know it’s hard, I’ve been doing this for 30 years as a professional
but the bottom line is, I’m not a good tester for my code. I want my tests, I want
my code to perform, I’m more about building it,
I’m more about it working well. You don’t wanna find out your baby’s ugly, and you know, you’ve dressed it funny. One of the things that you
have to begin doing though, is looking at your code
in a different way. How can I break it? What can I send into this code that’s going to damage the code or make the code do
something that’s unexpected? And that’s where complexity,
when we talk about complexity, we talk about emergent behavior, we have those moments
of, oh I didn’t realize that was gonna work that way
because it is very complex. So how you view your code, rather than once you’ve built
it up and it’s beautiful, it’s doing exactly what you want it to do, is to, how can I destroy it? And so many times we
don’t get to that part and that’s why these vulnerabilities tend to slip through our testing. But we will talk a lot more about the types of testing we can do in order to be able to catch these things before they go out the door, yeah? (audience member speaking faintly) I’m sorry, I didn’t catch that. – [Audience Member] Stack
canaries, will you explain them. – We will talk about stack canaries, somebody’s been reading ahead giving away the rest of this part of the talk. Yes we will talk about stack canaries and I’ll explain how they work. Yes sir? (audience member speaking faintly) (scoffs) You guys are
reading ahead, great. So there’s, we’ll talk,
I’ll go ahead and talk to you about countermeasures, since everybody’s been bringing them up. Okay, so ASLR Adder Space
Layout Randomization. What ASLR does is it just
randomizes certain places in your address space. So there’s a hat called
a return to Lib C , so there’s a system function in Lib C and if I can know exactly
where that system call is, instead of going into my
buffer, I just point it back out to where that library
starts on that system call, it’s the exact same thing. I’m running in the context
of whatever this application is running in, I just
simply go out, I run it. So randomizing where these
things are makes it much harder or much more of a challenge to hit. So. That’s the wrong password. Okay. So I’ve already got my code,
there’s no reason for us to compile all of this, but if you look on here you’ll notice that there is a function called
vulnerability or just vuln. So vuln is a, this is just my code that has got the vulnerability in it. The reason why this is
red in a Linux system for those of you who are not developers, is because the set unit is set on it. So when you run this,
you’re gonna run it as root, and there are a lot of things
that you can run in Linux like SU, you can run Ping,
which is owned by Root, so it’ll run in the context of root which is analogous to running things as an administrator on windows. So I have my chill code which
we, which we looked here, we’ll first look at the, So there’s my payload, it
looks a little bit different than what we covered,
because what I’m gonna do is I’m going to overflow that buffer, so my addressing is first. So I’m at the bottom of my buffer, the address is gonna point up
into the stack frame above me with a nice big buffer and
run my payload out of that. The code, is very simple. I’m just gonna go open the file, I’m gonna read in however
much data happens to be there, in this case it’s going to be, going into that buffer called STR, then I’m gonna make my function call, then it’s gonna go into bad copy and that’s where the overflow happens. So if we look at my account, I’m just a regular user. The shadow file for those of you that aren’t Linux developers, that’s where all the passwords are. I should not be able to view
that if I’m just a normal user. So I’ve run my vulnerability and now I have this
strange hash mark error. So the vulnerability
has pulled in the data, it’s overflowed the buffer,
it’s now run my exploit, and now I have root access. So if I wanna look at the, this is the problem with live coding, I can now see the passwords on the file, which I should not be able to see this. Now that I have root
access I can do anything that I want in this system. So now that we’ve done this once, let’s find out what a failure looks like, because in buffer overflows,
if somebody’s trying to run some sort of exploit like this against you where you’re overflowing,
whether it’s heap or something, your gonna see memory that’s corrupted in a very specific way. So let us, I’m going to change my file so that this is a failure, and right now if you look at
bad file, it’s 517 errors. So we’re going to, see now
it’s 200, this is gonna fail. In fact we want this to fail. So if we run our vulnerability again, we get a core dump. So you have the same analog in Windows, you’re gonna get some sort of
memory dump of the failure. So what I wanna look
at is at the core file. So I’m gonna do this, I may not have dumped the core file. So now we have a core file. So now we wind up having a stack that’s got two stack frames in it. So if we go to frame one and
we want to see what is in that, that looks pretty normal,
it’s just like regular memory, there’s really nothing there. But that’s because we
overflowed this buffer, but that’s not where we put the payload. This was a small buffer and
one we actually overflowed into the stack frame above it. So let’s go look at that one. So now all of the sudden
we begin to see at the top, we’ve got what looks
like a repeating address, we’ve got a bunch of 0x90’s,
we’ve got other things, these are sort of the tale tell marks that when you have a piece of code that has been running
just fine in production, it suddenly begins failing
for no explainable reason, go and look at the memory, go and look at, when you have a crash go
look at the stack dumps, go look at the memory dumps, if you begin seeing
strange behavior like this, where you’ve got tons of,
and you’ll see 0x90’s, I mean we have NOP’s in there and it’s mainly used for padding, but if you begin seeing
this kind of behavior what it means is that somebody is trying, whether they are successful or not, they’re trying to run
something against your system and it tells you somebody’s out there. (audience member speaking faintly) Also tells you, you have a bud. So I always tell people, all
vulnerabilities are buds, but not all buds are vulnerabilities. You can have these things fail
for reasons that have nothing to do with someone penetrating it, but at least it gives you a
clue as to where you’re going, why you’re having this particular problem. So let’s talk about some
of the counter measures and these counter
measures came into effect in the early 2000’s, every
operating system has them. Address Space Layout Randomization What we’re doing is, is the stack and the heap are basically where they normally are but we’re moving programs around, we’re moving libraries around, this the Lib C attack
where I wanna call system, if the library code is moving around, I suddenly don’t have a
reliable place to find it. Now there are ways you
can get around this, address spills are one particular
way of getting around it, you can also try brute forcing it just by going through a range of places, it becomes worse on a 64 bit machine ’cause the address space is
enormous compared to 32 bit. But what these do is, is these change where things are located so that you can’t get to them easily, and this is handled by the OS, so this isn’t anything you’d need to do, Now, the one thing you can do,
you can, believe it or not, you can turn this off,
and I’ve seen people, they didn’t really realize what ASLR was, so they turned it off ’cause they thought it was gonna give them
a performance boost. It will not give you a performance
boost by turning it off, it just doesn’t, you’re not
paying a penalty for it. One of the other one is Stack Canaries, someone brought up what a stack canary is. So we started doing these ourselves, I just put some known bit pattern, right below the address so the EBP-ERP would be
right above the canary and I took that out to
make it easier to see but I’m gonna write some
known bit pattern in there, then right before I do a return I’m gonna go find out that
bit pattern has changed, if it has, somebody’s
overflowed the buffer, and then I abort at that point. In fact that’s what a lot of these will do is if they find these
things they will abort. It is turned on by
default in every compiler, so make sure that somebody
didn’t accidentally put in the wrong compiler flag
and go and turn this off because it is useful. It is also not foolproof, there
are ways to brute force it, there are ways to guess it, there’s a million ways to get around it, this is an arms race, I mean there’s just, we come up with things
to protect the system, somebody’s gonna come up with
a way to penetrate the system. So questions. Yeah. (audience member speaking faintly) Yes in fact the entire next
talk is gonna be around things. So the question is do you
recommend tools like sanitizers and absolutely, we’ll talk about some of the best ones out there
and when to use them. So there is um, I have a
tendency to hear people say, oh well I just use static
analyzers and it’s all good, I mean the static analyzers
gonna catch everything. Static analyzers are not
gonna catch everything. Static analyzers are good for what the do, but they are not good for everything, and so we’ll go through
everything that we can use to test our systems to make sure that when that system goes out the door we have gotten vulnerabilities, and we’ll do things like threat modeling and we’ll do a quick exercise on that. Yes? (audience member speaking faintly) Okay so what happened is I, when I did it correctly,
I had an actual address that went back to a region so when it tried to go back to that it found executable code in there and in this case it was a bunch of 0x90’s, the one that failed though
is I overflowed the buffer, I blew away the address but I didn’t put a valid address in it and the system recognized
it and so it crashed. You’ll get the same kind of core dumps if you have ASLR turned on, and if you’ve got stack canaries in place, it’ll, when it finds
that there’s a problem somebody’s been playing with the code, it’s just going to abort
at that point in time so you’ll get a core dump there too. Yeah, right there. (audience member speaking faintly) So the question was how big
is the arsenal of attacks? We’re really creative people. We can find ways to get
into almost anything. What it does is though, we find
out that there’s an attack, the particular vulnerability, we patch it, they come back, they look
for a different way in. There is no balance, and here’s the thing, a lot
of people will say, well yeah, I mean once you sort of figured these out, the problem is that the
technology keeps changing, and you wind up having, we write new exploitable code, everyday. So in that end, there are classes, so buffer overflows are
one particular type, then there’s code pointer exploits, then there’s SQL injection,
then there’s what we’re gonna do here at the end of the next talk, that is going to be something
quite a bit different and there’s nothing in the OS that can protect you from that, that’s just code that misbehaves that I can take advantage of. So in terms of what are there? What there are is there are a
discreet number of patterns. So if you get used to seeing
the particular patterns of how code gets exploited you’ll know how not to
write exploitable code, but in terms of the
arsenal, it’s infinite, because we’re just really,
really creative people. I think we had someone over here. – [Audience Member] If your example of the sbit had not been set, it still would’ve started a shell but (drowned out by coughing in audience) – Yeah exactly. The question was that if
a Sbit had not been set, then you’re just running in the context of you’re own account, you
haven’t really gained anything, ’cause you’re already in
there on that account. The reason why, and I’ll,
I have actually a slide that deals with this, in Linux and Windows, you will have pieces
of the operating system that are running as a
high privileged account, which is why we call this
a privileged escalation. We’re getting extra privileges by taking advantage of a vulnerability. So in the case of this
one, it’s running as root and there are things like
ping that will run as root and that’s the way the
operating system designed. There’s things in Windows
that will run as system or things that will run
as an elevated privilege because there autonomic
to the operating system and they need those privileges. Used to be much worse in Windows because back before Windows 7, everything was an administrator
and so it was really easy to take advantage of privilege, so then everything just ran
as an escalated privilege. Question, anybody else? (audience member speaking faintly) So the question was, do I see a lot of return
oriented programming which is, this is actually a case of
return oriented programming, he’s talking about a
class of vulnerabilities that I just talked about a minute ago. Are we seeing it? Yes, and we’re getting
really creative ’cause, it’s died down in that
the easy stuff is gone. What we’re still seeing though is that people are finding other ways to get around the ASLR,
they’re finding ways, so you can do code pointer exploits, well if that’s in the heap
then that’s not covered by a stack that can’t execute code out of. So there are, there is
still a class of that. What we’re seeing more of
a rise of at this point, is we’re seeing more phishing exploits where you’re already inside the wire, you’re making use of a vulnerability that no one knew was there. So this is sort of becoming
a class that, sort of, is getting smaller but it’s still there, because there’s, especially
if you have things like, an address spill, if you
tell me where the address is either cause it’s in your logs or because you’ve made a mistake, well now I can run that whole class again against your code simply
because I know where the beginning of like, the Lib C is, and I now I know where system is, and now I can feed you the same data except instead of having to
execute something on a stack, I’m just going off to a different place that’s not on your stack. Anybody else? (audience member speaking faintly) The what that I’m talking about? Oh the stack canaries. The stack canaries are
created by the compiler, so you don’t have to worry
about creating your own, you can if you want, but it’s redundant. We started creating stack
canaries back in the late 1990’s and early 2000’s as a
defense against this, until compiler vendors began to catch up and that’s when they put in ASLR, they put in stack canaries, they put in, and these are all
progressions, these we’re not one day we woke up and said okay, here’s the three technologies
that are going to fix this. What we would do is we would add one, and they would get around
it, we’d add another, they’d get around it, we’d add a third, they’d get around it. So all that what we talked
about was stack canaries or ASLR, we’ve made it more of a challenge but we haven’t eliminated it completely. It’s just, and then the other part of that is we’ve found easier exploits. The one we’ll do at the
end of the next talk is actually really simple, in
fact it will take me longer to explain it to you in a way
that everybody can consume it than it will be to actually
run it or code it up. Anybody else? Oh yeah sorry. (audience member speaking faintly) Chandler Hearse is sitting
here, I’d love playing, (laughing) Compiler vendors do an excellent
job, most of the difference between compiler vendors
is how they optimize code. We have not really found a lot
of exploits that come from, oh, I wrote the code this way,
the compiler exploited it, they optimized it this way
which generated the exploit, so the compiler vendors are
really good about making sure that they’re not creating
exploitable moments, and the other thing we’re doing as far as the language is concerned is, if anybody is familiar with
the standards, SG 12 is there to look at each proposal
that comes through and say where are we creating
potential vulnerabilities in the code, where are we
creating these sharp edges that we talked about, so
we have undefined behavior, and trying to get those
out and then going back and looking at old code and
saying can we modify this, or at least going look at the standard, can we change the standard,
so this becomes a, something that is not undefined behavior and Chandler did a really
great talk a few years ago on undefined behavior and I
think his point was well taken, as is we need to start
removing undefined behavior from like, we need to come to a point where we can define the behavior for it, it may not be correct behavior for the context of the application, but at least we need to be
able to define the behavior. Anybody else? Yeah. (audience member speaking faintly) Yeah so fuzz testing, is
actually a good way to do this, and we will talk more about fuzz testing in the second half of this,
because what I wanted to do and what I did with the
talk is, I split it up I wanted, okay, how do we get
to where we are right now, and then the next talk is going to be, what do we do about it, and that’s going to
include a lot of things like threat modeling, testing, a whole another group of best practices and things that you can do that will eliminate these
problems in your code. Yeah. (audience member speaking faintly) So the question is do
I have any experience with specialty versions of
Linux for example one that Collie that says that it is a security. I don’t spend a lot of time
thinking about whether or not, this particular implementation is safer than that implementation because a lot of the really worst exploits and the one we’re gonna do is actually built into the kernel. So unless they’re rewriting kernel code and we don’t know about it, they’re using the same kernel
that every other one is using, so they’ve got the same
liabilities that every kernel has, in fact the exploit in the next talk is one that hit every
single implementation of Linux out there, including Android. So it’s, are there some,
there’s like backtrack Linux which is, I hear, really
good Linux that you can use in order to be able to go and actually do penetration testing and it’s got all sorts
of tools built into it. Theoretically that’s safer, but I wouldn’t go with a distro simply because they advertise that’s its safer, unless it’s demonstrably
provable that they are safer. ‘Kay, probably have time
for one more question. Okay let’s take a break
and we’ll come back for the second half. Thank you. (audience clapping)

3 thoughts to “CppCon 2018: “Secure Coding Best Practices: Your First Line Is The Last Line Of Defense (1 of 2)””

Leave a Reply

Your email address will not be published. Required fields are marked *