views:

572

answers:

8

Management strikes again.

How should I satisfy the code scanner that is going to read my php source and red flag my MySQL connection string?

  • Linux Server (soon to be Sun)
  • php 4.2 (soon to be latest version)
  • MySQL database
  • Servers in a DMZ outside of the firewall
  • Read only MySQL account
  • Not a single byte of non public information in the database

I have to encrypt my MySQL password in the connection string for no reason other than it is going to be red flagged by the automatic code testing solution. Management is enthralled with the concept of Pen Testing without understanding it.

I know full well it isn't any more secure to encrypt the password in the file with all the other measures in place, but my sites will be taken down if I don't comply. I know it hurts performance but this site isn't so popular, and isn't a huge database driven app anyway.

My attempt:

//encrypt and decrypt are functions I stole wholesale off of the php.net manual
...
$SuperSecure[0] = array(encrypt("test"), encrypt("test")); //dev
...
$dbcnx = mysql_connect('localhost', decrypt($SuperSecure[0][0]), decrypt($SuperSecure[0][1]));

Is there a better way? More importantly, am I missing something and this is actually necessary?

Edit: I can't fight national anymore. If I ignore this directive my site comes down and losing my job over this is dumb. I just to do this as easily (and with the least performance impact) as possible.

+3  A: 

It is pointless, an just makes it more confusing to someone maintaining your code. Don't be a wuss, take on the mindless code-scanning advocates and don't give in.

GregS
I have been fighting the good fight for a year. My boss and his boss are on my side, but the national office will not be ignored!
MrChrister
There's absolutely no reason to do what you're trying to accomplish, because it's just not adding any more security at all. You should either convince the national office or just ignore them and do it the right way. They could at least give you a good reason for doing that, but you already know that there's no such reason.
Tomas Markauskas
To be honest, this new "security" is what i would consider "stupid"... It reminds me of those Dilbert comics where the boss has no idea what the hell hes talking about, eh? Have you tried explaining to them why their new "method" doesn't add any actual security?
ItzWarty
+1  A: 

It IS unnecessary, since you'll just obfuscate the password. Anyone who has the source could log in to the database since your PHP script has to know decrypt to get the original password.

Example

let's say that your password is a number, for example 42 and that encrypt is a function which multiplies by two and decrypt does the opposite.

Then, you'll store 84 in the code somewhere. However, PHP has to know the decrypt function also and will convert it to 42 first before connecting to the database. So, since everything you need has to stand in the PHP file, it is pointless to obfuscate the necessary information.

Some evil hacker which has your source could always replace the mysql_connect in your code example with an echo and will get the plain text password...

Easy obfuscation

Maybe it suffices to use something like "t"."e"."s"."t" instead of "test" in your code to bypass detection of the password...

Etan
Exactly. The real purpose of the code is to beat whatever off the shelf source code scanner they will use to validate my code so I can get it published.
MrChrister
It is worse than you assume. The encrypt and decrypt functions are just 20 lines away from the DatabaseConnection function. If they have the file they have all they need. We aren't talking security here, since this new mandate offers the opportunity for none.
MrChrister
+1  A: 

You can use rot13 to obfuscate (not encrypt) the password

Otto Allmendinger
Does this perform better because it is native? I think I would have to mentally obfuscate the password before calling this right?
MrChrister
rot13 just shifts every character by 13 in the alphabet. rot13(rot13(originalstring)) returns the originalstring. I don't think that the performance you loose due to an encryption mechanism will be measureable.
Etan
A: 

You could use an ODBC connection to access the database. The ODBC abstraction layer stores its connection properties in a separate file (in UnixODBC, it's /etc/odbc.ini and ~/.odbc.ini). That way, the system DSN can know how to access the database, and your script will rely on it.

I'd advise caution in using ODBC, though, as it doesn't have access to some of the more complicated functions and queries that a straight MySQL connection does.

amphetamachine
And what if the code scanner does also check this file? ^^
Etan
+1  A: 

If you don't want to write the password directly into mysql_connect, why not write something like:

$username = 'test';
$password = 'test';
mysql_connect('localhost', $username, $password);

Without knowing how clever the scanner is you won't really be able to tell what obsfucation is enough to not raise any flags.

Tomas Markauskas
This is definitely simpler. I should keep it simple and try to get this through the scanner first.
MrChrister
For my web services, I write a secrets.php that isn't checked into version control. Include that on the deployment and the password is defined, yet unavailable.
Autocracy
Wait, so this passes as secure with the scanner (as opposed to not using variables)? I will pray for you, your boss and his boss.
Baddie
@Baddie. I thank you for your prayers. My personal hell continues with national web team meeting. The depth of their depravity knows the bounds of my shame and continues to hump me into peril.
MrChrister
+1  A: 

Couldn't you define the default mysql host, username, and password in a php.ini file? Then the mysql_connect function looks like:

`mysql_connect();`

And unless a hacker has your php.ini file, they won't be able to access the username or password. Even if they changed the function to echo. Sure they could echo the directives, but I think it is obfuscated enough, as the password could not be found in any of the source files, aside from php.ini, which is a server-file.

Given, if someone did a phpinfo(); it also would be displayed in plain site, but it would still work.


This solution is very similar to the ODBC solution provided by another answer. It also has the flaw that if the scanner checks your php.ini file, it is going to end up red flagging that instead.


If you would like to make fun of it at the same time, I'd suggest randomly putting snippets of your mysql code in random files that are all includes before you need to connect. AKA

Index.php

Global $password;
$password = "S";

RandomFile.php

Global $password;
$password .= "T";

RandomFile2.php

Global $password;
$password .= "A";

RandomFile3.php

Global $password;
$password .= "CK";

RandomFile4.php

Global $password;
mysql_connect($host, $username, $password."Overflow");
Chacha102
I already have define('SALT', 'Code_Scanners_Do_Nothing_1*#@!'); for my personal fun.
MrChrister
You know, there is a experimental library that will load all the code into a bytecode format. If you only let the scanner scan that, it probably wouldn't find the password.... then again it wouldn't find anything.
Chacha102
A: 

I might be missing the point here, but let me ask this.

Why are you not storing your mysql connection information in some form of config file, that is included at run time, and using some form of database abstraction, rather then peppering your code with mysql_connects and other legacy methods of dealing with database connections?

I would find it doubtful that your automated code scanning solution would read plaintext ini files, or xml ini files, and some frameworks, Like Zend, make it very easy to deal with these types of configuration files, so that your password is not scattered throught your code, or web accessible at any point...

It sounds like you have all the other measures in place(server outside of network, secure mysql account with only the needed privs.). Am I misconstruing what you are doing, or is there a reason to avoid the best practices here?

Regards

JC
+1  A: 

XOR! The basis of the venerable one-time pad. It's legitimate encryption, makes you look more suave then rot13() and anybody competent should be able to figure it out. At the same time, nobody will be grepping your password.

<?
$pass = 'foobar';
$key = 'monkey';
$secret = $pass XOR $key;
$list = array($key, $secret);
foreach($list as $x) {
    print "Keypart: ";
    print implode(unpack('H*',$x));
    print "\n";
}
?>

Aaand I suddenly hate how PHP does arrays... Now, take the output of that...

<?
#Keypart: 6d6f6e6b6579
#Keypart: 666f6f626172

$secret = '666f6f626172';
$key = '6d6f6e6b6579';
$pass = pack('H*', $key) XOR pack('H*', $secret);
print "$pass\n";
?>

The first part is your encryption generator, and the second part is what you have to put in the program. The only rule is that whatever bytestring you XOR the password against should be the same length as the password. It probably won't do anything unwanted if it isn't, but I don't feel like building a testcase.

Autocracy