Embedded - 312: Two Meter Exhaust Port
Episode Date: December 6, 2019Chris and Elecia talked through how security holes can get explored on a fictional product. Thanks to an Embedded listener who enjoyed hearing from Jacob Martinez about helping young adults have acces...s to technology, we have a grant to match donations to DigitalNEST up to $2500. Donate here: give.digitalnest.org/embeddedfm We talked through OWASP Top 10 Embedded Application Best Practices but OWASP Internet of Things and OWASP Mobile Security are also very useful. GREAT explanation of buffer overflow attacks by Coen Goedegebure XKCD Little Bobby Tables
Transcript
Discussion (0)
Hello and welcome to Embedded. I'm Alicia White. I am here with Christopher White. This time it's
just going to be us. We're going to talk about more of our show with Jacob Martinez about Digital Nest, the place
that gives access to technology to young adults, we are so fortunate that a generous embedded
listener has decided to do a matching grant. That means that if you donate $1 to Digital Nest,
they get $2, which is pretty cool.
So I'd like to ask you to consider donating to Digital Nest.
The website is give.digitalnest.org slash embeddedfm.
And of course, that will be in the show notes.
If you have any questions,
feel free to email me.
And I am really excited that embedded listeners are going to help other
people.
It's just neat.
Now let's get back to the show.
It's December and I don't care for it.
It's been raining and he doesn't care for that either.
These things may be linked.
We should just move to Australia.
Then it would be
July that I'd be unhappy with.
That's true.
Well, given that we are unlikely to be
snowbirds, anti-snowbirds,
I think we should just do a show.
Okay. You told me not to look at the notes, so I have no idea what we're talking about.
I was talking to Chris Wellens over at Interworking Labs, who are our corporate patron right now.
We were talking about Rick Arthur's show, and she asked about the details of how security risks get exploited.
We often talk about how important security is, and there are these top 10 vulnerabilities and all of that.
But how do you go from buffer overflows and exposed pins to systems that are hacked.
How do you bypass the license check in VXWorks
so you can install their tools when your company needs them
and their licensing is broken?
Anyway, I thought we would...
It's the same.
It is, it really is.
But I thought we would put on our gray and black hats and think about security. We are not experts in this. So my goal here is to think about it as you would. You know, if we're, if we have a design, how do you, what do you, why are you even worried about buffer overflows?
As a working firmware engineer, how do you protect against these things or how do they work so that you can protect against them?
How do they work? Okay. I mean, it's fine. Like buffer overflow, I looked at it before the show
because I know that a buffer overflow can lead to a security problem, but I hadn't really thought about how. And so we're going to talk a little bit about that,
but it's all the things, the physical security and just how do you go beyond security is hard to,
well, here's what we mean. Okay. So where do we start?
I think we should start as though we were...
Full disclosure, I'm not a security expert.
I actually haven't really done much with this except, well, I guess I did some authentication stuff, but that was sort of a different area.
So I'm at least going to be bloviating.
Bloviating, that means to just talk without reference to actual facts.
I'm going to be speculating to the best of my ability.
Thank you.
Yeah.
I mean, if we were having a meeting where we were designing a product,
we need to use our heads.
And I'm sure somebody out there will tell us, well, you forgot X, Y, and Z.
And maybe we'll talk about those later.
That's fine.
Or this is wrong.
Whatever.
Tell us if we're wrong.
We're okay with that.
Okay.
So let's start with if you had a device.
Let's say they made a Baby Yoda and we're going to take it apart.
Okay.
Okay.
How is a Baby Yoda device? A Baby Yoda robot. Okay. Okay. And
we were going to take it apart, of course, without hurting the puppet part, because how
could you? And look at how it was made. What would be your first steps? I mean, that's
not a great example, because I don't try to exploit a baby Yoda robot.
That's reverse engineering.
There's nothing I can do with a baby Yoda robot to cause harm.
Okay.
I mean, this is part of it, is thinking about threat modeling.
Okay, so I guess we could just go for the Polycon.
Some sort of, I mean, to be interesting, it has to be something connected to me.
Okay.
Don't you think?
Sure.
I mean, because if you don't, then your only vectors are physical and the only harms are limited to its area of influence. I say Polycon because so often when there's an interview and somebody says, how would you design this?
They point to the phone because it's the only thing in the room.
But it's a reasonable thing. So if we wanted to hack into a
voice over IP speaker phone
in order to eavesdrop on super company secrets.
Okay, now how would you do it?
Okay, well, first, I'd want to have one.
Yes.
And there's two important things I would want to understand,
one of which is slightly easier than the other,
but I would want to understand how it communicates over the network.
So I want a good understanding of its network protocol,
how calls are set up, how data is transferred,
what those packets look like.
So I'd want to observe that with some calls,
maybe using Wireshark and other TCP dump and things like that
to get a sense of that.
So eavesdrop on it.
Yeah, eavesdrop on it.
And all that's easy, and it a sense of that. So eavesdrop on it. Yeah, eavesdrop on it. And all that's easy and it has to expose that.
You can't hide those kinds of messages.
Well, I mean, you can use TLS to secure.
Yeah, well.
But let's, I mean, this is the past.
This is not the end.
Let's not solve their security hole before.
Yes.
Let's assume for a moment that not all the traffic is encrypted from phone to phone.
And whether it is or not, this is the first thing you look at.
You look for the open doors before trying out the locks.
Right.
And then the harder bit would be, for most things, I think, like buffer overflow attacks.
The sort of thing where the first thing you're going to attempt, to back up a little bit, the first thing that I would attempt would be to present messages to it that it handles in a buggy way.
So sending it packets or packets with data in it that I can exploit some sort of buffer overflow problem.
But I think in order to make that work,
you kind of need to understand the firmware too, right?
I mean, that is definitely an easier path
than just trying all of the possible packets you can send it.
And you need to know the architecture, right?
Because if you're going to do a buffer overflow attack,
presumably you want to run your own code on it.
So you probably need to know what the architecture is
and be able to write code for that.
And so that's actually where I would start,
is with the question of how would you design it?
If I want to reverse engineer something, I start with, okay, what am I looking for?
If I have, whether it's a baby or a robot or a Polycon, it's how would I do it?
And then you open it up and you look for the things that you expect.
And then look for the things that you didn't expect and try to figure out what their purpose is.
Like what sort of things?
Well, let's say with a Polycon that is on a secure network,
I would expect it to have some sort of EEPROM or flash
that is probably spy attached.
I would expect it to have some sort of buffering system.
And if it has an LCD,
I would expect some sort of
display buffer,
probably external to the chip and SRAM.
Okay.
I mean, things I would look for.
Because it's Ethernet,
assumably,
I would expect it to maybe have an operating system.
Maybe not. These are pretty cheap, so maybe not.
No, it definitely has an operating system.
But that would give me the class of processor, which would then let me look around the board for what I think the processor might be.
And so I would then take pictures of all the chips and try to figure out what all the chips do.
Is this one just an audio decoder or is this actually something else?
See, that seems too hardware focused.
That is my approach. It may not be the right one.
Is that your approach to attack something?
And not that you've ever done it.
Yeah, exactly.
That would be my approach
because as you said
you want to get to the firmware
and the easiest way
to get control
of the firmware
is to do something like a buffer overflow
which I promise we will define soon
but to do that you have to understand
what the chip is and you need to have some expectations
of what it's doing yeah but some of that seems like periphery stuff to me like
you can get bogged down in codecs and stuff it's not really applicable to the problem i mean
it seems like you'd want to focus on where the firmware is stored how it gets compared to the
processor oh but if i figured out that it was running VXWorks,
that gives me a different surface to look at.
Sure, sure, sure.
And if I figure out it is using this form of LibC or that form of LibC,
that gives me a different way to peek in.
Maybe I can now look at the code a little closer.
So it's a reverse engineering problem to start with.
Yeah.
Without even trying to attack anything.
For me it is.
And then I would also look at, you know,
the things I would use in manufacturing.
I love command line prompts over serial.
It's just, I do.
And so I would look for one.
And most of those are pretty easy to debug.
If you can figure out the baud rate, that's the hardest part.
So, yeah.
But that's assuming, I mean, that's kind of the exploration stage.
Presumably you're headed toward, I want a remote exploit, because it's not, I mean, it's less interesting to be able to attack things that you have right in front of you.
Oh, absolutely. Because, I mean, if you want to break be able to attack things that you have right in front of you. Oh, absolutely.
Because, I mean, if you want to break something, a hammer is much easier than...
The goal is definitely a remote attack.
But if I find out that they do, in fact, have a spy flash and they keep their own certificates on it...
Right.
I'm almost there. I'm almost done.
Well, you're almost done to do what?
The certificates are going to protect, I guess, their communication
path.
I mean, this is all, how is it designed? Does it protect the communication path to their
server and their server uses the same certificates for every Polycon out there? Don't do that.
Then, yeah, that's bad okay so um i've been
promising buffer overflow uh i've been probably it's only been five minutes i know promising
the whole time so let's talk about that because this is one of the primary ways to get arbitrary code running on something.
And it worked a little different than I expected. I'm going to put the post that I liked in the
show notes. So if we don't make sense, feel free to go there and look at it. But the idea is you have a buffer of some fixed length, and it's maybe in this stack.
So main calls this other function, which reads something from the command line and puts it in this buffer.
Or from the network, or from any external source.
Any external source. Any external source. If you use some sort of string handling that doesn't take into account the length of your buffer,
you can copy too much information into your buffer.
Say your buffer is 100 characters.
Normally, somebody types in, you have a hello world and you want it to type in their name.
So they type in their name and it says, hello, Christopher.
And then it exits.
But that Christopher part was in a buffer that was 100 characters long.
Nobody's name is over 100 characters.
Why would we bother?
And if you haven't felt that logic at some point, I don't know.
So many times.
Command's never going to be longer than 35 characters. This number is never going to need more than 12 digits. Anyway, there's a fixed buffer size,
which is four times more than you thought you needed. So why would it break? And then you copy
in from some other source, from the internet,
from the command line, from your user,
however, and you just
copy into this buffer,
it sits on the stack, and as you
overflow the buffer,
as you go from...
Which it allows you to do because this is a bug
that somebody's written. They're not
checking the input link.
They're using strcat instead of strncat. They're using
strcopy instead of strncopy. Yes. Okay.
And so when
you called this function that said get and print out
their name, you put something on
the stack called your return pointer, and it tells you
where to go after you're done.
It tells you where to return to.
And as you overflow your buffer, you get access to that pointer.
You can overwrite it.
And if you think about that, as soon as you get to the point where you can
make it jump to any address, you can make it run your code. Because, because,
instead of putting in a hundred bytes of my name, I wrote this tiny little program that loaded other programs at the command line.
Hypothetically.
Okay, that's going a little bit too far, I think, at this point.
Let's just say it does something simpler.
Loading other programs requires...
Okay, okay.
I wrote this tiny little program to instead print out the password database the
password database to print out some form of some piece of memory something you you want hidden
and so i now take this function pointer that it's supposed to this return pointer
and i point it to the beginning of my buffer,
and now it executes my buffer.
And, you know, string copy doesn't care what's in the buffer
unless you have a null terminator.
So let's back up a little bit.
Okay.
We talked about stack,
and we didn't say anything about how that works.
Okay.
So the stack is a kind of memory in your program.
And pretty much every system, operating system or not,
your code has what's called a stack as a section of memory.
It's usually invisible to you.
Yeah.
And anything within a function that's a variable gets put onto the stack.
And the stack, it's called a stack for a reason
you put stuff on it and it grows in one direction as you stack things onto it uh and stacks grow
i'm gonna get this wrong downward in memory so if you if your stack starts at address 100 1000
and you push 100 hex bytes on it, now the stack pointer
moves down to 900.
Right? Okay.
So as you put more things onto the stack
it grows downward, but
when you
copy buffers
they go the other direction because
address is increment. So
you put items on the stack in a downward fashion
until it runs out.
But items themselves
get written in
increasing address order, as you might
expect. Arrays get written in increasing
address order. And
the stack is also used to
store state between
when you call functions. So it's
not just, here's your variables, it's also
here's the registers as they were before. Here's some set of registers as they were before I called
this function so I can get them back when I return to the function. One of those registers says
here's the function to go back to when you're done. So if I'm inine and i call printf before i call printf the c runtime says oh you're about
to call printf let me gather some stuff up so that what i mean the compiler does some of that
to the compiler you said front time or whatever the the yeah it's not java what there's a runtime
yeah but all right it's not a virtual machine.
It's the infrastructure to make things work.
Anyway, it pushes that state onto the stack,
and one of those things is the return pointer.
I already said that.
But now I'm kerfluffled because I don't know where I was.
Puts the variables on, it puts the return pointer on.
Right, so you're calling printf. So right before you call printf, it pushes that stuff on the stack. One of the things is, how do I get back
to main? Okay, so printf finishes, and when you call return, at return, that's when all that stuff
gets popped back off the stack, and it repopulates those registers where it was supposed to go,
including the return address, and then it calls the return address. Jumps to the return address. So what you're describing is you have the stack,
you get this name variable which gets pushed onto the stack,
which is 100 bytes long.
Somebody writes 200 bytes to it, and it goes off the top of the stack,
including the place where the return address was written.
So there's a kind of a chicken and egg problem there that i haven't quite worked out but well it has to be written first so yeah the return address
happens okay now right and then you call printf or stir copy and then it writes yeah so that that
works and one of the tricks here is you have to figure out how long
that buffer is. Yeah.
Well, it doesn't have to be
perfect, right? No, because if you just
write some bogus
thing in there,
you'll get seg faults.
As soon as you've overflowed
the buffer, you'll get a seg fault.
Or a crash. Right, right.
Well, depending on how good your system is.
A real embedded system will probably just trundle along happily.
Not if you trash its return pointer.
If you trash it with something valid?
Happily trundle along randomly.
I said valid.
Okay.
So somewhere within the buffer.
Okay.
But it's not going to segfault.
You might get the interrupt that you tried to run from memory that is invalid.
Right.
Or tried to execute an invalid instruction.
Maybe you got that, maybe you didn't.
But stuff like writing to zero, for example,
that's often not caught unless you've done special things
or have special hardware that can catch that.
I think you need the MPU on the Cortex-M4
to map out the zero page.
But we're getting off.
Yeah, I'm not sure you do, but that's a separate discussion.
Okay, so now we've sort of discussed the overflow.
And the reason people use this is because it's pretty easy to use.
You just send it a bunch of buffers.
You just send it a bunch of buffers. You just send it a bunch of characters.
And if it fails, then okay, now I have to figure out where it fails. And once I know where it fails,
I can figure out how to adjust the pointer the way I want it to. I can send it code that I want
to execute, and then I can execute that code. Okay, so that is bad, right?
I mean, as soon as somebody can execute code on your system, that's bad.
And whether it's command line or in our Polycon,
if we could do that over a generic internet.
Yeah, well, that requires several other steps, but yes, bad.
I mean, that's the golden ticket here.
Then you can eavesdrop on anybody's Polycon.
If you can just send something to a phone and say, okay, I'm going to execute code.
Now I also want you to make me a party to this conversation.
Right.
Yeah.
Okay, so that's buffer overflow.
That's one of the big ones ones and it's probably the one
that we talk about the most right i mean that's and it gets more complicated because well we said
you know the chief reasons why this is exploitable is people forget to use like
stern cat and things with an end the end in there says number of items and it doesn't copy any
further than n if you use the ones without n, it can copy indefinitely,
and then thus be your buffer overflow.
As people got wise to that and started doing the right things,
the ways to find buffer overflows got more and more complicated.
And so now there's like, I don't have a good example,
but it's like cascading levels of bugs. Like, okay, I sent this packet, which put this in this state,
which means it was ready to accept, blah.
And, you know, or there's a bug in the Java, JavaScript, JIT compiler, you know, all sorts
of very much more subtle things than merely, oh, this person forgot to copy a string properly.
So these buffer overflow exploits still exist, even when people are are being conscientious is what I'm trying to say.
But mostly it's because of multiple failures.
And if we could get our systems to require multiple failures, then...
And they get harder and harder to find because of that.
Yeah. Multiple failures just means it's more expensive for someone to hack your device than it is for them to build their own.
And that's part of threat modeling is figuring out where your okay
point is yeah there's the whole i don't look good in orange i don't want to see my face on wire on
the cover of wired i don't want to get sued for billions of dollars um yeah there's there's
different layers and this product can kill somebody so we have to be very careful or
this is a children's toy and the worst
thing that can happen is someone makes it say foul words, which then goes up on the internet and we're
embarrassed. Okay, that's embarrassing, but really they could have just faked that video. Whatever.
Okay, so that actually is number one on the OWASP Embedded Application Security
Top 10 Best Practices
list.
OWASP is, we talked about that with
Rick, they look
for making
for
security and
best practices. They
actually have a lot of information. What does it
stand for?
I don't know. It's like an O and a wasp.
Open Web Application Security Project.
Thank you.
You could have looked that up yourself.
Anyway, the first thing on the embedded application security list is buffer and stack overflow protection.
And it's using things like sprintf, scanaf, strcopy, and strcat.
The ability to corrupt memory and make it do what you want is bad. And we talked about the stack. That is one way
to do it. You can do
things from the heap. Other memories. You can do
things from global memory. If you made your
oh, I'm not going to put the 100 byte buffer on the stack. That's
ridiculous. Who would do that? I'm going to put a static-byte buffer on the stack. That's ridiculous. Who would do that?
I'm going to put a static here.
So it goes into the global BSS memory.
Yeah, you can still do stuff.
The neat thing about these exploits is they're also the same class of things
that are some of the hardest bugs to find.
Exactly.
Stack overflows, memory overwrites.
I mean, these are all things that people who have been working on this kind of software engineering for a long time have seen over and over.
And they're very hard to find sometimes, even when, you know, it's your program itself that's causing the corruption, not some outside actor.
So it can be very hard to defend against something that you can't even really detect at runtime.
Oh, yeah.
Easily.
Even if you've got a complete dump, it can be a core dump,
or you're watching it in the debugger.
It can be sometimes maddening what's happening,
because once this stuff starts happening,
all the state gets corrupted everywhere.
Well, and if you were modifying your buffer,
but your buffer didn't modify every point,
you might still get a good return address.
But now its variables are messed up because its variables were put on the stack.
It just is.
Stack corruption is bad.
You were mentioning the globals too.
That's a great, that's a great exploit because you don't know where the compiler and the
linker are going to necessarily put things.
You may see stuff in the file listed a certain way, but it's free to rearrange things.
So when you look in the map file,
and I've had to do this with memory corruption bugs in the past,
it's like, all right, I'm doing graphics.
Why is there, what is this data that's coming in here?
Who's overriding my data buffer?
The name of my variable is getting creamed, right?
So how do I find out what that data is?
Because it just looks like data.
Well, you look at the map file and it says,
oh, this one, the heart rate...
Heart rate buffers right before this.
The heart rate buffers right before the graphics,
you know, this graphics linked list that I have.
And that's causing a crash.
Now, why is the heart rate buffer?
And, you know, it's overrunning its thing.
And it's something from another component
of your embedded system entirely
that somebody else works on.
Not even in your files, not even in your directory, in a different module, but the map just, the linker decided, oh, let's put this next to this, it fits nice.
And so stuff, yeah, those kinds have done a good job, but did the guy down the hall do a good job with their component, which happens to be contiguous in memory with your data?
So it may not be your fault at all, but in a system you don't really know.
Yeah.
Well, that's reverse engineering, right?
Yeah.
But so many of these things I have, I mean, I've never used a buffer overflow for debugging something.
Right.
But I have had to identify buffer overflows.
So it is something I'm used to from an engineering perspective.
The second one on the list is injection prevention, which is best represented by Little Bobby Tables and XKCD Comics, where somebody intentionally does something bad.
Exposed a command to the outside world that you didn't intend to.
And so, you get a command into your command processor through weird means. So like in the Bobby Tables example, somehow somebody's typing SQL into a field that
just happens to get executed because you didn't detect that that was just regular text, not SQL
you should execute. I saw a good example of this where they were executing a command.
It was kind of like our Hello World example broken down.
Instead of Hello Christopher, you would instead have a command you wanted to run,
maybe always output data to a file, or less or more.
You pipe to those,
but you would, instead of, you know, file pipe more, you would instead say, um, my, my reader file, and it would do the same thing, format it for you. But if you have it run commands so that you can, you know,
look at the results of commands in the same format, it will run any command. And as,
as an engineer, I might be like, oh, okay. So my reader will run PS or some function. And because I'm me, I'm like, okay, it'll run PS dash EF.
I don't care. It'll do the parameters. But I'm only going to let them run one command because
that's safe. Yeah. But then somebody will put a semicolon in it and then they'll run an entirely
different command as you because
you're a command because that's what you've set it up to do.
It's about looking at what people send you and actually looking for attacks.
Unlike buffer overflow, which is something that happens to the best of us, injections usually are intended to be malicious.
That isn't to say that I haven't shot myself in the foot by failing to look at whether
or not I'm getting floats or hex or integers.
That's another way of looking at sanitizing your data.
So that's a pretty good one because you can
like little Bobby Tables, if you haven't seen the XKCD,
the thing is somebody names their child
like Robert drop table
all users colon colon whatever,
SQL query, SQL command in the middle of the child's name.
And then the child goes to school
and the school cannot function because they've...
Because they put that in their database
and it's a bobby and
then a command and executed and then deleted all users yes yes um and so we call him little bobby
tables and yeah you it isn't even always on purpose why can't names have semicolons in them
right just because that would break so many things. Yeah, and that's all about sanitizing your inputs,
which, you know, with the Polycom example
would be the network attack, right?
It could be a buffer overflow,
but it could also be by looking at their protocol
and sending various malformed commands,
can you disrupt the system?
And sometimes it's not just, oh, I want to hack into this and run arbitrary code.
Sometimes it's a denial of service attack, right? If you find something that crashes it.
If you, for example, wrote an implementation of OSPF for a core router
company and you just happen to discover that if you
accidentally miswrote one of the
packet formats and you always crash the Juniper routers.
Really? Whose fault is that?
It's Juniper's fault. It was Juniper's fault.
I mean, they should sanitize their inputs.
Yeah.
Yeah. But, I mean, that's a big deal, right?
I mean, if you find a packet that can crash a router,
it's pretty easy to get a packet to a router, right?
So you can do all kinds of damage with that,
take down systems, and then, you know,
if you just keep sending them, what's their recourse?
They're not going to get a firmware update real quick.
So, yeah, that kind of thing can be very insidious.
But this is about, when I think about engineering and debugging,
this is, I mean, your coworkers can definitely do this to you by accident,
by sending you data that you don't expect.
And so it's about designing APIs that make sense
and then checking to make sure untrusted users are using your API correctly.
Well, or making sure your API can't be used in a malicious way, which is harder, but...
It can be, because I don't really want to check to make sure that all Boolean variables
input are either zero or one.
It depends on what your device is.
It depends on what your device is and who's calling your functions.
That goes back to threat modeling, right?
If you're making a seismometer that you can access remotely, probably not a big target, right?
So you can be a little more relaxed on these things.
But if you're making an internet-connected toaster oven...
And you don't want to light somebody's house on fire.
...that you expect to sell 12 million of and they can be turned to a thermal botnet.
Yeah, you should be paying more attention to industrial controls or things that government actors like to hack into.
Yeah, so that was injections.
Injection prevention is the thing you should be looking for.
The next one is for more updates and cryptographic signatures.
Yes.
This is the two-meter exhaust port of your device.
I can totally hit womp rats.
No, actually, this isn't the two-meter exhaust port.
That's hard mode. This is like, I don't know.
I don't have a good analogy.
It's the open front door that you can't adequately lock.
So, yeah, this is, I mean, if you have user-upgradable firmware
or remotely upgradable firmware, this is really hard.
It really is.
Because you're delivering the code, right?
If you want to run arbitrary code, the easiest way in is on the you're delivering the code, right? If you want to run arbitrary code,
the easiest way in is on the truck that delivers the code.
Yes.
How did you break into the bank?
Well, you see, I dressed as money.
I got a job as vice president, opened the vault, and took all the money.
Yes.
Sometimes that's easier.
Yeah. Okay, so for more updates. sometimes that's easier yeah okay so firmware updates i don't know how much we can talk about that that's a whole for show i think the thing that i want to mention here is again back to
this is something i have dealt with as an engineer. I mean, firmware updates, yeah, I put them together and I send them out.
But I have had to hex edit firmware updates.
I have had to decompile parts of them in order to look for things to see if that bug was fixed,
even though it was supposed to have been fixed in this release, and nobody's quite sure which got compiled.
I have had to look at the crypto on it to make sure it was applied correctly.
To try to open it with the wrong crypto, just to make sure.
I've had to, you know, I always have to open it with the right crypto to make sure. There are so many things we do in debugging that, yeah, you have to think about this.
And doing it wrong in debugging often leads to it being an attack point in production.
Yeah, and the firmware thing, it's a different class of problem because it's not like I'm writing normal code.
Let's say I'm the GUI person.
My job is to write GUI code.
It's not foremost in my mind that I should be thinking about security.
Like, okay, if somebody interacts with the input panel in the right way,
they can do a buffer overflow and gain control of the system.
It's not top of mind.
Can you imagine in a refrigerator typing in your op code?
But it's not top of mind.
You're working on the feature you're working on.
Whereas with firmware update, that's kind of like, yeah,
this is the main vector through which somebody could take over my system.
And that needs to be like job number one.
And it's not just a security job, not, not really a firmware update job.
It's not just, um,
they can replace your code with their own,
which is, you know, that can be bad,
but they might as well have rewritten the system.
The hard thing is,
the thing that a black hat would want to do is to take your code and decompile it
so that they can read it more easily.
And that also often means...
They find your buffer overflows or whatever.
They find your buffer overflows.
But also, they can look at libraries.
And so you don't just get all opcodes
and horribly written C in a decompiler.
You also get function calls.
Oh, look, here's a string copy.
Oh, look, here's a mem copy.
And the more libraries you use, the easier it is to see. function calls. Oh, look, here's a string copy. Oh, look, here's a mem copy.
And the more libraries you use, the easier it is to see. I mean, that's getting the firmware and then
finding attack points rather than replacing the firmware.
But then you replace the firmware with what you have, and
since it's so close to what they had, it does exactly what you want, and they can't tell the difference.
Plus a little extra. Plus a little extra.
Yeah.
I totally agree.
Framework updates, it's just so hard.
And if you can buy a solution, you should be thinking about that.
It's something that is just getting harder all the time.
Yeah.
So next on my list is securing sensitive information.
Do not hard-code secrets such as passwords, usernames, tokens, private keys, or similar variants into firmware release images.
Have you ever done that?
No.
Really?
I don't believe so.
Hard-coded a key into... no.
Oh, no, not into a production release, no.
The manufacturing software I have hard-coded passwords and felt very bad about that.
Felt very guilty.
But the problem here is that,
so how are you going to secure sensitive information?
You can send it out to a spy flash?
You can send it to a file system?
So usually it's on the device.
You can send it to an expensive little part that all it does is this that or your soc has what's called a secure
enclave on it um which are you know sequestered little memory spaces where you put these kinds
of things that can't be read out except in certain ways or not can't be read out at all
they're right only and when you're doing
an authentication challenge, you say,
okay, here's my thing, and it returns you
the result of the cryptographic operation.
Stuff like that.
I've done authentication systems for consumables,
and we had a little extra device,
and that had the key in it.
It was not readable, theoretically.
And there was another one in the consumable,
and they had a little transaction.
And those chips both had the keys in them,
sufficient keys to do the cryptographic authentication operation,
but they were not in our software anywhere.
And so those had to get written at a certain place.
They had to exist in some software on some database, but it was in a computer on premises in a cage with access controls.
And we still got hacked. At that job, I did everything right until somebody figured something
out. Never quite sure what they figured out, but we kept adding on layers of things to try to prevent it.
I think what probably happened is that somehow the key got out.
Either at one point we got a shipment of the chips from the company
and they were defective,
and you could do a lot of things with the cryptographic chip
you weren't supposed to be able to do past the blown fuses so that was a little odd so something like that happened and
then once the key gets out it's very challenging because you might have thousands of units in the
field or thousands and thousands of consumable devices with the old key in them
on shelves and you can't revoke it. You can't change it. So that can be a real challenge.
But that kind of operation where you have keys stored, it's not just for external devices,
it's for firmware updates, right? For communicating with your cloud service and saying,
oh, this is a legitimate device.
So protecting those is rather difficult.
And that's more of a challenge because I'm not sure you can really hide some things.
Like for some things,
there has to be a key in Flash, right?
And you can make it easy to change
if something goes wrong, but...
I mean, making per-device keys so that you can't...
Yeah.
So that when you hack one device,
you don't get control over all of them,
but then that means you have to have a database
of all devices and what their current keys are.
And it doesn't work for certain situations.
Like the consumable one, you can't do that.
You can't ship a different version
of the consumable for every...
Device. Every deviceable for every device.
Every master device.
I mean, the only
advice they, OWASP,
suggests is, if at all possible,
sensitive
data in clear text should be ephemeral
by nature
and reside in volatile memory.
And by that, they do not mean the
global memory, because that's not really, I mean, it is volatile, but it's not. they do not mean the global memory because that's not really,
I mean,
it is volatile,
but it's not,
they don't mean the keyword.
RAM.
Anyway.
RAM.
RAM that is reused often,
not just RAM.
Yeah,
people make mistakes
with that too
and forget to,
I think there was a,
with like one of the
password managers,
which is a difficult job.
Yeah.
It's got a big target
on it too.
They had the master
password stored in RAM,
and they had intended, I think, to clear it right after use,
but it just hung around.
It's hard to know what computers do, because they stick things in caches.
Stuff migrates.
But that's all.
I mean, that's different than embedded, because it applies,
but when you're dealing with Linux and full operating systems,
there's all kinds of other considerations.
Let's see.
The next one I have is identity management.
User accounts should not be static.
You should be able to change your passwords and internal web.
I'm not even going to worry about that one.
It's for IT people.
The next one is embedded frameworks and C-based hardening.
Things like tool chains and libraries, frameworks, other people's code,
embedded Linux systems with BusyBox and Yocto and BuildRoot.
And things with executables that are so out of date,
they've got 100 cert advisors against them,
but it's hard to update the Linux that you shipped.
Or that one version of PSOS TCP IP that existed for so long,
had so many bugs, but it was in, you know, thousands of different products because
it was super cheap and everybody used it. Yeah.
I'm sure there are libraries now that are being passed around that, oh, yeah, I'm going to use
that because I used it in my last project and it made sense. And so the more monoculture we get,
the easier it is to attack because you can just focus on the attack on one
spot.
And embedded.
So many of those libraries are just kind of small company produced things
that don't have a lot of people working on them.
They're not probably thinking about security.
Some of them started in the late nineties or mid-90s or the 80s even,
and are these old legacy code bases that just hang around
because, hey, it's embedded.
We never change.
Bob's R-TOS. It's great.
And then somebody sticks a TCP IP stack on it from who knows where,
and then, you know, super easy to exploit
if somebody bothers to spend the time.
And when we say exploit here, we're talking about all the things we've already said.
We're looking for buffer overload runs.
We're looking for a dependency injection.
We're looking for common points of failure.
Okay, so use of debug code and interfaces.
Well, I mean, yeah.
It's always nice to remove all of the pre-production code
before you go to market,
but then how are you going to debug it in the field?
Is that a backdoor? Yes.
Yes, it is.
All those things that
make things easier to debug,
they make things easier to manufacture,
also make it easier to hack.
Right, because, I mean, that's what you're doing, right?
By nature.
You're opening your device specifically so you can modify
the deepest parts of it in an easy way.
Okay, you've opened your device so you can modify
the deepest parts of it in an easy way.
So, yeah, there's a balance there, and it's really hard,
and you have manufacturing folks yelling at you
because something's too hard to provision in the factory, right?
And then somebody makes a decision somewhere to make it easier without consulting someone and
suddenly all bets are off i had a cm that once refused to blow the security fuses on a board
i mean they're supposed to do it on every system. And what do those do? Those made it so you couldn't JTAG read out the code.
And they were just like, no, because then...
Then I wouldn't be able to read out the code.
No, they were like, oh, no, because then it can't be updated.
And when you send us new firmware, we won't be able to update it.
And we're like...
That's the idea.
Yeah.
Yeah, that is the idea. We. Yeah. That is the idea.
We are aware of that.
Please only do 10 at a time or something.
It was just,
they told,
they flatly refused.
They were like,
we will not do this.
And I mean,
I imagine they've had bad experiences where they blew 3000 fuses and the,
their clients said,
Oh,
we need to update this firmware and it's your fault.
You shouldn't have done that ahead of time.
Yeah, I understand why that happens.
But if your chip comes with security mechanisms, you should use them.
And you should figure out how to make them usable in a fashion that makes sense financially for your product.
Yeah, and it goes back to the threat model, right?
Who's going to attack this? Why?
What are the repercussions?
How much is it going to cost us?
And some of that doesn't occur until you've become a success.
Yeah.
It's like you might be thinking,
oh, you know, I'm going to sell 10 of these, it'll be fine.
And it takes off and you sell 1,000 and maybe 20,000, maybe 100,000.
And all of a sudden you get on somebody's radar as, oh, that's a big footprint.
Let's see how this works.
And it can start with, let's see how this works, to, oh, my God, this is so cool,
to, oh, look, I can just shut everybody's off.
Yeah, or I can mine a lot of Bitcoin with this.
So we're almost done with the top 10 for embedded applications.
Transport security level,
transport layer security, TLS.
Mostly for networks.
That's mostly for networks,
but it's a thing to consider.
Every time you are putting things outside your system, whether it's a spy bus or an Ethernet or Bluetooth, the security there has to be considered because it's a weak point.
All of your doors and windows are weak points in your house.
Okay?
Just, yeah.
Data collection, usage, storage, and with respect to privacy, yes.
I don't think that really belongs in the security list.
I mean, it's important.
It is security, but it's, I mean, it's database security.
And they're talking about leaked numbers and how that can be terrible.
And I agree.
I guess the point here is just to limit the amount of data you store.
Don't store your customer's bank account and credit card information on the thermostat.
Or do.
Or do, whatever. And the last one is third party code and components we've already covered
this it was already in the list too yeah man yeah all right anyway yeah security is hard
and security is hard because there's so many ways to do it wrong and because so many of the ways to do it wrong are the things that we do right as engineers.
What do you mean?
Like making things easy to manufacture.
Oh, I see what you're saying.
Yeah.
Being conscientious to your coworkers or to the rest of the company.
And the things we do to take shortcuts because our time is so limited often.
Yeah. And there's all the intentional backdoors we put in.
Speak for yourself.
But it's more, for me, it's sometimes the time.
It's like, yes, you should absolutely do per-key encryption per system.
And you should keep track of it.
And you should be able to turn off only one system.
And you should be able, if one system should be able to turn off only one system and
you should be able to, if one system gets hacked, to not affect any others. Yeah, the manufacturing
database is just hideous when you, I mean, sometimes it is totally worth doing that, but
most of my clients are going to say, how about we just put in one key for the first thousand?
And how am I going to say no to that?
They're trying to build a thousand units.
They've only got budget for 12.
It's a balance.
And that's why we do threat modeling.
How often do you do threat modeling?
No.
Never?
I don't have clients that need it right now.
I've done a couple.
And the last few jobs where that wasn't my
part of the job.
But to me, what you just did is
where I would start with threat modeling.
You take the list, you go through, you talk
about your product, you talk
about who might attack it, you talk
about what steps you need
to do to prevent it.
It's the same kind of thing you do with the hazard analysis
for a safety-critical device.
Yeah, so you list the things that could go wrong,
you give them a severity, and you list mitigations,
or you start to think about mitigations.
And then you sort them by severity and ease of fixing the mitigation.
Yeah.
Usually you score the mitigation for like how easy it is and then you subtract
and then you sort by what's left over and do the,
do the most severe ones.
Do the easiest to fix and the most severe.
You gotta be right.
I mean,
this is all estimation.
Yeah.
There's things you're going to miss.
So there's a whole whole other top 10 list for
Internet of Things, OWASP.
It's basically the same stuff, but a different order.
They do talk about default settings in devices
and how you should probably not
do that.
I came across some cameras recently, some web cameras,
and they were pretty expensive.
And they were specced to make sure that they had no traffic to parts unknown,
so they were really quite expensive. And they had the stupidest password and the stupidest username.
And it was easy to change.
And I went out and I looked online just to check.
And there were, I mean, people had identified huge, huge numbers of cameras you could get to with just the default root name and password.
Yeah, in some sense, you know,
it's good that those people are out there
because those are the easy things to attack
and people go for them.
Ignoring you.
But yeah, I mean, there's a stratum of the kinds of people who
attack things right there's the sophisticated people who are going to go through all the effort
reverse engineering looking trying to get the firmware out reading it understanding it finding
ways to attack and then you know producing a whole uh and whole exploit and then and then using it
and then there's the people who are just kind of along for the ride and they're going to these websites and finding,
oh, this is how you get into this product
and then going and doing it.
So
there's fewer of the people who are spending
the time to really understand and generate
the exploits compared to the people
who are just using
the exploits that have been published somewhere.
Yeah.
Absolutely. Because it's easy to use the exploits that have been published somewhere. Yeah, absolutely.
Because it's easy to use the exploits.
And that's the problem, right?
Once somebody, it only takes one person who's gone through the effort
to produce maybe 100,000 people in dark apartments.
I wonder how, I wonder what, this is kind of like how many golf balls are in the state of Kentucky.
I wonder...
Trick question. Kentucky does not exist.
I wonder the population of experienced security researchers,
experienced security researchers with a willingness to be black hat.
Yeah.
The population of, let's call them script kitties, and the population of software engineers.
I mean, is it, how many people are we defending against?
Is it 10? Is it 100,000?
I don't know.
I don't even know the scale.
It's probably hundreds of thousands
of script kitties are on that order.
It's probably
thousands or less of
well, I don't know.
And not everybody wants to do anything bad.
This whole camera thing,
I mean, you could pan and tilt so you could change the stuff,
but most people just didn't really care.
They were just doing it to look at parking lots and surf locations.
That can be bad.
It totally can be.
It can be used nefariously.
I've seen Batman.
Which one was it? The Dark Knight.
I got all the cameras. That was very bad for the Joker.
Were you on the Joker set?
It was a violation of the Joker's rights.
It was certainly an invasion of privacy.
And I don't think you can do what they do on the cop shows, but...
It can't. You can now with neural networks.
It'll just fill in something that looks right.
Something random.
Yeah, watch which database you use
for training on that one.
All right, I will
post the top 10
that we just went through.
I did want to point out,
I forgot, there are tools that you can
use to try to attack your stuff too.
And I don't have any offhand.
Oh,
OWASP has a tab here.
and attack your software,
find all the inputs,
send all kinds of random input,
fuzz them,
it's called fuzzing.
Fuzzing.
There's,
there's ways to harden your stuff
without just sitting and thinking.
You know,
kind of automated,
automated tests to find, find ways in, and to, to exercise your sitting and thinking. Kind of automated tests to find
ways in and
to exercise your APIs and things
that can be quite useful.
Yeah, so they have a tab
because that's what other people are using to find exploits
too, so you might as well try it yourself.
Embedded firmware, embedded
device firmware analysis tools,
and it goes through the hardware stuff,
but there are also some software links.
And it goes beyond GDB
and IDA, which is one of the
big decompilers.
And lists
things you can try. And if
there's any chance your
audience, I don't know
if they're customers,
is going to use these things,
you should absolutely try them too.
I'm sure that your boss will let you.
And by the way, could you record that conversation?
Because it's hilarious.
They also have a book that describes a lot of this stuff and how to think about it and
how to manage identity and whatnot.
So there'll be lots of links.
And all I can say is, no, you're not going to solve this today, but maybe it's one of those things that if you could just get a little better this week
and a little better next week, then maybe in 25 years we'll have good security.
Or if you just realize how big a problem it is,
and maybe you, like most of us us don't fully understand all this stuff.
That's a step forward too.
Oh, yeah.
Danger, Will Robinson.
And being able to talk about it.
It's not just security scary.
It's I can make the security better in these ways for this reason in this amount of time.
And we should do it because it will otherwise cost us that amount of money.
And as a manager, that's a much easier choice.
All right, so I guess that's it.
Thank you to Christopher for blabbing with me,
blabbering.
Thank you for listening.
Thank you to our patrons
for supporting us.
We don't know why you do,
but we're really glad.
I mean, it's really nice
to have somebody say,
yeah, what you do
is interesting enough
and important enough
that I'm willing to kick in
a few bucks a month
to encourage you
to continue doing it.
So it's just a weird sort of validation.
Also, it pays for a lot of stuff, which is awesome.
And finally, thank you to our corporate patron, IWL, Interworking Labs.
So now we have Winnie the Pooh.
Oh, right. So now we have Winnie the Pooh.
Oh, right.
He's stuck in the door to Rabbit's cave, and Rabbit is hanging his washing on his feet.
I feel like he's been stuck there for a year.
Christopher Robin's in the front.
So he took hold of Pooh's front paws, and Rabbit took hold of Christopher Robin,
and all Rabbit's friends and relations took hold of Rabbit. And they all pulled together. And for a long time, Pooh only said,
ow, and oh, and then all of a sudden he said, pop, just as if a cork were coming out of a bottle. And Christopher Robin and Rabbit and all Rabbit's friends and relations
went head over heels backwards, and on top of them came Winnie the Pooh.
So with a nod of thanks to his friends, he went on with his walk in the forest,
which started like a year ago, humming proudly to himself.
But Christopher Robin looked after him lovingly
and said, silly old bear. Embedded is an independently produced radio show that focuses
on the many aspects of engineering. It is a production of Logical Elegance, an embedded
software consulting company in California. If there are advertisements in the show,
we did not put them there and do not receive money from them.
At this time, our sponsors are Logical Elegance and listeners like you.