1. GitLab [1]

- 소프트웨어 개발 및 협업을 위한 다양한 솔루션을 제공하는 웹 기반 DevOps 플랫폼
> 깃 저장소 관리, CI/CD, 이슈 추적, 보안성 테스트 등
> GitLab CE: Community Edition / GitLab EE: Enterprise Edition

2. 취약점

2.1 CVE-2025-25291 및 CVE-2025-25292

[사진 1] CVE-2025-25291
[사진 2] CVE-2025-25292

- 오픈소스 ruby-saml 라이브러리에서 REXML과 Nokogiri가 XML을 서로 다르게 파싱하여 발생하는 인증 우회 취약점 (CVSS: 9.3) [2][3]

> ruby-saml : Ruby 언어에서 SAML (Security Assertion Markup Language) Single Sign-On(SSO)를 구현할 수 있도록 도와주는 라이브러리 [4]

> ReXML, Nokogiri : Ruby 언어에서 XML을 파싱하고 조작할 때 사용하는 라이브러리 [5][6]

> XML 파싱의 차이로 인하여 공격자는 Signature Wrapping Attack을 통해 인증을 우회할 수 있음

영향받는 버전
- ruby-saml
< 1.12.4
>= 1.13.0, < 1.18.0

- Community Edition(CE) / Enterprise Edition(EE)
> 17.7.7
> 17.8.5
> 17.9.2

 

2.1 SAML (Security Assertion Markup Language) Single Sign-On(SSO)

- SAML : 인증 정보 제공자(Identity Provider, idP)와, 서비스 제공자(Service Provider, SP) 간의 인증 및 인가 데이터를 교환하기 위한 XML 기반의 표준 데이터 포맷

- SSO : 하나의 자격 증명으로 한 번만 로그인하여 여러 앱에 액세스할 수 있도록 해 주는 기술

 

[사진 3] 동작 과정 요약 [7]

단계 설명
서비스 요청 - 사용자가 서비스에 접근
> SP는 해당 유저의 인증 유무 확인 (Access Check)
SSO 서비스 이동 - 인증되지 않은 경우 SP는 SAMLRequest를 생성해 사용자에게 전송
> SP는 IDP는 직접 연결되지 않고, 사용자의 브라우저에서 SAMLRequest를 IDP로 리다이렉션
SSO 서비스 요청 - IDP는 SAMLRequest를 파싱하고 사용자 인증을 진행
SAML 응답 - 인증 성공 시 SAMLResponse를 생성하여 사용자의 브라우저로 전송
> SAMLResponse에는 SAMLAssertion (사용자의 인증 정보를 포함한 XML 문서)이 포함
> IDP는 웹 브라우저에 Session Cokkie를 설정하고 해당 정보는 브라우저에 캐싱
SAML 응답 전송 - 사용자는 SP의 ACS로 SAMLResponse를 POST
서비스 응답 - ACS는 SAMLResponse를 검증하고 유효한 경우 요청한 서비스로 사용자를 포워딩

 

[SAMLRequest 예시]
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="req123">
  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">sp.example.com</saml:Issuer>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <Reference URI="#req123">
        <DigestValue>req_digest</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>req_signature</SignatureValue>
  </Signature>
</samlp:AuthnRequest>

[SAMLResponse 예시]
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="resp456">
  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">idp.example.com</saml:Issuer>
  <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="assert789">
    <saml:Subject>
      <saml:NameID>user123</saml:NameID>
    </saml:Subject>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
      <SignedInfo>
        <Reference URI="#assert789">
          <DigestValue>assert_digest</DigestValue>
        </Reference>
      </SignedInfo>
      <SignatureValue>assert_signature</SignatureValue>
    </Signature>
  </saml:Assertion>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <Reference URI="#resp456">
        <DigestValue>resp_digest</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>resp_signature</SignatureValue>
  </Signature>
</samlp:Response>

 

2.2 Signature Wrapping Attack

- Assertion, Signature가 여러개일 경우, 순서가 다르게 들어갈 경우 제대로 처리하지 않을 수 있기 때문에 코드를 삽입하여 Rewrite 하는 공격 [8][9]

> XML 기반 시스템에서 디지털 서명 검증의 허점을 악용하여 서명 검증 통과 (인증 우회) 및 조작된 데이터 처리를 유발하는 공격

 

- 정상적인 경우 <Assertion ID="~">에 명시된 사용자 정보(abc123)를 <Reference URI="~">에서 찾아(#abc123) 검증

> 명시된 사용자에 대한 인증 정보가 <Reference URI="~">에 저장되어 있음

> <DigestValue> (메시지에 대한 해시 값)과 <SignatureValue> (메시지에 대한 전자서명)를 검증해 인증 여부 결정

 

<SAMLResponse>
  <Assertion ID="abc123">
    <User>user1</User>
    <Role>user</Role>
  </Assertion>

  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="..." />
      <SignatureMethod Algorithm="..." />
      
      <Reference URI="#abc123">
        <Transforms>
          <Transform Algorithm="..." />
        </Transforms>
        <DigestMethod Algorithm="..." />
        <DigestValue>"..."</DigestValue>
      </Reference>
      
    </SignedInfo>

    <SignatureValue>"..."</SignatureValue>
    <KeyInfo>...</KeyInfo>
  </Signature>
</SAMLResponse>

 

- 공격자는 조작된 Assertion 삽입해 인증 과정을 우회할 수 있음

① 조작된 Assertion 삽입 : <Assertion ID="attack123">에 User=admin, Role=admin 등 권한 상승된 정보 삽입

② SAML 서버 Signature 검증 : <Reference URI="#abc123">로 서명된 정상 Assertion만 검증 -> 검증 통과

③ 첫 번째 Assertion부터 처리 : 실제 처리 단계에서는 첫 번째 요소를 읽어 인증 정보 처리 -> attack123 참조

④ 권한 상승 : 조작된 Assertion의 admin 권한으로 접근 가능

⑤ 추가 악성 행위 : 계정 생성, 데이터 탈취 등 추가 악성 행위 수행

※ 기존 서명 검증 대상과 정보를 남겨두므로 인증 과정을 우회할 수 있음

 

<SAMLResponse>
  <Assertion ID="attack123">
    <User>admin</User>
    <Role>admin</Role>
  </Assertion>

  <Assertion ID="abc123">
    <User>user1</User>
    <Role>user</Role>
  </Assertion>

  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="..." />
      <SignatureMethod Algorithm="..." />
      
      <!-- Reference: 서명 대상 지정 -->
      <Reference URI="#abc123">
        <Transforms>
          <Transform Algorithm="..." />
        </Transforms>
        <DigestMethod Algorithm="..." />
        <DigestValue>base64-encoded-digest-value</DigestValue>
      </Reference>
      
    </SignedInfo>

    <SignatureValue>base64-encoded-signature-value</SignatureValue>
    <KeyInfo>...</KeyInfo>
  </Signature>
</SAMLResponse>

 

- 여러 유형이 존재 [10]

구분 설명
XSW1 기존 서명 뒤에 서명되지 않은 내용 추가
XSW2 기존 서명 앞에 서명되지 않은 내용 추가
XSW3 기존의 Assertion 앞에 Assertion의 서명되지 않은 내용 추가
XSW4 기존의 Assertion 다음에 Assertion의 서명되지 않은 내용 추가
XSW5 서명된 Assertion의 값을 변경하고 SAML 메시지의 끝에 서명이 제거 된 원본 Assertion 추가
XSW6 서명된 Assertion의 값을 변경하고 SAML 메시지의 끝에 서명이 제거 된 변조 Assertion 추가
XSW7 서명되지 않은 Extensions Block 추가
XSW8 서명이 제거 된 원래 어설 션을 포함하는 Object Block 추가

3. 대응방안

- 벤더사 제공 보안 업데이트 적용 [11][12]

> 업데이트 적용이 불가한 경우 GitLab 권고

① GitLab 2중 인증 활성화

② GitLab에서 SAML 이중 요인 우회 옵션을 허용하지 않음

③ 자동으로 생성된 새 사용자에 대한 관리자 승인 필요 설정 : gitlab_rails['omniauth_block_auto_created_users'] = true

취약점 제품명 영향받는 버전 해결버전
CVE-2025-25291
CVE-2025-25292
Community Edition(CE)
Enterprise Edition(EE)
< 17.7.7 17.7.7
< 17.8.5 17.8.5
< 17.9.2 17.9.2
ruby-saml < 1.12.4 1.12.4
>= 1.13.0, < 1.18.0 1.18.0

 

- Signature Wrapping 대응 방안

> Reference URI로 검증한 Assertion만 실제 처리에 사용

> Assertion 요소는 반드시 1개만 존재하도록 스키마 정의

> 최신 보안 라이브러리 사용

> 모의 침투 테스트 (ZAP, Burpsuite 등) [13][14][15]

4. 참고

[1] https://about.gitlab.com/
[2] https://nvd.nist.gov/vuln/detail/CVE-2025-25291
[3] https://nvd.nist.gov/vuln/detail/CVE-2025-25292
[4] https://github.com/SAML-Toolkits/ruby-saml
[5] https://github.com/ruby/rexml
[6] https://github.com/sparklemotion/nokogiri
[7] https://gruuuuu.github.io/security/ssofriends/
[8] https://www.hahwul.com/2018/07/13/Security-testing-SAML-SSO-vulnerability-and-pentest/#signature-wrappingxsw-attack
[9] https://www.hahwul.com/cullinan/saml-injection/#signature-stripping
[10] https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SAML%20Injection#xml-signature-wrapping-attacks
[11] https://www.boho.or.kr/kr/bbs/view.do?bbsId=B0000133&pageIndex=1&nttId=71680&menuNo=205020
[12] https://about.gitlab.com/releases/2025/03/12/patch-release-gitlab-17-9-2-released/
[13] https://www.hahwul.com/cullinan/saml-injection/#saml-in-zapburp
[14] https://www.zaproxy.org/docs/desktop/addons/saml-support/
[15] https://github.com/CompassSecurity/SAMLRaider

+ Recent posts