A padding oracle is a decryption process that reveals whether submitted ciphertext has valid padding without directly revealing its plaintext. That single yes-or-no signal can enable recovery of the entire message. section 5.4
A typical failure appears when a server decrypts AES-CBC data, validates PKCS#7 padding, and returns distinguishable errors for invalid padding, invalid ciphertext, or malformed timestamps. Troubleshooting information becomes a decryption signal. section 5.4.1
Listing 5.1 impl_padding_oracle.go
func PadWithPKCS7(data []byte, blockSize int) ([]byte, error) {
if blockSize <= 0 {
return nil, fmt.Errorf("invalid block size")
}
if data == nil {
return nil, fmt.Errorf("input data is nil")
}
padding := blockSize - len(data)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding) #1
return append(data, padtext...), nil
}
PKCS#7 padding appends bytes whose value equals the number of padding bytes; validation checks that the final bytes repeat that value. section 5.4.1
A CBC padding-oracle attack proceeds by manipulating the block preceding a target block:
- Submit modified ciphertexts while changing the final byte of the preceding block until the target plaintext ends in 0x01. section 5.4.2
- Repeat with padding values 0x02 through the block size, then process preceding blocks until the plaintext is recovered. section 5.4.2
Encrypted timestamp service
A service returns an encrypted timestamp and later accepts it to calculate elapsed time. Its padding-specific error enables an exploit that recovers a plaintext such as “Fri Jun 9 14:39:01 PDT 2023.”
