Server-Side Security¶
- Focus: Remote Attacker
- Target the server
- Goal: Compromise remote system
- Possibly malicious input to remote web server:
- Form fields (hidden + visible)
- GET/POST parameters
- Cookies
- HTTP Headers

SQL Injection¶
- SQL used for relational databases for
- Extraction (
SELECT) - Insertion (
INSERT INTO) - Updating (
UPDATE) - Deletion (
DELETE FROM)
- Extraction (
- Problem: Mixing of code + data
- SQL Queries are often generated on-the-fly with user input
- Attacks:
- End literal expression with
' - Comment rest of query
--/# - Comment range
/* ... */(two injection points required) - Leak data with
UNIONstatements- Respect union-compatibility
' UNION (SELECT 1 FROM ...)
- Add tautology:
a' OR 'a'='a/' OR 1#
- End literal expression with
- Column reference
- Name (e.g.,
id) - Index (e.g.,
1)
- Name (e.g.,
- Guess number of columns:
- Try
ORDER BY <columns>until no error occurs
- Try
- Try
UNION SELECT <columns>until no error occurs
- Try
- e.g.,
x' ORDER BY 1,2 --
- Schema Information
- MySQL/PostgreSQL
- Contained in table
information_schema.* .schemata: contains schemata (for MySQL: databases, for PostgreSQL: schemata).tables: accessible tables.columns: Accessible columns
- Contained in table
- SQLite
PRAGMA <cmd>statstable_info(<table>)
- MySQL/PostgreSQL
- Examples:
mysql_query("SELECT 1 FROM users WHRE name='".$_GET["name"]."' ...;");a' UNION SELECT table, column FROM information_schema.columns--
Drupageddon¶
- Real-world example (2014)
- Problem: Attack used Dict instead array (
['code' => 1]) and bypassed the automatic enumeration of the array - Vulnerable line:
foreach ($data as $i => $value)- Bypass with
$data = ['fakeKey' => 1]
- Better:
array_values($array): return array values
Blind SQL Injection¶
- Situation:
- Query does not return output but amount of rows matched or binary result (blind)
- e.g.,
OKandNOT OK
- Attack: Exfiltrate information from DB
- Functions:
MID(str, pos, len): Extract len characters from str starting at position posORD(str): ASCII code for first char in strLIKE:%for arbitrary amount of chars_single char
IF(condition, then, else):- Return then if condition is true, else otherwise
- e.g.,
SELECT IF(ORD(str) = 40, 1, 0) FROM ...
SLEEP(n): Sleepnseconds
- Approaches:
- Brute-forcing every single char: \( O(nm) \)
- Length \( n \)
- \( m \) possible characters
- Binary search:
- Char to ASCII value
- e.g.,
ORD(str) - Apply binary search \( O(n\log m) \)
- Reduce character set with
LIKE- e.g.,
password LIKE '%a%'
- e.g.,
- Timing-based:
- Exploit timing behavior (if database answer doesn’t change)
- e.g., use
IFwithsleep() - e.g.,
IF(cond, sleep(2), 0)
- Brute-forcing every single char: \( O(nm) \)
- Prevention:
- Main problem: Insecure usage of attacker-controlled data
- Prepared statements
- Separated code/data
- Increased performance (query-planner already optimized)
$prepared = $mysqli->prepare("INSERT INTO test(id) VALUES (?)");$prepared->bind("i", $i)("i"means integer)$prepared->execute()
- Sanitization/escaping
- Caution: Error-prone
- Escaping function:
mysqli_real_escape_string()
- Database permissions (protection)
- Example:
bob' AND password LIKE 'a%' #bob' AND (SELECT IF(MID(password, 1, 1) = 'a', SLEEP(1), 0) FROM users WHERE user='bob')#
NoSQL Injection¶
- Not Only SQL
- Database types:
- Document-based (MongoDB, CouchDB)
- Key-value (Redis, BerkeleyDB)
- Graph database (Neo4J)
- Mostly custom query format
- e.g.,
db.employees.find({lastname: "Stick"}) - e.g., Negation:
db.employees.find({name: {$ne: "Stick}}) - e.g., Regex:
db.employees.find({name: /tic/}) - e.g., Greater:
db.employees.find({age: {$gt: 30}})
- e.g.,
- Note: Parsing GET parameters in PHP:
- PHP takes last definition (e.g., GET)
?foo[]=bla&foo[]=barenforces arrayfoo = [bar, bla]
- Attack: Inject conditions
- Using the parsing behavior of PHP for HTTP parameters
- e.g.,
?user=bob&password[$regex]=.
- Defense:
- Type enforcement (e.g., for a string)
- PHP:
(string) $_GET['name'] - Python
str(request.GET['name'])
- PHP:
- Type enforcement (e.g., for a string)

Code Execution Flaws¶
Command Injection¶
- Scenario: App executes OS command directly with user input
- Known problem: Data and code not separated
- Example:
os.system("htpasswd -b .htpasswd %s %s" % (username, password))
- Attack: Inject malicious parameters into bash
cmd1; cmd2: Execute cmd1 and cmd2cmd1 && cmd2: Execute cmd2 if cmd1 workedcmd1 | cmd2: Pipe result of cmd1 into cmd2cmd1 $(cmd2): cmd2 result to cmd1
- Problem: Command and arguments are not separated
- Solutions:
- Separation of command and argument
- Python:
subprocess.call([...])
- Python:
- Escape shell arguments:
- PHP:
escapeshellarg(string $arg)
- PHP:
- Separation of command and argument
Path Traversal¶
- Scenario:
- PHP script reads from storage with user input or copies a certain file
- e.g.,
return read("downloads/" . $_GET['fn']); - e.g.,
move_uploaded_file(...)
- Use
../to move on file system - Attack:
- Leak information (
/etc/passwd,.htpasswd) - Overwrite information (e.g., PHP file)
- Leak information (
- Preventions:
- Sanitize path/input (focus on
.and/) - Access rights
- Sanitize path/input (focus on

File Inclusion¶
- PHP Parsing:
- PHP is HTML preprocessor
- Execute code between
<?php ... ?> - Include-statements:
include: Include, warning if not foundrequire: Include, die if not found
- Scenario:
- Application code is split across multiple files
includecall uses user input- e.g.,
include($_GET['page'])
- Attack:
- Include other files on server
- Denial of service: Include loop (
include(index.php))
- Denial of service: Include loop (
- Code Injection: Include remote files (disabled by default)
- Include other files on server
- Prevention:
- Use allow-list with allowed files
- Sanitize path (e.g.,
basename()resolves traversals) - Restrict directories with
open_basedir(all files outside this directory are inaccessible) - Use mapping from site ID to include file
Unrestricted File Upload¶
- Scenario: App allows file upload
- Attack: Upload file for remote code execution
- Types:
- Upload HTML to be display with JavaScript (XSS by upload)
- SVG images can contain JavaScript
- PHP file being executed
- Flash files
.htaccess: Overwrite webserver configuration (AddTypeadds executable to server)
- Real-life attack: GIFAR
- Combination of GIF and JAR
- GIF type information at beginning (bypass content sniff)
- JAR information at the end (ignores first bytes)
- Upload GIFAR to server and send link to uploaded file to user
- Prevention:
- Type checking/Content sniffing (explicit or implicit)
- Images: Remove non-image content/clear meta data (using libraries)
- Separate domain for upload
Deserialization Issues¶
- Scenario:
- Non-string data often exchanged between entities by using Serialization
- e.g., pickle, serialize
- Property Oriented Programming (POP) attack
- Idea: Chain together properties of different objects
- Attacker controls properties of de-serialized object
- Attacker chains together different magic functions
- Serialization in Python
pickle.loads()/pickle.dumps()loads()calls__reduce__- Attack example:
- Server calls
pickle.loads()on Cookie value - Use pickled object with malicious
__reduce__function as Cookie value - Attacker sends malicious Cookie to server
- e.g.
class Foo: def __reduce__(self): subprocess.call()
- Server calls
- Countermeasures
- Avoid serialization of complete objects
- Serialize using JSON
- Sign Cookies sent by the server (attack can not inject malicious code)
- Real-world attack: vBulletin 5.x
- Attacker could pass code into
eval()
- Attacker could pass code into
Template Injection¶
- Template Systems:
- Idea: Separate logic (controller) and rendering (view)
- MVC architecture
- PHP: Twig, Smarty
- Python: Django/Jinja2
- Attack:
- Template is combined with parameters, then rendered
- Execute code on server side
- Read/modify environment variables
- Example:
$twig->render("Hello {first_name}", array('first_name' => ...));first_name = lambda x: ...
- Prevention:
- Prohibit user-provided input in generation of templates
XML (In)security¶
XML¶
- Well-structured markup language
- Consists of elements
- Elements may have attributes
- Validity by Document Type Definition (DTD)
- DTD defines valid elements
<!ELEMENT img EMPTY><!ATTLIST img src %URI; #REQUIRED>
- Specifies elements
- Defines custom entities
- Entity: Mapping from element to value
- Example:
<!ENTITY age "Alter">- Usage:
%age;: 32->Alter: 32
- DTD defines valid elements
- Document Type (
<!DOCTYPE ...>)- Defined by DTD
- Refers to DTD (can be external file)
- e.g.,
<!DOCTYPE Name [ <!ELEMENT Name (#CDATA)> ]> SYSTEMfor external entities- Even within the entity definition
<!DOCTYPE Name SYSTEM "http://.../name.dtd"><!ENTITY passwd SYSTEM "file:///etc/passwd">
Attacks¶
- Abusing XML External Entities (XXE)
- Goal: Information disclosure (Confidentiality)
- Attacker must control XML file (e.g., for login protocol)
- Attacker includes sensitive files in
SYSTEM <!ENTITY xxe SYSTEM "file:///etc/passwd">
- Denial of Service (Availability)
- Define entities recursively
- XML Billion Laughs
- XPath Injection
- Scenario: Database is stored in XML
- XPath Injection (attacker could inject XPath query)
- Problem: Mixing code and data

Countermeasures¶
- Entity attacks:
- Disable entity loader (
libxmlin PHP) - Python:
etree, xmlrpc, minidom, defusedxmlare safe
- Disable entity loader (
- Injection attacks:
- Whitelisting of characters
- Use programmatic checks
HTTP Parameter Pollution¶
- HTTP Parameters
- Series of
name=value - Separator:
& - Escaping (percent-encoding):
& = ; / ? : # @ + $ ,- Hex-value of ASCII value
- e.g.,
?attr=123&foo=bar
- Series of
- Attack: Multiple parameters with same same
- Problem:
- Web server + application differ in interpretation of parameters
- e.g., Result of
?a=1&a=2?- Keep first:
a=1? - Keep last:
a=2? - Array:
a=[1, 2]? - Concatenation:
a=12?
- Keep first:
- Attacks
- Problem: Multiple instances interpret the data
- SQL Injection
- XSS
?page=SELECT 1,&page=2,3
- Real-world example: blogger.com
- Attacker added herself in the author’s list
- Author was checked on first parameter
- Target block was checked on second parameter
- Countermeasure
- Python: Double-check types of parameters (e.g., string vs. list)
- General: Ensure proper encoding
HTTP Header Injection¶
- Attacker inserts headers into HTTP response
- Problem:
- Headers are concatenated with user input
- e.g., modify Cookies
- Insert new headers by line break
- Insert malicious content with line breaks
- e.g.,
\nLocation: attacker.com\nFoo: bar
- HTTP Response Splitting:
- Inject attacker-controlled response into the actual response (which is cut off)
- e.g.,
\n\n<html><script>attack()</script></html>
- Countermeasure:
- Ensure: No new line character allowed
- PHP: Only one header per function call
Server-Side Request Forgery (SSRF)¶
- Use Case:
- Preview of resources ensuring privacy for the client
- e.g., Twitter shows preview of images, does not deliver original URL to user
- Three parties:
- Client (C)
- Middle server (S)
- External server (ES)
- Middle server (e.g., firewall, proxy) sends request to external server (target)
- Problems:
- Attack external server anonymously (attacker’s identity is not revealed)
- Access private resources behind a firewall (on the middle server)
- Deliver malicious content from the external server to client with the origin of the middle server
- Possible attacks:
- Server-side Request Forgery:
- Client wants to attack the external server which is behind a firewall
- e.g.,
http://10.0.1.1:1234/... - Problem: URL parsing is not consistent
- DNS Rebinding
- Client attacks external server
- Request (with IP) must be executed twice
- First time: Check if hostname is allowed
- Second time: Rebind DNS to target resource
- Time-to-check-to-time-of-use attack
- Web Origin Laundering (WOL)
- Middle server is acting as proxy
- Malicious content is sent from attacker server to client with the origin of the middle server
- May bypass the CSP (if host names are used)
- Server-side Request Forgery:
- Countermeasure:
- Whitelist server
- By the same component as taking the request
- Due to different parsing rules
Content-Disposition: attachment, do not display file inline (mitigate WOL)- DNS pinning (against DNS rebinding)
- Whitelist server

Execution after Redirect¶
- Problem: Bad programming
- Check permissions using PHP
- If no permissions exist, set redirect header
- Problem: Redirect only at end of script and not immediate (actions can be executed after setting the header)
- Finish script using
die()
