CS3226

Web Programming and Applications

Lecture 09 - Security

Dr Steven Halim
stevenhalim@gmail.com

Are you a (white) hacker?
Try this https://xss-game.appspot.com/

Outline

Why Do We Discuss Security? (1)

Analogy: Writing a web application and hosting it in a 24/7 publicly accessible web server is like opening the doors of your home for both visitors and intruders (side story)

Visitors are legitimate users
You want them to visit and use your web application

Intruders are users with intention of harming your web application and/or its database
You do not want them to attack your web application

Why Do We Discuss Security? (2)

Web security is basically a collection of growing techniques to let visitors in and keep intruders out

You cannot say that your web application is 100% secure and then becomes complacent

This is an ongoing battle of good and evil

A1 and A2

Two most important concepts in web application security are Authentication (AuthN, A1) and Authorization (AuthZ, A2)

Authentication (AuthN, A1)

Authentication is simply a way to tell a web application about who you are (what you know/have/are)

Usually by means of (strong) password (side story: a brute force dictionary attack experiment in a CS3233 contest)

In more sensitive web applications (e.g. Internet banking), we may also use additional token for 2FA*

PS: We are not yet in the era where biometric* authentication system is widespread yet

Authorization (AuthZ, A2)

Appropriate authorization level is granted by the web application after successful authentication

Example authorization levels @ VisuAlgo translation system:

  1. Admin (can grant approver/translation access to a user account)
  2. Approver (can approve translation work done by others for production use)
  3. Translator (can translate VisuAlgo English texts into a certain language)
  4. Normal user (can only view the translated text in various languages)

Implementation Details

HTTP Basic A1

Laravel built-in A1 system + additional A2

Optional: Old manual A1+A2 system

Review: HTTP Basic A1 (1)

Pros:

  1. It is simple to use (see HTTP lecture)
  2. It 'works*' okay if:
    1. We have a protected (read-only) content that we publish in the Internet, but
    2. We only want a few trusted readers to be able to read it by providing the userids/passwords
      (or just a single userid/password) to those users via separate means

Review: HTTP Basic A1 (2)

Cons:

  1. It is very inflexible, 0/1 authorization levels*
    1. 0 = no access to those who do not know the password
    2. 1 = full access for those who know the password
  2. It does not work well on shared Virtual Machine
  3. Poor user interface (uses browser default)
  4. User has to be notified of their password via other means
  5. User cannot (or can but too troublesome to) ask the admin (web application owner) to change their password

Laravel Built-in A1 System

Magic, just use:

php artisan make:auth

Assuming that we have done (any) database migration,
then the users and password_resets table should have been created too

Using Laravel Auth Scaffold

The following routes are automatically created:

  1. /register: Show a form for creating a new user account to be included in the users table
  2. /login: Show a form for login/Authorization (A1) purposes
  3. /logout: To logout from this session
  4. /password/reset: To show a form for entering a (registered) email address for password reset feature (more details here)

Customizing the Layout/Forms

Go to /resources/views/auth directory and /resources/views/layouts directory (optional) to find the relevant blade files that you can edit to suit your needs

Customizing Your App

If you now open your /routes/web.php file, you will see that it has Middleware Auth::routes()

If you only need the basic /login and /logout functionalities and want to disallow /register and/or /password/reset, you can comment out that Auth::routes() and replace it with the required routes only:

$this->get('login', 'Auth\LoginController@showLoginForm'); // for login form
$this->post('login', 'Auth\LoginController@login'); // for the actual login
$this->get('logout', 'Auth\LoginController@logout'); // for the actual logout

The Authorization (A2) Part

There are two general ways
(both requires database schema migration/refresh):

  1. Create the ACCESS table as in database lecture, or
  2. Just add one more column ACCESS in table users

Either way, we can use different integers (or enum) to differentiate the various roles

We can also use bitmask if we need to represent a small subset of (related) privileges

Middleware RedirectIfNotAdmin

To use the A2 feature, we need to create custom Middleware:

php artisan make:middleware RedirectIfNotAdmin

Then modify the 'handle' function:

public function handle($request, Closure $next) {
  if (Auth::user()->access != 1) // e.g. 1 = admin, 0 = normal user in db
    return redirect('/'); // redirect
  return $next($request); // else, allow the request to go through
}

And we register this middleware at /app/Http/Kernel.php:

Customizing Your App - Cont (1)

With Laravel A1 system plus additional A2 feature, we can now use middleware Auth in our Controller(s) to differentiate what are allowed/not depending on whether a user has logged in and what is his/her credentials

All these are mostly just if-else checks..., e.g. we can put simple if-else code like this in our /resources/views/navbar.blade.php

@if (Auth::check()) // just like this
   Logout {{ Auth::user()->name }}
@else
  Admin Login
@endif

Customizing Your App - Cont (2)

We can also put this code in the construction of our controller:

public function __construct() {
  $this->middleware('auth', ['except' => [ 'index' ]]); // A1 check
  $this->middleware('admin', ['except' => [ 'index' ]]); // A2 check
  // e.g. if one accesses method create/edit/delete but not authenticated
  // he/she will be redirected to /login
}

So that user must be logged in/authenticated (pass A1) and must have admin privilege (pass A2) before he/she can access the functions in our controller except that index

Old Manual A1+A2 System

Use PHP server-side scripting + MySQL database
(FYI only, as this is outdated)

Here are the key ingredients:

  1. A user table in our (supposedly more secure*) database, typically with the following schema: user_id, hashed* password (use crypt function in PHP*), and authorization level, something like this
  1. A sign in page login.php with typically two input boxes, a user_id and a password
    (with masked input like this )

    This script performs check against our database if such user_id exists and his/her hashed password (using the same one-way hashing algorithm, note about 'salt' if using PHP crypt function) matches the one stored in our database, typically we return a new session ID and let this user_id access resources according to his/her authorization level; If the sign in fails, we redirect the user back to login page

  1. A sign up page signup.php that allows initially total stranger to use your web application by specifying their preferred user_id and password (entered twice*, preferably with password strength indicator), and optional email field for password reset functionality (no 4 below)
  1. For convenience: A forget password page forgetpassword.php with at least one input: either user_id or useremail and we will send email with newly generated password to user's registered email address

    Be careful of not opening security loophole here

  2. For convenience: A change password page changepassword.php with typically four input: user_id, old password, new password (entered twice, preferably with password strength indicator)

    Similarly, be careful of not opening security loophole here

  1. For extra piece of mind: A logout page logout.php that basically destroys all session information, cookies (if any), and basically tries to 'forget' who you are (that is, the reverse of A1)

    Side discussion: Do we always need to logout from a web application?

Basic Web Security Principles

This is my current compilation so far and should grow over time

  1. NEVER TRUST THE USER

    Sanitize everything that comes from user (e.g. escape all quotes from string that will form (part of) SQL queries to minimize SQL injection), never trust client-side validation (it may have been bypassed by attackers who know his/her stuffs — example with Lab4/5/6, etc), whitelist* which users are allowed access and what those users can do — example with recursion @ VisuAlgo...

  1. DO NOT HARM OTHER (GOOD) USERS

    In case bad stuffs ever enter your web application database, do not let it affects your other (good) users

    BACKUP your database often, setup cron jobs for this

  1. Web Browser (Client-side) Same Origin* Policy

    The main reason why popular web browsers typically employ Same Origin Policy is for privacy issue (you don't want a random website to be able to check your personal details while you happens to have your Facebook account open in another browser tab) and to minimize Cross (Xross) Site Scripting (XSS, not CSS) attacks
    For now, I assume that you will* put your server-side (PHP) scripts in the same origin as your client-side (JS) scripts

  1. Setup Correct File/Directory Permissions

    Summary of permissions for "others" in UNIX file system:

    DirectoriesExecute only, no read access
    HTML/CSS/JS (client-side) filesRead only, so that the client web browser can read them
    PHP/SQL filesRead only, sensitive credentials outside public_html
  2. Turn off Apache's default directory listing via:

    sudo a2dismod autoindex

  1. Use HTTP POST instead of HTTP GET to avoid exposing sensitive user data in the URL (minimize shoulder surfing attack)

  1. Use HTTPS (HTTP over SSL) so that our HTTP requests/responses are encrypted

    Super important if your web application involves user accounts

    But you need to setup SSL (Secure Socket Layer) certificate...

    Good news: It is actually not that hard in Digital Ocean + LetsEncrypt (since 2015)

  1. Use (re)-CAPTCHA to differentiate human versus machine

    If necessary, you can use application-specific CAPTCHA, like this (but not maintained though...)

Notes (1)

By knowing more about (web) security, you will realize that your current web application is actually not that secure...
Try reading this OWASP (Open Web Application Security Project) Top 10 list

The more popular/important your web application is, the greater the need of making it as secure as possible...

Notes (2)

This lecture is short and will continually be updated with more details for future AYs

If this is not yet your final semester and you are "weak" at this topic, I recommend you to take security modules in SoC
CS5331 - Web Security is a very relevant level 5 module taught by my colleague Dr Prateek Saxena

Finally, I will close this topic by giving you this link: https://xss-game.appspot.com/; At least you should be able to clear the first level by yourself (it has been discussed in this lecture)

The End

Try https://xss-game.appspot.com/ if you have not done so