Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Security is an interesting concept and attracts a lot of people to it. Unfortunately it's a complex subject and even the professionals get it wrong. I've found security holes in Google (CSRF), Facebook (more CSRF), several major online retailers (mainly SQL injection / XSS), as well as thousands of smaller sites both corporate and personal.</p> <p>These are my recommendations:</p> <p><strong>1) Use parameterised queries</strong><br /> Parameterised queries force the values passed to the query to be treated as separate data, so that the input values cannot be parsed as SQL code by the DBMS. A lot of people will recommend that you escape your strings using <code>mysql_real_escape_string()</code>, but contrary to popular belief it is <strong>not</strong> a catch-all solution to SQL injection. Take this query for example:</p> <pre><code>SELECT * FROM users WHERE userID = $_GET['userid'] </code></pre> <p>If <code>$_GET['userid']</code> is set to <code>1 OR 1=1</code>, there are no special characters and it will not be filtered. This results in all rows being returned. Or, even worse, what if it's set to <code>1 OR is_admin = 1</code>?</p> <p>Parameterised queries prevent this kind of injection from occuring.</p> <p><strong>2) Validate your inputs</strong><br /> Parameterised queries are great, but sometimes unexpected values might cause problems with your code. Make sure that you're validating that they're within range and that they won't allow the current user to alter something they shouldn't be able to.</p> <p>For example, you might have a password change form that sends a POST request to a script that changes their password. If you place their user ID as a hidden variable in the form, they could change it. Sending <code>id=123</code> instead of <code>id=321</code> might mean they change someone else's password. Make sure that EVERYTHING is validated correctly, in terms of type, range and access.</p> <p><strong>3) Use htmlspecialchars to escape displayed user-input</strong><br /> Let's say your user enters their "about me" as something like this:<br /> <code>&lt;/div&gt;&lt;script&gt;document.alert('hello!');&lt;/script&gt;&lt;div&gt;</code><br /> The problem with this is that your output will contain markup that the user entered. Trying to filter this yourself with blacklists is just a bad idea. Use <code>htmlspecialchars</code> to filter out the strings so that HTML tags are converted to HTML entities.</p> <p><strong>4) Don't use $_REQUEST</strong><br /> Cross-site request forgery (CSRF) attacks work by getting the user to click a link or visit a URL that represents a script that perfoms an action on a site for which they are logged in. The <code>$_REQUEST</code> variable is a combination of <code>$_GET</code>, <code>$_POST</code> and <code>$_COOKIE</code>, which means that you can't tell the difference between a variable that was sent in a POST request (i.e. through an <code>input</code> tag in your form) or a variable that was set in your URL as part of a GET (e.g. <code>page.php?id=1</code>).</p> <p>Let's say the user wants to send a private message to someone. They might send a POST request to <code>sendmessage.php</code>, with <code>to</code>, <code>subject</code> and <code>message</code> as parameters. Now let's imagine someone sends a GET request instead:</p> <pre><code>sendmessage.php?to=someone&amp;subject=SPAM&amp;message=VIAGRA! </code></pre> <p>If you're using <code>$_POST</code>, you won't see any of those parameters, as they are set in <code>$_GET</code> instead. Your code won't see the <code>$_POST['to']</code> or any of the other variables, so it won't send the message. However, if you're using <code>$_REQUEST</code>, the <code>$_GET</code> and <code>$_POST</code> get stuck together, so an attacker can set those parameters as part of the URL. When the user visits that URL, they inadvertantly send the message. The really worrysome part is that the user doesn't have to do anything. If the attacker creates a malicious page, it could contain an <code>iframe</code> that points to the URL. Example:</p> <pre><code>&lt;iframe src="http://yoursite.com/sendmessage.php?to=someone&amp;subject=SPAM&amp;message=VIAGRA!"&gt; &lt;/iframe&gt; </code></pre> <p>This results in the user sending messages to people without ever realising they did anything. For this reason, you should avoid <code>$_REQUEST</code> and use <code>$_POST</code> and <code>$_GET</code> instead.</p> <p><strong>5) Treat everything you're given as suspicious (or even malicious)</strong><br /> You have no idea what the user is sending you. It could be legitimate. It could be an attack. Never trust anything a user has sent you. Convert to correct types, validate the inputs, use whitelists to filter where necessary (avoid blacklists). This includes anything sent via <code>$_GET</code>, <code>$_POST</code>, <code>$_COOKIE</code> and <code>$_FILES</code>.</p> <p><br /><br /> If you follow these guidelines, you're at a reasonable standing in terms of security.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload