Security Concerns

d2uhlman wrote on Thursday, May 01, 2008:

Many of you probably don’t know me but a pretty significant portion of the code still in use in OpenEMR was written, designed or merged by me while I was CTO of Pennfirm going back some years ago. I am currently the CEO of ClearHealth and in many ways the ClearHealth system was a next generation endeavor out of was was learned from OpenEMR.

Anyhow, one of the main reasons in creating ClearHealth from scratch code was the insecurity of the OpenEMR codebase as it had its roots all the way back in PHP version 3. As a recent project we are reviewing a wide range of systems to put together a feature comparison grid. As part of the that effort some of our engineers took a look at the existing OpenEMR codebase downloaded from www.oemr.org and we were troubled to find that there are currently a large number of php globals vulnerabilities, SQL injection vulnerabilities (at least one which does not appear to require login), URL and POST hacks, and other exploit avenues (especially through included libraries) still present.

A search found there to be a number of openemr installations that seemed to be real and connected to live practices operating without anything in front of their installations. I just wanted to advise that anyone doing so disable remote access or at least put a separate .htaccess in front of the system.

We would be happy to take a few minutes and brief anyone appropriate on the most obvious issues of which we are aware. We are not interested in publicly publishing any of the information or putting together any kind of actual exploit for obvious reasons.

Thanks.

sunsetsystems wrote on Thursday, May 01, 2008:

Why don’t you send your list of vulnerabilities to me (rod at sunsetsystems dot com) and I’ll forward it on to any of the other developers who are interested in working on it.

It’s hard to make PHP apps bulletproof, and virtually impossible to prove that they are.  What I usually do for my clients who need remote access is to set up browser-side SSL certificates (to authenticate the client to the server).  That does a very good job of keeping the bad guys out.

Rod
www.sunsetsystems.com

d2uhlman wrote on Thursday, May 01, 2008:

Ok, will do. We will have an email to you some time next week. I agree that it is difficult to make any application “bullet proof” but remote access sql injections without login I don’t think are an unreasonable base level of prevention. Certainly client side certs or basic authentication is a good outside layer of security.

sunsetsystems wrote on Thursday, May 01, 2008:

Agreed.

Thanks,

Rod
www.sunsetsystems.com

drbowen wrote on Friday, May 02, 2008:

Dear David,

It is good to hear from you again.  We appreciate your objectivity and assistance.

For the record, I for one advise end users not to run live OpenEMR installations on the open Internet, (though there are IT admins who have the skills to do so).

Currently (as of 2.8.3) we are requiring globals to be turned off in the installation routine.

We are repairing the SQL injection problems as they are discovered.

Have you tried the SQL injection against OpenEMR 2.8.3?  Rod introduced a fix in 2.8.3 and at least on my public Internet demo site it seems to have been working. (one of the side effects of running an open demo is you get to find out some of the badness that can happen to your software).

Sincerely,

Sam Bowen, MD

mbrody wrote on Friday, May 02, 2008:

I have a ‘live’ installation running behind a firewall, with very strict rules as far as allowed IP’s in IPTABLES.  This situation works well as long as you have static or semi static IP addresses.  Is anybody aware of any security issues with this type of configuration?

Michael

markleeds wrote on Friday, May 02, 2008:

Security holes are one of the side effects of a project that encourages medical professionals who are amateur programmers to contribute.  Some people say that the php language itself encourages security holes.  With a little guidance from those who know how to avoid creating these problems, we can all learn from them.  Maybe a page of programming guidelines on the wiki would be a good start.

I used to expose my openemr installation to the internet with .htaccess, as David recommends.  I became nervous about it when I read that this form of security is susceptible to a dictionary attack, so I took it offline.  Now, my office network has no internet connection.

I think that some of the concerns that David brings up are significant in a large practice that may have disgruntled employees who want to sabotage the system.

Thank you David for your contributions.

drbowen wrote on Friday, May 02, 2008:

Most of the problems that David Uhlman is referring to above are the use of registering global variables which was typical of development in PHP 3.  These "errors" were built into OpenEMR between 1999 - 2000 when OpenEMR was being developed by Synitech.  I would think that the developers at Synitech are working on a professional level.

The issue that he is referring to is that using global variables is known to be a really bad idea from a security standpoint.  PHP 3 has been deprecated at least 4 years for its severe security problems, register globals being chief on the list.  Register globals "On" compounds the problem because it can give an attacker inappropriate system access including possible root access to the operating system.

The original OpenEMR was written in PHP 3 and has huge number of lines of code.  (Over 450,000 lines not counting the calendar).  Instead of trying to fix the OpenEMR PHP 3 base, David Uhlman and his group decided for this and I am sure for a variety of reasons, to start over from scratch and to write a new project. 

The SourceForge OpenEMR project development made the decision to work on functionality first, realizing that sooner or later, we would need to root out the PHP 3 vestiges and to move system variables out of globals.php.  In the short term, we have forced Register Globals to be turned Off.  Rod Roark has already improved a several security issues and continues to work diligently on these as they are discovered.  Having an external review of our code is invaluable.

There are ready is a set of coding guidelines at www.oemr.org.  There will be I am sure for improvement.  One of the problems we see the most frequently with the volunteer developers that we have is not everyone is scrupulous about scrubbing ALL user input.  The first rule of security is to NEVER trust user input.

Preventing SQL injection starts with basic server side security and especially MySQL server security, running the web page MySQL user with limited privileges (As an example Do Not Allow the "GRANT" privilege).

There a number of forms of SQL injection techniques and the imagination of potential attackers seems to be limitless.  Additional measures include not allowing special characters during user input, checking user input for valid data, preventing multiple queries from being executed since many of the SQL-injection techniques cause the execution of two queries.  The first being a malformed query that allows access and the second holds a malicious payload. Newer PHP mysql extensions including mysqli do not allow multiple queries and provides some protection.

***not allowing special characters during user input***

addslashes( older )

mysql_real_escape_string( recommended )
   Mysql_real_escape_string prepends backslashes to the following characters: \x00, \n, \r, , ', " and \x1a
   Available in PHP >= 4.3.0

***checking user input for valid data***

date fields: check for valid characters, dashes and slashes / or \ where appropriate.

Username: Restrict usernames to upper case, lower case letters, and underscores
Passwords:  Do not allow known bad characters ’  " \

***Check for size***

allow the smallest inserts of data that is appropriate for the situation.  As an example a free form test box should not contain 10 megabytes of data.

Here is a review of preventing SQL-injection in a PHP and MySQL environment:

http://www.phpbuilder.com/columns/ProPHPSecurity_excerpt.php3
http://www.phpbuilder.com/columns/ProPHPSecurity_excerpt_part2.php3

And here is another:

http://www.askbee.net/articles/php/SQL_Injection/sql_injection.html

Sam Bowen, MD

lemonsoftwarero wrote on Wednesday, May 21, 2008:

As a note to what Dr. Bowen said:

- addslashes - it doesn’t account for different character sets, escaping always the same set of chars, no matter the input type.
- mysql_real_escape_string seems to take care of the character set used BUT if somehow, you manage to alter the char set of the connection (e.g. SET CHARACTER SET ‘GBK’), the function doesn’t recognize this change and it continues to escape data based of the specifics of the previous used char set.
(You can use before that mysqli_set_charset() but it’s available only for php >= 5 and mysql >= 5).

Here we can find more details and a nice exploit example:
http://ilia.ws/archives/103-mysql_real_escape_string-versus-Prepared-Statements.html

Best,
Cristian N.