php & web security - phpxperts 2009
TRANSCRIPT
PHP & WEB SECURITYM. Mizanur Rahman
C.T.O
Informatix Software
WHAT IS SECURITY? Security is a measurement, not a characteristic.
It’s is also an growing problem that requires an continually evolving solution.
A good measure of secure application is it’s ability to predict and prevent future security problems, before someone devises an exploit.
As far as application design goes, security must be considered at all times (initial spec, implementation, testing and even maintenance)
NECESSITY OF WEB SECURITY
We value our privacy We value our client’s important data We want to make everyone’s web presence
safer and better We must remember , it’s the users who uses
the system Users can be good as well as bad
PHP FACTS
A very popular language for web application development
Easy to learn and adopt. Popular among new learners
Almost all PHP programs are written for the web
During development most of us forget one important aspect and that is the security of the application
Always have a tendency of “do it later”. As a result high possibility of security holes in the system.
COMMON ATTACKS
Input Validation SQL Injection Code Injection XSS or Cross Site Scripting CSRF or Cross Site Request Forgery Session Security
INPUT VALIDATION Common development trends
Always expecting valid data type, as a result ignoring any validation
Trusting clients data as it passed the client side validations!!!
Problems Code injection SQL injection Command injection
Solution Always validate inputs using available PHP
functions (is_int(), is_float(), is_bool(),is_finite(), intval(), floatval(), doubleval(), strlen(), strpos(), ctype_alpha(), ctype_alnum()
SQL INJECTION
One of the most common problems with security
SQL queries are injected as input Also similar to input validation What are the possible problems can be
created: Data removal Modification of existing values Unwanted access grant Arbitrary data injection
SQL INJECTION - EXAMPLES
/* articles.php */$id = $_GET[‘id’];$sql = “select * from articles where id = ‘$id’ ”;$result = mysql_query($sql);
Now when we have a call like:http://www.example.com/articles.php?id=1
It is very much valid and we can expect article with id 1 will be fetched from the database.
SQL INJECTION – EXAMPLES CONTINUED
Now what if I write the following in the url:http://www.example.com/articles.php?id=1’;
delete from articles;
Now the query becomes “select * from articles where id = ‘1’; delete
from articles”
So what are we doing, we are actually deleting the whole table as we are not checking for the SQL injection.
SQL INJECTION – THE CURE
Escaping inputs using addslashes or built in PHP mechanism magic_quotes_gpc.
Use dedicated escaping function provided by the database interface MySQL
mysql_escape_string() mysql_real_escape_string()
PostgreSQL pg_escape_string() pg_escape_bytea()
SQLite sqlite_escape_string()
SQL INJECTION – THE CURE (CONT.)
So our example will look like this now$id = mysql_real_escape_string ($_GET[‘id’]);
$sql = “select * from articles where id = ‘$id’ ”;
$result = mysql_query($sql);
But sometime escaping can fail as well!!!$id = “0; delete from articles”;
$id = mysql_real_escape_string($id); // 0; delete from articles
mysql_query(“SELECT * FROM articles WHERE id={$id}”);
To solve such problem, use explicit casting
$id = (int) $id;
SQL INJECTION – THE CURE (CONT.)
Database specific escaping is not available for all database (MSSQL, ORACLE etc)
Prepared Statements - another approach Prepared queries are query “templates”: the
structure of the query is pre-defined and fixed and includes placeholders that stand-in for real data. The placeholders are typically type-specific—for example, int for integer data and text for strings—which allows the database to interpret the data strictly
We can use PDO (PHP Data Objects) for prepared statement
PREPARED STATEMENT - EXAMPLE
<?php
$db = new PDO('mysql:host=localhost;dbname=dbname', 'username', 'password');
$stmt = $db->prepare(‘select * from articles where id = ?');
try {
$stmt->execute(array($_GET['id']));
$stmt->fetchAll();
}
catch(PDOException $e) {
echo 'Selection failed. Please try again.';
}
?>
CODE INJECTION
Code injection occurs when we use parameters from the web as direct parameter for our code execution.
This is especially important for includes
$module = $_REQUEST['module'];
include(“lib/$module”);
This is ok: http://example.com/cms?module=login.php
But what if I do this?: http://example.com/cms?module=../passwords.ini
CODE INJECTION – PREVENTION Make sure the value is the one you expected.
Else show error message
$requestedModule = $_REQUEST['module'];switch($requestedModule){
case “login”:$module = “login”; break;case “logout”:$module = “logout”; break;default:$module = “error”;
}
XSS – CROSS SITE SCRIPTING
Cross Site Scripting (XSS) is a situation where by attacker injects JavaScript code, which is then displayed on the page without further validation. Can lead to embarrassment. Session take-over. Password theft. User tracking by 3rd parties.
Common XSS examples: User submitted content sites such as blogs, forums,
wikis etc User comments on different sites.
XSS – EXAMPLES
You have built a site where user can comment on articles
You have provided a comment box to take user input and store those in Database then redisplaying in the page.
What if a user enters the following as comment:<script>
Window.location = http://www.mysite.com/
</script>
Since we have not done any filtering of the input data, when the page loads user will be taken to mysite. Which is not the right scenario.
XSS - PREVENTION
Prevention of XSS is as simple as filtering input data via one of the following: htmlspecialchars()
Encodes ‘, “, <, >, & htmlentities()
Convert anything that there is HTML entity for. strip_tags()
Strips anything that resembles HTML tags
Tag allowances in strip_tags() are dangerous, because attributes of those tags are not being validated.
CSRF A CSRF exploit works by exploiting the trust
your website has for a specific user (for instance, a user that is logged in). Most websites allow a user to enable a “Remember Me” function that will keep their session active for a long period of time. With this session active, a user could visit a malicious link or visit a website with a malicious iframe, which causes that user to unknowingly perform actions on your site.
Major attacks on recent time: ING – CSRF used to transfer funds without any
notice Youtube
EXAMPLE
UserA is a member of bank.com. He sends money to UserB and found that the following URL used
http://bank.com/transfer.do?acct=UserB&amount=100
Now UserA constructs a URL like above to victimize UserC (who is also a user of bank.com)
http://bank.com/transfer.do?acct=UserA&amount=100000
Now UserA sends an email to UserC with a forged request.
<a href="http://bank.com/transfer.do?acct=UserA&
amount=100000">View my Pictures!</a>
EXAMPLE – (CONTINUED)
Now if userC clicks the link, he is actually initiating the request as he is already authenticated in the system.
But wait, when userC clicks the link, he will definitely notice that a payment has been done. So in order to trick userC without any notice. UserA does this (zero byte image).
<img src="http://bank.com/transfer.do?acct=UserA&
amount=100000" width="1" height="1" border="0“>
So without any problem, userA has got fund from userC.
PREVENTING CSRF
Distinguish each and every request generated from your server.
Distinguish request generated from your site and also from some other sites.
Do not rely on HTTP Referrer checking as it is not fully reliable.
Include a form token on every forms that you display. The form token must be unique and ensure that the request came from your site.
Yahoo! Uses similar approach and calls it Crumb
EXAMPLE<?php $_SESSION[‘formKey’] = md5(“unique_id”);?><form action="http://app.example.com/delete.php"method="POST"><input type="hidden" name="id" value="37"><input type="hidden" name=“formKey"value=“<?=$_SESSION[‘formKey’]?>"><input type="submit" value="Delete this item"></form>
/* server site code */if($_POST[‘formKey’] !== $_SESSION[‘formKey’]) {
echo ‘not valid request’; exit;} else {
// do something unset($_SESSION[‘formKey’]); // unset the formKey so it is not used anymore}
NOTE
Should be unique per user (or one user can use their crumb to attack another) Hence should be tied to the user’s session or
login cookie Should be changed over time (even for same
form request multiple time) Ajax requests must be from the same domain Limiting the lifetime of authentication
cookies
SESSION SECURITY
Sessions are common tool for user tracking across a web site
For the duration of a visit, the session is effectively the user’s identity
If an active session can be obtained by 3rd party, it can assume the identify of the user who’s session was compromised
During standard HTTP transactions, all request and response information is transmitted as plain-text. Anyone capable of intercepting these messages can steal the user’s session.
SECURING SESSION
To prevent session id theft, the id can be altered on every request, invalidating old values.
<?php
session_start();
if (!empty($_SESSION)) { // not a new session
session_regenerate_id(TRUE); // make new session id
} ?> Because the session changes on every
request, the “back” button in a browser will no longer work, as it will make a request with the old session id
NOTES
Use HTTPS Pass secure information Stop session ID being passed via URL Set session.use_only_cookies so that it is
hard to generate session fixation. Another session security technique is to
compare the browser signature headers
THERE ARE MORE!!!!
There are more security issues out there. Always try to be proactive on security
measure rather than being reactive. Keep updated with latest security flaws and
fixes Always try to avoid common pitfalls.
RESOURCES
http://www.modsecurity.org/ (mod_security Apache module)
http://www.hardened-php.net/ (PHP Security Patches)
http://www.xssoops.com/ (Security Scanner) http://www.cgisecurity.com/ http://www.owasp.org/ http://phpsec.org/
THANK YOU
Questions?