How to build a secure PHP webpage: Part 1

  • Home
  • Blog
  • How to build a secure PHP webpage: Part 1
How to build a secure PHP webpage: Part 1

PHP is a powerful tool that is often used when making websites. However, like most software it can be prone to a multitude of security issues, in both it’s implementation & it’s use. Because of this, a plethora of cyberattacks target PHP applications & a large amount of those are even automated malware which roam the internet.

This article attempts to share a list of some vulnerabilities with PHP websites that are commonly targeted & code examples to fix those issues. Please note that this is not an exhaustive list, there’s many common vulnerabilities that aren’t covered here & might be covered in further articles.

SQL Injection

SQL injections are a common vulnerability that can be remarkably simple to solve. The trick is to separate the data and the query, which can be done as seen below when using PHP Data Objects(PDO) as the SQL driver. Concatenation of the input with the query should never be done manually because it allows arbitrary input, which could be malicious. Built-in functions like a “prepare” and “execute” will help to filter malicious inputs in a way that has been time tested and approved by the community, making it much more resilient.

$query = "DELETE FROM website.Session WHERE (User_ID = :user_id AND Session_ID = :session_id)";

$values = array(':session_id' => session_id(), ":user_id" => $user_id);

try {

$delete = $PDO->prepare($query);


} catch(PDOException $exception) {

throw new Exception("Database failure!");


Now using PDO properly is one thing, but changes to the settings of PDO must also be done to ensure the data isn’t interpreted. Allowing interpretation of the data would allow malicious input since a malicious actor could fool the interpreter into thinking the data or part of it was a part of the query. Knowing this, a simple change in the PDO settings will prevent it, however it’s also recommended to enable error handling since logging errors tends to lead to the discovery of bugs.


$PDO->setAttribute(PDO::ATTR_EMULATE_PREPARES, False); // Disables interpretation

$PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Enables errors

Cross-Site Scripting (XSS)

XSS are very prominent attacks which are similar in nature to SQL injections since both try to inject malicious code. But, to prevent XSS one has to mainly do input sanitization and proper control character encoding. This is mainly done using two functions: “strip_tags()” & “htmlspecialchars()”. The first one, “strip_tags()” allows the developer to remove HTML & PHP tags from any string based input. Which is great, but not good enough for every XSS attack. Sometimes the XSS will use character encoding to try and bypass this removal of code tags. To prevent this and still allow special characters in an input, the use of the function “htmlspecialchars()” will convert the special characters into HTML entities. By doing this, the input will not be interpreted by the end user, thus preventing most XSS attacks. It should be noted that any user input could be malicious, hence why doing input sanitization on all user input is generally recommended. The use of built-in functions for input sanitization is preferable mainly because it’s time tested and approved by the community.

Password Hashing

Hashing algorithms are often an overlooked part of web apps, which I assume is because selecting the right hashing algorithm is only important after a breach has occurred since before that very little impact is seen. But in this case, as of this writing, it’s usually preferable to use SHA3 or ARGON2ID as a hashing algorithm in the context of PHP, SHA3 is preferable because it’s a post-quantum algorithm that is standardized. ARGON2ID is preferable because it’s the strongest algorithm available natively in most PHP functions related to password management. It should be noted that even if one uses the right algorithm, the implementation and use of it can render it vulnerable. One way to avoid this is to use built-in functions made for this usage. A good example is to use the functions “password_hash()”, “password_verify()” & “password_needs_rehash()”. Those are built-in, time tested and community approved, meaning they will protect you against more then just using the right algorithm, “password_verify()” also protects you against timing attacks which could be used to determine if a user exists or parts of the password.


Cookies are an important part of web applications, they allow the developer to store information on the browser which eases the design of the website. But often it’s forgotten that they have properties besides a value. For example the “SameSite” property allows you to restrict which websites can access the cookie, so naturally you usually would only want your website to access the cookie which is why it’s preferable to set it to “Strict”.

The property “Secure” also allows you to protect the confidentiality of the cookie because the browser will only share the cookie on secure channels which will typically be HTTPS but can be other protocols that are encrypted. So it’s best to enable that property.

HTTPOnly” is a property that indicates to the browser that the cookie should not be accessible to client side APIs like Javascript. So if your cookie is not used by any scripts or could be made to not be used by client side scripts, then it’s best to enable it. Mainly because this will prevent malicious scripts or attacks like XSS from accessing the content of the cookie.

session_start(['cookie_lifetime' => 604800, 'cookie_samesite' => 'Strict', 'cookie_secure' => true, 'cookie_httponly' => true]); // 7 days cookie lifetime

It’s needless to say that there are many more vulnerabilities out there, here’s a few for those that wish to read further on the topic: include injection, command injection, directory traversal, XML attacks & object injection.

Leave a Reply

Your email address will not be published. Required fields are marked *