借最近的一个案例,来聊聊实战中获取源码的一些姿势。
(也是前段时间某次闭门分享的素材:hope you guys enjoy it~
Liquid Files
Liquid Files是国外的一款网盘,官网:https://www.liquidfiles.com/

是收费的一套系统,老外用得多。
咱们今天就来试试获取这套系统的源代码,并进行前期的攻击面评估(初步的代码审计)
0x00 一般思路
正如我在文章《记一次Java Servlet实战审计 - 先知社区》中说的那样,获取系统的源代码主要可以从几个角度来考虑:
- 同类站扫目录。
- 上Fofa搜索同类系统
- 导出资产列表
- 目录扫描。具体操作起来,就是使用
dirbuster的字典directory-list-2.3-medium.txt来扫,工具就随便用个顺手的,dirseach(ps:它的字典dicc.txt也好用)
结论:因为本身这玩意儿的发布形式都是镜像,统一部署的,当然不会有备份文件了。。。无果。
- **网盘泄露。**这套系统并不开源,一般国内的厂家发版的时候为图方便,都会放了一些在网盘,简单一搜就知道有无结果。
结论:人家厂家本身有官网,没必要传网盘,麻烦。无果
- Github、gitlab泄露。搜了下——您看看,这像源码么?

结论:无果。。。
也不绕弯子了,但凡看过官网就知道:这公司很耿直,直接提供了试用……
这也正是本文主要想介绍的技巧:利用厂家的安装镜像,获取源代码。
0x01 试用
那么我们直接注册试用,登录注册进到下载界面…

舒舒服服的。随便下哪个都行,安上跑起来

填写License Key

安装信息填好,部署在内网,直接开冲!

在系统里玩耍一番后,发现System下面有个功能叫Console,大喜——点进去一看:nmd,试用License无法使用Console

可见,厂家并不希望试用用户拿到root权限……此时,获取源码像是陷入了僵局
0x02 柳暗花明
不过——且让我们来整理整理手上的信息:
- 端口只开了80,443,222,连ssh端口都没开…..
80/tcp open http
222/tcp open rsh-spx
443/tcp open https
- 不对,默认不放开ssh的话,那系统一旦出问题了——连也连不上——岂不是直接烂在里面,不合适吧。因此,感觉不怎么可能关闭ssh
- 仔细一看,噢,原来这个222,就是ssh的端口
PORT STATE SERVICE VERSION
222/tcp open ssh OpenSSH 7.4 (protocol 2.0)
MAC Address: 00:0C:29:4C:C9:82 (VMware)
- 好的,现在知道ssh开放了,但是root密码呢,翻了翻文档,没找到。。。
- 于是爆破!
top10k、rockyou.txt——给爷猛冲!
hydra -t 4 -l root -P rockyou-15.txt -s 222 ssh://10.10.111.6


全部出错?不让我爆破?
不让爆破,那咋办,这镜像安在我的电脑上,就是我的了,爆破一下居然还要被拒之门外?
- 突然想到——这套系统安装在VM中——相当于我可以物理接触它——再联想一下Windows不是开机的时候可以通过进入安全模式来恢复密码吗——Linux应该也有这种模式吧?
于是,有了这第三节
0x03 单用户模式
下面的内容参考自http://c.biancheng.net/view/1041.html
- 很多新手当面对“忘记 root 账户密码导致无法登陆系统”这个问题时,直接选择重新系统。其实大可不必,我只需要进入 emergency mode(单用户模式)更新 root 账户的密码即可。
- Linux 的单用户模式有些类似 Windows 的安全模式,只启动最少的程序用于系统修复。在单用户模式(运行级别为 1)中,Linux 引导进入根 Shell,网络被禁用,只有少数进程运行。
如何进入单用户模式
现在,我们假设系统出现了问题,已经不能正常登录了。那么,如何进入单用户模式呢?首先需要重启服务器,在 GRUB 读秒界面按任意键,进入 GRUB 菜单界面,如图所示

在想要进入单用户模式的 Linux 菜单上按"e"键,就会进入 GRUB 编辑界面,如下图所示:

找到linux /boot/vmlinuz-*那行,江湖上传闻有两种常见的操作方式:
- 【我常用】在最后添加
init=/bin/bash,然后按ctrl+x或者F10继续grub引导,此后的用户,即为root用户,可以在其中随意更改root用户的账号密码 - (没试过)将它的ro recovery nomodestset及之后的东西替换为
rw single init=/bin/bash,然后按 ctrl+x或者F10 进入单用户模式

总之,虽然单用户模式下面没有网络,但可以修改用户的密码呀~
更改密码之后重启,登录ssh

通过web的静态文件,锁定源码文件的路径:/app
zip打包,起SimpleHTTPServer到8080端口,准备下源码咯
诶,为啥访问不到???
一查,存在ufw防火墙——当然要把它关闭——不过我这里比较温柔,添加了放行规则

下载,搞定!

至此,源码到手,且无混淆——黑盒变白盒,美滋滋。
0x04 后台鸡肋命令执行(低权限)
发现一个叫做Actionscripts的功能,大意就是可以在这里自定义函数,在某些特定的流程中会自动执行。

顺手传个弹shell的脚本,上图中可以看到,系统会自动识别脚本的类型

上机查看,脚本被保存在目录/data/domains/default/actionscripts下,名字没有改动。

接下来,当然就跟源码
全局搜索actionscripts关键字,定位到这个文件app\current\app\helpers\admin\actionscripts_helper.rb

这里补充1个知识点:
Ruby中,
%x{COMMAND}这种写法,代表使用```执行一段 shell 脚本,并返回标准输出内容

霍!会执行命令,而且执行的内容跟用户传入的文件名相关——有搞头
跟入类的代码,发现构造方法initialize、path的实现
initialize,简单赋值,没啥path里面有用shellescape对参数进行转义,那没事了。。

然而,接着看下去就知道,无法命令注入,不光有这个原因。
还是回到刚刚的危险函数actionscripts_type_column,它在哪里被调用了呢?
——在erb模板中,也就是MVC框架中的View层,代码如下图所示

(顺便感受下Rails模板的渲染效果)
上面我们说到,用户请求在框架中的流转顺序,其实是Controller、Model、View
在View层发现了风险点,当然要跟一下它之前的Controller,也就是app\v3.5.12\app\controllers\admin\actionscripts_controller.rb
函数列表如下

其中,控制器的前两行是before_action,类似于Java Web中的Filter

使用sanitize_filename方法,对文件名参数进行了处理
def sanitize_filename
unless (@sanitized_filename = script_params[:script_name].gsub(/[^a-zA-Z0-9\-\_\.]/, "_").gsub(/^\./, "_").strip).present?
render_error "Invalid Filename", {
location: admin_actionscripts_url
}
end
end
校验了逻辑只允许a-zA-Z0-9-_,其它的字符都会被替换成_。
总之,这个功能点,先在Controller层就校验了文件名,后面在View层调用的也是shellescape转义过的安全执行函数——这个过滤还挺够劲儿。
不急,咱们继续往下分析。
后台找半天没找到这个ActionScript在哪里会触发…于是依然搜代码,原来
在“添加用户”的地方,有个功能叫Delivery Action,设置给某个用户发消息后自动进行的Action
What delivery action should be taken when a message is being delivered to this user.
You can manage Actionscripts in the Actionscripts section.
鸡肋EXP
完整的利用过程如下图所示

或是其它几个功能,也能触发

只不过,是一个低权限的用户——几乎什么权限都没有。。。既然改不了文件,就无法通过修改代码的方式来提权,那咋办?
留给各位师傅思考,今天的文章就写到这里,哈哈~