#user-input #sanitization #security #taint #validation #static-analyis #macro-derive

untrusted_value_derive

这个crate旨在提供一种类型安全的方式来处理和清理潜在的不受信任的值,如用户输入。

9个版本

0.3.1 2024年7月20日
0.3.0 2024年7月20日
0.2.4 2024年7月18日
0.1.1 2024年7月15日

#sanitization 中排名12

Download history 262/week @ 2024-07-11 389/week @ 2024-07-18 26/week @ 2024-07-25

每月下载量677
用于 untrusted_value

MIT 许可证

46KB
589

不受信任的值

这个crate旨在提供一种类型安全的方式来处理和清理潜在的不受信任的值,如用户输入。

它旨在将Rust中的污点检查作为编译时特性。所有用户输入或来自外部世界的所有输入都必须被视为不受信任的且可能是有害的(称为污点)。污点值会保持其污点状态,直到在受污数据上调用适当的清理函数,清除其污点。

此crate引入了几个数据类型、特性和宏,以简化污点跟踪的过程。

这个crate的目标是什么?

此crate的目标是帮助设计更安全的应用程序。通过污点所有程序输入,未清理的数据不能被意外使用。通过提供受污数据的清理接口,安全分析可以集中在分析实现的清理函数上,而不是确定污点数据的位置及其使用情况。

示例用法

用户数据必须包裹在提供/标记包含数据的污点的容器 UntrustedValue 中。

use untrusted_value::{UntrustedValue, SanitizeWith};

let user_input: i32 = -36;
let user_input = UntrustedValue::from(user_input);

// user data cannot be used on accident, since it is contained inside UntrustedValues
// UntrustedValue does only provide a limited set of implemented traits like Clone

let user_input = user_input.sanitize_with(...) // removes the taint

当用户数据是不同子类型的结构时

pub use untrusted_value::{IntoUntrustedVariant, SanitizeValue};
pub use untrusted_value::derive::UntrustedVariant;

#[derive(UntrustedVariant)]
#[untrusted_derive(SanitizeValueEnd, Clone)] // tainted variant of NetworkConfig should be Cloneable
pub struct NetworkConfig {
  pub port: u32,
  pub listen_address: String,
}

impl SanitizeValue<NetworkConfig> for NetworkConfigUntrusted {
    type Error = // ...
    fn sanitize_value(self) -> Result<NetworkConfig, Self::Error> { /* ... */ }
}

let user_data = load_from_config().to_untrusted_variant();

// user data cannot be used on accident, since it is contained inside UntrustedValues

let user_data = user_data.sanitize_value();

当应用程序框架(如Rocket/Poem/...)调用函数时,可以使用宏 untrusted_inputs 来污点函数输入

#[route(path = "/"), method = "get"]
#[untrusted_inputs]
fn index(name: &str) -> Result<String, ()> {
    // MACRO inserts the following code:
        // let name = UntrustedValue::from(name);
        // let ... = UntrustedValue::from(...);
    
    // we can not use "name" directly, since it is
    // wrapped in an UntrustedValue

    // we must explicitly sanitize the value before usage
    let name = name.sanitize_with(/* func */)?;
    Ok(format!("Hello, {}!", name))
}

提供返回不受信任数据的函数的库可以使用宏 untrusted_output 来有条件地污点输出,如果库用户希望这样做的话

#[cfg_attr(feature = "some_feature", untrusted_output)]
pub fn query_database() -> String {
    // if cfg matches, then use untrusted_output to wrap the
    // function output in UntrustedValue

    // the macro will wrap the body with:
        // UntrustedValue::from(
    "abcdef".to_string()
        // )
}

请参阅examples目录中的示例。

安装

该库是用Rust编写的,可以使用 cargo 添加。

cargo add untrusted-value

运行时开销

在使用编译优化时,由于我们实际上只是在“重命名”数据,因此不应存在运行时开销。UntrustedValue 结构体只包含原始数据类型的一个字段。当编译发布版本时,编译器应优化对 UntrustedValue 结构体的所有使用。

功能

默认启用

  • derive:启用宏自动生成代码

可选功能

  • derive_harden_sanitize:启用对 SanitizeValue derive 宏的加固。当此功能被禁用时,实现的 sanitize_value 函数会提前错误。如果担心对时序通道的清理,这可能是不可取的。当启用此功能时,首先运行所有清理器,然后传播第一个错误。

限制

提供污染跟踪系统是很好的,但仍然需要开发者正确地污染数据。目前,我们正在开发一个 crate 级别的宏,用于自动检查常见的污染源,如来自环境变量、参数和常见框架的输入,如果输入数据没有被污染,将会创建编译错误。

此 crate 只提供污染和清理数据的接口。使用此系统,这并不使应用程序固有的安全。开发者仍然需要实现适当的清理函数来清除数据的污染。这个统一的接口应该有助于将安全性分析集中在清理函数上,而不是集中在可能使用污染数据的所有地方。

贡献

欢迎对该项目的贡献!如果您有功能请求、错误报告或想为代码做出贡献,请打开一个 issue 或 pull request。

许可证

该项目受 MIT 许可证许可。有关详细信息,请参阅 LICENSE 文件。

依赖关系

~270–720KB
~17K SLoC