Дешифровать билет на Kerberos с помощью Spnego
-
12-10-2019 - |
Вопрос
Я использую Spnego ( http://spnego.sourceforge.net ) для аутентификации Kerberos при JBoss.
Мне нужно расшифровать билет Kerberos, чтобы получить доступ к Data-Data, которая будет Containt PAC данных. Данные PAC необходимы, чтобы решить, какие роли должны быть предоставлены пользователю.
Как получить доступ и расшифровать билет Kerberos? Я искал сеть для примеров, но без усилий.
Решение
У этих ребят полная реализация PAC декодирование:
http://jaaslounge.sourceforge.net/
Вы можете использовать анализатор токена, как это:
HttpServletRequest request = (HttpServletRequest) req;
String header = request.getHeader("Authorization");
byte[] base64Token = header.substring(10).getBytes("UTF-8");
byte[] spnegoHeader = Base64.decode(base64Token);
SpnegoInitToken spnegoToken = new SpnegoInitToken(spnegoHeader);
Вам нужно будет прыгнуть, хотя вы хотите дешифровать базовый билет Kerberos. Не уверен, если вам это нужно.
Грант
Другие советы
Я успешно использовал фильтр сервлета из http://spnego.sourceforge.net в сочетании с анализатором PAC из http://jaaslounge.sourceforge.net/ Без необходимости делать что -то явно с Der/Asn.1 Parsers:
/**
* Retrieve LogonInfo (for example, Group SID) from the PAC Authorization Data
* from a Kerberos Ticket that was issued by Active Directory.
*/
byte[] kerberosTokenData = gssapiData;
try {
SpnegoToken token = SpnegoToken.parse(gssapiData);
kerberosTokenData = token.getMechanismToken();
} catch (DecodingException dex) {
// Chromium bug: sends a Kerberos response instead of an spnego response
// with a Kerberos mechanism
} catch (Exception ex) {
log.error("", ex);
}
try {
Object[] keyObjs = IteratorUtils.toArray(loginContext.getSubject()
.getPrivateCredentials(KerberosKey.class).iterator());
KerberosKey[] keys = new KerberosKey[keyObjs.length];
System.arraycopy(keyObjs, 0, keys, 0, keyObjs.length);
KerberosToken token = new KerberosToken(kerberosTokenData, keys);
log.info("Authorizations: ");
for (KerberosAuthData authData : token.getTicket().getEncData()
.getUserAuthorizations()) {
if (authData instanceof KerberosPacAuthData) {
PacSid[] groupSIDs = ((KerberosPacAuthData) authData)
.getPac().getLogonInfo().getGroupSids();
log.info("GroupSids: " + Arrays.toString(groupSIDs));
response.getWriter().println("Found group SIDs: " +
Arrays.toString(groupSIDs));
} else {
log.info("AuthData without PAC: " + authData.toString());
}
}
} catch (Exception ex) {
log.error("", ex);
}
Я также написал новый httpfilter (раздвоенный от spnego.sf.net): spnego-pac, который раскрывает Logoninfo через getuserprincipal ().
Пример проекта, демонстрирующего приведенный выше код в полном объеме, можно найти здесь:
https://github.com/eleotlecram/jetty-pnego-demo
Фильтр spnego-pac (используемый в приведенном выше примере) можно найти здесь:
https://github.com/eleotlecram/spnego.sf.net-fork
Надеюсь, это полезно для всех.
__
Марсель
Если вы получите токен механизма от spnegoToken
как это:
byte[] mechanismToken = spnegoToken.getMechanismToken();
Токен механизма обычно является KerberosApRequest
. Анкет Eсть KerberosToken
конструктор, который берет KerberosApRequest
. Анкет Просто пройдите в mechanismToken
байт массив вместе с ключом, чтобы расшифровать содержимое.
Я даю свое собственное решение проблемы:
Я основал свое решение на библиотеке Bouncycastle (для разбора в частях токена) и jaaslounge (для расшифровки зашифрованной части токена). К сожалению, код декодирования всего токена Spnego от jaaslounge не удалось для моих требований. Я должен был написать это сам.
Я декодировал часть билета по части, сначала построив дерубекты из байта [] массива:
private DERObject[] readDERObjects(byte[] bytes) throws IOException {
ASN1InputStream stream = new ASN1InputStream(new ByteArrayInputStream(
bytes));
List<DERObject> objects = new ArrayList<DERObject>();
DERObject curObj;
while ((curObj = stream.readObject()) != null) {
objects.add(untag(curObj));
}
return objects.toArray(new DERObject[0]);
}
Untag () - моя вспомогательная функция, чтобы удалить упаковку dertaggedObject
private DERObject untag(DERObject src) {
if (src instanceof DERTaggedObject) {
return ((DERTaggedObject) src).getObject();
}
return src;
}
Для извлечения последовательности Derobject из данного DeRobject Я написал еще одну вспомогательную функцию:
private DERObject[] readDERObjects(DERObject container) throws IOException {
// do operation varying from the type of container
if (container instanceof DERSequence) {
// decode using enumerator
List<DERObject> objects = new ArrayList<DERObject>();
DERSequence seq = (DERSequence) container;
Enumeration enumer = seq.getObjects();
while (enumer.hasMoreElements()) {
DERObject curObj = (DERObject) enumer.nextElement();
objects.add(untag(curObj));
}
return objects.toArray(new DERObject[0]);
}
if (container instanceof DERApplicationSpecific) {
DERApplicationSpecific aps = (DERApplicationSpecific) container;
byte[] bytes = aps.getContents();
return readDERObjects(bytes);
}
if (container instanceof DEROctetString) {
DEROctetString octets = (DEROctetString) container;
byte[] bytes = octets.getOctets();
return readDERObjects(bytes);
}
throw new IllegalArgumentException("Unable to decode sequence from "+container);
}
В конце, когда у меня есть DeroctetStream, в которой содержалась зашифрованная часть, я только что использовал kerberosencdata:
KerberosEncData encData = new KerberosEncData(decrypted, matchingKey);
Последовательность байта, которую мы получаем из браузера клиента, будет проанализирована в отдельных реппликациях, который является корнем билета - уровень 0.
Корень содержит:
- DeRobjectIdentifier - spnego oid
- ДЕСКОВАНСКА
Уровень 1 содержит:
- Последовательность DerobjectedIdentifier - MECH -типы
- DeroCtetString - обернутая DerapplicationSepecific - Уровень 2
Уровень 2 содержит:
- DeRobjectIndentifier - kerberos oid
- TAG KRB5_AP_REQ
0x01 0x00
, проанализировано как логическое (ложное) - Derpplicationspecificific - контейнер с неэквадией - Уровень 3
Уровень 3 содержит:
- Номер версии - должен быть 5
- Тип сообщения - 14 (AP_REQ)
- Параметры AP (Derbitstring)
- Derpplicationspecificific - обернутая дерзоэквадиация с частью билета
- Dersequence с дополнительной частью билета - не обработана
Часть билета - уровень 4 содержит:
- Версия билета - должна быть 5
- Царство билета - название сферы, в которой пользователь аутентифицирует
- ДЕРЕВОДНОСТЬ ИМЕНИ СЕРВЕР. Каждое имя сервера - это неэффективность 2 строк: имя сервера и имя экземпляра
- ДЕРЕВОСТИКА С зашифрованной частью
Зашифрованная последовательность части (уровень 5) содержит:
- Используемый номер алгоритма
- 1, 3 - des
- 16-DES3-CBC-SHA1-KD
- 17-ETYPE-AES128-CTS-HMAC-SHA1-96
- 18-ETYPE-AES256-CTS-HMAC-SHA1-96
- 23 - RC4 -HMAC
- 24-RC4-HMAC-EXP
- Ключевой номер версии
- Зашифрованная часть (DeroctetStream)
Проблема была с Derboolean Constructor, этот бросок ArrayIndexoutOfBoundException, когда была найдена последовательность 0x01 0x00. Я должен был изменить этот конструктор:
public DERBoolean(
byte[] value)
{
// 2011-01-24 llech make it byte[0] proof, sequence 01 00 is KRB5_AP_REQ
if (value.length == 0)
this.value = 0;
else
this.value = value[0];
}
Вау было много времени с тех пор, как я использовал Spnego (почти год) ... вы задаете очень крутой вопрос.
Я немного копал и собирался попытаться запустить какой-то код, который у меня был некоторое время назад, который работал с MS-AD, но просто не чувствовал его сегодня:-/
В любом случае, я нашел эту ссылку через Google:http://www.google.com/url?sa=t&source=web&cd=1&sqi=2&ved=0cbmqfjaa&url=http%3a%2f%2fbofriis.dk%2ffiles%22fms_keros_pac.pdfrct=javtibleteravilegeblegebil 20certificate & ei = 2fastbalgcp38abk07iqdg & usg = afqjcnhcifqrutxkquvlrcgoaqkscaltha & sig2 = g8yn7ie1pbzske2mfv41bw & cad = rja
Надеюсь, это может дать вам некоторое представление.