Just the Gist
A not uncommon criticism of PHP is that it lacks in security. The sad part is, we can't argue against it. It's too broad of a criticism which can be leveraged against most languages, as most have some way a secret can be leaked. Modern PHP and modern coding practices exists to mitigate this. But today, we are going to take a look at one very basic security flaw example, and a way we could mitigate it. It's what could happen if we don't run a web server but still have our php-files public.
Say that we have an index.php
located in a public-folder. This file is protecting the identity of the secret santa until Christmas Day. It may look like this:
<?php
define('SECRET_SANTA', "Olaf ⛄");
?>
<!DOCTYPE html>
<html lang="en">
<body>
<h1>The Secret Santa is a secret!</h1>
<p>You have to wait until Christmas Day to know who it is.</p>
<?php
$today = new DateTime("now");
$christmas = new DateTime("2021-12-25");
if ($today >= $christmas) {
echo "<p>The Secret Santa is " . SECRET_SANTA . "!</p>";
} else {
echo "<p>The Secret Santa is still a secret.</p>";
}
?>
</body>
</html>
As long as we have a web server service active (such as Apache), this will be interpreted correctly and we would have the following output:
But what would happen if the service was down and we had visitors to the website? Instead of parsing the PHP file and rendering the correct output, we would serve the file as simple text. All our code would be visible and any one could see that it's Olaf! 😱
So how could we protect ourselves from this happening? We could move our secrets out of the public folder (or the web-root) and into a folder that is not accessible by visitors. Say that we have the following structure:
/
|-- public-folder
| |-- index.php
|
|-- private-folder
|-- SecretSanta.php
Our visitors would be unable to see the contents of the SecretSanta.php
file, but they would be able to see the index.php
file. So here's how we could do this.
SecretSanta.php
<?php
class SecretSanta
{
private const SECRET_SANTA = 'Olaf ⛄';
public static function getSecretSanta(): bool|string
{
if ((new DateTime("now")) >= new DateTime("2021-12-25")) {
return self::SECRET_SANTA;
} else {
return false;
}
}
}
This class declares a constant with the identity of the Secret Santa. It's private so no other file has access to it. We must use the static function getSecretSanta()
to access the secret santa. This function will return the secret santa if it's on or after Christmas Day, otherwise it will return false
.
Going back to the index.php
file, we can now get the secret santa by calling the static function on the class (SecretSanta::getSecretSanta()
):
<?php
require('../private/SecretSanta.php');
?>
<!DOCTYPE html>
<html lang="en">
<body>
<h1>The Secret Santa is a secret!</h1>
<p>You have to wait until Christmas Day to know who it is.</p>
<?php
if (SecretSanta::getSecretSanta()) {
echo "<p>The Secret Santa is " . SecretSanta::getSecretSanta() . "!</p>";
} else {
echo "<p>The Secret Santa is still a secret.</p>";
}
?>
</body>
</html>
We would still get the same output as before when the web server service is running, but now we can see that the secret santa is not visible to the public if the service is down. This is but one example of how it may be a good idea to have your application logic and secrets outside of the public folder.
There is so much more to keep track of when it comes to security. This article hasn't covered even a fraction of it. And many of the issues are not specific to PHP. There are Cross Origin Resource Forgery (CSRF) attacks, SQL Injection, Cross Site Scripting (XSS), and many more.
What about you?
Perhaps you have some good insight into good security practices within the PHP ecosystem, please share! Have you encountered projects with bad security? What are your best security recommendations to web developers building their first couple of PHP projects? Comment below and let us know what you think ✍
Further Reading
- PHP Manual on Security: https://www.php.net/manual/en/security.php
- Zend on how to handle security risks: https://www.zend.com/blog/managing-security-risks-php-engine-and-web-applications
Top comments (34)
I'd argue about the catchy headline...
This article is mostly about misconfiguration of a tool that is not PHP. It's like saying food is dangerous because one might suffocate eating it.
Just another article that spreads bad mood about a language that drives the majority of the web today.
PHP is just a tool and as with most tools, shitty users of the tool will produce shitty results.
I agree with you.
As a lover and user of PHP, I was driven to read this post due to the caption, but of course, it's rather misguided.
PHP is all about the configuration and coding orientation. As with other languages, when not properly used, can expose your codes to some security breaches. However, that does not make PHP bad in itself.
As you said, shitty users of every tool will produce shitty results.
I wrote it in a comment to someone else, but let's rehash this: I don't think PHP is any more insecure than any other language. In fact, if that was my argument I have made a pretty poor proof of it. I'm pretty sure I wrote this in the short article itself, but it's obvious I didn't make this point clear enough.
PHP is a great language. This article is the 19th article in this series, and nowhere am I claiming the language to be bad. It's up to how we use it! Now, what would have made any one think that I think this language is bad? Could it be the title? 🙃
Again, it's the code that's insecure. Not the language. So let's follow best practices to keep our insecurities to a minimum. I have benefitted greatly by following Symfony when I started coding PHP, but it's easy to just code and implement features and not keeping security in the front. So leaning against a handrail to guide us right is good. But again, that's not what this shift article was about. But I welcome anyone to discuss best practices.
Thanks for the clarification.
Yes and no.
The article does mention things that are not handled on any respect by PHP (eg csrf, xss).
But PHP does have a mixed responsibility legacy.
In just about any other language, you have a clear separation between the platform whose job is to execute code written in the language.
It's often clear cut. Compiled languages are executed by the is (or some VM). Or some runtime.
PHP is a different story in that it needs at least the interpreter (to execute via CLI) but generally you need a webserver or fastcgi proxy that can interact with the platform (fpm or module that interacts with interpreter).
Each moving part has its own security issues and challenges and building a secure PHP execution chain requires knowledge in all of them.
Writing secure code in PHP is only a part of the issue, much less so than with other languages.
The headline isn't much to argue about. The articles in this series often references a Christmas song or something along those lines. Sometimes I just can't figure one out, but this one is just "It's the most wonderful time of the year". I don't actually think PHP is particular insecure. It's just as unsecure as most others, and it is just as you say a tool for the user to do with as they will. They can use it terribly wrong, or just about right. This article dealt with a minor detail that some may get wrong. Having 24 articles on this series has meant that I've kept these incredibly tight.
And in closing, this is not to spread bad mood around PHP. This entire article series is about the opposite. I like PHP, and too many articles are written about its bad sides.
Forgive me, but I've read a ton of articles about how bad PHP is. Many of them by authors who used PHP for their personal page project back in summer 2000. The article gave me an impression of being one of those. I read "The most insecure code" ... and the open it ... and PHP comes out.
The title is catchy and simply misleading. I dislike that in any form of jurnalism.
The article itself does give a view on a security apsect related to PHP though, for which I am thankful. It's always good to educate about security flaws.
Yeah, you're not alone in that. Despite the very catchy title, it was just a mishap of me trying to tie it in with the theme of this article series that I'm writing. I appreciate you reading the article through and I'm going to make sure to keep a more balanced title in my other articles.
I don't know that PHP itself is particularly well-known as being bad for security these days. Most of the PHP flaws come from the PHP frameworks like WordPress. And I'm happy to say that I've gotten rid of all the WordPress in my company, and that we will no longer be using it.
I've seen plenty of decent Laravel code. PHP itself is a capable language that, as demonstrated, can be used safely. Like any language, knowing defensive coding techniques is important. I have some other beefs with PHP, but I don't view the language itself as being inherently insecure.
WordPress isn't really a "framework" in the traditional sense and the core WordPress application isn't really the issue either. It's mostly the incredibly bad third party plugins you install into WordPress to extend its functionality. But I understand what you're getting at.
Wordpress is a CMS or an ecosystem, but not a Framework. 😀 Laravel or Symfony devs find the difference to be important distinction. Same goes for Drupal, although it uses a lot of Symfony components, it is not a "PHP Framework". A good analogy is CraftCMS which is built with the Yii PHP Framework.
Yes. Anyone keeping up to date knows that PHP isn't particularly different from other languages when it comes to security.
The easy way users can install WP plugins is one of its major features and also one of its drawbacks. But I'd be puffing air if I said how WP keeps up with security and performance issues associated with that.
Yeah, Laravel (and Symfony) enforces some good coding practices. It has been a good handrail to lean against when I started with PHP.
I'm curious what you went with instead of WP in your business, if I may ask?
We didn't really use WP for much more than a blog, carousel and contact form. These are easily implemented by a number of low-code/no-code solutions like WebFlow and Wix. In general, we're seeing a trend of static sites moving to these sites as well as HubSpot and I'm supportive of this effort since I prefer servers I don't have to manage :)
As a non prof, I can easily say that if you coding an index.php like the examples here on top 'why you want to do that in php?'! If you follow the OOP way, you will have your data somewhere else in a php class that has a '__toString' method. Then in your index, all you have is 'echo new path/to/class.php' and there is nothing to worried about! This is also approachable in wp!
Answer: They would all get an error page.
You'd only get the PHP source if the web server was running AND was not configured to handle .php files in any specific way or the .php handler didn't actually process the script.
So this situation isn't really that common except for when you're initially configuring the web server and haven't set up PHP yet, but in those cases, you wouldn't typically have a lot of PHP code with sensitive data just sitting in the document root on a public server. If you do, the first person deserving any blame is the server admin.
The far more likely scenario is a script that takes a filename from user input and reads that file's contents into the output. That kind of thing happens all the time with novice developers
Thank you for this counter-point, Jonathan. It's indeed not a common occurence, and we should hardly be storing sensitive data like this. Let Olaf be a secret for now!
What about me? I can just recommend everyone to use a framework, even for the most trivial tasks. It's incredibly easy to get things wrong in PHP and frameworks somewhat mitigates the issue. There are plenty of small frameworks that don't add too much overhead to your project, so that shouldn't be the deciding factor against a framework - ever.
Exactly. Use frameworks and read their dox. Anything respectful will do, like Laravel, Symfony, even Nette. If you need raw power, use Slim, it's bare bones. Even with Laravel or Symfony the apps may still be made very light.
I don't consider php unsafe these days. index.php must be a front controller. the programmer in this case is the problem.
Yes. And this is the way I would have coded if I didn't get hooked on PHP and just satisfied myself with the first tutorial I completed. I would not be surprised if you've seen the like: we don't need controllers, because each PHP file corresponds to a page on our website. It's the fast and easy way to get started with PHP. It took me starting with Symfony and learning about how we do mvc in PHP that turned me around.
PHP is an easy language to learn badly.
That's a really good way to put it!
Sure, let's switch to nodeJS and load up 10k packages from who-knows-what sources that are safe just to show "hello world" code :)
Come on, this is such clickbait. This isn't a security flaw at all. Only way this could happen is disabling php or php-fpm or anything, then letting apache/nginx deliver php files as html ones. Can't see how that could happen on a normal environment.
dev.to/andersbjorkland/overview-th...
Perhaps you will see that I would not argue any such thing.
Anders I like the Christmas PHP series 🐘🐘🐘
Thank you so much Logan! This makes Santa happy 😁
Please don’t post things like that. It’s not an issue of php. It’s only confusing and is not related to a real use case. You are creating an artificial problem and blame the language for that
I'm not blaming the language at all, Emil. I think PHP is great and I think it's up to us as coders to use the language correctly. Storing secrets in public is a silly idea, no matter what language we are in.
Sorry, I might have seen this to pragmatic. I thought like „how the hell would someone do something like that“ 😂 but you explained the case very well
It's alright 😅 Someone else put it pretty succinct: it's easy to learn PHP wrong. And I think that is one of the best reflections on PHP I have heard in a while.
What kind of idiot puts secrets in code?
Use environmental variables.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.