Los problemas de validación y representación de entradas están causados por metacaracteres, codificaciones alternativas y representaciones numéricas. Los problemas de seguridad surgen de entradas en las que se confía. Estos problemas incluyen: «desbordamientos de búfer», ataques de «scripts de sitios», "SQL injection" y muchas otras acciones.
select()
de SimpleDB que busca facturas que coincidan con una categoría de productos especificada por el usuario. El usuario también puede especificar la columna por la que se ordenarán los resultados. Imagine que la aplicación ya ha autenticado y establecido correctamente el valor de customerID
antes de este segmento de código.
...
String customerID = getAuthenticatedCustomerID(customerName, customerCredentials);
...
AmazonSimpleDBClient sdbc = new AmazonSimpleDBClient(appAWSCredentials);
String query = "select * from invoices where productCategory = '"
+ productCategory + "' and customerID = '"
+ customerID + "' order by '"
+ sortColumn + "' asc";
SelectResult sdbResult = sdbc.select(new SelectRequest(query));
...
select * from invoices
where productCategory = 'Fax Machines'
and customerID = '12345678'
order by 'price' asc
productCategory
y price
no contienen caracteres de comillas simples. Sin embargo, si un usuario malintencionado proporciona la cadena "Fax Machines' or productCategory = \"
" para productCategory
y la cadena "\" order by 'price
" para sortColumn
, la consulta se convierte en lo siguiente:
select * from invoices
where productCategory = 'Fax Machines' or productCategory = "'
and customerID = '12345678'
order by '" order by 'price' asc
select * from invoices
where productCategory = 'Fax Machines'
or productCategory = "' and customerID = '12345678' order by '"
order by 'price' asc
customerID
y ver los registros de facturas que coinciden con 'Fax Machines'
de todos los clientes.customerID
que antecede a este segmento de código.
...
productCategory = this.getIntent().getExtras().getString("productCategory");
sortColumn = this.getIntent().getExtras().getString("sortColumn");
customerID = getAuthenticatedCustomerID(customerName, customerCredentials);
c = invoicesDB.query(Uri.parse(invoices), columns, "productCategory = '" + productCategory + "' and customerID = '" + customerID + "'", null, null, null, "'" + sortColumn + "'asc", null);
...
select * from invoices
where productCategory = 'Fax Machines'
and customerID = '12345678'
order by 'price' asc
productCategory
. Por lo tanto, la consulta solo presentará el comportamiento correcto si productCategory
y sortColumn
no contienen caracteres de comillas simples. Si un usuario malintencionado proporciona la cadena "Fax Machines' or productCategory = \"
" para productCategory
, y la cadena "\" order by 'price
" para sortColumn
, la consulta se convierte en:
select * from invoices
where productCategory = 'Fax Machines' or productCategory = "'
and customerID = '12345678'
order by '" order by 'price' asc
select * from invoices
where productCategory = 'Fax Machines'
or productCategory = "' and customerID = '12345678' order by '"
order by 'price' asc
customerID
y ver registros de facturas que coincidan con 'Fax Machines'
de todos los clientes.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.@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);
});
...
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();
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" metadata-complete="true">
...
<context-param>
<param-name>defaultHtmlEscape</param-name>
<param-value>false</param-value>
</context-param>
...
</web-app>
...
v_account = request->get_form_field( 'account' ).
v_reference = request->get_form_field( 'ref_key' ).
CONCATENATE `user = '` sy-uname `'` INTO cl_where.
IF v_account IS NOT INITIAL.
CONCATENATE cl_where ` AND account = ` v_account INTO cl_where SEPARATED BY SPACE.
ENDIF.
IF v_reference IS NOT INITIAL.
CONCATENATE cl_where "AND ref_key = `" v_reference "`" INTO cl_where.
ENDIF.
SELECT *
FROM invoice_items
INTO CORRESPONDING FIELDS OF TABLE itab_items
WHERE (cl_where).
...
SELECT *
FROM invoice_items
INTO CORRESPONDING FIELDS OF TABLE itab_items
WHERE user = sy-uname
AND account = <account>
AND ref_key = <reference>.
"abc` OR MANDT NE `+"
para v_reference y la cadena '1000' para v_account, entonces la consulta será de la siguiente forma:
SELECT *
FROM invoice_items
INTO CORRESPONDING FIELDS OF TABLE itab_items
WHERE user = sy-uname
AND account = 1000
AND ref_key = `abc` OR MANDT NE `+`.
OR MANDT NE `+`
hace que la cláusula WHERE
se evalúe siempre como verdadera porque el campo de cliente nunca puede ser igual al literal +, de manera que la consulta se hace lógicamente equivalente a la consulta mucho más simple:
SELECT * FROM invoice_items
INTO CORRESPONDING FIELDS OF TABLE itab_items.
invoice_items
, independientemente del usuario especificado.
PARAMETERS: p_street TYPE string,
p_city TYPE string.
Data: v_sql TYPE string,
stmt TYPE REF TO CL_SQL_STATEMENT.
v_sql = "UPDATE EMP_TABLE SET ".
"Update employee address. Build the update statement with changed details
IF street NE p_street.
CONCATENATE v_sql "STREET = `" p_street "`".
ENDIF.
IF city NE p_city.
CONCATENATE v_sql "CITY = `" p_city "`".
ENDIF.
l_upd = stmt->execute_update( v_sql ).
"ABC` SALARY = `1000000"
para el parámetro p_street, la aplicación permite que la base de datos se actualice con el ascenso de salario.
...
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var username:String = String(params["username"]);
var itemName:String = String(params["itemName"]);
var query:String = "SELECT * FROM items WHERE owner = " + username + " AND itemname = " + itemName;
stmt.sqlConnection = conn;
stmt.text = query;
stmt.execute();
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'; DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
owner
coincide con el nombre de usuario del usuario actualmente autenticado.
...
string userName = ctx.getAuthenticatedUserName();
string query = "SELECT * FROM items WHERE owner = '"
+ userName + "' AND itemname = '"
+ ItemName.Text + "'";
sda = new SqlDataAdapter(query, conn);
DataTable dt = new DataTable();
sda.Fill(dt);
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'); DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
Ejemplo 2:como alternativa, puede obtener un resultado similar con SQLite utilizando el siguiente código:
...
ctx.getAuthUserName(&userName); {
CString query = "SELECT * FROM items WHERE owner = '"
+ userName + "' AND itemname = '"
+ request.Lookup("item") + "'";
dbms.ExecuteSQL(query);
...
...
sprintf (sql, "SELECT * FROM items WHERE owner='%s' AND itemname='%s'", username, request.Lookup("item"));
printf("SQL to execute is: \n\t\t %s\n", sql);
rc = sqlite3_exec(db,sql, NULL,0, &err);
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'); DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
...
ACCEPT USER.
ACCEPT ITM.
MOVE "SELECT * FROM items WHERE owner = '" TO QUERY1.
MOVE "' AND itemname = '" TO QUERY2.
MOVE "'" TO QUERY3.
STRING
QUERY1, USER, QUERY2, ITM, QUERY3 DELIMITED BY SIZE
INTO QUERY
END-STRING.
EXEC SQL
EXECUTE IMMEDIATE :QUERY
END-EXEC.
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itm
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'; DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
...
<cfquery name="matchingItems" datasource="cfsnippets">
SELECT * FROM items
WHERE owner='#Form.userName#'
AND itemId=#Form.ID#
</cfquery>
...
SELECT * FROM items
WHERE owner = <userName>
AND itemId = <ID>;
Form.ID
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para Form.ID
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemId = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario hacker
introduce la cadena "hacker'); DELETE FROM items; --
" para Form.ID
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'hacker'
AND itemId = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'hacker'
AND itemId = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
...
final server = await HttpServer.bind('localhost', 18081);
server.listen((request) async {
final headers = request.headers;
final userName = headers.value('userName');
final itemName = headers.value('itemName');
final query = "SELECT * FROM items WHERE owner = '"
+ userName! + "' AND itemname = '"
+ itemName! + "'";
db.query(query);
}
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un atacante con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la siguiente consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'; DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
...
rawQuery := request.URL.Query()
username := rawQuery.Get("userName")
itemName := rawQuery.Get("itemName")
query := "SELECT * FROM items WHERE owner = " + username + " AND itemname = " + itemName + ";"
db.Exec(query)
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un atacante con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la siguiente consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'; DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un atacante escribe la cadena "name'; DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crean las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
...
String userName = ctx.getAuthenticatedUserName();
String itemName = request.getParameter("itemName");
String query = "SELECT * FROM items WHERE owner = '"
+ userName + "' AND itemname = '"
+ itemName + "'";
ResultSet rs = stmt.execute(query);
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'; DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
Example 1
a la plataforma Android.
...
PasswordAuthentication pa = authenticator.getPasswordAuthentication();
String userName = pa.getUserName();
String itemName = this.getIntent().getExtras().getString("itemName");
String query = "SELECT * FROM items WHERE owner = '"
+ userName + "' AND itemname = '"
+ itemName + "'";
SQLiteDatabase db = this.openOrCreateDatabase("DB", MODE_PRIVATE, null);
Cursor c = db.rawQuery(query, null);
...
...
var username = document.form.username.value;
var itemName = document.form.itemName.value;
var query = "SELECT * FROM items WHERE owner = " + username + " AND itemname = " + itemName + ";";
db.transaction(function (tx) {
tx.executeSql(query);
}
)
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'; DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
...
$userName = $_SESSION['userName'];
$itemName = $_POST['itemName'];
$query = "SELECT * FROM items WHERE owner = '$userName' AND itemname = '$itemName';";
$result = mysql_query($query);
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'; DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
procedure get_item (
itm_cv IN OUT ItmCurTyp,
usr in varchar2,
itm in varchar2)
is
open itm_cv for ' SELECT * FROM items WHERE ' ||
'owner = '''|| usr || '''' ||
' AND itemname = ''' || itm || '''';
end get_item;
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itm
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'; DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
...
userName = req.field('userName')
itemName = req.field('itemName')
query = "SELECT * FROM items WHERE owner = ' " + userName +" ' AND itemname = ' " + itemName +"';"
cursor.execute(query)
result = cursor.fetchall()
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'; DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
...
userName = getAuthenticatedUserName()
itemName = params[:itemName]
sqlQuery = "SELECT * FROM items WHERE owner = '#{userName}' AND itemname = '#{itemName}'"
rs = conn.query(sqlQuery)
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.
...
id = params[:id]
itemName = Mysql.escape_string(params[:itemName])
sqlQuery = "SELECT * FROM items WHERE id = #{userName} AND itemname = '#{itemName}'"
rs = conn.query(sqlQuery)
...
SELECT * FROM items WHERE id=<id> AND itemname = <itemName>;
itemName
aparentemente hemos evitado la vulnerabilidad de SQL Injection. Sin embargo, como Ruby no es un lenguaje estático, y a pesar de que esperamos que id
sea un entero de algún tipo, no tiene por qué ser necesariamente un número, ya que se asigna a partir de la entrada del usuario. Por lo tanto, si un usuario malintencionado logra cambiar el valor de id
a 1 OR id!=1--
, dado que no se comprueba si id
es realmente un número, la consulta SQL se convierte en:
SELECT * FROM items WHERE id=1 OR id!=1-- AND itemname = 'anyValue';
SELECT * FROM items WHERE id=1 OR id!=1;
id
es 1 o no, lo que por supuesto equivale a todo el contenido de la tabla.
def doSQLQuery(value:String) = Action.async { implicit request =>
val result: Future[Seq[User]] = db.run {
sql"select * from users where name = '#$value'".as[User]
}
...
}
SELECT * FROM users
WHERE name = <userName>
userName
no contiene un carácter de comilla simple. Si un atacante con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para userName
, la consulta se convertirá en lo siguiente:
SELECT * FROM users
WHERE name = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la siguiente consulta más simple:
SELECT * FROM users;
users
, independientemente del usuario especificado.owner
coincide con el nombre de usuario del usuario autenticado actualmente.
...
let queryStatementString = "SELECT * FROM items WHERE owner='\(username)' AND itemname='\(item)'"
var queryStatement: OpaquePointer? = nil
if sqlite3_prepare_v2(db, queryStatementString, -1, &queryStatement, nil) == SQLITE_OK {
if sqlite3_step(queryStatement) == SQLITE_ROW {
...
}
}
...
SELECT * FROM items
WHERE owner = '<userName>'
AND itemname = '<itemName>'
itemName
no contiene un carácter de comilla simple. Si un atacante con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la siguiente consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'); DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
...
username = Session("username")
itemName = Request.Form("itemName")
strSQL = "SELECT * FROM items WHERE owner = '"& userName &"' AND itemname = '" & itemName &"'"
objRecordSet.Open strSQL, strConnect, adOpenDynamic, adLockOptimistic, adCmdText
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.Example 1
. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name'; DELETE FROM items; --
" para itemName
, la consulta se convertirá en las dos consultas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. Si un usuario malintencionado escribe la cadena "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", se crearán las tres instrucciones válidas siguientes:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
owner
coincide con el nombre de usuario del usuario actualmente autenticado.
...
string userName = ctx.getAuthenticatedUserName();
string queryString = "SELECT * FROM items WHERE owner = '"
+ userName + "' AND itemname = '"
+ ItemName.Text + "'";
SimpleQuery<Item> queryObject = new SimpleQuery(queryString);
Item[] items = (Item[])queryObject.Execute(query);
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
no contiene un carácter de comilla simple. Si un usuario malintencionado con el nombre de usuario wiley
introduce la cadena "name' OR 'a'='a
" para itemName
, la consulta se convertirá en lo siguiente:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
hace que la cláusula where siempre se evalúe como true, por lo que lógicamente la consulta pasará a ser equivalente a la consulta más simple:
SELECT * FROM items;
items
, independientemente del propietario especificado.