Recently I had to improve mailing system of an existing prestashop platform. It was based on 126.96.36.199 version, released on 2009-08-27. The task was to use a gmail account over SMTP to authorize e-mail sender. It seems quite easy thanks to the swift mailer, which is included in prestashop package (prestashop 188.8.131.52 used swift 3.3.2). Unfortunately, the task turned out to be very painful since swift mailer was included in prestashop in a very bad way. Each time I tried to connect to the smtp service I was redirected to the project homepage with absolutely no errors, no logs and no any kind of information provided. But this was just the tip of the iceberg - the main problem was (and still is) elsewhere.
bubble index.php redirect
It's a security technique, adapted by prestashop, trying to block unwanted access to the file structure. The mechanism is based on a simple index.php file containing following code:
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); header("Location: ../"); exit;All directories inside the project, no matter where or how deep inside the file structure they are, contain this obligatory index.php file. The workflow is really simple - if you make a request (e.g. from a browser) to an existing directory (different from the root directory of the project) you'll step on the index.php that redirects your browser one directory up. There you'll step on another index.php file. You go up and up like a bubble in a water pool, until you get to the top level directory (could be document root), where the index.php controller file resides - it will generate the homepage. The browser will not display the entire redirecting route - it'll just load the homepage.
and my problem was
... that Swift Mailer stepped on index.php bubble each time a mail was going to be sent. And it was really frustrating and time-consuming to spot such bug.
If no authenticators are set before the SMTP session is started, Swift tries to handle it by himself. Swift iterates through all PHP files inside the
Swift/Authenticator directory: loads them and tries one by one to authorize. Swift 3.3.2 authenticators directory contains:
PopB4Smtp.php and... index.php bubble. The solution was to replace:
if (preg_match("/^[A-Za-z0-9-]+\\.php\$/", $file))with:
if (preg_match("/^[A-Za-z0-9-]+\\.php\$/", $file) && $file != 'index.php')
As I said before, problem with badly included Swift Mailer is just the tip of the iceberg. The main problem in my opinion is using the "bubble redirect" system...
is it secure?
Let's focus on the weaknesses that a potential attacker could use. First of all, all PHP and other files are still accessible from the browser. Moreover, all those file paths are very easy to track. It's not difficult for a PHP developer to find out that a shop is based on the prestashop engine (routing should be enough to determine this, especially that routing is not configurable). Just download a prestashop package to discover entire file structure, which is probably unmodified in most of the shops available online (prestashop's aim is to be used mainly by non-PHP-developers so original structure will probably be kept). If any major prestashop security bug will be tracked in future, all online shops based on older versions will be defenseless.
Another danger is the (almost) omnipresent
chmod -R 777. Prestashop installer script forces the user to grant recursive writable permissions to most of top level directories of the project.
how about a better solution?
The following question arises: how about virtual hosts and setting the document root to the public directory of the project? Such approach is adopted in most PHP frameworks (e.g. cakePHP or all versions of symfony framework: 1 and 2). Hiding files (moving them outside the document root) disables direct access to the files, which dramatically reduces the risk of a successful attack. Another possibility is to use
.htaccess files among project file structure.
The above approach is clearly defined in the PHP manual security chapter. Ocrow wrote:
[...] The most robust way to guard against this possibility is to prevent your webserver from calling the library scripts directly, either by moving them out of the document root, or by putting them in a folder configured to refuse web server access. [...]
Note that it was submitted in 2003...
virtual hosts? how about shared hosting limitations?
Most shared hosting providers allow their customers access to the
/home/user directory where they can put whatever they want and it won't be accessible directly from the web. Only
/home/user/public_html (or a similar directory) is accessible. And it is feasible to design the installer script to copy or move the files outside the document root - PHP will need only the autoloader properly set. Or use
prestashop 1.5 still uses bubble redirect
The only thing that changed, concerning above topic, is a three-line comment inside the swift mailer included. If you look at
tools/swift/Swift/Authenticator/index.php, you'll find:
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); // The header location has been commented because swift do a require() on each .php of this folder // (and this relocation make it do it recursively on each PrestaShop folder and so PrestaShop PHP file) //header("Location: ../"); exit;
Well, this is not a solution. It's just a problem workaround. I understand, that a PHP framework is a complex tool and is used by programmers who can adopt webserver features, chmod directories and so on - and e-commerce package should be easy enough to be installed by an average internet user. But "bubble index.php redirect" is not the best way to secure the application code.
it doesn't mean that prestashop is bad, though...
I want to make it clear: I do appreciate all the hard work the prestashop team has done already (really)! Prestashop is becoming more and more popular - it's a great success. And I'm a prestashop user/developer after all :). Anyway, I strongly encourage the developers team to discuss the security topic and the installer script.