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
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
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
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 .
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 are setting the "cookie" option to a non-false value, then you must use cookie-parser before this module.
- Otherwise, you must use a session middleware before this module. For example:
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!
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!
Understanding XSS Attacks
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