Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1134930
  • 博文数量: 414
  • 博客积分: 10030
  • 博客等级: 上将
  • 技术积分: 4440
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-05 21:42
文章分类

全部博文(414)

文章存档

2011年(1)

2009年(1)

2008年(412)

我的朋友

分类: 网络与安全

2008-10-11 12:15:07

一个评价入侵检测系统漏洞攻击检测覆盖面的指标


创建时间:2006-08-20
文章属性:原创
文章提交:stardust (stardust_at_xfocus.org)

对入侵检测防护产品的评测中,我们经常需要对它们的漏洞攻击检测能力做出评价,其中涉及漏洞的覆盖面即是能力的一方面,那么如何去评价?以什么指标去衡量才能得到相对客观公平且有说服力的结果呢?这个文章中我们来讨论一下这个问题,在此提出一个可操作的量化指标。


1. 指标的设计

1.1 CVE漏洞条目数量指标

最 简单的方案是显而易见的,通过统计IDS/IPS所能检测的利用漏洞攻击种数来进行比较。目前多数主流的IDS/IPS产品都提供了CVE名的支持,每个 CVE名对应一个独立的安全漏洞,虽然CVE名字表不可能包含所有的已知安全漏洞,但至少包括了其中的大多数重要条目。因此通过统计产品相关的CVE条目 数量可以大致了解IDS/IPS的漏洞攻击检测覆盖面。我们最原始的评价指标可以是产品相关的CVE漏洞条目个数。


1.2 CVSS漏洞威胁评分修正

上 面的漏洞数量指标存在一个问题,因为它假设了每个漏洞有相同的威胁级别,而事实情况并非如此,因此我们在评价过程中必须考虑漏洞本身的威胁等级。感谢 CVSS漏洞威胁评分项目的工作成果,它为每个CVE漏洞条目按威胁程度的高低打了分,最高威胁级别的漏洞为10分,从NVD的网站上可以轻易地获取漏洞 基本威胁评分的数据。由此,我们的指标可以修正为产品涉及到的CVE漏洞条目的CVSS评分的总和。


1.3 时间因素上的修正

考 虑了漏洞威胁级别的高低,无疑使我们的指标更具准确性和可比较性,但上面的指标还是有可以改进的地方。在这里我们需要引入时间因素,因为当漏洞被披露以 后,随着时间的推移,由于软件新版本的更新,有意或无意的漏洞修补,存在漏洞的系统越来越少,相对来说漏洞的威胁呈现一个越来越小的趋势,也就是说,同样 CVSS威胁基本评分为8的2000年与2006年的漏洞在2006年评价时现实的威胁程度是很不一样的。其实,CVSS漏洞威胁评分系统的设计考虑了威 胁评分随时间及布署状况的修正,一个漏洞的CVSS威胁评分涉及三个层次:基本评分、生命周期因素修正、环境因素修正。基本评分是根据漏洞本身固有特性所 可能造成的影响评价得到的分值,生命周期因素修正就是基于时间进程的修正,环境因素即是基于布署情况的修正。NVD提供了CVE条目的基本评分,环境因素 取决于组织受漏洞影响产品布署状况,生命周期因素修正需要跟踪每个漏洞的补丁发布情况,工作量巨大,一个单独的组织是无法完成的,因此NVD也未给出相应 的数据。

对于我们的评价指标,我们简单地采用一个极粗糙的威胁随年数增加线性递减的算法:

漏洞的当前威胁评分 = CVSS基本评分* (8-(2006-漏洞发布的年))/8

这样一个线性算法与事实情况并不一致,事实情况是漏洞在公布的一两年内威胁程度迅速下降,之后几年内的下降则非常的小,所以,基本上线性递减只是一个聊胜于无的计算方法,考虑到每个漏洞的情况并不那么一致而且指标只用于作相对的比较,这样的算法也是可接受的。

到此评价指标修正为所有CVE相关的漏洞当前威胁评分的总和。


2. 如何操作及几个常见产品的指标分析

2.1 获取每个CVE条目对应的CVSS评分

从 NVD网站下载CVE评分数据文件,文件为XML格式,每年一个单独的文件,它包含了每个CVE条目的详细信息,使用所附的 extract-cve-score.pl 脚本将其中CVE名和相应的CVSS评分提取出来,把打印出来的数据重定向的文件中,并将多年的数据整合到一个文件中,这个即是我们以后会使用到的CVE 名和对应CVSS评分的对照表。


2.2 获取评测产品的涉及到的CVE条目信息

以几个能从公开渠道获取信息的IDS产品为例:

Snort
-----
Snort的规则信息索引文件(sid-msg.map)中每个与CVE漏洞相关的检测都列出了相应的CVE名,我们只要使用类似 extract-snort-cve.pl 的简单脚本将其提取出来即可。

RealSecure 7
------------
RealSecure 7的每个检测模块升级包文件中包含了一个名为 issues.csv 的索引文件,文件中并不直接包含每个检测条目对应的CVE名信息,但包含了对应于ISS网站上详细说明信息的ID号,在详细说明中包含有CVE名。处理这 种情况稍稍复杂一些,我们必须把检测条目相关的详细信息从网站上下载回来,这可以通过 get-iss-content.pl 脚本实现,它读取 issues.csv 文件中的检测条目ID号从ISS的网站下载每个条目的详细信息,每个条目一个文件,然后用 extract-iss-cve.pl 脚本提取检测条目涉及到的CVE名。

IDP
---
IDP的规则文件是可公开下载的,也未做加密,规则文件中包含了涉及到CVE名信息,与处理Snort规则索引文件类型,使用类似 extract-idp-cve.pl 的脚本将其提取出来。

对于其他产品一般通过分析其检测条目详细信息说明文档,都应该是可以得到相关的CVE条目信息的。


2.3 计算漏洞覆盖面的评分指标

有了CVE名到相应CVSS评分的对应表和产品涉及到的CVE名,使用 caculate-score.pl 脚本即可得到评分。


上述几个产品的分析结果比较:

                CVE条目数 总威胁得分 CVE条目平均CVSS评分 时间因素修正后的总威胁得分
RealSecure 7    979       6000.7     6.1                 2694.3
Snort           550       3454.3     6.3                 1476.9
IDP             311       1947.3     6.3                 796.6

由以上的数据,产品相关漏洞覆盖面的高下就很明显了。


3. 结论

事实上,由于威胁得分的计算是面向漏洞的,因此所有以漏洞处理为核心的安全产品比如漏洞数据库、安全评估、入侵检测类产品都,可以用计算“时间因素修正后的总威胁得分”指标的方法来评价。


附,评分计算相关的脚本工具:

extract-cve-score.pl
--------------------------------- 8< --------------------------------------
#!/usr/bin/perl

my $data = "";
my @cve_names = ("");
my @cve_scores = ("");
my $cve_name = "";

$data = readDBcontent($ARGV[0]);
$data =~ s/
@cve_names = $data =~ m|@cve_scores = $data =~ m|
for (my $i=0;$i<=$#cve_names;$i++) {
    print $cve_names[$i]."\t".$cve_scores[$i]."\n";
}

sub readDBcontent {
        my ($table) = @_;
        my $dbcon = "";

        open(TBL,"<$table")||die($table);
        while () {
            $dbcon .= $_ ;
        }
        close(TBL);

        return ($dbcon);
}
--------------------------------- 8< --------------------------------------

extract-snort-cve.pl
--------------------------------- 8< --------------------------------------
#!/usr/bin/perl
#
my @issues = ("");

readDBcontent($ARGV[0],\@issues);

for (my $i=0;$i<@issues;$i++) {
    my $issuetext = $issues[$i];

    if ($issuetext =~ m/\|\| cve,(\d{4}-\d{4}) /) {
        print "CVE-".$1."\n";
    }
}

sub readDBcontent {
        my ($table,$dbcon)=@_;
        my $count=0;

        open(TBL,"<$table")||die($table);
        @{$dbcon}=;
        close(TBL);

        for(my $i=0;$i<@{$dbcon};$i++) {
                chomp(${$dbcon}[$i]);
                if(${$dbcon}[$i] ne "") { $count++; }
        }

        return ($count);
}
--------------------------------- 8< --------------------------------------

get-iss-content.pl
--------------------------------- 8< --------------------------------------
#!/usr/bin/perl
#
my $flag = 0;
my $program = "lynx -source ";
my $url_b = "
my @issues = ("");

$|++;

readDBcontent($ARGV[0],\@issues);

for (my $i=0;$i<@issues;$i++) {
    my $issuetext = $issues[$i];
    my ($aa,$bb,$cc,$vul_id) = split (',',$issuetext);


    if ($vul_id =~ m/^\d+/) {

        my $iss_vuln = "$vul_id.txt";
        # print $iss_vuln."\n";
        if (!(-e $iss_vuln) || (-z $iss_vuln)) {
            my $content = "";
            $url = $url_b."${vul_id}";

            $content = getSection();
            open (DATAFILE,">$iss_vuln") or die ("$iss_vuln\n");
            print DATAFILE $content;
            close (DATAFILE);
        }
    }
}

sub getSection {
    my @page;
    my $section_con = "";
    my $last = 0;

    getPage("$url",\@page);

    $section=uc("$section");
    for ($i=0;$i<@page;$i++) {
        if ($page[$i] =~ m/^

The information within this database may change without notice/) {$flag = 0};
        if ($flag) {
            $page[$i] = removeHtmltag ("$page[$i]");
                        if($page[$i] eq "") {

                                if(!$last) { $section_con .= "\n"; $last = 1;}
                        } else {
                                $section_con .= "$page[$i]\n";
                                $last = 0;
            }
        }
        if ($page[$i] =~ m/X-Force Database Results/) {$flag = 1};
    }
    
    return $section_con;
}


sub getPage {
    my ($url_section,$page_con) = @_;

        open (EXECFILE, "$program '$url_section' |");
        @{$page_con} = ;
        close (EXECFILE);
}

sub removeHtmltag {
    my ($string)=@_;

    $string =~ s/\t//g;
    $string =~ s/\n//g;
    $string =~ s/ / /g;
    $string =~ s/"/"/g;
    $string =~ s/

/\n/g;
    $string =~ s/
/\n/g;
    $string =~ s/
/\n/g;
    $string =~ s/

/\n/g;
    $string =~ s/

/\n/g;
    $string =~ s/<\/P>/\n/g;
    $string =~ s/<\/p>/\n/g;
    $string =~ s/

  • /---/g;
        $string =~ s/
  • /---/g;
        $string =~ s/—/-/g;
        $string =~ s/<\/OPTION>/\n/g;
        $string =~ s/<[^<]*>//g;
        $string =~ s/</    $string =~ s/>/>/g;
        $string =~ s/&/&/g;
        $string =~ s/"/"/g;
        $string =~ s/\015//g;
        $string =~ s/^\s*\n*//;
    #    $string =~ s/\s*\n*$//;

        return $string;
    }    

    sub readDBcontent {
            my ($table,$dbcon)=@_;
            my $count=0;

            open(TBL,"<$table")||die($table);
            @{$dbcon}=;
            close(TBL);

            for(my $i=0;$i<@{$dbcon};$i++) {
                    chomp(${$dbcon}[$i]);
                    if(${$dbcon}[$i] ne "") { $count++; }
            }

            return ($count);
    }
    --------------------------------- 8< --------------------------------------

    extract-iss-cve.pl
    --------------------------------- 8< --------------------------------------
    #!/usr/bin/perl
    #
    my @issues = ("");

    readDBcontent($ARGV[0],\@issues);

    for (my $i=0;$i<@issues;$i++) {
        my $issuetext = $issues[$i];
        my ($aa,$bb,$cc,$vul_id) = split (',',$issuetext);

        if ($vul_id =~ m/^\d+/) {

            my $iss_vuln = "$vul_id.txt";

            if ((-e $iss_vuln) && !(-z $iss_vuln)) {
                my @contents = ("");

                readDBcontent($iss_vuln,\@contents);
                for (my $j=0;$j<@contents;$j++) {
                    if ($contents[$j] =~ m/^---(CVE-\d{4}-\d{4})/) {
                        print $1."\n";
                    }
                }
            }
        }
    }

    sub readDBcontent {
            my ($table,$dbcon)=@_;
            my $count=0;

            open(TBL,"<$table")||die($table);
            @{$dbcon}=;
            close(TBL);

            for(my $i=0;$i<@{$dbcon};$i++) {
                    chomp(${$dbcon}[$i]);
                    if(${$dbcon}[$i] ne "") { $count++; }
            }

            return ($count);
    }
    --------------------------------- 8< --------------------------------------

    extract-idp-cve.pl
    --------------------------------- 8< --------------------------------------
    #!/usr/bin/perl
    #
    my @issues = ("");

    readDBcontent($ARGV[0],\@issues);

    for (my $i=0;$i<@issues;$i++) {
        my $issuetext = $issues[$i];

        if ($issuetext =~ m/:cve \((CVE-\d{4}-\d{4})\)/) {
            print $1."\n";
        }
    }

    sub readDBcontent {
            my ($table,$dbcon)=@_;
            my $count=0;

            open(TBL,"<$table")||die($table);
            @{$dbcon}=;
            close(TBL);

            for(my $i=0;$i<@{$dbcon};$i++) {
                    chomp(${$dbcon}[$i]);
                    if(${$dbcon}[$i] ne "") { $count++; }
            }

            return ($count);
    }
    --------------------------------- 8< --------------------------------------

    caculate-score.pl
    --------------------------------- 8< --------------------------------------
    #!/usr/bin/perl

    if(scalar(@ARGV) < 2){
    print "Usage: $0 CVES-LIST-FILE CVE-SCORE-PAIR-LIST-FILE\n";
    exit 1;
    }

    my %cve_name_score = ();

    my @score_data = ("");
    readDBcontent($ARGV[1],\@score_data);

    my $cur_name = "";
    my $cur_score = 0.0;
    foreach (@score_data) {
        $_ =~ m/(.+)\t(.+)/;
        $cur_name = $1;
        $cur_score = $2;
        $cve_name_score{$cur_name} = $cur_score;
    }

    my @cves = ("");
    readDBcontent($ARGV[0],\@cves);

    my $score = 0.0;
    my $score1 = 0.0;
    my $cve_count = 0;
    my $year = 0;
    my $score_modified = 0;
    foreach (@cves) {
        if ($_ ne "") {
            if (defined($cve_name_score{$_})) {
                $score += $cve_name_score{$_};
                $cve_count++;
                $_ =~ m/(\d\d\d\d)-\d\d\d\d/;
                $year = $1;
                $score_modified = $cve_name_score{$_} * ((8-(2006-$year))/8);
                $score1 += $score_modified;
            }
        }
    }

    my $average = $score/$cve_count;

    printf "%d\t%.1f\t%.1f\t%.1f", $cve_count,$score,$average,$score1;

    sub readDBcontent {
            my ($table,$dbcon)= @_;
            my $count= 0;

            open(TBL,"<$table")||die($table);
            @{$dbcon}=;
            close(TBL);

            for(my $i=0;$i<@{$dbcon};$i++) {
                    chomp(${$dbcon}[$i]);
                    if(${$dbcon}[$i] ne "") { $count++; }
            }

            return ($count);
    }
    --------------------------------- 8< --------------------------------------


    资源链接:

    通用弱点评价体系(CVSS)简介
    http://www.xfocus.net/releases/200602/a850.html

    NVD/CVE XML Data Files


    CVSS Draft


    RealSecure Network Sensor XPUs


    Snort Rules


    IDP Rule
  • 阅读(556) | 评论(0) | 转发(0) |
    给主人留下些什么吧!~~