rust-web编译题型
rust在线编译项目常见漏洞
近年来,随着Rust语言在高性能、内存安全等领域的优势被广泛认可,越来越多的开发者选择将其应用于后端开发,尤其在WebAssembly、微服务和高并发场景中表现亮眼。然而,Rust生态的快速扩张也带来了新的安全挑战:尽管语言本身通过所有权机制规避了内存安全问题,但Web应用层的逻辑漏洞(如SQL注入、身份验证绕过)、第三方库的潜在缺陷(如未充分审计的unsafe
代码滥用)以及对安全实践的过度自信(如忽略输入验证或错误配置CORS策略),正在导致Rust相关的Web安全问题逐渐浮出水面。社区亟需在享受Rust底层安全红利的同时,建立更完善的安全开发规范,加强依赖库审计,并推动Web框架的漏洞响应机制,以应对日益复杂的安全威胁。而本次就是在阿里ctf中出现的一道rust编译类题目,故总结了一套相关的相关知识。
跨项目引用
在Rust生态中,Cargo.toml
文件如同项目的中枢神经,扮演着至关重要的清单(Manifest)角色。其不仅是一份静态的配置文件,还是是开发者与Rust编译工具链(Cargo)之间的核心。通过toml,开发者能够以声明式语法精确控制项目——从定义包元数据(如版本、作者、许可证)、声明依赖关系(通过本地路径、Git仓库或官方注册表[crates.io]引入第三方crate),到定制编译策略(如特性开关、优化级别、目标平台配置),甚至扩展自定义构建脚本。
实现跨项目引用的核心机制,则隐藏在Cargo.toml
的特定字段中:
dependence引用
1 | [dependencies] |
引用本地过程
Rust的过程宏(Procedural Macros)是元编程(metaprogramming)的核心工具之一,允许开发者在编译时对代码进行动态生成和转换。与声明宏(Declarative Macros)不同,过程宏通过自定义代码逻辑直接操作抽象语法树(AST),实现更复杂的代码生成能力。以下是过程宏的深度解析,而我们也可以通过Cargo.toml
对其进行引用
那么如果现在存在一个文件夹拥有如下的rust项目的文件夹。
1 | ├─testaaa |
那么此时可以通过在testaaa项目的Cargo.toml中使用
1 | [lib] |
来对其他的过程宏项目进行引用。利用这个方法,可以实现在引用的项目中不使用lib.rs,来生成proc-macro。如此一来我们遍可以在项目a的main.rs里实现过程宏,虽然不能被正常编译,但是可以在项目b中引用,从而实现编译。
当然不仅这些,如果rust启用了一些unstable特性,如(metabuild等),这些功能也会在未来可能成为利用的关键点
编译执行
rust的编译存在以下三种执行
- 过程宏编译执行
- build.rs执行
- 编译时计算(不能利用)const fn
而其中build构建执行和过程宏编译时执行是常可以利用的项,他们可以实现通过编译就进行一些命令的执行。
利用Cargo.toml实现main.rs自执行
很多时候我们无法自己创建build.rs,但是可以利用Cargo.toml中的选项。
1 | build = "路径" |
我们可以将build的路径换成任何我们想要的rs文件(包括 main.rs !我们可以通过这点在很多有限制的地方进行执行)从而实现build.rs执行。
不只是这种情况,前面我们提到过rust的依赖选项,rust通过从crates.io下载源码或读取本机的源码编译。那么此时这些crates中的build.rs文件也会进行运行,我们也可以通过这种方式进行利用
利用过程宏
在Cargo.toml中启用
1 | [lib] |
来引用过程宏或开启过程宏来运行,这里巧妙的是,cargo会直接对path的目标文件进行rustc编译,也就是说,即使目标文件的结构并不符合rust项目的标准,只要rust代码没有错误都可以将其作为过程宏生成。
替换编译器、资源
很多情况我们并不能正常回显或是不能正常的触发一个程序,那么我们可以通过“挖空”程序本体,换入我们的代码,这样一来,程序就可以通过流程的调用来触发。
以下是linux中rustc和cargo的常见位置
系统级
1 | ~/.cargo/bin/ # rustc, cargo, rustup 等可执行文件 |
用户级
1 | ~/.rustup/toolchains/ # 不同版本工具链 |
下面就是一个替换内容的例子,将cargo替换为以下的脚本,这个脚本将会把flag作为错误状态码依次返回(运行一次返回一次),我们便可以通过不断运行编译流程,此时返回的错误码就为flag的ascii码
1 | #!/bin/sh |