Analyzing the Security of Freeswitch’s XML Curl Interfaces

Recently, we were working on a part of our Freeswitch configuration web app. This app generates configuration files for our servers in XML format. When Freeswitch needs a piece of configuration data, it is able to fetch the configurations in real time from our web server using its ‘mod_xml_curl’ module. This is a very powerful tool, but as we were thinking about how to deploy this to a large number of our client servers, security came to mind.

Freeswitch’s XML interfaces have the ability to provide authentication credentials to a web server using HTTP Basic authentication, which essentially transmits the username and password as plain text (yeah, ok, it’s base64 encoded, but that may as well be plain text). To offset this potential security issue and prevent unauthorized individuals from requesting our server configs, Freeswitch can connect to a web server through SSL (https). This is a little bit better, but there were a few things lacking from this solution.

For one, there was no ability for us to use anything other than an official Certificate Authority-issued SSL certificate (i.e. Verisign or Godaddy). Or at least that’s what the Freeswitch docs said, more on that later. Anyway, those certificates cost money, and during the development phase I’d consider it to be an unnecessary expense.

In order to get around the need to verify the server’s SSL certificate with a CA, there was an option in xml_curl.conf.xml called ‘ignore-cacert-check’. This was supposed to tell Freeswitch to not even bother checking whether the web server’s certificate was valid or not. Not a great solution, because this opens up the potential for a man in the middle attack where another web server intercepts communications with the Freeswitch server and pretends to be our official server. Once the Freeswitch server establishes a connection and sends out its plaintext username/password, the unauthorized web server now has the credentials and could use them to request configs from our server.

So it seemed to be an all-or-nothing choice: either pay for a licensed SSL certificate or forgo any real notion of security in the system. But as it turned out it didn’t even matter, because regardless of the ‘ignore-cacert-check’ variable, mod_xml_curl and mod_xml_cdr were already telling libcurl to skip peer verification and skip hostname validation (checking to see that the host is actually the one listed in the cert).

if (!strncasecmp(bindings->url, "https", 5)) {
	curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
	curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
}

So these options were being disabled no matter what when https was used. Obviously some changes were needed to enhance the security here.

More in the next post.

FUCKED