OpenSSL命令注入漏洞 (CVE-2022-1292)

文章详细介绍了OpenSSL的c_rehash工具中的命令注入漏洞,该漏洞允许攻击者在未授权情况下执行系统命令。漏洞源于c_rehash脚本对输入的外部数据过滤不足,导致可以执行任意命令。文章提到了受影响的OpenSSL版本,并分析了源码中的问题点,以及提供了漏洞修复方案,包括升级到安全的OpenSSL版本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      openssl 是目前最流行的 SSL 密码库工具,其提供了一个通用、健壮、功能完备的工具套件.

浅浅了解一下c_rehash 命令:

   1.  c_rehash是openssl中的一个用perl编写的脚本工具,c_rehash 为文件创建一个符号连接,并将此符号连接的名称设为文件的hash值,作用是让openssl在证书目录中能够找到证书,批量创建证书等文件 。

      语法:c_rehash [-old] [-h] [-n] [-v] [ directory... ]

       -old:使用1.0.0版本之前的老式hash(MD5,而不是SHA-1)去生成连接。
       -h:显示一个简短的使用信息。
       -n:不要移除已经存在的连接。当要同时保留新的和老式的连接时需要此选项。
       -v:打印移除的老式连接和新创建的连接的信息。默认c_rehash只会列出被处理目录的信息。

  2.  如果命令行指定了目录名,则依次处理它们。

        如果命令行中没有指定目录名,那么会去询问SSL_CERT_DIR环境变量

       (SSL_CERT_DIR环境变量:以冒号作为分隔,存放目录列表。)

        如果环境变量中未指定目录,则默认的目录由安装时的信息指定。

        通常是:/usr/local/ssl/certs。

 

 回归正题:

Openssl命令注入漏洞形成的原因:

      该漏洞由于c_rehash脚本未对外部可控数据进行有效过滤。

危害:

      该漏洞在未授权的情况下,导致可操作/etc/ssl/certs/的攻击者,以脚本的权限执行任意命令,从而执行系统命令,导致远程代码执行。

影响版本:

            OpenSSL 1.0.2

            OpenSSL 1.1.1

            OpenSSL 3.x

漏洞分析:

openssl/tools at master · openssl/openssl · GitHub //c_rehash源码

大致能看懂,源码解释来自CVE-2022-1292的分析_黑客技术

一部分源码:

# 将命令行传入的参数赋值给dirlist
if (@ARGV) {
    @dirlist = @ARGV;
} elsif ($ENV{SSL_CERT_DIR}) {
    @dirlist = split /$path_delim/, $ENV{SSL_CERT_DIR};
} else {
    $dirlist[0] = "$dir/certs";
}

# 判断$dirlist[0]目录是否存在, 并把工作目录修改为$dirlist[0]
# 检查是否存在$openssl是否存在 
if (-d $dirlist[0]) {
    chdir $dirlist[0];
    $openssl="$pwd/$openssl" if (!-x $openssl);
    chdir $pwd;
}

# 检查$dirlist中的每一项是否存在且可写, 均满足则调用hash_dir函数
foreach (@dirlist) {
    if (-d $_ ) {
            if ( -w $_) {
        hash_dir($_);
            } else {
                print "Skipping $_, can't write\n";
                $errorcount++;
            }
    }
}
exit($errorcount);

接下来进入hash_dir函数, 也就是存在问题的函数

sub hash_dir {
    my %hashlist;
    print "Doing $_[0]\n";
    chdir $_[0];
    opendir(DIR, ".");
    # 问题出在这里, 将改目录所有文件名读入到flist数组, 但没有处理, 导致文件名命令注入的可能
    my @flist = sort readdir(DIR);
    closedir DIR;
    if ( $removelinks ) {
        # Delete any existing symbolic links
        foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) {
            if (-l $_) {
                print "unlink $_" if $verbose;
                unlink $_ || warn "Can't unlink $_, $!\n";
            }
        }
    }
    # 这里也不是很严格, 仅仅需要文件名含有所定义的关键字即可
    FILE: foreach $fname (grep {/\.(pem)|(crt)|(cer)|(crl)$/} @flist) {
        # Check to see if certificates and/or CRLs present.
        my ($cert, $crl) = check_file($fname);
        if (!$cert && !$crl) {
            print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n";
            next;
        }
        link_hash_cert($fname) if ($cert);
        link_hash_crl($fname) if ($crl);
    }
}

#使用perl -d c_rehash "."调试一下, perl自带的调式工具。

#可以看到$flist[5]文件名中存在"`"特殊字符

#导致没有过滤反引号就直接将文件名拼接到了命令中,那么我们在文件名中添加反引号即可执行任意命令。

#由于文件名检测, 只要求文件名含有(pem)|(crt)|(cer)|(crl)字符即可, 所以恶意文件名通过检测, 进入check_file函数

sub check_file {
    my ($is_cert, $is_crl) = (0,0);
    my $fname = $_[0];
    open IN, $fname;
    while(<IN>) {
        if (/^-----BEGIN (.*)-----/) {
            my $hdr = $1;
            if ($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) {
                $is_cert = 1;
                last if ($is_crl);
            } elsif ($hdr eq "X509 CRL") {
                $is_crl = 1;
                last if ($is_cert);
            }
        }
    }
    close IN;
    return ($is_cert, $is_crl);
}

主要检查文件头格式是否满足要求, 这样是为什么最开始制作恶意文件需要带上-----BEGIN CERTIFICATE-----

检查通过到link_hash_cert函数也就是注入发生的函数

sub link_hash_cert {
        my $fname = $_[0];
        # 这里对于传过来的参数也没有检查, 并且把$fname直接用``包裹, 直接执行命令, 导致$fname中的命令也可以执行
        $fname =~ s/\"/\\\"/g;
        my ($hash, $fprint) = `"$openssl" x509 $x509hash -fingerprint -noout -in "$fname"`;
...

 

漏洞修复:

OpenSSL 1.0.2 升级至 1.0.2ze (仅针对高级用户);

OpenSSL 1.1.1 升级至 1.1.1o;

OpenSSL 3.0 升级至 3.0.3;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值