初学Web安全之sql注入(一)
sql注入产生原因
sql注入漏洞的产生需要满足以下两个条件:
- 参数用户可控
- 传入的参数拼接到sql语句并且带入到数据库查询
一般来说,用户登录网页所使用的sql语句为:
select * from user where username='admin' and password='password';
而如果程序员设计网页之初没有对用户的输入进行过滤,使得用户的输入可以带入到数据库,那么这时候就可以产生sql注入,最简单的一种,就是构造万能密码,这里拿dvwa来测试一下:
打开dvwa,修改等级为low,选择sql注入:
输入如下:
' or '1'='1'#
输入结果如图:
那么原理是什么呢?首先我们查看源代码:
其中sql语句为:
SELECT first_name, last_name FROM users WHERE user_id = '$id';
再看看我们前面输入的:
’ or ‘1’=‘1’#
将它带入到sql语句中,就变成了:
SELECT first_name, last_name FROM users WHERE user_id = '' or '1'='1'#';
这里利用了or语句,只要有一个true那么语句就返回true,这时候语句就会被带到数据库中,查询出全部的"first_name"和"last_name" (第一个引号与前面的引号形成了闭合,变为’’,后面的#为注释符,将后面的单引号注释掉)
sql注入方法
sql注入有get型,post型和cookie型,因为笔者是初学者,所以先从get型开始,正常的注入步骤如下:
判断有无注入点
回显正常——联合查询,回显报错——报错注入
联合查询步骤:
判断字符型还是数字型
如果是字符型,判断闭合情况
判断字段数
判断显示位
查看数据库版本(因为MYSQL4.0和MYSQL5.0版本注入方法不一样,不过现在普遍是5.0以上版本)
获取全部数据库名字(可用可不用,看情况而定)
获取当前数据库下所有的表名
判断关键表列名
获取数据
拿sqli-lab来测试一下,这里使用的是mysql数据库,打开sqli-lab的第一关:
(可以在url输入,这里笔者使用的是hackbar插件)
输入单引号报错,判断有注入点:
删除单引号,输入单引号,没报错,判断是字符型,闭合是单引号(原理后面再细说):
利用order by判断字段数,输入order by 3不报错,输入order by 4报错,说明字段是是3,注意,因为是字符型,所以最后面要加注释符注释掉引号:
接着判断显示位,使用union拼接select 1,2,3,发现页面并无变化,判断有可能是前面的id=1占用了显示位,改为id=-1,发现2和3显示出来了,说明2,3是显示位:
接着便是查看数据库版本了,顺带查看了下当前数据库名字(因为后面所使用是同个数据库,所以这个步骤在后面文章里会省略):
获取全部数据库名字(这个步骤只是演示一下,在后面也会省略):
获取当前数据库下所有的表名,判断管理员账号密码存放在users表里:
判断关键表列名为username和password:
最后一步,获取数据:
至此,第一关完成。
那么现在来解释下判断数字型和字符型还有闭合的原理:
- 数字型的sql语句:
select * from user where id=1;
- 字符型的sql语句:
select * from user where id='1';
select * from user where id="1";
拿数字型来说,你不管在后面加单引号还是双引号,都会导致语句错误而报错,那么两种引号都报错,我们就可以判定为数字型;
字符型的话,拿单引号类型来说,加入单引号之后:
id='1''
会导致语句后面多出来一个单引号,使得语句错误,如果加入双引号:
id='1"'
双引号被单引号包裹着,那么会将双引号也认为是一个字符,所以并不会报错,从而可以判断出是单引号闭合。双引号类型也是同理,只是引号相反而已。
总结:两种引号都报错为字符型,单引号报错双引号不报错为单引号闭合,双引号报错单引号不报错为双引号闭合,字符型最后要加注释符注释掉闭合后多余出来的引号。
笔者这里的注入是针对MYSQL数据库的,所以需要了解MYSQL的相关知识:
mysql5.0版本之后,默认有一个“information_schema”数据库,里面有三张表:
SCHEMATA: 存放了所有数据库信息
关键字段:schema_name——数据库名字
TABLES:存放所有数据表信息
关键字段:table_schema——数据库名字
-------------- table_name ——数据表名字
COLUMNS:存放所有列的信息
关键字段:table_schema——数据库名字
-------------- table_name——数据表名字
-------------- column_name——列名
理解了这些,相信上面的sql语句也就明白了>_<
转载:https://blog.csdn.net/weixin_47531846/article/details/109735250