sql手工注入漏洞测试 mysql数据库

一个登录框,手试m数据用户名填 ' OR 1=1 -- ,工注密码随便写,入漏点提交,洞测直接进了后台。手试m数据这不是工注电影桥段,是入漏十年前大量PHP网站的真实日常。MySQL数据库配上没过滤的洞测SQL查询,等于把大门钥匙插在锁上还贴了张纸条告诉你锁在哪。手试m数据

SQL注入的工注本质很简单:你写的SQL语句,和用户输入的入漏数据,被拼接成了同一个字符串。洞测数据库引擎分不清哪部分是手试m数据代码、哪部分是工注数据,用户输入什么,入漏它就当代码执行什么。比如一个查询:

$sql = "SELECT * FROM users WHERE username='$user' AND password='$pass'";

当 $user 被替换成 admin' --,整条语句变成 SELECT * FROM users WHERE username='admin' -- ' AND password='xxx'。MySQL里 -- 是注释符,后面的密码验证直接被注释掉。数据库只查了用户名,密码形同虚设。

手工注入的流程通常从一个单引号开始。在输入框里打一个 ',如果页面报错,说明存在注入点,而且错误信息可能直接把SQL语句暴露出来。把报错关掉的情况也有,那就用 and 1=1 和 and 1=2 对比页面返回是否一致,判断闭合方式。

确认注入点之后,第一步是判断字段数。order by 1、order by 2 一直往上加,直到页面报错,就能确定当前查询用了几列。假设是3列,接着用 union select 1,2,3 看哪几个位置的内容会显示在页面上——那些位置就是后续提取数据的地方。

MySQL的信息密度很高。union select 1,database(),version() 能直接拿到当前数据库名和版本。有了库名,查 information_schema.tables 拿表名,再查 information_schema.columns 拿字段名。整个过程像翻目录一样,一层一层剥开。

union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()

拿到表名之后,比如看到 admin 或者 users,基本可以断定这就是目标。group_concat(column_name) 把字段名一次性拉出来,常见的有 username、password、email。最后一步直接读数据:

union select 1,group_concat(username,0x3a,password),3 from admin

0x3a 是冒号的十六进制,用来分隔用户名和密码。密码如果是MD5,拿去彩虹表或者hashcat跑一下,弱密码几秒钟就出来了。

实际测试中不会这么顺利。有的页面只返回布尔状态,没有回显位,那就得用布尔盲注或者时间盲注。布尔盲注靠 and substr(database(),1,1)='a' 这种逐字符判断,页面正常就说明猜对了。时间盲注更慢,用 sleep(5) 看响应延迟。手工跑这些效率极低,通常写个脚本或者丢给sqlmap,但手工注入的价值在于理解原理——你知道sqlmap在替你做什么,出问题的时候能手动排查。

防御手段其实不复杂。预处理语句(Prepared Statement)把代码和数据彻底分开,用户输入永远只是数据,不会被当成SQL执行。PHP的PDO、Java的PreparedStatement都是干这个的。退一步,对输入做类型转换、白名单校验也有用,但不如预处理彻底。再配上数据库账号最小权限,就算被注入了,也读不到 information_schema 以外的敏感库。

我见过的真实案例里,最离谱的是一个电商站,搜索框直接拼接 LIKE '%$keyword%',用 union select 把整个用户表拖了出来,包括手机号和收货地址。开发当时觉得“搜索框又不是登录框,没人会注”,这种心态才是漏洞的温床。SQL注入被说了二十年,OWASP Top 10 里依然年年上榜,不是技术难防,是写代码的人总觉得“这次不一样”。

时尚
上一篇:派出所上门
下一篇:宁波数据分中心外网