web入门SSRF篇--ctfshow
0x01基础知识
1.SSRF漏洞简介:
SSRF全称:Server-Side Request Forgery,即,服务器端请求伪造。是一个由攻击者构造请求,在目标服务端执行的一个安全漏洞。攻击者可以利用该漏洞使服务器端向攻击者构造的任意域发出请求,目标通常是从外网无法访问的内部系统。简单来说就是利用服务器漏洞以服务器的身份发送一条构造好的请求给服务器所在内网进行攻击。也正因为请求是由服务端发起的,所以服务端能请求到与自身相连而与外网隔绝的内部系统。也就是说可以利用一个网络请求的服务,当作跳板进行攻击。
2.主要的攻击方式
当攻击者想要访问服务器B上的服务,但是由于存在防火墙或者服务器B是属于内网主机等原因导致攻击者无法直接访问。如果服务器A存在SSRF漏洞,这时攻击者可以借助服务器A来发起SSRF攻击,通过服务器A向主机B发起请求,达到攻击内网的目的。此时A被作为中间人(跳板)进行利用。
3.漏洞形成成因
SSRF漏洞形成的原因大都是由于服务端提供了从其他服务器获取数据的功能但没有对目标地址做过滤与限制。攻击者可以利用改漏洞获取内部系统的一些信息(因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内网系统)。例如,黑客操作服务端从指定URL地址获取网页文本内容,加载指定地址的图片,下载等,利用的就是服务端请求伪造,SSRF利用存在缺陷的WEB应用作为代理 攻击远程 和 本地的服务器。
4.危害
- 对外网、服务器所在内网、本地进行端口扫描
- 向内部任意主机的任意端口发送payload来攻击内网服务
- DOS攻击(请求大文件,始终保持连接Keep-Alive Always)
- 攻击内网的web应用,如直接SQL注入、XSS攻击等
- 利用file、gopher、dict协议读取本地文件、执行命令等
- 可以无视网站CDN
内网服务防御相对外网服务来说一般会较弱,甚至部分内网服务为了方便运维并没有对内网的访问设置权限验证,所以存在SSRF时,通常会造成较大的危害。
5.检测漏洞
1.因为SSRF是构造服务器发送请求的漏洞,所以我们可以通过抓包分析发送的请求是否是服务器端发来的请求来判断是否存在SSRF漏洞
2.也可以在页面源码中查找是否存在可以访问的资源地址,如果有一个资源地址的类型为http://www.xxx.com/a.php?image=地址,就可能存在SSRF漏洞
6.示例
假如我们有一个网站可以加载远程地址的内容到本地,并且系统没有对我们传入的url参数进行任何的检查,我们就可以构造其他的请求,例如:
1 | http://www.xxx.com/article.php?url=http://127.0.0.1:22 |
file:///
协议用于访问本地文件系统,而/etc/passwd
文件通常存储着系统用户的信息
7.相关的函数和类
8.相关的伪协议
- file 协议结合目录遍历读取文件。
- gopher 协议打开端口。
- dict 协议主要用于结合 curl 攻击。
- http 协议进行内网探测。
0x02刷题
web351
1 |
|
因为是新的章节,所以我们先来分析一下这段代码
1 |
|
总的来说,这段代码的功能是接收一个远程URL,使用cURL库访问该URL,并将获取到的内容直接输出到浏览器
,结合我们上面说的知识点,这里的话可能就会存在ssrf漏洞,为什么呢?因为他可以向别的地址发起访问申请,我们可以抓包分析一下
我们分析一下这个请求包的内容
1 | Sec-Fetch-Site: same-origin#用于指示请求的来源,此处的 same-origin 表示请求来自于同源页面 |
那这道题该怎么去做呢?
首先我们是可以知道这里是有一个flag.php的,我们先访问看看
发现这里是非本地用户无法访问的,所以我们就可以发现这个flag.php的话可能是存在本地也就是我们访问不到的,那我们得通过这个当前的服务器去访问我们的本地服务器,就可以拿到flag了
这里的话就通过这个ssrf去构造服务器请求,去带出我们本地服务器中的flag.php文件
当然我们也可以用file协议去读取我们本地的文件
file:///etc/passwd 有返回值,猜测flag在当前目录,而当前目录一般都是/var/www/html 故传入file:///var/www/html/flag.php
web352
#过滤本地地址
1 |
|
$x=parse_url($url);
在PHP中,parse_url()
函数用于解析 URL,并返回一个关联数组,其中包含 URL 的各个部分,如 scheme(协议)、host(主机)、path(路径)、query(查询参数)等。当你调用parse_url($url)
时,它会将提供的 URL 字符串 $url
进行解析,并返回一个包含解析后各部分信息的数组 $x
。
例如,如果 $url
是 http://www.example.com/test.php?q=123
,那么 $x
数组可能如下所示:
1 | Array ( |
这里的话就是对参数禁止了本地访问,但是又需要我们去传入协议为http或者https
进制绕过
这里我们用127.0.0.1的十进制2130706433
1 | url=http://2130706433/flag.php |
当然也可以用十六进制去绕过哈
1 | url=http://0x7F000001/flag.php |
但是后来我发现这里有过滤但是好像没什么用,所以web351的本地访问的做法还是可以正常做的
web353
1 |
|
和上题一样用进制可以打的通
关于环回地址
但是127.0.0.1 ~ 127.255.255.254 都表示 localhost,在IPv4地址空间中,127.0.0.1到127.255.255.254是保留的地址范围,用于表示本地主机(localhost),也称为环回地址。
所以我们的payload也可以是
1 | url=http://127.233.233.233/flag.php |
sudo.cc代替本地地址
当你在浏览器中输入sudo.cc
时,操作系统会将这个域名解析为127.0.0.1
,从而把请求发送到本地主机。
payload
1 | url=http://sudo.cc/flag.php |
web354
1 |
|
这次的话把1和0过滤了,能用的方法就是sudo.cc,但是我学了一种方法就是302跳转
302跳转
在自己的网站页面添加php文件进行302跳转
1 | <?php |
这串代码会将浏览器重定向到本地主机(localhost)上的flag.php
页面,当浏览器收到这个响应头后,它会自动跳转到指定的URL地址。
然后我们的payload:
1 | url=http://自己的网页地址/php文件名 |
web355
1 |
|
这里对host的长度进行了限制,也就是我们不能用127.0.0.1这种地址去解题了,但是我们可以想到
关于0的解析
0在 linux 系统中会解析成127.0.0.1在windows中解析成0.0.0.0
所以我们设置payload
1 | [POST]payload:url=http://0/flag.php |
关于无效地址解析
在 URL 中,当域名或主机名中使用了一个无效的 IP 地址时,浏览器通常会将其解析为本地地址 127.0.0.1,即回送地址。
所以我们的payload
1 | [POST]payload:url=http://127.1/flag.php |
web356
1 |
|
只能有3个字符了,那就直接0或者0.0都行
web357
1 |
|
gethostbyname()函数
gethostbyname()
函数是PHP中用于获取主机名对应的IP地址的函数。它接受一个主机名作为参数,并返回该主机名对应的IP地址。
基础语法
1 | string gethostbyname ( string $hostname ) |
$hostname
:要获取IP地址的主机名。
filter_var()函数
filter_var()
函数是 PHP 中用于过滤和验证数据的函数之一。它可以根据指定的过滤器对数据进行过滤和验证,确保数据符合特定的格式、类型或规则。
基础语法
1 | mixed filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] ) |
$variable
:要过滤或验证的变量。$filter
:可选参数,指定要应用的过滤器。默认是FILTER_DEFAULT
,表示使用默认过滤器。$options
:可选参数,用于设置过滤器选项。
FILTER_VALIDATE_IP过滤器
FILTER_VALIDATE_IP
是 PHP 中的一个常用过滤器,用于验证一个字符串是否为有效的 IP 地址。当使用 FILTER_VALIDATE_IP
过滤器时,filter_var()
函数将检查字符串是否为有效的 IPv4 或 IPv6 地址。
FILTER_FLAG_NO_PRIV_RANGE
FILTER_FLAG_NO_PRIV_RANGE
是过滤器标志,用于排除私有地址。私有地址是指保留用于内部网络的地址
FILTER_FLAG_NO_RES_RANGE
FILTER_FLAG_NO_RES_RANGE 是过滤器标志,用于排除保留地址。保留地址是指在公共网络中不可路由的地址。
这里的话会验证我们传入的地址是否是有效的ip地址,并且会排除我们的私有地址和保留地址
那我们的做法就是用302跳转去做
payload:
1 | url=http://服务器的web页面地址/php文件名 |
或者也可以dns rebinding攻击
DNS rebinding 攻击是一种利用 DNS 协议的漏洞来攻击网络应用程序的方法。在 DNS rebinding 攻击中,攻击者通过将恶意站点绑定到一个 IP 地址,然后将此 IP 地址映射到一个不同的 IP 地址,来欺骗目标浏览器执行恶意代码。
1·修改自己域名的a记录,改成127.0.0.1
2·这个网站a记录指向127.0.0.1 可以直接利用
这个方法没试过,可以试一下
web358
1 |
|
先讲payload
1 | url=http://ctf.@127.0.0.1/flag.php#show |
为什么呢?
- 当
parse_url()
解析到邮箱时:@前面是user,后面是password。因为在基于 HTTP 和 HTTPS 协议的 URL 中,@
符号通常用于指定用户名和密码,而不是作为域名的一部分。
web359
打无密码的mysql