Things That Matter Most

Things That Matter Most

  • Home
  • Business
  • Faith
  • Technology
  • Politics
  • Creative Writing
  • Email
  • GitHub
  • RSS
  • Twitter

Powered by Genesis

Disclosure: SQL Injection in Cart66 Pro

April 6, 2018 by Eric Leave a Comment

This vulnerability was reported earlier directly to both the Cart66 team and to Semper Fi Web Design (the maintainers of the GitHub clone). This post follows a 30-day responsible disclosure window.

Last month, a friend pointed me to the no-longer-in-development Cart66 Pro module for WordPress. The plugin ceased development about two years ago when the team moved to a hosted SaaS model, but it’s still available by way of a GitHub mirror for anyone still actively using the tool. Just one problem: it has some significant security holes.

Password Use

The first critical flaw in the plugin is the way protects it fails to protect user credentials. WordPress isn’t widely known for its strong stance on user password hashing, but at least leverages multiple hashing rounds and a random salt to prevent the creation of rainbow tables for brute forcing a login.

Cart66, however, uses a single round of MD5 hashing on the password. Without a cryptographic salt.

This fails to offer much protection at all on a user password. Further, MD5 is considered a broken hash and it’s relatively easy to use an aforementioned rainbow table to reverse from a hash to a user-specified string.

Considering how frequently end users reuse passwords, getting a copy of the unsalted single-round MD5 hashes from a Cart66 database would give any attacker a solid starting point for trying to steal a customers’ account elsewhere. Perhaps they reused the same password for PayPal? For another ecommerce site? For their email address?

The weak state of password hashing on Cart66 Pro-powered sites results in databases ripe for abuse if they can be stolen by a malicious party.

SQL Injection

Like all good ecommerce and marketing tools, Cart66 Pro presents an efficient way both to email customers and for customers to opt-out of receiving emails. Unfortunately, the opt-out mechanism is vulnerable to a somewhat trivial SQL injection vulnerability!

The opt-out system is powered by a WordPress shortcode. A WordPress administrator adds this shortcode to a standard post or page in WordPress, then visitors hit that page when they click an opt-out link in the footer of an email. PHP code running on the page will then extract certain query parameters from the URL to identify and flag the user as opted out of messaging.

One of these parameters is the customer’s email address (as that’s their primary identifier in the database). By default, the email address is passed as a Base64-encoded, URL-encoded parameter in the request.

For example, eric@thisisareallybadidea.com would be encoded as ZXJpYyU0MHRoaXNpc2FyZWFsbHliYWRpZGVhLmNvbQ==.

However, there is zero sanitization on this input. While a typical user would click a link in their email client, an attacker could craft their own URL with whatever parameters they want specified. Imagine instead that an attacker passed JTI3JTNCVFJVTkNBVEUrd3BfY2FydDY2X2FjY291bnRzJTNCLS0= as the email parameter in the request.

This decodes to ';TRUNCATE wp_cart66_accounts;--, which is obviously not an email address. To understand why it’s an issue, you have to understand that, after decoding the email parameter, Cart66 Pro passes the value directly into a SQL statement:


$itemsTable = Cart66Common::getTableName('accounts');
$sql = "SELECT id from $itemsTable where email = '$email'";
$id = $this->_db->get_var($sql);

Running through the interpolation, this will have the effect of running the following query directly against the WordPress database:

SELECT id from wp_cart66_accounts where email = '';TRUNCATE wp_cart66_accounts;--'

The first SELECT statement will obviously fail to match any accounts, but the second TRUNCATE statement will drop all account data from the database!

A well-armed attacker could also craft a request to insert arbitrary information into the database, manipulate the data already present, or even extract whatever contents they want from the WordPress database (including a list of all account logins and weakly-hashed passwords)!

If you are using Cart66 Pro and have not already patched this issue, please do so immediately as your database (and your customers’ information) is at risk!

Moving Forward

SQL injection attacks are one of the most prevalent in the open source software community. It’s incredibly easy to write insecure code and trust that the only inputs to our functions are legitimate. But every developer needs to occasionally put on their “how would someone break my code” hat and protect against the worst case scenario.

WordPress in particular has extensive documentation about how to properly prepare SQL statements to prevent this kind of injection attack. If you’re using WordPress and writing code that queries the database directly, use this approach to avoid a malicious party abusing your code to attack the platform.

If you’re writing PHP but not using WordPress, leverage tools like PDO that support prepared, parameterized statements to protect your code from abuse.

There is literally no excuse to not prepare your SQL statements in modern code. Anything less is reckless and opens not only your customers but also your business to attack and abuse. It’s worth it to take the time and do things right the first time. Security engineers will often find these issues in the wild and give you a head’s up; but usually a malicious party has already found and exploited the hole by then.

-~-

For more advice on writing secure PHP code, I’d encourage you to pick up a copy of my new book, Security Principles for PHP Applications. I’ll walk you through all of the updated OWASP Top Ten, and specifically through properly avoiding both SQL and other forms of injection attacks. It’s a great place to start to keep your project secure.

Filed Under: PHP Tagged With: security, vulnerability

DNS and Cross-Site Scripting

September 19, 2014 by Eric Leave a Comment

One of the first things on any security auditor’s list is checking to see if a site is vulnerable to cross-site scripting (XSS).

The point of an XSS vulnerability is that an attacker can inject a script into your page. Once the script is there, it can manipulate your page in any way it wants. It can add markup (i.e. reconfigure the page). It can intercept visitor interactions (i.e. capture usernames and passwords, sending them to a remote site).

Or it can make your entire page to the Harlem Shake.

Ok, this is a pretty amazing XSS exploit: http://t.co/PObynTNTMV

— Owen Winkler (@ringmaster) September 18, 2014

Own linked here to a DNS lookup tool that, apparently, is suffering from a cross-site scripting exploit. 1 Shortly after the page loads, you hear a Harlem Shake track play in the background and, shortly thereafter, see all of the content on the page dance along with the music.

It’s awesome, both in terms of humor, and in terms of the stellar example this presents of how not to build a site.

The Exploit

It took a few minutes of digging to figure out what was actually going on with the site. I couldn’t track down exactly how the Harlem script was being injected … until I saw a very specific indicator.

The domain being looked at returns several TXT records. Two of them appear to be (intentionally) malicious.

One showed up as blank in the page, so I skipped over it. The second was a YouTube video embed.

Wait …

One of the DNS TXT records was a YouTube video embed. What’s worse, it was a functional YouTube video embed!

I used the DOM inspector to look at the seemingly blank TXT record, and found out it was, indeed, the script tag that was triggering the Harlem Shake takeover.

When the DNS lookup tool rendered the raw content of the TXT records directly to the page. No validation. No escaping. So both the <iframe> and <script> TXT tags became functional markup and part of the page.

Lessons Learned

When developers are pulling information from external sources, it’s often easy to just print the information direction to the page. Often we’re the ones writing the information in the first place, so we assume that data will be safe when we read it back out.

This includes remote APIs, databases, filesystems. Basically any place we take data and turn around to present it to visitors.

Always assume a malicious party can stand between you and your data.

This is why, with WordPress code, the accepted best practice is to escape everything. Core functions, custom functions, database reads, remote data fetches – everything must be escaped before we print it to the browser.

After all, no one expects a TXT record to contain a <script> tag, so it’s safe to print without escaping, right?

Notes:

  1. The site was being actively mocked at the time of this writing, but late yesterday afternoon I noticed that the site host updated their system to properly escape DNS record output. Unfortunately you can’t see the active exploit any longer. ↩

Filed Under: Technology Tagged With: cross-site scripting, DNS, escaping, hacking, vulnerability

Why Showing The WordPress Username Is A Security Risk

April 4, 2014 by Eric 12 Comments

There have been a handful of discussions lately surrounding WordPress and usernames – particularly whether or not exposing usernames is a security risk.

The consensus appears to be “no.”  I beg to differ.

Two Factor Authentication

Your username is one of the two pieces of information WordPress uses to identify you versus the hoards of people pretending to be you in order to gain access to your website.  The second piece of information is your password.

Gravatar HovercardsIn older systems (not WordPress), users were able to log in using just a unique ID – i.e. their username.  Actually, in current systems this is still a widely accepted identification scheme.  Anyone could visit any WordPress site, drop my email address in a comment form, and be recognized as me when they leave a comment.

No second form of authentication is required.  This is hugely disturbing as I have zero control over the content (or removal) of comments masquarading as me by merely using my email, which is then hashed by Gravatar and used to pull in not just my profile image, but often also a “hovercard” with my information on many sites.

Two factor authentication requires two separate forms of user identification.  Take the everyday example of ATM cards:

To prove that users are who they claim to be, the system requires two items: an ATM smartcard (application of the possession factor) and the personal identification number (PIN) (application of the knowledge factor). In the case of a lost ATM card, the user’s accounts are still safe; anyone who finds the card cannot withdraw money as they do not know the PIN. The same is true if the attacker has only knowledge of the PIN and does not have the card. 1

If we were talking about bank cards rather than WordPress access, you would be hard-pressed to find someone claiming that “showing your card number is not a security risk” because, well, it’s a huge one.  Even if an attacker doesn’t have your PIN, having just one piece of information is so dangerous (as a 4-digit pin can easily be guessed) that we immediately cancel/change our cards if lost, stolen, or if, say, records of a vendor like Target are hacked.

When it comes to usernames, however, we’re so used to the username/password tuple being treated as a single piece of information that two-factor authentication means something different – using a tool like Google Authenticator on a mobile phone.

I use Google Authenticator for my WordPress.com account because it’s a built-in service.  However I have yet to find a comparable system for self-hosted WordPress, so I don’t use it. 2

Brute-Force

In the lack of a sufficient two-factor authentication scheme (username is publish, Google Authenticator is not enabled), hacking a WordPress site is relatively easy.  Usernames are public information, meaning hackers only need one piece of information.

If you’ve seen the movie Olympus Has Fallen, you’ll see where I’m going here.  In the film, the attackers needed three separate codes to hack the national defense system. The President ordered the two other code-holders to give theirs up, swearing “they’ll never get mine” each time. In the end, they didn’t even need his – two codes got them far enough into the system they could use a brute force generator to guess his code and, eventually, launch the missiles.

Fictional storyline or no, this helps prove my point: if an attacker knows your login, they can brute force your password.

This is actually the key reason one of the first recommendations for securing a WordPress installation is to remove the “admin” user.

In fact, WordPress even allows administrators to set a custom username for the initial user upon instantiation to avoid having “admin” used by default.  There have been further changes in core to remove “admin” as a fallback when the username is not otherwise set.

Why? Because leaving your site’s administrative username as “admin” is considered a security flaw.

Vulnerability

I’ve spoken before at how vulnerable logins to your site can be when an admin-level account is used too frequently and in poor environments.  That said, the fact that usernames are exposed – and are enumerable – is one of the largest failings in WordPress when it comes to security.

There are open source tools on GitHub 3 that allow attackers to quickly list usernames for accounts on your site.  These tools are made possible by the fact that user IDs are assigned as auto-incrementing integers rather than true GUIDs. 4

All this comes back to something blindingly obvious though. Everyone is going to know part of your access. The reason we tell people not to use ‘admin’ as a login ID is not because it’s more or less secure, but because it makes it easy for script kiddies to target. 5

Once an attacker has an account they want to target, the same tools will allow them to brute-force the account’s password. It doesn’t require a personal vendetta against a single user, just an extra line of code to grab a list of usernames and pick one.

For many servers, this will essentially DOS the system – something a daily blogger will notice.  But if scheduled during off hours, it would be easy to fly under the radar.

Honestly, when was the last time you logged into your server and checked the access logs?

Moving Forward

Usernames should not be public information – we should have an alternative field (i.e. user_nicename) to serve as a unique identifier for author permalinks.  Usernames should be used for authentication only and for nothing else.

Obfuscating user logins won’t resolve every potential vulnerability in WordPress.  However, as the scale of the project continues to grow, decisions made in WordPress’ infancy will continue to rear their heads as security issues.

Usernames aren’t inherently insecure on a small scale – when a platform reaches the level of visibility attained by WordPress, however, the number of potential attack vectors tied to public usernames goes through the roof.  Curtailing these attacks helps strengthen the platform.

Notes:

  1. Two-step verification ↩
  2. If Automattic were to finally open source their implementation, I’d use it in a heartbeat. I mention this at every opportunity in the hope that someone will finally do so. ↩
  3. I will not link to these tools. I thought about it, but I don’t want anyone using this article as a “how to hack WordPress” tutorial. If you’re interested in these tools, contact me privately and explain why. ↩
  4. There have been proposals to change this, making automated enumeration of usernames essentially impossible. Unfortunately, these proposals have been met with resistance from many on the core team – not because it would be difficult, but because they fail to recognize the importance of such a task. ↩
  5. Your Username is Not A Secret ↩

Filed Under: Technology Tagged With: administration, security, vulnerability, WordPress

Web Requests and Data Leakage

January 18, 2014 by Eric 3 Comments

When I wrote earlier on securing images and solving mixed content issues on websites, my friend Mike Schinkel asked if I could explain why it mattered.  I briefly covered information leakage in the comments, but wanted to go over things a bit more in detail for anyone interested.

The Tools

I use a variety of network tools to monitor requests going back and forth from the browser to the server.  Seeing exactly what the browser sends and exactly what the server returns helps debug interactions, detect potential optimization routes, and gain a better sense of what’s going on under the hood.

On my Windows machine, I use Fiddler as a proxy so I can see every piece of data passing over the wire.  On both my Windows and Mac I use Wireshark to monitor both web requests and, well, everything exchanged over the network.

Wireshark, in particular, is a fun tool to run when connected to any network as it lets me see not just the traffic from my machine but any machine on the network.  If you want proof that people are still using insecure network connections to send sensitive data, spend 5 minutes reading a Wireshark feed.  It’s a sobering experience.

The Experiment

To demonstrate how information could leak with images, I did a quick experiment on my own site.  I made a web request to http://eamann.com/biz/does-the-fold-still-matter/?username=testing&amp;password=1234.  This is to demonstrate two things:

  1. The relative insecurity of GET parameters (variables passed in a URL)
  2. How data passed in a referrer header can be intercepted by an eavesdropper

Once upon a time I worked on a stateless REST-based web application that still authenticated users on each request.  The user authentication required the username and password of the current user to be passed as GET parameters in every request.  Every. Request.  This experiment recreates that environment as an illustration.

Assume, though, that we’re requesting an https url. 1  The document will be passed over an encrypted connection and eavesdroppers won’t grab anything.  The images, however, could be passed over HTTP and can be viewed by anyone intercepting network traffic.  If the browser is passing a Referrer header, eavesdroppers will now know exactly what page you’re viewing, can see any cookies on the site, and can see your GET parameters – your username and password. 2

The Results

After making the request and taking a look in Wireshark, it was fairly easy to find an image request on the page. 3

Screenshot-Request

If this were truly an SSL site, the other requests in this image wouldn’t appear (I’m filtering on HTTP requests only), but the GET for the image would still be present and (in most browsers) would still contain the same headers.  The image itself is an innocuous request.  It doesn’t expose anything vital.

The headers are a different story:

Screenshot-Referrer

I’ve highlighted the referral header in the example above.  In plain text, it would be Referer: http://eamann.com/biz/does-the-fold-still-matter/?username=testing&password=1234.  Here we have, exposed for all the world to see, the original web url and it’s plaintext GET parameters. 4

The Implications

Honestly, few of us are ever going to send a username and password pair via GET parameters.  But there are situations where this could still cause an issue.

I use a plugin on my WordPress site called “Share a Draft.”  This plugin allows me to very easily draft a post, and share a private link for that post with peers to review content before publishing anything.  This private link contains a hash, affixed to the URL via a GET parameter, that tells WordPress to give a visitor access to a not-yet-published post.

Again, my site doesn’t contain any sensitive information – but what if it did.  What if, instead of blogging about personal topics, I was writing news articles about major international affairs for a news media organization?  What if I sent a Share a Draft link to a colleague to proofread a post on not-yet-public international policy decisions?  What if my colleague read the post in a Starbucks over open WiFi?

Even if the site itself is encrypted and transferred over SSL, any non-SSL images in the post body can be intercepted by anyone else on that network, potentially revealing the referrer URL, exposing the GET parameter, and allowing an eavesdropper access to sensitive news data before it’s available to the public.

Is this a major security flaw?  No.  But it’s a flaw nonetheless and something security-minded developers and publishers should keep in mind.  I’ll be among the first to admit that thinking about security in this way is extremely paranoid.  I’d also like to point out, though, that professional paranoia is the mark of a good security engineer.

Have I convinced you that “mixed content” warnings are a valid security concern yet?

Notes:

  1. I don’t have an SSL certificate set up for my site because I’m cheap. Also, none of the data on this site is of a sensitive nature, so encryption isn’t a big deal.  If, however, I decide to ever host sensitive data the first thing I’ll do is lock everything down over SSL. ↩
  2. Good browsers are now locking down on this and beginning to omit the Referrer header when making an http asset request on an https page. But there’s no guarantee here, and you’ll never know what browser your visitors are using.  If the page needs to be secure, make sure your assets are secure as well or you’ll be leaking information to would-be attackers! ↩
  3. Remember, we’re taking the example of an SSL site that contains a vanilla HTTP image in its body. ↩
  4. I want to point out once more this will still be exposed on most SSL-secured websites if the image is requested over HTTP.  I requested the page over HTTP because my site doesn’t currently have an SSL certificate.  However, I wanted to present a real demonstration from a real website with data captured live over an open WiFi network.  This is a real request, captured remotely, using readily-available tools and eavesdropping over a real network.  I used my own site as an example so no one can accuse me of hacking their data. ↩

Filed Under: Technology Tagged With: data leakage, data security, encryption, https, mixed content, privacy, ssl, vulnerability

About Me

Eric is a storyteller, web developer, and outdoorsman living in the Pacific Northwest. If he's not working with new tech in web development, you can probably find him out running, climbing, or hiking in the woods.

Get the newsletter