We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Secure by accident

00:00

Formale Metadaten

Titel
Secure by accident
Untertitel
How performance optimisation can lead to more secure apps
Serientitel
Anzahl der Teile
542
Autor
Lizenz
CC-Namensnennung 2.0 Belgien:
Sie dürfen das Werk bzw. den Inhalt zu jedem legalen Zweck nutzen, verändern und in unveränderter oder veränderter Form vervielfältigen, verbreiten und öffentlich zugänglich machen, sofern Sie den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen.
Identifikatoren
Herausgeber
Erscheinungsjahr
Sprache

Inhaltliche Metadaten

Fachgebiet
Genre
Abstract
A security researcher known by the nickname percidae has drawn my attention to the Angular compilations. By bundling a single page application without code splitting, SPAs can make the job for penetration testers easier. This talk will look into an Angular app and highlight areas, where means for performance optimisation can lead to a more secure app. At the end of the presentation you should have a good understanding about how to read a webpack compilation for a SPA. You will know where to look for your own code and what webpack pulls in in addition. Other SPA frameworks could be affected as well, but are out of scope given the time constraint of this presentation. Subtitles will be provided after the event as .srt if I can find the time. Otherwise I encourage you to contact me and I'll send them. Accessibility is a human right.
Minkowski-MetrikComputersicherheitDatentypSkriptspracheHeegaard-ZerlegungCodeAutorisierungGebäude <Mathematik>AuthentifikationSoftwareentwicklerFramework <Informatik>Rechter WinkelLaufzeitfehlerNabel <Mathematik>IndexberechnungHash-AlgorithmusTemplateZeitzoneMaßerweiterungBrowserTextbausteinParserGammafunktionRouterTurtle <Informatik>Interface <Schaltung>SpieltheorieImplementierungMIDI <Musikelektronik>VektorrechnungKomponente <Software>Einfacher RingGruppe <Mathematik>MultiplikationsoperatorHeegaard-ZerlegungSoftwareentwicklerMapping <Computergraphik>Kartesische KoordinatenSchreiben <Datenverarbeitung>ServerFlächeninhaltElektronische PublikationRoutingCASE <Informatik>AutorisierungFramework <Informatik>Kategorie <Mathematik>App <Programm>MereologieMathematikTextbausteinWeb-SeiteGebäude <Mathematik>Hash-AlgorithmusLaufzeitfehlerPunktBrowserAppletShape <Informatik>ResultanteAttributierte GrammatikEDV-BeratungLastAutomatische IndexierungIdentifizierbarkeitZusammenhängender GraphCoxeter-GruppeRechenschieberCodeWort <Informatik>HilfesystemInformationExogene VariableProgrammierumgebungWeb-DesignerGrenzschichtablösungLokales MinimumInjektivitätNamensraumElement <Gruppentheorie>DiagrammComputeranimation
BenutzerfreundlichkeitVektorrechnungBildschirmmaskeRechenschieberGammafunktionEin-AusgabePasswortATMRouterSpezialrechnerZusammenhängender GraphTemplateEin-AusgabeSkalarproduktRoutingMapping <Computergraphik>BimodulRechenschieberPasswortEndliche ModelltheorieTypentheorieSchnelltasteBrowserFaserbündelCLIRouterApp <Programm>LastMereologieZeichenketteVererbungshierarchieDifferenz <Mathematik>FunktionalResultanteComputersicherheitBildschirmmaskeKartesische KoordinatenCoxeter-GruppeWeb-SeiteHomepageVerschlingungAutorisierungLanding PageElement <Gruppentheorie>
BimodulLokales NetzGraphische BenutzeroberflächeUnendlichkeitExpertensystemImplementierungCLIDialerRouterTypentheorieToken-RingBimodulApp <Programm>RoutingMereologieCASE <Informatik>SchnittmengeQuellcodeKlasse <Mathematik>InjektivitätZusammenhängender GraphFunktionalHash-AlgorithmusRechenschieberStrömungsrichtungKartesische KoordinatenMusterspracheTextbausteinCodeInterface <Schaltung>Automatische IndexierungZweiLastGeradeComputeranimation
VerzeichnisdienstComputersicherheitInhalt <Mathematik>E-MailKontrollstrukturPasswortKlasse <Mathematik>ÄhnlichkeitsgeometrieDatensichtgerätFehlermeldungLoginLastAutorisierungServerKonfiguration <Informatik>FaserbündelElektronische PublikationHydrostatikCoxeter-GruppeBenutzerprofilKategorie <Mathematik>ServerElektronische PublikationHash-AlgorithmusEinflussgrößeRechenschieberMailing-ListePasswortBefehl <Informatik>Kartesische KoordinatenBitRoutingAutorisierungDickeComputerspielE-MailMereologieCASE <Informatik>ForcingBildgebendes VerfahrenInformationProfil <Aerodynamik>AuthentifikationExogene VariableResultanteAusnahmebehandlungKlasse <Mathematik>Digital Rights ManagementComputersicherheitToken-RingService providerComputeranimation
Flussdiagramm
Transkript: Englisch(automatisch erzeugt)
Hello, everybody. Can you hear me? That's cool. I'm Andreas. I will talk today about CTU by accident. And the slides are to be published under a Creative Commons Attribution 4.0 license.
I am a freelancer since last month. I'm doing web development and consulting. I'm available on Mastodon, for example, and among other places. So if you have questions, please get in touch with me,
either afterwards, preferably outside, or on Mastodon. Who is the target audience? So I expect you to have some knowledge about Angular, about TypeScript, and Webpack. Because I can't go into thesis, it's not enough time for it. I'm interested in security and performance.
If you are, we are in good shape. What will you learn today? I'm going to something, which I will get to in a minute. And I'll show you which steps I take to reproduce it, help you to understand the results of a Webpack build.
And then go into more details, because you could see the child routes from Angular in the result. And I want to mention how you can protect them, what benefits it can have, and how code splitting works and helps with that.
A few words about how that came to be. I was approached by Perchida last year, and was researching something for security, and had questions about Angular, because that's not her expertise area.
I explained how Angular works, what the different files are meant, how to read it, and learned about which information you better not include in an Angular build without prior authentication and authorization. So we have four more seats here.
This presentation will focus on Angular, but the issue at hand is not limited to Angular. It will happen in React or V as well. So it's not something the framework can help you with, because it's a responsibility that lies with you as an app developer. I used Angular for this presentation.
It's a minimal application. And to help me with the webpack build, I used Pretia, which is also quite nice. So I started with a brand new Angular project, used the recommended approach to use ng new,
called Foster, because that was something I had in mind when I was writing the slides. And because we have to deal with Angular, the documentation isn't complete, so I had to install some more dependencies to be able to generate a build on a dev server environment.
As a result from the build, we get several files. For this presentation, I just looked at the JavaScript files, but I can also quickly go through what are the files meant for. We have several files, for example an HTML,
that is a minimal app shell. That means it contains a bare minimum of HTML you need to know to have to load the Angular files and some CSS and have the JavaScript file loaded we saw before. Then we have some size.something.css,
which is empty because at that point, we don't have styles applied to components, otherwise they would go in here. The hash is generated by a webpack at that point. We have a runtime file that contains the Angular runtime,
that those parts Angular needs to pass the template and manage the dependency injection and everything. Mostly not interesting from what we are interested in. We have polyfills that contain something like the zones, certain promises, features as polyfills, so if some browser doesn't support it,
it gets added to the global namespace. And we have the main file, which is mainly what we as an app developer wrote, but also some boilerplate code for example for RxJS or some other template-passing elements.
So what's the case right now? I looked at the routing file, the routing module, that's how it's generated by Angular and we are mainly interested in that route variable
over here. So I looked up what is the TypeScript definition for a route that's not complete, it's just a partial of it. We are mainly interested in those properties paths, especially the path and the component,
which is basically used if you don't use child routes or just have a mapping from a path segment to a component, but that's also helpful to have wider access is also something you will add early on to have a catch all route or write direct to a 404 page.
What is interesting for this presentation is also the children property, which is another area of routes and load children, which is used for lazy loading other route segments. So you can activate in front of it to guard it,
that means you have some check, okay, is the currently user allowed to access that route. If you then look into what is produced by Angular, you get some JavaScript file and can look for something with ng-generate-component,
because that's part of the index HTML that generated and that's part of the main app component that gets generated by the boilerplate code and that's the entry point above that line, it's Java Webpack boilerplate code,
so you can just ignore it for now. Below that is that what you as an author wrote. So next I created some components, the patient found, I thought about two more components for some of the speaker components and the slides component and let's say we want to protect the speaker component for some reason, if you then generate a new build,
you will see no other changes to it, so it's identically, why, because the build gets re-shaken by Webpack, that means that if you don't load those components, they will not be part of the build.
So let's include them then, we want to have them as routes, so I extend the routing module, declare a route for the slides and for the speakers, right now just without children, therefore I also have to import them. I added some ports because when I look
at Angular documentation, I often find that the documentation isn't complete, which is a bummer, so if you want to reproduce it yourself, I give you the necessary hints to follow along. So I added the route, I just reran the Angular build command
and gbuild and looked into the results and then for example, I see that the JavaScript now contains some more lines, the variable names or identify as my change because Angular and Webpack is mainly the variables, but it has something like this structure, for example, for the slides
or directly below the speaker, so that's what Angular makes out of your route definition. We also have a mapping from the path to the components, the components where the function calls before and that's how you can read it.
So if you are a security researcher, that is what you would look at and try to make sense of it. So I feel it's helpful to have, okay, we have the result now, how would I translate it back? Reverse engineer, so to speak. So the next thing we can add is general
catch all path that redirects to the slide page, so to some kind of landing page or index page or for everything else that can't be mapped, we have a page not found component.
So now I want to go into more details about how I would actually see the components that I had and the index, the app component HTML is really bloated and it tells you with an HTML command that you can drop certain paths and if you just remove everything within that diff container
with the role of main, with something more semantically, you could actually see, okay, what's happening here. No, what's doing on? So now we have updated our component HTML
and I can look into the guarding into defining child routes and I would like to have some kind of model. So I'm going with a template-driven form here.
It might also be possible to use a reactive form but most of the Angular applications I've worked with use the template-driven form, so I'm more familiar with that and just defined a model here, it's called auth with some string that is used as password.
It's just for demonstration purposes, you wouldn't use this kind in actual application, I hope. Okay, now we have defined it in the component part, we should also update the template and here it's like I remove that speaker work
and replace it with some basic HTML, still no styling because that's not relevant for what I'm doing here. I added a form element and basically an input and to demonstrate, okay, we have something working here, I show the link to the access,
so the slide subpass once a form is valid. So we have a password here with a type of password, so the browser is using that obfuscation with dots or stars or what have you and you have a model that's helpful for Angular as well,
so it's a two-way data binding and once it's valid, you get access to that anchor. So last thing you should have is because when you have shared routes, you should have a route outlet that tells Angular where to display that shared route.
So now we have updated the template, the next step will be to also update the route definition, so back to the routing module, I extended that speaker route, it's now not having a mapping from past component,
but it's also declaring, okay, we have some shared components here in this application, it would be slash speaker slash slide to access that shared component. It's still rendering the parent, the speaker component, but also the slide component in the router outlet.
So at that point, it would still be possible to look at the bundle and see, okay, we can enumerate every route in the application, so as a security search, I know, okay, this is the place I have to look at and check for security.
Going more into protecting the thing, the first thing I would do is defining a new route for the speaker module because that's a part of the presentation I want to protect. Angular CLI offers you a new, a way to generate the biopic for that as well with the ng-generate module,
which you tend to, okay, that's the name of the module, I want to have a router as well and I want to have it as a sub-module of app module. Once that speaker routing module is defined, or the speaker module is defined,
you can update the routing module of the app and replace everything you had there with just the path and then tell it to lazy load the speaker module. I will get to that in a minute, later on. So now I lazy load the whole speaker
module and I have to redo the slide sub-pass there. So I go into that, load the slides component, and okay, I want to have the slides module as a sub-component of the speaker module and the path for the speaker module is here,
it's an empty string because I already am in the speaker path from the parent component. It's also important to remove that speaker component from the app module definition because otherwise Angular will be sad. It can't have that in two places.
So once I generate a new build, I will now see that I have a second part about lazy shine files, which has some hash and some other hash. I come back to that as well and it has a speaker speaker module because that's what we defined and we have some sizes.
I can tell right now I really have some part of my application that gets lazy loaded. So that means it will only be loaded once that path segment is entered. Now I told you that I would like to protect that path segment. So I define a guard and GCLI have a guard schema
for that as well. So I run ng-generate or ng-guard and name it something. Here it's usually something like can activate, can deactivate or the other types of guards you have. You get a small interactive prompt for what do you want the guard to be able to do
and here it's for protecting the speaker. What I receive is that I get some boilerplate code provided by the GCLI again and I follow the documentation about how to define guards, define a user token and permissions stop basically.
Right now it's just returning true always. You would have some more checks here. For example, if there's some JSON token set in the local source or whatever you want. I also describe it as a documentation isn't complete here because either you have to export those two classes
or you have to declare them as injectable. So once those two classes are defined, you can have them somewhere else. You need to inject them into the guard itself, declare that the guard implements a can activate interface. That means it has to have a public function
called can activate that takes active route snapshot as one part and returns an observable whatever, not relevant for our case. I just want to use that injected permissions here and check the can activate method on it
and handle the current user and route patterns. There's some way you can do it and then you can check, okay, I want to enter that route with that user is he or she allowed to do that? In our case for demonstration, I just returned true. So it's always allowed, but you can also set it to false
to test it on your thing and discover that you get redirected to the index page, the slides. Now that we have a guard, I have to update the app routing module because I want to protect the speaker. And that means it gets a new line for the can activate,
which is a list of guards and now in our case only one. And I also have to tell us that there are some providers for those injected dependencies. Therefore it's important to have those two classes permissions and user tokens exported as well.
Otherwise I couldn't use them here. And now I'm at the part where I would like to use the name chunk, a magic comments from repack. And after my pitch and I got accepted, I discovered, hey, Angular doesn't support that,
but you can turn on the Angular JSON property in the, or the name chunk property in Angular JSON, which would give you not the hashes, but the whole file name that you would have in a death server. And therefore you could then apply some more security measures.
I will get to that on the next slide. For those of you who don't know what name chunks is, when you have that import statement for lazy loading, you can have a JavaScript comment, which is called repack name chunk and declare another name and repack will use that one
instead of the generated hash. So my idea is that you have certain files that are on your server then as static applications and you can add HTTP headers, for example, content security policy.
You can also look at the documentation about Angular and it says you have to have especially unsafe inline for scripts, which is bad because it allows more for attacks. If you can't use a content security policy, you still have the ability to declare it
as a char hash or as a nonce, which is a bit more labor, but in my experience, I worked with companies who deployed every other week or so that's the doable to compute a hash and add it to the HTML. The idea is that nobody else is able to cross that route
of the JavaScript chunk and look at two more because for example, you could have a list of certain passwords that was the case of Pecadia. And if you would like to attack that application, you can just exclude those passwords because they won't be valid anyway and therefore you would aid with credential stuffing that is trying out passwords
and credentials you found somewhere else. Or you can exclude your brute force attack because you know it has to have this length or this special characters are allowed or not allowed and therefore you would make the tremendous life easier. So I would like to have that not part of the bottle
but loaded from some JSON file or something else which is then be able to be protected. So basically having some authorization for certain information and only give more information once that user is authenticated. For example, by an authorization header and the response.
So what have you learned today? I hope you get a bit better understanding about how the result looks like, what Angular's producing, what name chunks are in Angular.
You learned a bit about content security policy which is really important. There's a documentation on MDN as well and learned about some ways to secure static files. I used creative comments images and provide the results
with the exception of the profile picture of Paquita but I got the written permission that I am allowed to use that one. Thank you, do you have questions?