Adam Caudill

Security Leader, Researcher, Developer, Writer, & Photographer

phpMyID: Fixing Abandoned OSS Software

phpMyID is a simple solution for those that want to run their own OpenID endpoint – the problem is that its author stopped maintaining the project in 2008. Despite this, there’s still quite a few people that use it, because it’s the easiest single-user OpenID option available.

Unfortunately, the author didn’t follow best practices when building the software, and as a result multiple security flaws were introduced. In 2008, a XSS was identified and never fixed (CVE-2008-4730), in the years since then it seems the software has been below the radar. While conducting a pentest I discovered a previously undocumented XSS (CVE-2014-2890) – which left me with a dilemma – what to do about it?

Looking at the code, I found a couple more potential XSS vulnerabilities – so the application clearly needed help, and if the author won’t do it, somebody should. Ethically, it seemed wrong to disclose the issue but leave users to fend for themselves; full disclosure is normally used to push a vendor into acting – but in this case it’s assured that there won’t be a vendor response.

Fixing The Code #

One good thing is if a OSS project is abandoned, anyone can prepare patches to fix the issues. So, that’s what I did. I’ve committed fixes for both CVE-2008-4730 and CVE-2014-2890, as well as a couple potential issues. In both cases, the fix was easy:

CVE-2008-4730:

@@ -439,7 +439,7 @@ function checkid ( $wait ) {
if ($trust_root != $return_to) {
    // the urls are not the same, be sure return decends from trust
    if (! url_descends($return_to, $trust_root))
-          error_500('Invalid trust_root: "' . $trust_root . '"');
+          error_500('Invalid trust_root: "' . htmlentities($trust_root, ENT_QUOTES) . '"');

}

CVE-2014-2890:

@@ -568,7 +568,7 @@ function checkid_setup_mode () {
*/
function error_mode () {
isset($_REQUEST['openid_error']) 
-      ? wrap_html($_REQUEST['openid_error'])
+      ? wrap_html(htmlentities($_REQUEST['openid_error'], ENT_QUOTES))
    : error_500();
}

I’ve only given the code a quick once-over, so there may be other issues – if I find time for a more thorough review I may commit additional fixes.

Status of phpMyID #

I’m not taking over the maintenance of the project, I simply don’t have time to do the cleanup needed to bring it up to reasonable standards. I’d love to see somebody with a little time to invest cleanup the code and add more defensive measures. It needs some help, that’s clear.

One of the things I’d love to see fixed is the way the user’s password is stored – it’s currently stored in the MyID.config.php file as a MD5 hash – making brute-forcing entirely too easy. Hopefully this Internet Draft will be adopted soon, obsoleting RFC 2617, which will be an easy win to improve the security of the password when in transit. There are many places where the code can be improved by somebody with a little time.

If you are using phpMyID today, replace the MyID.php file with the one here (it also fixes compatibility with PHP 5.4).

Adam Caudill


Related Posts

  • Developers, Developers, Developers

    Note: This was written in 2012, but not published at the time. The point is still valid, perhaps moreso than ever and deserves to be made publicly. The content has been updated as appropriate, though the core of this article remains intact from the 2012 draft. I would like to note that this doesn’t apply to every environment, there are some where developers are very knowledgeable about security, and write code with minimal issues – my current employer happens to be one of those rare & exciting places.

  • Threat Modeling for Applications

    Whether you are running a bug bounty, or just want a useful way to classify the severity of security issues, it’s important to have a threat-model for your application. There are many different types of attackers, with different capabilities. If you haven’t defined the attackers you are concerned about, and how you deal with them – you can’t accurately define just how critical an issue is. There are many different views on threat models; I’m going to talk about a simple form that’s quick and easy to define.

  • Juniper, Backdoors, and Code Reviews

    Researchers are still working to understand the impact of the Juniper incident – the details of how the VPN traffic decryption backdoor are still not fully understood. That such devastating backdoors could make it in to such a security-critical product, and remain for years undetected has shocked many (and pushed many others deeper into their cynicism). There are though, some questions that are far more important in the long run:

  • First, Do No Harm: Developers & Bad APIs

    Primum non nocere (first, do no harm) – an iconic phrase in modern medicine, yet also applicable to many other fields. This is something I wish more people would think about, developers especially – and primarily when writing new APIs. In general, developers don’t have an impressive history with security – quite frankly, developers suck. Seeing as I consider myself a developer, that’s painful to admit. Chris Andrè Dale posted an interesting article some time ago that got me thinking: Why it’s easy being a hacker: A SQL injection case study – Chris pointed out the problems with educational material that developers are using, and just how bad the examples are.

  • Win by Building for Failure

    Systems fail; it doesn’t matter what the system is. Something will fail sooner or later. When you design a system, are you focused on the happy path, or are you building with the possibility of failure in mind? If you suffered a data breach tomorrow, what would the impact be? Does the system prevent loss by design, or does it just fall apart? Can you easily minimize loss and damage, or would an attacker have free rein once they get in?