[Authorize]
con el uso de un atributo [AllowAnonymous]
de clase o método.[Authorize]
a una clase o un método. Además, el requisito de autorización especificado de una clase o método de aplicación se puede omitir agregando el atributo [AllowAnonymous]
. Cuando se especifican ambos, el atributo [AllowAnonymous]
tiene prioridad y omite el atributo [Authorize]
. Esto puede resultar en el acceso arbitrario y anónimo a datos y acciones confidenciales por parte de un atacante.[AllowAnonymous]
de clase anulando un conjunto de atributos [Authorize]
en el método. El método secretAction()
no requiere autorización a pesar de tener el atributo [Authorize]
.Ejemplo 2: El siguiente ejemplo muestra el atributo
...
[AllowAnonymous]
public class Authorization_Test
{
[Authorize]
public IActionResult secretAction()
{
}
}
...
[AllowAnonymous]
de clase de una superclase anulando un atributo [Authorize]
establecido en el método de una subclase. Debido a que la clase heredada Inherit_AA
tiene el atributo [AllowAnonymous]
, el método secretAction()
no requiere autorización a pesar de especificar el atributo [Authorize]
.Ejemplo 3: A continuación, se muestra el atributo
...
[AllowAnonymous]
public abstract class Inherit_AA
{
}
public class Authorization_Test:Inherit_AA
{
[Authorize]
public IActionResult secretAction()
{
}
}
...
[AllowAnonymous]
que anula un atributo [Authorize]
de método con herencia. Debido a que el método heredado secretAction()
tiene el atributo [AllowAnonymous]
, el método secretAction()
no requiere autorización, a pesar de especificar el atributo [Authorize]
en el método de anulación.
...
public abstract class Inherit_AA
{
[AllowAnonymous]
public abstract IActionResult secretAction()
{
}
}
public class Authorization_Test:Inherit_AA
{
[Authorize]
public override IActionResult secretAction()
{
}
}
...
<apex:page controller="accessControl">
<apex:pageBlock >
<apex:pageBlockSection >
<apex:outputText value="Survey Name: "/>
<apex:inputText value="{!surveyName}"/>
</apex:pageBlockSection>
<apex:pageBlockSection >
<apex:outputText value="New Name: "/>
<apex:inputText value="{!newSurveyName}"/>
</apex:pageBlockSection>
<apex:pageBlockSection >
<apex:commandButton value="Update" action="{!updateName}"/>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:page>
public String surveyName { get; set; }
public String newSurveyName { get; set; }
public PageReference updateName() {
Survey__c s = [SELECT Name FROM Survey__c WHERE Name=:surveyName];
s.Name = newSurveyName;
update s;
PageReference page = ApexPages.currentPage();
page.setRedirect(true);
return page;
}
String canned_acl = request.getParameter("acl");
CreateBucketRequest createBucketRequest = CreateBucketRequest.builder()
.bucket("foo")
.acl(canned_acl)
.createBucketConfiguration(CreateBucketConfiguration.builder().locationConstraint(region.id()).build())
.build();
acl
en un grupo limitado, un usuario malintencionado puede definirlo como public-read-write
y conceder acceso anónimo completo al contenedor.
...
String selectedInvoice = request.getParameter("invoiceDate");
...
AmazonSimpleDBClient sdbc = new AmazonSimpleDBClient(appAWSCredentials);
GetAttributesResult sdbResult = sdbc.getAttributes(new GetAttributesRequest("invoices", selectedInvoice));
...
Example 1
genera una lista de facturas que pertenecen al usuario actual, un atacante podría omitir este comportamiento para solicitar la factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
...
id = this.getIntent().getExtras().getInt("id");
cursor = db.query(Uri.parse(invoices), columns, "id = ? ", {id}, null, null, null);
...
id
. Aunque la consulta genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede omitir este comportamiento para solicitar cualquier factura que desee. Como el código de este ejemplo no garantiza que el usuario tenga permiso para acceder a la factura solicitada, se mostrará cualquier factura, aunque no pertenezca al usuario actual.DirectoryEntry de
mediante un enlace anónimo.
...
de = new DirectoryEntry("LDAP://ad.example.com:389/ou=People,dc=example,dc=com");
...
de
se realizarán sin autenticación ni control de acceso. Un atacante puede ser capaz de manipular una de estas consultas de forma inesperada para obtener acceso a registros que, de otro modo, estarían protegidos por el mecanismo de control de acceso del directorio.ldap_simple_bind_s()
para vincularse de forma anónima a un directorio LDAP.
...
rc = ldap_simple_bind_s( ld, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
...
}
...
ld
se realizarán sin autenticación ni control de acceso. Un atacante puede ser capaz de manipular una de estas consultas de forma inesperada para obtener acceso a registros que, de otro modo, estarían protegidos por el mecanismo de control de acceso del directorio.DirContext ctx
mediante un enlace anónimo.
...
env.put(Context.SECURITY_AUTHENTICATION, "none");
DirContext ctx = new InitialDirContext(env);
...
ctx
se realizarán sin autenticación ni control de acceso. Un atacante puede ser capaz de manipular una de estas consultas de forma inesperada para obtener acceso a registros que, de otro modo, estarían protegidos por el mecanismo de control de acceso del directorio.
...
$ldapbind = ldap_bind ($ldap, $dn, $password = "" );
...
...
PARAMETERS: p_xfeld TYPE xfeld.
...
CALL FUNCTION 'BAPI_EMPLOYEE_GETDATA'
EXPORTING
employee_id = emp_id
authority_check = p_xfeld
IMPORTING
return = ret
TABLES
org_assignment = org_data
personal_data = pers_data
internal_control = con_data
communication = comm_data
archivelink = arlink.
...
p_xfeld
, no se llevan a cabo las comprobaciones de autorización antes de devolver la información personal y de contacto de un empleado.Ejemplo 2: el siguiente código elimina el contenedor de blob dado y su contenido.
...
var queueName = queryStringData['name'];
var queueSvc;
queueSvc = azureStorage.createQueueService();
...
queueSvc.deleteQueue(queueName, option, function(error, response){
if(!error){
// all the messages has been deleted
}
});
...
...
var containerName = queryStringData['name'];
var blobSvc;
blobSvc = azureStorage.createBlobService();
...
blobSvc.deleteContainer(containerName, function (error, response) {
if (!error) {
// all the content in the given container has been deleted
}
});
...
Example 1
y el Example 2
elimina la cola o el contenedor de blob dado y sus mensajes o contenido que pertenecen al usuario o programa actual, un usuario malintencionado puede eliminar cualquier cola o blob de esa cuenta de Azure. Dado que el código en este ejemplo no realiza una comprobación para asegurarse de que el usuario o programa tiene permiso para borrar la cola o blob solicitado, borrará la cola o blob, incluso si no pertenece al usuario o programa actual.
public boolean isTrusted(String paramString) {
if (this._applicationContext.getPackageName().equalsIgnoreCase(paramString)) {
return true;
}
DATA: id TYPE i.
...
id = request->get_form_field( 'invoiceID' ).
CONCATENATE `INVOICEID = '` id `'` INTO cl_where.
SELECT *
FROM invoices
INTO CORRESPONDING FIELDS OF TABLE itab_invoices
WHERE (cl_where).
ENDSELECT.
...
ID
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
...
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var id:int = int(Number(params["invoiceID"]));
var query:String = "SELECT * FROM invoices WHERE id = :id";
stmt.sqlConnection = conn;
stmt.text = query;
stmt.parameters[":id"] = id;
stmt.execute();
...
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.inputID
se origina a partir de una lista definida previamente, y una variable de enlace contribuye a evitar la inyección de SOQL/SOSL.
...
result = [SELECT Name, Phone FROM Contact WHERE (IsDeleted = false AND Id=:inputID)];
...
inputID
. Si el atacante es capaz de evitar la interfaz y enviar una solicitud con un valor diferente, tendrá acceso a otra información de contacto. Dado que el código en este ejemplo no realiza una comprobación para asegurarse de que el usuario tiene permiso para acceder al contacto solicitado, se mostrará cualquier contacto, incluso si el usuario no tiene permiso para verlo.
...
int16 id = System.Convert.ToInt16(invoiceID.Text);
var invoice = OrderSystem.getInvoices()
.Where(new Invoice { invoiceID = id });
...
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
...
CMyRecordset rs(&dbms);
rs.PrepareSQL("SELECT * FROM invoices WHERE id = ?");
rs.SetParam_int(0,atoi(r.Lookup("invoiceID").c_str()));
rs.SafeExecuteSQL();
...
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
...
ACCEPT ID.
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT INVNO, INVDATE, INVTOTAL
FROM INVOICES
WHERE INVOICEID = :ID
END-EXEC.
...
ID
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.deleteDatabase
que contenga el nombre de una base de datos controlada por el usuario puede permitir que un atacante elimine cualquier base de datos.
...
id := request.FormValue("invoiceID")
query := "SELECT * FROM invoices WHERE id = ?";
rows, err := db.Query(query, id)
...
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
...
id = Integer.decode(request.getParameter("invoiceID"));
String query = "SELECT * FROM invoices WHERE id = ?";
PreparedStatement stmt = conn.prepareStatement(query);
stmt.setInt(1, id);
ResultSet results = stmt.execute();
...
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.Example 1
a la plataforma Android.
...
String id = this.getIntent().getExtras().getString("invoiceID");
String query = "SELECT * FROM invoices WHERE id = ?";
SQLiteDatabase db = this.openOrCreateDatabase("DB", MODE_PRIVATE, null);
Cursor c = db.rawQuery(query, new Object[]{id});
...
...
var id = document.form.invoiceID.value;
var query = "SELECT * FROM invoices WHERE id = ?";
db.transaction(function (tx) {
tx.executeSql(query,[id]);
}
)
...
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
...
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:@"Invoices" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSPredicate *pred = [NSPredicate predicateWithFormat:@"(id = %@)", invoiceId.text];
[request setPredicate:pred];
NSManagedObject *matches = nil;
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if ([objects count] == 0) {
status.text = @"No records found.";
} else {
matches = [objects objectAtIndex:0];
invoiceReferenceNumber.text = [matches valueForKey:@"invRefNum"];
orderNumber.text = [matches valueForKey:@"orderNumber"];
status.text = [NSString stringWithFormat:@"%d records found", [objects count]];
}
[request release];
...
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
...
$id = $_POST['id'];
$query = "SELECT * FROM invoices WHERE id = ?";
$stmt = $mysqli->prepare($query);
$stmt->bind_param('ss',$id);
$stmt->execute();
...
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
procedure get_item (
itm_cv IN OUT ItmCurTyp,
id in varchar2)
is
open itm_cv for ' SELECT * FROM items WHERE ' ||
'invoiceID = :invid' ||
using id;
end get_item;
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
...
id = request.POST['id']
c = db.cursor()
stmt = c.execute("SELECT * FROM invoices WHERE id = %s", (id,))
...
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
...
id = req['invoiceID'].respond_to(:to_int)
query = "SELECT * FROM invoices WHERE id=?"
stmt = conn.prepare(query)
stmt.execute(id)
...
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
def searchInvoice(value:String) = Action.async { implicit request =>
val result: Future[Seq[Invoice]] = db.run {
sql"select * from invoices where id=$value".as[Invoice]
}
...
}
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
...
let fetchRequest = NSFetchRequest()
let entity = NSEntityDescription.entityForName("Invoices", inManagedObjectContext: managedContext)
fetchRequest.entity = entity
let pred : NSPredicate = NSPredicate(format:"(id = %@)", invoiceId.text)
fetchRequest.setPredicate = pred
do {
let results = try managedContext.executeFetchRequest(fetchRequest)
let result : NSManagedObject = results.first!
invoiceReferenceNumber.text = result.valueForKey("invRefNum")
orderNumber.text = result.valueForKey("orderNumber")
status.text = "\(results.count) records found"
} catch let error as NSError {
print("Error \(error)")
}
...
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
...
id = Request.Form("invoiceID")
strSQL = "SELECT * FROM invoices WHERE id = ?"
objADOCommand.CommandText = strSQL
objADOCommand.CommandType = adCmdText
set objADOParameter = objADOCommand.CreateParameter("id" , adString, adParamInput, 0, 0)
objADOCommand.Parameters("id") = id
...
id
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.
...
ACCEPT ID.
EXEC DLI
GU
SEGMENT(INVOICES)
WHERE (INVOICEID = ID)
END-EXEC.
...
ID
. Aunque la interfaz genera una lista de identificadores de factura que pertenecen al usuario actual, un atacante puede eludir esta interfaz para solicitar cualquier factura que desee. Dado que el código de este ejemplo no comprueba si el usuario tiene permiso para acceder a la factura solicitada, se mostrará cualquier factura, incluso si no pertenece al usuario actual.aspnet:UseLegacyFormsAuthenticationTicketCompatibility
para permitir que entradas no validadas se pasen a las API nativas y puede llevar a que un atacante pueda eludir la autenticación. Un atacante que aproveche con éxito esta vulnerabilidad podría eludir la autenticación de formularios ASP.NET para cualquier nombre de usuario conocido sin su contraseña. El atacante podría entonces realizar cualquier acción en el contexto del usuario víctima, incluida la ejecución de comandos arbitrarios en el sitio.aspnet:UseLegacyFormsAuthenticationTicketCompatibility
está definido como true
.
...
<appSettings>
<add key="aspnet:UseLegacyFormsAuthenticationTicketCompatibility" value="true" />
</appSettings>
...
Metadata
de Google Remote Procedure Call (gRPC) a pesar de faltar la validación.Metadata
se usa a menudo para albergar datos de cabeceras para un protocolo subyacente que usa Google Remote Procedure Call (gRPC). Al implementar la clase io.grpc.ServerInterceptor
, el objeto Metadata
debe validarse y devolver un error si se lanza una excepción.Metadata
de gRPC que pasa al siguiente objeto io.grpc.ServerCallHandler
después de obtener la excepción:
class PotentialAuthByPassInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata metadata, ServerCallHandler<ReqT, RespT> next) {
try {
customValidate(metadata);
} catch (RuntimeException e) {
return next.startCall(call, metadata);
}
...
return Contexts.interceptCall(Context.current(), call, metadata, next);
}
}
static string AllowlistVerify(string name) {
Regex pattern = new Regex(@"^[a-zA-Z\-\.']+$");
if (pattern.IsMatch(name)) {
return name;
}
return null;
}
...
string verifiedName = AllowlistVerify(managerName.Text.trim());
if(verifiedName != null) {
DirectorySearcher src = new DirectorySearcher("(manager=" + verifiedName + ")");
src.SearchRoot = de;
src.SearchScope = SearchScope.Subtree;
foreach(SearchResult res in src.FindAll()) {
...
}
}
empName
. Aunque la interfaz envíe automáticamente el ID de empleado al usuario actual, un atacante podría enviar un valor alternativo como parte de una solicitud maliciosa. Como el código de este ejemplo ejecuta la consulta bajo un vínculo anónimo, devolverá la entrada de directorio para un ID de empleado válido, independientemente de la identidad del usuario autenticado actualmente.
char* allowlist_verify(char* name) {
const char *error;
int errOffset;
char* regex = "^[a-zA-Z\\-\\.']+$";
pcre* re = pcre_compile(regex, 0, &err, &errOffset, NULL);
int rc = pcre_exec(re, NULL, name, strlen(name), 0, 0, NULL, 0);
if (rc == 1)
return name;
return NULL;
}
...
fgets(managerName, sizeof(managerName), socket);
char* verified_name = allowlist_verify(managerName);
if(verified_name != NULL) {
snprintf(filter, sizeof(filter), "(manager=%s)", verified_name);
if ( ( rc = ldap_search_ext_s( ld, FIND_DN, LDAP_SCOPE_BASE,
filter, NULL, 0, NULL, NULL, LDAP_NO_LIMIT,
LDAP_NO_LIMIT, &result ) ) == LDAP_SUCCESS ) {
...
}
}
username
. Como el código de este ejemplo ejecuta la consulta bajo un vínculo anónimo, devolverá la entrada de directorio para un ID de empleado válido, independientemente de la identidad del usuario autenticado actualmente.
...
env.put(Context.SECURITY_AUTHENTICATION, "none");
DirContext ctx = new InitialDirContext(env);
String empID = request.getParameter("empID");
try
{
int id = Integer.parseInt(empID);
BasicAttribute attr = new BasicAttribute("empID", empID);
NamingEnumeration employee =
ctx.search("ou=People,dc=example,dc=com",attr);
...
empID
. Aunque la interfaz envíe automáticamente el ID de empleado al usuario actual, un atacante podría enviar un valor alternativo como parte de una solicitud maliciosa. Como el código de este ejemplo ejecuta la consulta bajo un vínculo anónimo, devolverá la entrada de directorio para un ID de empleado válido, independientemente de la identidad del usuario autenticado actualmente.
...
CALL TRANSACTION 'SA38'.
...
MQOD-ALTERNATEUSERID
y MQOD-ALTERNATESECURITYID
del descriptor de objetos MQ.
...
10 MQOD.
** Alternate user identifier
15 MQOD-ALTERNATEUSERID PIC X(12).
** Alternate security identifier
15 MQOD-ALTERNATESECURITYID PIC X(40).
...
...
ACCEPT MQOD-ALTERNATEUSERID.
ACCEPT MQOD-ALTERNATESECURITYID.
CALL 'MQOPEN' USING HCONN, MQOD, OPTS, HOBJ, COMPOCODE REASON.
...
AUTHORITY-CHECK
se usa junto con la adición FOR USER
AUTHORITY_CHECK
con el usuario especificadoSU_RAUTH_CHECK_FOR_USER
con el usuario especificado
...
AUTHORITY-CHECK OBJECT 'S_TCODE' FOR USER v_user
ID 'TCD' FIELD 'SA38'.
IF sy-subrc = 0.
CALL TRANSACTION 'SA38'.
ELSE.
...
with sharing
: Se aplicarán las reglas de uso compartido de usuarios.without sharing
: Las reglas de uso compartido no se aplicarán.inherited sharing
: Se aplicarán las reglas de uso compartido de la clase que realiza la llamada. Cuando la clase que realiza la llamada no especifica una palabra clave de uso compartido, o cuando la propia clase es un punto de entrada, como un controlador de Visualforce, las reglas de uso compartido de usuarios se aplicarán de forma predeterminada.
public class MyClass1 {
public List<Contact> getAllTheSecrets() {
return Database.query('SELECT Name FROM Contact');
}
}
public without sharing class MyClass2 {
public List<Contact> getAllTheSecrets() {
return Database.query('SELECT Name FROM Contact');
}
}
public inherited sharing class MyClass3 {
public List<Contact> getAllTheSecrets() {
return Database.query('SELECT Name FROM Contact');
}
}
MyClass1
como MyClass2
son inseguras porque los registros se pueden recuperar sin la aplicación de reglas de uso compartido de usuarios.MyClass3
es más seguro porque impone reglas de uso compartido de forma predeterminada. Sin embargo, aún se puede otorgar acceso no autorizado si se llama la función getAllTheSecrets()
en una clase que declara explícitamente without sharing
.