当前位置:网站首页 > 黑客培训 > 正文

基于free5gc+UERANSIM的5G注册管理流程及安全服务分析 下

freebuffreebuf 2021-11-24 467 0

本文来源:中兴沉烽实验室

一、前言

随着5G的快速建设,5G的安全问题受到越来越多的关注。本篇作为《基于free5gc+UERANSIM的5G注册管理流程及安全服务分析 上》的姊妹篇,基于模拟环境对《3GPP TS 33.501》中定义的相关安全服务进行详细分析。旨在为5G安全研究及测试人员提供参考。

二、5G安全服务介绍

3GPP 5G的协议标准种类繁多,其中与安全紧密相关的协议标准是5G系统安全架构和流程(3GPP TS 33.501),该协议规定了5G系统和5G核心的安全特性和安全机制,以及5G系统内包括5G核心和5G新无线在内的安全流程。

《3GPP TS 33.501》标准14章定义了安全相关服务,这些服务为5G网络提供鉴权认证等安全相关的功能。其中和用户注册管理流程相关的有Nausf_UEAuthentication、Nudm_UEAuthentication以及Nudm_UEAuthentication_ResultConfirm。

三、模拟环境介绍

本节简单介绍了UERANSIM+free5gc环境,用户可以通过使用arp、ifconfig、docker inspect及网桥brctl 相关命令,来收集容器IP及Mac地址相关信息,绘制的组网示意图如下:

1637717462_619d95d68206002441df3.png?1637717454042

如上图所示:环境基于ubuntu 20.04 VMware虚机部署,5gc网元分别部署在虚机的docker容器中。5gc各模拟网元与模拟RAN 通过虚拟网桥进行数据交换。物理机上的VMware 虚拟网卡作为DN(互联网节点)通过虚拟网桥与容器中的UPF对接。详细的搭建方法可以参考沉烽网络安全实验室的文章《free5gc+UERANSIM模拟5G网络环境搭建及基本使用》 。

四、安全服务分析

本章节主要介绍注册管理流程相关的安全服务,并对流量、源代码进行分析,其中包括AUSF网元的Nausf_UEAuthentication服务,UDM网元的Nudm_UEAuthentication服务以及Nudm_UEAuthentication_ResultConfirm服务。

4.1、AUSF安全服务流量及代码分析

4.1.1 Nausf_UEAuthentication服务介绍

AUSF通过Nausf_UEAuthentication安全服务向请求者NF提供UE的认证服务,验证UE并提供相关的密钥资料,AMF会使用这些密钥来派生后续密钥。5GAKA认证中,AMF通过提供UE相关信息和服务网络名称来请求UE的身份验证,然后,NF服务消费者应将从UE收到的结果返回给AUSF进行XRES和HXRES的验证,具体定义可参考《3GPP TS 33.501 V16.5.0》标准。 服务输入:1、在初始身份验证请求中:SUPI或者SUCI,网络服务名称。 2、后续的认证请求中,AUSF从UDM中检索UE的签约身份验证方法,并根据UDM提供的信息,AUSF进入5G-AKA或者EAP-based authentication,两种鉴权方法的的输入分别如下。 a.5G AKA:带有RES*的鉴权信息或者失败信息,以及其他相关信息(比如RAND/AUTS)。 b.EAP-AKA':RFC 4187[21]和RFC5448[12]以及附件中描述的EAP数据包。 服务输出:1、Nausf_UEAuthentication将根据认证方式的不同输出一下内容之一。 a.5G AKA:认证向量。 b.EAP-AKA':RFC 4187[21]和RFC5448[12]以及附件中描述的EAP数据包。 2、认证结果,如果认证成功,则为AMF用于导出NAS安全密钥和其他。

4.1.2 Nausf_UEAuthentication服务流量及代码分析

Nausf_UE_Authentication请求一处理过程AMF收到RAN侧发送来的UE注册请求,如果AMF中不存在UE的安全上下文,则会向AUSF发起Nausf_UE_Authentication请求,该请求报文如下,报文包含了SUPI或者SUCI以及网络服务名称,对应标准中的描述。1637717489_619d95f1819ad67e6d175.png?1637717481045

{
"supiOrSuci": "suci-0-208-93-0000-0-0-0000000003",
"servingNetworkName": "5G:mnc093.mcc208.3gppnetwork.org"
}

从free5gc的代码中的路由配置可以找到Nausf_UEAuthentication安全服务的处理函数为HTTPUeAuthenticationsPost。

var routes = Routes{    
{
"HTTPUeAuthenticationsPost",
strings.ToUpper("Post"),
"/ue-authentications",
HTTPUeAuthenticationsPost,
}
}

HTTPUeAuthenticationsPost函数将调用HandleUeAuthPostRequest处理AMF发送的请求报文,并使用ctx.Data方法发送响应报文给AMF网元。

// HTTPUeAuthenticationsPost -
func HTTPUeAuthenticationsPost(ctx *gin.Context) {
...
req := http_wrapper.NewRequest(ctx.Request, authInfo)
rsp := producer.HandleUeAuthPostRequest(req)
for key, value := range rsp.Header {
ctx.Header(key, value[0])
}
responseBody, err := openapi.Serialize(rsp.Body, "application/json")
if err != nil {
logger.UeAuthPostLog.Errorln(err)
problemDetails := models.ProblemDetails{
Status: http.StatusInternalServerError,
Cause:  "SYSTEM_FAILURE",
Detail: err.Error(),
}
ctx.JSON(http.StatusInternalServerError, problemDetails)
} else {
ctx.Data(rsp.Status, "application/json", responseBody)
}
}

进入HandleUeAuthPostRequest方法后,会调用UeAuthPostRequestProcedure方法处理,该函数将返回response并通过http_wrapper.NewResponse进行封装,返回给上层函数。

func HandleUeAuthPostRequest(request *http_wrapper.Request) *http_wrapper.Response {
logger.UeAuthPostLog.Infof("HandleUeAuthPostRequest")
updateAuthenticationInfo := request.Body.(models.AuthenticationInfo)

response, locationURI, problemDetails := UeAuthPostRequestProcedure(updateAuthenticationInfo)
respHeader := make(http.Header)
respHeader.Set("Location", locationURI)

if response != nil {
return http_wrapper.NewResponse(http.StatusCreated, respHeader, response)
} else if problemDetails != nil {
return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails)
}
problemDetails =
err != nil {
logger.ContextLog.Warnf("SN compile error: %+v", err)
} else {
ausfContext.snRegex = snRegex
}
InitAusfContext(通过udm发送给ausf认证向量AV中的RAND和XRES进行SHA256计算得到HXRES
concat := authInfoResult.AuthenticationVector.Rand + authInfoResult.AuthenticationVector.XresStar
var hxresStarBytes []byte
if bytes, err := hex.DecodeString(concat); err != nil {
logger.Auth5gAkaComfirmLog.Warnf("decode error: %+v", err)
} else {
hxresStarBytes = bytes
}
hxresStarAll := sha256.Sum256(hxresStarBytes)
hxresStar := hex.EncodeToString(hxresStarAll[16:]) // last 128 bits
logger.Auth5gAkaComfirmLog.Infof("XresStar = %x\n", authInfoResult.AuthenticationVector.XresStar)

// 通过Kausf计算Kseaf,将kuasf,0x6c常量,服务网络P0作为入参,计算Kseaf。
// 同时ausf将Ksauf、XRES和RAND作为上下文进行保存。
Kausf := authInfoResult.AuthenticationVector.Kausf
var KausfDecode []byte
if ausfDecode, err := hex.DecodeString(Kausf); err != nil {
logger.Auth5gAkaComfirmLog.Warnf("AUSF decode failed: %+v", err)
} else {
KausfDecode = ausfDecode
}
P0 := []byte(snName)
Kseaf := UeauCommon.GetKDFValue(KausfDecode, UeauCommon.FC_FOR_KSEAF_DERIVATION, P0, UeauCommon.KDFLen(P0))
//将XRES*、Kausf、Kseaf、Rand保存到上的下文中
ausfUeContext.XresStar = authInfoResult.AuthenticationVector.XresStar
ausfUeContext.Kausf = Kausf
ausfUeContext.Kseaf = hex.EncodeToString(Kseaf)
ausfUeContext.Rand = authInfoResult.AuthenticationVector.Rand
}

AUSF将,然后将新的AV(RAND,AUTH,HXRES*)以及其他相关信息放在Nausf_UE_Authentication的响应报文中发送给AMF网元进行双向认证。1637717752_619d96f81b337049af57b.png?1637717743633

{
"authType": "5G_AKA",
"5gAuthData": {
"rand": "e37a60c2a71676fa504d531f5103e03f",
"hxresStar": "9ba762a79f2f97cdebf1cc952f2af418",
"autn": "40bd72e10f7d8000a233aa3b112b0979"
},
"_links": {
"link": {
"href": "http://ausf.free5gc.org:8000/nausf-auth/v1/ue-authentications/suci-0-208-93-0000-0-0-0000000003/5g-aka-confirmation"
}
},
"servingNetworkName": "5G:mnc093.mcc208.3gppnetwork.org"
}

封装Nausf_UE_Authentication的代码如下。

//封装Nausf_UE_Authentication返回报文
var av5gAka models.Av5gAka
av5gAka.Rand = authInfoResult.AuthenticationVector.Rand
av5gAka.Autn = authInfoResult.AuthenticationVector.Autn
av5gAka.HxresStar = hxresStar
responseBody.Var5gAuthData = av5gAka

linksValue := models.LinksValueSchema{Href: putLink}
responseBody.Links = make(map[string]models.LinksValueSchema)
responseBody.Links["5g-aka"] = linksValue

Nausf_UE_Authentication请求二处理过程AMF完成鉴权后,会发送5g-aka-confirmation报文给AUSF的Nausf_UE_Authentication服务,该报文类型为PUT,body数据中包含了UE的RES*信息。1637717764_619d9704aa008dbbf3628.png?1637717756185

{
"resStar": "c094c8af16226e35962fab5d15aff080"
}

根据AUSF代码中的路由信息,可看到该请求处理函数为HTTPUeAuthenticationsAuthCtxID5gAkaConfirmationPut。

var routes = Routes{
{
"HTTPUeAuthenticationsAuthCtxID5gAkaConfirmationPut",
strings.ToUpper("Put"),
"/ue-authentications/:authCtxId/5g-aka-confirmation",
HTTPUeAuthenticationsAuthCtxID5gAkaConfirmationPut,
}
}

HTTPUeAuthenticationsAuthCtxID5gAkaConfirmationPut函数会对报文进行反序列化并调用HandleAuth5gAkaComfirmRequest处理请求信息并将返回报文通过ctx.Data发送给AMF。

func HTTPUeAuthenticationsAuthCtxID5gAkaConfirmationPut(ctx *gin.Context) {
var confirmationData models.ConfirmationData

requestBody, err := ctx.GetRawData()
...//略过错误处理
req := http_wrapper.NewRequest(ctx.Request, confirmationData)
req.Params["authCtxId"] = ctx.Param("authCtxId")
rsp := producer.HandleAuth5gAkaComfirmRequest(req)
responseBody, err := openapi.Serialize(rsp.Body, "application/json")
if err != nil {
logger.Auth5gAkaComfirmLog.Errorln(err)
problemDetails := models.ProblemDetails{
Status: http.StatusInternalServerError,
Cause:  "SYSTEM_FAILURE",
Detail: err.Error(),
}
ctx.JSON(http.StatusInternalServerError, problemDetails)
} else {
ctx.Data(rsp.Status, "application/json", responseBody)
}
}

HandleAuth5gAkaComfirmRequest函数最终通过Auth5gAkaComfirmRequestProcedure进行处理,并使用http_wrapper.NewResponse封装消息体。

func HandleAuth5gAkaComfirmRequest(request *http_wrapper.Request) *http_wrapper.Response {
logger.Auth5gAkaComfirmLog.Infof("Auth5gAkaComfirmRequest")
updateConfirmationData := request.Body.(models.ConfirmationData)
ConfirmationDataResponseID := request.Params["authCtxId"]

response, problemDetails := Auth5gAkaComfirmRequestProcedure(updateConfirmationData, ConfirmationDataResponseID)
if response != nil {
return http_wrapper.NewResponse(http.StatusOK, nil, response)
} else if problemDetails != nil {
return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails)
}
problemDetails =
sendErr != nil {
logger.Auth5gAkaComfirmLog.Infoln(sendErr.Error())
var problemDetails models.ProblemDetails
problemDetails.Status = http.StatusInternalServerError
problemDetails.Cause = "UPSTREAM_SERVER_ERROR"
return nil, i len(sqn); i++ {
SQNxorAK[i] = sqn[i] ^ AK[i]
}
// fmt.Printf("SQN xor AK = %x\n", SQNxorAK)
AUTN := append(append(SQNxorAK, AMF...), macA...)
fmt.Printf("AUTN = %x\n", AUTN)

// 计算 XRES*
key := append(CK, IK...)
FC := UeauCommon.FC_FOR_RES_STAR_XRES_STAR_DERIVATION
P0 := []byte(authInfoRequest.ServingNetworkName)
P1 := RAND
P2 := RES

kdfValForXresStar := UeauCommon.GetKDFValue(
key, FC, P0, UeauCommon.KDFLen(P0), P1, UeauCommon.KDFLen(P1), P2, UeauCommon.KDFLen(P2))
xresStar := kdfValForXresStar[len(kdfValForXresStar)/2:]

// 计算 Kausf
FC = UeauCommon.FC_FOR_KAUSF_DERIVATION
P0 = []byte(authInfoRequest.ServingNetworkName)
P1 = SQNxorAK
kdfValForKausf := UeauCommon.GetKDFValue(key, FC, P0, UeauCommon.KDFLen(P0), P1, UeauCommon.KDFLen(P1))

// 填充 rand, xresStar, autn, kausf
av.Rand = hex.EncodeToString(RAND)
av.XresStar = hex.EncodeToString(xresStar)
av.Autn = hex.EncodeToString(AUTN)
av.Kausf = hex.EncodeToString(kdfValForKausf)

4.2.3 Nudm_UEAuthentication_ResultConfirm服务介绍

Nudm_UEAuthentication_ResultConfirm服务的主要作用是AUSF用来告知UDM本次UE身份验证的结果,具体定义可参考《3GPP TS 33.501 V16.5.0》协议中的相关章节。

服务输入:

SUPI、身份验证的时间戳、身份验证类型以及服务网络名称。

5.2.4 Nudm_UEAuthentication_ResultConfirm服务流量及代码分析

在free5gc模拟环境中截获AUSF向UDM返回的报文如下:

1637718100_619d985453a599433d599.png?1637718091909

报文中携带了本次验证UE的SUPI信息。

消息体中携带的数据如下:

{
"nfInstanceId": "",
"success": true,
"timeStamp": "2021-09-24T08:28:53.330400908Z",
"authType": "5G_AKA",
"servingNetworkName": "5G:mnc093.mcc208.3gppnetwork.org"
}

通过这个报文可以看到本次认证的结果是成功的,并且携带了认证的时间戳,认证的方式和服务网络名称。

整个服务的过程和协议描述一致。

代码定位于ausf\producer\functions.go中的sendAuthResultToUDM函数

func sendAuthResultToUDM(id string, authType models.AuthType, success bool, servingNetworkName, udmUrl string) error {
timeNow := time.Now()
timePtr := &timeNow

var authEvent models.AuthEvent
authEvent.TimeStamp = timePtr   //时间戳
authEvent.AuthType = authType   //验证方式
authEvent.Success = success     //认证结果
authEvent.ServingNetworkName = servingNetworkName   //服务网络名称

client := createClientToUdmUeau(udmUrl)
_, _, confirmAuthErr := client.ConfirmAuthApi.ConfirmAuth(context.Background(), id, authEvent)
return confirmAuthErr
}

五、总结

本文借助free5gc+UERANSIM模拟5G网络环境,通过抓包和源码分析的方式介绍了33501标准中的安全相关服务。希望能帮助到对5G知识感兴趣的读者,不足之处请多多指正。

参考资料

  • 沉烽网络安全实验室:《free5gc+UERANSIM模拟5G网络环境搭建及基本使用》

  • 沉烽网络安全实验室:《基于UERANSIM+free5gc 5G模拟环境的5G_AKA协议解析》

  • 张忠琳:【5G核心网】free5GC 注册请求流程源码分析

  • 3GPP TS 23 502

  • 3GPP TS 33.501

转载请注明来自网盾网络安全培训,本文标题:《基于free5gc+UERANSIM的5G注册管理流程及安全服务分析 下》

标签:协议安全网络安全技术5G安全

关于我

欢迎关注微信公众号

关于我们

网络安全培训,黑客培训,渗透培训,ctf,攻防

标签列表