简介
本文档介绍RADIUS身份验证器报头和消息身份验证器属性,如何使用它们,以及何时会出现验证失败。
身份验证器报头
根据RFC 2865,身份验证器报头的长度为16个字节。在访问请求中使用时,它称为请求身份验证器。当它用于任何类型的响应时,它称为响应身份验证器。它用于:
响应身份验证
如果服务器使用正确的响应身份验证器进行响应,则客户端可以计算该响应是否与有效请求相关。
客户端发送带有随机身份验证器报头的请求。然后,发送响应的服务器将使用请求数据包以及共享密钥来计算响应身份验证器:
ResponseAuth = MD5(Code + ID + Length + RequestAuth + Attributes + Secret)
接收响应的客户端执行相同的操作。如果结果相同,则表示数据包正确。
注意:知道加密值的攻击者无法欺骗响应,除非它能够嗅探到请求。
何时会出现验证失败:
如果交换机不再缓存请求(例如,由于超时),则会发生验证失败。 当共享密钥无效时,您也会遇到这种情况(是 — Access-Reject也包含此信头)。 这样,网络接入设备(NAD)可以检测到共享密钥不匹配。通常,身份验证、授权和记帐(AAA)客户端/服务器将其报告为共享密钥不匹配,但不会显示详细信息。
密码隐藏
身份验证器报头也用于避免以纯文本格式发送User-Password属性。首先计算消息摘要5(MD5 - secret, authenticator)。然后,对密码块执行几个XOR操作。此方法容易受到离线攻击(彩虹表),因为MD5不再被视为强单向算法。
以下是用于计算用户密码的Python脚本:
def Encrypt_Pass(password, authenticator, secret):
m = md5()
m.update(secret+authenticator)
return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(password.ljust
(16,'\0')[:16], m.digest()[:16]))
重新传输
如果RADIUS Access-Request中的任何属性已更改(如RADIUS ID、用户名等),则必须生成新的Authenticator字段,并且必须重新计算依赖该字段的所有其他字段。如果是重新传输,则不会发生任何变化。
记账
Access-Request和Accounting-Request的Authenticator Header含义不同。
对于Access-Request,身份验证器是随机生成的,需要接收响应,ResponseAuthenticator计算正确,这证明响应与该特定请求相关。
对于Accounting-Request,身份验证器不是随机的,但它是计算得出的(根据RFC 2866):
RequestAuth = MD5(Code + ID + Length + 16 zero octets + Attributes + Secret)
这样,如果重新计算的值与Authenticator值不匹配,服务器可以立即检查记帐消息并丢弃数据包。身份服务引擎(ISE)返回:
11038 RADIUS Accounting-Request header contains invalid Authenticator field
此问题的典型原因是共享密钥不正确。
消息验证器属性
Message-Authenticator属性是在RFC 3579中定义的RADIUS属性。其用途与此类似:进行签名和验证。但这一次,它不是用于验证响应,而是用于验证请求。
发送访问请求的客户端(也可以是响应访问质询的服务器)从自己的数据包计算基于哈希的消息身份验证代码(HMAC)-MD5,然后添加Message-Authenticator属性作为签名。然后,服务器可以验证它是否执行了相同的操作。
公式类似于身份验证器报头:
Message-Authenticator = HMAC-MD5 (Type, Identifier, Length, Request Authenticator,
Attributes)
HMAC-MD5函数有两个参数:
- 数据包的负载,包括填入零的16字节消息验证器字段
- 共享密钥
何时使用消息验证器:
每个数据包都必须使用消息验证器,包括可扩展身份验证协议(EAP)消息(RFC 3579)。 这包括发送访问请求的客户端和使用Access-Challenge进行响应的服务器。如果验证失败,另一端会以静默方式丢弃数据包。
何时会出现验证失败:
当共享密钥无效时,验证失败。然后,AAA服务器无法验证请求。
ISE报告:
11036 The Message-Authenticator Radius Attribute is invalid.
这通常发生在附加EAP消息的较后阶段。802.1x会话的第一个RADIUS数据包不包含EAP消息;没有Message-Authenticator字段,无法验证请求,但在此阶段,客户端能够使用Authenticator字段验证响应。
验证Message-Authenticator属性
以下示例说明如何手动计算值以确保正确计算值。
已选择数据包编号30(Access-Request)。它位于EAP会话的中间,并且数据包包括Message-Authenticator字段。目的是验证Message-Authenticator是正确的:
- 右键单击Radius Protocol,然后选择导出选定的数据包字节。
- 将RADIUS负载写入文件(二进制数据)。
- 要计算Message-Authenticator字段,必须在该字段中置入零并计算HMAC-MD5。
例如,使用十六进制/二进制编辑器(如vim)时,在键入“:%!xxd”后,该编辑器将切换到十六进制模式,从“5012”之后开始将零设置为16个字节(50hex在十进制中为80,该十进制是消息验证器类型,12是包含属性值对(AVP)标头的大小为18):
请注意,vim和其他文本编辑器可以在保存时向文件末尾添加一个额外的LineFeed字符(十六进制为“0a”)。确保使用文本编辑器的二进制模式(vim -b文件)防止LineFeed字符出现。
修改之后,负载准备就绪。必须返回十六进制/二进制模式(类型:“:%!xxd -r”)并保存文件(“:wq”)。 您可以通过“hexdump -C file”仔细检查是否未添加额外的LineFeed字符。
- 使用OpenSSL计算HMAC-MD5:
pluton # cat packet30-clear-msgauth.bin | openssl dgst -md5 -hmac 'cisco'
(stdin)= 01418d3b1865556918269d3cf73608b0
HMAD-MD5函数有两个参数:标准输入(stdin)中的第一个是消息本身,第二个是共享密钥(本例中为Cisco)。 结果与RADIUS Access-Request数据包附加的消息验证器的值完全相同。
使用Python脚本可以计算相同内容:
Python 2:
pluton # cat hmac.py
#!/usr/bin/env python
import base64
import hmac
import hashlib
f = open('packet30-clear-msgauth.bin', 'rb')
try:
body = f.read()
finally:
f.close()
digest = hmac.new('cisco', body, hashlib.md5)
d=digest.hexdigest()
print d
pluton # python hmac.py
01418d3b1865556918269d3cf73608b0
Python 3:
import hmac
import hashlib
with open('packet30-clear-msgauth.bin', 'rb') as f:
body = f.read()
digest = hmac.new(b'cisco', body, hashlib.md5)
print(digest.hexdigest())
上一个示例展示如何从Access-Request计算Message-Authenticator字段。对于Access-Challenge、Access-Accept和Access-Reject,逻辑完全相同,但必须记住必须使用请求身份验证器,如之前的Access-Request数据包中所提供。
相关信息