首页
社区
课程
招聘
[转帖]Package 钓鱼
发表于: 2017-6-2 10:20 2414

[转帖]Package 钓鱼

2017-6-2 10:20
2414

0x00 前言

前几天 Samba 公开了一个远程代码执行的漏洞,然后各种 POC 也随之出现, exploit-db 上也有这样一个 Python 版本的 POC: Samba 3.5.0 - Remote Code Execution.

直接执行 POC,报错误信息:

这种情况非常简单,直接 pip install smb 就行,但是:

好吧,我们还是需要 Google 一下这个 smb 的 package 名字,最后发现原来是 pysmb

最后 POC 终于跑了起来.

我们再回过头来看看整个流程,似乎并没有什么地方不对劲。

直接说问题所在吧,如果你在 2017-05-24 到 2017-05-31 这段时间内执行过 pip install smb 或者 pip download smb, 那么恭喜你,你的名字可能出现在我的绵羊墙上。

0x01 试水 (2017-05-23 19:00)

第一天,我在 PyPI 上投放了 4 个 evil package: python-devmongodbproxyshadowsock 测试一下不检查 package、随意安装 package 的人有多少。

其中所有的内容都是用 cookiecutter 根据模版 cookiecutter-evilpy-package 生成。

每个 package 都会收集用户的

  • username
  • hostname
  • ip
  • hostinfo

我选择了 GitHub Issues + webtask.io 的方式,将安装 evil package 的用户信息通过 webtask.io 中转到 GitHub Issues 上对外公开。

所以我就在 Github 上注册了个小马甲 evilpackage 专门提交 Issue。

因为 webtask.io 获取客户端 ip 的时候,其实获取到的是 webtask.io 前面 nginx 的 ip 地址,并不是用户的 ip,所以就只能在代码里面获取客户端的外网 ip. 使用 webtask.io 和 GitHub Issues 的主要原因是这两都是免费的。

0x02 增加投放 package (2017-05-24 19:00)

查看了一天的 Issues 数量,大概有 700+,效果非常不错,决定继续投放 evil package。 与此同时,@ztz 同学也加入了游戏,也在 RubyGems 上投放 Gems。

继续投放 evil package,就必须想一些比较好的名字,我主要使用下面两种方法:

  1. Google 搜索提示框
    直接根据 Google 的搜索框提示:

    便收集到了没有在 PyPI 上注册,而且比较流行的 Package 名字:

    • caffe
    • ffmpeg
    • git
    • mkl
    • opencl
    • opencv
    • openssl
    • pygpu
    • tkinter
    • vtk
    • proxy
  2. 想象力
    依据平时写代码的经验总结出下面可能觉得会常用,但并没有在 PyPI 上注册的 Package 名字:

    • ftp
    • smb
    • hbase
    • samba
    • rabbitmq
    • zookeeper
    • phantomjs
    • memcached
    • requirement.txt
    • requirements.txt

其中 requirements.txt 并没有注册成功,稍后再说。

0x03 暂停服务 (2017-05-25 23:00)

晚上回家的时候又统计了一下安装量,一天安装量达到了 2000+,效果已经很显著,不必再增加新的 package 了,但是到了晚上 23:00 的时候, 我的 GitHub Issues 被恶意插入脏数据,所以只能暂停服务:

之所以只能暂停服务,那是因为 webtask.io 没法获取客户端 ip,我也没法 ban 掉对应的 ip,作出任何相对的处理,只能停服务。

话说到底谁才是攻击者。

0x04 evilpackage 被封 (2017-05-26 2:00)

我专门提交 Issue 的小马甲 evilpackage 因为触发了 GitHub 对 Spam 的检测,所以被封号了。 早上起床看到消息后,立马写邮件申诉,直到 2017-05-26 13:00 终于回复我的邮件了:

0x05 放弃 webtask.io (2017-05-26 19:00)

为了避免和之前一样被恶意插入脏数据,决定要放弃 webtask.io,每月花费 $10 巨款购入一台 vps。

使用 nginx + flask 的配置,继续将 user data 提交到 GitHub Issues 上。

nginx 的 ngx_http_limit_req_module 模块最大能够支持 1s/m,也就是最多可以限制每个 ip 在每分钟内最多请求一次, 所以我们必须修改 ngx_http_limit_req_module 模块代码

增加一个 else if block,直接将 scale 增加到 1000,这样就能限制每个 ip 在 16 min 内只能访问一次我们的接口, 除非使用大量代理,不然很难在短时间内插入大量脏数据。

0x06 repo 被封 (2017-05-27 3:00)

早上起床刷新一下 GitHub Issues 页面,结果发现:

邮件:

赶紧先上服务器加上一行代码,将用户上传的数据先暂时存在本地(之前太懒)。 然后马上回邮件,问情况,两天后:

解封无望,之前的数据大概就是没了。

目前还能通过 GitHub Search 找到以前的部分数据 GitHub Issue

0x07 写 web 界面 (2017-05-30 19:00):

由于之前一直在忙,最后拖到了30号才开始写 web 展示界面 http://evilpackage.fatezero.org/

也准备好新的 cookiecutter 模版 cookiecutter-evilpy-package

新的 cookiecutter 模版会提示用户安装了 evilpackage,并打开用户的浏览器去访问 http://evilpackage.fatezero.org/,让用户知道,自己已经是绵羊墙上的一员了。

计划打算第二天再往 PyPI 上提交新版本的 Package。

0x08 清空 (2017-05-31):

早上查找资料的时候发现,原来已经有好几批人干过和我一样类似的事情了

前两批都只是上传一个 package 用来提示安装用户,也防止恶意用户使用这些 package 名字, 后面一个小哥和我一样收集了用户不太敏感的信息,只不过他的数据一直没有公开。

过了一会 @ztz 同学告诉我他的 RubyGems 被清空了。

再过了一会我这边也被 PyPI 管理员警告要删除账号了,所以我就把所有的 Package 给删除了,账号也给删除了。

目前为止所有的 package 又回到了 unregister 的状态, 任何人都可以继续注册使用我之前注册的 package.

0x09 数据统计

目前我只能对在 http://evilpackage.fatezero.org/ 上那 10685 条数据进行统计

从 2017-05-27 10:38:03 到 2017-05-31 18:24:07,总计 106 个小时内, 有 9726 不重复的 ip 安装了 evil package,平均每个小时有 91 个 ip 安装了 evil package。

  1. 每个 package 命中排名:

  2. 前 50 个国家命中排名

  3. 每个访问排名

光从这几天来看,在 PyPI 上投放 evilpackage 的效果还是非常不错的, 每天都会有大概 2200+ 个独立 ip 进行访问,数据量稍微比之前那位小哥好一点, 也就是说,即便是类似的文章发出来,过了一年之后,随意安装 package 的这种情况完全没有改善,可能更严重了。

那位小哥释放掉所有的 package 之后,我作为一个 “恶意者” 再次使用他之前使用的 gitopenssl 名字来统计数据, 我作为一个 “恶意者”,被官方勒令删除所有的 package,这些 package 名字再次被释放,我比较好奇下一位 “恶意者” 会是谁, 会在 package 里放什么?会是和我一样收集数据,还是直接 rm -rf /,还是勒索。拭目以待。

0x10 requirements.txt

一般经常使用 Python 的人都知道 requirements.txt 是整个项目的依赖文件,一般这样使用:

不过也有可能一时手速过快,敲打成

所以 requirements.txt 也是一个比较好的 evil package 的名字

诡异的 requirements.txt

在 2017-05-24 19:00 晚上,我尝试在 PyPI 注册上传 requirements.txt 的时候:

嗯,都失败了,但是 GitHub Issues 上竟然会有 153 个和 requirements.txt 相关的 Issues:

我并不怀疑这些 requirements.txt 数据的真实性,因为就没有人知道我尝试上传过 requirements.txt,所以这些数据肯定是真实的。

PyPI 上也并不存在 requirements.txt 信息,本地尝试安装也失败了,至今仍未明白这种情况为何发生。

绕过 PyPI requirements.txt 的限制

在 PyPI 账号被删除之后,我还是对 requirements.txt 很好奇,为什么之前 GitHub 上会有记录? 能不能绕过 PyPI 的限制?下面简单讲一下如何绕过 PyPI 的限制。

我们直接查看提交 Package 时,PyPI 对 Package 名字限制的地方:

通过上面的代码,我们可以看到 PyPI 直接硬编码 'requirements.txt', 'rrequirements.txt', 'requirements-txt', 'rrequirements-txt' 禁止用户上传这些文件。

我们再看看 pip install xxx 的时候,PyPI 是怎么查找 Package 的:

好吧,直接查找数据库,我们再跟下来看 normalize_pep426_name

看到中间那个正则了吧,这也就意味着

这几条命令其实都是等价的,都是在安装 youtube_dl, 那么我们就可以很容易的就绕过 PyPI 的限制, 直接上传一个 requiremnets--txt

来来来,我们直接尝试 pip install requirements.txt

通过上面的图,我们可以看到 PyPI 已经返回我们的 package url, 到了 pip 准备安装这个 package 的时候报错了,所以直接看 pip 代码:

看了代码,也就是没法在 url 中获取 package 的版本号, 因为 package 的名字(requirements--txt)和搜索名字(requirements.txt)对不上,我们得找找其他方法:

看到这里,大家应该也知道了,之前我们一直都是使用 source 的方式提交 package,如果我们直接打包成 wheel, 根据上面的代码,就不会再报错了,我们重新打包,再次上传:

终于成功了,当然 wheel 安装方式并不能直接执行命令, 不过我们可以通过给 requirements.txt 添加一个恶意依赖达到执行任意代码的效果。

在这里,我就添加了一个名为 ztz 的 source package,用于提醒安装 requirements.txt 的用户

0x11 总结

想做一件坏事情真不容易,快去看看 http://evilpackage.fatezero.org/ 上面有没有你的名字。


来源:fate0


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 68
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
所以就是为了写一篇论文?
2017-6-2 16:43
0
游客
登录 | 注册 方可回帖
返回
//