Saltar a contenido

GraphQL Authorization Misconfiguration

Configuración incorrecta de autorización de GraphQL

Descripción

Una configuración incorrecta de autorización de GraphQL (GraphQL Authorization Misconfiguration) es una vulnerabilidad de seguridad crítica en la que una API de GraphQL no aplica de manera consistente y exhaustiva los controles de acceso en todas sus operaciones y modelos de datos. Esta omisión permite a los usuarios no autorizados acceder, modificar o eliminar información más allá de los permisos previstos, lo que podría comprometer la seguridad de todo el sistema. Las características clave de esta vulnerabilidad incluyen controles de acceso inconsistentes, donde diferentes consultas (queries) o mutaciones para datos similares tienen niveles variables de comprobaciones de autorización; un esquema demasiado permisivo que expone campos u operaciones sensibles sin las restricciones adecuadas; y la falta de límites de profundidad en las consultas, lo que resulta en la ausencia de mecanismos para evitar consultas excesivamente anidadas o que consuman muchos recursos.

Implicaciones

  1. Acceso y manipulación de datos no autorizados:
  2. Los atacantes pueden recuperar información sensible como datos personales de los usuarios, registros financieros o información comercial confidencial.
  3. Los usuarios malintencionados pueden alterar o eliminar datos críticos, afectando la integridad del sistema y la confianza del usuario.

  4. Posible escalada de privilegios:

  5. Al explotar consultas o mutaciones mal configuradas, los atacantes podrían obtener privilegios administrativos.
  6. Se hace posible el movimiento lateral dentro del sistema, permitiendo el acceso a otras áreas restringidas.

  7. Integridad del sistema comprometida:

  8. La fiabilidad y exactitud de todo el conjunto de datos se ponen en duda.
  9. Pueden producirse infracciones de cumplimiento normativo, especialmente en lo relativo a normativas de protección de datos como el GDPR o la CCPA.

  10. Exfiltración de datos:

  11. El robo de datos a gran escala se vuelve factible mediante consultas cuidadosamente diseñadas.
  12. Se podrían extraer bases de datos de usuarios o inteligencia competitiva sin ser detectados.

  13. Daño reputacional:

  14. La divulgación pública de tales vulnerabilidades puede llevar a la pérdida de confianza de los usuarios y a posibles consecuencias legales.

Ejemplo de código

  class UserType(DjangoObjectType):
    class Meta:
      model = User
      fields = ("id", "username", "email")

  class OrganizationType(DjangoObjectType):
    class Meta:
      model = Organization
      fields = ("id", "name", "users")

  class Query(graphene.ObjectType):
  all_users = graphene.List(UserType)
  organization = graphene.Field(OrganizationType, id=graphene.ID(required=True))

  def resolve_all_users(self, info):
    user = info.context.user
    if not user.is_authenticated:
      raise graphene.GraphQLError("Authentication required")
    return User.objects.all()

  def resolve_organization(self, info, id):
    try:
      org = Organization.objects.get(id=id)
    except Organization.DoesNotExist:
      raise graphene.GraphQLError("Organization not found")

    return org
En este ejemplo, tenga en cuenta que, aunque la Users Query implementa un control de acceso, la Organization Query no lo hace. Dado que la consulta de la organización expone el atributo de usuarios anidados, un atacante puede usarlo para acceder a información que fue denegada al ser consultada directamente.

Ejemplos de consultas:

# Consulta segura
query {
  allUsers {
    id
    username
    email
  }
}

# Consulta vulnerable
query {
  organization(id: "123") {
    id
    name
    users {
      id
      username
      email
    }
  }
}

Recomendación

Mejores prácticas para la mitigación

  1. Implementar una autorización consistente en el lado del servidor:
  2. Utilice middlewares o decoradores para aplicar controles de acceso de manera uniforme.
  3. Ejemplo:

    @require_permission('admin')
    def resolve_sensitive_data(self, info):
        # Solo los administradores pueden acceder a este resolver
        pass
    
  4. Utilizar permisos a nivel de campo:

  5. Defina y aplique controles de acceso a nivel de campo.
  6. Ejemplo usando graphene-django:

    class UserType(DjangoObjectType):
        class Meta:
            model = User
            fields = ('id', 'username', 'email')
    
        @staticmethod
        def resolve_email(parent, info):
            if info.context.user.has_permission('view_email'):
                return parent.email
            return None
    
  7. Usar escalares personalizados para datos sensibles:

  8. Implemente tipos escalares personalizados con comprobaciones de autorización incorporadas.

  9. Deshabilitar o limitar la introspección:

  10. En entornos de producción, deshabilite la introspección o limítela únicamente a usuarios autenticados y autorizados.

  11. Auditorías y escaneos de seguridad periódicos:

  12. Realice revisiones exhaustivas de su esquema GraphQL, resolvers y mecanismos de control de acceso.

Al abordar estas causas fundamentales e implementar mecanismos de autorización robustos, los desarrolladores pueden reducir significativamente el riesgo de configuraciones incorrectas de autorización en GraphQL y crear API de GraphQL más seguras.

Enlaces

Estándares

  • CCPA:
    • CCPA_1798_150
  • CWE_TOP_25:
    • CWE_862
  • OWASP_ASVS_L3:
    • V1_2_4
    • V4_1_3
    • V13_4_1
    • V13_4_2
  • SOC2_CONTROLS:
    • CC_6_3