#用户输入 #清理 #安全 #验证 #污染 #静态分析

untrusted_value

本库旨在提供一个类型安全的方式来处理和清理潜在的不可信值,如用户输入

11个版本

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

327Rust模式

Download history 354/week @ 2024-07-11 412/week @ 2024-07-18 33/week @ 2024-07-25

每月 533 次下载
用于 2 个 库中

MIT 协议

38KB
172

不可信值

本库旨在提供一个类型安全的方式来处理和清理潜在的不可信值,如用户输入。

它旨在将Rust中的污染检查作为编译时进行检查。所有用户输入或来自外部世界的所有输入都必须被视为不可信且可能有害(称为污染)。污染值在其被适当清理函数清理之前都会保持其污染状态。

本库引入了几个数据类型、特性和宏来简化污染跟踪过程。

本库的目标是什么?

本库的目标是帮助设计更安全的程序。通过污染所有程序输入,未经清理的数据不能被意外使用。通过提供污染数据的清理接口,安全分析可以专注于分析实现的清理函数,而不是确定污染数据的位置和使用方式。

示例用法

用户数据必须被包装在提供/标记包含数据为污染的容器 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:启用对 derive 宏 SanitizeValue 的强化。当此功能禁用时,实现的 fn sanitize_value(self) 会立即报错。如果担心清洗时间相关的通道,这可能是不可取的。当启用此功能时,首先运行所有清洗器,然后传播第一个错误。

限制

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

此crate仅提供污染和清洗数据的接口。使用此系统,这并不意味着应用程序本身是安全的。开发人员仍然必须实现适当的清洗函数来清除数据的污染。这个统一的接口应该有助于将安全分析集中在清洗函数上,而不是集中在可能使用污染数据的所有地方。

贡献

欢迎对项目做出贡献!如果您有功能请求、错误报告或希望为代码做出贡献,请打开一个问题或拉取请求。

许可证

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

依赖关系

~105KB