0% found this document useful (0 votes)
9 views

14 Applied Secure Coding Principles

Uploaded by

es169371
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views

14 Applied Secure Coding Principles

Uploaded by

es169371
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 34

PRACTICAL WEB DEFENSE COURSE MODULE

14

APPLIED SECURE
CODING
PRINCIPLES
PRACTICAL WEB DEFENSE COURSE

Applied Secure Coding Principles


Author • Abraham Aranguren
Technical Editor • Giuseppe Trotta
Document version • 1.0
Last update • Friday, November 15, 2013

eLearnSecurity 2013 ©

All rights reserved. No part of this document may be reproduced in any form or by any electronic or
mechanical means, including information storage and retrieval systems, without written permission
from the publisher, except in the case of a reviewer, who may quote brief passages embodied in
critical articles or in a review.

eLearnSecurity s.r.l.
36,38 Via Matteucci
Pisa, ITALY 56124
P W D / P R A C T I C A L W E B D E F E N S E

1. TABLE OF CONTENTS
INTRODUCTION 1
1. REDUCE THE ATTACK SURFACE 2
1.1 PRINCIPLE DESCRIPTION 2
1.2 PRACTICAL EXAMPLES 2
1.3 FURTHER READING 4
2. STRICT INPUT VALIDATION 5
2.1 PRINCIPLE DESCRIPTION 5
2.2 PRACTICAL EXAMPLES 5
2.3 FURTHER READING 7
3. AGGRESSIVELY DIFFERENTIATE INPUT FROM CODE 8
3.1 PRINCIPLE DESCRIPTION 8
3.2 PRACTICAL EXAMPLES 9
3.3 FURTHER READING 11
4. SECURE ACCESS TO DATA AND FUNCTION 12
4.1 PRINCIPLE DESCRIPTION 12
4.2 PRACTICAL EXAMPLES 12
4.3 FURTHER READING 13
5. SECURE COMMUNICATIONS AND STORAGE 14
5.1 PRINCIPLE DESCRIPTION 14
5.2 SECURE COMMUNICATION EXAMPLES 14
5.3 SECURE STORAGE EXAMPLES 15
5.4 FURTHER READING 16
6. LEAST PRIVILEGE 17
6.1 PRINCIPLE DESCRIPTION 17
6.2 WEB SERVER EXAMPLES 17
6.3 DATABASE EXAMPLES 19
6.4 FURTHER READING 20
7. DEFENSE IN DEPTH 21
7.1 PRINCIPLE DESCRIPTION 21
7.2 DOM XSS PREVENTION IN HTML5 POSTMESSAGE EXAMPLE 21
7.3 REFLECTED XSS PREVENTION EXAMPLE 23
7.4 FURTHER READING 24
8. SECURE DEFAULTS 25
8.1 PRINCIPLE DESCRIPTION 25
8.2 PRACTICAL EXAMPLES 25
8.3 FURTHER READING 26
9. MAKE SECURITY SIMPLE AND OBVIOUS 27
9.1 PRINCIPLE DESCRIPTION 27
9.2 DATA LABELING EXAMPLE 27
9.3 STOPPING EXECUTION AS SOON AS A SECURITY CHECK FAILS EXAMPLE 28
P W D / P R A C T I C A L W E B D E F E N S E

9.4 CENTRALIZED SECURITY CONTROL EXAMPLE 29


9.5 FURTHER READING 30
P W D / P R A C T I C A L W E B D E F E N S E
INTRODUCTION

I
INTRODUCTION
This module focuses on general strategies to produce secure code.
As we saw in the tactical chapters, defending against every possible attack is non-trivial. In
addition to this, new attacks are being published every year and it is unreasonable to
expect developers to know and defend against every “cutting-edge attack that was
published last week”. Because of this, this module, although strategic, will illustrate the
general and widely accepted principles to produce secure code against known and future
(not-yet-known) attacks.
The principles in this chapter aim to produce web applications that enforce the core pillars
of information security:
• Confidentiality: Sensitive information should not be available unless permissions
grant it
• Integrity: The application should protect data from unauthorized modifications
• Availability: The application should be available to legitimate users at all times

APPLIED SECURE CODING PRINCIPLES - Introduction 1


P W D / P R A C T I C A L W E B D E F E N S E
CHAPTER

1
1. REDUCE THE ATTACK SURFACE

1.1 Principle description


The attack surface reduction principle is comprised of two objectives:
1. Reduce application functionality to the absolute minimum that the customer is
willing to accept
2. Reduce data entry points to the absolute minimum the application will need to
work correctly.
This principle is based on the fact that the security of any system is inversely proportional
to the amount of functionality: The more functionality and entry points the more attack
opportunities and the more risk.
For example: A website running only static HTML files without a database, without
JavaScript, without Flash, without Silverlight, and hosted on the latest Apache version
would automatically eliminate a great number of security problems (i.e. all data validation
vulnerabilities, most client side attacks, etc.).

1.2 Practical examples


The following practical examples illustrate some real world scenarios to apply this
principle:
• Use a front-controller to reduce the number of files directly reachable: If you
have an application with over 10,000 PHP files reachable through the URL you
may seriously reduce the attack surface by moving them away from the webroot
and address them using a front controller. For example:
http://example.com/dispatcher.php?page=2

APPLIED SECURE CODING PRINCIPLES - REDUCE THE ATTACK SURFACE 2


P W D / P R A C T I C A L W E B D E F E N S E

Then the dispatcher source code has a map of “Page ID Page info”:

$pageMap = array(1 => array("path" => "path/to/file", …),


…);//white-list of allowed pages
$page = (string) $_GET['page'];//Avoid fun array tricks in PHP via
“page[]=”
if (!isset($page) || !isset($pageMap[$page])) {
die('Invalid page'); //Abort processing
}
$file_path = " ../
app_code/"; //Location of 10,000 PHP files
(outside of webroot)
require $file_path . $pageMap[$page]['path'];//Execute the file

Now we have:
1. Reduced the attack surface of the application from 10,000 PHP files
directly reachable (really difficult to secure) to just 1 (making access control
much easier to implement)
2. Removed path traversals as an attack vector in the front-controller: The
user must supply a valid id, not the file path. The request is rejected if the
file id is not defined.
3. A dispatcher using known, defined paths (in $pageMap), instead of user
input.

• Always favor server-side sources of input over client-side ones: Having things
like “User role id” in the user session (i.e. $_SESSION in PHP) or a database
instead of a parameter is a smart way to prevent tampering (i.e. as opposed to
storing this information in GET, POST or cookie parameters). The attack surface
is removed by not exposing such parameters in the client-side.
• Avoid storing information on the client: Anything on the client side (even if
encrypted) can be an attack vector. For example, store tokens in cookies (i.e. so
that you lookup the token in your database instead of decrypting a cookie): Now
the attacker can only tamper the token but not the data. Cryptographic and reverse
engineering attacks become impossible because there is nothing to reverse or
decrypt. This approach would have prevented the padding oracle vulnerability
PayPal had via encrypted cookies1.
• Avoid long session durations: If users are automatically logged out after 5-10
minutes of inactivity, using some client-side JavaScript to go to the login page too,
the attack window to ride on a user session will be significantly reduced over a 1
month-valid session.

1
http://seclists.org/fulldisclosure/2013/Aug/278

APPLIED SECURE CODING PRINCIPLES - REDUCE THE ATTACK SURFACE 3


P W D / P R A C T I C A L W E B D E F E N S E

• Avoid wildcard domain cookies: If you have 50 sub-domains like test.a.com,


dev.a.com, etc. and a session cookie is set using a wildcard for all sub-domains like
below the attack surface is great:

Set-Cookie: JSESSID=alsjdKilfiejlvmskd; path=/; Domain=.a.com

Now the attacker only needs a vulnerability on a single domain to steal 1 cookie
that works on 50 domains. Instead of this, each domain should have its own
cookie and session handling.
• Avoid wildcard CORS: A CORS server configured as follows is unnecessarily
allowing any domain on the internet to read responses and send valid
authentication cookies:

header('Access-Control-Allow-Origin: ' + $_SERVER['HTTP_ORIGIN']);


header('Access-Control-Allow-Credentials: true');

If you really need CORS, then reduce the attack surface to only the domains you
trust.
• If the database server is on the same host as the web server, don’t expose
the port to the internet: If MySQL is listening on the web server on port 3306
this should only be accessible to the web application and not the whole planet. If
port 3306 must be remotely accessible, then MySQL can be configured to only
allow connections from the company/administrator IP address. Reducing the
attack surface from “allowing connections from any computer in the planet” to
“allow connections from this company IP address” is a great improvement.
• Require authentication: Valid users vs. anybody on the internet is a reduction in
attack surface.
• Reduce the number of screens, parameters, features: Less screens, parameters
and/or features will generally imply less complexity, less attack surface and more
security.

1.3 Further Reading


The following resources may provide additional information about this principle:
• OWASP Attack Surface Analysis Cheat Sheet
https://www.owasp.org/index.php/Attack_Surface_Analysis_Cheat_Sheet
• OWASP Development Guide: Secure Coding Principles
https://www.owasp.org/index.php/Secure_Coding_Principles

APPLIED SECURE CODING PRINCIPLES - REDUCE THE ATTACK SURFACE 4


P W D / P R A C T I C A L W E B D E F E N S E
CHAPTER

2
2. STRICT INPUT VALIDATION

2.1 Principle description


User input should be always validated strictly and in the following order of
preference:
1) Validate against a white-list of allowed values and reject anything else: Best
2) Validate against a white-list of allowed characters and reject anything else: Second
best
3) Use blacklists ONLY as a last resort when 1-2 are really not possible: Worst
4) Validate length regardless of approach selected in 1-3: Complementary control
The reasoning of this principle is that restricting the available characters and length will in
many cases be enough to render many attacks useless despite the underlying code being
vulnerable.

2.2 Practical examples


The following are some practical examples for these general guidelines:
1) Validate against a white-list of allowed values and reject anything else: Best
Validating against a white-list of allowed values is the absolute best method to avoid all
surprises

if (!in_array($user_input, $array_of_allowed_values)) {//Validation


against a white-list of values
die('Invalid input …');
}

APPLIED SECURE CODING PRINCIPLES - STRICT INPUT VALIDATION 5


P W D / P R A C T I C A L W E B D E F E N S E

The following example uses the white-list as a lookup for the value to use, in order to
avoid using user input. This example validates the user provided page ($_GET['page'])
against a known white-list of allowed pages and rejects anything else. Please note how
$_GET['page'] is meant to be the ‘id’ instead of the ‘path’:

$pageMap = array(1 => array("path" => "path/to/file", …),


…);//white-list of allowed pages
$_GET['page'] = (string) $_GET['page'];//Avoid fun array tricks in
PHP via “page[]=”
if (!isset($_GET['page']) || !isset($pageMap[$_GET['page']])) {
die('Invalid page'); //Abort processing
}

2) Validate against a white-list of allowed characters and reject anything else: Second
best
When validating against a white-list of allowed values is not possible, the next best is to
validate against a white-list of allowed characters. This is typically best accomplished using
a regular expression but because of ReDoS2 attack vectors:
• The length should always be checked before the regular expression
• Repetition patterns such as “()+” should be avoided in the regular
expression (if possible)

$input = (string) $_GET['input'];


if (strlen($input) > 20|| !preg_match('/^[a-z]+$/i', $input))
{//Something other than letters was provided!
die('Invalid input …');//Abort processing
}

3) Use blacklists ONLY as a last resort when 1-2 are really not possible: Worst
Blacklists should only be considered when white-list approaches are absolutely not
possible (which is very rare). Blacklists are a very weak form of validation that only
rejects “known bad” and therefore validation will be more likely to become vulnerable as
new attack vectors are published.
This, being said, blacklists can be a great way to complement white-lists as an additional
security control:

$input = (string) $_GET['input'];


if (strlen($input) > 20|| !preg_match('/^[a-z]+$/i', $input))
{//Something other than letters was provided!
die('Invalid input …');//Abort processing
}
//Applying blacklist after white-list:
$clean_input = $input;//Initialize $clean_input to input, before
applying blacklist

2 https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS

APPLIED SECURE CODING PRINCIPLES - STRICT INPUT VALIDATION 6


P W D / P R A C T I C A L W E B D E F E N S E

foreach ($forbidden_character_array as $blacklisted_character)


{//Delete all blacklisted characters
$clean_input = str_replace($blacklisted_character, '',
$clean_input);
}

2.3 Further Reading


The following resources may provide additional information about this principle:
• OWASP Input Validation Cheat Sheet
https://www.owasp.org/index.php/Input_Validation_Cheat_Sheet
• OWASP Code Review Guide: Input Validation
https://www.owasp.org/index.php/Codereview-Input_Validation
• OWASP Development Guide: Data Validation
https://www.owasp.org/index.php/Data_Validation
• OWASP Development Guide: Canonicalization, locale and Unicode
https://www.owasp.org/index.php/Canonicalization,_locale_and_Unicod
e
• OWASP Development Guide: Secure Coding Principles
https://www.owasp.org/index.php/Secure_Coding_Principles

APPLIED SECURE CODING PRINCIPLES - STRICT INPUT VALIDATION 7


P W D / P R A C T I C A L W E B D E F E N S E
CHAPTER

3
3. AGGRESSIVELY
DIFFERENTIATE INPUT FROM
CODE

3.1 Principle description


User input should be differentiated from application instructions using the most
aggressive means available in the following order of preference:
1) Use parameterized queries: Best
2) Escape and surround user input in quotes: Second Best
3) Apply a blacklist as a last resort when 1-2 are not possible: Worst
The reasoning behind this principle is that all injection attacks occur when user input
and application instructions are “confused” via string concatenation:

$code = "SELECT … $user_input …";//Now $code cannot differentiate


user input from instructions

Please note that injection attacks include XSS, SQLi, LDAP, SMTP, XML, Shell
commands, code, etc.

APPLIED SECURE CODING PRINCIPLES - AGGRESSIVELY DIFFERENTIATE INPUT FROM CODE 8


P W D / P R A C T I C A L W E B D E F E N S E

3.2 Practical examples


The following are some practical examples for these general guidelines:
1) Use parameterized queries: Best
The most aggressive form of differentiation between user input and instructions is to use
parameterized queries. For example, pass user input to SQL queries via bind variables:

$sql = "INSERT INTO test_table VALUES (?, ?, ?, ?)"; //No user-input


in the SQL query string
$sql_statement = $mysqli->prepare($sql);
$sql_statement->bind_param('dsss', $user_id, $name, $address,
$email);//Tell the library which variable goes to which part of the
query
$user_id = $_POST['user_id'];
$name = $_POST['name'];
$address = $_POST['address'];
$email = $_POST['email'];
$sql_statement->execute(); //Executes the query in the database

Another example where parameterized queries are possible is XPath: Using XQuery, it is
possible to bind variables to XPath queries3. In addition to this, in .NET it is possible to
compile XPath queries4.
2) Escape and surround user input in quotes: Second Best
Sometimes parameterized queries are not an option, particularly when rendering user input
in a page where the HTML are the “instructions” and user input needs to be displayed
within the HTML. In such cases, the most aggressive form of escaping/encoding
should be used. For example:

echo "<html>
<head><meta charset="UTF-8"></head>
<span class=\"" . htmlentities($_GET['xss'], ENT_QUOTES, "UTF-8") .
"\">test</span>
</html>";

Some platform functions, such as escapeshellarg in PHP will automatically add


surrounding quotes to the value:

//NOTE: Do not forget to surround the value in quotes for escaping


to be more effective
system('ping ' . escapeshellarg($_POST['ip'])); //PHP:
“escapeshellarg” will add quotes to the value

3 http://www.slideshare.net/kverbert/xml-parta
4 http://msdn.microsoft.com/en-us/library/093b7219.aspx

APPLIED SECURE CODING PRINCIPLES - AGGRESSIVELY DIFFERENTIATE INPUT FROM CODE 9


P W D / P R A C T I C A L W E B D E F E N S E

Sometimes quoting the value will not be possible, like <div>$here</div>, however,
surrounding the value in quotes is very important to make escaping work and
should always be done where possible.
3) Apply a blacklist as a last resort when 1-2 are not possible: Worst
Blacklists are a very weak security control. This should only be done when
parameterization and escaping are absolutely not possible and only after white-list
validation.
A blacklist will be most effective after performing the relevant research to identify
absolutely all available control characters for the language/protocol at hand and/or using a
trusted platform/library to do this for you: Escaping a shell command has nothing to do
with escaping an STMP command or input within an XML tag. Blacklist sanitization
must be relevant to the language/protocol at hand.
For example, escaping and parameterization are typically not possible are email libraries:

$to = (string) $_POST['to']; //Explicit cast to string: No funny []


array tricks
//Step 1) white-list input validation
if (strlen($to) > 254 || !preg_match('|^[A-Z0-9._-]+@[A-Z0-9.-
]+\.[A-Z]{2,4}$|', $to)) {
die('Invalid To field, please try again'); //Abort processing
}
//Step 2) black-list sanitization
//Now apply black list: Remove "\r", "\n", "\r\n", ", ', #, | and \
$to = str_replace(array("\r", "\n", "\r\n", '"', "'", "#", "|" and
"\"), "", $to);

APPLIED SECURE CODING PRINCIPLES - AGGRESSIVELY DIFFERENTIATE INPUT FROM CODE 10


P W D / P R A C T I C A L W E B D E F E N S E

3.3 Further Reading


The following resources may provide additional information about this principle:
• OWASP Query Parameterization Cheat Sheet
https://www.owasp.org/index.php/Query_Parameterization_Cheat_Sheet
• OWASP SQL Injection Prevention Cheat Sheet
https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sh
eet
• OWASP XSS (Cross Site Scripting) Prevention Cheat Sheet
https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Preventio
n_Cheat_Sheet
• OWASP DOM based XSS Prevention Cheat Sheet
https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_
Sheet
• OWASP Development Guide: Interpreter Injection
https://www.owasp.org/index.php/Interpreter_Injection
• OWASP Development Guide: Secure Coding Principles
https://www.owasp.org/index.php/Secure_Coding_Principles

APPLIED SECURE CODING PRINCIPLES - AGGRESSIVELY DIFFERENTIATE INPUT FROM CODE 11


P W D / P R A C T I C A L W E B D E F E N S E
CHAPTER

4
4. SECURE ACCESS TO DATA AND
FUNCTION

4.1 Principle description


Before allowing access to application data or functionality the following should
always be checked:
1) Does access to this function/data require authentication? (i.e. logged in user)
2) Does access to this function/data require authorization? (i.e. can user X do/read
Y?)
Implementing Authentication and Authorization correctly in web applications is very
important especially when the application deals with sensitive information.

4.2 Practical examples


The following are some practical examples for these general guidelines:
1) Does access to this function/data require authentication? (i.e. logged in user)
2) Does access to this function/data require authorization? (i.e. can user X do/read
Y?)
Authentication and authorization checks should heavily rely on server-side
platform sources of information such as $_SESSION (in PHP) or a database. This
reduces the attack surface of the application.

APPLIED SECURE CODING PRINCIPLES - SECURE ACCESS TO DATA AND FUNCTION 12


P W D / P R A C T I C A L W E B D E F E N S E

Checking a user is logged in, and belonging to an administrator role before creating a new
user:

session_start();

if (!isset($_SESSION['logged_in']) ||
!isset($_SESSION['user_group'])
|| !$_SESSION['logged_in'] || $_SESSION['user_group'] !==
ADMIN_GROUP) {
die('You are not authorized to do this …'); Abort processing
}
else {//Permission check successful: User is logged in and an
administrator
if (validate_input(…)) {
create_new_user(…);
}
}

Checking a user is allowed to access a given record in the database (i.e. the record belongs
to the user department):

$record = retrieve_from_db($input);
if ($record->department !== $_SESSION['department']) {
die('You are not allowed to view this record…'); //Abort
processing
}

IMPORTANT: Development teams should use platform constructs or vetted libraries to


handle sensitive but difficult to get right functionality such as session handling.

4.3 Further Reading


The following resources may provide additional information about this principle:
• OWASP Authentication Cheat Sheet
https://www.owasp.org/index.php/Authentication_Cheat_Sheet
• OWASP Access Control Cheat Sheet
https://www.owasp.org/index.php/Access_Control_Cheat_Sheet
• OWASP Development Guide: Guide to Authentication
https://www.owasp.org/index.php/Guide_to_Authentication
• OWASP Development Guide: Guide to Authorization
https://www.owasp.org/index.php/Guide_to_Authorization
• OWASP Development Guide: Secure Coding Principles
https://www.owasp.org/index.php/Secure_Coding_Principles

APPLIED SECURE CODING PRINCIPLES - SECURE ACCESS TO DATA AND FUNCTION 13


P W D / P R A C T I C A L W E B D E F E N S E
CHAPTER

5
5. SECURE COMMUNICATIONS
AND STORAGE

5.1 Principle description


User data, including credentials, sessions, cookies, etc. should be protected both at
rest and in transit.

5.2 Secure communication examples


A simple and very effective way to protect communications is to: Avoid mixed protocol
usage (i.e. having both SSL and non-SSL content on a website), use SSL for all content,
setup HSTS5, and setup the secure and httpOnly flags on cookies:
1) Create a permanent redirect from HTTP to HTTPS:
On most websites this will be a redirect from port 80 to port 443. In Apache this
can be accomplished as follows:

<VirtualHost *:80>
ServerAlias *
RewriteEngine On
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [redirect=301]
</VirtualHost>

5 https://www.owasp.org/index.php/HTTP_Strict_Transport_Security

APPLIED SECURE CODING PRINCIPLES - SECURE COMMUNICATIONS AND STORAGE 14


P W D / P R A C T I C A L W E B D E F E N S E

2) Set the HSTS header on the HTTPS website configuration:


If using Apache, this can be accomplished as follows:

Header add Strict-Transport-Security "max-age= 31536000;


includeSubDomains"

The “; includeSubDomains” section can be removed if no HSTS enforcement is


desired on the website sub-domains.
3) Setup Cookie protections, especially on session cookies (and limit the domain and
max-age):

Set-Cookie: SESSIONID=k5z6hc2Ebq9B6Xmy; path=/;


Domain=www.company.com; max-age=300; HttpOnly; secure

If you are using PHP you have the following options:


o Setup the “httponly” and “secure” flags in the php.ini file

session.cookie_secure = On
session.cookie_httponly = On

o Setup the “httponly” and “secure” flags before “session_start()” in the code

$secure = $httponly = true; //Set these flags to true


session_set_cookie_params ($lifetime, $path, $domain, $secure,
$httponly);
session_start(); //Now start the session

5.3 Secure storage examples


Storing sensitive information inadequately may result in violation of privacy rights,
prosecution, fines and/or failure to meet minimum compliance requirements. The easiest
way to avoid this problem is simply to not store sensitive information where possible. For
situations where sensitive information must be used, then appropriate use of strong
cryptographic algorithms is highly encouraged.
For example:
• Store password hashes using an algorithm designed for it such as pbkdf26.
• Store sensitive information using encryption (i.e. AES), and store the long and
random key in another server (i.e. so that if the attacker gains access to the data
they do not have the key to decrypt it).

6 http://www.ietf.org/rfc/rfc2898.txt

APPLIED SECURE CODING PRINCIPLES - SECURE COMMUNICATIONS AND STORAGE 15


P W D / P R A C T I C A L W E B D E F E N S E

A typical way to do this is to store the encryption key in the application server,
while the encrypted data is in the database server.
NOTE: If your database and application are on the same server, then at least have
the encryption key in the server and not the database. But ideally, applications and
databases should be on different servers, where possible.
In addition to this, it is important to note that some industries require the use of certain
approved cryptographic algorithms, for example: FIPS 140-27.

5.4 Further Reading


The following resources may provide additional information about this principle:
• OWASP Transport Layer Protection Cheat Sheet
https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_S
heet
• OWASP Top 10 for JavaScript - A9: Insufficient Transport Layer Protection
http://erlend.oftedal.no/blog/?blogid=135
• OWASP Top 10 for .NET developers part 9: Insufficient Transport Layer
Protection
http://www.troyhunt.com/2011/11/owasp-top-10-for-net-developers-part-
9.html
• OWASP Top 10 and ESAPI (Java developers): Insecure Communications
http://www.jtmelton.com/2010/08/04/the-owasp-top-ten-and-esapi-part-
10-insecure-communications/
• OWASP Development Guide: Secure Coding Principles
https://www.owasp.org/index.php/Secure_Coding_Principles

7 http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf

APPLIED SECURE CODING PRINCIPLES - SECURE COMMUNICATIONS AND STORAGE 16


P W D / P R A C T I C A L W E B D E F E N S E
CHAPTER

6
6. LEAST PRIVILEGE

6.1 Principle description


When permissions must be granted they should involve the least possible
privileges for the application to work. Although this applies to all user accounts in
general, this typically affects the following user accounts the most:
• Web server user: The privileges of the user account used by the web server should
be as restrictive as possible.
• Database user: The privileges of the database user account used by the web
application should be as restrictive as possible.

6.2 Web server examples


Whenever possible, the web server user should:
• NOT be able to read/write files from/to anywhere on the filesystem except
where it is strictly needed
• NEVER run as root!
That is the opposite of least privilege.
• NOT be able to write files in the webroot directory (i.e. /var/www)
For example, in Windows, Deny permissions take precedence over Allow, so
assuming the web server runs as “IUSR” a Deny Write permission on the webroot
directory (and all subdirectories) is highly recommended unless the application
requires a different permission setup. To do this, simply right click on the webroot
directory (i.e. www in this example), then click on “Properties”, the “Security” tab,
then “Edit”, then “IUSR” (the user the web server runs as) and then put an
explicit “Deny Write” permission like in the screenshot below:

APPLIED SECURE CODING PRINCIPLES - LEAST PRIVILEGE 17


P W D / P R A C T I C A L W E B D E F E N S E

FIGURE 1 Setting up “Deny Write” permissions on the webroot directory in Windows

In Linux the following is a one liner that will prevent the webserver user (assuming
it is not root, which should not be) from writing files (this should be ok for most
applications). This assumes the webroot directory is /var/www:

sudo chown -R root /var/www


sudo chmod -R 755 /var/www

• NOT be able to run shell commands


For example, if “www” is the user the web server is running as, deny shell access
like this:

sudo usermod -s /bin/false www

APPLIED SECURE CODING PRINCIPLES - LEAST PRIVILEGE 18


P W D / P R A C T I C A L W E B D E F E N S E

6.3 Database examples


Similarly to the web user account, the user account under which the database process
runs should have the most restrictive permissions possible (i.e. not be able to run
commands, write files, etc).
In addition to that, the user account the web application uses to connect to the database,
should:
• Have the most restrictive read/write/etc. permissions possible for the
application to work
• NEVER be a privileged account such as root/sa/sysdba/etc.
• NOT be able to run shell, perl, PHP, etc. commands
For example:
o xp_cmdshell8 in SQL Server
o myperl9 in MySQL
• NOT be able to modify the registry
For example:
o xp_regread10 in SQL Server
• NOT be able to access any more tables than it needs
For example, if a third party application needs read access to one table in the
database, then a custom database user should be created for such purpose and this
database user should absolutely only be able to access the required table and
nothing else. Similarly, if the only required permission is “read”: then only “read”
should be granted and nothing else.

8 http://blogs.msdn.com/b/sqlsecurity/archive/2008/01/10/xp-cmdshell.aspx
9 http://freecode.com/projects/myperl
10 http://blogs.msdn.com/b/sathishcg/archive/2006/11/24/undocumented-sql-server-2000-functions.aspx

APPLIED SECURE CODING PRINCIPLES - LEAST PRIVILEGE 19


P W D / P R A C T I C A L W E B D E F E N S E

6.4 Further Reading


The following resources may provide additional information about this principle:
• Common Weaknesses Enumeration - CWE-272: Least Privilege Violation
http://cwe.mitre.org/data/definitions/272.html
• How to successfully implement the principle of least privilege
http://www.techrepublic.com/blog/it-security/how-to-successfully-
implement-the-principle-of-least-privilege/
• Least Privilege 2.0: Access Control for Web 2.0 applications
http://researcher.watson.ibm.com/researcher/files/us-msteiner/least-
privilege_2.0.pdf
• OWASP Development Guide: Secure Coding Principles
https://www.owasp.org/index.php/Secure_Coding_Principles

APPLIED SECURE CODING PRINCIPLES - LEAST PRIVILEGE 20


P W D / P R A C T I C A L W E B D E F E N S E
CHAPTER

7
7. DEFENSE IN DEPTH

7.1 Principle description


Security controls should not be used in isolation: they should be layered, even if
they are redundant or overlap.
The reasoning behind this principle is that, if a security control is bypassed, the attacker
will need to bypass additional security controls after that, which will, in many cases, render
the attack useless.

7.2 DOM XSS prevention in HTML5 postMessage


example
Let us say that a web application requires enabling HTML5 push message from a given
domain. The following example uses a defense in depth approach to this:
1) Checks the origin
2) Validates input against a regular expression
3) Performs output encoding via “escape”
4) Uses JavaScript’s textContent/innerText instead of an HTML sink

APPLIED SECURE CODING PRINCIPLES - DEFENSE IN DEPTH 21


P W D / P R A C T I C A L W E B D E F E N S E

<div id="msg">Waiting for message..</div>


<script>
function processMessage(e) {
if (e.origin != 'http://a.com') {//1) Origin validation
alert('domain ' + e.origin + ' is not allowed on ' +
document.domain);
return; //Abort
}
if (!/^[0-9a-z]+$/i.test(e.data) {//2) Input validation
alert('the message is not valid: only letters and numbers
allowed please');
return; //Abort
}
var msg = document.getElementById("msg");
//Avoiding HTML sinks (i.e. using textContent / innerText
instead) + output encoding (escape)
if (msg.textContent) {//cross-browser check
msg.textContent += document.domain + " received " +
escape(e.data) + " from " + e.origin;
}
else {
msg.innerText += document.domain + " received " +
escape(e.data) + " from " + e.origin;
}
}
if (window.addEventListener) {//browsers that nicely follow
standards
window.addEventListener("message", processMessage, false);
}
else {
window.attachEvent("onmessage", processMessage);
}
</script>

APPLIED SECURE CODING PRINCIPLES - DEFENSE IN DEPTH 22


P W D / P R A C T I C A L W E B D E F E N S E

7.3 Reflected XSS prevention example


The following example combines a number of security controls to prevent XSS (and other
things):
1) Casts user input to string first (this is PHP-specific to avoid &number[]= to
become an array)
2) Validates the number using a white-list regular expression
3) Casts the number to integer after validation
4) Sets up the charset of the HTML page
5) Performs output encoding using the most restrictive function (htmlentities) in the
most aggressive way (ENT_QUOTES) and using the charset of the page (UTF8)
6) It surrounds the attribute in quotes

<?php
//Lets suppose $_GET['number'] needs to be provided for the class
name to be “test1”, “test2”, “test3”, etc.
$number = (string) $_GET['number']; //Cast to string to avoid “[]”
PHP conversions to array
if (!preg_match('/^\d+$/', $number)) {//This is not a number
die('Invalid number!...');//This is an attack, abort processing
}
$number = (int) $number; //Now cast the number to integer, in case
there is a mistake earlier
//Finally output encode the value:
echo "<html>
<head><meta charset="UTF-8"></head>
<span class=\"test" . htmlentities($number, ENT_QUOTES, "UTF-8") .
"\">test</span>
</html>";

APPLIED SECURE CODING PRINCIPLES - DEFENSE IN DEPTH 23


P W D / P R A C T I C A L W E B D E F E N S E

7.4 Further Reading


The following resources may provide additional information about this principle:
• Defense-In-Depth: An Information Assurance Strategy for the Enterprise
http://www.sdsc.edu/~victor/DefenseInDepthWhitePaper.pdf
• Understanding layered security and defense in depth
http://www.techrepublic.com/blog/it-security/understanding-layered-
security-and-defense-in-depth/
• If You Cannot Prevent It, Detect It: Why Defense In Depth Works
http://www.savidtech.com/blog/application-security/if-you-cannot-
prevent-it-detect-it-why-defense-in-depth-works/
• NSA Defense in Depth guidelines
http://www.nsa.gov/ia/_files/support/defenseindepth.pdf
• OWASP CLASP Security Principles
https://www.owasp.org/index.php/CLASP_Security_Principles
• OWASP Development Guide: Secure Coding Principles
https://www.owasp.org/index.php/Secure_Coding_Principles

APPLIED SECURE CODING PRINCIPLES - DEFENSE IN DEPTH 24


P W D / P R A C T I C A L W E B D E F E N S E
CHAPTER

8
8. SECURE DEFAULTS

8.1 Principle description


The web application should use a framework, platform, libraries, etc. which are
“secure by default” or at least are all configured to be so.
The reasoning behind this principle is that if something can be forgotten, it will be, and
will introduce a security problem. Having secure defaults is an easy way to avoid human
error with security impact.

8.2 Practical examples


Ruby on Rails offers protections against cross site scripting (XSS), cross site request
forgery (CSRF) and SQL injection out of the box11.
In Python, Pyramid12 and Django13 offer out of the box protection against a wide number
of web attacks.
In PHP, some frameworks/templating engines like FuelPHP14, CakePHP15, Twig in
Symfony16 and Latte17 will perform output encoding and provide other protections by
default.
Having an output layer that makes output encoding automatic, simple and convenient is
the safest way to ensure everything is output encoded correctly.

11 http://blog.codeclimate.com/blog/2013/03/27/rails-insecure-defaults/
12 http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/security.html
13 https://docs.djangoproject.com/en/dev/topics/security/
14 http://fuelphp.com/docs/general/security.html
15 http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html
16 http://symfony.com/doc/current/book/templating.html
17 http://doc.nette.org/en/templating

APPLIED SECURE CODING PRINCIPLES - SECURE DEFAULTS 25


P W D / P R A C T I C A L W E B D E F E N S E

In the case of XSS, a component that renders HTML on the fly will generally be best for
output encoding correctly since it will be able to take context into account (i.e. escape
inside an attribute instead of inside a <div> element).
Most ORM18 libraries nowadays will also use bind variables in their dynamically generated
SQL queries by default.
Using a framework will also focus code review effort into “code that bypassed the
framework”, which will be “the code where human error is more likely”, hence lowering
the cost of code reviews significantly.
The ultimate goal of web application frameworks, from the security point of view is to
make more convenient to produce secure code than insecure code.
For example, CakePHP makes this (safe from XSS by default via automatic output
encoding):

echo $this->Form->input('password');

Much more convenient than this (vulnerable to XSS by default):

echo '<input type="password" value="' . $_POST['pass'] . '">';

8.3 Further Reading


The following resources may provide additional information about this principle:
• Secure by Default: Why "Secure By Default" is a step in the right direction.
http://www.securityfocus.com/columnists/241
• Case Study of Django: Web Frameworks that are Secure by Default
http://www.slideshare.net/Voulnet/case-study-of-django-web-
frameworks-that-are-secure-by-default
• OWASP Development Guide: Secure Coding Principles
https://www.owasp.org/index.php/Secure_Coding_Principles

18 http://en.wikipedia.org/wiki/Object-relational_mapping

APPLIED SECURE CODING PRINCIPLES - SECURE DEFAULTS 26


P W D / P R A C T I C A L W E B D E F E N S E
CHAPTER

9
9. MAKE SECURITY SIMPLE AND
OBVIOUS

9.1 Principle description


Security should be as simple and obvious as possible when looking at the source
code.
The reasoning behind this principle is that it should take as little effort as possible to
realize whether any given piece of source code is secure or insecure. This is not only to
save time but also to help development teams to avoid introducing security problems in
the first place by using coding standards and guidelines.

9.2 Data labeling example


Data labeling is a coding standard technique to make it obvious to differentiate what is
user input, from what is valid, what is escaped, etc.
The labeled data sink is a data structure that makes it clear that data is user input,
validated or escaped. For example, let us compare this (the developer needs to visually
track all the alterations to $user_id, this is error-prone when thousands of lines of code are
involved):

$user_id = (string) $_POST['user_id'];//The source


if (preg_match('|^\d+$|', $user_id)) {//This contains only digits
$user_id = (int) $user_id;//Explicit cast to integer, just to
be sure
$user_id = mysql_real_escape_string($user_id);//SQL Escape
$sql = "SELECT ….. WHERE user_id ='" . $user_id . "'";//The
sink
}

APPLIED SECURE CODING PRINCIPLES - MAKE SECURITY SIMPLE AND OBVIOUS 27


P W D / P R A C T I C A L W E B D E F E N S E

To this (the developer is doing exactly the same, but now does not need to follow all the
code):
$user_input = $valid_input = $sql_escaped =
array();//Initialize the data structure arrays
$user_input['user_id'] = (string) $_POST['user_id'];//The
source

if (preg_match('|^\d+$|', $user_input['user_id'])) {//This


contains only digits
$valid_input['user_id'] = (int) $user_input['user_id'];
//Explicit cast to integer, just to be sure
$sql_escaped['user_id'] =
mysql_real_escape_string($valid_input['user_id']);//SQL Escape
$sql = "SELECT ….. WHERE user_id ='" .
$sql_escaped['user_id'] . "'";//The sink
}
The first example makes it difficult to see what “$user_id” is, the second example makes it
much easier to see that the code has been secured, even though both examples are safe.
Please note that in the real world bind variables should always be preferred over
escaping, this is simply an example to illustrate how tracking variables can assist making
the code easier to review.

9.3 Stopping execution as soon as a security check


fails example
Some developers will favor a coding style approach like this (when the code is long and
complicated, this makes it significantly more likely to introduce business logic flaws):

$valid = true;
$input = (string) $_GET['input'];
if (strlen($input) > 20|| !preg_match('/^[a-z]+$/i', $input))
{//Something other than letters was provided!
$valid = false;
}
if ($valid) {
//processing
}

Over an approach like this (stops execution as soon as a security check fails):

$input = (string) $_GET['input'];


if (strlen($input) > 20|| !preg_match('/^[a-z]+$/i', $input))
{//Something other than letters was provided!
die('Invalid input …');//Abort processing
}
//processing

APPLIED SECURE CODING PRINCIPLES - MAKE SECURITY SIMPLE AND OBVIOUS 28


P W D / P R A C T I C A L W E B D E F E N S E

Whether you prefer to throw a exception, exit() or die() is a matter of taste, what matters
the most from the security perspective is to ensure that developers do not need to follow
the source code to determine if it is secure or not. In the first example, a developer would
need to follow what happens with $valid (which may be non-trivial on a large code-base
involving many files), while in the second example, the developer sees straightaway that
when a check fails, execution is aborted and does not need to keep track of anything else
mentally.

9.4 Centralized security control example


Centralizing security controls are perhaps one of the most powerful defensive techniques:
Instead of implementing the same security control in many places, the security control
should, whenever possible, be implemented in a central place that is then reused
by many lines of code. Centralized security controls simply follow the basic
programming principles of “DRY – Don’t repeat yourself” and “Code Reuse is Good”19.
For example, if we have 10,000 PHP files that require authentication it will be significantly
easier to implement authentication in a single front controller than in the 10,000 PHP files:

session_start();
if (!isset($_SESSION['logged_in']) || ! $_SESSION['logged_in']) {
die('To login please <a
href="http://example.com/login.php">click here</a>');
}

$pageMap = array(1 => array("path" => "path/to/file", …),


…);//white-list of allowed pages
$page = (string) $_GET['page'];//Avoid fun array tricks in PHP via
“page[]=”

if (!isset($page) || !isset($pageMap[$page])) {
die('Invalid page'); //Abort processing
}
$file_path = " ../
app_code/"; //Location of 10,000 PHP files
(outside of webroot)
require $file_path . $pageMap[$page]['path'];//Execute the file

19 http://www.artima.com/weblogs/viewpost.jsp?thread=331531

APPLIED SECURE CODING PRINCIPLES - MAKE SECURITY SIMPLE AND OBVIOUS 29


P W D / P R A C T I C A L W E B D E F E N S E

9.5 Further Reading


The following resources may provide additional information about this principle:
• RSA Conference Message: Make Security Simple
http://www.crn.com/news/security/180206845/rsa-conference-message-
make-security-simple.htm
• Can We Make Security Simple?
http://par4tech.com/can-we-make-security-simple/
• Chris Shifflet: SQL Injection (explains the $clean array technique)
http://shiflett.org/articles/sql-injection
• OWASP Development Guide: Secure Coding Principles
https://www.owasp.org/index.php/Secure_Coding_Principles

APPLIED SECURE CODING PRINCIPLES - MAKE SECURITY SIMPLE AND OBVIOUS 30


Powered by TCPDF (www.tcpdf.org)

You might also like