Does Laminas Framework DB Adapter automatically strip tags etc. like mysqli_real_escape_string?

1.1k Views Asked by At

I'm using Laminas framework (formerly ZEND Framework) and would like to know if the DB Adapter automatically strip tags etc. at Insert and Select Statements / Execution ($statement->prepare() / $statement->execute()->current()) to avoid SQL injection?

If not what is the best method to implement it while working with LAMINAS DB Adapter? A Wrapper function to get a clean SQL statement?

Before, I was using a wrapper function that cleaned the input with mysqli_real_escape_string

1

There are 1 best solutions below

0
Will Jones On

You'd need to provide some sample code in order to get a more accurate answer to this question, however the topic you're talking of here is parameterisation. If you use laminas-db properly, you won't have to call mysqli_real_escape_string or similar to protect against SQL injection. However, you should still be very wary of any potential cross site scripting (XSS) issues if any data written to your database eventually gets echoed back to the browser. See the section below on that.

How to NOT do it

If you do anything like this, laminas-db won't parameterise your query for you, and you'll be susceptible to SQL injection:

// DO NOT DO THIS
$idToSelect = $_POST['id'];
$myQuery = "select * from myTable where id = $idToSelect";
$statement->prepare($myQuery);
$results = $statement->execute();

How to do it properly

Personally, I make use of the Laminas TableGatewayInterface abstraction, because it generally makes life a lot easier. If you want to operate at the lower level, something like this is a much safer way of doing it; it'll ensure that you don't accidentally add a whole heap of SQL injection vulnerabilities to your code

Named Parameters

$idToSelect = $_POST['id'];
$myQuery = "select * from myTable where id = :id";
$statement->prepare($myQuery);
$results = $statement->execute(['id' => $idToSelect]);

Anonymous Parameters

$idToSelect = $_POST['id'];
$myQuery = "select * from myTable where id = ?";
$statement->prepare($myQuery);
$results = $statement->execute([$idToSelect]);

If you do it in a way similar to this, you won't need any additional wrapper functions or anything, the underlying components will take care of it for you. You can use either the named or anonymous parameter version, however I personally prefer the named parameters, as I find it aids code readability and generally makes for easier debugging.

Sanitising Input/Escaping Output

Be very careful with sanitising input. Not only can it lead to a false sense of security, it can also introduce subtle and very frustrating behaviour that the end user will perceive as a bug.

Take this example: Someone tries to sign up to a site under the name "Bob & Jane Smith", however the input sanitisation routine spots the ampersand character and strips it out. All of a sudden, Bob has gained a middle name they never knew they had.
One of the biggest problems with input sanitisation is context. Some characters can be unsafe in one given context, but entirely benign in another. Furthermore, if you need to support the entire unicode character set (as we generally should be unless we have a very good reason to not), trying to sanitise out control characters in data that will potentially pass through several different systems (html, javascript, html, php, sql, etc) becomes a very hard problem due to the way multibyte characters are handled.

When it comes to MySQL, parameterisation pretty much takes care of all of these issues, so we don't need to worry about the "Little Bobby Tables" scenario.

It's much easier to flip all of this on its head and escape output. In theory, the code that's rendering the output data knows in which context it's destined for, so can therefore escape the output for said context, replacing control characters with safe alternatives.

For example, let's say someone's put the following in their bio on a fictional social networking site:

My name is Bob, I like to write javascript
<script>window.postStatusUpdate("Bob is my hero ♥️");</script>

This would need to be escaped in different ways, depending upon the context in which this data is to be displayed. If it's to be displayed in a browser, the escaper needs to replace the angle brackets with an escaped version. If it's going out as JSON output, the double quotes need to be backslash escaped, etc.

I appreciate this is a rather windy answer to a seemingly simple question, however these things should certainly be considered earlier on in the application design; It can save you heaps of time and frustration further on down the line.