PyLoris: A Python implementation of Slowloris

I came across a wonderful idea on Hack a Day recently: a Denial of Service attack that overwhelms only the service under attack. After reading through RSnake's two writeups, I decided to take a swing at the code. Thus PyLoris was born.

RSnake's tool, Slowloris, is elegant and effective. Its basic principal is that it sends a large number of HTTP requests to a webserver, keeping the connections open for extended periods of time by continuing to send headers to the server. Because Slowloris never completes a request, and because the popular webservers limit the number of concurrent requests allowed, this will eventually fill all usable connections to the server. The nice side effect of this is that the webserver is the only service that is affected; the network and memory are undamaged leaving all other services on the system fully operational.

PyLoris is written entirely in Python, utilizes only standard modules, is OS and platform independent, and is less than 100 lines of code. It runs a little differently than Slowloris, in that it throttles the entire request, allows users to specify the bandwidth for the connection as well as how large the request is. Unfortunately, the brevity of the code does not leave room for SSL/TLS handling, so only HTTP is supported for the time being.

Here is a brief description of the things PyLoris can do:

Usage: pyloris.py [options] www.host.com Options: -h, --help show this help message and exit -c COUNT, --count=COUNT Number of requests to perform (default = 50) -f, --finish Complete each session rather than leave them unfinished (lessens the effectiveness) -g GET, --get=GET Page to request from the server (default = /) -l, --loop Loop indefinitely (overrides -c) -p PORT, --port=PORT Port to initiate attack on (default = 80) -s SIZE, --size=SIZE Size of data segment to attach in cookie (default = 0) -t THROTTLE, --throttle=THROTTLE Throttle each request, bytes per second (default = 1) -u USERAGENT, --useragent=USERAGENT The User-Agent string for connections (defaut = pyloris) -w WAIT, --wait=WAIT Seconds between starting sessions (default = 1)
-

If a user wanted to run a basic test against NOM, it would be as simple as:

-

But this is hardly a thorough test, there is a lot to be done to improve it,

(1) it limits the total number of requests made to a meager 50

(2) it sends a relatively small request

(3) it requests a page that doesn't exists

(4) it advertises PyLoris in the User-Agent (err...)

A more malicious individual might perform a test like so:

$ ./pyloris www.nationformarriage.org -l -s 600000 -g "/site/c.omL2KeN0LzH/b.3836955/k.BEC6/Home.htm"-u "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/2.0.172.31 Safari/530.5" -w 0.1 -t 25
-

This test will pound the server with an unyeilding number of requests, each request over 600 kB in length, starting 10 connections per second, each throttled at 25 B/s, and masquerading as Google Chrome.

As stated before, PyLoris runs on Linux, Windows, and Mac OS X. Additionally, it should work on any platform capable of running Python with Threads. If you find any errors or bugs to report, please submit them via SourceForge.

Post your comment

Comments

  • Motoma,

    You're slightly off the mark here... Yes circuits.web is a WSGI compliant web framework that can be run with mod_wsgi behind Apache - however this is not what I was testing...

    I was testing circuits.web's Web Server - This is the simplest case I was testing:

    {{{
    #!python
    from circuits.web import Server, Controller

    class Root(Controller):

    def index(self):
    return "Helllo World!"

    (Server(8000) + Root()).run()

    This was tested with PyLoris on my Desktop PC (I have no other hardware/platforms). This is a single-process/single-threaded event-driven application. circuits.web is akin to lighttpd and nginx (which are unaffected by PyLoris) as you've stated.

    The point I was trying to make earlier was that the kernel killed PyLoris - most likely because it consumed far too much system memory. It's feasible that PyLoris has a memory leak ?

    Anyway - regardless - circuits.web (the server - not deployed under apache+mod_wsgo), resists PyLoris' attack.

    --JamesMills (prologic)

    Posted by James Mills, 22/06/2009 6:12pm (4 hours ago)

  • James,

    You are quite astute to test this script against your web server. You are right to assume that this vulnerability does not affect all servers; Apache, dhttpd, and Squid all show weakness to this brand of attack, while IIS, lighthttpd, and nginx seem to resist it well.

    Assessing the documentation you linked, it appears that your webserver is actually Apache with mod_wsgi calling your Python framework; unless you have configured your server another way.

    What I am most curious about is the kernel error you received. More than likely this stopped the test before threads could finish spawning. Could you elaborate on your system configuration? What operating system was running? Another important factor: how did you invoke PyLoris on the command line?

    Get back to me and we will see if we can get a thorough test running.

    Cheers,
    Motoma

    Posted by Motoma, 22/06/2009 5:39am (17 hours ago)

  • Hi,

    A friend of mine (Matthew) linked me to this post. I was intrigued at first then decided to test pyloris against my Web Server (written in Python). circuits.web (a set of Web components for circuits) is a high performance scalable Web Server - that does beat all other python web server(s)/framework(s) (so far).

    circuits: http://trac.softcircuit.com.au/circuits/
    circuits.web: http://trac.softcircuit.com.au/circuits/wiki/docs/circuits.web

    When I ran some tests on my local Desktop PC (unfortunately I don't have access to better hardware - let alone a network of PCs to run proper tests on), pyloris died and was Killed by the kernel. circuits.web still happily running.

    cheers
    James

    Posted by James Mills, 21/06/2009 11:11pm (23 hours ago)

RSS feed for comments on this page