← 목록
기타 2026-07-25 9KB 읽기 9분

크라우니클라우드(cloud:9611) 데이터 위생 + 파일명 인젝션 재스캔 (P1-⑥)

개요

/Users/ef/crowny-services/data/ 전수 조사 → 명백한 정크(SQLi 페이로드 파일명·guardtest/test-verify/출시검증/probe 오너)만 _격리_2026-07-25/로 이동(rm 아님, 가역). 이어서 서비스서버.한선 코드 감사로 파일명 생성경로 인젝션 지점 전수 재스캔.

아카이브 결과 (이동, 삭제 아님)

/Users/ef/crowny-services/data/_격리_2026-07-25/ 하위 원 구조 보존:
  • store: 20개 오너 디렉토리 (0123456789abcdef, abc12345, adv-verify-9999, anon_butler_probe_1782093063, anon_reg12345, anon_test1234, anon_testuser, ascii-owner-9999, audit2162c2f5, guardtest-30000-9999, safeowner12345, sztest-30000/60000/65000/70000/100000-9999, test-verify-001, user_test_01, 출시검증-9999, 출시검증-1783387186)
  • anchor: anon_blobtest1234, anon_testuser
  • blobs: audit2162c2f5, q연동테스트, q연동테스트GW, anon_blobtest1234, safeblob123, q연동1mb, q연동검증, 출시검증-9999(URL인코딩) — 8개
  • merge: shadow-validator(전체), anon_mrvzk33zh4tcli0kayzNDkVNU5(전체, 오너명 자체가 fuzz 변종), anon_mrvzk33zh4tcli0kay 안의 SQLi 페이로드 파일명 17개(정상 키 cloud_items_v1.json은 보존)
총 3.5MB, 파일 54개(디렉토리 27개 오너분).

보류/제외 목록 (애매 — 건드리지 않음)

  • store/anon_butler_cowork_c07bvyaz4m8udw4p — 내용이 실제 코워크집사 가동 알림(시스템 생성 실데이터로 판단)
  • store/u_kpsmemo77777, store/u_memotest_kps01 — "test"가 이름에 있으나 내용이 실제 메모(회의록·장보기 목록)로 실사용 정황. 이름만으로 정크 단정 위험 → 제외
  • anchor/anon_mrvzk33zh4tcli0kay/cloud.jsonl — 해시체인(prev/anchor 연쇄) 내부에 SQLi 문자열이 content 값으로 잔존(36개 seq 중 다수). 체인 무결성 특성상 중간 항목만 골라 삭제/이동 불가(재계산 없이는 체인 파손) → 이동 보류, 별도 정리 필요 시 재계산 전제 작업으로 분리 권고

라이브 무영향 실측

$ curl -s http://127.0.0.1:9611/api/health
{"status":"ok","service":"cloud","domain":"cloud.crowny.org","port":9611,"engine":"hanseon"}  HTTP 200

$ curl -s -H "X-Crowny-Owner: u_821313aa87df9ce...cb4f" http://127.0.0.1:9611/api/store
→ 200, 실사용자(kps) cloud_items_v1/crowny-convs/crowny-theme 전체 정상 반환

$ curl -s -H "X-Crowny-Owner: test-verify-001" http://127.0.0.1:9611/api/store
→ 200, {} (아카이브된 오너 → 서버가 정직하게 빈 상태 반환, 에러/크래시 없음)

파일명 생성경로 인젝션 재스캔 (서비스서버.한선 코드 감사)

엔드포인트지점(줄)사용자 입력경로/셸 결합방어위험도
/api/store486-518소유자(헤더)루트+"/data/store/"+소유자, mkdir/mv 체계()소유자유효() 화이트리스트(영숫자_-, 8~100자)방어됨
/api/anchor535-631소유자(헤더), 콘텐츠(body content 필드)루트+"/data/anchor/"+소유자+"/"+서비스명.jsonl소유자=화이트리스트 방어. 콘텐츠는 길이(16~128)만 검증, 문자셋(hex) 미검증 → JSONL 내 " 포함 시 로그 구조 파손 가능(파일경로엔 안 쓰임, 셸엔 미결합이라 RCE 아님, 데이터무결성 리스크)LOW(데이터 정합성만)
/api/merge642-689키(body JSON "key" 필드 / GET 쿼리 "key")머지디렉+"/"+키+".json", POST는 체계("mv -f \""+tmp+"\" \""+머지파일+"\"")로 셸 결합없음 — 화이트리스트 전무CRITICAL
/api/quota700-716없음(소유자만, 화이트리스트됨)블롭디렉 du -sb소유자=화이트리스트방어됨
/api/access731소유자만접근파일 경로(셸 미사용, VM 읽기만)소유자=화이트리스트방어됨
/api/share909,949,995토큰(SHA256 앞24자, 서버생성)share파일 경로, 체계("rm -f ...")토큰유효() 화이트리스트(2026-07-25 심층방어 완료, P0-②)방어됨
/api/blob/upload/<owner>605-613owner(URL)blob디렉/blob경로, mkdir 체계()blob소유자안전() 화이트리스트(2026-07-09 수정)방어됨
GET /api/blob/<owner>/<sha256> (Range)블롭스트림.한선:657-675, 291-293sha256(URL 경로 세그먼트)blob경로()체계("wc -c "+경로+" 2>/dev/null | awk ...")경로가 따옴표조차 없이 직접 셸 문자열에 이어붙음길이만 검증(==64), 문자셋(hex) 미검증. owner는 화이트리스트 있지만 sha256엔 없음CRITICAL(가장 심각 — 인증 불필요 GET 경로, 따옴표 방어도 없음)

CRITICAL ① — /api/merge 키 무방어 셸 인젝션 (서비스서버.한선:672-683)

  • 키 = JSON필드(바디, "key") — 길이 0 체크만 있고 화이트리스트 없음.
  • POST 경로: 체계("mv -f \""+tmp+"\" \""+머지파일+"\"") — 머지파일에 키가 그대로 포함, 이중따옴표로만 감쌈.
  • 익스플로잇(코드상 경로, 실공격 미수행): 키 = 'x$(touch /tmp/pwned)' 또는 에 리터럴 " 포함 시 이중따옴표 탈출 → 임의 명령 실행. $(...) 는 이중따옴표 안에서도 셸이 그대로 치환하므로 따옴표 탈출 없이도 가능.
  • GET 경로는 셸엔 안 가지만 ../ 경로traversal로 임의 파일 존재확인/읽기(파일존재/읽기, VM 빌트인) 가능 — 소유자 스코프 밖 파일 접근.
  • 실제로 data/merge/anon_mrvzk33zh4tcli0kay/에서 발견된 SQL인젝션 스캐너 페이로드들이 바로 이 무방어 파라미터를 통해 파일명으로 남은 흔적(단, 페이로드가 SQL 지향이라 셸 이스케이프 문자는 안 씀 — 실제 RCE 트리거는 안 됐으나 벡터는 100% 개방).
  • 수정 제안(P0-②와 동형): merge처리() 시작부에 머지키유효(키) 신설 — 영숫자/_/-/.(필요시) 화이트리스트, 길이 상한(예 1~128자), .. 시퀀스 명시 차단. 실패 시 400. share/blob과 동일 패턴 재사용.

CRITICAL ② — GET Range 블롭 다운로드, sha256 미검증 셸 인젝션 (블롭스트림.한선:660-665, 291-293)

  • sha256은 URL 경로에서 슬래시 분리 후 길이(==64)만 검증, hex 문자셋 검증 없음.
  • blob_range()체계("wc -c " + 경로 + " 2>/dev/null | awk '{print $1}'") 호출 — 경로가 따옴표 없이 바로 이어붙음(merge의 이중따옴표보다도 방어가 약함).
  • 인증 불필요: GET 다운로드는 owner 화이트리스트만 거치고(그것도 owner 세그먼트에만 적용), sha256엔 아무 검증이 없으며 Range 헤더만 붙이면 트리거됨. 즉 누구나 임의 GET 요청 하나로 도달 가능한 최우선순위 취약점.
  • 익스플로잇 스케치(코드상 경로만, 실공격 미수행): GET /api/blob/<유효owner>/<64자 세그먼트: '$(touch$IFS/tmp/pwned)' 패딩> HTTP/1.1 + Range: bytes=0-1 헤더 → wc -c 셸 문자열에 그대로 삽입되어 명령 치환 실행.
  • 수정 제안: blob_range()/다운로드 진입부에 sha256 hex 화이트리스트([0-9a-f]{64}) 검사 추가(이미 owner에 쓰는 blob소유자안전() 패턴을 hex 전용으로 하나 더 만들면 됨) + 체계() 호출부 경로를 최소한 이중따옴표로 감싸기(따옴표만으로는 $() 방어 안 되므로 화이트리스트가 필수, 따옴표는 보조).

관련 파일

  • /Users/ef/crowny-services/서비스서버.한선 (642-689 merge처리, 899-1005 share처리 — 정상 패턴 예시)
  • /Users/ef/crowny-services/블롭스트림.한선 (272-300 blob_range, 570-687 라우팅/검증)
  • /Users/ef/crowny-services/data/_격리_2026-07-25/ (아카이브 본체)
  • 라이브 프로세스: crownyc run /Users/ef/crowny-services/서비스서버.toau (다수 워커) — 서비스서버.한선에서 컴파일된 바이너리, 이번 조사 시점 기준 라이브

잔여 이슈

  1. merge 키 화이트리스트 미수정 — 발견만 하고 코드 수정은 지시에 따라 안 함(수정은 하지 말라는 지시). 실제 패치는 별도 작업으로 승인 필요.
  2. blob sha256 hex 화이트리스트 미수정 — 동일하게 발견만.
  3. anchor content 필드 hex 미검증(LOW) — 우선순위 낮음, 참고만.
  4. anon_mrvzk33zh4tcli0kay의 anchor 해시체인 내부 SQLi 문자열 오염은 이동 보류(체인 재계산 없이는 안전하게 정리 불가) — 후속 작업으로 분리 필요.
  5. u_kpsmemo77777/u_memotest_kps01/anon_butler_cowork_c07bvyaz4m8udw4p는 이름은 테스트스럽지만 내용이 실사용 정황이라 아카이브에서 제외 — 오너 본인(KPS) 확인 후 필요시 별도 정리.