I call my main page framework_ui.php in it I require auth.php where I have a filter function.
function filter($data)
{
// normalize $data because of get_magic_quotes_gpc
$dataNeedsStripSlashes = get_magic_quotes_gpc();
if ($dataNeedsStripSlashes) {
$data = stripslashes($data);
}
// normalize $data because of whitespace on beginning and end
$data = trim($data);
// strip tags
$data = strip_tags($data);
// replace characters with their HTML entitites
$data = htmlentities($data);
// mysql escape string
$data = mysql_real_escape_string($data);
return $data;
}
and on every page with get and post variables I do a: (and call my framework.php)
// filter GET values
foreach ($_GET as $key => $value) {
$get[$key] = filter($value);
}
// filter post
foreach ($_POST as $key => $value) {
$post[$key] = filter($value);
}
Will the function still operate properly if I make the above a function and call that instead on every page?
function filter_all() {
// filter GET values
foreach ($_GET as $key => $value) {
$get[$key] = filter($value);
}
// filter post
foreach ($_POST as $key => $value) {
$post[$key] = filter($value);
}
}
I understand this is not the most secure way, however I was wondering if this sort of thing was possible and wouldn't negatively effect my code.
Your filter_all() function returns nothing and it does not modify the $_GET and $_POST globals so after your function finishes to run those original variables your foreach looping through will be effectively the same. You should either manipulate $_GET/$_POST directly or global $get/$post if you plan on using them or return some combination of the two. Other than that there's nothing necessarily negative about what your planning to do.
If you are going to be doing this every time might as well not make a function and just include a file (like your framework_ui.php) which just does the loopage and filters the variables.
zerkms is correct though your filter function is not ideal in that it is not secure and in fact that mysql_real_escape_string will cause issues if you plan on re-displaying user submitted info back (among many other things).
To quote the OWASP ESAPI project page:
Don't write your own security controls! Reinventing the wheel when it comes to developing security controls for every web application or web service leads to wasted time and massive security holes. The OWASP Enterprise Security API (ESAPI) Toolkits help software developers guard against security‐related design and implementation flaws. http://code.google.com/p/owasp-esapi-php/
You just have to make some tweaks to ensure the 'filtered' values are available to the rest of your code. There are a couple of ways to do it, marking them as global or returning them; probly the second option is generally considered cleaner. Here's an example:
function filter_all() {
$get = array();
$post = array();
// filter GET values
foreach ($_GET as $key => $value) {
$get[$key] = filter($value);
}
// filter post
foreach ($_POST as $key => $value) {
$post[$key] = filter($value);
}
return array(
'get' => $get,
'post' => $post);
}
$aFilteredInput = filter_all();
$get = $aFilteredInput['post'];
$post = $aFilteredInput['post'];
Related
I am currently trying to create a simple template engine in PHP. The main thing I care about is security, however template tutorials do not. Lets say I have a database table with a username and his description. The user can type whatever he wants there.
My guess would be to use htmlspecialchars() function, to prevent javascript and html injection. But what about 'template code injection'? If my template rule is to replace [#key] to "value", the user can update his description that interferes with my template handler. Should I treat "[", "#", "]" as special characters and replace them with their ascii code when using my set method?
template.php:
class Template {
protected $file;
protected $values = array();
public function __construct($file) {
$this->file = $file;
}
public function set($key, $value) {
$this->values[$key] = $value;
}
public function output() {
if (!file_exists($this->file)) {
return "Error loading template file ($this->file).";
}
$output = file_get_contents($this->file);
foreach ($this->values as $key => $value) {
$tagToReplace = "[#$key]";
$output = str_replace($tagToReplace, $value, $output);
}
return $output;
}
}
example.tpl:
Username: [#name]
About me: [#info]
index.php:
include 'template.php';
$page = new Template('example.tpl');
$page->set('info', '[#name][#name][#name]I just injected some code.');
$page->set('name', 'Tom');
echo $page->output();
This would display:
Username: Tom
About me: TomTomTomI just injected some code.
The code I used is based on:
http://www.broculos.net/2008/03/how-to-make-simple-html-template-engine.html
Change your function to search in the unchanged template only once for the known keys:
public function output() {
if (!file_exists($this->file)) {
return "Error loading template file ($this->file).";
}
$output = file_get_contents($this->file);
$keys = array_keys($this->values);
$pattern = '$\[#(' . implode('|', array_map('preg_quote', $keys)) . ')\]$';
$output = preg_replace_callback($pattern, function($match) {
return $this->values[$match[1]];
}, $output);
return $output;
}
I was thinking about it and I think this solution is fastest and simplest:
foreach ($this->values as $key => $value) {
$tagToReplace = "[#$key]";
if (strpos($output, "[#$value]") !== FALSE)
$value = '['.substr($value,1,-1).']';
$output = str_replace($tagToReplace, $value, $output);
}
It replaces brackets in value with html entity string if [$value] is in output.
Used this html entity list
For future adopters:
This kind of solution is OK if Template Parser is implemented by loading non-interpeted/non-evaled file (as is OP's case by loading local file using file_get_contents). However, if it's implemented by INCLUDING PHP view, beware that this check won't handle the case when you put some user-modifiable data from database into view directly (without using parser, e.g. <?=$var;?>) and then use template parser for this view. In that case, parser has no way to know if these data are part of template structure and this check won't work for them. (I don't know how should this case be handled properly.) Anyhow, I think best practice is to never pass sensitive data to template parser, even if you don't use them in your template. When attacker then tricks parser to eval his custom data, he won't get information he didn't already have. Even better, don't use template parser.
How do you think about security in laravel 4 ? I mean how laravel is managing xss attacks ?
In codeigniter you have someting like xss_clean($_GET['yourValue']) to clean user input fom xss code.
How laravel manage those kind of problems ? You get user values using Input::get('yourValue') but how do you apply an xss filter to it ? It comes with this functionality out of the box or what ?
You can use App::before event to filter all of your inputs like this
App::before(function($request)
{
Input::merge(array_strip_tags(Input::all()));
}
The array_strip_tags function is given below, I've put it in a helper file to call it directly, you may use it as a helper function or as a library but it's easy to use it as a helper function, just create a helper file inside app/start/ folder and give it a name, for example custom_helper.php and include it inside global.php file like this
require '/custom_helpers.php';
Function array_strip_tags
function array_strip_tags($array)
{
$result = array();
foreach ($array as $key => $value) {
$key = strip_tags($key);
if (is_array($value)) {
$result[$key] = array_strip_tags($value);
}
else {
$result[$key] = strip_tags($value);
}
}
return $result;
}
This is copied from an working project of mine.
In laravel templates, any data that comes form user input should be enclosed in three curly braces to sanitize it:
<h1>{{{ $input }}}</h1>
There's no native xss clean function in Laravel, but if you're desparate for one there is a port of the codeigniter security library available here:
http://packalyst.com/packages/package/gvlatko/laravel-xss
Here is how I solved this. Inspired on #the-alpha's solution. I'm using Laravel 4.2.
app/start/global.php:
function array_strip_tags($array)
{
$result = array();
foreach ($array as $key => $value) {
$key = strip_tags($key);
if (is_array($value)) {
$result[$key] = array_strip_tags($value);
}
else {
$result[$key] = strip_tags($value);
}
}
return $result;
}
app/filters.php:
Route::filter('strip_tags', function()
{
Input::merge(array_strip_tags(Input::all()));
});
app/routes.php:
Route::group(array('before' => 'strip_tags'), function(){
// all routes under this route group will get all their inputs passed through the strip_tags php's function
Route::any('/', ['as' => 'home', 'uses' => 'PageController#anyHome']);
Route::any('/some-page', ['as' => 'some-page', 'uses' => 'PageController#anySomePage']);
}
Create a new Helper file and put these two methods in you helper.
public static function globalXssClean()
{
// Recursive cleaning for array [] inputs, not just strings.
$sanitized = static::arrayStripTags(Input::get());
Input::merge($sanitized);
}
public static function arrayStripTags($array)
{
$result = array();
foreach ($array as $key => $value) {
// Don't allow tags on key either, maybe useful for dynamic forms.
$key = strip_tags($key);
// If the value is an array, we will just recurse back into the
// function to keep stripping the tags out of the array,
// otherwise we will set the stripped value.
if (is_array($value)) {
$result[$key] = static::arrayStripTags($value);
} else {
// I am using strip_tags(), you may use htmlentities(),
// also I am doing trim() here, you may remove it, if you wish.
$result[$key] = trim(strip_tags($value));
}
}
return $result;
}
Then put this code in the beginning of your before filter (in Laravel 4 it should be in app/filters.php).
App::before(function($request)
{
Helper::globalXssClean();
});
I believe Laravel doesn't, unfortunately, have a built-in XSS Filter. However, there's a package you can try laravel-xss and it's easy to use, you just need to do something like: $user->about = Xss::clean(Input::get('about'); and you're set to go!
There is also another package for XSS filter for laravel which can be downloaded here
Usage Example:
Simple form code snippet
{{Form::open(['route' => 'posts.store'])}}
{{Form::text('title')}}
{{Form::textarea('body')}}
{{Form::submit('Post')}}
{{Form::close()}}
Filter package usage
$rules = ['title' => 'required|min:13', 'body' => 'required|min:150'];
$validator = Validator(Input::all(), $rules);
if($validator->passes()){
$xss = new XSS;
$xss->clean(Input::all());
$input = $xss->get();
$post = new Post;
$post->title = $input->title;
$post->body = $input->body;
// to test the results you can dd($input); & happy coding everyone!
}
I examined the Laravel's protection {{{...}}} against xss attack. It just uses the htmlentities() function in the way like this: htmlentities('javascript:alert("xss")', ENT_QUOTES, 'UTF-8', false); This protects you against xss only if you use it properly means dont use it in certain HTML tags because it will result in XSS attack possibility. For example:
$a = htmlentities('javascript:alert("xss")', ENT_QUOTES, 'UTF-8', false);
echo 'link';
In this case, your code is vulnerable to xss.
I'm trying to save a long form in Codeigniter's Datamapper. I'm able to save the form if I pass the value like this
$t->brandName = $this->input->post('brandName');
$t->specialNotes = $this->input->post('specialNotes');
$t->name = $this->input->post('name');
Now if I call save method it works
$t->save();
Since the form is big I tried to add object values in foreach
$a = get_object_vars($t);
foreach ($a['stored'] as $k => $val){
$t->$k = $this->input->post("$k");
}
however if I call the $t->save() it doesn't work.
I'm not sure what $a['stored'] represents, but it's nothing that's default in Datamapper.
Why don't you do it the opposite way, looping through the post keys?
foreach ($_POST as $key => $val)
{
$t->$key = $this->input->post($key);
}
$t->save();
Note: Any columns that don't exist will just be ignored by Datamapper.
I actually wrote a Datamapper extension for this:
class DM_Data {
function assign_postdata($object, $fields = NULL)
{
// You can pass a different field array if you want
if ( ! $fields)
{
$fields = $object->validation;
}
foreach ($fields as $k => $data)
{
$rules = isset($data['rules']) ? $data['rules'] : array();
if ( ! isset($_POST[$k])) continue;
// Cast value to INT, usually for an empty string.
if (in_array('integer', $rules))
{
$object->$k = (integer) $_POST[$k];
}
// Do other manipulation here if desired
else
{
$object->$k = $_POST[$k];
}
}
return $object;
}
}
You can use $t->assign_postdata()->save(), and optionally pass an array of fields to update to the function (in the datamapper validation format). However, I forget why I use that... but I removed some of the custom stuff. This should be useful for you if you are doing this a lot. It definitely saves me time.
I am writing a library for CI and I have a method I call to gather all possible post variables. I would somehow like to leverage the xss and security classes built into the codeigniter input class.
Is that possible?
Here is the working method without any use of the CI input class.
private function parse_options()
{
foreach($_POST as $key => $val)
{
$options[$key] = $val;
}
return $options;
}
Why not then:
private function parse_options()
{
foreach($_POST as $key => $val)
{
$options[$key] = $this->input->post($key);
}
return $options;
}
Some 8 years later..
The documentation (https://www.codeigniter.com/user_guide/libraries/input.html) says this:
$this->input->post(NULL, TRUE); // returns all POST items with XSS filter
$this->input->post(NULL, FALSE); // returns all POST items without XSS filter
The reason for trying to only do it the ci-way and not bypassing ci is to keep things uniform. Likely.
I need to create a column-system for Wordpress with shortcodes, which is not a problem, but I'm trying to make it with less code.
I have an array with the data needed, I loop through it, create a unique-named function and set it as shortcode-function. The third step is a mystery. How can I create a function from a variable.
Here's an example, how it should be done:
$data[] = "first";
$data[] = "second";
foreach($data as $key => $value) {
function $value($atts,$content) {
return '<div class="'.$value.'">'.$content.'</div>';
}
add_shortcode($value,$value);
}
However, it seems that it's not possible to make it work like that in PHP. Is there any way to make this work, as I would not want to write all the (identical) functions separated. I could make the shortcode something like [col first]text[/col] but the client wants to have different names for every one of them.
you can use the double dollar syntax to use the value of a variable as a variable identifier,
Example:
$variable = "test";
$$variable = "value of test"
echo $test; //or echo $$variable;
I have never tried but you way want to try:
foreach($data as $key => $value)
{
function $$value($atts,$content)
{
}
add_shortcode($value,$value);
}
or a function like create_function
if your using PHP 5.3 or greater then you can do something like so:
$$value = function()
{
}
which should work fine
I'm not sure how WP invocates the functions, but if it uses call_user_func then you might cheat by using an object with virtual methods:
class fake_functions {
function __call($name, $params) {
return '<div class="'.$name.'">'.$params[1].'</div>';
}
}
$obj = new fake_functions();
foreach ($data as $value) {
add_shortcode($value, array($obj,$value));
}