CMPUT 404

Web Applications and Architecture

Web Security

Created by
Abram Hindle (abram.hindle@ualberta.ca)
and Hazel Campbell (hazel.campbell@ualberta.ca).
Copyright 2014-2023.

Goals of Web Security

Leak Prevention
Prevent unauthorized access of information owned by the organization (business, school...)
User Privacy
Prevent unauthorized access of other user's information
  • Other users by logged-in users
  • All users by logged-out users
  • Legally required!

Goals of Web Security

RCE on Server
Prevent code that is unauthorized/unknown/dangerous/etc. from being run on the server by people outside of the organization/business.
  • Ransomware
  • Miners
  • Proxies & Botnets
XSS
Cross Site Scripting. Unauthorized code or actions running on the client, usually the browser.
  • Reflected
  • Persistent
  • DOM-based
  • Server
  • Client

Goals of Web Security

CSRF
Cross-Site Request Forgery. Any action that appears to be taken on an authorized user's behalf but isn't actually... including GET.
SSRF
Server-Side Request Forgery. Any action that appears to be taken on an authorized server/service's behalf but isn't actually... including GET.
DoS
Denial of Service. Anything that causes the web site or web service to be unable to serve its normal users.

High-Value Targets

  • Personal Information
  • Private Information
  • Ransom-able Information
  • Compute Resources (Mining)
  • Network Resources (Proxy/Botnets)

What's Getting Exploited

Mitre's Top 25 Weaknesses. (Includes non-Web weakenesses.)

Is your website supposed to...

  • Distribute malware/worms/viruses?
  • Vouch for the identity of fraudsters?
  • Send spam?
  • Distribute pirated software/media?
  • Run crypto-miners?
  • Host pornography?
  • Help attack other services?

XSS (Cross-Site Scripting)

  • Doesn't need to come from another site
  • Inclusion of unauthorized HTML/CSS/JavaScript in page.
  • Malicious code that runs in the browser.
  • Malicious code that runs on the server is not XSS, it's RCE.

XSS Types

Where does the bad code come from?

Server
URL navigation, <script>, <link, src=, ...
Client
Bad code comes from an AJAX call.
DOM
When bad code is generated by code on the client that modifies the DOM.

XSS Types

How long is the malicious code around?

Reflected (Type 1)
Provided by a single server response as an immediate response to a malicious request.
Persistent (Type 2)
Provided by any number of server responses. The malicious code is stored on the server.

XSS Types

Server Client DOM
Reflected Reflected Server XSS Reflected Client XSS Reflected DOM XSS
Stored Stored Server XSS Stored Client XSS Stored DOM XSS

Reflected Server XSS Example

  1. Error page generated server side that complains about incorrect query parameters.
  2. Error page shows user their incorrect query parameters.
  3. Error page does not stop contents of query parameters from being interpreted by the browser as HTML/CSS/JS code.

Stored Server XSS Example

  1. User profile page on server allows user to enter a description or bio for themselves.
  2. Bio is stored on server.
  3. Anyone navigating to the page sees the user's custom bio.
  4. Someone sets their bio to contain HTML/CSS/JS.

XSS and URLs

someAElement.href = "http://mysite.com/?q=" + searchQuery
someAElement.href = "http://mysite.com/users/" + userName + "/profile"

Server XSS Prevention

  • Check incoming POST/GET parameters, paths, & uploads for validity.
    • Should a user be able to enter their name as <script>?
  • Apply HTML/CSS/JS escaping to anything filled in.
    • Example: Use built-in library functions to change < to &lt; in HTML.

XSS Prevention

  • Avoid "unsafe sinks"
    • .innerHTML (react: dangerouslySetInnerHTML)
    • document.write()
    • .onevent
    • eval()
    • setTimeout(string)/setInterval(string)

XSS Prevention

  • Use safe sinks instead
    • .innerHTML.textContent
    • document.write() → create elements the OO way
    • .oneventaddEventListener
    • eval() → Just don't.
    • setTimeout(string)/setInterval(string)
  • if (typeof somecode === 'function') {
        setTimeout(somecode);
    } else { throw new Error("Possible XSS?"); }

Apply Escaping EVERYWHERE

  • Any time something is inserted by interpolation, templating, AJAX, etc. consider it could possbly be exploited.
  • If its a URL, apply percent encoding to variables.
    # Python example:
    dest = base_url + item_name + '?t=' + tracking_id
    # Instead:
    import quote from urllib.parse
    dest = base_url + quote(item_name) + '?t=' + quote(tracking_id)
  • If it's being added to HTML, apply entity encoding to &<>"'&amp;&lt;&gt;&quot;&apos;

Apply Escaping EVERYWHERE

  • CSS
    • Make sure you only put variables into css values.
    • Make sure values are quoted and escaped.
      // JS Example
      customized_style = "body { background-color: " + user_color + "}";
      # Instead:
      customized_style = "body { background-color: \"" + CSS.escape(user_color) + "\"}";

Apply Escaping EVERYWHERE

  • JavaScript
    • Best to just avoid ever interpolating something into JavaScript.
    • Use an encoder library.
    • Place value in single quotes and convert every character to a hex code or unicode code.
      # Python example
      output_js = "someFunction('" + some_string + "');"
      # should be changed to something like
      output_js = "someFunction('" + ''.join(['\\u' + hex(ord(c)) for c in some_string]) +"');"

Lock it down!

  • HTTP: Content-Security-Policy: default-src: 'self'; img-src https://*;
  • HTML: <meta http-equiv="Content-Security-Policy" content="default-src: 'self'; img-src https://*;">
  • Unlock inline CSS: style-src: 'unsafe-inline';
  • 'self' value means only other URLs on the same source (domain, http/https & port number) can be used.
  • Only listing 'self' prevents use of inline data.

CSP

  • Example script-src: 'self':
  • <script src="/scripts/banana.js"></script><!-- this one loads ok -->
    <script src="https://some.cdn.com/somelibrary.js"></script><!-- not allowed, different origin -->
    <script>
        alert("This one doesn't load, it's unsafe inline.");
    </script>
    <button onclick='alert("this one doesnt load either, unsafe inline")'>

CSP

  • General approach
    1. Set 'default-src: self;' and see what breaks.
    2. Add exceptions as needed
      or
      move things out of inline.

Cross-Site Request Forgery (CSRF)

  • Trick a user or user-agent into executing malicious requests.
  • Hijack weak authentication measures.
  • Repeat actions unnecessarily.

Cross-Site Request Forgery (CSRF)

  • Server-side ("Classic") CSRF
    • Server cannot tell if request is coming from a legitimate client/user or not.
  • Client-side CSRF
    • Legitimate Client-side JavaScript running in the authorized user's browser is tricked into sending an unwanted, or malicious request.

Server-Side CSRF Mitigation

  • Check Referer header.
  • Request tokens
    • Most Frameworks come with this! For example, Django!
    • Generate unique token with each GET of a HTML form.
    • Send token by using a
      <input type="hidden" name="csrfToken" value="4399b92a-7a75-11ee-b962-0242ac120002">

Server-Side CSRF Mitigation

  • Include bearer auth with AJAX that isn't public GET.
  • Make sure unsafe actions (actions that change state) aren't GET.
    • /logout should not be a GET
  • Apply XSS prevention
    • XSS & CSRF are often combined!

CSRF Mitigation

  • Naive Double-Submit Cookie
    1. Server sets random cookie on first visit.
    2. When any request is made, browser always sends cookie.
    3. Also send cookie as a hidden form field or with custom header in AJAX request.
      • Browsers only allow custom headers to be set for same-origin requests!
    4. Server double-checks they match.

CSRF Mitigation

  • Access-Control-Allow- headers.
    Access-Control-Allow-Origin: http://mobile.yoursite.com
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Headers: My-Custom-Header
  • Access-Control-Allow-Origin: * allows any origin but it cannot be sent at the same time as Access-Control-Allow-Credentials: true.

Path Travesal Exploit

  • Using relative paths like
    .
    ..
    .
    ./././etc/passwd

Path Travesal Mitigation

  • Reject / in things like names in the first place.
  • Reject sequences such as .., /.., ./
  • Don't use regular expressions to check these 💀
  • Use path library to convert relative path to absolute path, and check that its still in the correct folder

SQL Injection

  • The famous XKCD Comic
  • Example:
    cursor.execute("select * from user_table where name = " + user_name + ";")
  • What's the problem here?

SQL Injection

  • The famous XKCD Comic
  • Example:
    cursor.execute("select * from user_table where name = " + user_name + ";")
  • What's the problem here?
    • user_name = '"oopsie"; drop table user_table;'
    • user_name = '"oopsie"; update user_table set admin=TRUE where name = "Hazel";'

Preventing SQL Injection

  • Never construct an SQL query from strings!
  • Use placeholders instead!
# Python/sqlite3 example
import sqlite3
con = sqlite3.connect("mydatabase.db")
con.execute("SELECT * FROM user_table WHERE name = " + user_name + ";") # BAD WRONG DO NOT
con.execute("SELECT * FROM user_table WHERE name = ?;", (user_name,)) # good yes do do this

Shell Injection

  • Like SQL injection
  • But with shell commands (command-line commands)
    • Unix/Linux/MacOS sh
    • Windows cmd & powershell

Preventing Shell Injection

  • Validate paths and names
  • Don't execute commands as shell commands, do direct exec...
import subprocess
subprocess.run("program operation --option " + file_name) # BAD, will be run with system shell
subprocess.run(["program", "operation", "--option", file_name]) # GOOD, run directly

Poorly Secured Cookies/Tokens

  • We want the server to go stateless!
  • We want the client/user to remember the state, not us!
  • So lets use cookies or tokens and make the browser/client remember it.

Poorly Secured Cookies/Tokens

  • What if they forge or tamper with the cookie/token?
  • What if the cookie/token gets stolen?
    • Does the hacker even have to log in?
  • What if the cookie/token gets reused?
  • What if the cookie/token gets repeated?
  • Hackers can change data even when it's encrypted.
    • It might not decrypt to something that makes sense anymore, but that's fine if it lets the hacker do what they want!
  • Integrity must also be protected.
    • Rely on secure hash functions
    • Salt hashes
    • Key hashes
    • Hash the WHOLE thing (entire message plus important context)
  • Single Service creates messages (tokens) that it can verify it created:
    • Rely on secure hash functions (not your own, not MD5)
    • Salt hashes
    • Key hashes
    • Hash the WHOLE thing (entire message plus important context)
    • Hash the encrypted text if encrypting (EtM)
    • Use different keys for hash and for encryption
  • Two services that need to verify the other created messages:
    • Cryptographic Signatures
  • Actually it's better to just use a widely-known library...
  • Making your own encyption code that's actually secure, rather than just looking secure, is difficult!

Tokens are not that safe...

  • Include info in tokens about:
    • When it was made
    • For who it was made
    • For what IP it was made
    • When its expected to expire
    • What purposes it can be used for
    • What backend version made it
    • What frontend version requested it

DoS Denial of Service

  • An attacker makes a service unavailable
  • Common methods:
    • Spamming
    • Flooding
    • Filling queues with large requests
    • Sending useless expensive jobs
    • Using all available Resources
      • CPU
      • RAM
      • Disk
      • Network

DDoS: Distributed DoS

  • Same thing as DoS when the attacker has
  • Many computers (lightbulbs)
  • or computers all over the world
  • or computers that will Reflect requests
  • or some way to redirect or reroute legitimate traffic to the target

Non-Distributed DoS Mitigation

  • Limit cpu time/ram/disk per request
    • HTTP 517 Insufficient Storage
  • Limit request size
    • HTTP 413 Content Too Large
  • Limit requests per second per user
    • HTTP 429 Too Many Requests
  • Limit users per IP or network
  • Limit clients per user
  • Limit ...
  • CAPTCHAs
    • HTTP 402 Payment Required

DDoS Mitigation

  • Look for patterns in trafic and filter out that pattern
    • Specific requests/endpoints/paths?
    • Specific areas of the world?
    • Specific user agents?
    • Specific HTTP headers?

DDoS Mitigation

  • Maintain white-lists of known-good request sources
    • Only allow users who were logged-in before the attack started
    • Only allow IPs who accessed before the attack started
    • Use IP "reputation lists"
    • Session cookies from before the attack started

DDoS Mitigation

  • Pay for cloud-based caching & DDoS defense reverse-proxies
    • Fastly
    • Akami
    • Cisco Umbrella
    • ...
  • Host your own caching & defense reverse-proxy...
    • HAProxy
    • BunkerWeb
    • FastNetMon
    • Various HTTP server (nginx, etc.) config and plugins
    • ...

License

Copyright 2014-2023 ⓒ Abram Hindle

Copyright 2019-2023 ⓒ Hazel Victoria Campbell and contributors

Creative Commons Licence
The textual components and original images of this slide deck are placed under the Creative Commons is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Other images used under fair use and copyright their copyright holders.

License


Copyright (C) 2019-2023 Hazel Victoria Campbell
Copyright (C) 2014-2023 Abram Hindle and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN.

01234567890123456789012345678901234567890123456789012345678901234567890123456789