Page 2 of 3
Posted: Mon Jun 07, 2004 6:09 am
by dave420
Security risk can increase with complexity, but giving what is essentially a templating engine access to the entire functionality of the PHP language
is a huge security risk

A mal-formed template could theoretically destroy your machine, and any others it can get its hands on. A bit sensationalist, true, but possible none-the-less.
True, regexps are more complicated, but their strength lies in the fact they can match *exactly* what you specify, kind of like how a key has to fit precisely in a lock, your templates have to fit in well-defined boundaries set by your patterns. That lets you specify exactly what can constitute a template. There is no way to sneak code into your PHP engine this way. With your eval-ing of code, if (somehow) an unrelated PHP script got caught up in your template (through controller error, bad memory, fudged keystrokes or whatever), you would end up executing it (which, needless to say, is rather bad).
I'm not saying your method is bad, but there are more precise (and secure) methods for achieving the same goal. Also, regular expressions are one of the most useful tools in the PHP toolshed. If you can master them for this, you will be unstoppable. Eval is one of the least useful tools, as it really does function as a crutch when programming logic fails (which isn't a bad thing in itself, as it serves as a sanity check

- "Wait - I'm eval()ing something here - I must have missed something")
Posted: Mon Jun 07, 2004 11:19 am
by Buddha443556
dave420 wrote:I'm not saying your method is bad, but there are more precise (and secure) methods for achieving the same goal.
I'm not saying regexp Template Engines are bad either. As I said, if I needed them, I would use them. The complexity of the solution should fit the problem. I don't need many of the benefits of a full blown template engine.
As for being more secure? My template system (I use the word "system" loosely here because it's
just PHP) has one funtion, Smarty (Not picking on them, they're just the best example of a regexp Template Engine) has 181 functions. That's 181 places to look for holes.
Every nail doesn't needs a 12 pound sledge hammer.
Posted: Tue Jun 08, 2004 3:36 am
by dave420
No, but if your one hole is the same size as PHP, which if your using eval it is, then you are more at risk compared to using a templating engine of a different nature. The fact that eval() has no intrinsic security (that is, everything is just executed "as is", with no sanity checking) means even though it's effective as a templating engine, it's so open to abuse it's amazing. As I said, one malicious or accidentally-corrupted template could destroy your system. Using a regexp solution (which is not difficult at all), there is no such thing as a malicious template, and an accidenally-corrupted template can only cause bad output. The regexp solution explicitly defines what a template can and can't do. Using eval means that definition encompasses every single thing PHP can do, which is a LOT.
Posted: Tue Jun 08, 2004 3:47 am
by patrikG
What I don't understand is why anyone (including me) hasn't just written a filter that filters out selected PHP-commands and functions. Then you could easily and selectively disable PHP-functionalities in a template while retaining the PHP's power. No need for another parser, no need for any iterator with funky syntax - just plain old PHP, only limited.
The wheel needs no re-inventing, imho.
Posted: Tue Jun 08, 2004 4:02 am
by dave420
Patrick - instead of defining what functions can't be used, just define what functions can. That is effectively a template engine

I think people believe a template engine is a complicated thing. It's not. I use mine like this:
Code: Select all
$t=new template("my_template.html");
$t->addReplace("myName", "dave420");
$t->addReplace(array("weather"=>"cloudy", "temperature"=>"22C"));
echo $t->render();
The engine itself is rather simple, and achieves 100% seperation of HTML and PHP (which eval()ing doesn't). All you do is match your template commands and replace with the desired output. Just a couple of for loops tied to a preg_replace_callback. It's so simple. You end up with HTML templates that are actually HTML documents, as opposed to a mishmash of PHP and HTML stuck together. You can give your HTML templates to web developers to change, safe in the knowledge they can upload their own changes without wiping half of the internet clean off the face of the planet.

Posted: Tue Jun 08, 2004 4:07 am
by patrikG
Either way - I fail to see why few people use filtered PHP including simple iterators. Template engines per se create overhead. PHP doesn't. And instead of a the alien syntax of the template-engine, designers could just use well documented code bits of PHP - even, and very easily, from Dreamweaver.
Anyway, the bottom half of
http://wiki.devnetwork.net/index.php/TemplatesTutorial sums up my opinion on templates-engines.
Posted: Tue Jun 08, 2004 9:53 am
by Buddha443556
dave420 wrote:The engine itself is rather simple, and achieves 100% seperation of HTML and PHP (which eval()ing doesn't).
dave420 wrote:You can give your HTML templates to web developers to change, safe in the knowledge they can upload their own changes without wiping half of the internet clean off the face of the planet.

Well there's two items I don't need in a template engine. All I want to do is seperate business logic from presentation. Also, as I said, I'm the only one editing my templates. For those reasons alone, I don't see a need for using anything as complex as your using.
Dave420, so far you haven't brought up any security concerns that are specific enough to change my mind. eval() can be misused however that doesn't mean it shouldn't be used. Just that caution is necessary.
patrikG wrote:What I don't understand is why anyone (including me) hasn't just written a filter that filters out selected PHP-commands and functions. Then you could easily and selectively disable PHP-functionalities in a template while retaining the PHP's power. No need for another parser, no need for any iterator with funky syntax - just plain old PHP, only limited.
The wheel needs no re-inventing, imho.
There are two php.ini configuration directives that would serve that purpose, disable_functions and disable_classes. However, they're PHP_INI_SYSTEM. Of course if your going to be processing a large number of templates, for say a free hosting service, then setting up a seperate PHP for them might be worth the preformance gain over regexp.
Posted: Thu Jun 10, 2004 3:39 am
by dave420
Buddha - don't get me wrong - I'm not criticising anyone/thing here. All I'm pointing out is that using eval() is fraught with security hazards. I haven't given you a single explicit scenario, because as it's PHP, there are thousands (every single command in PHP that can change something can be used to attack your system. You can't provide a defense against something that large).
The easiest way isn't always the best way. eval() can be used very often, commonly as a quick hack to get around developing some more complicated logic. I guess it's up to you if you want to progress as a programmer or take the shortcut.
You mention you want a seperation of business logic and display, which is exactly what I'm talking about. Your method doesn't have that, as it still keeps PHP with HTML (PHP=business logic, HTML=display). If you use eval(), you can never, ever seperate the two. That's the whole point of using a seperate parser - it's a logical barrier between the two, providing everything you've asked for, and security. Using eval() you'd have to specifically define functions you don't want being executed, and then write your own parser (or filter as patrikG called it) to ensure they don't end up in your template. As the PHP function library is constantly expanding, you'd have to keep on top of that to make sure no harmful commands can enter into your templates. With your own templating engine, you specifically give it the functionality you want (which, obviously, doesn't include the ability to format your hard disk, or launch a DoS attack on a server - two functions not needed in a templating engine for obvious reasons).
Posted: Thu Jun 10, 2004 8:20 am
by Buddha443556
dave420 wrote:Buddha - don't get me wrong - I'm not criticising anyone/thing here. All I'm pointing out is that using eval() is fraught with security hazards. I haven't given you a single explicit scenario, because as it's PHP, there are thousands (every single command in PHP that can change something can be used to attack your system. You can't provide a defense against something that large).
PHP is fraught with security hazards on this I hope we may agree. However, php templates don't introduce any new security hazards. Do they? PHP templates are just PHP scripts, same security hazards. Weather they're included or eval'ed it doesn't matter it still PHP and the same security concerns apply.
dave420 wrote:The easiest way isn't always the best way. eval() can be used very often, commonly as a quick hack to get around developing some more complicated logic.
I'm not say eval() can't be misused. I am saying the complexity of the solution should fit the problem.
In my application I don't need any thing more complicated than PHP templates. In your application you have desided you need something more complicated than PHP templates. I'm sure we're both right in our decisions for our particular applications. My point is the decision should be made on a project by project basis.
dave420 wrote:You mention you want a seperation of business logic and display, which is exactly what I'm talking about. Your method doesn't have that, as it still keeps PHP with HTML (PHP=business logic, HTML=display). If you use eval(), you can never, ever seperate the two. That's the whole point of using a seperate parser - it's a logical barrier between the two, providing everything you've asked for, and security.
No PHP template don't seperate PHP and HTML, but in my application I don't need to seperate them. Not to say there aren't application where this kind of seperation may be desireable. However, I make such decision on a project by project basis.
Posted: Thu Jun 10, 2004 9:50 am
by redmonkey
Dave420 wrote:
PHP=business logic, HTML=display
While I'm sure there are many opinions on this, personally I would disagree that PHP = business logic.
My view is that PHP can be used for both business logic and presentation logic. Consider the following possible simple template....
Code: Select all
<table>
<tr>
<td>Username</td>
<td>Email Address</td>
</tr>
<?php
foreach ($users as $user)
{
echo "\t<tr>\n\t\t<td>" . $user['name'] . "</td>\n";
echo "\t\t<td>" . $user['email'] . "</td>\n\t</tr>\n";
}
?>
</table>
In this case we are using PHP for the sole purpose of generating a table of users. This I would class as presentation logic, for me personally I would see no need to remove the PHP from this template.
However, consider the following.....
Code: Select all
<table>
<tr>
<td>Username</td>
<td>Email Address</td>
</tr>
<?php
$asize = count($users);
for($i=0; $i<$asize; $i++)
{
$sortarr[] = strtolower($users[$i]['name']);
}
array_multisort($sortarr, SORT_ASC, $users);
foreach ($users as $user)
{
echo "\t<tr>\n\t\t<td>" . $user['name'] . "</td>\n";
echo "\t\t<td>" . $user['email'] . "</td>\n\t</tr>\n";
}
?>
</table>
I would consider this a mix of business logic (the sorting of the usernames) and presentation logic (the displaying of the user table).
The only other way to get things like loops into your template is to use some sort of pseudo templating code which in itself is merely an absraction layer to PHP which means that you are introducing another processing layer. For this reason I personally have no objection to using straight PHP code within templates. I do agree that your code should be seperated but only to the extent that business logic should be seperate from presentation logic.
Posted: Thu Jun 10, 2004 10:25 am
by magicrobotmonkey
Yea, i think php as only business logic is a nice ideal, but its just not worth it because it just makes your life a lot more difficult! redmomkey's simple temple is a great example of this!
Posted: Thu Jun 10, 2004 5:18 pm
by d3ad1ysp0rk
redmonkey, real seperation would have you go:
Code: Select all
<table>
<tr>
<td>Username</td>
<td>Email Address</td>
</tr>
<?php echo $variable; ?>
</table>
and build $variable in your bussiness logic
Posted: Thu Jun 10, 2004 6:56 pm
by redmonkey
LiLpunkSkateR wrote:redmonkey, real seperation would have you go:
Code: Select all
<table>
<tr>
<td>Username</td>
<td>Email Address</td>
</tr>
<?php echo $variable; ?>
</table>
and build $variable in your bussiness logic
So what would happen if you wanted to offer two or more display options?
For example you could have one template for standard web browsers and offer a simplified view for WAP/Portable device users. Adopting your method, you are not seperating presentation from business logic, and further more if you wanted to offer a simplified version you would then have two templates and have to add a conditional statement within your business logic to build the appropriate $variable dependant on the users choice of display.
Consider the following.....
A rich HTML version....
Code: Select all
<table>
<tr>
<td>Username</td>
<td>Email Address</td>
</tr>
<?php foreach ($users as $user) : ?>
<tr>
<td><?php echo $user['name'] ?></td>
<td><?php echo $user['email'] ?></td>
</tr>
<?php endforeach ?>
</table>
A simple HTML version....
Code: Select all
<?php foreach ($users as $user) : ?>
<br />
Name - <?php echo $user['name'] ?>
<br />
Email - <?php echo $user['email'] ?>
<br />
<?php endforeach ?>
A plain text version....
Code: Select all
<?php foreach ($users as $user) : ?>
Name : <?php echo $user['name'] ?>
Email: <?php echo $user['email'] ?>
<?php endforeach ?>
I could offer these three versions of the display by simply adusting my business logic to include a small code snippet to work out which template to load. With your approach you need to include the formatting for these three display versions within your business logic and have the three templates too. I fail to see how you can refer to your example as 'real seperation' of any type? If anything you are just creating more work for yourself, as not only have you combined your business logic with presentation logic (i.e. build $variable within the business logic) you have also made your presentation logic harder to maintain as the constuction of the table is now split across two files.
Posted: Thu Jun 10, 2004 7:55 pm
by d3ad1ysp0rk
No, because you could test the users input and build the variable dependant on that, IN your templating engine, where it belongs.
[edit]Also, all you'd need is 3 different templates, and include one depending on their selection. (rich, plain, text).
Posted: Thu Jun 10, 2004 8:47 pm
by redmonkey
The main purpose of your template engine should be to assign variables to the choosen template file then parse the template file to produce your output.
Any layout information should be defined in your template file. While you may have various widget libraries for building common table structures, drop down boxes etc.. these should not be integral to the main templating engine.
LiLpunkSkateR wrote:
No, because you could test the users input and build the variable dependant on that
As I said, you seem to require a conditional statement to be able to build the relevant presentation source (HTML, plain text etc...) for inclusion within your template. For me, this should not be built in the business logic and I also see no sense or practicality by building this within the main template engine.
LiLpunkSkateR wrote:
Also, all you'd need is 3 different templates, and include one depending on their selection.
Not quite, see above, you still have to build $variable somewhere?