Skip to main content

DNSSEC RFC 9276

Comments

16 comments

  • cPRex Jurassic Moderator

    Hey there!  I did some research on this and found that we should be supporting iterations of 0 according to the RFC:

    https://datatracker.ietf.org/doc/rfc9276/

      Note that [RFC5155] describes the Iterations field as follows
    
       |  The Iterations field defines the number of additional times the
       |  hash function has been performed.
    
       This means that an NSEC3 record with an Iterations field of 0
       actually requires one hash iteration.

    I also confirmed that trying a value of 0 gives me the following error from the API call:

    reason: "API failure: (XID 7sm6mf) “nsec3_iterations” must be a positive integer less than or equal to 2500."

    I've created case CPANEL-45613 for our developers to look into this, and I'll be sure to post an update here if I hear back from them!

    0
  • Fraak Schoombert

    Hi,

    Is there an update available on CPANEL-45613 ? This issue is currently affecting over 50 of my domains.

    Thank you

    0
  • cPRex Jurassic Moderator

    I don't have any updates on this just yet but it is going to get discussed in a meeting next Friday. 

    0
  • cPRex Jurassic Moderator

    i did want to let you know our developers are investigating the issue at this time - I'll post any other updates once I get them!

    0
  • Fraak Schoombert

    Another month has passed. I was wondering if there's any update available on this issue. Thank you

    0
  • cPRex Jurassic Moderator

    I'm not seeing any updates to the case at this time.

    0
  • Fraak Schoombert

    It's been three months - has there been any progress on this? If not, perhaps it's time to report this as a security vulnerability. In theory, it could be exploited for CPU-exhausting DoS attacks, in addition to the increased risk of interoperability issues mentioned in the original post.

    Thank you

    0
  • cPRex Jurassic Moderator

    I did speak with the team about this and I have two thoughts.  The first is going to sound dismissive, and I know that even before I type it out, but I want to make sure I'm presenting the whole truth.  This thread represents the entire number of complaints/reports we have about this issue, so that makes it a very low priority case with only two users talking about the issue.  It just isn't affecting enough users for us to give it priority over more pressing issues.

    However, you did mention a potential security issue related to this behavior.  If you have a wow to show and reproduce that exploit it would be best to send that to the security team at security@cpanel.net so they can review that, as the team I talked to today about this didn't see any immediate threats from the details we have so far.

    0
  • Are

    I'm waiting for this also. 

    0
  • Kasper Jepsen

    This thread represents the entire number of complaints/reports we have about this issue, so that makes it a very low priority case with only two users talking about the issue.

    I don't think that's a fair assumption. I've been following this thread since it was created as I initially had the same thoughts as webo3com. I kept the thread bookmarked until I noticed I could follow the thread (by clicking "Follow").

    A message from you confirmed that developers was looking into this. If I see that, I'm not going to reply to the thread. I usually just lurk - but I'm very interested to see this being implemented.

    4
  • cPRex Jurassic Moderator

    Lurking is fun, but it doesn't help me make a case with developers ;)

    0
  • webo3com

    Hi,

    I’d like to respectfully express some concern and frustration regarding the lack of movement on this issue.

    If cPanel chooses to implement features like DNSSEC support, it should also take responsibility for implementing them in accordance with relevant RFC standards — in this case, RFC 9276. PowerDNS supports the correct behavior (NSEC3 with 0 iterations), yet cPanel's interface and API explicitly block this configuration.

    The fact that this was acknowledged 10 months ago with a promise that developers would investigate — and that no further action has been taken — is disappointing. We’re not asking for a new feature; we’re asking for compliance with DNS standards and for removal of an artificial limitation that prevents correct, secure use of DNSSEC.

    As noted in RFC 9276, using iterations > 0 can lead to CPU-exhausting DoS vulnerabilities and interoperability issues. That alone should warrant prioritization — especially since this is a security-related feature.

    We’re all paying customers here, and I think it’s fair to expect security-related standards to be followed. If a new feature can't be implemented correctly according to the RFC, perhaps it shouldn't be released until it is. Otherwise, we're left with broken implementations and workarounds that aren't even cluster-aware.

    2
  • cPRex Jurassic Moderator

    webo3com - thanks for the feedback.  I will say that just because I create a case doesn't guarantee that developers will fix it, as it just brings the issue to their attention.  The still ultimately get to decide what gets handled, although I can push for various things to get priority as I get feedback.

    I'm definitely going to let them know that more people have responded to this in the last week.

    0
  • Fraak Schoombert

    I share the frustration and opinion of webo3com. As requested by cPRex, I've created a proof of concept (PoC) and shared it with security@cpanel.net. For full transparency, here is the script along with the accompanying email I sent.

     

    Dear cPanel Support Team,

    I'm writing regarding your DNSSEC implementation, specifically concerning the NSEC3 iteration count setting. As you're aware, your current implementation enforces hash + 7 iterations, which conflicts with RFC 9276, which explicitly states: "If NSEC3 must be used, then an iterations count of 0 MUST be used to alleviate computational burdens."

    As requested in our previous correspondence on your forum, you asked for evidence demonstrating that iteration counts other than 0 increase the impact of CPU-exhausting DoS attacks. I've attached a proof of concept script written in Python that conclusively demonstrates this security vulnerability.
    To use this script, make sure to install the required dependencies (matplotlib, numpy, tabulate, psutil) and run it with 'python3 nsec3_cpu_attack_poc.py'
    You can also customize the parameters with command-line arguments:
    --max-iterations: Set the maximum iteration count to test
    --domains: Number of domains to process in each test
    --processes: Number of processes to use (simulates distributed attack)

    While the performance impact may seem negligible when processing a handful of domains, the real danger appears at scale. The attached script shows how computational requirements increase exponentially with higher iteration counts. In a DoS attack scenario, attackers specifically target resource-intensive operations. With iteration count = 7, each malicious query consumes significantly more CPU resources than with iteration count = 0, making the attack vastly more effective. Additionally, a single attacker can generate thousands of malicious NSEC3 queries across distributed sources, and each additional iteration multiplies the server-side resource consumption without increasing the attacker's resource requirements. And lastly; RFC 9276 standard wasn't created arbitrarily - it specifically addresses this security vulnerability. Organizations running non-compliant implementations face increased risk.

    While the impact might seem low when testing with just a few domains in a controlled environment, I urge you to consider the bigger picture. Hosting providers manage thousands of domains and during peak traffic or attack conditions, these additional computational burdens compound quickly. Security standards exist precisely to prevent these types of vulnerabilities. The proof of concept demonstrates that servers using your current implementation require substantially more resources than RFC-compliant servers (iterations=0) to handle the same query volume, creating an unnecessary attack surface.

    I respectfully request that you prioritize bringing your DNSSEC implementation into compliance with RFC 9276 by setting the NSEC3 iteration count to 0. This change would significantly improve security for all cPanel customers while reducing server resource consumption.

    Thank you for your attention to this important security matter.

    Kind regards

     



    #!/usr/bin/env python3
    """
    NSEC3 Iteration Count CPU DoS Attack Proof of Concept

    This script demonstrates how increasing NSEC3 iteration counts significantly
    impacts CPU resources, creating vulnerability to DoS attacks.

    Reference: RFC 9276 section 3.3
    https://datatracker.ietf.org/doc/html/rfc9276#section-3.3
    """

    import time
    import hashlib
    import multiprocessing
    import argparse
    import matplotlib.pyplot as plt
    import numpy as np
    from tabulate import tabulate
    import psutil

    def nsec3_hash(domain, salt, iterations):
        """Perform NSEC3 hash calculation with given iterations."""
        # Convert domain to lowercase
        domain = domain.lower()
        
        # Initial hash
        result = domain.encode('utf-8')
        
        # Salt is appended to the hash input at each iteration
        salt_bytes = bytes.fromhex(salt) if salt else b''
        
        # Perform the specified number of iterations
        for _ in range(iterations + 1):  # +1 because spec defines iterations as additional rounds
            result = hashlib.sha1(result + salt_bytes).digest()
            
        return result.hex()

    def attack_simulation(iterations, domains_count=1000, processes=1):
        """
        Simulate attack by calculating multiple NSEC3 hashes with specified iterations.
        Returns the total time taken.
        """
        salt = "AABBCCDDEEFF"  # Example salt
        domains = [f"test{i}.example.com" for i in range(domains_count)]
        
        start_cpu = psutil.cpu_percent(interval=None)
        start_time = time.time()
        
        if processes > 1:
            # Multiprocessing approach to simulate distributed attack
            pool = multiprocessing.Pool(processes)
            results = []
            
            for domain in domains:
                results.append(pool.apply_async(nsec3_hash, (domain, salt, iterations)))
            
            # Wait for all processes to complete
            pool.close()
            pool.join()
            
            # Ensure all results are retrieved
            for r in results:
                r.get()
        else:
            # Single process approach
            for domain in domains:
                nsec3_hash(domain, salt, iterations)
        
        end_time = time.time()
        end_cpu = psutil.cpu_percent(interval=None)
        
        return {
            "time_taken": end_time - start_time,
            "cpu_change": end_cpu - start_cpu
        }

    def run_benchmark(max_iteration=15, domain_count=1000, processes=1):
        """Run benchmark tests for different iteration counts."""
        results = []
        iteration_values = list(range(0, max_iteration + 1))
        
        print(f"\nRunning benchmark with {domain_count} domains and {processes} processes...")
        
        for iterations in iteration_values:
            print(f"Testing iterations={iterations}...")
            result = attack_simulation(iterations, domain_count, processes)
            results.append({
                "iterations": iterations,
                "time_taken": result["time_taken"],
                "requests_per_sec": domain_count / result["time_taken"],
                "cpu_impact": result["cpu_change"]
            })
            
        return results

    def visualize_results(results):
        """Create visualization of the benchmark results."""
        iterations = [r["iterations"] for r in results]
        times = [r["time_taken"] for r in results]
        requests_per_sec = [r["requests_per_sec"] for r in results]
        
        # Prepare data for table
        table_data = []
        for r in results:
            table_data.append([
                r["iterations"],
                f"{r['time_taken']:.4f}s",
                f"{r['requests_per_sec']:.2f}",
                f"{r['cpu_impact']:.2f}%"
            ])
        
        # Display tabular results
        print("\nBenchmark Results:")
        print(tabulate(
            table_data,
            headers=["Iterations", "Time (s)", "Requests/sec", "CPU Impact (%)"],
            tablefmt="grid"
        ))
        
        # Calculate the fold increase compared to 0 iterations
        baseline_time = times[0]
        relative_times = [t/baseline_time for t in times]
        
        print(f"\nTime taken with 0 iterations: {baseline_time:.4f} seconds")
        print(f"Time taken with {iterations[-1]} iterations: {times[-1]:.4f} seconds")
        print(f"Performance impact: {relative_times[-1]:.2f}x slower")
        
        # Calculate the attack amplification factor
        print("\nDoS Attack Amplification Analysis:")
        print(f"With 0 iterations (RFC 9276 compliant), processing {len(results[0])} requests took {times[0]:.4f} seconds")
        print(f"With {iterations[-1]} iterations, the same number of requests took {times[-1]:.4f} seconds")
        print(f"Attack amplification factor: {times[-1]/times[0]:.2f}x")
        
        # Calculate server resources needed
        print("\nServer Resource Requirements:")
        baseline_resources = 1.0  # Normalized to 1 server
        for i, t in enumerate(times):
            if i == 0:
                continue
            relative_resource = t / times[0]
            print(f"Iterations={iterations[i]}: Requires {relative_resource:.2f}x server resources compared to iterations=0")

    def main():
        parser = argparse.ArgumentParser(description='NSEC3 Iteration Count DoS Attack PoC')
        parser.add_argument('--max-iterations', type=int, default=10, 
                            help='Maximum iteration count to test (default: 10)')
        parser.add_argument('--domains', type=int, default=1000, 
                            help='Number of domains to process in each test (default: 1000)')
        parser.add_argument('--processes', type=int, default=4, 
                            help='Number of processes to simulate distributed attack (default: 4)')
        args = parser.parse_args()
        
        print("=" * 80)
        print("NSEC3 Iteration Count DoS Attack Proof of Concept")
        print("=" * 80)
        print("\nThis script demonstrates how NSEC3 iteration counts impact CPU resources")
        print("and create vulnerability to DoS attacks, as mentioned in RFC 9276.")
        print("\nReference: RFC 9276 section 3.3")
        print("https://datatracker.ietf.org/doc/html/rfc9276#section-3.3")
        
        # Run the benchmark
        results = run_benchmark(args.max_iterations, args.domains, args.processes)
        
        # Visualize and analyze the results
        visualize_results(results)
        
        print("\nConclusion:")
        print(f"This proof of concept demonstrates that using {results[-1]['iterations']} iterations")
        print(f"instead of 0 iterations (as required by RFC 9276) makes the server")
        print(f"{results[-1]['time_taken']/results[0]['time_taken']:.2f}x more vulnerable to DoS attacks.")
        print("\nThe RFC 9276 recommendation to use iterations=0 is clearly justified by these results.")
        print("Higher iteration counts create significant CPU load that can be exploited in DoS attacks.")

    if __name__ == "__main__":
        main()
    0
  • cPRex Jurassic Moderator

    I personally can't comment on security issues like this, but I've brought this up with our team and I'll let you know what they say. 

    0
  • cPRex Jurassic Moderator

    I did confirm that our team is looking into this behavior now, although I don't have any ETA on the specific resolution.

    1

Please sign in to leave a comment.