HIGH prompt injectionhmac signatures

Prompt Injection with Hmac Signatures

How Prompt Injection Manifests in Hmac Signatures

Prompt injection in HMAC-based authentication systems occurs when an attacker manipulates input data to trick the API into accepting malicious requests or leaking sensitive information. Unlike traditional prompt injection in LLMs, HMAC prompt injection exploits the cryptographic signing process itself.

The most common manifestation involves crafting request payloads that, when signed, create collisions or bypass authorization checks. For example, an attacker might manipulate array parameters or JSON structures to alter the canonical string that gets hashed:

// Malicious payload exploiting HMAC canonicalization
const maliciousPayload = { 'action': 'transfer', 'amount': 1000, 'account': 'victim-123', // Array parameter that gets sorted differently during signing 'items': ['item1', 'item2', 'item3'] };

// Attacker crafts request where items array sorting affects signature
// If the server sorts items before signing but the client doesn't,
// the signatures won't match but the server might process the request

Another attack vector involves time manipulation in HMAC signatures. Attackers can exploit clock skew between client and server to create valid signatures that appear legitimate but execute malicious actions:

// Time-based prompt injection
const now = new Date().getTime() - 3600000; // 1 hour in the past
const timestamp = Math.floor(now / 1000);
const message = `${HTTP_METHOD}${URL_PATH}${timestamp}${PAYLOAD}`;
const signature = crypto.createHmac('sha256', SECRET_KEY).update(message).digest('hex');

// This signature might be valid during server's clock skew window,
// allowing replay attacks or bypassing rate limiting

Header manipulation represents another critical attack surface. Attackers can inject additional headers or modify existing ones to change the canonical string without invalidating the signature:

// Header injection attack
const originalHeaders = { 'Content-Type': 'application/json', 'X-Custom-Header': 'value' }; // Attacker adds headers that affect canonical string but not signature calculation
const maliciousHeaders = { ...originalHeaders, 'X-Forged-Header': 'malicious-value', // Changes canonical string 'X-Forwarded-For': '127.0.0.1' // Might bypass IP-based restrictions };

HMAC Signatures-Specific Detection

Detecting prompt injection in HMAC systems requires analyzing the cryptographic signing process and request handling. The first step is verifying canonical string construction consistency between client and server:

// Detection: Verify canonical string consistency
function detectCanonicalizationIssues(request) { const clientCanonical = buildCanonicalString(request); const serverCanonical = buildServerCanonicalString(request); if (clientCanonical !== serverCanonical) { console.warn('Canonical string mismatch detected - potential injection vector'); return true; } return false; }

Parameter tampering detection is crucial. Implement strict type checking and length validation for all parameters that contribute to the HMAC signature:

// Detection: Parameter tampering analysis
function analyzeParameters(payload) { const suspiciousPatterns = [ /\$\{.*\}/, // Template injection /eval\(.*\)/, // Code execution /\.\./, // Path traversal /[<>]/, // HTML injection /\n\s*\n/ // Header injection ]; for (const [key, value] of Object.entries(payload)) { if (typeof value === 'string' && suspiciousPatterns.some(pattern => pattern.test(value))) { console.warn(`Suspicious parameter detected: ${key} = ${value}`); return true; } } return false; }

Time-based detection helps identify clock skew exploitation attempts. Monitor signature timestamps for anomalies:

// Detection: Time-based anomalies
function detectTimestampAnomalies(signatureTimestamp) {
  const currentTime = Date.now() / 1000;
  const maxSkew = 300; // 5 minutes
  
  if (Math.abs(currentTime - signatureTimestamp) > maxSkew) {
    console.warn('Timestamp outside acceptable skew range');
    return true;
  }
  
  // Detect rapid succession of requests with similar timestamps
  if (recentTimestamps.includes(signatureTimestamp)) {
    console.warn('Potential replay attack detected');
    return true;
  }
  
  recentTimestamps.push(signatureTimestamp);
  if (recentTimestamps.length > 100) {
    recentTimestamps.shift();
  }
  
  return false;
}

HMAC Signatures-Specific Remediation

Remediation starts with implementing strict canonical string construction that eliminates ambiguity. Use deterministic ordering and explicit encoding:

// Remediation: Strict canonical string construction
function buildCanonicalString(request) {
  const sortedKeys = Object.keys(request.payload).sort();
  const canonicalParams = sortedKeys.map(key => {
    const value = request.payload[key];
    const encodedKey = encodeURIComponent(key);
    const encodedValue = encodeURIComponent(String(value));
    return `${encodedKey}=${encodedValue}`;
  }).join('&');
  
  const canonicalString = [
    request.method.toUpperCase(),
    request.path,
    request.timestamp,
    canonicalParams
  ].join('\n');
  
  return canonicalString;
}

Implement parameter type enforcement and strict validation to prevent injection through malformed data:

// Remediation: Parameter validation and type enforcement
function validateParameters(payload) {
  const schema = {
    action: { type: 'string', enum: ['transfer', 'query', 'update'] },
    amount: { type: 'number', min: 0.01, max: 1000000 },
    account: { type: 'string', pattern: '^[a-zA-Z0-9-]{3,20}$' },
    items: { type: 'array', items: { type: 'string', pattern: '^[a-zA-Z0-9]{1,50}$' } }
  };
  
  for (const [key, rules] of Object.entries(schema)) {
    const value = payload[key];
    if (value === undefined) continue;
    
    if (rules.type === 'string') {
      if (typeof value !== 'string' || !rules.pattern.test(value)) {
        throw new Error(`Invalid parameter: ${key}`);
      }
    } else if (rules.type === 'number') {
      if (typeof value !== 'number' || value < rules.min || value > rules.max) {
        throw new Error(`Invalid parameter: ${key}`);
      }
    } else if (rules.type === 'array') {
      if (!Array.isArray(value)) {
        throw new Error(`Invalid parameter: ${key}`);
      }
      for (const item of value) {
        if (typeof item !== 'string' || !rules.items.pattern.test(item)) {
          throw new Error(`Invalid array item in ${key}`);
        }
      }
    }
  }
}

Implement replay protection and clock synchronization mechanisms:

// Remediation: Replay protection and clock synchronization
class ReplayProtection {
  constructor() {
    this.usedTimestamps = new Set();
    this.maxWindow = 300; // 5 minutes
  }
  
  isReplay(timestamp) {
    const current = Math.floor(Date.now() / 1000);
    const windowStart = current - this.maxWindow;
    
    // Remove old timestamps
    this.usedTimestamps.forEach(ts => {
      if (ts < windowStart) {
        this.usedTimestamps.delete(ts);
      }
    });
    
    // Check if timestamp already used
    if (this.usedTimestamps.has(timestamp)) {
      return true;
    }
    
    this.usedTimestamps.add(timestamp);
    return false;
  }
  
  isClockSkewAcceptable(timestamp) {
    const current = Math.floor(Date.now() / 1000);
    const maxSkew = 300;
    return Math.abs(current - timestamp) <= maxSkew;
  }
}

Related CWEs: llmSecurity

CWE IDNameSeverity
CWE-754Improper Check for Unusual or Exceptional Conditions MEDIUM

Frequently Asked Questions

How does prompt injection in HMAC signatures differ from traditional prompt injection?
Traditional prompt injection targets language models by manipulating input text to override system instructions. HMAC prompt injection exploits the cryptographic signing process itself, manipulating request parameters, headers, or timestamps to create valid signatures that execute malicious actions or bypass authorization. The attack surface is the canonical string construction and parameter handling rather than LLM system prompts.
Can middleBrick detect prompt injection vulnerabilities in HMAC-based APIs?