知识

哪些是代码执行漏洞的常用防护手段

时间:2010-12-5 17:23:32  作者:焦点   来源:百科  查看:  评论:0
内容摘要:```html 去年某电商平台的订单查询接口被爆出漏洞,攻击者只需在URL里加一个单引号,就能把整个用户表拖走。事后复盘,开发团队承认:他们直接把用户输入拼进了SQL语句。这不是孤例。代码执行漏洞——

```html

去年某电商平台的代码的常段订单查询接口被爆出漏洞,攻击者只需在URL里加一个单引号,执行就能把整个用户表拖走。漏洞事后复盘,用防开发团队承认:他们直接把用户输入拼进了SQL语句。护手这不是代码的常段孤例。代码执行漏洞——包括SQL注入、执行命令注入、漏洞反序列化、用防表达式注入——本质上是护手同一类问题:程序把不该信任的数据当成了代码来执行。防护手段必须围绕“数据与代码的代码的常段边界”来设计。

参数化查询是执行堵SQL注入最硬的一招。它的漏洞原理不是过滤特殊字符,而是用防让数据库驱动把用户输入当作纯数据传递,SQL结构在编译阶段就固定了。护手比如Java里的PreparedStatement,或者Python的cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))。注意,拼接字符串再传给execute,哪怕做了转义,依然可能被绕过。我见过一个项目用正则替换掉单引号,结果攻击者用双引号加编码就绕过了。参数化查询不给你绕过的机会。

命令注入的防护更直接:别用shell。PHP的system()、Python的os.system(),只要参数来自外部,就是定时炸弹。如果非要执行外部命令,用subprocess.run()并传列表参数,同时设shell=False。但更安全的是根本不让用户控制命令名。比如图片处理,不要拼convert命令,而是调用ImageMagick的库函数。去年某CMS的缩略图功能被RCE,就是因为把用户上传的文件名拼进了exec("convert " . $filename)。

反序列化漏洞的防护有点反直觉:不要反序列化不可信数据。Java的ObjectInputStream、PHP的unserialize()、Python的pickle.loads(),这些接口一旦接收外部输入,攻击者就能构造恶意对象链。很多团队用白名单类来限制,但白名单本身容易漏。更彻底的做法是换数据格式——JSON或Protobuf,它们只解析数据,不执行构造方法。如果必须用Java序列化,至少加上ObjectInputFilter,但别指望它能挡住所有 gadget chain。

表达式注入常出现在规则引擎、模板引擎和SpEL里。Spring的@Value("#{ ...}")如果拼接了用户输入,攻击者就能执行任意代码。防护原则是:表达式模板必须静态化。比如用Thymeleaf时,不要动态拼接模板字符串,而是把变量通过上下文传入。我见过一个风控系统,把用户填的规则直接塞进SpelExpressionParser,结果被T(java.lang.Runtime).getRuntime().exec()打穿。后来他们改成用有限状态机解析规则,彻底放弃了动态表达式。

输入验证和输出编码是辅助手段,但不能当主力。输入验证容易漏掉编码变形,比如%27、%2527、Unicode同形字。输出编码解决的是XSS,对代码执行帮助有限。真正有效的是最小权限原则:数据库账号只给必要表的增删改查,Web进程不要用root跑,容器里禁用exec系统调用。这样即使漏了一个注入点,攻击者也拿不到shell。

最后说个现实观察:很多团队把WAF当救命稻草。WAF能挡脚本小子,但挡不住针对性的绕过。某次渗透测试中,我用/*!50000union*/这种MySQL内联注释就绕过了某云WAF的SQL注入规则。防护要落在代码层,WAF只是补丁。每次代码评审时,看到eval、exec、system、Runtime.getRuntime()这些关键词,就该停下来问一句:这个参数用户能控制吗?如果能,换实现方式。

```
最近更新
热门排行
copyright © 2026 powered by 力不从心网   sitemap