Web Attacks & Defenses
George Obaido
Slides from , , , ,
Copyright By PowCoder代写 加微信 powcoder
https://github.com/OWASP/Top10/blob/master/2017/OWASP%20Top%2010-2017%20(en).pdf
Phishing: Types
• A type of social engineering where an attacker sends a fraudulent message designed to trick individuals into revealing sensitive information
• Spear phishing: Targeted towards a specific individual or brand that appears
trusted. E.g. Company’s admin, etc.
• Whaling: Aimed at senior executives (high-ranking), masquerading as legitimate email.
• Smishing: An attack that uses text messages or short message service (SMS) to execute an attack.
• Email phishing: Email phishing is the most common type of phishing, and it has been in use since the 1990s. Hackers send these emails to any email addresses they can obtain.
Mitigations
• Learn to recognize all the tell-tale signs
• Always check suspicious emails
• Use multifactor authentication (MFA) and consider advanced password solutions.
• Use proper email security
• Train end-users
Cross Site Request Forgery (CSRF)
Typical Authentication Cookies
POST /login: username=X, password=Y
200 OK cookie: name=BankAuth, value=39e839f928ab79
GET /accounts
cookie: name=BankAuth, value=39e839f928ab79
POST /transfer
cookie: name=BankAuth, value=39e839f928ab79
CSRF Scenario
• User is signed into bank.com
• An open session in another tab, or just has not signed off • Cookie remains in browser state
• User then visits attacker.com
• Attacker sends POST request to bank.com
• Browser sends bank.com cookie when making the request (assume SameSite=None)
CSRF via POST Request
SameSite Cookies
Cookie option that prevents browser from sending a cookie with cross-site requests.
SameSite=Strict Never send cookie in any cross-site browsing context, even when following a regular link. If a logged-in user follows a link to a private GitHub project from email, GitHub will not receive the session cookie and the user will not be able to access the project.
SameSite= cookie is allowed when following a navigation link but blocks it in CSRF-prone request methods (e.g. POST).
SameSite=None Send cookies from any context.
Referer/Origin Validation
The Referer request header contains the URL of the previous web page from which a link to the currently requested page was followed. The Origin header is similar, but only sent for POSTs and only sends the origin. Both headers allows servers to identify what origin initiated the request.
https://bank.com -> https://attacker.com ->
https://bank.com https://bank.com X
-> https://bank.com ???
Not so great…
• Assumption: GET requests are not side-effecting
• Some are. Need another mechanism to tell your server request is coming from you.
• Assumption 2: browser will not send cookie cross-site if Lax/Strict set • Old browsers ignore cookie attributes they don’t recognize.
A better future:
• Solves fundamental problem: Tell server who they are talking to
• Sec-Fetch-Site: {cross-site, same-origin, same-site, none} Who is making the request?
• Sec-Fetch-Mode: {navigate, cors, no-cors, same-origin, websocker} What kind of request?
• Sec-Fetch-User: ?1
Did the user initiate the request?
• Sec-Fetch-Dest: {audio,document,font,script,..} Where does the response end up?
CSRF Summary
Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on another web application (where they’re typically authenticated)
CSRF attacks specifically target state-changing requests, not data theft since the attacker cannot see the response to the forged request.
– Validation Tokens (forms and async), robust but hard to implement
– Referer and Origin Headers, not sent with every request + privacy concern – SameSite Cookies, fail-open on old browsers
– , robust but not supported on old browsers
Server-side Injection
Command Injection
• Injection bugs happen when you take user input data and allow it to be passed on to a program (or system) that will interpret it as code
• Database
• Sound familiar?
• Similar idea to our low-level vulnerabilities, but at a higher level
Injection bugs in Python
Most high-level languages have safe ways of calling out to a shell.
Incorrect:
import subprocess, sys
cmd = “head -n 100 %s” % sys.arv[1] // nothing prevents adding ; rm -rf / subprocess.check_output(cmd, shell=True)
import subprocess, sys subprocess.check_output([“head”, “-n”, “100”, sys.argv[1]])
Does not start shell. Calls head directly and safely passes arguments to the executable.
…Node.js
Code Injection
Most high-level languages have ways of executing code directly. E.g., Node.js web applications have access to the all powerful eval (and friends).
Incorrect:
var preTax = eval(req.body.preTax); var afterTax = eval(req.body.afterTax); var roth = eval(req.body.roth);
var preTax = parseInt(req.body.preTax); var afterTax = parseInt(req.body.afterTax); var roth = parseInt(req.body.roth);
(Almost) never need to use eval!
SQLInjection (SQLi)
Last example focused on shell injection
Injection oftentimes occurs when developers try to build SQL queries that use user-provided data
SQL basics
• Structured query language (SQL) • Example:
• SELECT * FROM books WHERE price > 100.00 ORDER BY title • Also, be aware:
• Logical expression with AND, OR, NOT
• Two dashes (–) indicates a comment (until end of line) • Semicolon (;) is a statement terminator
Insecure Login Checking
Sample PHP:
$login = $_POST[‘login’];
$sql = “SELECT id FROM users WHERE username = ‘$login'”; $rs = $db->executeQuery($sql);
if $rs.count > 0 {
// success
Insecure Login Checking Normal Input: ($_POST[“login”] = “alice”)
$login = $_POST[‘login’];
$sql = “SELECT id FROM users WHERE username = ‘$login'”;
$rs = $db->executeQuery($sql); if $rs.count > 0 {
// success
Insecure Login Checking Normal Input: ($_POST[“login”] = “alice”)
$login = $_POST[‘login’];
login = ‘alice’
$sql = “SELECT id FROM users WHERE username = ‘$login'”;
sql = “SELECT id FROM users WHERE username = ‘alice'”
$rs = $db->executeQuery($sql); if $rs.count > 0 {
// success
Insecure Login Checking
Adversarial Input: ($_POST[“login”] = “alice'”)
$sql = “SELECT id FROM users WHERE username = ‘$login'”;
$rs = $db->executeQuery($sql);
Insecure Login Checking
Adversarial Input: ($_POST[“login”] = “alice'”)
$sql = “SELECT id FROM users WHERE username = ‘$login'”;
SELECT id FROM users WHERE username = ‘alice” $rs = $db->executeQuery($sql);
Insecure Login Checking
Adversarial Input: ($_POST[“login”] = “alice'”)
$sql = “SELECT id FROM users WHERE username = ‘$login'”;
SELECT id FROM users WHERE username = ‘alice” $rs = $db->executeQuery($sql);
// error occurs (syntax error)
Building An Attack
Adversarial Input: “alice’–” — this is a comment in SQL
$sql = “SELECT id FROM users WHERE username = ‘$login'”;
$rs = $db->executeQuery($sql); if $rs.count > 0 {
// success
Building An Attack
Adversarial Input: “alice’–” — this is a comment in SQL
$sql = “SELECT id FROM users WHERE username = ‘$login'”;
SELECT id FROM users WHERE username = ‘alice’–‘ $rs = $db->executeQuery($sql);
if $rs.count > 0 {
// success
Building An Attack
Adversarial Input: “‘–” — this is a comment in SQL $login = $_POST[‘login’];
$sql = “SELECT id FROM users WHERE username = ‘$login'”;
$rs = $db->executeQuery($sql); if $rs.count > 0 {
// success
Building An Attack
Adversarial Input: “‘–” — this is a comment in SQL
$login = $_POST[‘login’];
login = ”–‘
$sql = “SELECT id FROM users WHERE username = ‘$login'”;
SELECT id FROM users WHERE username = ”–‘
$rs = $db->executeQuery($sql);
if $rs.count > 0 { <- fails because no users found
// success
Building An Attack
Adversarial Input: "' or 1=1 --" -- this is a comment in SQL
$login = $_POST[‘login'];
login = '' or 1=1 --'
$sql = "SELECT id FROM users WHERE username = '$login'";
SELECT id FROM users WHERE username = '' or 1=1 --' $rs = $db->executeQuery($sql);
if $rs.count > 0 {
// success
Building An Attack
Adversarial Input: “‘ or 1=1 –” — this is a comment in SQL
$login = $_POST[‘login’];
login = ” or 1=1 –‘
$sql = “SELECT id FROM users WHERE username = ‘$login'”;
SELECT id FROM users WHERE username = ” or 1=1 –‘
$rs = $db->executeQuery($sql);
if $rs.count > 0 { <- succeeds. Query finds *all* users
// success
Turning it into an attack
Adversarial Input: "'; drop table users --"
$sql = "SELECT id FROM users WHERE username = '$login'";
SELECT id FROM users WHERE username = ''; drop table users --' $rs = $db->executeQuery($sql);
Turning it into command injection
SQL server lets you run arbitrary system commands!
xp_cmdshell (Transact-SQL)
Spawns a Windows command shell and passes in a string for execution. Any output is returned as rows of text.
Turning it into command injection
Adversarial Input: “‘; exec xp_cmdshell ‘net user add bad455 badpwd’–” $sql = “SELECT id FROM users WHERE username = ‘$login'”;
SELECT id FROM users WHERE username = ”; exec xp_cmdshell ‘net user add bad455 badpwd’–‘
$rs = $db->executeQuery($sql);
Preventing SQL Injection
Never, ever, ever, build SQL commands yourself!
Parameterized/Prepared Statements
ORMs (Object Relational Mappers)
NoSQL databases are vulnerable to similar attacks (e.g., object injections)
Parameterized SQL:Separate Code and Data
Parameterized SQL allows you to pass in query separately from arguments
sql = “SELECT * FROM users WHERE email = ?” cursor.execute(sql,
sql = “INSERT INTO users(name, email) VALUES(?,?)” cursor.execute(sql, [‘ ‘,
Benefit: Server will automatically handle escaping data
Values are sent to server
separately from command.
Library doesn’t need to try to escape
Extra Benefit: parameterized queries are typically faster because server can cache the query plan
Object Relational Mappers (ORM) provide an interface between native objects and relational databases
class User(DBObject):
id = Column(Integer, primary_key=True) name = Column(String(255))
email = Column(String(255), unique=True)
users = name=‘ ’) session.commit()
Underlying driver turns OO code into prepared SQL queries.
Added bonus: can change underlying database without changing app code. From SQLite3, to MySQL, MicrosoftSQL, to No-SQL backends!
Injection Summary
• Injection attacks occur when un-sanitized user input ends up as code (shell command, argument to eval, or SQL statement).
• This remains a tremendous problem today
• Do not try to manually sanitize user input. You will not get it right.
• Simple, foolproof solution is to use safe interfaces (e.g., parameterized SQL)
Client-side injection or Cross Site Scripting (XSS)
Cross Site Scripting (XSS)
Cross Site Scripting: Attack occurs when application takes untrusted data and sends it to a web browser without proper validation or sanitization.
Command/SQL Injection
attacker’s malicious code is executed on victim’s server
Cross Site Scripting
attacker’s malicious code is executed on victim’s browser
Search Example
https://google.com/search?q=
Results for
Search Example
https://google.com/search?q=apple
Results for
Sent to Browser
Results for apple
Search Example
https://google.com/search?q=
Results for
Sent to Browser
Results for
Search Example
https://google.com/search?
q=
Sent to Browser
Results for