1
00:00:02,140 --> 00:00:06,670
So don't put important information into your frontend code.

2
00:00:06,670 --> 00:00:11,860
Now let's move on to the next attack which is the most dangerous attack or the most dangerous attack

3
00:00:11,860 --> 00:00:19,780
pattern you can expose in your client side Javascript code and I'm specifically talking about the client

4
00:00:19,780 --> 00:00:26,680
side, so about the side which runs in the browser because the server side by default is way more secure

5
00:00:26,680 --> 00:00:33,550
and when we talk about server side attack patterns, they are not specific to Javascript, whereas cross

6
00:00:33,550 --> 00:00:37,070
site scripting and exposing security details is.

7
00:00:37,180 --> 00:00:41,390
So for the server side, there is a different range of potential attacks,

8
00:00:41,440 --> 00:00:47,350
one of them being CSRF attacks, others being SQL injection for example if you use a SQL database

9
00:00:47,770 --> 00:00:53,870
and I'm not talking about them here because they're not primarily related to Javascript. In my Node.js

10
00:00:53,880 --> 00:00:58,150
course which talks way more about server side code writing and so on,

11
00:00:58,390 --> 00:01:00,510
I do talk about more security holes

12
00:01:00,610 --> 00:01:02,950
you could expose on a server in general.

13
00:01:02,950 --> 00:01:08,860
So back to the Javascript specific ones and there, to cross site scripting attacks, also shortened or

14
00:01:08,860 --> 00:01:11,240
abbreviated with XSS.

15
00:01:11,440 --> 00:01:18,070
This is an attack pattern where malicious Javascript code gets injected into your application and is

16
00:01:18,130 --> 00:01:18,940
executed there.

17
00:01:18,940 --> 00:01:24,520
Now I'll show you an example for this because it can sound abstract at first but this is really a dangerous

18
00:01:24,520 --> 00:01:25,840
attack pattern,

19
00:01:25,840 --> 00:01:33,580
you have to imagine if people are able to add code to your application which all users of your application

20
00:01:33,580 --> 00:01:39,150
therefore execute, they are effectively executing code on the behalf of these users

21
00:01:39,160 --> 00:01:44,560
and at the same time on the behalf of your application on the machines of those users and your code

22
00:01:44,560 --> 00:01:47,890
can do anything the code you write could do as well,

23
00:01:47,890 --> 00:01:54,790
so your code could send requests to certain domains which might allow access by your application with

24
00:01:54,790 --> 00:01:56,440
the right CORS headers,

25
00:01:56,440 --> 00:02:02,500
the code might read the local browser storage of the user and send that to some server of the malicious

26
00:02:02,500 --> 00:02:05,560
user who injected the code and much more.

27
00:02:05,560 --> 00:02:11,650
If you're able to inject Javascript code into another page so that it runs for every visitor of that

28
00:02:11,650 --> 00:02:18,640
page, you're able to gather a lot of data about these visitors, potential security relevant data included

29
00:02:19,000 --> 00:02:24,760
and you're also able to fake a lot of things and send a lot of requests, maybe to your own malicious

30
00:02:24,760 --> 00:02:32,400
pages on the behalf of the application and only the behalf of the users visiting that application where you

31
00:02:32,410 --> 00:02:38,260
injected your code into so that's really dangerous. You've got full behind the scenes control if you

32
00:02:38,260 --> 00:02:44,920
inject code into another page. An example for that would be unchecked user generated content and I want

33
00:02:44,920 --> 00:02:52,000
to show you that example so that you understand what the problem is. When we talk about cross site scripting

34
00:02:52,000 --> 00:02:59,380
attacks, let's go back to our application here, to this share a place application and there let's generate

35
00:03:00,220 --> 00:03:01,170
an address,

36
00:03:01,240 --> 00:03:06,390
6th Avenue, find that place and then we have this shareable link here.

37
00:03:06,430 --> 00:03:11,560
This is the link which does not use our backend code with a database but which encodes all information

38
00:03:11,590 --> 00:03:17,440
into that URL, this attack pattern would also work with a backend database though

39
00:03:17,440 --> 00:03:19,030
and I will come back to that in a second.

40
00:03:19,030 --> 00:03:23,410
So here we have this link, we can visit this page and we see this page here,

41
00:03:23,410 --> 00:03:25,660
so that's of course not too fancy,

42
00:03:25,660 --> 00:03:27,800
how could this be insecure?

43
00:03:27,940 --> 00:03:31,780
Now if we have a look at our code, there we have the my-place.js file and

44
00:03:31,780 --> 00:03:38,440
this is the file responsible for displaying the page and this title here on this page once we visit

45
00:03:38,440 --> 00:03:45,930
this link with the encoded information, specifically there we set the title text content to our address.

46
00:03:45,940 --> 00:03:52,600
Now what if we would set, not the text content here which just sets the text node but in an HTML,

47
00:03:52,960 --> 00:03:59,710
eother as a mistake or because we actually do expect address to be more than just a plain string which

48
00:03:59,710 --> 00:04:04,780
it is in application but which it might not be in all applications and therefore since this might be

49
00:04:04,810 --> 00:04:11,020
HTML code we want to output, we want to set innerHTML to not just render a text node but all the HTML

50
00:04:11,020 --> 00:04:13,080
code which is inside of address.

51
00:04:13,450 --> 00:04:18,300
If we do that and I save that and reload, we get the same output as before,

52
00:04:18,310 --> 00:04:24,280
however if we inspect this in the developer tools, keep in mind we're setting the innerHTML code of the

53
00:04:24,280 --> 00:04:25,290
h1 tag

54
00:04:25,300 --> 00:04:31,140
and what we set there is the end what we send to address which is currently this part of the URL.

55
00:04:31,240 --> 00:04:34,180
Now what if this part were actually a script

56
00:04:34,180 --> 00:04:40,810
however? What if I prepared a URL which I want to share with other users which contains a script

57
00:04:41,200 --> 00:04:45,400
as the address and not every user might carefully look at that

58
00:04:45,490 --> 00:04:50,950
URL and therefore this might not be seen by all users who visit this page with whom I shared this

59
00:04:50,950 --> 00:04:52,060
link.

60
00:04:52,060 --> 00:04:58,760
So there, I could try to run an alert where I say hi there and hit enter,

61
00:04:58,840 --> 00:05:01,370
now what you see is now this is injected here,

62
00:05:01,390 --> 00:05:03,040
now we don't see a title here,

63
00:05:03,040 --> 00:05:08,610
instead we see the script was indeed added here because I'm rendering this as innerHTML.

64
00:05:08,710 --> 00:05:13,600
Now you also see it doesn't seem to execute though because actually modern browsers have a security

65
00:05:13,600 --> 00:05:20,920
mechanism where they don't execute script tags which are output with the help of innerHTML because

66
00:05:20,920 --> 00:05:27,790
of this exact scenario that you try or that someone tries to abuse a security hole in your application

67
00:05:28,150 --> 00:05:36,830
and inject Javascript code which executes on your behalf, also keep in mind that normal visitors

68
00:05:36,830 --> 00:05:39,210
off the page of course would probably not see that.

69
00:05:39,320 --> 00:05:43,850
They might wonder why they don't see a title but they don't typically check the developer tools to see

70
00:05:43,850 --> 00:05:44,660
what's in there,

71
00:05:44,750 --> 00:05:46,110
so they might not see that.

72
00:05:46,160 --> 00:05:48,850
Now still, this doesn't really seem to hurt us,

73
00:05:48,860 --> 00:05:54,640
it's certainly unexpected but since the browser doesn't execute that script, we're fine, right?

74
00:05:54,650 --> 00:06:00,080
Well turns out there's more than one way of executing script code, besides these script tags which indeed

75
00:06:00,170 --> 00:06:02,360
are prevented by the browser to execute,

76
00:06:02,540 --> 00:06:11,120
what if we added an image here with a source that does not exist and then add an onError handler where

77
00:06:11,120 --> 00:06:16,260
we then instead execute our Javascript code,

78
00:06:16,290 --> 00:06:18,740
this is a valid HTML element.

79
00:06:18,890 --> 00:06:24,480
Now the source is not found, therefore onError should trigger and we can add this kind of event listener

80
00:06:24,480 --> 00:06:25,620
to our elements,

81
00:06:25,620 --> 00:06:29,490
we as a developer don't want to do that because it's not really a good way of writing code

82
00:06:29,520 --> 00:06:35,630
but as an attacker it's great, we can add Javascript code that executes right on a HTML element.

83
00:06:35,970 --> 00:06:40,040
If I now hit enter, indeed we should see hi there, in Chrome at least

84
00:06:40,200 --> 00:06:44,880
and we see that here because this HTML code is injected here,

85
00:06:44,910 --> 00:06:48,090
This image tag is injected here, the source is not found

86
00:06:48,120 --> 00:06:54,690
so the onError handler executes and therefore this script, this alert executes. Now this alert of course

87
00:06:54,690 --> 00:07:00,420
is just annoying but keep in mind I can share this link with anyone, I can post it in a Facebook group

88
00:07:00,870 --> 00:07:02,440
for people to visit it

89
00:07:02,580 --> 00:07:06,600
and of course an alert is not that dangerous, it's just annoying and unexpected

90
00:07:06,600 --> 00:07:08,490
but here we could be doing other stuff too,

91
00:07:08,490 --> 00:07:12,350
we could be doing anything which might be security relevant.

92
00:07:12,630 --> 00:07:17,850
I could write a script in here and yes, we can write a longer script in here simply by separating our

93
00:07:17,850 --> 00:07:25,410
lines of semicolons, where I access the local storage, read data from it or read data from the local cookies

94
00:07:25,590 --> 00:07:32,010
and send that to my own malicious server for example. Visitors of the page will not see anything there,

95
00:07:32,010 --> 00:07:33,050
they don't get an alert,

96
00:07:33,060 --> 00:07:34,470
they don't get an error,

97
00:07:34,560 --> 00:07:47,700
I could even if I'm really bad in addition render a h2 tag here with 6th Avenue and then people might

98
00:07:47,700 --> 00:07:50,080
not see anything. If I now hit enter here,

99
00:07:50,130 --> 00:07:51,230
you don't get an error,

100
00:07:51,270 --> 00:07:51,530
okay I

101
00:07:51,540 --> 00:07:56,520
didn't format this, probably I should fix that but other than that, the page works as it should

102
00:07:56,520 --> 00:08:01,500
and here in the onError handler, in this script we can do whatever we want as an attacker. We can steal

103
00:08:01,500 --> 00:08:03,940
confidential data from browser storage,

104
00:08:04,080 --> 00:08:11,220
we can send requests on behalf of the user who visit this page with this link to any backend we want

105
00:08:11,580 --> 00:08:15,590
and that is therefore really dangerous. Here,

106
00:08:15,600 --> 00:08:20,610
this is a security hole we have in this application, we have this hole because here, we're outputting

107
00:08:20,790 --> 00:08:21,720
innerHTML.

108
00:08:21,750 --> 00:08:23,600
Now how can we fix that?

109
00:08:23,730 --> 00:08:30,300
One solution to fix this XSS security hole we have here is to use text continents instead of 

110
00:08:30,470 --> 00:08:31,060
innerHTML.

111
00:08:31,140 --> 00:08:37,710
If we do that and we visit this, you'll see now the code which previously was executed and rendered as

112
00:08:37,710 --> 00:08:44,130
HTML is now output as text and therefore if we had any Javascript code in here, like for example our

113
00:08:44,190 --> 00:08:45,060
alert again

114
00:08:49,370 --> 00:08:52,050
where I say hi would not execute.

115
00:08:52,070 --> 00:08:57,460
So now we automatically are not vulnerable to cross site scripting attack and if you never use 

116
00:08:57,470 --> 00:09:03,830
innerHTML anywhere in your code, you of course rule out a lot of potential attack patterns

117
00:09:03,890 --> 00:09:07,150
but with that alone you're not totally safe yet.

118
00:09:07,300 --> 00:09:09,990
For one, sometimes you might need innerHTML,

119
00:09:10,040 --> 00:09:16,670
so then you need a way around potential malicious code and in addition, it's not just innerHTML.

120
00:09:16,910 --> 00:09:24,470
If you're for some reason setting the onError handler of some HTML element dynamically to some user

121
00:09:24,470 --> 00:09:26,510
generated content in some way,

122
00:09:26,690 --> 00:09:31,270
Maybe you just want to have a user generated text which is output in here,

123
00:09:31,280 --> 00:09:37,790
well still then whenever you inject any user generated code anywhere into the DOM, this could be

124
00:09:37,790 --> 00:09:44,240
a potential issue so you always want to make sure you either inject it as only text with text content

125
00:09:44,240 --> 00:09:50,690
or if you set some other attribute of an element to some user generated content and potentially Javascript

126
00:09:50,690 --> 00:09:53,270
code could execute there, like with these onError

127
00:09:53,270 --> 00:09:59,850
and so on handlers, then you want to sanitize user generated content before you output it.

128
00:09:59,870 --> 00:10:06,980
So for example here, if if we really needed to use innerHTML, we want to sanitize the content before

129
00:10:07,130 --> 00:10:08,790
we output it here.

130
00:10:08,860 --> 00:10:16,250
Now sanitizing means that we strip away any Javascript syntax we might have in there, that starts with

131
00:10:16,250 --> 00:10:22,220
simple script tags but should also include common keywords like alert and so on.

132
00:10:22,220 --> 00:10:28,010
Now how can you work around the problem that you might need to inject user generated content somewhere

133
00:10:28,040 --> 00:10:30,000
where Javascript could execute?

134
00:10:30,140 --> 00:10:33,080
So you have no way of using a text content

135
00:10:33,290 --> 00:10:38,090
node here for example and you still want to make sure that the user generated data you're getting here

136
00:10:38,390 --> 00:10:41,230
is secure and doesn't contain any scripts that execute?

137
00:10:41,390 --> 00:10:45,150
You can use packages like sanitize-html.

138
00:10:45,260 --> 00:10:52,280
This is a package which basically helps you sanitize text and remove any unwanted tags in there so that

139
00:10:52,340 --> 00:10:54,980
invalid code doesn't execute in there.

140
00:10:55,010 --> 00:10:58,700
Now one import note can be found here in the description right away,

141
00:10:58,700 --> 00:11:03,830
this sanitization actually should be done on the server if possible,

142
00:11:03,830 --> 00:11:10,520
that simply means that if we were in our Node.js application here, we might want to store any user input

143
00:11:10,520 --> 00:11:11,110
we get,

144
00:11:11,120 --> 00:11:16,580
so in our case the address, before we put it into the database. So we sanitize it with this package for

145
00:11:16,580 --> 00:11:22,640
example on the server-side before we store it so that the sanitized code is stored in a database because

146
00:11:22,670 --> 00:11:27,560
that's also something I mentioned, this attack pattern does not only exist if you can inject it into the

147
00:11:27,560 --> 00:11:34,940
URL, it also exists of course if you store something in the database because here, I could be entering

148
00:11:34,940 --> 00:11:39,540
my malicious code, like this,

149
00:11:39,730 --> 00:11:46,150
click find place and find place triggers our server to store this in a database,

150
00:11:46,150 --> 00:11:47,400
then we have a problem.

151
00:11:47,680 --> 00:11:53,980
So I want to make sure that whatever I send here is validated on this server before it's stored in a

152
00:11:53,980 --> 00:11:58,060
database and you can do this with sanitize-html as well.

153
00:11:58,060 --> 00:12:02,490
You can also use this in the browser but that is a bit too late,

154
00:12:02,500 --> 00:12:08,710
it's not it's not too late from a security perspective but you still might have hacked or adjusted code

155
00:12:08,710 --> 00:12:10,810
in your database which you also don't want,

156
00:12:10,810 --> 00:12:14,280
it doesn't do any harm in there but it's not ideal,

157
00:12:14,350 --> 00:12:20,590
if you ever forget to sanitize a browser, you then have an issue. So try to sanitize on the server not

158
00:12:20,680 --> 00:12:22,180
on the browser.

159
00:12:22,180 --> 00:12:27,610
Anyways if you wanted to sanitize then, well then you would just need to make sure you have this package

160
00:12:27,610 --> 00:12:31,660
installed and you then can run the sanitize-html function,

161
00:12:31,780 --> 00:12:38,660
pass your user generated content so that variable which holds the content the user has to sanitize-html

162
00:12:38,680 --> 00:12:44,830
and then it will strip away things like that, it will ensure that this is not part of the output,

163
00:12:44,830 --> 00:12:49,540
that instead you are able to render HTML but only secure HTML,

164
00:12:49,540 --> 00:12:52,410
this is what sanitize-html does.

165
00:12:52,420 --> 00:12:53,930
Now how do you use that package?

166
00:12:54,220 --> 00:13:00,340
Well you can actually use the Node.js recommendation here, run this command here in your project so

167
00:13:00,340 --> 00:13:05,260
I quit my dev server and run npm install sanitize-html with the --save flag

168
00:13:10,360 --> 00:13:17,680
Now this will install it here as a dependency and in my-place.js, we can now import sanitize-html

169
00:13:17,800 --> 00:13:21,750
from sanitize-html

170
00:13:21,760 --> 00:13:28,110
and now here, whenever we want to output or inject some user generated content into an innerHTML tag

171
00:13:28,390 --> 00:13:34,100
or into another place where Javascript could execute, we run sanitizeHtml address

172
00:13:34,150 --> 00:13:35,240
in this case here.

173
00:13:35,390 --> 00:13:41,680
And if I do that and then we restart the development server here, with this added and the file saved,

174
00:13:43,330 --> 00:13:43,930
you will see that

175
00:13:43,930 --> 00:13:49,490
now if I reload this page here, the alert is not thrown,

176
00:13:49,630 --> 00:13:52,730
instead now I just have my header here

177
00:13:52,870 --> 00:13:59,320
even though I still have my dangerous code in there but that was stripped away by sanitize-html. So

178
00:13:59,320 --> 00:14:04,870
just to show this again, if I remove that and we reload it, we get the alert,

179
00:14:05,080 --> 00:14:09,440
if we add it again and I save it, we don't get the alert.

180
00:14:09,440 --> 00:14:13,210
So now we protect ourselves against cross site scripting attacks.

181
00:14:13,280 --> 00:14:17,410
Again this is best done on the server before it's stored in a database

182
00:14:17,480 --> 00:14:22,790
but in this example here, in this app where I don't have a server side, where it's all client side code,

183
00:14:23,090 --> 00:14:29,480
where it's just data that's part of URL, then of course our only chance is to do that sanitization

184
00:14:29,480 --> 00:14:31,830
in the browser and then we can do it like this

185
00:14:31,880 --> 00:14:36,950
and we're now making sure that this specific cross site scripting attack hole is fixed.
