null
antes de comprobar si es null
o no. Los errores de desreferencia tras la comprobación se producen cuando un programa realiza una comprobación explícita de null
y procede a desreferenciar el puntero cuando se sabe que es null
. Los errores de este tipo son normalmente el resultado de errores de escritura o descuidos del programador. Los errores de desreferencia tras el almacenamiento se producen cuando un programa establece de forma explícita un puntero en null
y luego lo desreferencia. Con frecuencia, el error es el resultado de que un programador inicialice una variable en null
cuando se declara.foo
es null
y por eso lo desreferencia erróneamente. Si foo
es null
cuando se comprueba en la instrucción if
, se produce una desreferencia null
, lo que provoca una excepción de puntero nulo.Ejemplo 2: En el código siguiente, el programador presupone que la variable
if (foo is null) {
foo.SetBar(val);
...
}
foo
no es null
y confirma esta suposición eliminando la referencia del objeto. Sin embargo, este contradice posteriormente esta suposición al comprobar si foo
es null
. Si foo
puede ser null
al comprobarlo en relación con la instrucción if
, también puede ser null
cuando se elimina su referencia, lo que puede provocar una excepción de puntero nulo. O bien la desreferencia no es segura o la comprobación posterior es innecesaria.Ejemplo 3: En el código siguiente, el programador establece explícitamente la variable
foo.SetBar(val);
...
if (foo is not null) {
...
}
foo
en null
. A continuación, el programador desreferencia foo
antes de comprobar si en el objeto hay un valor null
.
Foo foo = null;
...
foo.SetBar(val);
...
}
null
antes de comprobar si es null
o no. Los errores de desreferencia tras la comprobación se producen cuando un programa realiza una comprobación explícita de null
y procede a desreferenciar el puntero cuando se sabe que es null
. Los errores de este tipo son normalmente el resultado de errores de escritura o descuidos del programador. Los errores de desreferencia tras el almacenamiento se producen cuando un programa establece de forma explícita un puntero en null
y luego lo desreferencia. Con frecuencia, el error es el resultado de que un programador inicialice una variable en null
cuando se declara.ptr
no es NULL
. Esta suposición se hace explícita cuando el programador desreferencia el puntero. Esta suposición luego queda contradicha cuando el programador contrasta ptr
y NULL
. Si ptr
puede ser NULL
al comprobarla en la instrucción if
, entonces también puede ser NULL
cuando se desreferencia y podría ocasionar un error de segmentación.Ejemplo 2: En el código siguiente, el programador confirma que la variable
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
es NULL
y por eso lo desreferencia erróneamente. Si ptr
es NULL
cuando se comprueba en la instrucción if
, entonces se produce una desreferencia de null
que provocará un error de segmentación.Ejemplo 3: En el código siguiente, el programador olvida que la cadena
if (ptr == null) {
ptr->field = val;
...
}
'\0'
es en realidad 0 o NULL
; por lo tanto, puede desreferenciar un puntero nulo y provocar un fallo de segmentación.Ejemplo 4: En el código siguiente, el programador establece explícitamente la variable
if (ptr == '\0') {
*ptr = val;
...
}
ptr
en NULL
. A continuación, el programador desreferencia ptr
antes de comprobar si en el objeto hay un valor null
.
*ptr = NULL;
...
ptr->field = val;
...
}
null
, pero continúa eliminando la referencia del objeto cuando se detecta que es null
. Los errores de este tipo son normalmente el resultado de errores de escritura o descuidos del programador.foo
es null
y por eso lo desreferencia erróneamente. Si foo
es null
cuando se compruebe en la instrucción if
, se producirá una desreferencia null
, provocando una excepción de puntero nulo.
if (foo == null) {
foo.setBar(val);
...
}
Content-Disposition
mal configurado que permite al atacante controlar los encabezados Content-Type
o Content-Disposition
en la respuesta HTTP, o la aplicación de destino incluye un encabezado Content-Type
que no se representa de forma predeterminada en el explorador.ContentNegotiationManager
de Spring Web MVC para producir dinámicamente diferentes formatos de respuesta, cumple las condiciones necesarias para hacer posible un ataque RFD.ContentNegotiationManager
está configurada para decidir el formato de respuesta en función de la extensión de la ruta de acceso de la solicitud y para utilizar Java Activation Framework (JAF) para encontrar un encabezado Content-Type
que se adapte mejor al formato solicitado por el cliente. También permite al cliente especificar el tipo de contenido de la respuesta mediante el tipo de medio que se envía en el encabezado Accept
de la solicitud.Ejemplo 2: En el siguiente ejemplo, la aplicación está configurada para permitir que el encabezado
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="true" />
<property name="useJaf" value="true" />
</bean>
Accept
de la solicitud determine el tipo de contenido de la respuesta:
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="ignoreAcceptHeader" value="false" />
</bean>
ContentNegotiationManagerFactoryBean
en Spring 4.2.1 son:useJaf
: true
favorPathExtension
: true
ignoreAcceptHeader
: false
Example 1
permite a un atacante crear una URL malintencionada, como:ContentNegotiationManager
utilizará Java Activation Framework (si el archivo activation.jar se encuentra en el objeto classpath) para intentar resolver el tipo de medio para la extensión de archivo dada y establecer el encabezado ContentType
de la respuesta en consecuencia. En este ejemplo, la extensión de archivo es "bat", lo que da como resultado un encabezado Content-Type
de application/x-msdownload
(aunque el valor exacto de Content-Type
puede variar según el sistema operativo del servidor y la configuración de JAF). Como consecuencia, una vez que la víctima visita esta dirección URL malintencionada, su máquina iniciará automáticamente la descarga de un archivo ".bat" que con contenido controlado por el atacante. Si luego se ejecuta este archivo, la máquina de la víctima ejecutará cualquier comando especificado por la carga útil del atacante.
...
host_name = request->get_form_field( 'host' ).
CALL FUNCTION 'FTP_CONNECT'
EXPORTING
USER = user
PASSWORD = password
HOST = host_name
RFC_DESTINATION = 'SAPFTP'
IMPORTING
HANDLE = mi_handle
EXCEPTIONS
NOT_CONNECTED = 1
OTHERS = 2.
...
int rPort = Int32.Parse(Request.Item("rPort"));
...
IPEndPoint endpoint = new IPEndPoint(address,rPort);
socket = new Socket(endpoint.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
socket.Connect(endpoint);
...
...
char* rPort = getenv("rPort");
...
serv_addr.sin_port = htons(atoi(rPort));
if (connect(sockfd,&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
...
...
ACCEPT QNAME.
EXEC CICS
READQ TD
QUEUE(QNAME)
INTO(DATA)
LENGTH(LDATA)
END-EXEC.
...
ServerSocket
de Java y utiliza un número de puerto que se lee de una solicitud HTTP para crear un socket.
<cfobject action="create" type="java" class="java.net.ServerSocket" name="myObj">
<cfset srvr = myObj.init(#url.port#)>
<cfset socket = srvr.accept()>
Passing user input to objects imported from other languages can be very dangerous.
final server = await HttpServer.bind('localhost', 18081);
server.listen((request) async {
final remotePort = headers.value('port');
final serverSocket = await ServerSocket.bind(host, remotePort as int);
final httpServer = HttpServer.listenOn(serverSocket);
});
...
func someHandler(w http.ResponseWriter, r *http.Request){
r.parseForm()
deviceName := r.FormValue("device")
...
syscall.BindToDevice(fd, deviceName)
}
String remotePort = request.getParameter("remotePort");
...
ServerSocket srvr = new ServerSocket(remotePort);
Socket skt = srvr.accept();
...
WebView
.
...
WebView webview = new WebView(this);
setContentView(webview);
String url = this.getIntent().getExtras().getString("url");
webview.loadUrl(url);
...
var socket = new WebSocket(document.URL.indexOf("url=")+20);
...
char* rHost = getenv("host");
...
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)rHost, 80, &readStream, &writeStream);
...
<?php
$host=$_GET['host'];
$dbconn = pg_connect("host=$host port=1234 dbname=ticketdb");
...
$result = pg_prepare($dbconn, "my_query", 'SELECT * FROM pricelist WHERE name = $1');
$result = pg_execute($dbconn, "my_query", array("ticket"));
?>
...
filename := SUBSTR(OWA_UTIL.get_cgi_env('PATH_INFO'), 2);
WPG_DOCLOAD.download_file(filename);
...
host=request.GET['host']
dbconn = db.connect(host=host, port=1234, dbname=ticketdb)
c = dbconn.cursor()
...
result = c.execute('SELECT * FROM pricelist')
...
def controllerMethod = Action { request =>
val result = request.getQueryString("key").map { key =>
val user = db.getUser()
cache.set(key, user)
Ok("Cached Request")
}
Ok("Done")
}
...
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
var inputStream : NSInputStream?
var outputStream : NSOutputStream?
...
var readStream : Unmanaged<CFReadStream>?
var writeStream : Unmanaged<CFWriteStream>?
let rHost = getQueryStringParameter(url.absoluteString, "host")
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, rHost, 80, &readStream, &writeStream);
...
}
func getQueryStringParameter(url: String?, param: String) -> String? {
if let url = url, urlComponents = NSURLComponents(string: url), queryItems = (urlComponents.queryItems as? [NSURLQueryItem]) {
return queryItems.filter({ (item) in item.name == param }).first?.value!
}
return nil
}
...
...
Begin MSWinsockLib.Winsock tcpServer
...
Dim Response As Response
Dim Request As Request
Dim Session As Session
Dim Application As Application
Dim Server As Server
Dim Port As Variant
Set Response = objContext("Response")
Set Request = objContext("Request")
Set Session = objContext("Session")
Set Application = objContext("Application")
Set Server = objContext("Server")
Set Port = Request.Form("port")
...
tcpServer.LocalPort = Port
tcpServer.Accept
...
@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {
super("callback");
}
}
GET /api/latest.json?callback=myCallbackFunction
, el método de controlador generará una respuesta como:
HTTP/1.1 200 Ok
Content-Type: application/json; charset=utf-8
Date: Tue, 12 Dec 2017 16:16:04 GMT
Server: nginx/1.12.1
Content-Length: 225
Connection: Close
myCallbackFunction({<json>})
Script
para cargar la respuesta desde el punto final JSONP, lo que provocará la ejecución de la función myCallbackFunction
. Un atacante podría usar un nombre de devolución de llamada diferente e interactuar con el DOM. Por ejemplo, podría usarse opener.document.body.someElemnt.firstChild.nextElementSibling.submit
para colocar un formulario en la página de destino y enviarlo.
def myJSONPService(callback: String) = Action {
val json = getJSONToBeReturned()
Ok(Jsonp(callback, json))
}
GET /api/latest.json?callback=myCallbackFunction
, el método de controlador descrito en Example 1
generará una respuesta como:
HTTP/1.1 200 Ok
Content-Type: application/json; charset=utf-8
Date: Tue, 12 Dec 2017 16:16:04 GMT
Server: nginx/1.12.1
Content-Length: 225
Connection: Close
myCallbackFunction({<json>})
Script
para cargar la respuesta desde el punto final JSONP, lo que provocará la ejecución de la función myCallbackFunction
. Un atacante podría usar un nombre de devolución de llamada diferente e interactuar con el DOM. Por ejemplo, podría usarse opener.document.body.someElemnt.firstChild.nextElementSibling.submit
para colocar un formulario en la página de destino y enviarlo.sanitizeValue
a false
permite una entrada insegura que conduce a vulnerabilidades, tales como Cross-Site Scripting.sanitizeValue
determina si ejecutar una corrección de HTML cuando el valor se aplica a la revisión de HTML. La entrada puede provenir directamente de un usuario y aun así se puede considerar insegura. La propiedad de sanitizeValue
puede configurarse a false
por múltiples razones, tales como permitir la entrada de caracteres adicionales. Sin embargo, hacerlo puede permitir de forma inconsciente que un usuario no seguro haga alguna entrada que se vaya a ejecutar en el código. Es más seguro configurar la propiedad de sanitizeValue
a true
, lo que se da como predeterminado.sanitizeValue
en el RichTextEditor
de SAPUI5 a false
:
new RichTextEditor({
sanitizeValue: false,
value: input
}).placeAt("moreContent");
...
lv_uri = request->get_form_field( 'uri' ).
CALL METHOD cl_http_utility=>set_request_uri
EXPORTING
request = lo_request
uri = lv_uri.
...
http
o https
, como:
...
PageReference ref = ApexPages.currentPage();
Map<String,String> params = ref.getParameters();
HttpRequest req = new HttpRequest();
req.setEndpoint(params.get('url'));
HTTPResponse res = new Http().send(req);
http
o https
, como:
string url = Request.Form["url"];
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(url);
http
o https
, como:
char *url = maliciousInput();
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
CURLcode res = curl_easy_perform(curl);
http
o https
, como:
...
final server = await HttpServer.bind('localhost', 18081);
server.listen((request) async {
final headers = request.headers;
final url = headers.value('url');
final client = IOClient();
final response = await client.get(Uri.parse(url!));
...
}
http
o https
, como:
url := request.Form.Get("url")
res, err =: http.Get(url)
...
http
o https
, como:
String url = request.getParameter("url");
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response1 = httpclient.execute(httpGet);
http
o https
, como:
var http = require('http');
var url = require('url');
function listener(request, response){
var request_url = url.parse(request.url, true)['query']['url'];
http.request(request_url)
...
}
...
http.createServer(listener).listen(8080);
...
http
o https
, como:
val url: String = request.getParameter("url")
val httpclient: CloseableHttpClient = HttpClients.createDefault()
val httpGet = HttpGet(url)
val response1: CloseableHttpResponse = httpclient.execute(httpGet)
http
o https
, como:
$url = $_GET['url'];
$c = curl_init();
curl_setopt($c, CURLOPT_POST, 0);
curl_setopt($c,CURLOPT_URL,$url);
$response=curl_exec($c);
curl_close($c);
http
o https
, como:
url = request.GET['url']
handle = urllib.urlopen(url)
http
o https
, como:
url = req['url']
Net::HTTP.get(url)
http
o https
, como:
def getFile(url: String) = Action { request =>
...
val url = request.body.asText.getOrElse("http://google.com")
ws.url(url).get().map { response =>
Ok(s"Request sent to $url")
}
...
}
http
o https
, como:
// Set up the context data
VelocityContext context = new VelocityContext();
context.put( "name", user.name );
// Load the template
String template = getUserTemplateFromRequestBody(request);
RuntimeServices runtimeServices = RuntimeSingleton.getRuntimeServices();
StringReader reader = new StringReader(template);
SimpleNode node = runtimeServices.parse(reader, "myTemplate");
template = new Template();
template.setRuntimeServices(runtimeServices);
template.setData(node);
template.initDocument();
// Render the template with the context data
StringWriter sw = new StringWriter();
template.merge( context, sw );
Example 1
utiliza Velocity
como motor de plantillas. En el caso de ese motor, un atacante podría enviar la siguiente plantilla para ejecutar comandos arbitrarios en el servidor:
$name.getClass().forName("java.lang.Runtime").getRuntime().exec(<COMMAND>)
app.get('/', function(req, res){
var template = _.template(req.params['template']);
res.write("<html><body><h2>Hello World!</h2>" + template() + "</body></html>");
});
Example 1
se utiliza Underscore.js
como motor de plantillas en una aplicación Node.js
. En el caso de ese motor, un atacante podría enviar la siguiente plantilla para ejecutar comandos arbitrarios en el servidor:
<% cp = process.mainModule.require('child_process');cp.exec(<COMMAND>); %>
Jinja2
.
from django.http import HttpResponse
from jinja2 import Template as Jinja2_Template
from jinja2 import Environment, DictLoader, escape
def process_request(request):
# Load the template
template = request.GET['template']
t = Jinja2_Template(template)
name = source(request.GET['name'])
# Render the template with the context data
html = t.render(name=escape(name))
return HttpResponse(html)
Example 1
utiliza Jinja2
como motor de plantillas. Para ese motor, un atacante podría enviar la siguiente plantilla a fin de leer archivos arbitrarios del servidor:Ejemplo 2: El siguiente ejemplo ilustra cómo recuperar una plantilla de una solicitud HTTP y cómo se procesa mediante el motor de plantillas
template={{''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}}
Django
.
from django.http import HttpResponse
from django.template import Template, Context, Engine
def process_request(request):
# Load the template
template = source(request.GET['template'])
t = Template(template)
user = {"name": "John", "secret":getToken()}
ctx = Context(locals())
html = t.render(ctx)
return HttpResponse(html)
Example 2
utiliza Django
como motor de plantillas. Para ese motor, un atacante no podrá ejecutar comandos arbitrarios, pero podrá acceder a todos los objetos del contexto de plantillas. En este ejemplo, hay un token secreto disponible en el contexto que podría filtrar el atacante.
<http auto-config="true">
...
<session-management session-fixation-protection="none"/>
</http>
Example 1
, el atacante logra esto mediante un método directo obvio que no resulta adecuado para ataques donde los sitios web son menos populares. Sin embargo, no hay que bajar la guardia, ya que los atacantes disponen de muchas herramientas para eludir las limitaciones de este vector de ataque. La técnica más habitual que utilizan los atacantes consiste en aprovechar las vulnerabilidades Cross-Site Scripting o de división de respuestas HTTP en el sitio de destino [1]. Al engañar a la víctima para que envíe una solicitud malintencionada a una aplicación vulnerable que muestra JavaScript u otro código en su explorador, el atacante puede crear una cookie que provocará que la víctima vuelva a utilizar el identificador de sesión controlado por el atacante.bank.example.com
y recipes.example.com
, una vulnerabilidad en una aplicación puede permitir que un atacante establezca una cookie con un identificador de sesión fijo, que se utilizará en todas las interacciones con cualquier aplicación que se encuentre en el dominio example.com
[2].use_strict_mode
en las cookies de sesión.
ini_set("session.use_strict_mode", "0");
@SessionAttributes
indicará a Spring que replique los cambios realizados en los atributos de modelo en el objeto de sesión. Si un atacante puede almacenar valores arbitrarios en un atributo de modelo, estos cambios se replicarán en el objeto de sesión, donde la aplicación confiaría en ellos. Si el atributo de sesión se inicializa con datos de confianza que el usuario no debería ser capaz de modificar, el atacante podría llevar a cabo un ataque Session Puzzling y abusar de la lógica de la aplicación.
@Controller
@SessionAttributes("user")
public class HomeController {
...
@RequestMapping(value= "/auth", method=RequestMethod.POST)
public String authHandler(@RequestParam String username, @RequestParam String password, RedirectAttributes attributes, Model model) {
User user = userService.findByNamePassword(username, password);
if (user == null) {
// Handle error
...
} else {
// Handle success
attributes.addFlashAttribute("user", user);
return "redirect:home";
}
}
...
}
User
desde la sesión, ya que la clase tiene la anotación @SessionAttributes("user")
y la utiliza para comprobar la pregunta de restablecimiento de la contraseña.
@Controller
@SessionAttributes("user")
public class ResetPasswordController {
@RequestMapping(value = "/resetQuestion", method = RequestMethod.POST)
public String resetQuestionHandler(@RequestParam String answerReset, SessionStatus status, User user, Model model) {
if (!user.getAnswer().equals(answerReset)) {
// Handle error
...
} else {
// Handle success
...
}
}
}
user
desde la sesión en la que se almacenó durante el proceso de inicio de sesión. No obstante, Spring comprobará la solicitud e intentará enlazar sus datos con la instancia user
del modelo. Si la solicitud recibida contiene datos que se pueden enlazar con la clase User
, Spring combinará los datos recibidos con el atributo de sesión del usuario. Se puede abusar de este escenario mediante el envío de una respuesta arbitraria en el parámetro de consulta answerReset
y del mismo valor para reemplazar el valor almacenado en la sesión. De este modo, el atacante podría establecer una nueva contraseña arbitraria para usuarios aleatorios.
...
taintedConnectionStr = request->get_form_field( 'dbconn_name' ).
TRY.
DATA(con) = cl_sql_connection=>get_connection( `R/3*` && taintedConnectionStr ).
...
con->close( ).
CATCH cx_sql_exception INTO FINAL(exc).
...
ENDTRY.
...
sethostid(argv[1]);
...
sethostid()
, es posible que los usuarios sin privilegios puedan llamar al programa. El código de este ejemplo permite a la entrada de usuario controlar directamente el valor de un parámetro del sistema. Si un atacante especifica un valor malicioso para el ID de host, este puede identificar incorrectamente el equipo en la red o provocar otro comportamiento imprevisto.
...
ACCEPT OPT1.
ACCEPT OPT2
COMPUTE OPTS = OPT1 + OPT2.
CALL 'MQOPEN' USING HCONN, OBJECTDESC, OPTS, HOBJ, COMPOCODE REASON.
...
...
<cfset code = SetProfileString(IniPath,
Section, "timeout", Form.newTimeout)>
...
Form.newTimeout
se utiliza para especificar un tiempo de espera, un usuario malintencionado puede ejecutar un ataque de denegación de servicio (DoS, Denial of Service) contra la aplicación especificando un número lo suficientemente grande.
...
catalog := request.Form.Get("catalog")
path := request.Form.Get("path")
os.Setenv(catalog, path)
...
HttpServletRequest
y la establece como el catálogo activo para una Connection
de base de datos.
...
conn.setCatalog(request.getParamter("catalog"));
...
http.IncomingMessage
y la utiliza para establecer marcas de línea de comandos de V8 adicionales.
var v8 = require('v8');
...
var flags = url.parse(request.url, true)['query']['flags'];
...
v8.setFlagsFromString(flags);
...
<?php
...
$table_name=$_GET['catalog'];
$retrieved_array = pg_copy_to($db_connection, $table_name);
...
?>
...
catalog = request.GET['catalog']
path = request.GET['path']
os.putenv(catalog, path)
...
Connection
de base de datos.
def connect(catalog: String) = Action { request =>
...
conn.setCatalog(catalog)
...
}
...
sqlite3(SQLITE_CONFIG_LOG, user_controllable);
...
Request
y la establece como el catálogo activo para una base de datos Connection
.
...
Dim conn As ADODB.Connection
Set conn = New ADODB.Connection
Dim rsTables As ADODB.Recordset
Dim Catalog As New ADOX.Catalog
Set Catalog.ActiveConnection = conn
Catalog.Create Request.Form("catalog")
...
myModule.config(function($compileProvider){
$compileProvider.imgSrcSanitizationWhitelist(userInput);
});
/^(http(s)?|javascript):.*/
, la aplicación permitirá el uso de JavaScript en línea en las direcciones URL de origen de la imagen, lo que puede provocar ataques de scripts entre sitios.ProcessWorkitemRequest.setAction()
.
void processRequest() {
String workItemId = ApexPages.currentPage().getParameters().get('Id');
String action = ApexPages.currentPage().getParameters().get('Action');
Approval.ProcessWorkitemRequest req = new Approval.ProcessWorkitemRequest();
req.setWorkitemId(workItemId);
req.setAction(action);
Approval.ProcessResult res = Approval.process(req);
...
}
var hash = window.location.hash;
var myStartSymbol = decodeURIComponent(hash.substring(1, hash.length));
myModule.config(function($interpolateProvider){
$interpolateProvider.startSymbol(myStartSymbol);
});
clientaccesspolicy.xml
en el host. Sin embargo, es necesario tener cuidado al cambiar la configuración porque una directiva entre dominios demasiado permisiva permitirá que aplicaciones malintencionadas se comuniquen con el servicio víctima de manera inadecuada, lo que provocará suplantación de identidad, robo de datos, retransmisión y otros ataques.clientaccesspolicy.xml
con un carácter comodín para especificar los dominios con los que el servicio se puede comunicar.
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
*
como el valor de los elementos domain
, atributo uri
indica que las aplicaciones de cualquier dominio pueden conectarse al servicio.
...
public String inputValue {
get { return inputValue; }
set { inputValue = value; }
}
...
String queryString = 'SELECT Id FROM Contact WHERE (IsDeleted = false AND Name like \'%' + inputValue + '%\')';
result = Database.query(queryString);
...
SELECT Id FROM Contact WHERE (IsDeleted = false AND Name like '%inputValue%')
inputValue
no contiene un carácter de comilla simple. Si un usuario malintencionado introduce la cadena name') OR (Name like '%
para inputValue
, entonces la consulta será de la siguiente forma:
SELECT Id FROM Contact WHERE (IsDeleted = false AND Name like '%name') OR (Name like '%%')
name') OR (Name like '%
, la cláusula where utiliza la condición LIKE '%%'
, lo que hace que la consulta muestre todos los valores de ID posibles, ya que se convierte lógicamente en el equivalente a esta consulta, mucho más simple:
SELECT Id FROM Contact WHERE ... OR (Name like '%%')
...
public String inputValue {
get { return inputValue; }
set { inputValue = value; }
}
...
String queryString = 'Name LIKE \'%' + inputValue + '%\'';
String searchString = 'Acme';
String searchQuery = 'FIND :searchString IN ALL FIELDS RETURNING Contact (Id WHERE ' + queryString + ')';
List<List<SObject>> results = Search.query(searchQuery);
...
String searchQuery = 'FIND :searchString IN ALL FIELDS RETURNING Contact (Id WHERE Name LIKE '%' + inputValue + '%')';
inputValue
no contiene un carácter de comilla simple. Si un usuario malintencionado introduce la cadena 1%' OR Name LIKE '
para inputValue
, entonces la consulta será de la siguiente forma:
String searchQuery = 'FIND :searchString IN ALL FIELDS RETURNING Contact (Id WHERE Name LIKE '%1%' OR Name LIKE '%%')';
OR Name like '%%'
, la cláusula where utiliza la condición LIKE '%%'
, lo que hace que la consulta muestre todos los registros que contienen la frase 'map', ya que se convierte lógicamente en el equivalente a esta consulta, mucho más simple:
FIND 'map*' IN ALL FIELDS RETURNING Contact (Id WHERE Name LIKE '%%')
String beans = getBeanDefinitionFromUser();
GenericApplicationContext ctx = new GenericApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new UrlResource(beans));
ctx.refresh();
ACTUATOR
pueden acceder a ellos.
management.security.enabled=false
endpoints.health.sensitive=false
@Component
public class CustomEndpoint implements Endpoint<List<String>> {
public String getId() {
return "customEndpoint";
}
public boolean isEnabled() {
return true;
}
public boolean isSensitive() {
return false;
}
public List<String> invoke() {
// Custom logic to build the output
...
}
}