release: v0.7.1 — Security-Patch (R-01 bis R-06)
Sanctum Release / Build & Release (Windows x86_64) (push) Waiting to run
Sanctum Release / Build & Release (Windows x86_64) (push) Waiting to run
- R-01: Bereinigung verbliebener Restbehauptungen in Doku und Code (LEGAL.md, README.md, QUICKSTART.md, main.rs, crypto/storage/recovery/verify.rs) - R-02: Lückenloser Carrier-Schutz in SanctumFs::copy (Quelle & Ziel) und sync (Pull-Skip & Push-Schutz) - R-03: Shared Dateinamen-Validierung (validate_node_name) in pathutil.rs, durchgesetzt in storage.rs und vfs.rs - R-04: Fail-closed Release-Packaging & obligatorische Minisign-Signatur in CI (.gitea/workflows/release.yaml) und Scripts - R-05: Session-Token Beseitigung im argv: In-Process Win32 WNetAddConnection2W/WNetCancelConnection2W, kein gio argv-Token, Multi-Auth HTTP Middleware (Basic Auth, X-Sanctum-Token, Path-Fallback) mit 401 WWW-Authenticate - R-06: Sofortiges Löschen von SANCTUM_RECOVERY_KEY aus der Prozessumgebung
This commit is contained in:
@@ -1094,10 +1094,8 @@ async fn test_webdav_loopback_session_token_and_host_validation() {
|
||||
|
||||
let fs = SanctumFs::new(db.clone(), dek.clone(), FORMAT_VERSION);
|
||||
let session_token = "deadbeefcafebabe0123456789abcdef";
|
||||
let token_path_prefix = format!("/{}", session_token);
|
||||
|
||||
let dav_server = DavHandler::builder()
|
||||
.strip_prefix(token_path_prefix.clone())
|
||||
.filesystem(Box::new(fs))
|
||||
.locksystem(FakeLs::new())
|
||||
.build_handler();
|
||||
@@ -1109,11 +1107,11 @@ async fn test_webdav_loopback_session_token_and_host_validation() {
|
||||
let server_handle = tokio::spawn(serve_webdav_loop(
|
||||
listener,
|
||||
dav_server,
|
||||
token_path_prefix.clone(),
|
||||
session_token.to_string(),
|
||||
shutdown_rx,
|
||||
));
|
||||
|
||||
// 3. Angriffstest A: Unbefugter Zugriff auf Root ohne Session-Token -> 403 Forbidden
|
||||
// 3. Angriffstest A: Unbefugter Zugriff auf Root ohne Session-Token -> 401 Unauthorized mit WWW-Authenticate
|
||||
{
|
||||
let mut stream = TcpStream::connect(addr).await.unwrap();
|
||||
let req = format!("GET / HTTP/1.1\r\nHost: 127.0.0.1:{}\r\nConnection: close\r\n\r\n", addr.port());
|
||||
@@ -1122,8 +1120,13 @@ async fn test_webdav_loopback_session_token_and_host_validation() {
|
||||
stream.read_to_end(&mut resp).await.unwrap();
|
||||
let resp_str = String::from_utf8_lossy(&resp);
|
||||
assert!(
|
||||
resp_str.starts_with("HTTP/1.1 403 Forbidden"),
|
||||
"Anfrage ohne Session-Token muss mit 403 Forbidden abgewiesen werden, erhalten:\n{}",
|
||||
resp_str.starts_with("HTTP/1.1 401 Unauthorized"),
|
||||
"Anfrage ohne Session-Token muss mit 401 Unauthorized abgewiesen werden, erhalten:\n{}",
|
||||
resp_str
|
||||
);
|
||||
assert!(
|
||||
resp_str.to_lowercase().contains("www-authenticate: basic realm=\"sanctum\""),
|
||||
"401-Antwort muss WWW-Authenticate Header enthalten, erhalten:\n{}",
|
||||
resp_str
|
||||
);
|
||||
}
|
||||
@@ -1143,7 +1146,7 @@ async fn test_webdav_loopback_session_token_and_host_validation() {
|
||||
);
|
||||
}
|
||||
|
||||
// 5. Legitimer Zugriff: Korrektes Session-Token & Loopback-Host -> 200 OK
|
||||
// 5. Legitimer Zugriff: Korrektes Session-Token via Path-Prefix Fallback -> 200 OK
|
||||
{
|
||||
let mut stream = TcpStream::connect(addr).await.unwrap();
|
||||
let req = format!("OPTIONS /{}/ HTTP/1.1\r\nHost: 127.0.0.1:{}\r\nConnection: close\r\n\r\n", session_token, addr.port());
|
||||
@@ -1162,6 +1165,23 @@ async fn test_webdav_loopback_session_token_and_host_validation() {
|
||||
);
|
||||
}
|
||||
|
||||
// 6. Legitimer Zugriff: HTTP Basic Auth (R-05) -> 200 OK
|
||||
{
|
||||
use base64::Engine;
|
||||
let auth_hdr = format!("Basic {}", base64::engine::general_purpose::STANDARD.encode(format!("sanctum:{}", session_token)));
|
||||
let mut stream = TcpStream::connect(addr).await.unwrap();
|
||||
let req = format!("OPTIONS / HTTP/1.1\r\nHost: 127.0.0.1:{}\r\nAuthorization: {}\r\nConnection: close\r\n\r\n", addr.port(), auth_hdr);
|
||||
stream.write_all(req.as_bytes()).await.unwrap();
|
||||
let mut resp = Vec::new();
|
||||
stream.read_to_end(&mut resp).await.unwrap();
|
||||
let resp_str = String::from_utf8_lossy(&resp);
|
||||
assert!(
|
||||
resp_str.starts_with("HTTP/1.1 200 OK"),
|
||||
"Legitime OPTIONS-Anfrage mit Basic Auth muss 200 OK liefern, erhalten:\n{}",
|
||||
resp_str
|
||||
);
|
||||
}
|
||||
|
||||
// Server ordnungsgemäß beenden & aufräumen
|
||||
let _ = shutdown_tx.send(true);
|
||||
let _ = server_handle.await;
|
||||
|
||||
Reference in New Issue
Block a user