CVE-2024-25715: URL Redirection to Untrusted Site ('Open Redirect') (CWE-601)
value: Glewlwyd SSO server 2.x through 2.7.6 allows open redirection via redirect_uri.
CWE description: A web application accepts a user-controlled input that specifies a link to an external site, and uses that link in a Redirect. This simplifies phishing attacks.
CVSS v3 base score: 6.1
Published: 2024-02-11T03:15Z
Repository: https://github.com/babelouest/glewlwyd
Language: C
Files changed: src/plugin/protocol_oidc.c
Commit date: 2024-01-26 14:41:48 -0500
Commit message: Enforce open redirection fix

Diff: diff --git a/src/plugin/protocol_oidc.c b/src/plugin/protocol_oidc.c
index 23ad54e17..3b761a394 100644
--- a/src/plugin/protocol_oidc.c
+++ b/src/plugin/protocol_oidc.c
@@ -3801,12 +3801,10 @@ static int check_client_redirect_uri_valid(struct _oidc_config * config,
       if (json_array_has_string(json_object_get(json_object_get(j_client, "client"), "redirect_uri"), redirect_uri)) {
         uri_found = 1;
       } else {
         uri_found = 0;
       }
-    } else {
-      uri_found = 1;
     }
     if (!uri_found) {
       y_log_message(Y_LOG_LEVEL_DEBUG, "check_client_redirect_uri_valid - oidc - Error, redirect_uri '%s' is invalid for the client '%s', origin: %s", redirect_uri, client_id, ip_source);
       ret = G_ERROR_UNAUTHORIZED;
     } else {
@@ -3832,18 +3830,15 @@ static json_t * check_client_valid_without_secret(struct _oidc_config * config,
   size_t index = 0;
 
   j_client = config->glewlwyd_config->glewlwyd_plugin_callback_get_client(config->glewlwyd_config, client_id);
   if (check_result_value(j_client, G_OK) && json_object_get(json_object_get(j_client, "client"), "enabled") == json_true()) {
     if (redirect_uri != NULL) {
-      uri_found = 0;
       json_array_foreach(json_object_get(json_object_get(j_client, "client"), "redirect_uri"), index, j_element) {
         if (0 == o_strcmp(json_string_value(j_element), redirect_uri)) {
           uri_found = 1;
         }
       }
-    } else {
-      uri_found = 1;
     }
 
     authorization_type_enabled = 1;
     if (authorization_type & GLEWLWYD_AUTHORIZATION_TYPE_AUTHORIZATION_CODE_FLAG) {
       if (!json_array_has_string(json_object_get(json_object_get(j_client, "client"), "authorization_type"), "code")) {
@@ -4001,12 +3996,10 @@ static json_t * check_client_valid(struct _oidc_config * config,
       y_log_message(Y_LOG_LEVEL_DEBUG, "check_client_valid - oidc - Error, confidential client must be authentified with its password, origin: %s", ip_source);
       j_return = json_pack("{si}", "result", G_ERROR_UNAUTHORIZED);
     } else {
       if (redirect_uri != NULL) {
         uri_found = json_array_has_string(json_object_get(json_object_get(j_client, "client"), "redirect_uri"), redirect_uri);
-      } else {
-        uri_found = 1;
       }
 
       authorization_type_enabled = 1;
       if (!authorization_type) {
         authorization_type_enabled = 0;
@@ -14163,11 +14156,11 @@ static int callback_oidc_authorization(const struct _u_request * request, struct
       if (o_strstr(response_type, "code") == NULL) {
         response_mode = GLEWLWYD_RESPONSE_MODE_FRAGMENT;
       }
     }
 
-    if (!o_strnullempty(client_id) && !o_strnullempty(redirect_uri) && check_client_redirect_uri_valid(config, client_id, redirect_uri, ip_source) != G_OK) {
+    if (!o_strnullempty(response_type) && check_client_redirect_uri_valid(config, client_id, redirect_uri, ip_source) != G_OK) {
       y_log_message(Y_LOG_LEVEL_DEBUG, "callback_oidc_authorization - invlid client identified with redirect_uri");
       response->status = 403;
       break;
     }
 
@@ -14272,11 +14265,11 @@ static int callback_oidc_authorization(const struct _u_request * request, struct
           display = json_string_value(json_object_get(json_object_get(j_request, "request"), "display"));
           ui_locales = json_string_value(json_object_get(json_object_get(j_request, "request"), "ui_locales"));
           login_hint = json_string_value(json_object_get(json_object_get(j_request, "request"), "login_hint"));
           prompt = json_string_value(json_object_get(json_object_get(j_request, "request"), "prompt"));
           max_age = json_string_value(json_object_get(json_object_get(j_request, "request"), "max_age"));
-          if (!o_strnullempty(client_id) && !o_strnullempty(redirect_uri) && check_client_redirect_uri_valid(config, client_id, redirect_uri, ip_source) != G_OK) {
+          if (check_client_redirect_uri_valid(config, client_id, redirect_uri, ip_source) != G_OK) {
             y_log_message(Y_LOG_LEVEL_DEBUG, "callback_oidc_authorization - invlid client identified with redirect_uri");
             response->status = 403;
             break;
           }
           if (code_challenge == NULL || request_par) {
@@ -14521,14 +14514,11 @@ static int callback_oidc_authorization(const struct _u_request * request, struct
       break;
     }
 
     // Check if at least one scope has been provided
     if (o_strnullempty(scope)) {
-      // Scope is not allowed for this user
-      y_log_message(Y_LOG_LEVEL_DEBUG, "oidc validate_endpoint_auth - scope list is missing or empty or scope 'openid' missing, origin: %s", ip_source);
-      u_map_put(&map_redirect, "error", "invalid_scope");
-      build_auth_response(config, response, response_mode, json_object_get(j_client, "client"), redirect_uri, &map_redirect);
+      response->status = 403;
       break;
     }
 
     if (!json_string_null_or_empty(json_object_get(config->j_params, "restrict-scope-client-property"))) {
       j_reduced_scope = reduce_scope(scope, json_object_get(json_object_get(j_client, "client"), json_string_value(json_object_get(config->j_params, "restrict-scope-client-property"))));

Vulnerable code:     } else {
      uri_found = 1;
      uri_found = 0;
    } else {
      uri_found = 1;
      } else {
        uri_found = 1;
    if (!o_strnullempty(client_id) && !o_strnullempty(redirect_uri) && check_client_redirect_uri_valid(config, client_id, redirect_uri, ip_source) != G_OK) {
          if (!o_strnullempty(client_id) && !o_strnullempty(redirect_uri) && check_client_redirect_uri_valid(config, client_id, redirect_uri, ip_source) != G_OK) {
      // Scope is not allowed for this user
      y_log_message(Y_LOG_LEVEL_DEBUG, "oidc validate_endpoint_auth - scope list is missing or empty or scope 'openid' missing, origin: %s", ip_source);
      u_map_put(&map_redirect, "error", "invalid_scope");
      build_auth_response(config, response, response_mode, json_object_get(j_client, "client"), redirect_uri, &map_redirect);
Fixed code:     if (!o_strnullempty(response_type) && check_client_redirect_uri_valid(config, client_id, redirect_uri, ip_source) != G_OK) {
          if (check_client_redirect_uri_valid(config, client_id, redirect_uri, ip_source) != G_OK) {
      response->status = 403;