shadow1ng/fscan · error

i18n.GetText("ms17010_ciphertext_too_short")

Error message

i18n.GetText("ms17010_ciphertext_too_short")

What it means

aesDecrypt rejects ciphertext whose decoded length is less than aes.BlockSize (16 bytes) with "ms17010_ciphertext_too_short". CBC mode requires at least one full block, so any shorter decoded blob cannot be a valid AES-CBC ciphertext.

Source

Thrown at plugins/services/ms17010.go:184

}

// 以下是完整的原始MS17010检测和利用代码,保持不变

// AES解密函数 (从legacy/Base.go复制)
func aesDecrypt(crypted string, key string) (string, error) {
	cryptedBytes, err := base64.StdEncoding.DecodeString(crypted)
	if err != nil {
		return "", fmt.Errorf("%s: %w", i18n.GetText("ms17010_base64_decode_failed"), err)
	}

	keyBytes := []byte(key)
	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return "", fmt.Errorf("%s: %w", i18n.GetText("ms17010_aes_cipher_failed"), err)
	}

	if len(cryptedBytes) < aes.BlockSize {
		return "", fmt.Errorf("%s", i18n.GetText("ms17010_ciphertext_too_short"))
	}

	mode := cipher.NewCBCDecrypter(block, keyBytes[:aes.BlockSize])
	mode.CryptBlocks(cryptedBytes, cryptedBytes)

	// 移除PKCS7填充
	padding := int(cryptedBytes[len(cryptedBytes)-1])
	if padding > len(cryptedBytes) || padding > aes.BlockSize {
		return "", fmt.Errorf("%s", i18n.GetText("ms17010_invalid_padding"))
	}

	for i := len(cryptedBytes) - padding; i < len(cryptedBytes); i++ {
		if cryptedBytes[i] != byte(padding) {
			return "", fmt.Errorf("%s", i18n.GetText("ms17010_padding_check_failed"))
		}
	}

	return string(cryptedBytes[:len(cryptedBytes)-padding]), nil

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Base64-decode and assert len >= 16 bytes before calling aesDecrypt.
  2. Verify the payload source actually emits AES-CBC ciphertext (multiple of 16 bytes, IV prepended or keyed separately).
  3. Check the payload wasn't truncated in storage/transport (compare length with the producer's byte count).
  4. If your scheme prepends a 16-byte IV, remember the minimum valid total is 32 bytes (IV + one block).

Example fix

// before
plain, err := aesDecrypt(tok, key)
// after: pre-check decoded size
raw, _ := base64.StdEncoding.DecodeString(tok)
if len(raw) < aes.BlockSize || len(raw)%aes.BlockSize != 0 {
    return fmt.Errorf("ciphertext must be >=16 bytes and block-aligned, got %d", len(raw))
}
plain, err := aesDecrypt(tok, key)
Defensive patterns

Strategy: validation

Validate before calling

raw, err := base64.StdEncoding.DecodeString(payload)
if err != nil { return err }
if len(raw) < aes.BlockSize || len(raw)%aes.BlockSize != 0 {
    return fmt.Errorf("ciphertext must be >=16 bytes and 16-byte aligned, got %d", len(raw))
}

Try / catch

plain, err := aesDecrypt(payload, key)
if err != nil && strings.Contains(err.Error(), "too_short") {
    return fmt.Errorf("truncated or non-CBC payload")
}

Prevention

When it happens

Trigger: aesDecrypt receives a crypted string that base64-decodes to 0–15 bytes: empty string, truncated payload, or data that was never AES-CBC encrypted (e.g. plaintext, checksum, or IV-only).

Common situations: Copy/paste truncation of long payloads, feeding the IV alone instead of IV||ciphertext, or decrypting a field produced by a different scheme (GCM tag, hex blob).

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/9495089900659145. Report an issue: GitHub.