sql-labs

Last updated on 6 months ago

sqlilabs安装

下载

1.下载phpstudy
2.在www文件夹下https://github.com/Audi-1/sqli-labs.git
3.在sql-connections文件夹下,打开db-creds.inc文件(用notepad++方便),更改密码为root,复制security

配置

1.phpstudy面板,打开mysql工具,mysql命令行
2.create database security;
3.use security
4.sql文件导入数据库,此处需要用到sql-lab.sql文件,source (C:\software\phpstudy\WWW\sqli-labs\sql-lab.sql)(sql-lab.sql的文件路径)

打开

http://localhost/sqli-labs
点开第一个set up,再返回即可

基础查询

information_schmea

这个是自带的数据库,从这里可以查询建立的数据库名及表名

查表名

select table_name from information_schema.tables where table_schema=database()

(table_name存储所有表名,table_schema存储所有数据库名)

(这里的顺序是先用database()得到数据库名,用数据库名赋值给table_schema,从而限定information_schema.tables的查找范围限定在当前数据库,再查询对应的表名)

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

前面的查询可能会只查询出一条结果,但是实际要查的表名可能很多,比如passwd和key,这样用group_concat就可以联合查询,让所有内容一起输出

假设查出的表名为stu

查列名

select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name = 'stu'

(加where table_schema=database()是为了防止有不同数据库内有重复表名的存在)

查信息

1
2
3
union select 1,group_concat(username),group_concat(passwd) from information_schema=database() and table_name= 'stu' 
也可以
union select 1,group_concat(username),group_concat(passwd) from stu

常见函数

函数名 例子 作用
group_concat() group_concat(id,name,passwd) / group_concat(version(),database()) 将()内的内容聚合到一行输出
database() 查询数据库名
version() 查询版本信息

union查询

原理

正常使用:

select * from stu where id = 1 union select * from coach where id = 1

1
表单stu
id name age
1 xiaoming 12
1
表单coach
id name
1 dk

结果会回显stu的id,name,age的内容和coach的id和name的内容,但是coach少了一列,而union查询必须要前后列一致,所以需要补齐查询

1
select * from stu where id = 1 union select *,123 from coach where id = 1 

这样查询的结果就都是三列了

注入查询:

通常在页面内的回显只会是返回查询stu的内容而不是coach的内容,所以可以查询stu中空的内容来显示coach的内容,比如查询stu的id为-1,在查询时使用union 查询,通常会查询数据库名或者服务器版本信息等

1
select * from stu where id = 1 union select 1,passwd,version

字符类型

如果输入的变量是字符类型(string),那么查询之后要加上单引号或者双引号,id=’1’这样的

如果输入的变量是整型(int),那么不需要加上引号或各种括号进行闭合,比如id=1

列的数量

order by或者group by都可以,group by可能会出现一些奇怪的东西,但是order by会被waf记录,而group by则不会

原理

order by

正常使用

比如一个数据表有每个人的成绩,第一列是学号,第二列是姓名,第三列是成绩(score),那么order by 3order by score就是等效的,是按照学生的成绩对表单进行排序

注入查询

这个表单只有三列,到order by 3还可以正常显示,order by 4就会报错,所以表明表单只有3列

group by

正常使用

表单有三列,第一列是名字,第二列是性别(gender),第三列是成绩(score),通常group by会和其它查询函数联合使用,比如avg() average平均值,联合查询后,就会只有两列,group将按照gender将表单的所有行分成男女两组,并分别求平均值

注入查询

同上

报错查询

extractvalue()

1
2
3
?id=100' union select 1,
extractvalue(1,concat(0x7e,(select database())))
,3 --+

用于查询xml数据,正确用法是extractvalue(数据类型,数据路径)

这里只能用concat而不能用group_concat(),concat是单纯将两个及以上字符连接起来,而group_concat是将查询的结果连接起来,而且group_concat()后要跟上group by才能正常使用,而select group_concat(table_name) from information_schema.tables where table_schema=database()可以不跟group by就直接使用是因为information_schema.tables本身就是一个group(理解成隐式群组)

必须要用concat()进行联合查询是因为extractvalue()必须是数据类型和数据路径,在数据类型这里可以选择错误的内容,而数据路径要更改为需要查询的内容,直接select是进行一个查询,而这里需要一个字符串(用括号将select查询包裹起来也不可以,不知道为什么)

笔记

Lession1

img
1.先判断是否有sql注入
?id=1
img

2.用sqlmap跑一下试试(主要是没看懂教程网课说的是什么意思)
sqlmap.py -u http://localhost/sqli-labs/Less-1/?id=1
img
返回给我四个类型的注入

基于布尔型盲注

1.概念:构造可以判断为真或假的SQL逻辑语句,根据页面返回的结果是否正常来判断语句结果是真或假。典型的构造方式是使用“AND 1=1”(真)或“AND 1=2”(假)。(源自claude)
就是在url界面输入值后,是否会在页面进行显示内容,比如本题,进行注入'and 1=1 --+此时结果为真,可以返回id=1的值img,如果结果为假,例如1=2,由于是and语句,前后都为真才可执行,id=1为真,1=2为假,所以语句不执行,则返回空值img
2.步骤:确认注入点、信息收集和利用(同样来源于claude)img现在应该还学不到那种程度,现在可以利用简单的函数来判断一些数据,比如length(database())这个函数,可以判断数据库名称的长度是多少,比如现在的数据库(database)的名称是security,那么length(database())返回值就是8(应该可以配合burpsuite的爆破使用,爆破出正确的值,然后根据这个正确的值注入,后面的ascii同理)
img
ascii判断:?id=1’ and ascii(substr(database(),1,1))=33 –+ 比如security这个数据库第一个字母为s,ascii码值为115,所以img
(剩下的还没学明白)

注释符号

单引号报错img
两个单引号可以img
原语句select * from table where id = '$id' 假设现有的两个’分别记为1号,2号
注入语句为?id=1' 这里的’记为3号,注入后select * from table where id = '$id'',此时’分别为1,3,2号,那么拼接后的语句1,2号为引号但是3号没有与之配对的,所以会报错,但注入双引号之后,就是1332,12正常配对,33配对引起的内容为空,但是不会报错(传入参数的分号配对优先级低于原来的’’,所以前面可以用3号分号跟原来的1号配对,而2号则被注释掉了)
select * from table where id = '1'and 1=2''

Lession2

注入语句 y/n
?id=1 and 1=1--+ y
?id=1' and 1=1--+ n
?id=1' and 1=1 n
?id=1 and 1=1 y

所以后台语句为select * from table where id = $id

Lession3

单引号起手尝试img
报错,但是看到报错里有),推测原查询语句为select * from table where id = ('1')select * from table where id = '(1)'

先尝试?id=1)' and 1=2 --+,这里猜测原语句为select * from table where id = '(1)' 如果是这个则注入之后就是select * from table where id = '(1)'and 1=2--+)'如果是这个,则原来的括号和引号被注释掉
img报错,所以这个不对,那么猜测原语句为select * from table where id = ('1')
然后再尝试注入?id=1') and 1=2 --+,如果是这个则注入后为```select * from table where id = (‘1’)and 1=2–+)’

Lession4

img
原语句是id=($id)

Lession5

找原语句还是没什么太大问题,但是看着不少教程从这一关开始搞爆破了,所以跟着走一遍
注入代码?id=1' and 1=2--+不报错,但是不显示内容,所以原语句是select * from table where id = '$id'
爆破数据库名称 substr(database(),1,1)
img
不是s的情况
img
但是bp还没搞明白怎么逐个字母爆破,所以改成ascii码值,a-z的ascii码值分别是97-122,所以注入语句改为?id=1' and ascii(substr(database(),1,1))=115
img
以及非115的情况
img

现在用bp爆破一遍
1.代理抓包
2.右键,发送到intruder
3.清除原有payload,选定115为新的payload
4.img
5.爆破img

捯饬了一下找到怎么用字母爆破了
前三步一样,但要用ascii()包起来原来的参数,payload集还是1,类型由数值改为简单列表,点击payload设置>>从列表添加
img

Lession6

一开始傻了,以为双引号就是两个单引号,一直找不到语法报错提示,改成shift+”就有正常报错提示了,跟第五关差不多

Lession7 GET-Dump into outfile

这个可以注入文件 dump是临时存储的数据,outfile是上传文件,就是通过url框向服务器传入一个文件,文件的内容就是在url框里查询出来的内容
注入语句?id=1')) union select 1,3,4 into outfile "E:\\phpstudy\\PhpStudy2018\\PHPTutorial\\WWW\\sqli-labs\\Less-7\\a.php"--+
union必须带 后面只能穿3个参数,可能是因为源文件就这么设置的 into outfile是固定语句
踩得一些坑:
SHOW VARIABLES LIKE "secure_file_priv";查看状态 ,如果是空值就可以成功注入,如果是null则不行
如果是null的话需要打开mysql.ini文件(claude说的是mysql.cnf),添加secure_file_priv = ''
一开始添加在文件的最下面,但是不行,然后加在[mysqld]的下面,重新重启phpstudy可以注入了

Lession8

又是布尔盲注,但看攻略也没发现跟前面的基于错误报错有什么区别,试一下爆出版本号
mid()函数
img
?id=1' and mid(version(),1,1)=5 --+
?id=1' and mid(version(),1,2)=5.0 --+

Lession9

img
不知道为什么0 1都是一样的you are in…,再用sqlmap跑一次
img
用时间注入,从29秒开始可以注入,应该是
img
?id=1'and if(length(database())=7,sleep(3),1) --+
if(判断,如果对则,错则) 错的返回值(结果集)填什么都可以,但必须要填,就比如select * from table where id = 1返回值就是id=1的所有字段,所有字段就是结果集
img

Lession10

跟9差不多,但是双引号

1
?id=1"and if(1=2,sleep(50),1) --+

Lession11 Post

img

一上来界面就不一样了,变成一个输入账密的代码框,一开始各种乱试瞎猜都没成功,唯一一次有点沾边的想法是username框不能给注释掉,要不然password就输入不进去了,搜了教程才想明白

1
select * from table where name='$username' and password = '$password'

所以想要注入应该是在username框输入 admin' and 1='1 这样admin左边原来有一个分号,右边在代码框输入了一个分号,而’1 右边有原来属于’$username’的右边的分号,这样就齐活了
select * from table where uname='$username' or 1=1 and passwd = '$password'这个语句包括了三个判断条件,$username存在,1=1,$password存在,但是因为1=1为永真,所以剩下两个只要一个有就能查出来

Lession12

单引号边双引号


sql-labs
https://blog.yblue.top/2023/08/20/sql-labs/
Posted on
August 20, 2023
Licensed under