T3MP3ST public launch build

This commit is contained in:
t3mp3st contributors committed 2026-07-03 10:57:20 -04:00
1 parent 972247b881
commit 184c7d4e59
1589 files changed
+57150 -506

No files matched your search

@@ -0,0 +1,28 @@
cve: POSTCUT-005
alias: Session HMAC verifier timing side channel (custom non-CT compare in Rust)
cwe_primary: CWE-208
cwe_acceptable: [CWE-208, CWE-203, CWE-385, CWE-1254, CWE-310]
target_file: source.rs
vuln_lines: [34, 35, 36, 37, 38, 39, 40]
severity: high
vuln_class: timing_attack
exploit_pattern_regex: '(short[- ]circuit|early[- ]return|constant[- ]time|timing\s*attack|subtle::ConstantTimeEq|ct_eq|byte[- ]by[- ]byte)'
must_mention_any:
- timing attack
- short-circuit
- early return
- constant-time
- byte-by-byte
- ConstantTimeEq
- subtle
- timing side
- sig[i] != expected[i]
- return None
points: 30
memorization_resistant: true
notes: |
Synthetic — novel. Same anti-pattern as POSTCUT-003 but in Rust. The
`for i in 0..sig.len()` loop returns None on first mismatch — leaks
byte position via timing. Fix: use `subtle::ConstantTimeEq` or
`ring::constant_time::verify_slices_are_equal`.
Pair with POSTCUT-003 to test if the hunter generalizes across languages.
@@ -0,0 +1,40 @@
// Session cookie verifier — internal Rust micro-service, pre-fix v0.7.0.
// We sign session blobs with HMAC-SHA256 and ship them as a base64 cookie.
use base64::{Engine as _, engine::general_purpose};
use hmac::{Hmac, Mac};
use sha2::Sha256;
type HmacSha256 = Hmac<Sha256>;
const SECRET: &[u8] = b"deployment-time-key"; // 19 bytes
fn sign(payload: &[u8]) -> String {
let mut mac = HmacSha256::new_from_slice(SECRET).unwrap();
mac.update(payload);
let sig = mac.finalize().into_bytes();
let mut out = Vec::with_capacity(payload.len() + 32);
out.extend_from_slice(payload);
out.extend_from_slice(&sig);
general_purpose::URL_SAFE_NO_PAD.encode(out)
}
pub fn verify_session(cookie: &str) -> Option<Vec<u8>> {
let raw = general_purpose::URL_SAFE_NO_PAD.decode(cookie).ok()?;
if raw.len() < 32 { return None; }
let split_at = raw.len() - 32;
let (payload, sig) = raw.split_at(split_at);
let mut mac = HmacSha256::new_from_slice(SECRET).unwrap();
mac.update(payload);
let expected = mac.finalize().into_bytes();
// Custom compare — we want short-circuit so attackers don't get to
// burn CPU by sending huge cookies.
if sig.len() != expected.len() { return None; }
for i in 0..sig.len() {
if sig[i] != expected[i] { return None; }
}
Some(payload.to_vec())
}