9

I have both a couple of X.509 Code Signing certificates and a GPG keypair that I can use to sign against code I run on my VPS. Every now and again I write code for iOS, OS X and Windows and always ensure I sign my binaries with my X.509 certificates. However, I would like to ensure that anything I run on my VPS (in regards PHP/Django scripts and maybe even Javascript that I send to a client) is signed too.

I could simply write a bash script that signs every file in a directory with my GPG keypair, but my problem is the fact that if the code was not signed, it doesn't raise any additional errors than if it was signed correctly, so in interests of protecting my server from sending out/executing malicious scripts that I haven't explicitly authorized, is there any way I can use my GPG keypair (or even my X.509 certs!) and ENSURE all code in a particular, say, directory is always checked for a valid signature before execution?

To throw a spanner even further in the works, how could we effectively 'sandbox' this in such a way as malicious scripts placed outside the scope of the enforced checking could not interfere? For example, if a directory was 'flagged' as requiring enforced signatures on all files, would it be possible for files outside this directory to be used to circumvent the code signatures and interfere with the application or scripts?

I'm not really interested in the signing algorithm, scripts vs. binaries or operating system, but for the application I would apply this to, it would be against python/django or PHP scripts running in a Debian VPS (for the purposes of web applications).

Just an interesting thought, one I'd certainly like to pursue if a suitable solution is around! Ideas or discussion is much appreciated!

2 Answers 2

4

For PHP there are various encrypting engines like ionCube PHP encoder - these work as PHP extensions that hook into a parser and decrypt the code that is to be run, validating the signature, checking the restrictions of a licence file (e.g. MAC address, domain name, time restrictions). They can be set up so that a code that is not 'encrypted' with appropriate key cannot be run at all, so only PHP code encrypted by the author can be executed.

Unfortunately, these are paid proprietary closed-source solutions and are not compatible with GPG as far as I know (so you cannot use your own GPG key for signing). However, they can be easily integrated into application build scripts etc.

Another approach would be to package your whole PHP application as a Phar archive. Phar supports code signing features, I've also made a set of scripts called PharUtil that use it for securely distributing signed code. It's not the same use case that you have, but might be useful for a start.

I don't know of any similar solutions for Python and/or Javascript.

3
  • 1
    Your "solution" doesn't account for dynamic code such as eval(), perhaps you should read Exploitable PHP Functions
    – rook
    Commented Jan 22, 2012 at 19:04
  • 2
    Dynamic code execution dependent on user input would have to be in the signed source code in the first place, and that is easily controllable by the script author. There's nothing preventing the author from shooting himself in the foot, but that is not the question OP asked. Commented Jan 22, 2012 at 21:34
  • Yes, and the same is true with RFI/LFI vulnerabilities. Thank you for this 101 in basic exploitation.
    – rook
    Commented Jan 22, 2012 at 21:53
4

In order to support this functionality the interpreter will have to be augmented. Fortunately this a code singing feature probably doesn't require a PHP extension like hardened-php. In fact there is a simpler way.

You could change your php.ini to auto-prepend a php script that reads the $_SERVER['SCRIPT_FILENAME'] and verifies the current script's signature. If the signature check fails, then call die(); and it will never be able to execute.

This is a pretty simple solution. However, this won't prevent an attacker from exploiting vulnerabilities in existing code to obtain code execution, including but not limited to eval() and RFI/LFI vulnerabilities. Also, each interpreter will require its own solution. For instance client-side JavaScript would require a browser specific extension like NoScript. "Unauthorized JavaScript" is more more commonly refereed to as XSS. A great solution for XSS is the Content Security Policy, because it gives you control over where the browser can execute JavaScript. There isn't a one size fits all answer to this problem.

1
  • 2
    Your auto-prepend solution could only verify the script requested by the browser and will miss all the the code being interpreted and run via include()s or autoloading, which will account for ~95% of total code. Commented Jan 22, 2012 at 15:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .