一、核心知识点总览
(一)文件包含漏洞
简单理解:网站代码里有个 "引用文件" 的功能,如果这个功能能被我们随便改引用的文件,就可能出问题。
举例子:比如网站想引用 "1.txt",我们改成引用藏了恶意代码的文件,网站就会执行这个恶意代码。
(二)SQL 注入漏洞
这是最基础也最常见的网站漏洞,咱们从 "是什么、怎么来的、怎么测、怎么防" 一步步说,全是入门级内容。
二、SQL 注入
(一)先搞懂:什么是 SQL 和 SQL 注入?
SQL 是什么:简单说,SQL 是给数据库 "下命令" 的语言。比如网站想查 "用户名为 admin 的密码",就会用 SQL 命令问数据库:SELECT 密码 FROM 用户表 WHERE 用户名='admin',数据库就会返回对应的密码。
SQL 注入是什么:网站拿我们输入的内容(比如登录时输的用户名),直接拼到 SQL 命令里,没做任何过滤。我们故意输点 "特殊内容",让 SQL 命令变味,数据库就会执行我们想要的操作 ------ 这就是 SQL 注入。
(二)SQL 注入的核心原因
举个生活例子:食堂阿姨问你 "要打什么菜?",正常你说 "番茄炒蛋",阿姨就打这个;但如果你说 "番茄炒蛋,再把隔壁桌的红烧肉也给我",如果阿姨直接照做(没过滤你的话),就相当于 "注入成功"。对应到网站:网站想查用户名,写的代码逻辑是:SQL命令 = "SELECT 密码 FROM 用户表 WHERE 用户名='" + 你输入的用户名 + "'"如果你输入的用户名是正常的admin,SQL 命令就是:SELECT 密码 FROM 用户表 WHERE 用户名='admin'(没问题);但你输入admin' OR '1'='1,SQL 命令就变成:SELECT 密码 FROM 用户表 WHERE 用户名='admin' OR '1'='1'------ 数据库一看 "1=1 肯定对",就会把所有用户的密码都返回出来。
(三)先认识 MySQL(最常用的数据库)基础
不用记复杂的,就记 3 个核心:
数据库的结构:数据库 → 表 → 列 → 数据(像:文件夹 → 表格文件 → 表格的列 → 单元格内容)
比如:有个叫security的数据库,里面有个users表,表有username(用户名)和password(密码)两列,存着admin/123456、test/666666这些数据。
3 个最常用的 SQL 命令:
查数据:SELECT 列名 FROM 表名 WHERE 条件(比如SELECT password FROM users WHERE username='admin');
注释符:# 或 --+(作用是 "把后面的内容注释掉",比如输入admin'#,后面的内容就不算数了);
拼接查询:UNION SELECT(把两个查询结果拼在一起,比如查完用户表,再查数据库名字)。
1 个必记的系统表:information_schema这个表是 MySQL 自带的 "目录",里面记着:
所有数据库的名字(存在SCHEMATA表里);
所有表的名字(存在TABLES表里);
所有列的名字(存在COLUMNS表里)。不用记复杂用法,知道有这个表、能查名字就行。
(四)怎么判断网站有没有 SQL 注入
核心:输入特殊字符,看网站反应 ------ 就测 3 个步骤,
第一步:输单引号(')测试找网站有输入框的地方(比如登录框、搜索框、网址里的参数,比如?id=1),输入'(单引号),看反应:
如果网站报错(比如提示 "SQL 语法错误""您的 SQL 语法有错误"),大概率有注入;
如果网站没反应,也可能是有过滤,先记下来,换个地方测。例子:网址是http://xxx.com/?id=1,改成http://xxx.com/?id=1',如果报错,说明有注入点。
第二步:用 OR 判断(看是否能控制查询结果)比如网址是?id=1,改成?id=1 OR 1=1(注意空格):
如果原本只显示 1 条数据,现在显示所有数据,说明注入成立;再改成?id=1 AND 1=2:
如果原本显示的数据消失了,进一步确认有注入。
第三步:用注释符验证输入admin'#(比如登录框输用户名),如果网站没报错,说明注释符生效了 ------ 因为#把后面的内容注释掉,原本可能出错的 SQL 命令变正常了。
(五)最基础的 2 种 SQL 注入玩法
玩法 1:联合查询注入(有页面回显时用)
"回显" 就是网站会把查询结果显示在页面上(比如搜索结果、用户信息页),步骤超固定:
第一步:判断查询的列数用ORDER BY命令(按列排序),比如网址?id=1:
先试?id=1 ORDER BY 1(按第 1 列排序),页面正常;
再试?id=1 ORDER BY 2,页面正常;
试?id=1 ORDER BY 3,页面报错 ------ 说明这个查询只有 2 列(数到报错前的数字就是列数)。
第二步:用 UNION SELECT 拼查询先把原查询搞成 "查不到数据"(比如id=-1,因为没有 id=-1 的内容),再拼我们的查询:比如列数是 2,就输?id=-1 UNION SELECT 1,2:
页面会显示 "1" 和 "2",说明这两个位置能显示我们查的内容;
把 "2" 换成user()(查当前数据库用户),就变成?id=-1 UNION SELECT 1,user(),页面会显示数据库的用户名;
再换成查数据库名:?id=-1 UNION SELECT 1,database(),就能看到当前用的数据库名字。
第三步:查敏感数据(比如用户名和密码)知道数据库名(比如security)、表名(比如users)、列名(username和password)后,输:?id=-1 UNION SELECT 1,CONCAT(username,':',password) FROM users页面就会显示所有用户的 "用户名:密码",比如admin:123456。
玩法 2:报错注入(页面不显示数据,但会报错时用)
如果页面不回显查询结果,但输错 SQL 会弹出错误提示,就用这个方法:核心:用updatexml这个函数制造报错,报错里会带出我们要的内容。举个最简单的例子:在输入框输' AND updatexml(1,CONCAT('~',database(),'~'),1)#
updatexml是 MySQL 的一个函数,要求第二个参数是合法的格式,我们拼了~数据库名~,格式不对就会报错;
报错内容会显示:XPATH syntax error: '~security~'------ 其中security就是数据库名;
想查用户名密码,就把database()换成(SELECT CONCAT(username,':',password) FROM users LIMIT 0,1),报错里就会带出第一条用户的账号密码。
(六)新手也能会的实战小技巧
怎么找网站的后台?
用工具:dirsearch(输入网站地址,自动扫后台地址,比如/admin、/login);
看文件:网站根目录的robots.txt(可能写着后台地址,比如Disallow: /admin);
搜一搜:用 Google / 百度搜site:目标网站 intext:"管理"(比如site:xxx.com intext:"后台管理")。
用工具辅助
sqlmap是专门测 SQL 注入的工具,新手只需要记一个命令:把网站的请求保存成1.txt,然后输sqlmap -r 1.txt,工具会自动检测有没有注入,还能自动查数据。
爆破账号密码小注意
先试常见用户名:admin、root、manager;
先试常见密码:123456、666666、admin123;
别频繁输错,不然 IP 可能被网站封了。
(七)怎么防 SQL 注入
过滤输入内容:网站对用户输入的内容做检查,比如不让输'、UNION、SELECT这些特殊字符;
不用拼接 SQL:用 "参数化查询"(比如先写好SELECT 密码 FROM 用户表 WHERE 用户名=?,再把用户名填到?里,数据库会自动过滤特殊内容);
给数据库设限:让数据库账号只有 "查数据" 的权限,没有 "改数据、删表" 的权限,就算注入了也干不了大事。