SQL注入(3) #Web安全攻防

SQL注入的具体流程是指利用web应用程序对用户输入数据的合法性没有判断或过滤不严的漏洞,通过构造恶意的SQL语句来实现对数据库的任意操作。

用案例解释的话,可以参考以下的步骤:

1.判断注入类型,数字型(1)还是 字符型(2)。

(1).数字型的参数不用被引号引用,如?id=1,

(2).字符型的参数需要被引号引用,如?name="phone"。

可以通过在参数后面添加and 1=1或and 1=2等逻辑判断来看是否影响查询结果,或者在参数后面添加单引号来看是否报错。

例如,如果一个网站的查询语句是:

SELECT * FROM users WHERE username = '$username'  AND password = '$password'

其中$username和$password是用户输入的参数,那么如果用户输入的$username是:

admin' -- 

那么实际执行的查询语句就变成了:

SELECT * FROM users WHERE username = 'admin' -- AND password = '$password'

这样就可以绕过密码验证,因为 – 是SQL中的注释符号,后面的内容都被忽略了。

为了检测是否存在这样的SQL注入漏洞,可以在参数后面添加and 1=1或and 1=2等逻辑判断来看是否影响查询结果。例如,如果在$username后面添加and 1=1,那么实际执行的查询语句就变成了:

SELECT * FROM users WHERE username = 'admin' and 1=1 -- AND password = '$password'

这样仍然可以绕过密码验证,因为and 1=1总是成立。但是如果在$username后面添加and 1=2,那么实际执行的查询语句就变成了:

SELECT * FROM users WHERE username = 'admin' and 1=2 -- AND password = '$password'

这样就无法绕过密码验证,因为and 1=2总是不成立。通过比较两种情况下的查询结果,就可以判断是否存在SQL注入漏洞。

!--【这是因为SQL注入的本质是利用参数来改变原本的查询逻辑,从而执行恶意的SQL语句。如果在参数后面添加and 1=1,那么相当于没有改变原本的查询逻辑,因为and 1=1对任何条件都没有影响。但是如果在参数后面添加and 1=2,那么相当于改变了原本的查询逻辑,因为and 1=2会使任何条件都不成立。如果网站存在SQL注入漏洞,那么这两种情况下的查询结果会有明显的差异,例如返回的记录数或者错误信息。如果网站没有SQL注入漏洞,那么这两种情况下的查询结果会一致,都是按照原本的查询逻辑返回结果。】--!

!--【那么我们为什么还要把注释掉的AND再加回去呢?因为网站会对参数进行合法性检查或者转义处理,防止SQL语句被篡改。简单来说,如果我们不加上注释掉的and,系统就会监测到我们的语句错误,所以我们才会加上 and 1=1,那为啥还有 and 1=2呢?这不是肯定会报错吗?额,其实在上面已经回答过了,就是 例如返回的记录数或者错误信息。如果网站没有SQL注入漏洞,那么这两种情况下的查询结果会一致,都是按照原本的查询逻辑返回结果。 我们是通过 and 1=2与and 1=1写出来反应的语句作比较,从而判断出是否有SQL注入漏洞!!! 】--!

另一种检测方法是在参数后面添加单引号来看是否报错。例如,如果在$username后面添加单引号,那么实际执行的查询语句就变成了:

SELECT * FROM users WHERE username = 'admin'' AND password = '$password'

这样就会导致SQL语法错误,因为单引号没有正确匹配。如果网站没有对错误信息进行处理,就会暴露出SQL注入漏洞的存在。

2.猜解SQL查询语句中的字段数。可以使用order by num#子句,利用网页报错或回显来判断字段数,其中#号用于截断SQL查询语句。例如,如果order by 3#正常显示,而order by 4#报错,则说明查询语句中有三个字段。

SQL查询语句中的字段数是指查询结果包含几个列,也就是几个属性。猜解字段数的作用是为了利用union select语句进行联合查询,从而获取数据库中的敏感信息。

!--【这句话的意思是,当我们执行一个SQL查询语句时,比如:

select username,password from users where id=1

那么查询结果是一个表格,表格的每一列对应一个属性,比如username或者password。这个表格有几个列,就是字段数。在这个例子中,字段数是2】。--!

!--【为啥 id=1 就是一个表格? id=1不是一个表格,它是一个条件,用来筛选users表中的数据。select username,password from users where id=1这个语句的意思是,从users表中选择username和password这两个属性,但只选择id等于1的那一行数据。所以查询结果是一个表格,只有一行,两列。】--!

!--【那么如果没有where条件呢? 如果没有where条件,那么就表示不对users表中的数据进行筛选,而是选择所有的行。比如:

select username,password from users

这个语句的意思是,从users表中选择username和password这两个属性,但不限制id的值。所以查询结果是一个表格,有多行,两列。每一行对应users表中的一条记录。】--!

!--【那么如果有多个where条件呢?如果有多个where条件,那么就表示要对users表中的数据进行更细致的筛选,只选择满足所有条件的行。比如:

select username,password from users where id=1 and password='123456'

这个语句的意思是,从users表中选择username和password这两个属性,但只选择id等于1且password等于’123456’的那一行数据。所以查询结果是一个表格,只有一行,两列。如果没有满足所有条件的行,那么查询结果就是一个空表格。】--!

order by num#子句是一种常用的猜解字段数的方法,它的原理是利用数据库的报错机制,如果排序的列数大于查询结果的列数,就会报错。例如,如果查询语句是:

select username,password from users where id=1

那么查询结果只有两个列,username和password。如果我们在后面加上order by 3#子句,就相当于:

select username,password from users where id=1 order by 3#

这时候数据库就会报错,因为它不认识第三列。所以我们可以从第一列开始排序,依次增加列数,直到报错为止,就可以猜解出字段数。

举个例子,假设我们有一个注入点:

http://www.example.com/news.php?id=1

我们可以在后面加上order by num#子句,逐渐增加num的值,观察页面的变化。比如:

http://www.example.com/news.php?id=1 order by 1#
http://www.example.com/news.php?id=1 order by 2#
http://www.example.com/news.php?id=1 order by 3#
http://www.example.com/news.php?id=1 order by 4#

如果前三个URL都正常显示,而第四个URL报错或者页面变空白,那么就说明查询结果有三个字段。

猜解出字段数后,我们就可以使用union select语句进行联合查询,从而获取数据库中的敏感信息。比如:

http://www.example.com/news.php?id=1 union select 1,2,3#

这样就可以在页面上看到数字1,2,3分别显示在哪个位置,也就是数据显示位。然后我们就可以根据数据显示位来替换成想要查询的内容,比如数据库名、表名、列名等。

!--【这句话的意思是,当我们使用union select语句进行联合查询时,我们可以在页面上看到查询结果的每一列显示在哪个位置,这就是数据显示位。比如:

http://www.example.com/news.php?id=1 union select 1,2,3#

如果页面上显示:

<h1>News Title</h1>
<p>2</p>
<h2>News Content</h2>
<p>3</p>

那么就说明第二列显示在新闻标题的位置,第三列显示在新闻内容的位置,这就是数据显示位。然后我们就可以根据数据显示位来替换成想要查询的内容,比如数据库名、表名、列名等。比如:

http://www.example.com/news.php?id=1 union select 1,database(),3#

如果页面上显示:

<h1>News Title</h1>
<p>error</p>
<h2>News Content</h2>
<p>3</p>

那么就说明当前数据库名是error,这就是我们想要查询的内容。】--!

!--【解释一下 database()函数 ?

database()是一个数据库函数,它的作用是返回当前数据库的名字。当我们使用union select语句进行联合查询时,我们可以用database()函数来获取当前数据库的名字。比如:

http://www.example.com/news.php?id=1 union select 1,database(),3#

这个语句的意思是,从news表中选择id等于1的那一行数据,然后和另外一条查询结果合并,这条查询结果是1,database(),3。也就是说,第二列是当前数据库的名字,第三列是3。所以页面上显示:

<h1>News Title</h1>
<p>error</p>
<h2>News Content</h2>
<p>3</p>

这就说明当前数据库的名字是error,它显示在新闻标题的位置,也就是第二列。

】--!

3.确定字段的显示顺序。可以使用union select num,num,num#子句,联合查询并在网页回显数字来确定字段的显示顺序,其中数字可以是任意值。例如,如果回显了2,3,1,则说明第一个字段显示在最后,第二个字段显示在最前,第三个字段显示在中间。

4.获取当前数据库的名称、表名、列名和数据。可以使用MySQL中的内置函数和信息库来获取数据库相关信息。

  • 获取当前数据库的名称:可以使用database()函数返回默认或当前数据库的名称。 例如,union select 1,database(),3#可以在第二个字段回显当前数据库的名称。

  • 获取当前数据库中的表名:可以使用information_schema.tables表来获取MySQL服务器中所有表信息的表,指定table_schema=database()即可显示当前数据库中表的信息。例如,union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()#可以在第二个字段回显当前数据库中所有表名。

  • 获取某个表中的列名:可以使用information_schema.columns表来获取MySQL服务器中所有列信息的表,指定table_name='xxx'即可显示某个表中列的信息。 例如,union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'#可以在第二个字段回显users表中所有列名。

  • 获取某个表中的数据:可以直接从目标表中查询数据,并利用回显点显示结果。 例如,union select 1,group_concat(username,password),3 from users#可以在第二个字段回显users表中所有用户名和密码。

以上是一个简单的SQL注入案例,具体操作可能会根据不同的情况有所变化。

【最后!!!额,我只详细讲了SQL注入前两个内容,后两个的具体内容,下期再讲!!!】

如果你觉得我写的不错的话,给个关注再走呗。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

》(。・ω・。)ノ♡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值