这期给大家带来一台比较特殊的靶机,之所以特殊,是因为这个靶机在21年8月9号才正式发布出来的一台靶机。我个人是花了一天的时间把它打下来,截止到目前为止,我在互联网上还没有看到有人写出关于这台靶机的打靶过程文章。所以我有可能是世界上第一个人把这台靶机给打下来的。
我会把我打靶过程记录下来。包括我在这个打靶过程中遇到的问题,以及我个人当时的一些思路尽量完整地呈现出来。
这个靶机作者把这个靶场难度定义为中级难度,我个人在打靶过程中发现无论是边界打点、突破边界、拿到基础权限以及到后期的一个提权的方法都非常的巧妙 。和我们通常打的那些靶机思路我们习惯打的那些靶机利用的那些漏洞都有很大的不同。即便是传统的漏洞它也采用了新颖的方式,所以整个构思非常的巧妙,我个人非常喜欢这个靶机。
目标:取得2个flag + root 权限
靶机下载地址: https://www.vulnhub.com/entry/chronos-1,735/
设计攻击方法:
端口扫描 WEB侦查 命令注入 数据编码 搜索大法 框架漏洞利用 代码审计 NC串联 本地提权
我的kali机ip是10.0.2.4,靶机ip是10.0.2.7
依旧开始是主机的发现,前面两个靶场用到了arp-scan和arping命令,这次再给大家介绍一个不一样的工具:netdiscover(原理都是一样的,都是通过arp地址解析协议方式来发现)
可以扫描网段ip,拿我这个网段举例命令格式:sudo netdiscover -r 10.0.2.0/24
接着开始扫描目标ip的端口开放情况:
可以看到22、80、和8000端口开放,前面两个不用说,这个8000端口是个Node.js开发以及结合Express框架。(虽然自己看过Node.js这方面的书,但是从来没有实践开发应用过。所以当我看到这个端口是这个服务的时候心里略微有些担心的,怕自己拿不下这台服务器。这也印证了我后来大量的搜索学习最后找到那个漏洞,最后也再次印证打下这台靶机的关键其实就在于这个8000端口)
按照惯例,既然开启了80端口的http服务,就去访问一下:
什么功能点也没有,似乎就是一个静态页面。
对于这种网页,想要找出漏洞一般就两种方法:
第一种就是爆破目录,看看是否存在管理员等后台地址;第二种就是查看页面源码是否有泄露的信息、调用接口、脚本信息等。
好像没有什么信息,都是html元素标签,但是细心的同学可能会发现js文件里面有一串脚本代码。我们将代码复制下来,然后去一个在线网站对这串整理与美化相关操作(这里给大家介绍一款工具:cyberchef 这款工具非常强大,可以针对计算机做各种数据的编码、解码、还原、解密、解压等相关操作):
我这里先将复制的代码粘贴到input模块,然后选择JavaScript Beautify,让它帮我整理,成为Output模块的内容了:
美化之后还是比较难读,因为绝大多数函数都是编码的,当然用这个工具解码不是问题,不过为了不打乱渗透最原始的数据,我们先阅读一下这个源码看看有没有敏感信息之类的再解码也不迟:
所有的都数据都编码了,唯独这个链接,它是一个chronos.local这个域名,同时是8000端口,还记得我们一开始扫描靶机端口也有一个8000端口开放吗?那么这个域名是不是就是我们这个靶机10.0.2.7这个ip对应的同一个主机呢?我们有理由怀疑它就是目标靶机本身。
接下来我们就修改hosts文件:
将靶机ip和这个域名进行绑定,同时再ping域名可以通:
这时候我们再次访问这个靶机:
这时候页面变化了,上面显示当前的时间了。
我们这时候就想用burpsuite来抓取这个页面访问请求的资源、流量请求等:
重新请求这个页面,放包,看历史记录,这个GET发起Request请求包,放回Response返回包有个返回的在线时间,而这个过程只用到了一个format后面那一串传参导致的,那么我们给这个Request请求放到repeater模块尝试修改传参值看看页面还能否返回不一样的信息:
很显然,我随便修改了传参值,Response不会返回给我任何信息了。
所以我们很想知道这一串传参值是什么?能够发送请求会让服务端返回到页面给出当前的一个时间值?
我大概看了一下这个传参值很可能是个base64编码的值。
4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL
我们将这个传参值同样放到刚才这个cyberchef工具上面解码:
我们用到这个工具神奇的功能(当你不知道一串值是什么编码的时候就是用“magic”这个模块,它会自动识别)
识别出来是base58编码之后生成的这种密文。(因为base家族大家比较常用的都是base64编码,而不知道还有base32,58等编码格式。作者在这里也是故意没有设置base64编码防止被人很容易还原出来,遂采用了不是很多人使用的一种base编码)
仔细观察这个被还原的明文:
'+Today is %A, %B %d, %Y %H:%M:%S.'
我第一眼看到时候直观感觉好眼熟啊,结合url前面的date,有点像linux系统当中的date命令
date命令后面是可以跟上一些列变量名。
到这我想很多人都明白了。当我们访问这个url的时候,是不是服务器执行了一个:
date '+Today is %A, %B %d, %Y %H:%M:%S.'
这种命令。
这时候会不会立即想到命令注入,熟悉前面靶场的就知道管道符作用来了。
今天我给大家用个其它命令(用的工具和命令多样性为了让大家能够学到更多,而不是只有一种招式)
双管道前后两个命令,如果前面命令执行错误才会执行后面命令,如果前面命令执行正确后面就不会被执行。
而“&&”符号相反,当前面命令执行正确才会执行后面的命令。
这次比较适合用&&符号,因为访问页面传参就是一个正确的指令,如果再去修改有些麻烦,不如直接在后面加上想要执行的命令:
就像这样,时间输出了,我们想要的ls命令内容也输出了。
接下来我们就要在页面输出,所以需要format传参修改,既然传参是base58编码,我们也需要编码之后再放进去:
得到编码之后的字符了,把它加到之前formate传参后面执行一下:
我们看到成功了,时间和ls执行的当前文件目录列出来了。
接下来我们就是要做反弹shell操作,反弹shell靶场1我用到第三方工具来玩的(Venom),
靶场2我是用nc反弹,我也比较推荐使用这个nc,因为很多linux发行版都自带这个工具,如果用第三方工具还需要传输下载。会麻烦一点。我用命令查看目标上是否有nc:
同时看到bash,接下来我要获取shell的时候可以尝试去执行bash shell来反弹它。
事实上这个nc没有-e参数,由于篇幅关系,我这里不做演示判断。
直接来用之前所讲的”串联nc”反弹shell:
开启两个监听端口,同时把要反弹的命令编码:
能够看到成功反弹shell,这时候在目标靶机得到一个基本的shell权限,接下来收割flag,并且提权:
依旧是信息收集查看靶机上的文件有哪些信息,通过一番查找:
看到一个user.txt文件,打不开,查看权限显示只有root用户才能执行,这时候就需要提权操作了。
在这里我用了三种方法1.基于内核漏洞提权2.uid权限配置错误漏洞 3.sudo配置漏洞。
系统该版本无漏洞利用,suid也没有权限配置错误,sudo权限是www-data,权限非常低。。
到这里为止了,似乎遇到瓶颈了。
这种困难的处境在我们真实渗透测试环境当中我相信每个人都会遇到,你常见的、通常使用的惯用方法针对当前系统无效,所以你必须要寻找新的出路。那如何寻找新出路呢?
那就是在目标靶机上做大量的信息收集,你越做渗透测试经验越丰富,你越发现信息收集是整个过程中最最关键的那个环节。当信息足够多的时候你就有思路,当你信息不完善的时候,你可能一条思路也没有。
于是我经过一番折腾大量信息收集之后我在web系统根目录下查看源代码:
查看package-lock.json文件(因为在所有的基于node.js开发下根目录都会包含这个文件,会定义项目模块、版本信息等)
声明了一些框架:bs58(这个模块就是服务端利用它进行base58字符编码、解码、还原等操作)、cors、express(针对这个框架搜索了很多是否有漏洞,无果)
接下来查看app.js(应该是个主文件)
首先加载了一些库,路由配置,比如访问根目录,就把它路由到/var/www/html/index.html路径下
当有人访问/date路径下,就路由下面的:
首先是agent头获取’user-agent’
定义cmd是’date’
接着获取到format赋值,然后通过bs58解码,(提交上来的数据都是经过bs58编码,而在服务端是经过解码,再把字节还原成相应的字符,然后再把字符串和cmd连接起来),于是完整拼凑date.
所以发现从客户端传过来的数据没有经过任何处理防御,只是加解密编码,做出响应。
这也是为什么我们刚才利用了它的漏洞来命令注入进行反弹shell操作。通过这个源码审计也印证我们的操作。
接下来是判断头,User-agent字段都是Chronos会进行判断,如果不是会返回拒绝访问。而如果是这个字段,但是你输入的字符当中包含id、python、nc、bash、php、which、socat这些字符时,会出现”Something went wrong”,但虽然会报这样一句错误信息,但是服务器没有进行拦截和阻断,仅仅是提示这样一句话,这也是为什么我们命令注入的时候出现这样一句话反而程序照样执行成功了。所以再次印证我们之前的操作都是说得通的。
通过源码分析之后,发现找不到和提权操作有关系的漏洞。于是当时我在打靶机的时候也是很遗憾,于是不得不继续找其他地方。终于,功夫不负有心人,当我访问到它上一级目录的时候,发现一个chronos文件,进入chronos-v2里面有个backend文件
同样看到了这个package.json文件,我之前说了,这是用node.js会在根目录生成这样一个文件,里面会配置用到的一些依赖库文件名等信息,(我当时想能不能又利用的模块库呢,这是我唯一能想到的)我们打开看看:
里面分了两块,第一块上面展示服务端主程序是server.js(稍后再去查看它),启动这个服务端程序调用node
第二块是一些依赖的库信息,ejs(嵌入式javascript),express库,上一个程序chronos也用到了(这个库上面没有找到有效提权的漏洞),不过最后一个express-fileupload,是不是有点像文件上传(我的第一反应,既然可以上传,那可不可以上传webshell)?
既然配置信息有这个,我们就去主文件server.js去看看:
首先也是一些个标准的请求库,基于这些库进行应用程序的开发,它设置了一个parseNested这个开关,设为true,然后调用了sjs模板以及页面文件。最后这个应用它启动在127.0.0.1这个ip,这就是为什么扫描的时候没有发现8080端口,因为它只在本机上
也就是引用了express和express-fileupload模块,于是我就搜索引擎搜索了大量的文章,
甚至去国外才发现node.js存在一个原型漏洞污染漏洞,也是在express-fileupload这个模块上,同时作者很细心给出了payload代码。
于是我在kali本地生成一个文件,同时将payload代码拷贝进去,回头让靶机来下载执行这个文件从而反弹shell:
保存好我们在kali上面开启http的80服务端口监听,在靶机上面来下载这个文件:
靶机上执行这个exp.py程序,可以在kali上面看到反弹shell,进去之后发现我们权限是个imera用户,不是root权限。
接着来查看这目标机上面文件,在一个user.txt文件看到flag(解密就不演示了),
这就是第一个flag,官方作者给出root账号下还有另外的一个flag,于是进入root文件
可是没有权限(Permission denied),于是不得不需要再次提权。当时我的头有点大,但是当我做了简单的检查之后呢,发现这次提权会相对简单很多。
我在前面说过linux提权三种方式,这次我使用sudo发现有能利用的点。
可以看到/usr/local/bin/npm和/usr/local/bin/node
在不需要密码情况下可以运行npm和node命令。
这个node可以反弹shell,在第一个靶场演示了python反弹shell操作,这次用node来做一个演示:
sudo node -e ‘child_process.spaw(“/bin/bash”, {stdio:[0,1,2]})’
(这是调用node执行生成一个子进程,进程运行的是bin/bash)
利用这串代码成功提权了
进去查看也是一个flag,(flag可以去解密在这里就不演示了)同时我们权限也是root。打靶到这里也就基本结束了。
不过我个人还是想对两个flag进行一下查看,首先对flag解密:
然后我拿到翻译网站翻译:
或许这是作者留给的一个彩蛋内容吧。到这里整个打靶过程都结束了。我在这次打靶过程中把自己的思路和心得尽量完整呈现给大家了,希望这次打靶对大家能有所收获!
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)