Cookie (un)serialization in Laravel 5.5.42 - php

Security release 5.5.42 "disables all serialization / unserialization of cookie values" - https://laravel-news.com/laravel-5-6-30
But I have my values serialized still, only not unserialized. While I do
Cookie::get('key')
I get something like
"s:5:"value";"
Setting protected static $serialize = true; in App\Http\Middleware\EncryptCookies helps, and so does
unserialize(Cookie::get('key'))
But as I understand unserialize() itself is the source of the problem with this security release, not what I do with the unserialized value later, so this kinda beats the purpose of the update.
Why are my cookies serialized here and how to fix this?

This is actually worth an answer as the question itself is quite interesting.
From a Laravel perspective this isn't a cookie problem as much as it's a APP_KEY config key problem combined with serialize/unserialize.
Relevant quote from the docs:
However, if your application's encryption key is in the hands of a
malicious party, that party could craft cookie values using the
encryption key and exploit vulnerabilities inherent to PHP object
serialization / unserialization, such as calling arbitrary class
methods within your application.
The relevant part is this vulnerabilities inherent to PHP object serialization / unserialization.
Usually the form of explot is Object Injection(the most common at least).
OWASP has a very good example here.
Even php.net has a red warning for it's unserliaze function.
Warning
Do not pass untrusted user input to unserialize()
Cookies come from a user and users are NOT to be trusted.
Since an example is in order I'll just leave the OWASP one here too:
class Example1
{
public $cache_file;
function __construct()
{
// some PHP code...
}
function __destruct()
{
$file = "/var/www/cache/tmp/{$this->cache_file}";
if (file_exists($file)) #unlink($file);
}
}
// some PHP code...
$user_data = unserialize($_GET['data']);
// some PHP code...
In this example an attacker might be able to delete an arbitrary file via a Path Traversal attack, for e.g. requesting the following URL:
http://testsite.com/vuln.php?data=O:8:"Example1":1:{s:10:"cache_file";s:15:"../../index.php";}
With that said, I highly recommend reading(even briefly) about serialize/unserliaze vulnerabilities.
If you're using a proper framework, usually, you'll have most security things taken care of IF you don't go out of your way to introduce some vulnerability and you stick to the framework's standards.

It's less efficient but in case of structured data, I replace serialize/unserialize with json_encode/json_decode.

Related

How well does Checkmarx understand PHP and libraries?

Sorry for the very broad question but we have some problems, e.g. Checkmarx is complaining about code injection in something like the following
$accesskey = $_GET['accesskey'] ?? $argv[1] ?? null;
if (!$accesskey || !ctype_alnum($accesskey)) {
throw new RuntimeException(sprintf('Passed accesskey "%s" is invalid', $accesskey));
}
$commandParts = ['echo', $accesskey]
$commandParts = array_map('escapeshellarg', $commandParts);
$command = implode(' ', $commandParts);
$command = escapeshellcmd($command);
system($command);
I think the commands are escaped and everything is fine but why is Checkmarx thinking different?
The application's <?php method calls an OS (shell) command with system, at line 1 of REDACTED, using an untrusted string with the command to execute.
This could allow an attacker to inject an arbitrary command, and enable a Command Injection attack.
The attacker may be able to inject the executed command via user input, _GET, which is retrieved by the application in the <?php method, at line 1 of REDACTED.
I'm also wondering if and how Checkmarx is able to understand library or framework code which is installed via Composer? E.g.
Assert::oneOf($unsafeUserInput, ['foo', 'bar']); // throws an Exception if $unsafeUserInput is not 'foo' or 'bar'
// $unsafeUserInput is now safe
or WP related stuff which is also often falsely flagged as being prone to SQL injections
global $wpdb;
$foo = $wpdb->getVar($wpdb->prepare('SELECT foo FROM bar WHERE baz = %s', $_GET['baz'] ?? ''));
If it checks for sanitisation methods is there a specific way they have to look? I honestly want to avoid changing too much code for Checkmarx.
Your question of how well Checkmarx analyzes PHP code could lean towards a subjective answer and your perception of the tool can be biased given that you are using methods (escapeshellcmd) that are not recognized as sanitizers and the framework that you are inquiring about (Wordpress and Composer) are not technically supported.
In fairness to Checkmarx, they do support a variety of PHP frameworks such as Zend, Kohana, CakePHP, Symfony and Smarty which could end in lesser false positives (note: I'm not suggesting you switch platforms)
Any static analyzers would need some help from it users for it to be effective. I would advice you to exclude the Composer files from the scan.
You don't really don't have to make changes to the code and just argue with your AppSec team that these findings are false positives since the prepare method prevent SQL injection attacks and that escapeshellcmd does encode string. My recommendation however is to use escapeshellarg on $accesskey instead

can we rely on laravel encryption for future?

We are building application where we need to store a data encrypted in database and instead of using MySql AES_ENCRYPT and AES_DECRYPT we are plaining to use laravel's inbuilt encrypt & decrypt functions.
Is it will be future proof as we don't want to loose data for future updates.
First of all, nothing is truly "future proof." In fact, we're on the verge of current encryption being rendered obsolete by quantum computing, making all current encryption methods very much not future proof.
Does Taylor have any plans of changing it in the foreseeable future? Maybe, maybe not, but the only real way of knowing is to ask him directly. He's quite active on Twitter and in other venues, so as far as business owners go, he's pretty approachable. He's also a generally nice person, so don't be afraid to ping him.
But let's take a look at the code:
public function encrypt($value, $serialize = true)
{
$iv = random_bytes(16);
// First we will encrypt the value using OpenSSL. After this is encrypted we
// will proceed to calculating a MAC for the encrypted value so that this
// value can be verified later as not having been changed by the users.
$value = \openssl_encrypt(
$serialize ? serialize($value) : $value,
$this->cipher, $this->key, 0, $iv
);
if ($value === false) {
throw new EncryptException('Could not encrypt the data.');
}
// Once we get the encrypted value we'll go ahead and base64_encode the input
// vector and create the MAC for the encrypted value so we can then verify
// its authenticity. Then, we'll JSON the data into the "payload" array.
$mac = $this->hash($iv = base64_encode($iv), $value);
$json = json_encode(compact('iv', 'value', 'mac'));
if (! is_string($json)) {
throw new EncryptException('Could not encrypt the data.');
}
return base64_encode($json);
}
That's the main encrypt() function from master in the repository, and from the looks of it, it's not likely to be changed too much without completely rewriting it. And while Laravel doesn't really follow the SemVer versioning spec, it does generally follow an internally consistent versioning scheme, making the most likely times for it to change are at the whole number and first-decimal change (i.e. - 5.4 to 5.5 or 5.5 to 6.0).
However, it's worth noting that it's actually accessed via contracts and the service provider pattern (so the only time the class is actually directly referenced is in its associated ServiceProvider class). This means that you can use this one for now and if a breaking change is introduced in the future, you can copy this version into your own encryption class, replace the reference in config/app.php to Illuminate\Encryption\EncryptionServiceProvider to your new encryption service provider, and you've now preserved that method and can use it throughout your application, without making any other changes to your application.
On a bit of a side note, you can also consider writing an "encryption converter" if you find you do need to change algorithms (such as if your original algorithm is insecure) by using the old system's decrypt method to decrypt everything, then re-encrypt it all with the new system and storing it again. The application would then just use the new algorithm going forward.

Securing controller PHP (MVC)

I know dynamically loading requested classes is extremely insecure, but it does save alot of complexity in my code...
Is this consider secure, or is there a way for the user to exploit this?
this is my code:
$currentPage = Classes\stdlib::GetVariable("view"); //Gets a variable from $_GET and escapes it...
$isAdmin = isset($_GET["admin"]);
$view = "";
$content = null;
$allowedViews = array("Admin","Brukere","Fag","Fravær","Kontakt","Login","Profil","Registrer");
if (in_array($currentPage,$allowedViews,true)) {
$view = "Views\\$currentPage";
$content = new $view(); // <--- This is usualy unsecure since its derived from user request
}
//Using $content later in the code....
This basically just loads the class if it is allowed (in_array).
What do you guys think? Major security hole or OK?
As Marc B. said including files with code like include($_GET['foo']) is not secure, because it is a file inclusion vulnerability. For example an attacker can upload a completely valid image file with PHP code in it and include it with this code by changing the value if the $_GET['foo']. So you can use include() only after you validated the input. There are several ways to do that, for example
$map = array('bar' => 'bar.php');
if (!isset($map[$_GET['foo']]))
throw new \Exception();
include($map[$_GET['foo']]);
or simply with an if-else
if ($_GET['foo'] == 'bar')
include('bar.php');
else
throw new \Exception();
Using autoload solves the same problem. It defines a rule how to build a class - file map, so it has a lower risk. For example by this vulnerable code:
$foo = $_GET['foo'];
$bar = new $foo();
$bar->doSomething();
he can only check what classes are available in your system, and probably use an available class against you with the doSomething() method. Which is still a security risk ofc, but not as huge as a file inclusion would be.
So by using classes you should do the same mapping or if-else as I wrote down at the beginning:
if ($_GET['foo'] == 'bar' && $_SESSION['isAdmin'])
$view = new Views\AdminView();
else
$view = new Views\RegularView();
$view ->doSomething();
I don't think having a list of allowed view classes is a best practice. I think you should do the authorization before querying your data. By rendering a view you usually already got some data from a database or from a file, but we don't want users without authorization to send that query, because it is completely superfluous and just eats up resources on the server.
In your code $isAdmin = isset($_GET["admin"]); is very strange. Everybody can set that parameter, so using it to decide whether somebody is an admin would be a very huge design flaw. Every variable coming from $_GET or $_POST can be faked (except OAuth request signatures and CSRF tokens :D). Try to learn more about sessions, authentication and authorization, and if you have further questions about security, you should ask it here: https://security.stackexchange.com/

PHP - Application config file stored as - ini,php,sql,cached,php class,JSON,php array?

I am trying to decide on the best way to store my applications configuration settings. There are so many options.
The majority of applications I have seen have used a simple require and a PHP file that contains variables. There seem to be far more advanced techniques out there.
What have you used?
What is most efficient?
What is most secure?
We use a file called Local.php which is excluded from the SCM system. It contains several constants or global variables. For example:
// Local.php
class Setting
{
const URL = 'http://www.foo.com';
const DB_User = 'websmith';
}
And it can be referred to anywhere simply by:
Setting::URL
If you need the settings to be writable at runtime, I suggest you use public static variables instead.
The best thing you can do is the simplest thing that could possibly work (php variables) and wrap it up in a class. That way you can change the implementation later without changing any client code. Create an interface that the configuration class implements and make the client code use the interface methods. If you later decide to store configuration in a database or JSON or whatever, you can simply swap out the existing implementation with a new one. Make sure your configuration class is testable and write unit tests.
Try to use php-arrays config files using technique described here: http://www.dasprids.de/blog/2009/05/08/writing-powerful-and-easy-config-files-with-php-arrays
This method allows you to write app configuration in this way:
app.config.php
<?php
return array(
'appname' => 'My Application Name',
'database' => array(
'type' => 'mysql',
'host' => 'localhost',
'user' => 'root',
'pass' => 'none',
'db' => 'mydb',
),
);
This method is secure, cache-able by opcode cachers (APC, XCACHE).
How about:
; <?php die('Direct access not allowed ;') ?>
; The above is for security, do not remove
[database]
name = testing
host = localhost
user = root
pass =
[soap]
enableCache = 1
cacheTtl = 30
Save as config.php (or something like that, must have php extention), and then just load it with:
parse_ini_file('config.php', true);
And you could use
array_merge_recursive(parse_ini_file('config-default.php', true), parse_ini_file('config.php', true))
to merge a default config file with a more specific config file.
The point here is that you can use the very readable ini format, but still be able to have your config file in a public directory.
When you open the file with your browser, php will parse it first and give you the result, which will just be "; Direct access not allowed ;". When you parse the file directly as an ini file, the php die statement will be commented out according to the ini syntax (;) so it will not have any effect then.
I find Zend_Config to be a good solution. You can load the configuration from a simple array, from an INI style file, or from an XML document. Whichever you choose, the configuration object is the same, so you can switch storage formats freely. Zend_Config objects can also be merged, depending on your application this may be useful (a server config, then a per site/installation config).
As with most (or all) things in the Zend Framework, you can easily use Zend_Config by itself.
Considering efficiency, I'd say the fastest method would be to use an array, since that requires less (in this case no) string parsing. However, a INI/XML format may be easier for some to maintain. Of course some caching would give you the best of both worlds.
Also, using INI files with Zend_Config allow you to define sections of configurations that inherit from each other. The most common use is a 'development' section that inherits from the 'production' section, then redefines the DB/debugging settings.
As for security, keeping the config file out of the web root is the first step. Making it read only and limiting access could make it more secure; however, depending on your hosting/server configuration you may be limited in what can be done there.
Just an example of how to implement a central XML/Xpath configuration.
class Config {
private static $_singleton;
private $xml;
static function getInstance() {
if(is_null (self::$_singleton) ) {
self::$_singleton = new self;
}
return self::$_singleton;
}
function open($xml_file) {
$this->xml = simplexml_load_file($xml_file);
return $this;
}
public function getConfig($path=null) {
if (!is_object($this->xml)) {
return false;
}
if (!$path) {
return $this->xml;
}
$xml = $this->xml->xpath($path);
if (is_array($xml)) {
if (count($xml) == 1) {
return (string)$xml[0];
}
if (count($xml) == 0) {
return false;
}
}
return $xml;
}
}
Example call
Config::getInstance()
->open('settings.xml')
->getConfig('/settings/module/section/item');
In my view good solution would be ini files.
I don't prefer config file using arrays/variables for storing settings; here is why:
What if a user accidently re-named your setting variable?
What if a variable with similar name is defined elsewhere too by the user?
Variables in config file may be overwritten some where deep in the script or even included files.
and possibly more problems....
I like to use ini file for setting of my php apps. Here is why:
It is section based
It is easier
You can set values by friendly names
You don't have to worry about variables being overwritten because there are no ones.
No conflict of variables of course.
It allows more flexibility in specifying the types of values.
Note: You need to use parse_ini_file function to read ini files.
It is best to do any core configuration in PHP itself, but if you are using a database and don't mind the extra overhead - you may find some flexibility in storing some settings in the database with a single extra query (assuming you organize it properly).
Either way, storing this data in JSON, INI, XL, etc is just another unneeded abstraction that is done way too much nowadays on the web. Your best bet is pure PHP, unless you like the flexibility of some settings being in the database.
The only reason I can think of to not use php vars as others are suggesting is if you need to switch between configurations in a controlled manner, so there data/behavior consistency during the switch. For example, if you're switching databases, then the system could write locked until the switch-over occurs (to prevent ghost-writes, but dirty reads are still possible).
If things like this are a concern, then you could write a special admin page in your app(pref local access only for security) that locks the system temporarily, then reads and deploys all your changes before unlocking.
If you're running a high traffic site where consistency matters, this is something you'll want to consider. If you can deploy during off hours when there is little/no traffic, then php vars or other standard text formats will be fine.
I like the idea of having "namespaces" or some kind of tree
so you can have:
db.default.user
or
db.readonly.user
and so on.
now regarding code what I did was an interface for the config readers: so you can have a memory reader, array reader, db reader, etc.
and a config class that uses those readers and allow you have a config from any kind of source

Constant server variables?

What's the easiest way of storing a single number on a server so that any script can access it, using PHP? Currently, I have a number stored in a file, but this seems somewhat inelegant.
There's no right answer here, but most modern PHP systems for building web applications have some kind of Configuration object. This is often implemented as a singleton
//brain dead config object
class NamespaceConfiguration {
public static function getInstance() {
if (!self::$instance instanceof self) {
self::$instance = new self;
}
return self::$instance;
}
public static function set($key,$value){
//code to set $key/$value paid
}
public static function get($key){
//code to get a $value based on a $key
}
}
$config = NamespaceConfiguration::getInstance();
$config->set('myNumber',42);
....
function somewhereElse(){
$config = NamespaceConfiguration::getInstance();
$myNumber = $config->set('myNumber');
}
This class is loaded on every page requiest. This gives every developer a standard API to call when they want to get or set single configuration values, and allows a single developer to control the where of storage and the how of retrieval (which may be a flat file, XML file, memory cache, MySQL database, XML file stored in a MySQL Database, XML File stored in a MySQL Database that contains a node which points to a file that contains the value, etc.)
The where and how of retrieval is going to depend on your application environment, although by using a configuration object you can create some efficiencies up front (storing already retrieved values in a property cache, pre-fetching certain values on instantiation, etc.)
Since your application probably already have some sort of include-file on the top "header.php" or simular, you could just create a constant/variable in that file, and all the files that include the header will also have access to the constant.
This may help you to define the constant:
http://php.net/constant
That depends on the characteristics of the number. Is it updated/modified often? Is it the only such number? If it isn't changed it's probably better to do as Espo suggests and store it as a php constant that can be included when necessary. If you have other such numbers you can put them all in that file. If they are updated often it's probably better to put it in the database.
But. If it's a single number, that is subject to change, and you don't forsee any need for storing other numbers, why not use a file? Just remember to use flock() when updating it to avoid concurrency issues.
Your best bet would be to put it in a MySQL table for fetching later. That's probably the best way to store information in PHP.
If it is a variable that is more of a environmental nature you could always use set those in Apache
in your httpd.conf file you can set the following:
SetEnv myVar myValue
You can then use $_SERVER to fetch it
$_SERVER['myVar']
I usually set varibles on this if i am to setup same application on a few different virtual hosts but dont want them to have different parameters in the config file.
A config file will also meet your needs.
There is some easy to use classes in Zend framework that can help out
http://framework.zend.com/manual/en/zend.config.html
more specific section 7.3 and 7.4 describes how you can write config parameters in a plain text file or in XML.
if you prefer plain old php you have the function parse_ini_file that lets you read in config parameters from a text file
http://us.php.net/parse_ini_file
You can also use the Alternative PHP Cache or other caching options.
http://www.php.net/manual/en/function.apc-add.php
And you can use this in combination with the other solutions listed above, e.g saving a config to cache.

Categories