Are you a (white) hacker?
Try this https://xss-game.appspot.com/
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
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
Two most important concepts in web application security are Authentication (AuthN, A1) and Authorization (AuthZ, A2)
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
Appropriate authorization level is granted by the web application after successful authentication
Example authorization levels @ VisuAlgo translation system:
Pros:
Cons:
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
The following routes are automatically created:
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
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
There are two general ways
(both requires database schema migration/refresh):
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
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:
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
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
Use PHP server-side scripting + MySQL database
(FYI only, as this is outdated)
Here are the key ingredients:
login.php
with typically two input boxes, a user_id and a passwordThis 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
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)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 addressBe careful of not opening security loophole here
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
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?
This is my current compilation so far and should grow over time
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...
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
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
Summary of permissions for "others" in UNIX file system:
Directories | Execute only, no read access |
HTML/CSS/JS (client-side) files | Read only, so that the client web browser can read them |
PHP/SQL files | Read only, sensitive credentials outside public_html |
Turn off Apache's default directory listing via:
sudo a2dismod autoindex
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)
If necessary, you can use application-specific CAPTCHA, like this (but not maintained though...)
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...
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)
Try https://xss-game.appspot.com/ if you have not done so