 No, it was, hey, hey, you can hear me now. So this is Jeremy. He works at iMeasureU, which is a global startup in Auckland. And he's going to be talking about web security. Thank you. So I'm going to talk about security, which is really weird, because I don't know anything about security. So we'll go into that talk knowing that. And please be kind to me at the end. So about me, I'm an embedded system engineer. So most of my stuff's in C. But then usually I use Python to break out of that and talk to the real world. I like open source software, open source hardware, electronics, and most recently, security. So the disclaimer, just like Brenda, I like her disclaimer, is more fun than legal advice or security advice. So just use these as the beginning of your introduction to security. Oh, I saw that Jeremy's talk, so now that's what I'm going to do and blame Jeremy. So my security, the reason I got into security is I went to KiwiCon. You want to be to KiwiCon? Woo! Great, so there's quite a few people that haven't been to KiwiCon. It's an awesome conference. I love it. It was the first time I went last year, and it was just great. You'll probably end up doing a talk on security in about six months' time if you go to it. So what happened? Don't get a police ankle monitor? Well, I wasn't really going to get one of those before anyway, but now I really won't get one of those. World War II bomb fuses, fascinating. Never thought I'd say that. Turn your monitor off when you leave the office, otherwise your data might escape through QR code videos. Don't ride electric skateboard downtown LA, otherwise someone might disconnect your remote and take over your skateboard and go the other direction. There was lots of beer, some handcuffs, badge challenge, lots of great people, and it was just awesome or splendid. I thought it was just great. So I'd highly recommend it that you go along and check it out. It's in Wellington every year, usually. So a little bit after that, I was inspired at KiwiCon. I saw this tweet by Laura Bell. So she's well known in the security sector, and she had a poor startup student non-for-profit. Yes, wanted a super cheap seat. That's me on a safe deck, 10-week course. Excellent. So I applied, and luckily I was lucky enough to get given a seat on this. So this talk is really for me to reinforce what I learned on that talk. Nothing forces you to learn something more than having to tell other people about it. So it's a bit outside my comfort zone, which is also a good thing. But also if I can inspire you guys, get you interested in the same thing I'm interested in, then we can have a good discussion at morning tea or something. So why is security so hard? I had a slide here that was going to scare you. It's like, oh, this thing happened last month, and this thing happened two months before that, and your car is going to go off the road, whatever. But you guys have all heard that, and we know that security is important, and we know that bad things happen to these big companies. But yet we still make the same mistakes. So why is it that even though we know the consequence, we still end up in the same routine? So there's some of the common questions. Are there really people out there who will do that? And I did get this question asked at me a couple of weeks ago. So yes, someone will enumerate your user list if you tell them the email's valid, but the password's not. But we're releasing it next week. We're giving it away, and we're releasing it next week. We don't have time to put security in before we release it, and nobody will attack us. We're just a little company in New Zealand trying to make it really big. Actually, that's a good one. So actually, we're on nobody will attack us. It doesn't really matter when you're really small, but when you're really big, then it really matters. So where's that line where you no longer small and start becoming big? You need to have it sort of all set up from the beginning. Well, we don't store anything important. We don't have medical records or something. It's $50 for a medical. We don't have that. We've just got email addresses, or we've just got this thing or that thing. You don't know that it's important until you've lost it. So even just an email address can be devastating to some people if that is published. And oh, this person went to that website can mean a lot of things. Actually, as a side note, I had a demo application based on that leak, but I thought that joke was not that appropriate. Well, we can't afford it yet. We'll wait until we get investment. Then we'll do security. Until then, we'll convince our investors it's fine, and they should give us lots of money before we make it really good. Or my framework already handles the security. I'm all good. I use Django, and it's out of the box. It's good. What are you talking about? So these are funny because we've all kind of heard them in one shape or form or another. But I think what it all boils down to is, as a developer, security is my responsibility. So I want to write good code. And secure code is good code. Therefore, I need to write secure code. And it's my responsibility. It's not someone else's responsibility. I can't go to the security team and say, make my thing secure. I finished it now. And it's actually not just developer, it's anyone. As a tester, as a insert anything here, I've touched this application. I should at least think about what implications my work has had on it. And ask your security team for help instead of forgiveness. So they're not going to do your work for you. You can't go to them and say, I need you to make this secure. It's your job. You're doing it. You're coding it. And at the end of the day, you're going to write the software. So they're your experts. They're the people you go to for help. They're going to help you write the nice code. And if you go to them and say, I need you to fix this shitty problem, no one's going to be very receptive to that. But if you went to them and said, look, I would like your input on how I should do this better, you'll find a huge, huge change in attitude. And if you don't have a security team that doesn't exclude you, there are plenty of small security companies, consultants that will help out on a range of budgets. So there's no excuse really. So I'll introduce this application, PASL. So it is a project I found on GitHub that was small enough that I could show you in about 20 minutes. And it's basically a PASPIN. So if you've used GitHub and you've got the just program, you can basically submit a little bit of text for your function. And it looks like this. You go and you push the link, say hello. And we just submit that. There's our text. And you can see a list of the recent ones. And there it is. And you can go and have a look. OK, it's all great. Now, if you didn't want everyone to be able to see this, you might want to put a password on it. So there's secure, three exclamation marks. So here we've got password and protect this text. Got my password there. Really good password. There's a button I don't really know what it means. So I'll just push submit. So cool. Now, it's password protected. I need to now enter this password every time I want to open this thing. So ABC, I mean, whatever my password was. And there's your thing. Now, the key observers, what's the problem with this? Is there anyone? No? No? Well, no, that's OK. Yes, yes. This is going out plain text. So I just put in my ABC and I push submit. And I'm on the open Wi-Fi with no encryption. Anyone else who's in the room, they could have seen that go by and got my password. That really is just, that's the worst. There's nothing you can do about that. So if we go back, create a new one. So the author of this package had said, oh, well, actually, I'll just zoom in on this a bit, keep in mind that passwords is transmitted in clear text. OK. That's not very good. Keep that in mind, whatever that means. And the password is not ciphered in the client's side, because shipping an SHA1 JavaScript library is perhaps too much. If you check the is encrypted checkbox, make sure your password is ciphered with SHA1, or perhaps you better use the console helper. So I'm a user of this thing. I've got no idea what he's talking about. He's gone on about an implementation of his JavaScript library. Anyway, let's try it out. So I've got my super encrypted thing. I need to make sure it's SHA1 encrypted. OK, well, we can do that after I googled and found out how to do that. OK, so there I've just hashed the word orange into those numbers. It's an algorithm that converts orange into that set of numbers. That's all it does. SHA1 is not a very good hashing algorithm either. It depends what you're using it for. So I copy that text, and I paste it there. I click the button and I submit. Great, now it's protected, and I type in orange. Super encrypted. What's wrong with that? Right, there's nothing. I've just sent my hash, which is the password, over the wire. It's still plain text, so I don't know why it's got that super encrypted feature there. Just as a side note, the author of this package does actually host this as HTTPS, and he does do all the right things there. So it's not something that he's doing really wrong. It's just that this feature is maybe a bit misleading. So let's see what else we can. Oh, yeah. Right, so let's go HTTPS. A bit of a quick recap. That gives us confidentiality. Our data is encrypted. That's what we were after. Our ABC is no longer ABC, no one can read it. We also get a couple other extra things, which are nice. We've got authenticity, means we can make sure that we're talking to the right person. We can validate that the person who's receiving this is actually the one we want to send it to. So you can make sure it's ASB Bank that you're talking to. And you can verify that. And integrity is that my data that I'm sending is gonna be the same when it gets to the other end. So even though someone might not be able to look at it, they can't actually change it either. So what do you do? What's the basic things? I had a whole bunch of lists of things here which ended up being far too complicated. And actually, because this is the first time I've really deployed in HTTPS, I went back to basics because perhaps it's the same for you guys. Use HTTPS on your whole site. Not even a question. Don't just put on your login form. It's everywhere. We'll get to some of the reasons why later on. So if you don't know what you're doing, don't host it yourself. How many people have self-signed certificates of unknown strength on a website somewhere? Right? Yeah, yeah. So my idea here is you're probably gonna leave them there for a year or two years or get back to them eventually. And maybe when you get back to them, you realize, oh, that was a bad idea. I should actually improve this. Well, if you just get someone else to host it from the get-go, maybe you pay the $10, $20 per month with Heroku. But whatever platform you find, pay that upfront to get a reasonable expectation of security. And then later on, when you're sort of going into more advanced stuff, you can say, okay, I can actually do this myself. And that's when you do that. So for example, if you're gonna do it yourself, the Mozilla SSL config generator, that will generate a starting point for your web server for SSL configuration. That's pretty good. So this is an example. You take, okay, I've got Apache or Nginx, and it's basically the beginning of why it's... Okay, I've used Heroku for this web application. So first thing I did to get HTTPS, I went, got a certificate, bought a certificate. It was $10. You won't need to buy certificates soon with let's get encrypted. Let's encrypt a free automated root authority. But that's coming out next month, so just keep an eye on that. So I bought my certificate, I uploaded it, I followed their blog thing, and right, now I have HTTPS. Let's just verify that that's what we've got. Okay, so we'll just go back to the main page. Might take a bit of time for Heroku to realize something's changed. And hey, we went back to the main page. It's redirected automatically to spastel. Spastel is a secure pastel. So spastel.xyz is the very popular domain name of months, also a dollar on special. So we've got spastel.xyz. It's redirected automatically, so that's really important. So that was my first change to his program is to automatically redirect, oops, it's just okay. So we had to go in here and we added a bit of middleware to bottle. So it's basically every request comes in, it's just checking to see should we need to redirect this and we'll redirect it for everything. So that was quite a neat little thing. I found a Stack Overflow, don't know what the license is on that, but I've put the link in there, so maybe that's okay. Cool, so what's next? So we've got our secure pastel. Now, it's a bit of a bother. Sorry, just before we get into that. It's a bit of a bother. Every time I wanna go and create my thing, I have to enter in my password. So if we look at our recent items, it's nothing there because we just restarted it. So password protect. So every time I want to access this, I need to enter that password and that's really annoying. So what can we do about that? This is a magical place where you store things called cookies. And the first time you discover these, you think this is amazing. I can do all sorts of stuff with this. This is a great, huge thing. I can put all my application logic in these cookies. It's great, it tastes great. So let's store our password in a cookie. I mean, I know you guys even know that sounds like a bad idea, right? Just because it's a security token, that's what I said. Let's do it and you say no. But why is it bad? Because cookies can be read using JavaScript. So even though you might be transmitting that cookie, using HTTPS, a bit of script on your page could actually read the contents of that cookie. So we protect it. There's a flag on your cookie. You set HTTP only to be true. And that means that your cookie is only accessible through HTTP. It's only gonna send it to your server. You can't actually access it through JavaScript. But cookies are sent with every request, which means even though your web server redirects you to the HTTPS version, if the person just went to the normal www.spastle.xyz, it would go, oh, here's the cookie you need. And that would go out in plain text. So that's not good either. But you can set the secure flag to true. So that means that only send the cookie when it's an HTTPS request. But ultimately, cookies are not encrypted by the client. You don't know what's gonna happen to them. So you never store anything personal. Never store anything identifiable. There are tools, there are viruses that will go and scan your cookies and grab all the information. It's just a bad idea. You don't put anything important in the cookie. So what do I do then? I still don't wanna enter my password every time. We authenticate and authorize. Now I've highlighted those two words. So is there anyone who would have auth? Let's add some auth into our program. We'll auth it, oh, auth. But there's actually two words there. And they're actually very different. They mean different things. So authentication is we're verifying who somebody is. So Jeremy's logged in. Is it actually Jeremy? That's all it is. Just making sure that it's Jeremy that's talking to us. And not someone who just claims to be Jeremy and actually isn't. But then authorization is to make sure that Jeremy is allowed to view that thing. Doesn't matter what it is, that's the authorization. So can Jeremy delete this database? Whatever it is you've got on your application. So let's add auth and auth into Spastal. So let's have a quick look at what we've added. We just added our authentication to make sure Jeremy is who he says he is. And there's a few things we needed to add here. We needed to add a few more libraries. So we've got some utilities for SQL for me. We've got some password library. We've added a new table into our model. New model into our system that's gonna hold a username and password. Now actually, by the way, this is the first mistake I'm making is I'm doing this myself. First thing you should be thinking is don't do it yourself. Go and look at your framework and use their tool. So there's heaps of gotchas when you're doing this and this is a very simplified example. So you don't wanna make those mistakes and find out about them later on. The problem is for bottle, there's a package called bottleAuth. And I didn't really want to suggest that we use bottleAuth to write up saying don't use auth. You must tell us what auth you mean. And then it imports a thing called auth into your namespace and I just couldn't do it. And there's another one for, that was actually for authentication. So it was for third party services like Google and Facebook and stuff. So we've added that table. We've added a few more methods to our server, a few more routes. We want to be able to sign up and log in and do things like that. So on our page, I'll just get that underway. So we've added in our login, that's gonna accept our username and password. We're gonna need to give our user something that they can use to then later authenticate. And that's usually what we do is we give them a token or a session ID or something like that. And that's basically a number that is very random, cryptographically random, that we can then check on our end to make sure that it's the same one we gave you earlier. And you can have timeouts on that, you can control things like that. So when the user logs in, you verify they are who they say they are by checking your database, right? They've got the right username, they've got the right password and then you give them this token so that every subsequent request, they can just give you the token and you can say, yep, you've been to the theme park before you've got your stamp on your wrist. So we've added a login form. So this is just to say, oh, that's, we'll log in. Hey, that's not right because we're not actually a member of the site yet. Let's sign up, create an account, you use it. Okay, so I haven't actually logged in yet, I've just registered myself on the website and now I can go and, so by the way, these passwords are still being sent in plain text. We haven't changed anything there, right? It's just now that we've got HTTPS encrypting our traffic. So as far as the implementation of that form, web form and stuff, I mean, that's all the same. Your traffic's encrypted, that's why you needed to redirect everything so you don't make a mistake and have an image leak your cook or your password. But the difference is now that we should get a token back from the server. And that's in the form of a cookie. It's a really handy little extension that will let you just view the cookies of your website that you're currently on. I think it's called cookie explorer. I only enable it when I'm doing something with it because it sort of needs all of the data to all your websites, but anyway. So there's my token. I've got this cookie, it's got a thing called token. It's got some random string in it. And I don't know who, I can't see who this is for anything like that. It's just a random number. And you can see I've got my secure tick and my HTTP only ticked. Cool, so now we're logged in. Let's go and make sure that we can create really secure text. And I've changed this bit at the bottom now. So now it just says, is this paste private? So now that I've signed in, I can say this one should be only for me. And then when I sign it next time, I don't have to keep logging in for every paste, but all of my private ones will be available. So let's make this private and we'll submit. So here it is. We've got the really, really secure one. And if we go back to our list of items, I can still view it. I don't have to type in my password. That token's being sent around everywhere. Right, so now we've got some user input. I modified that page. It was okay before because all it accepted was a password. But now I've actually got this username coming in. So I need to be careful because you don't ever trust your users. They will feed your database cream cheese and pizza just to see what will happen. So this is the classic example of injection where you select everything from our users where password equals the user input, right? And you've got quotes around your user input. Great. And then along comes your user and gives you his very, very secure user his password. He's got symbols and he's got numbers, equals signed and everything. That's great. Except now my query looks like this. Select everything from users where password equals empty or one equals one. So query is my cheese and the result is everything. I hear what some of you are saying. That's SQL. I don't use SQL. I use a NoSQL database. And it executes JavaScript. Anyway. So check your framework for tools to escape user input. Most database drivers, if not all of them, have a proper way to bind parameters. So you just say, this is the thing, goes here and here it is. I'll give it to you as a parameter instead. And you perform whitelist instead of blacklist because you can never possibly think of all of the crazy combinations people are gonna come up with. So if you are limiting it to a small subset, you use a whitelist. And make sure your web server is running through low privileges and create a user. Those are more sort of ambulance bottom of the cliff kind of thing. But it should be done anyway. So our spastile application, now that I changed it, is vulnerable to this. So we go to create a new, let's log out of Jeremy. And we'll go and create a new account. And my username is script alert. Hello. Script, I use that on all the forums, it's always available. So submit, yay, I've created an account. Now let's log in, it's fine. Ah, what's going on? Let's go and look at another page. So what's just happened there is a user outside of my control has been able to execute some JavaScript on my page. What's worse, it's now in my database so that every time someone else visits that page for that, that's a username, but you can see how it would work with a comment for a blog or something. So that's your cross-site scripting. So militia script sent to a user browser. It usually happens when you don't escape your output. And it can be easy to forget if it's coming from a database, right? Because it's like, oh, I put that stuff in there, that's fine. All those comments, oh yeah, wow, I didn't write all of those. So the consequences can be really bad. So if you haven't created your cookies, you could read a cookie and you could send it off somewhere else. You could redirect the user, you can steal information, you can do all sorts of crazy things. It's usually then you can use cross-site scripting with something else to do something even worse. So an important thing here, running out of time, but don't write your own sanitization function. It's like, I'm gonna implement a comms library. I'm gonna do a PhD's worth of work in five minutes. So don't reinvent the wheel, just reuse something that's proven to work. So in summary, we've looked at HTTPS, we've done some author north, that you're not gonna say author anymore. We've got some sessions, we've given a token back to our user, we've discovered that we had some user input problems and briefly touched on some cross-site scripting. So a big thanks to Laura Bell and Tom for helping me with this presentation. So I was a bit of a noob with this and it was nice to get there, sort of run through of it. So thanks guys. So the question was, have I done challenge response like an OAuth style thing? No, I haven't done that. It gets into this, that's a tricky thing as well. It's a good idea because then you don't have to store the passwords on your system. So you've got sort of a little bit less things, a little bit something less to worry about, but no, I haven't tried. There are some libraries for Bottle that can do that, that Bottle OAuth that I mentioned. But sometimes you can't get around it, you'll need a user account. People don't wanna use Google, they don't wanna use Facebook, they don't wanna use Twitter, they don't wanna use GitHub. They just want to give you an email address and a password. Well, I think so the question, the response was it's more secure that way. So your password's not being sent plain text? Well, even, yeah, okay. If you have the hash, you can still get the password. That's, it's not, it's not, but it's encrypted so you'll be okay.