test: 补齐C-01未授权文件攻击矩阵

This commit is contained in:
2026-09-12 02:31:44 +08:00
parent 604702e980
commit f6fd6b9ce9
3 changed files with 91 additions and 0 deletions
@@ -1015,3 +1015,4 @@ Core 的独立数据目录目前不等于已授权 Vault。Python 旧笔记写
- 精确测试及 `core_process` 全文件 3 项通过,严格 Clippy `-D warnings` 通过。该实现提交为 `bdba729`
- A-04 尚不能记为通过:Core/Host 签名 RC 的原子更新事务与每个切换点 20 次真实重启恢复仍未完成。当前会话也没有受控签名 RC 或旧 RC。
- C-01 运行环境复核显示当前 Windows 用户不是管理员,且未发现可用的 `pktmon``tshark``dumpcap` 命令,因此不能生成规划要求的禁止网络零收包证据;已有 AppContainer 文件与环回测试不能替代该证据。
- C-01 文件攻击夹具继续补强:由真实编译的恶意二进制在 AppContainer 中分别对未授权 Vault、用户目录、凭据库和其他包诱饵执行各 100 次读取与 100 次写入,总计 800 次文件系统攻击均失败,四个诱饵 SHA-256 保持不变。精确 Rust 测试通过;C-01 状态仍保持未通过,直至网络类别的管理员抓包证据齐备。
@@ -708,6 +708,84 @@ mod tests {
fn real_container_cannot_reach_ipv4_or_ipv6_loopback_listeners() {
real_native_protocol_probes(false, false);
}
#[test]
fn real_malicious_binary_cannot_read_or_write_four_ungranted_file_scopes() {
use sha2::{Digest, Sha256};
use std::os::windows::fs::OpenOptionsExt;
use windows_sys::Win32::Storage::FileSystem::*;
let profile = Profile::create().unwrap();
let package = tempfile::tempdir().unwrap();
let executable = package.path().join("file-probe.exe");
let fixture = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests/fixtures/sandbox_network_probe.rs");
let compile = std::process::Command::new("rustc")
.arg("--edition=2021")
.arg(&fixture)
.arg("-o")
.arg(&executable)
.output()
.unwrap();
assert!(
compile.status.success(),
"{}",
String::from_utf8_lossy(&compile.stderr)
);
let open = |path: &std::path::Path| {
std::fs::OpenOptions::new()
.access_mode(READ_CONTROL | WRITE_DAC)
.share_mode(FILE_SHARE_READ | FILE_SHARE_WRITE)
.custom_flags(FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)
.open(path)
.unwrap()
};
let package_root = open(package.path());
let entry = open(&executable);
profile.grant_package_read_execute(&package_root).unwrap();
profile.grant_package_read_execute(&entry).unwrap();
let bait_root = tempfile::tempdir().unwrap();
let scopes = ["vault", "home", "credentials", "other-package"];
let bait: Vec<_> = scopes
.iter()
.map(|scope| {
let directory = bait_root.path().join(scope);
std::fs::create_dir(&directory).unwrap();
let path = directory.join("bait.txt");
std::fs::write(&path, format!("OpenNexus C-01 {scope} bait")).unwrap();
path
})
.collect();
let before: Vec<_> = bait
.iter()
.map(|path| Sha256::digest(std::fs::read(path).unwrap()))
.collect();
let folder = profile.folder().unwrap();
let system = std::path::PathBuf::from(std::env::var_os("SystemRoot").unwrap());
let mut arguments = vec!["file_denied_100".to_owned()];
arguments.extend(bait.iter().map(|path| path.to_string_lossy().into_owned()));
let data = crate::extension_launch_data::LaunchData::new(
&executable,
&arguments,
&system,
&folder,
&folder.join("Temp"),
&std::collections::BTreeMap::new(),
)
.unwrap();
assert_eq!(
checked_executable_data(&profile, &executable, None, Some(data)),
Some(0)
);
let after: Vec<_> = bait
.iter()
.map(|path| Sha256::digest(std::fs::read(path).unwrap()))
.collect();
assert_eq!(after, before);
drop(entry);
drop(package_root);
profile.remove().unwrap();
}
#[cfg(feature = "desktop")]
#[test]
#[ignore = "real MCP tools/call 60-second deadline acceptance; run explicitly"]
@@ -3,6 +3,18 @@ use std::net::{SocketAddr, TcpStream, UdpSocket};
use std::time::Duration;
fn main() {
let args: Vec<_> = std::env::args().collect();
if args.get(1).is_some_and(|value| value == "file_denied_100") {
for path in &args[2..] {
for _ in 0..100 {
if std::fs::File::open(path).is_ok()
|| std::fs::OpenOptions::new().write(true).open(path).is_ok()
{
std::process::exit(88);
}
}
}
std::process::exit(0);
}
if args.get(1).is_some_and(|s| s == "cpu_burn") {
std::thread::scope(|scope| {
for _ in 0..8 {