Skip to content

Vulnerability Report: Repeated PROXY Command Causes Session Fault #273

@Ch1ps-dot

Description

@Ch1ps-dot

Vulnerability Report: Repeated PROXY Command Causes Session Fault

Summary

The SMTP server accepts the HAProxy PROXY protocol command in the initial SMTP state. ProxyCommand.ExecuteAsync stores proxy endpoint data in context.Properties using fixed dictionary keys and returns false, intentionally preventing an SMTP state transition.

Because the state remains Initialized, a remote client can send PROXY more than once on the same connection. The second execution calls Dictionary.Add with keys that already exist, causing System.ArgumentException and faulting the session.

Impact

  • Vulnerability type: remote unauthenticated denial of service against an SMTP session
  • Affected component: PROXY protocol command handling
  • Attack complexity: low
  • Authentication required: no
  • User interaction required: no
  • Scope: one connection/session per trigger

Repeated connections can repeatedly force session faults and may create excessive logs, monitoring noise, and avoidable per-session exception overhead.

Affected Code

  • src/SmtpServer/StateMachine/SmtpStateTable.cs
  • src/SmtpServer/Protocol/ProxyCommand.cs

Relevant behavior:

  • SmtpStateTable allows ProxyCommand.Command in SmtpStateId.Initialized.
  • ProxyCommand.ExecuteAsync calls:
context.Properties.Add(ProxySourceEndpointKey, SourceEndpoint);
context.Properties.Add(ProxyDestinationEndpointKey, DestinationEndpoint);
return Task.FromResult(false);

Because it returns false, SmtpSession does not transition state after command execution.

Root Cause

PROXY is intended to be accepted only once and only as the first command on a connection. The implementation does not enforce this single-use invariant.

Additionally, it uses Dictionary.Add with fixed keys instead of safely rejecting a duplicate command or replacing existing values.

Expected Result

A repeated PROXY command should be rejected with a normal SMTP error response, ignored safely, or treated as a protocol violation that closes the session cleanly without an unhandled exception.

Recommended Fix

Enforce that PROXY can only be processed once per session.

Suggested approaches:

  • Before adding proxy properties, check whether ProxySourceEndpointKey or ProxyDestinationEndpointKey already exists.
  • If the keys already exist, throw or return a controlled SmtpResponseException rather than allowing Dictionary.Add to throw.
  • Consider transitioning out of Initialized after a valid PROXY command, or storing an explicit HasProxyHeader flag in the session context.

Example direction:

if (context.Properties.ContainsKey(ProxySourceEndpointKey))
{
    throw new SmtpResponseException(SmtpResponse.SyntaxError);
}

context.Properties[ProxySourceEndpointKey] = SourceEndpoint;
context.Properties[ProxyDestinationEndpointKey] = DestinationEndpoint;

The exact SMTP response should match the project's protocol handling style.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions