2022 Web Development Bootcamp

Section 30: Website Security - Beyond Authentication

olivia_yj 2022. 9. 30. 01:19

The goals

💪🏻Security vs Authentication

✌🏻CSRF Attacks, XSS Attacks, SQL Injection

👍🏻Escaping & Sanitizing User Input

 

Security vs Authentication

Authentication

Control expected actions by your website visitors.

Grant some visitors (e.g. logged in visitors) more privileges than others

 

Website Security

Prevent unexpcted (potentially malicious)actions by visitors / other people

Prevent exposing data or granting unwanted access to certain actions or your code

 

Understanding CSRF Attacks

Cross Site Request Forgery

So here we are trying to be two types of users

First is just normal user and the other case is hacker which is bad user

we will open two ports, localhost:3000 and localhost:8000.

One is normal user and one is a hacker.

Let's see how hacker would do and how we should protect ourselves

 

Basically we can forge our request that will send to website and server to make some fuss

Or they just make a same looking website and send user's data to their database!

 

Same Site Cookies

The SameSite attribute tells browsers when and how to fire cookies in first- or third-party situations. SameSite is used by a variety of browsers to identify whether or not to allow a cookie to be accessed.

SameSiteExplicitly declare the use of cookies using attributes 

SameSiteBy introducing an attribute ( defined in RFC6265bis ), you can declare whether cookies should be restricted to first-party or same-site contexts. It is helpful to understand exactly what 'site' means here. A site is a combination of a domain suffix and the part of the domain immediately preceding it. For example, a www.web.devdomain is web.devpart of a site.

 

key terms

If the user is www.web.devat and static.web.devrequests an image from , this is a same-site request.

A list of public suffixes defines this, so it includes .comnot only top-level domains like , but also github.ioservices like . This allows your-project.github.ioand my-project.github.iocan be considered as separate sites.

key terms

If a user is your-project.github.ioat and my-project.github.iorequests an image from , this is a cross-site request.

Introducing attributes for cookies gives SameSiteyou three ways to control this behavior. You can choose not to specify an attribute, Strictor Laxyou can use or to limit cookies to same-site requests.

SameSiteIf set to Strict, cookies are only sent in first-party contexts. From the user's point of view, a cookie is only sent if that site matches the one currently displayed in the browser's URL bar. So , if the promo_showncookie is set to:

Set-Cookie: promo_shown=1; SameSite=Strict

When a user is on your site, a cookie is sent with the request as expected. However, if you follow a link from another site to your site, or through a friend's email, a cookie will not be sent on this initial request. promo_shownThis behavior is useful, but too restrictive if you have cookies associated with features that always work on your initial navigation, such as changing your password or making a purchase . We want a cookie to be sent to our readers so that they can apply their preferences when they come to the site by following this link.

Enabling the sending of cookies along with these top-level navigations SameSite=Laxhelps in this case. Let's go back to the example cat article above, which references your content on another site. They use cat pictures themselves and provide links to original articles.

<p>Look at this amazing cat!</p>
<img src="https://blog.example/blog/img/amazing-cat.png" />
<p>Read the <a href="https://blog.example/blog/cat.html">article</a>.</p>

And the cookie was set like this:

Set-Cookie: promo_shown=1; SameSite=Lax

When a reader is on someone else's blog, the cookie is not sentamazing-cat.png when the browser requests . However, when a reader follows a link on your blog, that request will include a cookie. Therefore , is a good choice for cookies that affect the display of the site, and is useful for cookies that are related to the actions the user is taking.cat.htmlLaxStrict

caution

StrictBoth are Laxnot perfect solutions for site security. Cookies are sent as part of a user request and should be treated the same as any other user input. This means that the input must be properly censored and validated. Never use cookies to store data that is considered server-side confidential.

Finally, as a way to implicitly state that you want the cookie to be sent in all contexts previously, there is a way to not specify a value. The latest draft of RFC6265bisSameSite=None explicitly introduces a new value for . In other words, Noneyou can intentionally communicate that you want the cookie to be sent in the context of a typing by using .

Explicitly indicate the context of the cookie with , None, Laxor .Strict

If you are providing services that are consumed by other sites, such as widgets, embedded content, affiliate programs, advertisements, or logins that span multiple sites, you should use , for clarity of intent None.

 

 

How should we protect our code?

It would be the best if the user doesn't click weird link on the email or message.

But we can't just hope it goes like that.

Then how we should do to protect this situation?

 

Use CSRF Token

A CSRF token is a unique, secret, unpredictable value that is generated by the server-side application and transmitted to the client in such a way that it is included in a subsequent HTTP request made by the client. When the later request is made, the server-side application validates that the request includes the expected token and rejects the request if the token is missing or invalid.

CSRF tokens can prevent CSRF attacks by making it impossible for an attacker to construct a fully valid HTTP request suitable for feeding to a victim user. Since the attacker cannot determine or predict the value of a user's CSRF token, they cannot construct a request with all the parameters that are necessary for the application to honor the request.

 

Csurf

Node.js CSRF protection middleware.

Requires either a session middleware or cookie-parser to be initialized first.

If you have questions on how this module is implemented, please read Understanding CSRF.

 

 

In general: ANY requests that manipulate something on your backend (typically POST requests -  but that's just a convention as you learned), should carry a CSRF token!

 

transaction.js

So we imported this csurf as middleware in app.js to use it and fix the route also to use csurf as variable in form page so when we make some request through the form we can send some special csurf value!

 

app.use(csrf());

 

send csrfToken to transaction

 

Understanding XSS Attacks

 

This code just got executed!

So they can inject malicious javascript code here!

 

Protecting Against XSS Attacks

In frontend JavaScript, we learned about that as the difference between someElement.textContent (for outputting content as plain text) vs someElement.innerHTML (for outputting it as to-be-parsed HTML)

 

 

Let's remind EJS code!

EJS template language

 <%- %> vs <%= %>

If we use <%= %> it escapes the input and it will be treated as plain text in the end.

So we should use this language when outputting user-generated content unless we really really know that we must parse it as actual HTML content

And when it comes to <%- %> case, we can see this when we use <%- include%>, it's not user-generated code. It's about what we  will show to user.

 

So, in this code, if we use <%- %> code then it will focus on what we will put is giving more control to developer not user.

 

And this is the sanitizing user input!

 

Sanitizing input in Express using express-validator

You’ve seen how to validate input that comes from the outside world to your Express app.

There’s one thing you quickly learn when you run a public-facing server: never trust the input.

Even if you sanitize and make sure that people can’t enter weird things using client-side code, you’ll still be subject to people using tools (even just the browser devtools) to POST directly to your endpoints.

Or bots trying every possible combination of exploit known to humans.

What you need to do is sanitizing your input.

The express-validator package you already use to validate input can also conveniently used to perform sanitization.

Say you have a POST endpoint that accepts the name, email and age parameters:

const express = require('express')
const app = express()

app.use(express.json())

app.post('/form', (req, res) => {
  const name  = req.body.name
  const email = req.body.email
  const age   = req.body.age
})

You might validate it using:

const express = require('express')
const app = express()

app.use(express.json())

app.post('/form', [
  check('name').isLength({ min: 3 }),
  check('email').isEmail(),
  check('age').isNumeric()
], (req, res) => {
  const name  = req.body.name
  const email = req.body.email
  const age   = req.body.age
})

You can add sanitization by piping the sanitization methods after the validation ones:

app.post('/form', [
  check('name').isLength({ min: 3 }).trim().escape(),
  check('email').isEmail().normalizeEmail(),
  check('age').isNumeric().trim().escape()
], (req, res) => {
  //...
})

We can sanitize the input value like this and return clean value!

 

So it changed a code to non-html code!

 

Understanding SQL Injection Attacks

We controlled our database. So this is NOT GOOD.

 

SQL Injection

SQL injection is a code injection technique that might destroy your database.

SQL injection is one of the most common web hacking techniques.

SQL injection is the placement of malicious code in SQL statements, via web page input.


SQL in Web Pages

SQL injection usually occurs when you ask a user for input, like their username/userid, and instead of a name/id, the user gives you an SQL statement that you will unknowingly run on your database.

Look at the following example which creates a SELECT statement by adding a variable (txtUserId) to a select string. The variable is fetched from user input (getRequestString):

Example

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

The rest of this chapter describes the potential dangers of using user input in SQL statements.

 

 

Use SQL Parameters for Protection

To protect a web site from SQL injection, you can use SQL parameters.

SQL parameters are values that are added to an SQL query at execution time, in a controlled manner.

ASP.NET Razor Example

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);

Note that parameters are represented in the SQL statement by a @ marker.

The SQL engine checks each parameter to ensure that it is correct for its column and are treated literally, and not as part of the SQL to be executed.

Another Example

txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);

Key Takeways

 

Don't trust your users - and especially not their input!

 

Also don't trust any frontend (browser-side) validation like HTML validation attributes (e.g. "required") or browser-side JavaScript logic -  all these things can be changed or disabled by advanced website visitors!

 

 

 

 

Sources

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite

 

SameSite cookies - HTTP | MDN

The SameSite attribute of the Set-Cookie HTTP response header allows you to declare if your cookie should be restricted to a first-party or same-site context.

developer.mozilla.org

https://www.kevel.com/blog/chrome-samesite/

 

SameSite Cookie Attribute: What It Is And Why It Matters

SameSite cookie attributes - what they are and how Google's Chrome 80 defaults will impact ad tech vendors and publishers

www.kevel.com

https://web.dev/samesite-cookies-explained/

 

SameSite 쿠키 설명

SameSite 속성을 사용하여 자사 및 타사 사용을 위해 쿠키를 표시하는 방법을 알아보세요. SameSite의 Lax 및 Strict 값을 사용하여 CSRF 공격에 대한 보호를 개선함으로써 사이트의 보안을 강화할 수 있

web.dev

https://portswigger.net/web-security/csrf/tokens

 

CSRF tokens | Web Security Academy

In this section, we'll explain what CSRF tokens are, how they protect against CSRF attacks, and how CSRF tokens should be generated and validated. What are ...

portswigger.net

https://www.stackhawk.com/blog/node-js-csrf-protection-guide-examples-and-how-to-enable-it/

 

Node.js CSRF Protection Guide: Examples and How to Enable It

Learn about cross-site request forgery, list some examples of CSRF attacks, and some mitigation strategies against them in Node.js.

www.stackhawk.com

https://www.npmjs.com/package/csurf

 

csurf

CSRF token middleware. Latest version: 1.11.0, last published: 3 years ago. Start using csurf in your project by running `npm i csurf`. There are 506 other projects in the npm registry using csurf.

www.npmjs.com

https://www.w3schools.com/sql/sql_injection.asp

 

SQL Injection

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com