Yukang's Page

Ruby的 open 函数导致命令执行

说明

首先看看 open 函数的文档说明, https://apidock.com/ruby/v1_9_3_392/Kernel/open/class:

If path starts with a pipe character, a subprocess is created, connected to the caller by a pair of pipes. The returned IO object may be used to write to the standard input and read from the standard output of this subprocess. If the command following the “|” is a single minus sign, Ruby forks, and this subprocess is connected to the parent. In the subprocess, the open call returns nil. If the command is not “-”, the subprocess runs the command. If a block is associated with an open(“|-”) call, that block will be run twice—once in the parent and once in the child. The block parameter will be an IO object in the parent and nil in the child. The parent’s IO object will be connected to the child’s stdin and stdout. The subprocess will be terminated at the end of the block.

其中说明了如果以|开头则会 fork 出一个进程,| 后面的内容则会当成一条命令执行,比如:

cmd = open("|date")
print cmd.gets
cmd.close
=> 2018212日 星期一 213745秒 CST

漏洞

正因为这样,这个 open 函数真的是很容易出错,最近的这个 PR:

https://github.com/ruby/ruby/pull/1777

之前我们的项目里也出现过类似的情况,直接相当于一个 webshell,任意执行命令。这样的 command injection 当然也很好检测,brakeman 之类的就可以。所以 Rails项目还是时不时地扫描一下比较好。

Ruby 里面有几个 Open,这里有比较明晰的解释,Kernel.open 这个函数就是一个 wrapper,根据不同的情况做对应的处理。趟多了坑之后,才会觉得这样的特性其实是增加了程序员的负担,比如这个|特性可能有的人就没注意到,即使是看过文档也可能看到了老版本的文档,从而不知道这个边边角角。

当然同样的 system这样的命令执行函数也是类似的情况,比如railsgoat 里的这个 command injection。原则是对于任何用户输入的参数,都需要做不安全的假设,做好检查。

https://github.com/OWASP/railsgoat这个项目里有各种 Rails漏洞,值得看看。

发表评论

BuckleScript and Reason

BuckleScript虽然我不是前端工程师,不过因为喜欢 OCaml,所以偶尔关注 BuckleScript 有一段时间了,今天又花时间看了看文档和代码。BuckleScript 是张宏波主导开发的开源项目,『有希望成为第一个完全由国人设计主导实现并被世界各地广泛使用的编译器』,不过是 .....
阅读全文

《深度工作-如何有效使用每一点脑力》读后

深度工作这本书主要讲解了一些时间和精力管理方面的东西,人到了一定年龄就会觉得时间不够用,日子过得太快,每天觉得都没干什么就过去了。工作几年后这种感觉时不时袭来。反而是如果某段时间一直有一个阶段性的目标,就会觉得很踏实,进度和效率也可以。那种完全沉浸在思考中的状态真的也并不是累,相反所得到 .....
阅读全文

Kong的0.11.0版本

Kong发布了新的版本0.11.0,从这里开始区分了社区版本和商业版。这次改动比较大的是丢弃了serf,这样整个Kong节点之间的缓存同步方式变化了。开发者给出的理由如下: 依赖serf,serf并不属于Nginx/OpenResty 这种依赖相互间通信来同步的机制对于deploym .....
阅读全文

Lua时间处理

我需要用Lua处理一个与时间相关的问题,比如我们在配置文件里面配置一个日期(北京时间),然后在Openresty里面判断当前时间是否在这个日期之前或者之后来做对应的逻辑。 Lua的时间处理还有点麻烦,主要是自带的相关库函数比较少。 os.time() &l .....
阅读全文

使用 exercism 来练手学语言

有时候我们想学一门编程语言,但是光看看书和代码用例总是找不到感觉,这时候我们应该尝试写点不短不长的程序片段,可能是一个函数,或者是实现一个简单的算法。最近我发现这个叫做exercism.io的网站不错,自己也在闲余时间在上面看看。 这里支持30多种编程语言,每种语言大概有80个左右的小问 .....
阅读全文

从 Jekyll换成Hexo

昨天看到自己的 Blog 在移动端显示丑死了,所以想着优化一下,找一个 mobile first 的风格试试。顺便把 blog 从 jekyll 换成了 Hexo。最后找到这个 hexo 的主题非常顺眼,便拿来用了,感谢yanm1ng为大家提供如此优秀的主题。回想起自己之前用过搜狐博客, .....
阅读全文

Kong源码分析: 事件

Kong的缓存更新很多依赖于事件,而事件看起来是相对来说比较复杂、也是最有趣的一部分。 worker模型假设我们对Kong做了一个更改的请求,这个请求通常是通过admin_api这个路由处理的。也就是说最终执行数据库操作的动作是在一个Nginx worker进程里。因为操作了数据库所以我 .....
阅读全文

Kong源码分析: 缓存

Nginx里的缓存使用在Kong里面我们缓存的内容大部分是配置,不管是API本身的配置还是插件相关的配置,缓存之后就存储在内存中。 Kong里的缓存基础代码在tools/database_cache.lua文件里面。这里又分两种类型的缓存,一种是shared dict, 一种是使用lua .....
阅读全文

Kong源码分析: 插件

插件的强大之处在我自己使用 Kong 的过程中,最方便的还是在于 Kong 的强大的插件机制。 Nginx 本身提供了提供模块开发机制,但是相对来说更底层一些,并且需要使用 C/C++ 来开发,对于很多开发人员来说 Nginx 仍为一个黑盒。OpenResty 集成了很多好用插件,并提供 .....
阅读全文
Prev Next