← All talks

BSIDESKyiv 2018 - ALEX RESHETNYK JS - SECURING THE HIPSTER STACK

BSides Ukraine43:3291 viewsPublished 2018-05Watch on YouTube ↗
About this talk
JS - SECURING THE HIPSTER STACK Figuring out if the common security problems remain relevant for new technologies Alex is Web Application Security Engineer at SoftSeq. He started his career as a programmer - first as a C ++ Developer at Luxoft, then as a Backend Engineer at Do It Programming Solutions. At first, when he was a programmer, security was more like a hobby for him. He looked for vulnerabilities and shortcomings in his projects and tried to point out to colleagues unsafe places in their projects.
Show transcript [en]

Now I'll show you how it works. How does a regular day of security engineer look like. Andrey already told you at the end of the lecture. But I'll show you again. Look. Not like that, not like that at all. What is it? Why? Come on, quote. Well, what have you done? Okay, look, this is a quote. This is enter, this is stack trace. This is me if everything worked out. It would seem that everything is fine, but in fact it's not like that. My typical day goes like this: "Enter" and the same "Enter" and nothing works out. When I worked as a programmer, no one was interested in security. We were sitting with the guys for a beer, I asked them: "Guys, how do you handle your own

Angular, XSS and everything?" They are like: "What? It's SPA, it's modern, Facebook made it, Google made it, what do you mean?" And everything is fine there. But I'm not used to take all this stuff for granted, so I decided to check it myself. Well, to google it, to read it. So today we will check modern stack for vulnerability. In order to break it, you need to first understand where to look. Andrey already told you where to look, how to push, what to push, it's very cool. It doesn't matter. If you want, I can tell you why JavaScript became popular. Well, there were guys sitting, they had a bunch of front-enders. Front-enders wrote, wrote, and they thought: "Damn, we still need to hire back-enders." Think about

it. Let's take the same engine that runs JavaScript in the browser and make a backend. It will be really cool. We will have full stacks and we will be able to hire less specialists. But in fact, all these jokes about JavaScript, you have seen them anyway. Comparing an object with a mass, adding various perverted lines. Jokes about JavaScript. But in fact, JavaScript is the only front-end language, and all corporations have started By making their own browsers, this fact improved and improved and improved. This made him a really normal friend, despite the fact that his author wrote on his knee for 20 days. And he is like: "Oh my God, why?" So, in fact, it's quite

easy to teach him. He has a large community, a package manager, everything is very cool. So, I said where we need to look. This is Avast Top 10, but here are not 10 points, because I excluded from them what does not concern today's presentation. Not at all. We are talking about injection. For now, no candy, sorry. Injections are: SQL injection, command injection, XSS - all of them are injections. About sensitive data exposure, it's when you made your own rest up and didn't protect it. And guys keep walking and walking, sensitive data exposure in relation to our lecture. Security misconfiguration is all the same open ports, default passwords and all sorts of things like that. I've

already told you a lot about XSS, but I'll repeat it again. It occurs when the user input appears uncoded on the page. So you can insert any arbitrary script there and do very bad things, like taking a cuckoo, drawing a cat on the page. and transfer users to another site, by putting an iframe under his mouse. About deserialization, it's when you get an object from backend to frontend, for example, in the form of a line, and you form it back into an object to work with it. If you don't do it right, you can execute a random code, because it's an object, you can add some load to it, and it will work. But it's still unpleasant. And about the

components, It works like this: someone says: "We have an old Angular, why don't I update it? Everything will break, let's just not touch anything, everything will be fine, I swear." But in fact, no. You need to look through your dependencies automatically and see which of them have dangerous vulnerabilities. Let's start with Nintendo. And it's SPA. SPA is Single Page Application. It became a hype recently because it allows your frontend looks more like an app, just because you don't have a page reboot, you make the first request to the server, you get the whole frontend right away. Then this frontend is drawn and handles its routes completely in javascript and pulls data from the backend with ajaxes, which most often look like restabs. This allows you to make beautiful animations

between transitions from page to page, because your page is not loading, and you can do it smoothly and beautifully. And besides, there is a lot of syntax sugar, all sorts of goodies, which, in principle, greatly facilitates the life of a programmer, especially in complex applications. For example, imagine you will make an application for 500 pages using JavaScript and jQuery. Okay, this can be done, but the problem will be that you will have It's a complicated and highly connected code. Besides, you should not forget about security. For each input you need to apply certain sanitization, it should be centralized. But in all these modern frameworks there are already built-in mechanisms for this. For security, for authentication. Everything becomes quite simple. And you

spend less time writing code, but more time, but more features. And it's more pleasant to write. Not writing code for the sake of writing code, but writing code for the sake of making a normal product. So, it's time for sweets. Raise your hands, who can tell me about XSS with three points? Well, let's do it. Well, look. Does XSS work? Yes. Well, for example, we make a picture, we insert some non-existent resource into it. The picture has the method "unload onError", which will execute any script in case the picture is not loaded. Here is an example. Okay, how to protect from it? I'm not questioning, I'm not perceiving myself as a mean teacher, we're just talking here, guys, really.

Ah, there is an insertion, maybe, a key? No, look, there... Yes, filter the output. That is, you need to convert... command instructions of HTML, opening and closing brackets in HTML code. So when it is inserted into the page, it is not parsed by browser and it is impossible to execute the arbitrary code. The picture is just an example. You can put a script, you can put a text script, but it's very fat. The guys didn't try at all. - So the absence of - Screening of user's name and name of user in form. - Yes. - That's it? - Yes. - It was easy. - Super. I hope it will be so in the future. It's a very

interesting format. But the problem is that HTML is a pretty top-notch example. Because in fact, there are a lot of different contexts in the modern web. HTML is just one of them. For example, context of JavaScript, context of link, context of style. All of this needs to be sanitized and screened correctly. Why? For example, we allow a user to insert a link, to form a link, so that someone will click on it later. We think that the user is good, he will insert http there, everything will be fine. In fact, the user can insert JavaScript, JavaScript protocol, and he will get a message when he clicks. what he wrote there, that is, the JavaScript load that he made there. We have already talked about HTML and code.

As for files, a large number of applications work with files somehow. They are loaded onto servers, displayed somehow. In some applications, even metadata files are displayed, such as size, date of creation, and so on. This is also a user input, because the user completely owns the file, and he can write anything there, even tags. So, if you directly trust the metadata of the user's file, it's the same vector as the usual user input. And, of course, there are many other things that are in your application, work with files, or display on the header page, query parameters as a result of, for example, a search request, metadata of files, as I said. By the way, I forgot to ask. Are there

any of you who write on Angular, React? Do you have production experience? Everything is fine. I will torture you a little. I remembered you, I will torture you, but I will give you candy. We agreed, I think. - attack vectors, like giant recursive tags, huge javascripts. So I hope you already understood that custom sanitizers don't work. They don't work at all. Do you know why? Because javascript is without types and it's dynamic. HTML is also quite free and you have about a million ways to make your attack vector is not available for all these filters. In fact, it's true. If you look on GitHub, there are, in my opinion, more than a thousand different vectors for one XSS

file. How do we solve the problems with escape in modern SPA technology? In Angular 1, in all versions of Angular 1 to 2, there was a certain SCS service. It was just the topic that according to context, user input. As I said, JS, URL, HTML, styles sanitized everything. But there was also sanitize that worked only with HTML. For example, you had to display user input in HTML form on the page, it was necessarily passed through the sanitize service. If the sanitize could remove all unnecessary and dangerous things from there, it did it. If it couldn't, it threw an exception. These wonderful things can be cut off, of course. I did it once, I'm not proud of it, honestly. I didn't believe what I

was doing. I won't do it anymore. Okay. There is DomSanitizer service in older Angular. These are the same eggs, but in the profile. They combined SCA and Sanitize into one thing, called it more obvious, and now it is doing the same thing. It escapes and sanitizes immediately. Of course, there are ways to make it easier, as in any framework. There are several unsafe methods to insert raw HTML right there. About React. React has managed to do its job with its virtual home. There is no dedicated service, because it is quite lightweight. You can't turn it off. You will have to live with it. Everything escapes you. It's great. But of course there are also some unsafe methods, but even with them

it's quite difficult to insert some vector into the page. Because even developers who need to insert some valid script, they are somehow stumbling there. In JavaScript, they combine parts of the markup. They stumbling well. I saw such overflow and got scared. React is normal. So, now we will talk about how to break all these beautiful things. See? This is a motto of many developers. It sounds like "Security by optimism and prayer". Let's consider this thing. I already said that SPA is all client-side rendering. That is, you make one request to the backend and you get the whole frontend, which is dynamically updated with AJAX. And server-side is when you contact the server on each route and the

server already forms each specific page. All this has its pros and cons. It's not that interesting. Server-side has all optimizations, and so on. This slide is just a summary. Does anyone have any idea why I'm looking at it here? The answer is, of course, a candy. SPA cannot be indexed by any system. It is used as a client-side rendering for clients and as a server-side rendering for service providers. Okay, and how does it work? What does server-side rendering have to do with it? If the same CSS can lead to the same attack on the same CSS. Okay, and you? Probably because the same CSS can be used for the server. It will be two sweets, but I'll tell you why. It's

great close, but no.

The problem is that SPA is a frontend thing that doesn't come out of the browser. So it should just ask for some API and update on this API. Some guys think: "Listen, SPA is so fashionable, and let's do it on Angular, on Vue, on React, everything will be very cool." But at the same time we need SEO, and we have PHP developers, let's mix it all up and it will be cool. In fact, no. Because when a page is formed on the server, such a beautiful thing, for example, data from the get parameter, is inserted into templates on the server, then it is given to the client, And the client renders it. No React, no Angular, no any new technology. It

is initialized after you have the nasty HTML. It doesn't sanitize it in any way. If you do server-side rendering with these SPAs, forget about built-in protection in frameworks. Because it doesn't work when you leave user input on the server. You need to code it with the help of the server. and insert the page. There is another great thing. Many people like to use jQuery and jQlite with Angular, React, whatever. Angular works with DOM, React works with DOM, but we will use Javascript to install. I saw a great thing. Guys decided to add a tag to the page. They did it very well. They selected the whole document and re-pressed it to the HTML with this tag. So, all

the input that was not so vulnerable, became vulnerable. Just because of one string transfer. Angular is like its own big factory. It's a combine. It even rewrote the log. You don't make a console log, but you make a dollar log. You don't make some abstract XML HTTP or fashionable AJAX, but you make a dollar HTTP. It makes overtkings with all methods and thus it protects them. But if you use JavaScript or jQuery or something else, you can also successfully forget about built-in framework protection, because it passes by it and is inserted directly on the page. What are web devs doing nowadays? They are rewriting frontend, but it's not for sure.

Now let's see what problems are in each selected framework. Angular is the first. It has a sandbox. Many guys say that sandbox sounds like something antivirus. It is definitely created for protection. I'm answering you. And in general, do not forget that Angular was made by Google, and in general, Google already knows how to do things. This is a thing for protection. So, it never was a thing for protection. It was for the wonderful devs to stop hanging variables on Windows and started doing it normally using Angular. So, in principle, in the first version of Angular, this thing was perfectly bypassed by calling We get to the object, create a new object, you know, these are prototype studies, dynamic languages, all

sorts of funny things. So, as I said, it was never a security mechanism, and devs, apparently, are so tired of poor Google that he sawed it out from Angular 1.6 and didn't add it to the second one at all. They made a separate article, for some reason it was never a security mechanism, and how did they plan to use it? I'm sure it was in the doc, but who reads it? We just need to have an overflow and it's okay. There are also wonderful things. This one Andrey has already shown, but I'll tell you a little more now. I said that you did it. All the honors to Andrey. I just liked it, it fits my topic a little bit. There was such a

thing called Spoofed Element in React. In general, if you use React with JSX, then you don't need it. This is not a problem for you. Because in JSX you just immediately mix the stack with JavaScript, make JavaScript cycles by tags, Compilers and transpilers do it for you. You use syntax sugar and it has different input. But if you decided to do it without JSX, with React createElement and pass second and third parameters, props and children, some user input, it can lead to cool things. For example, in props you can add a newly created component property setDangerouslyInnerHTML and write your HTML there. You will have a great new element that is fully controlled by the attack on the page, which is XSS. If such a thing

is passed to children, you can create another element for the child on which this case is called and write your logic there. It will also be fully controlled by the user. One smart guy found such vulnerability on HackerOne himself and reported it to HackerOne. This is because he says: "I like to put unusual things in the usual thing. For example, there is a number, I will make a mass out of it. There is a number, I will make an object out of it. Well, he did it. It turned out fine. He transferred the mass there, and he created two elements as children, which he fully controlled. But it was fixed in the React itself. Not so interesting.

Again, about mixing server-side rendering with modern technologies, like ToView. Here is a great thing. Let's say you had a post request when you created some logic on the frontend. In this post request you inserted some user data. Sounds normal. The problem is that you are doing it with server-side rendering and these things go straight to the HTML page. And you can just take and finish creating the object new view, for example, Closing brackets, you go closer to the "cool" You exit the object creation, write your own load, and then just take and rewrite everything that was above. Very beautiful. So that it does not paint, so that it works somehow. This is all a wonderful thing. It is in

the get parameter. And you give a link to your friend and say: "Click". He clicks, and there is his face. Cool. Let's move away from SPA and move to the usual templates that are formed by the server. The bug is exactly this. It is normal, but the problem is when you allow users to dynamically create pages themselves. For example, you have a project, it is creating an HTML letter. And you allow the user to mark the text for this letter and then open it in a new page. User can use JavaScript logic there. And what will happen? How do all these templates work? They execute server code to fill in this template. So, in principle,

we can do it even easier in JavaScript. We can spawn the process there. Make connection to your server, lure Bitcoin. Cool. No, we don't read. Tell me now how to avoid all this. Who wants to tell? The candy is still in style. What do you remember from this speech? What not to do? At least someone. Do you want a candy, Andrey? I'm a little bit... I'll correct you. You shouldn't write your own programs for... There is a ready-made solution. It's very simple. You just install them and use them. You don't even need to write a code. That's the secret of success of JavaScript. But in general, you said it right. And that's good. I would also advise devs to

try to look at their project from the outside. from attacker's side. Because you are sitting behind the PC and you are like being blocked by Angular. And nobody will get me here. But in fact, no. Well, basically, what you said. You don't need to mess around, you don't need to mix client and server side templates. This is equivalent to not having to trust the entire user input. And, of course, again, don't mess around. Don't interfere with Angular, with plain.js, with jqlite, with javascript. If you want to make a mess, just take it to directive. Do it normally. Again, be careful with all user inputs. And don't do eval. Never. It's like goto. Everyone heard about goto, everyone laughed at it,

but actually goto is normal compared to eval. Yes. Now let's move to the backend. Together with Angular React, the same JavaScript is used on the backend to hire fullstacks, to make it pleasant, because the same data is given, JSON goes back and forth, it is updated, it's very cool. I've already told you about Node a little bit. This is the same JS, but on the server. It is executed using the same V8, under the JavaScript engine. It is asynchronous and it is basically a wrap-up of the operating system. It's very simple if you already know about JavaScript. Express is a syntax sugar for the server part. You can create your own back-end routes, make your own logic, make middlewares for authorization. normal logging system. It makes things much

more pleasant than it could be done with a regular node. And of course, a huge amount of NPM packages that help you a lot. Let's do it again. Four candies on the horse. Let's start with the first one. Who is ready to tell about SQL lecture? Half of the audience raised their hands. What do you mean? Half of the audience raised their hands at the last lecture because they don't know what is SQL. Where are you? Candy on the horse.

Okay, good. Again, the problem with user input verification. For example, the user's name is entered, and if we do not use the parameterized request, when we write a request to the database, then we can write the symbol of the end of the line and then insert any injection. How to protect yourself from this? Validation, screened and using parameterized queries. Great. Can you tell me, it's a bonus question, if you use ORM, or you use parameterized queue. How else can you allow SQL injection? It's quite an obvious thing. In case of ORM you need to read documentation, because it protects not all injections. For example, in like it may not protect, and it needs to be studied and be ready. I'll say more.

You can do custom functions in SQL. They don't work with ORMs, they are all plain. like Plains SQL. If you add any user input there, even if it's a base recording, then there can still be an SQL injection. It will just not be in the place where you expect it. Super. Two. I said the question with an asterisk, an additional candy. Three candies are canceled. Okay, about remote code execution. I'll quickly remind you. The same as in all other languages, only in JavaScript. eval, function that is transferred to setTimeout, setInterval, creation of a new function with a user input. All of this is a potential remote code execution. But in some Java, you are protected from it somehow. In Node, you can do anything. DOS,

just insert it into file 1. File system access, just import the file system package. Execute everything. Everything is in your hands. You don't need it. Please, better gota. No SQL injection. It's the same, just a little different syntax. But NoSQL-based are the same as JavaScript. They even work with functions. It's even worse if you don't escape them. It's all the same. Everything I said before. Access to the file system, execution of the arbitrary code. Everything. Please. ORMs and sanitized, prepared statement. Even in NoSQL. In all NoSQL. Cassandra, all these new things. Whatever. Let's talk about rest api. Let's say you have two rest api: public api, which allows you to post ads, and private api. Public api should be protected, because people will see

what a good-written api they have. And let me use it too. Just make a key to limit the number of incoming requests on your rest api. And I'll tell you a little more about private. CSRF, good old CSRF. It's a pity there won't be any candy. The simplest approach. You can use JVT, but not cookies. If there are no cookies, there are no problems. Because CSRF is all about cookies. Each request is attached to a cookie, the request can be made from any other server and the cookie will fly to that server. If you still need to use cookies, everything is already built-in. The only thing you need to do is to insert, to make a cookie using Express, which is called XSRF token. Then

Angular will see that such a cookie exists, will also submit it to the header, and you will get the implementation of double submit token, which will protect you from the CSRF. You can also check origin and referrer, but it is not a fact that they will be, so you don't need to rely only on this. It's the same, guys. About Defensive Depth. Look, any user input that has already been in the base, well, the base is also an unreliable place. You don't have to think that if it's a base record, then everything is fine there. No. You could miss some validation place on the frontend, on the backend, anywhere else. You will already get into the base If you display it in the same place

where there is no sanitization or validation, because you didn't expect that there would be such a nasty thing in the database, you will have vulnerability. It is better to escape and sanitize everything in general. Between layers. Frontend-backend, backend-data base, backend-data base, frontend-data base. Everywhere, on each of these layers, you need to sanitize and validate. Don't do it. And no custom sanitizers, please. And read Wasp. Everything will be fine. About whitelists vs blacklists. I repeat once again. You remember how many options there were to make XSS. There are also many options to make any other crap. Therefore, you will not have enough patience to spoil such a blacklist. It is easier to just specify what should definitely be there. What is definitely trusted.

How much time? 7 minutes. Oh, that's reactive. I'll tell you what I didn't tell you about CORS. In such things as Angular and API you need to configure CORS, especially if it's some abstract docker with a bunch of microservices. and it will be on different domains, you need to set the core. You don't need to make the core too wide. You need to make it star-star. Set all your domains that you use so that the attacker can't just take and accidentally insert a file from some of his resources on yours. Okay. Andrey told about this. Cut off all methods you don't know what they do. Head, trace, whatever. Well, you need head, Angular uses head, don't cut it off. Open ports. Close all ports you

don't know why they are needed. Close them. Default passwords. There will be more examples about Tesla later, it's quite fun. Open folders on the server. There are utilities that just browse the well-known folder names and when they find such a folder, they can just download it. Take the whole folder with the .git folder, find metadata files from the .ios folder or something like that. And that's it. About Docker. is a virtualization system. It's not the same as VirtualBox. VirtualBox is a ready-made system for which you roll your software, your packages. Docker is a little different. The guys thought: "Why should we carry the whole VM if we can take the main packages of the system

and the system itself and make it a separate layer?" Then the user will just pull this layer and make its own changes. This div between the core of the system and the user's additional packages is a docker container. So, in fact, our core is between all instances. If you use any version of Docker, there are excellent CVEs of vulnerability that allow you to exit the docker and execute the arbitrary code on the entire server to all your containers. Not very pleasant. Regarding the lack of protection. Some people use AWS and don't protect it at all. They don't close it. It will be further in the lecture, guys. There are just data, Excel, reports, user data. You

just take it, google it, find it, open it, download it. Great. Also in the modern NoSQL. No one wants to close it too. They are like: "What do you mean? This is a new technology, nothing can happen. We are hipsters, we don't write about all the old bad things." Everything will be ok. But in fact, no. All the same problems that exist in old technologies, in most cases, there are also in new ones. About Dev Instances. Tesla had Jenkins. They were testing, testing, testing. But the problem is that there is a console, a web console, which they did not notice and did not close. So the guys found this Dev Console, and there was a default login and password. They went there and

hung miners on Jenkins. Who of you could think why tests are taking so long? The last thing you could think about is that attacker came, found our dev instance and put miners in it. Miners were there for a year and earned several million. How do you like it, Elon Musk? Okay, about NPM modules. This is a hype topic. In NPM modules, they do the nasty thing that will mine crypto on our backend. Well, guys, what do you mean? This is how it works. These similar domains, invisible symbols. You click and go. Here it works exactly the same. You put the package once for the whole application. Just choose a normal package and copy the name. This problem is generally with all package managers. Where users

can fill their packages, they can also fill the filth. It is also obvious how to validate and code everything. Unpleasant summary. What you write on Facebook or Google technologies doesn't mean that you can just sit and not think about what will happen if you don't worry about user input. It helps you a lot in protecting your application. It really makes your life easier. But nevertheless, write code carefully and think from the outside, from the outside of the system. How would an attacker look at my code? How could he find my crotch? Because for an attacker who was a developer, like me, it's quite simple. You just think: "Hmm, I would probably crotch here." And yes, they crotch there. It's

really very simple. Just look at your code from the outside. It was already. Questions? Candy, of course, too.