[ Silence ]
>> All right.
Welcome back.
This is Lecture Eight, Security.
Only one lecture to go after this.
So summer is almost over and tonight we start talking
about all of the dangerous things you might currently be
doing in your code, specifically in the context of PHP,
and MySQL, as well as in JavaScript.
So of the topics we've discussed thus far this semester what are
some of the possible threats that we've encountered,
possible security issues we've encountered?
What comes to mind?
Ben?
>> SQL injection attacks when typing in scripts
as [inaudible] parameters.
>> Okay, good.
So SQL injection attacks
which we'll see a concrete example of today.
Typing in Script, JavaScript code into like a form
and accidently tricking the user into displaying
that on some webpage or executing that on some webpage.
We'll see an example of that as well.
Other possible threats?
Isaac is looking to Axle for an answer.
What do you got Axle?
>> It's not really a possible threat
but if you don't encrypt your data over HTTPS it's going
to open for anybody to see
and hijack your session and all of that.
>> Okay, good.
So back in lecture zero we talked a bit about HTTPS,
or SSL, and how not using it obviously means your traffic is
completely unencrypted and what the implications of that are,
particularly for what kind of information?
What kind of information is at risk
if you're using HTTP versus HTTPS?
Yeah?
>> Well your data is really sent unencrypted so anybody
on the same network can see that connection
and get all the information that's sent.
>> Okay, good.
So anyone on the same network can sniff and read any
of the data that you're transmitting,
and frankly on the entire Internet, right?
Anyone between you, point A, and say Amazon,
point B. If Amazon's not using HTTPS at all, in theory anyone
with access with any of the various routers
in between point A and B count sniff that traffic.
So it doesn't just have
to be wireless connectivity nearby you.
All right, so let's try to flesh some of these things out
and most of you probably aren't familiar
with a protocol called Telnet.
You might be familiar with a protocol called FTP.
Does someone want to pluck off one, or either,
or both of these -- what these protocols,
Telnet and FTP are or are used for?
Isaac?
>> Well, I know FTP, like file transcript protocol,
means to send like files from one computer to another.
>> Good. So, file transfer protocol is FTP,
it's used to transfer programs, files,
anything from one computer to another.
There's a got-you with it,
it's that it's completely unencrypted,
and yet many webhosts support only FTP,
or many webhosts offer FTP but don't really warn customers
of the potential concerns with it.
So what does it mean concretely
if you're transferring stuff via FTP?
Right, if you have a webhosting account, maybe it's DreamHost,
maybe it's someone else,
by nature of the content you're uploading you want the whole
world to be able to see your GIF's, and JPEG's,
and HTML files anyway.
So what's the big deal if moving the files from your computer
or even your appliance from this remote server is
all unencrypted?
Axle?
>> Well, say that you send more important stuff
than just images.
Say you send the PHP configuration file.
>> Good.
>> It contains the database name, username, password.
And once somebody has that they could essentially log
into your database and get everything.
>> Yeah, absolutely.
So if you're sending more
than just publicly accessible content like, HTML files, JPEGS,
images and the like, but rather you're sending things
like your PHP code, which has your intellectual property,
or your configuration files for PHP,
which might have your database usernames and passwords,
and God knows what else,
well now you're sending this completely in the clear
for anyone on the Internet, or anyone in Starbucks,
anyone between point A and B to potentially intercept.
And even worse than that, what also is going in the clear
if you're not using any kind of encryption when you use FTP?
Axle?
>> I think you're login credentials
for the actual server.
>> Exactly.
Which is the absolute worse part of the whole story.
Which is that your username
and your password are sent completely in the clear,
which means who cares if everything else is sent
in the clear, anyone else can just login into the server
after the fact and do whatever they want with your account.
So in short, if you end up signing
up for some commercial webhost,
if you end up supporting your own server locally,
there is no reason today to use FTP unless it's maybe
on a local isolated network.
But even then it's just bad practice
because you can use quite easily an encrypted protocol,
one of which we're about to see,
one of which isn't mentioned here, but it's called SFTP,
secure file transfer protocol, which actually has encryption.
And these days there is really no good reason not
to use something like SFTP.
So Telnet is a little more dated,
but it's still used for various things.
It's a protocol that's used to control one computer
from another, whereby if you think about your terminal window
within the CF50 appliance.
When you open a terminal you have a black
and white command prompt.
Well Telnet is a protocol that allows you to access a black
and white command prompt like that but from another computer.
So I could be sitting at home and I could use Telnet back
in the day to connect to a Harvard server
and then have a blinking prompt on my window --
on my screen, but that computer
that I'm actually controlling is somewhere else on campus.
Or conversely, in theory you could telnet, as a verb,
from your own laptop to the appliance in order
to get a prompt, but these days you would instead use something
called SSH.
Indeed the appliance does not have Telnet support enabled,
you cannot connect to it insecurely via Telnet,
rather you have to use SSH, which encrypts the traffic.
Even if you're just trying to connect from your Mac or PC
to the appliance in order to pull up that terminal window.
And though I keep describing it as a black and white window,
of course some of you might have noticed that it supports color
in theory with various programs,
but it's still a command line interface ultimately.
So, HTTP, this one we've definitely talked about.
What kinds of things are sent in the clear
when you're using just HTTP and not HTTPS?
What kind of stuff is at risk?
How about Jack?
You have the look of an answer on your face.
>> [Inaudible] together here.
Put me on the spot here.
>> I know, I have time.
It's okay.
Come on. We can do it.
HTTP, you have -- it's completely sent in the clear.
It's used by a lot of websites.
So what kind of stuff might be sent in the clear?
[ Inaudible Speaker ]
Okay. Session, what's a session though?
>> The very same file that is on your computer
that tells a website or a webhost
that you are the one currently logged into them.
>> Okay.
>> And someone can steal your session and then go
and pretty much login as if they were you.
>> Okay, good.
So recall that we discussed this sort of higher level concept
of a session that's incarnated in PHP
with the superglobal called $_SESSION
that it gives you the illusion of having really a sort
of persistent connection to some user even though they might be
visiting you with a browser every few seconds
or every few minutes.
Nonetheless, you're still provided
with the storage even though HTTP itself is stateless.
Now you're not technically transferring the session back
and forth across the Internet via HTTP.
What are you actually transferring
across the Internet via HTTP that enables sessions to exist?
>> It's some sort of session ID which is a really long stream
of letters and numbers you can't really guess.
>> Perfect.
So it's a really long sequence of letters and numbers
and this is specifically an example of what?
The session idea is implemented with what feature of HTTP?
Or how -- where is this sent?
Let's see, someone else?
So like I've totally -- I agree
that HTTP involves sending this unique identifier
that somehow implements sessions but how?
If we opened up that virtual envelope
where in the contents inside would it be -- this ID?
Or what's it an example of?
No one wants to make eye contact.
Axle?
>> I mean sending -- it's send in the headers
as the session cookie.
>> Okay, good.
So it's sent in the headers as a session cookie,
or just as a more general notion of a cookie.
Right? There's a set cookie header that a server sends
to a browser and the set cookie header allows you to set a value
for some key and in the world of PHP that key happens
to be called by default PHPSESID, in all caps,
but that's totally arbitrary.
And the server meanwhile sets a value for that key which is,
as Jack says, a big random sequence of letters and numbers,
and then every time the browser revisits that same website
that it originally sent it, the set cookie header,
that browser is essentially reminding the server,
"I am this ID.
I am this ID."
And weeks ago we kind of likened it to a handstamp that you get
at a club or an amusement park.
So that it permits you access even after you're first time
through that gate so that you can kind
of come and go as you please.
Because that handstamp is sort of reminding the guy at the gate
that you have been here before
and in this case it's being even more specific,
it's reminding him who you actually are, not in terms
of your identity but in terms of your unique identifier.
So HTTP is dangerous in terms of its lack of encryption
because the session ID, if it's being sent back and forth
across the wire, it doesn't contain itself private
information, it doesn't contain your username, your password,
your credit card information.
Because again, as Jack said, it's a big random number
or big random sequence of letters and numbers,
but the catch is if you're not encrypting it what's the
implication if someone sniffs it and steals it somehow
by listening to your traffic?
Axle?
>> Well they can take your session and pretend
that their computer is actually my computer running the
same session.
>> Exactly.
>> [Inaudible] website, that website is going to recognize
that website and it's going to say, "Hey,
you're already logged in."
It's going to log them in and it's going
to display the login -- the secure side of the page.
>> Exactly.
Right. If all it takes to remind a server
who you are is presentation of this big random sequence
of letters and numbers and a bad guy is able to steal
that sequence of letters and numbers from you,
by just listening in on your traffic wirelessly,
or even poking around on your computer, and then copying
that big random sequence of letters and numbers.
And then he is smart enough to know how
to configure their computer to transmit that same cookie value
with a cookie header, well he or she can just pretend to be you
and the server doesn't really know the difference.
So we'll come back to how we might mitigate this,
but that's one of the key shortcomings of just using HTTP
for anything sensitive, not to mention the fact
that if you're submitting a form that has your username,
your password, your credit card number,
if the site is itself not using HTTPS and all
of that stuff too is going in the clear,
and so more private information could indeed be taken
in that case.
MySQL meanwhile is similar in spirit to the rest
of these protocols in that it itself is not encrypted.
Recall we talked briefly a couple lectures ago
that generally you want your MySQL server sitting
on the same network as your web servers, even if it's
on a different physical machine
so that your traffic is only going
over your own local network and not connecting
to some remote database server elsewhere.
So, what are some
of the problems we did solve though thus far?
Well, recall there's this feature in the appliance,
which I think I mentioned ever so briefly, or maybe not even,
suPHP, substitute user PHP.
Oh we did have this conversation.
Recall that one of the problems with a web server in general is
that if you are running that web server as root, that's very bad,
and thankfully it's rarely done these days.
Why is it bad to run a web server, which is just a program
that serves up webpages,
as the administrator account, so-called root?
Jack?
>> If anyone ever breaks into the account via some PHP hack
or something they can literally wreck anything on the server.
>> Exactly.
>> [Inaudible] has root access.
>> Perfect.
So if the web server is running with administrative privileges
as the so-called root user
and that web server is executing buggy code, that you
or someone else wrote, buggy in the sense
that there's something stupid in there
that lets a user execute some command.
The scary part here is that who's going to be executing
that command if a bad guy is taking advantage of that bug
or vulnerability in the software is going to be executed as root.
And root unfortunately generally has privileges
to delete everything, download anything, change usernames,
passwords, install anything.
It's just there's really no constraints
on that particular user.
So, running anything as root is generally bad because again,
if what root is running is vulnerable to being taken
over by a bad guy, or tricked
into executing some arbitrary command,
well then that command's going to be run as root and at
that point who knows what the bad guys has done
to or with your system.
Axle, question, comment?
No? Okay. All right, so we can fix this by running a web server
under a different username.
Something like Apache, or HTTPD, or some systems run it
as literally an account called "Nobody."
And in all of those cases the user
in question does not have administrative privileges.
So the worst thing that can happen
if you're running your web server as Apache or as HTTPD,
as the appliance does, is that the only account
that can be compromised,
the only account whose files can be deleted, the only account
that can have some damage done to it is the HTTPD user.
Now that's not great because that means a bad guy could take
down your entire web server, or delete the logs
for the web server, or any files that the HTTPD user owns,
but at least that's one user you can just remove the whole web
server account, you can blow away all those files
because root hasn't been compromised
and you can reinstall.
But there is a problem.
If your files are being read and executed by Apache,
the web server, what do you have
to chmod your files to be in that case?
If you are someone like J. Harvard, or Axle, or Isaac,
if you have your own user ID and yet the web server is running
as a different username, like HTTPD, what do you have
to set the permissions on your own files
to for this to all work?
Previously it didn't matter because root can read
and write any file so it doesn't matter what the permissions are.
He has unfettered access.
But HTTPD wouldn't.
So what do you have to chmod your files usually?
And chmod remember is the command for changing the mode
of a file which means the permission, 644, 711, 700,
A plus R, A plus X, whatever the case may be.
And don't worry if you don't remember the codes,
but in words what kind of permissions do your files need?
Yeah?
>> This is probably not the best solution
but you can set all plus read on a group of all the users
that are allowed access, including Apache.
>> Okay, say that once more.
Set what to read?
>> All plus read.
>> Oh, okay.
>> On the group -- on a group, like students
or [inaudible] on a web server.
>> Okay, good.
>> [Inaudible] all the accounts that are allowed to access
that file, including Apache.
>> Okay, good.
So in theory you could put all of the users
into a group called students or something like that,
and make sure that Apache is in the same group,
and then you can give the group read access, and the command
for this, recall, is not A plus R, but would be G plus R
in this case, chmod G plus R, group plus readability, right,
to whatever file or directory is in question.
All right, so that's not bad.
It's a little more work and it's a little weird I would say
that you have all of these students for instance or all
of these customers in a group and the web server
who is not a customer or a student in that same group.
It's a little weird, but possible.
But if we don't like that we could just do A plus R,
all plus everybody can read the files,
and that seems reasonable right?
Because if my GIF's, and JPEG's, and HTML files are
on the Internet they're meant to be read.
What's the big deal about giving read access to all students
or to Apache and other accounts on the system?
Jack?
>> Well that means if I really wanted to I could find a way
to easily see your plain text PHP without having
to go through any hoops.
>> So in this case if you're on a shared webhost
and you're a customer, someone else is a customer,
and all of you have your own websites, which is common
on a virtual hosting environment like, DreamHost or the like,
but the web server by necessity needs you to chmod your files
to be world readable, those files then are going to readable
by anyone else on the system.
For instance, if Axle has chmoded his files
to be world readable just because Apache needs them to be.
Well if Jack if a malicious user on the system
and knows Axle's username he can essentially start poking
around his around using CD or LS or the various Linus commands
with which you could do this, and see Axle's PHP files,
inside of which might be passwords,
usernames, and so forth.
So it doesn't feel ideal,
it feels like we're giving too much access to the world here.
Yeah?
>> But the PHP source would never be distributed
over the Internet, right?
Because it's actually is configured never
to display the PHP source unless there's an internal
server error.
>> Good. Correct.
So, in this case your PHP code is not at risk for being spit
out on the Internet without being interpreted.
The threat here is that Jack is just another paying customer
on the same server.
So at least it's not billions of people,
who could potentially see your code,
but it's at least a few more malicious users or just curious,
nosy people who are poking around the account.
So thankfully there do exist protections against even this,
and even then the appliance has this built
in even though it's not strictly necessary
if there's only one John Harvard and the appliance isn't
on the whole Internet.
But the principle is the same in that suPHP and other software
like it allows you to specify that the username
that should be used to execute this PHP file should
be jharvard.
Shouldn't be HTTPD, definitely shouldn't be root,
it should be whoever actually owns the file.
So the idea here is that when you are running Apache
in the appliance, which I'm currently doing as,
is anyone else running this version of it, and I'm going
to run a command that we haven't run before but just
to poke around, ps aux and then grep httpd.
So this is a fairly cryptic sequence of symbols
that simply gives me a process list, ps, with a bunch of flags
which means show me everything.
The pipe means send the output of ps to the command grep,
and the grep command is like a find command.
So I'm saying spit out the process list,
all the running programs on the system,
like the activity monitor or the task manager in Mac OS
and Windows, respectively.
And then pass that output to grep and search for httpd.
And I'm going to hit enter
and what you see here is, oh, I lied.
The username that's being used is not in fact Apache it is --
sorry, not in fact httpd, its Apache.
So in this case each of these rows says
that there's a program called httpd running on the system,
and that's to be expected, right?
The appliance runs a web server, that's how project zero,
project one works in the appliance.
There seems to be a whole bunch of them,
but more on that in a moment.
But if I scroll to the left you see in the left most column
who the web server is running as here and almost all of those are
as Apache, and it's those rows that are going to be used
to actually execute user code or serve up user files.
But you don't see jharvard's name, but that's fine
because notice what's going to happen here if I go
into my vhost directory and my appliance directory.
Here's all of our examples from last time.
I'm going to do a quick and dirty demo here, demo.php.
And I'm going to say echo "hello";
just as a quick quick test.
Okay, and let me zoom out.
Let me open by browser, and let me go
to http://appliance/demo.php.
Okay, so now we're -- this is just sort of,
we did this weeks ago.
So now let's do something a little more interesting.
Let's so echo 'whoami;
Now notice I'm using back-ticks mean execute the command
called whoami.
So whoami is a program on the system,
and I can demonstrate this at a command prompt.
So let me pause that program and run whoami enter,
and I'm indeed jharvard.
If I go back in here, the fact that I'm putting whoami
in the PHP program means
that when this file is interpreted it's going
to inform me who is interpreting the file.
And so the litmus test here is, is it root?
Is it apache?
Or is it jharvard?
Hopefully its jharvard,
otherwise suPHP is not in fact enabled.
So let's go down here to the appliance again.
Let's reload, and indeed I'm running the web server
as Apache.
And if I weren't suPHP we would instead see the username Apache
in this case.
As an aside, too, another thing that's useful diagnostically
when you're setting up your own webhost,
which some of you might want to do after the class ends,
there's a function in PHP called phpinfo.
Generally you would not write a program
and then make it available on the web that echoes phpinfo
because this dumps all of the details
of the current php installation, including its version number
and all of the various modules that are installed.
But if I go up here and click
on reload this is what phpinfo spits out.
It deliberately spits out a whole bunch
of HTML that's crazy cryptic looking at first
but this configure command essentially tells you how the
people at Fedora, who oversee this operating system,
decided to compile this version of PHP.
So PHP itself recalls a program, it's an interpreter;
it's an executable program that happens to read
or interpret other programs.
It itself is written in C, or C plus plus most likely,
and this is the command with which they compiled PHP
from source code into its binary.
And all of these various flags essentially tell you what
features are enabled.
But there's an easier way to parse this.
If we scroll down we see a whole bunch of stuff.
For instance, I mentioned weeks ago php.ini is the configuration
file that's typically used, and this output is confirming
as much, that the config file we're using is
in the etc directory, called php.ini.
We have, let's see, what are other particulars here
of interest.
You can see that there's apparently built in bz2,
which is compression support, some kind of calendar support,
some kind of -- let's scroll down -- woops.
Let's scroll down even further to --
let's see if we can find this.
DOM support and so forth.
So PHP has a whole bunch of modules
that you can add optionally,
and long story short this output just informs you what's
actually there.
So this is useful because sometimes
when you're using commercial webhosts they might have certain
features on that you did not have on in the appliance.
They might have certain features off, and running this, say,
on your local machine, your Mac, your PC, your appliance,
and then also running this command on the remote webhost,
like DreamHost, will give you a sense
of what the differences might be.
For instance, there is a feature of PHP called Magic Quotes
and this is largely been disabled these days,
but Magic Quotes did this.
Anytime a user used GET or POST to send input to a PHP file,
PHP, if Magic Quotes were enabled,
would very presumptuously escape all of the quotes in that input.
So anytime there was a quote PHP would automatically put a
backslash there.
The upside of this is that if you then insert
that into your database you're already safe, for the most part.
Right? Because all
of the potentially dangerous characters have been escaped.
And we'll come back to SQL injection attacks in a bit.
The problem though is that if you then call MySQL real escape
string, or use PDO, or the equivalent,
it's going to escape the escaped characters.
And so a symptom that just the other day someone was seeing was
that her code was spitting out
"/" marks all throughout her website,
and it was because not only was she escaping user input,
as is good practice, the web servers presumptuously doing it
and do just a lot of bad things happened aesthetically.
So in short, this is not a good feature
where you should outsource your security to the web server,
you should be doing this yourself in code.
So this is something too that can be helpful diagnostically.
And if I search for this, let's see if we can find it in here.
Magic -- yeah, there it is here.
So, enable-magic-quotes, but we've disabled it elsewhere
in the configuration file even though Fedora enabled it
by default.
All right, so finally, suPHP then ensures what?
So, if your PHP files are executed as you, jharvard,
or Axle, or Jack, and you screw up, and you write buggy PHP code
that somehow allows someone on the Internet to trick you
into running commands, not just whoami,
but maybe the delete command, whose files, whose accounts are
at risk when using something like suPHP?
Jack?
>> Only their own.
Right? You can't affect other customers,
you can't affect the root account,
you can't affect the web server account.
So in general this is a very good thing.
Meanwhile, files like images and CSS files and HTML files,
those are just served up, not as you, but as Apache itself
because it doesn't matter.
Those are static files; they're not programs being executed.
So suPHP really just applies here to PHP files.
All right, so you guys proposed cookies earlier
as a potential threat and here's one such example.
So these are HTTP headers.
Two hundred at the top signifies what?
Don't say okay.
Yeah.
>> Everything -- well, it's really okay,
but that the page has been received by the client
and there's no error [inaudible] server side.
>> Okay, good.
So it indicates that there was no error on the server
and that everything is well, it's been received okay,
and indeed everything is okay.
So this is in contrast to something like 404, 401, 500,
all of the various numbers that we sometimes see on our own
or other people's websites when mistakes have happened.
But here, 200, you rarely see and in fact you'll only see it
if you take a look at the HTTP headers,
because it means all is well.
So we see some other information.
Date of the current web server, when this response was made,
the server's name and version number, X-Powered-By.
Why are these included in the headers?
Axle?
>> Really no reason other than [inaudible]
and just Apache selling their product.
>> Which is free, in fairness.
>> Yeah. No, no, no, but they are telling people about it
and it could be a potential security risk
because you are telling people what version
of PHP you are running.
>> Good.
>> So if, for example, we saw an older version in the PHP
and later we had discovered like a flaw in that,
something that you do with that, you would know that,
well this server's vulnerable
and now you can search the Internet for those servers.
>> Exactly.
So one is branding, that's why it's there for the most part.
But two, the downside of this is
that you're telling the whole not only what you're running
but what version of it.
So as Axle says, if there's somehow a flaw discovered in PHP
or in Apache, and it's in a specific version of one of those
because it was introduced accidentally at some point.
Well now, you've just told the whole world that hey,
I'm vulnerable to this error and if someone is kind
of like aggregating that information and hanging onto it
for a rainy day the moment the world realizes that oh,
PHP 5.3.3 is buggy, let me go ahead
and wage my attack using the list I gathered in advance
by poking around on the Internet to compromise those servers.
So you're just making it unnecessarily easy
for the adversary.
So this kind of stuff is typically on by default
but where can you disable something like the Apache line?
It's version number?
Where would you go?
So if you agree that this is not necessary
and not great how do you go turning this off?
Jack?
>> Isn't it somewhere in the httpd.conf?
>> Good. Yeah, so there's this file we keep referring
to httpd.conf.
It's generally somewhere in the etc directory,
the et cetera directory, and you just have
to find the appropriate line there that has to do
with OS tokens, which will reveal whether or not --
tokens, whether or not this will be displayed.
And how about something related to PHP, X-Powered-By,
how do you get rid of that?
Axle?
>> [Inaudible] to the php.ini.
>> Yeah, exactly, php.ini, the config file
for PHP specifically, there's a directive
in there called expose php, which by default is
on you just have to change it to off
and then restart the web server.
All right, so more interesting is this expires date.
This is kind of weird, right?
I definitely didn't make this example in 1981 and
yet for some reason there's mention of 1981.
Thursday, 19 November, 1981 in my headers, for some reason.
Expires. Why is this here?
Frankly, the Apache version two and PHP 5.3.3 did not exist
in 1981, let alone the web.
At least in this form.
What could that possibly signify?
Yeah? Scott?
[ Inaudible Speaker ]
Okay. So in this case it's actually not the expiration date
for the cookie, though that's on the right track,
but it's the expiration date for the page.
So if a browser and server are trying to optimize so as
to not re-download this content unnecessarily
if it hasn't changed,
the expiration here is telling the browser
that this page expired in the past,
which means you should always re-fetch it.
And this is actually just kind of a stupid convention;
essentially what most websites do is if you want
to disable caching or try to disable caching of things
like HTML files that are generated by PHP,
or really whatever file this is referring to here,
you specify that this page expired like 10 years ago.
Right? So then you don't do like a minute ago,
you don't do an hour ago,
just in case there's a bit of clock skew.
You choose something that's really far in the past so that
when the web server -- when the browser receives this it's going
to realize wow, this page is really old,
the next time you request the same URL I'm going
to definitely request it again and not go to my cache.
So not all browsers historically have respected all
of these things, so we have an additional header here,
Cache-Control: no-store, no-cache, must-revalidate.
All these possible directives trying
to really discourage caching.
So in general you'll find that this is a combination
of techniques that people use for various browsers.
Pragma: no-cache is yet another header that's meant
to further discourage caching.
At the end of the day the browser can still do whatever it
wants, so these various headers exist really
to really encourage the browser to cooperate and not cache.
But there in bold is our Set-Cookie header, PHPSESSID,
big random sequence of letters and numbers, path,
and Set-Cookie: secret equals 12345 is not a session cookie,
but what are some of the takeaways here?
So one, the set cookie here does not seem
to have an expiration time associated with it.
It's not -- there's no mention of seven days
from now, an hour from now.
So what's the implication?
Axle?
>> Well, it's going to live forever
so anybody finding your computer in a week will be able
to see the cookie and anyone -- yeah.
>> So, careful, it's actually the opposite in this case.
So PHPSESSID -- so when you set an expiration
to zero whereby you don't have an expiration
that actually means the opposite which is that this only going
to live for the life of the browser.
So as soon as you close your -- quit your browser or even worse,
restart your computer,
that session cookie is going to be lost.
The server might still have the contents of your session stored
around in a temp file or in a database,
but your browser is not supposed
to resend this cookie once you have actually quit the browser.
Now, changing tabs, sometimes the behavior is not quite
predictable but generally
until you quit your browser session cookies might linger,
but a session cookie by definition is meant to live only
for the life of the browser actually running.
When you quit it, it should go away.
By contrast if you actually saw an expiration date next
to path here, path is slash, just signifying the root
of the web server, then you could specify
that this cookie is in fact good for a week, a month, a year,
and you could typically do that yourself if you wanted
to remember something for some amount of time.
So the second Set-Cookie line here is just stupid.
It seems that the programmer
of this webpage has specified a secret key of 12345.
In other words, feels like the website is trying
to remember your password by storing it in a cookie.
So what is bad about this?
Well one, there's absolutely no reason as we've seen
to store the user's password in a cookie.
It suffices in PHP through all of our login examples just
to use the session and just remember the user by way
of this random identifier.
You don't have to have the user send you his username
and password, again, and again, and again.
So this would be indicative of bad practice
or at least an opportunity now for a bad guy to kind
of do something malicious with that.
Yeah? Axle?
>> I have a question.
When I work with cookies [inaudible] specify which domain
and sub-domain the cookie was valid in,
so not specifying [inaudible] that make the cookie valid
in all sub-domains of the root of the path?
>> Exactly, in this case.
Yeah. So, if we had visited foo.com, the cookie is valid
for foo.com and anything above it.
So dub dub dub foo -- bar.foo.com.
or the like.
>> Would that be a security threat as well
if you were running a big site that has multiple sub-domains?
>> It's a good question.
Potentially yes.
If you're running a big site with multiple sub-domains,
or different applications, web applications running
at different sub-domains, absolutely.
Generally you should put cookies
in the most narrowly defined cookie space as possible.
So if you have a website that is, again, foo.com,
and you have a.foo.com, b.foo.com, c.foo.com,
all of which are different applications maybe
with different users, different functionality,
then you should really be setting your cookies
in a.foo.com, or b.foo.com,
and nothing should go in foo.com itself.
Really good point.
You can also mitigate this in some part by,
as we saw with mod rewrites,
the ability to redirect the user to different URL's.
If you want to standardize not on CS75.net,
but dub dub dub.CS75.net, you can ensure
through a redirect mechanism
that you're only planting the cookies
in the DUB DUB DUB version ultimately, which can be useful.
All right, so let's push a little harder
on this cookie issue in session hijacking.
So session hijacking, again, to be clear, refers to the process
of someone stealing your cookie somehow,
whether by sitting near you in Starbucks, or having access
to the routers on the Internet between Points A and B,
and then presenting it to the world as their own.
Now how can go about hijacking someone's session?
Well physical access.
If you have physical access to someone's computer how do you go
about finding their session cookie?
Yeah, Jack?
>> You find their cookies folder
and you take whatever is in there.
>> Yeah, exactly.
You can poke around in some operating systems,
in some browsers, literally to a folder somewhere
on the hard drive that contains cookies.
Now in fact, the folder tends not to contain session cookies
because it tends to contain persistent cookies
that have an expiration that's not zero,
but in this case you can probably open like,
about colon cookies, or about colon history.
Generally in all browsers you can start poking
around your own history.
So if you have physical access to your sibling's
or your roommate's computer
and they've left it unlocked there's really not much
of a barrier between you and their cookies.
It might take some technical know-how but frankly
if you Google how to find cookies in Firefox or the like,
I'm sure someone has posted how you can go
about finding cookies in various browsers.
Useful for diagnostic purposes, a little scary
if you're vulnerable to having your session hijacked.
Packet sniffing.
So we talked about this earlier, whereby it's really not all
that hard to download free software these days
that just sniffs wireless traffic
in Starbucks, in this room.
Anytime you're not using something like WPA2,
the encryption protocol that's used by a lot
of wireless routers these days to encrypt your traffic,
well then anyone's sitting near you right now could be sniffing
your traffic and stealing your cookie
from any website that's unencrypted.
So session fixation is just a necessarily fancy way
of saying hardcoding a session ID as your own.
Now in theory you could just guess someone's session ID
by picking a random sequence of letters and numbers,
but the reality is, as you saw, these things are
so long that's going to take a huge amount of time for you
to try guessing all possible session values --
session keys and that's why they're so long.
But as soon as you found it maybe by sniffing
or physical access, session fixation just refers
to the spoofing of your own cookie as by writing a program
or downloading some program that says here, use this cookie
as my own and not what the web server gave me.
And then XSS, cross site scripting attacks,
we've discussed these a couple times, and we'll see
in just a little bit an example.
So how do we mitigate these threats?
Like this is a bunch of scenarios, all of which lead
to a bad ending for me whereby my session's been hijacked.
What kinds of defenses do we have
against these various scenarios?
Axle?
>> Well, physical access, you don't really have
that much defense against.
Once somebody has your computer they can essentially
do everything.
>> Okay.
>> But the packet sniffing and session fixation,
that could be fixed by sending the data encrypted by --
>> Good.
>> -- HTTPS and the XSS could be fixed by being really thorough
and escaping everything that the user sends [inaudible].
>> Okay, good.
So in the case of packet sniffing especially,
just using HTTPS goes a long way,
because HTTPS is end-to-end encryption between points A
and point B. And in this way you're ensuring
that you're cookies are among the things encrypted
so no one can see actually what you've encrypted
in that scenario.
All right, but HTTPS, the website doesn't offer HTTPS,
so what if I just instead turn on the encryption feature
of my wireless router, in Starbucks or in my home,
or even on Harvard's campus?
What if I just turn WPA2
so there's a little padlock icon then next to the name
of the router in my list on Mac OS or Windows?
Does that solve it?
Yeah?
>> Well anybody who's ever done a trace route sees
that the actual packet is sent through multiple [inaudible]
and many networks before it actually arrives,
so anybody on any of those networks can essentially do it
even if they don't have --
and if they don't have WPA2 they can sniff it.
>> Okay, good.
And to be clear then, when I turn on something like WPA2
and connect to an access point, a WiFi access point
that requires a password, for instance that one right there
on the wall with the green blinking light,
where is my data encrypted, between what points?
Yeah?
>> Well, your computer and the router.
>> Good. And where is it not encrypted?
>> Anywhere else.
>> Good, between the router and anywhere else.
All right, so good.
So, what's the implication there?
Well, you're protecting yourself against someone in Starbucks
but you're not protecting someone who's somehow sitting
between you and point B, whether it's some random staff member
in some facility that has a router
or it's someone in Amazon's area.
In short, you don't have true end-to-end encryption.
So, better, but not great.
And XSS we'll come back to in just a bit as to how
to try protecting that.
But there's some other things I propose here.
Hard-to-guess session keys.
So frankly they're already pretty hard to guess
but clearly PHP long session are not a complete protection,
because again, as soon
as you sniff then you can just copy/paste.
So making them even longer is probably not going
to gain as much.
What about rekeying the session?
In other words changing the user session ID, changing the value
of their PHPSESSID cookie every few seconds, every few minutes,
every request, whatever, just change it once in a while.
Good? Bad?
Axle?
>> I see a potential risk for that.
Wouldn't you be sending the session --
wouldn't you be sending it many times so that somebody
on the network could see well,
this computer is every minute sending out a session ID
and I know it lasts for a minute, so they'll see.
If you just send it once then it might be harder for somebody
to actually find that in [inaudible] in all the traffic.
>> Okay.
>> If you send it continuously somebody might notice that
and that might be a security threat,
even though it only lasts for like a minute or whatever.
>> Okay, good.
So rekeying really just means sending a new set cookie header,
but the problem is if you're worried
about people sniffing your keys
and that's why you're changing the key, well if the threat is
that they're sniffing your keys you can change it as much
as you want, the bad guy's still just going
to sniff the new ones.
So you might be making his life more annoying in that he has
to constantly stay up to date with your latest key,
but actually there's a worse scenario here.
If the web server is changing the key --
>> Well if the person, whoever's trying hack in,
sniffs your cookie or your key, sniffs your session
and takes the session and they log on in some period
of time while it's expired, the session,
they get your session ID and they also make it
so that you can't [inaudible] on with that same session.
>> Perfect.
If you rekey the session but the bad guy's already sniffed your
initial ID, spoofed his own as yours, so as to log
into your Facebook account or whatever,
and now the server decides okay, it's time to rekey
to prevent bad guys from getting in,
whose going to get the new key potential first?
The bad guy, at which point your cookie no longer valid
so you've effectively just been logged out of your account.
So in short, rekeying while it may seem like, oh,
this is a good way to sort of dodge the adversary,
doesn't really fundamentally help us
because it's still sending the rekeying
over the same insecure mechanism.
Encryption, this is actually pretty decent solution,
and using at least something like WiFi
with encryption enabled so at least you're not vulnerable
to random people who are sitting in the airport
or Starbucks or bored near you.
More likely than not someone near you cares a little more
about your data, roommate, sibling, or whatnot,
than some random person on the Internet.
So at least that raises the bar, but even better would be HTTPS.
Unfortunately not all servers support that
and indeed it was only a year or so ago
that Google started offering it for Gmail by default,
and Facebook only a few months back started offering SSL
support as well.
So, not all websites have done it.
Because what's involved in SSL?
How do you make your site run on HTTPS?
What do you need?
Yeah?
>> Well you buy a certificate that a person sells and the way
that people sell certificates is through a big chain of trust.
Yeah, somebody trusts somebody and all the vendors,
so that sells certificates, they're backed
up by bigger players, big companies.
So that's essentially how it works.
And it's not really -- it can be assuring for the user
but it's mostly just getting the green bar
and then an image say certificate, like [inaudible].
>> Okay. Good.
So, in short if you want to enable SSL on your server, one,
you have to buy -- or you should buy a certificate
from someone reasonably reputable.
You don't need to break the bank by paying
for $1000 VeriSign certificates.
Generally $50 or $100 ones from places
like GoDaddy or the like suffice.
But you do have to buy this because you need someone else
to endorse that fact that you are who you say you are.
In other words, if I go to GoDaddy
and by a certificate before they give me
that certificate they're going to send an email
to the email address of the person who bought that domain.
Hopefully it's me, because if that's the case they're going
to send an email to the email address
with which I bought the domain, that email account I'm going
to check, I'm going to see, oh, someone is trying
to buy an SSL certificate for CS75.net, is this okay?
Click this link to approve.
And if indeed I've received that email I can approve it.
By contrast, if Axle owns some domain name, like Axle.com,
and I want to, for whatever reason buy an SSL certificate
for his domain.
Because maybe I'm trying to trick users
into visiting my website by calling it the same domain
and therefore, I want to trick them even more
into thinking it's secure by buying an SSL certificate
for his domain name, he's going to get that email confirmation
because he bought the domain, he gave them his email address,
and unfortunately they're not going
to hand me the SSL certificate until he confirms.
And unless he actually confirms and isn't reading the email,
well then I'm going to get that certificate after all.
So once I do that I install it in my web server.
We saw a while back in http.conf you have
to specify the file name of the certificate
that you've downloaded as well as your so-called private key,
which is a number that you have generated.
Because at the end of the day recall that SSL boils
down to this thing called public key cryptography,
which is a mechanism mathematically whereby a person
has a private key and public key, and which of those is used
for what process when it comes to encryption?
With which of those keys, private or public,
do you encrypt information if you know?
Yeah? Axle?
>> The private one?
>> Not a bad guess, but it's the opposite.
So in this case, in public-key crypto you start the process
by generating two really big random numbers
that are somehow -- not quite random,
they're somehow mathematically related.
And they have these key properties
in public-key crypto whereby the private key is the only key
in the world that can decrypt information that's been
encrypted with the public key.
Now why is this compelling?
The fact that I have two keys is really nice
because suppose now Jack and I --
suppose I'm a user on the Internet and Jack has a website
and he's trying to sell widgets
on this website securely using HTTPS,
and therefore he's brought an SSL certificate
and somehow I need to communicate securely with Jack.
Well, unfortunately most encryption algorithms assume a
private secret between me and Jack.
For instance, if you think back to a silly example
in grade school, if you wanted to pass a note to a classmate
or someone you were crushing on.
You want to send them a secret note, literally pass it
to a classmate and then give it to the boy or girl
across the room, but you don't really want the teacher,
let alone the kids between you and that boy or girl
to intercept it and read your secret love note,
or whatever it is you're sending.
So a kid might do something super simple,
like change the letters around, so instead of sending an A,
you say a B. Instead of writing a B,
you write a C. C, D, and so forth.
Something simple like that,
and in fact there's an algorithm known as the Caesar cipher,
or ROT13, which is a specific example of this
that does exactly that.
Right? Because what's a non-technical teacher going
to do?
They're going to see this note, it's going to look
like nonsense, they're not going to know what it is,
or they're at least not going to care to decrypt it by figuring
out how you encrypted it.
So, in short, nice little childhood encryption scheme.
So the problem with that is that if Jack is some random website
on the Internet from whom I want to buy something
for the first time, Jack
and I do not have some known algorithm that we can use.
I can't just write him a purchase order
and then encrypt it by changing A's to B's, B's to C's,
and handing it to him over the Internet
because he's obviously not going to know how
to reverse that process.
So, I could call him up, we could agree on some secret
like rotate all the letters one place or something stupid
like that, but obviously this is not how Amazon.com works,
or real stores work.
So public-key crypto is an alternative to that scenario,
which is generally called secret-key crypto where Jack
and I have some secret.
If that's not going to work I can instead use public-key
crypto whereby I have a public key and a private key,
Jack has a public key and a private key,
and the nice feature of public keys is
that as their name suggests you can broadcast them to the world.
You can display them on your website.
You can put them in your email signatures.
You can just send them in the clear
over the Internet whenever someone asks you for it.
And indeed the way SSL and other algorithms work
to get started is if I am trying to buy something
from Jack's website and it's using SSL,
Jack's website essentially says, "Here, this is my public-key,
use this to send me information securely."
And before I send him any messages or orders
or credit card information I first take my information
and I encrypt it with his public key,
then I transmit the cipher text, the scrambled stuff,
across the Internet to him, because what's the only key
in the world that can unlock or decrypt that message now?
Axle?
>> Well, that's the private key.
>> The private key.
>> He's the only one who has that.
>> Exactly.
He, by definition of private is the only one
who should have that.
He's made a mistake if he gives it to anyone else.
So only he should be able to decrypt that message.
And similarly if he wants
to send me a secret message I can just give him my public key,
like I can anyone else, and that process can happen
in the other direction as well.
In reality something like SSL uses a little bit
of public-key crypto as well as some other techniques
because it tends to be a little more expensive computationally
than secret-key crypto, but that in general is the key property.
So, how does this help us?
Well, so SSL is again, as Axle said, it's this chain of trust.
You buy an SSL certificate and it will just work mathematically
but until the browser --
until you pay someone for that certificate
and have them digitally sign the certificate, so to speak,
no one else in the world is supposed
to trust the certificate.
Because recall from a few weeks ago various browsers, IE,
and Firefox, and Chrome, and the like all ship
with certain certificate authority keys in them --
certificate authority certificates in them,
which says Chrome will trust any SSL certificate from GoDaddy,
from VeriSign, and from this list of a whole bunch
of other SSL certificate selling companies.
So, if you have not bought your certificate from one
of those companies Chrome is going to do what to the user
when you try to visit the website?
Jack?
>> Send some crazy warning to you that says like,
this site has an invalid security certificate
and you shouldn't stay here,
or it might be dangerous [inaudible].
>> Exactly.
You will get some warning message scaring you.
Chrome tends to look like this right now.
"This site's security certificate is not trusted!"
I ironically as I did a few weeks ago went
to cs.harvard.edu, which has not paid for an SSL certificate,
and you see a big red X, you see a big red screen here
which means you can't actually proceed unless you click
this button.
Now, out of curiosity what do most of you do
when you encounter a website like this?
Ben?
>> Keep going.
>> You just keep going.
Anyone else just keep going?
Yeah? Axle?
I mean I do.
>> If you wanted to access the website in the first place.
>> Right, if you want to access the website
and you know you haven't mistyped it, so you haven't gone
to some sketchy random website.
You're where you want to be.
This generally signifies an error,
or a lack of payment, or the like.
So I would propose, and I have no data to back this up,
that most people probably proceed.
Now, on fairness, Chrome makes it pretty easy to proceed,
you literally just click proceed now.
If I instead use something like Firefox and go in here,
Firefox is a real pain in the neck.
So, if you've ever used Firefox here is how you get
around this issue.
And this is kind of tragic because if you do screw up,
or you don't want to pay for a certificate,
and you pretty much should.
Or if you generate your own certificate
and do what's called self-signing it,
in other words you do the mathematics yourself,
which is totally legitimate in terms of the formula,
but you haven't had anyone else vouch for you like GoDaddy
or VeriSign, here is what your friends or family
or customers would have to do on Firefox.
One, they're probably not going to click "get me out of here."
They're instead going to have to click "I understand the risks."
Add exception, get certificate, confirm security exception.
And now you can proceed, and so forth.
And right now it's hanging for just a moment.
There we go.
Now it redirected to the actual CS page.
So no, most people are not going to do that, even I get annoyed
as anything when I have to go through those hoops.
So in short, this is why you pay for an SSL certificate.
Now the theory behind it is great.
As we discussed a couple weeks ago, chain of trust,
it's very reasonable, it's a nice way of sort
of ensuring there's a mechanism
in place whereby you're not visiting potentially bad guys
or the wrong websites.
But again, it's nice in theory,
it's not necessarily the best experience
in the end in practice.
All right, any questions?
All right, so rather than scare with some math let's go ahead
and take our five minute break here,
but when we come back we'll give an example
of how you can implement public-key cryptography
to make it a little more concrete
than just there's math that makes it work.
And then we'll also take a look at a bunch
of other threats including involving SQL,
JavaScript, and HTML.
So why don't we go ahead and take our five minute break here.
All right.
So, math time, though it's fairly formulaic math.
All right, so how do you possibly send --
come up with a public and a private key in such a way
that you can use the public key to reverse the effects of --
rather, you can use the private key to reverse the effects
of the public key and ultimately exchange some secret?
So, there's a couple of very popular protocols when it comes
to public key cryptography.
RSA is one with which you're probably familiar,
at least by name.
Has to do with coming up with a public
and a private key using very interesting properties
of large numbers that when multiplied together are very
difficult to un-multiply
or factor back down to their primes.
So -- but that one's a little more involved and so a nice one
to use for the sake of discussion when it comes
to public-key crypto, something called Diffie-Hellman, or DLP.
And this is an algorithm
that similarly involves public-key cryptography,
but it's an interesting example of how you can essentially shout
across a crowded room some number and your partner, B,
can do the same and somehow together that mere exchange
of that information is enough to come
up with a public/private key pair.
So this story works as follows.
In the case here of Alice and Bob we have the following story.
Alice and Bob in advance are going to agree upon two numbers,
G and P. P is going to be some prime number, and G is going
to be what's generally called a generator,
which is often the number two.
As simple as that.
But P is a big prime number
and they can choose P however they like.
So they have to agree upon those in advance,
they can tell their friends and announce
to the world what they are, these are not secret values,
but they have to decide on them upfront.
So then Alice decides on some random number A,
and Bob similarly decides
on some random number B. They don't tell each other these
numbers, but they choose them in isolation of each other,
and then they perform a bit of mathematics,
specifically Alice goes ahead and computes this value here.
G to the A mod P. In other words, Alice goes ahead
and takes G, which is probably the number two,
raises to the power A, and then does modulo P,
What is the modulo operator generally do?
Yeah, Isaac?
>> Well it's kind of like the remainder.
>> Okay, yeah.
It's kind of like the remainder.
It's what you would get if you were to divide some value,
like G to the A, by some value.
It's what you have left over if it doesn't divide evenly.
And as an aside I'm trying a new program for the first time here
which is why I have this trial software on the screen,
but it's the only way I could try drawing
for the first time here today.
So G to the A mod P ends up being some number,
and we're going to call it generically T sub A. So it's T
and it's Alice's T. So what does Alice then do?
She transmits that number, G to the A mod P, otherwise known
as T sub A, across the Internet, in the clear, doesn't matter.
So in other words, even though it's drawn here mathematically
as G to the A mod P, she doesn't send that written expression.
She sends the result of that arithmetic operation,
T sub A. So Bob does the same thing but using his B instead
of A. So he gets some number, sends that across the Internet.
So at this point in the story Alice has sent that first box,
Bob has now sent this second box, and so now Alice has what?
She has A, because she came up with it,
and she also has T sub B. Similarly, does Bob have B,
and T sub A. So those are the values
that have now been exchanged.
So what do they then do?
They then both go ahead
and compute this value and this value.
Alice computes T sub B raised to the A power.
Now what does that mean?
Well, T sub B is just our variable
that represents what Bob sent her.
So she's raising whatever Bob sent her to the power of A.
And Bob does the same thing, raising to the power
of B what Alice sent him.
But if you recall how exponentiation works,
when you raise something to the power and then again
to another power you end up multiplying the exponents.
So mathematically what both Alice
and Bob have done here is raise G, which again is some number
like two, to the power of A times B, or rather,
power of B times A, but that's the same thing.
With multiplication you can do it in either direction,
mod P. So at this point in the story Alice has A,
she has T sub B, but she also has G to the AB mod P,
even though she doesn't know what B is.
And Bob conversely the same resulting value,
G to the AB mod P, and he has B, but he doesn't have A.
So we seem to have constructed a scenario in which both Alice
and Bob have some shared secret, rather where Alice
and Bob both have some value, G to the A mod P,
but each of them only has a piece of the rest of the puzzle.
Alice has A, Bob has B. So essentially Alice
and Bob can now use this number to encrypt information
and they can reverse its effects
by using their own respective private keys.
So it's not quite identical to, for instance,
what a browser would use these days,
it's sort of a simpler version,
or simpler story of what's possible.
But it hints at how the mathematics can behave
in such a way that you can share some information publicly,
like me just talking to Jack's web server, or me just talking
to Bob in this scenario,
and nonetheless preserving some notion
of privacy whereby there's still a number that only I know
and can use for the decryption part.
All right, so now let's try a concrete example
of the SQL injection attack.
We've been talking about it for some time
but haven't necessarily teased apart.
So here's a login form up top.
It's representative of most login forms.
You got a username, a password field, and then a checkbox
for keeping me logged in.
Now as an aside, before we look at the SQL, how does a box
like that generally get implemented?
Facebook has something like this;
most websites have something like this.
And when you check that it obviously keeps you logged
in until either for seven days or until you explicitly log out.
Yeah, Axle?
>> Well it has to store the login variable in a cookie.
Right? Because the session would be destroyed once you closed the
browser window.
>> Good.
>> So if you want to be still logged
in when you open it again you have to store it [inaudible].
>> Good. Exactly.
So, by checking this box I'm essentially asking the web
server, plant a cookie on my hard drive
that somehow will remind you who I am and that I have logged in.
Now in the worse possible implementation of this,
that box could result in the server setting a cookie
with both my username and password
so that anytime I visit it just sends it again and again
and then when I finally logout it just deletes those cookies.
But that's of course not a good mechanism, we talked earlier
about HTTPS and if it's sent
in the clear you're just telling the whole word your username
and password.
Plus it's just not necessary.
So instead what this button would probably do is tell the
web server to set another cookie that's not the PHPSESSID,
which is a PHP specific thing,
it's just for the superglobals purpose.
Instead setting a cookie
with the set cookie function that's called authenticated,
or something like that.
And that key authenticated has some value that's similarly a
big random looking number,
but that big random looking number is remembered
on the server, maybe in some database,
and the next time the server sees
that same big random number in a cookie.
It checks its database and sees, oh,
I gave this big random number to Isaac, let me assume
that this is Isaac again
and show him Isaac's Facebook profile,
or whatever website he's actually visiting.
Now of course you're still vulnerable to what?
>> Physical [inaudible].
>> Okay, physical access is always a problem,
but what else here?
Jack?
>> Packet sniffing.
Right? If it's not HTTPS this feature is even worse now
because sessions are generally ephemeral, right?
They only exist for the life of that browser window.
But something like a cookie that has a seven day expiration
or no expiration, that means someone can sniff this
and you use it anytime they want so all the more reason to ensure
that this is encrypted.
All right, so now the SQL part of this.
Suppose that this form is a login form
that essentially results
in a SQL query getting generated like this one here.
So we have -- this can be implemented in a few ways,
and I went with the MySQL query version of this specifically
so that the inputs would not be escaped.
So let me go ahead here and zoom in a bit.
And what do we have here?
So on the left we just have a variable called result
for our result set.
To the right we have mysql_query,
recall which was the function we used initially a couple lectures
ago for executing SQL commands.
Then I'm using sprintf.
Does anyone recall what sprintf does?
It's not strictly necessary but it's a possible approach?
>> That you insert placeholders where the variables go
and then you do command and then you define the variable.
>> Yeah. Exactly.
You just insert these placeholders.
So in this case I have a placeholder %s,
another placeholder %s, and that means
that the next two arguments to sprintf, here's the first,
here's the second, are going to be plugged
in for that placeholder.
And it just makes things a little more readable,
I don't have to use the concatenation operator,
the dot operator.
I don't have to use the curly braces.
It's just one way of constructing a SQL query
without just doing it all very manually.
But there's a fundamental problem here with my query
because I've obviously not done what?
Axle?
>> You haven't escaped with user input [inaudible] anything.
>> Exactly.
I haven't called MySQL real escape string,
which even though it's a poorly named function it does escape
potentially dangerous characters,
things that might lead to the server being tricked
into executing a command like delete, or drop in the database.
Now, how can we see this here?
Well notice that the SQL query that's being built
up is SELECT uid, so user ID, or whatever that is,
FROM users WHERE username equals '%s' AND password equals '%s'.
So what's perhaps a dangerous character a malicious user could
provide when filling out this form?
Jack?
>> Semicolon?
>> Semicolon, potentially dangerous because it would seem
to terminate the query, or in this case what's even worse?
>> You can do a single quote to end the username --
yeah end the username and then you can insert the SQL
in between.
>> Exactly.
In this case the semicolon is not going to be too worrisome
because it's going to be in between quotes.
So it's not going to terminate the query.
But if I were to be like David O'Malley, like O-'-M-A-L-L-E-Y,
or some Irish name that has an apostrophe,
or any name that has an apostrophe, that's going
to be a problem because it's going to be
WHERE username equals 'O seemingly unquote
and then Malley and then another quote, a third quote,
and now things are just imbalanced.
Now that's going to break.
So that's just going to trigger some kind of server error,
but what if the bad guy is smart enough to realize
that if he's going to pretend to close one of my quotes,
if he's going to pretend to close this first quote here.
He had better realize that in order for this not
to be a syntax error, and in order to truly trick the server
into executing something, he better open a new quote later
that corresponds with my second apostrophe.
So what do I mean by this?
Well let's take a look at what a user might type in.
Suppose the user -- rather, woops.
Suppose the user types in this,
and I've deliberately removed the bullets
that would normally appear in a password field just
so you can see what this bad guy has typed.
But what if he proclaims his password is 12345'
OR '1' equals '1.
Now that in and of itself does not look syntactically valid,
but what's the implication
of the bad guy having provided this as his password?
Axle?
>> Well it's going to be sent to the server and first
of all it's going to add two quotes on either side
because that's what's inside your password thing.
>> Good.
>> But then it's going to interpret --
I think it's going to interpret the 1=1 as just a valid,
logical statement, so it's going to return true to the login.
>> Exactly.
So because one obviously equals one,
and because the bad guy has been smart enough
to construct a string that looks weird, but if you think
about where it's going in my PHP code it's going to be prefixed
with a single quote and it's going to be suffixed
with a single quote, at which point this actually becomes a
syntactically valid SQL expression, or condition.
So now the fact that he's specifically saying
OR '1' equals '1 that's the real brilliant aspect here
because he had a hunch that I was doing some kind of select
where I'm and-ing or maybe or-ing things together.
But if he somehow tricks me into executing,
give me uid if 1equals1, well that code is indeed going
to return one or more uid's
if there are any users in the system.
And presumably, like we saw
in our login examples a couple weeks ago,
if you are using the presence of a uid signifying
that a user exists and should therefore be logged in,
well now the bad guy has somehow tricked the server
into logging him in as who knows who but as someone.
And if his goal was simply to get into the system
or get WiFi access, or you know, take someone's money,
now he has access to an account on the system even
if he doesn't know which uid was returned.
So to be clear, in red here,
the query that's just been constructed would look
like this.
SELECT uid FROM users WHERE name equals 'jharvard'
AND password-'12345' OR '1' equals '1'.
And unfortunately one always equals one,
which means you're going to get back a result set with one
or more uid's if there are, again,
one or more in the database.
So, kind of bad.
How do we actually fix this?
Irony is that it's so simple to fix, it's annoying
to type but simple to fix.
And we can take the exact same code in blue from before
and this time simply call mysql_real_escape_string
on both the username field and on the password field
so that now I have the ability to specify
that these things should be escaped in advance specifically
by calling this function here, and this function here.
So, why do SQL injection attacks nonetheless happen even though
it's so relatively easy to avoid them
by simply escaping your input?
And to be clear, what is mysql_real_escape_string do?
It's for things like quotes; it puts a backslash in front
of them, which means you won't be tricked
into executing the wrong thing.
So why does the world still suffer SQL injection
attacks sometimes?
Jack?
>> Just errors on the programmer.
Maybe he didn't put it in.
>> Yeah. Exactly.
The lack of knowledge, lack of remembering, an attitude of oh,
I'll go back an escape my inputs later,
which is a horrible possible scenario,
to know you're doing it wrong then
to claim you'll do it later, lest you forget.
>> But also I don't think
that the login forms are the most vulnerable
because I think people don't do this in the login forms,
but I know of some Internet security programs they scan the
entire website looking for [inaudible] forms and the ones
that usually the most vulnerable ones the ones
that say send a suggestion, or send [inaudible].
>> Yeah.
>> The ones that were added later on top of the site,
after the login was finished, and they didn't really think
that that would be a potential security threat.
>> That's good.
Yeah. It's potentially the stupid
or the seemingly innocuous forms that have nothing to do
with security, nothing to do with users, but if they have
to do with SQL, like if you're using SQL to insert
into the database some user's feedback,
well the problem here is that they can execute not just
or 1equals1, they could do something
like semicolon select star from users
and dump your whole database.
Or worse, they can do drop table users, or delete star
from user, or delete from users.
You can do any number of things.
So in fact some of the popular press attacks
that you've read about, there was one, was it Yahoo?
Someone's recently, I forget, that involved a dump
of a SQL database, was very likely the result
or was likely the result of something like this
where someone injected SQL into a script
that hadn't scrubbed it properly.
That or someone got access electronically to the database
and just kind of manually executed these queries.
Both scenarios could yield the data in question.
I don't think Yahoo, or whoever it was, was very --
>> I think it LinkedIn.
>> Oh, it was LinkedIn, maybe that was the one.
I don't think they were very forthcoming with their details.
But the fact too that one
of them actually had clear text passwords I think.
That was idiotic, whoever that was.
That was just not necessary.
Right? That was like, what?
Lecture three or something?
So, all right.
Anyhow. So what more is there to fear out there?
Oh, and to be clear in green here this is what the bad guy
would experience if you actually called mysql_real_escape_string.
Looks stupid but it's no longer tricking you
into evaluating something as 1equals1 expression.
Now it says give me the user ID where the username is jharvard
and the password is literally 12345; OR and so forth.
Which is not likely someone's password.
And even if it is it's probably John Harvard who's trying
to log in with that.
All right.
So same-origin policy, and its relation here to security.
So we talked briefly about this on Monday in what context?
There's a same-origin policy that, long story short,
essentially says what?
Axle?
>> Well, I encountered it when I tried
to get some [inaudible] data from the [inaudible].
They wouldn't allow me because I wasn't on the same server.
>> Good.
>> So what I had to do -- well, you can go around it,
you can just do a PHP [inaudible] contents
and then echo [inaudible] HTML, but you would essentially,
the policy constitutes that you have to be
on the same server [inaudible] database.
>> Exactly.
Browser behavior is governed generally
by the same origin policy which is really relevant
for us most recently by context of Ajax.
Which allows us of course to get more data from a server
and incorporate it into the existing DOM.
Problem is the same origin policy tells browsers
that you can make Ajax requests to other servers
but you cannot integrate their response into the current DOM
because it's not from the same origin as the original DOM,
the original HTML file that was downloaded.
So there's a couple workarounds for this.
One, the person who owns the server, Yahoo in that case,
could start sending certain HTTP headers, called cors headers,
C-O-R-S, that essentially tell browsers it's okay
to let people incorporate our data into their existing DOMs.
Most websites don't enable that, and you can do it
if you run the server, you can't do it
if obviously you're trying to use Yahoo.
Alternatively you can write a proxy,
a little PHP script that's maybe one or two lines
that makes the request for you, but that PHP script
at least lives in the same origin
as your JavaScript file, so that might help.
You can use a third party proxy service like Yahoo's YQL service
that I mentioned last time, which will allow you to go
to some other server and sends it back to you in a way
that you can incorporate it back
into your own DOM, which is nice.
Or you can use something called JSONP, called padded JSON,
which essentially uses some interesting script tag hacks
so that you can grab data from a server and you tell the server
in advance what function you want to be called
when the data comes back.
And if the server cooperates then you can trick the server,
rather, it's not so much a trick in that case.
You can incorporate data into your DOM by using a server
that supports, again, JSONP, padded JSON.
But many websites don't support that;
they'll support just JSON or XML, or the like.
So in short, number of workarounds
but a pain nonetheless.
Oh, and this affects everything, windows, frames, objects,
Ajax requests, and it's the Ajax ones
that are the most current for us.
All right, so a couple
of remaining attacks to be mindful of.
Things that you might not have even appreciated
as you've made your HTML based websites
or more recently your PHP websites,
or now your JavaScript based websites.
Cross-Site Request Forgeries,
which has an acronym I rarely remember,
and Cross-Site Scripting attacks, XSS.
So what are the two and what should you fear?
So here's the story here.
You log into something like project2 and suppose it lives
in some domain name on a web.
So domain.tld, top level domain.
So you log into project2.domain.tld.
You then visit a bad guy's site and the bad guy has a link
to this URL here, HTTP://projecet2.domain.
tld/by.php?
symbol=INFX.PK.
You unwittingly buy the penny stock.
What's going on here?
So this is assuming something like CS75 finance in this case,
although, actually, two would have been the [inaudible].
So if it's project1, this would have been something
like CS75 finance, and it seems to be proposing
that this bad guy has a link that just so happens
to be leading back to your domain, but he has it there
because he just likes tricking people
into buying his penny stock.
And that's advantageous for him, the bad guy,
because the more people that buy the penny stock,
the more it drives the price up, then he can sell and screw
over all these people, so a reasonable attack scenario.
So how is this working, or what's the flaw
in your website, project2.domain.tld?
Jack?
[ Inaudible Speaker ]
Good.
[ Inaudible Speaker ]
Perfect, right?
It's not that hard to figure out how a website works;
you can just use Chromes Inspector.
Anyone who's taken this class, like, has --
is savvy with which to start poking around, and just figure
out how almost every mechanism of a website works,
unless things -- like, JavaScript [inaudible]
which just makes it harder.
But at the end of the day you can certainly figure
out what HTTP parameters are being used
by just watching the traffic in your own browser
or some other debugging tool.
And if you made the conscious decision as the designer
of this website to have a buy.thp file,
which that's reasonable, and it takes a parameter called symbol,
and a stock symbol as its value,
and that buys one share [inaudible]
or something like that.
Well, you have made a mistake here
because you've made it super easy for a user
to similarly construct a URL that looks like this.
And the bad guy might not even put it in his website,
what if he just sends a million spams and tells people
in that spam email to click this link, right?
He's going to get some small percentage
of people actually clicking the link, who if they also happen
to be users of your website, have just been tricked
into buying that stock.
Now obviously this is kind of a silly name for a website,
but what if the URL is actually etrade.com, or something
like that, and you've been logged in recently
to your E-Trade account and they have implemented their
[inaudible] parameters in this way, you can trick them
into buying the penny stock.
So what's a defense?
So Jack proposed, like, a random number.
Can you elaborate, Jack?
[ Inaudible Speaker ]
Good.
[ Inaudible Speaker ]
Good. So you can have the web server, etrade.com for instance,
generating some kind of random token
that it requires be in the actual buy.
And the motivation here is that if the server uses cookies
or sessions to remember that I gave Jack this random ID
for subsequent purchases, now the bad guy has
to not only know the format of the URL, he also has to get
so damn lucky as to also hard code
into his link the same identifier that Jack was handed.
And if the number is long enough,
there's no way statistically that's going to happen.
So that can help ward off the threat.
[ Inaudible Speaker ]
Okay.
[ Inaudible Speaker ]
Ah, a really good thought.
So among the HTTP headers
that a browser typically sends there's one called the referer
header, which specifies,
I came from this URL recently, and this is useful.
This is how things like Google Analytics figure
out where you're coming from when you get to a page.
They can tell you that you came from the Google, or the like.
But the catch with this HTTP referer header is
that it's not guaranteed to exist.
It's a nice feature that most browsers honor,
but if you're one of these paranoid types,
or you are behind corporate firewall
that scrubs certain information,
the HTTP referer header is not required for correct behavior
of a browser, so privacy scraping tools --
privacy scrubbing tools could remove it all together.
And it's just not always sent,
depending on how you visited the URL
or you open a new tab or the like.
So not bad, it raises the bar a bit,
but it's not a sufficiently reliable mechanism.
It's not going to keep your purchases super secure.
So one problem, too, seems to be we're using what method here
for the stock purchase?
Ben?
[ Inaudible Speaker ]
Okay, so what's an obvious alternative, then?
[ Inaudible Speaker ]
Okay, good.
So if you use post instead, you don't just have
to trick the user into clicking the link, you have to trick them
into filling out a form, at least clicking a button.
Axle?
[ Inaudible Speaker ]
Good.
[ Inaudible Speaker ]
Good. So that's the catch.
So this does raise the bar, and you've just protected yourself
against the less intelligent of adversaries.
But we saw the other day how you can register event handlers
[inaudible] that prevents form submission.
Turns out in JavaScript there's a function called submit
that you can call to actually submit a form via code.
So all you've done here, too,
is you've made it a little harder for them.
You've tried -- now the user has to fill out a --
has to submit a form by clicking a button.
But, again, with JavaScript,
and almost everyone has JavaScript enabled,
a user could visit a page, there could be a hidden form there,
and they're tricked into submitting it
because there's a JavaScript function that just says,
when the dom is loaded, submit this form automatically.
So it raises the bar, helps maybe with emails a little bit,
but not all of the possible attacks.
And in fact it's a little scarier than this.
Even though I chose this example of, like, a spam email
or the user visiting the URL,
take a look at these other possible attacks.
Suppose you just happen to visit a website that has an image
in it, a script tag, an iframe, another JavaScript tag
with some code, you can trick the user to visiting URL
in so many different ways, right,
simply by including an image tag,
that's maybe the simplest one.
And notice this is kind of weird
in that I'm saying the image is the URL of the buy.php,
but it's not a big deal if that doesn't actually return an
image, right?
It's going to return a broken icon or something like that,
but who cares, I just tricked the user
into buying the stock already.
So realize that you don't even have to be overtly trying
to trick the user into clicking a link, you can trick them
into sending an HTTP request from their browser
or their mail client just by hard coding the URL.
So now POST would help with these attacks in particular,
but not in the case of a browser supporting JavaScript.
So how can we really fix this, then?
It's not sufficient just to use POST.
I claim it's not sufficient to rely on the referer header,
because it's not always there.
It might help, but not sufficient.
POST doesn't seem to do it fully for us.
The random numbers, not bad, actually, that's probably one
of the most solid solutions thus far
because it requires server side cooperation.
Axle?
[ Inaudible Speaker ]
Okay.
[ Inaudible Speaker ]
Okay. Good.
[ Inaudible Speaker ]
Good.
[ Inaudible Speaker ]
Okay, so a slight variant on Jack's idea.
This time you have a hidden form field
that contains some server generated token
that it can validate somehow so that if it doesn't get
that same token, it knows that this is a forged buy.
So that's not bad.
That, too, is solid.
What is -- if you've ever bought something from Amazon,
what does Amazon ask you to do before you buy something?
Yeah?
[ Inaudible Speaker ]
Okay, so CAPTCHA's.
What's a CAPTCHA?
[ Inaudible Speaker ]
Okay, but what does that mean?
>> It's a -- generally an image
that viewers having a hard time figuring out.
It's distorted text --
>> Okay, good.
>> -- generally.
And for -- for [inaudible] it's really hard
to see what it actually says,
but for you it's really easy [inaudible].
So [inaudible] spend time [inaudible] can't have
[inaudible] because [inaudible].
But [inaudible] buy stock, it's going to go, okay,
[inaudible] five letters and five numbers.
>> Perfect.
Yeah, and so you just -- you put a bump in the road,
so that even though the user could be tricked
into visiting your webpage, either behind the scenes
with a tag like these, the image tag, or explicitly
by a link they click in an email or in a website
that they visited or redirect.
Before the buy.php actually buys the stock,
it shows the user a CAPTCHA, a thing like,
please type in the following word that you see,
just to raise the bar so that the user now kind
of has to be not so sharp.
If they're like, okay, I'll fill out this form,
even though that form says to buy this stock fill
out this form, or fill out this CAPTCHA.
And similarly we could do something
like Amazon does itself,
they just prompt the user to re-login.
So even if you're logged into your Amazon account
and are browsing and adding things to your cart,
the moment you click check out, even if you just logged
in a minute ago, they prompt you to login again,
putting that bump in the road so that the user has to demonstrate
that it's indeed me and not some bad guy that just tricked me
into visiting the checkout line.
And that's particularly important for Amazon
because they have this patented feature that does what?
One-click shopping.
All right, one-click, kind of bad, right?
If you can buy a stock or a buy a book or buy a TV
with one click, you better be sure that it's the user
who has clicked and they haven't been duped by one
of these various techniques.
And lastly, XSS.
So this one we've talked about, but let's take a look
at a concrete example.
So this URL's unfortunately a little long and small,
but demonstrates the idea.
So let me zoom in.
so supposed in this scenario you happen to click on a link
that goes to vulnerable.com, literally, and foo equals
and then some crazy looking script tag.
Now, generally the script tag would not be written
as a script tag, it would be something cryptic looking
like this with percent signs, because we call it PHP
and other languages and have a URL and code function
that take potentially dangerous characters and spaces
and they URL and code them using percent signs and numbers
to make sure that it's all one string,
with no spaces or breakages in it.
But just so we can talk about it,
the top is what the bottom translates to.
But what does that do?
It's a script tag inside
of which is apparently some JavaScript code,
and we didn't see document.location the other day,
but document.location is a property inside
of the document global object in JavaScript
that if you assign a new URL to it,
it redirects the browser to that URL.
So we saw the redirect ability of PHP
by sending the location header, the [inaudible] header.
You can also redirect users in JavaScript
by setting document.location or document.location.atra,
more specifically, to another URL and they'll be whisked away
as soon as the code executes.
But in this case the bad guy is doing something clever,
he's sending the user to badguy.com, for clarity,
/log.php, the idea being that he's going
to log whatever he gets of this file.
And the argument he's giving himself is cookie equals the
[inaudible] of document.cookie.
We also didn't talk about this, but it turns out that
in JavaScript you can also access cookies; you can set them
and get them, and they're all stored
in an object called document.cookie.
So inside this global document object there's another object
called cookie and everything in there is --
all of the key value pairs you have
for this website's cookies are stored there.
So what's the implication?
If it's a PHP based website you're visiting,
there's at least one cookie involved [inaudible] sessions
and that cookie is called what?
[ Inaudible Speaker ]
A PHPSESSID, right?
That big capitalized word we keep seeing in the headers.
So PHPSESSID is going to be present in the memory
of any browser that's visited a PHP website
that has session start having been called,
where sessions are in use.
So that means in document.cookie I have access
to a user's session cookie.
So what I'm doing here is constructing a URL,
badguy.com/log.php cookie equals document.cookie,
so that effectively the URL I'm going to be sending the user
to is badguy.com/log.php?cookie equals one, two, three, four,
five, six, seven, either,
whatever the big random number is
that is the user's PHP session ID.
So what does this mean?
This is a very sophisticated way
of sniffing someone's session cookie, not via WiFi,
not via a wired Internet connection.
In fact, it's doing it via JavaScript.
So they could be anywhere in the world.
They could be on an encrypted connection, on a VPN,
they can have WPA2 installed, but it doesn't matter
because JavaScript is as close to the user as you can get.
The cookies are unencrypted at that point,
they're stored inside of this container
called document.cookie.
So if I trick the user into executing some JavaScript code,
that JavaScript code doesn't have to be something stupid,
like a few lectures ago where I just said, alert hello,
or alert annoy, or whatever it was, rather,
it can be something dangerous like this.
Because now badguy.com has in his log file somewhere, what?
[ Silence ]
[ Inaudible Speaker ]
Exactly, someone's cookie value.
Maybe it's Facebook, maybe it's Gmail, maybe it's Bank
of America, something and now he can presumably take that value
from his logs and use a special program that he wrote
or downloaded and pretend that that is his own cookie,
and now he's logged in as this random person.
So in the end of the story -- by the end of the story,
vulnerable.com has to be flawed,
it has to be vulnerable by doing what?
So step two describes it, but what do I mean
by it makes the mistake
of writing the value of foo to its body?
Jack?
[ Inaudible Speaker ]
Exactly. Right?
So just as we did this silly example a couple lectures ago
where I tricked the browser into triggering an alert
that said hi, or annoy me, or whatnot,
if there's a similar form on vulnerable.com's website,
and I have tricked it into pre-populating that form field
with in this case a script tag,
because that's what the bad guy has tried to trick me
into providing as input, and you did not only --
you only called print or echo or use the equals sign operator,
you did not use what function?
[ Inaudible Speaker ]
Yeah, HTML special charge, which escapes things with ampersands
and entities and the like and makes them execute.
Well, badguy.com is going to get your cookies in this case.
So what's the key takeaway here?
How do you protect yourself against XSS?
Jack?
[ Inaudible Speaker ]
It really is as simple as that, right?
Like, the alternative is, don't click links,
but that's not going to happen, users are going to that.
And it doesn't even matter if they click,
because they can just use an image tag to trick them.
Don't trust user input.
So that's a given, all right.
So a key theme here with these latest attacks is,
you should never trust that what the user is typing is going
to be valid, and you should certainly encode it or escape it
so that you're warding off these kinds of attacks.
All right, because what if --
and again, just to emphasize one lesson
from our JavaScript discussions,
but this is why we have form validation.
Why don't I just check that what the user is submitting doesn't
contain the open bracket or the script tag?
Why do I also still need to encode or escape all user input?
[ Inaudible Speaker ]
Exactly.
[ Inaudible Speaker ]
Exactly. [Inaudible] validation not sufficient because it can be
so easily disabled, as I did the other day
by just clicking something, you can turn it off
for your entire browser by some preferences menu, usually,
or can just write your own software at a terminal window
that pretends to be a browser
and therefore doesn't have any JavaScript support whatsoever,
it just makes HTTP requests.
So there's a whole number of attacks that we explored today,
and we've talked about things here and there over time.
But ultimately the lesson really should be,
never trust the users input, and also consider the fact
that at least one of your users is going to be some adversary
or just a little bit curious as to your site works
and you should never just expect that, you know, users are going
to behave in the manner you intend.
So what remains?
Thus far we've been using [inaudible] appliance,
you've been having probably one user bang on your website,
or two, including your teacher fellow.
But on Monday what we'll discuss is scalability
and how you can actually take a website
and not just tolerate dozens or hundreds or even thousands
of users, but maybe tens of thousands.
And what kinds of design decisions you can make even
for the simplest of projects so that
if you do have some happy coincidence
of becoming popular overnight,
as some websites these days have become,
you at least have designed things in such a way
that you can scale your website out without having
to throw a lot of money at it, certainly,
and also without having to rewrite all of your code.
There's a number of decisions you'll be able to make
up front that, if you are so lucky as to have a problem
of scalability, you'll be able to adapt to it.
Why don't we adjourn here.
I'll stick around for one on one questions,
otherwise we have Section coming up,
and I'll see you guys on Monday.