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.
nresp = packet_get_int();
if (nresp > 0) {
response = xmalloc(nresp*sizeof(char*));
for (i = 0; i < nresp; i++)
response[i] = packet_get_string(NULL);
}
nresp
tiene el valor 1073741824
y sizeof(char*)
tiene su valor típico de 4
, el resultado de la operación nresp*sizeof(char*)
se desbordaría y el argumento de xmalloc()
sería 0
. La mayor parte de las implementaciones de malloc()
permitirán la asignación de un búfer de 0 bytes, lo que hará que las iteraciones de bucle posteriores desborden el búfer de montón response
.
char* processNext(char* strm) {
char buf[512];
short len = *(short*) strm;
strm += sizeof(len);
if (len <= 512) {
memcpy(buf, strm, len);
process(buf);
return strm + len;
} else {
return -1;
}
}
512
, la entrada no se procesará. El problema es que len
es un entero con signo, de modo que la comprobación en relación con la longitud máxima de la estructura se realiza con enteros con signo, pero len
se convierte en un entero sin signo para la llamada a memcpy()
. Si len
es negativo, parecerá que la estructura tiene un tamaño adecuado (se tomará la rama if
), pero la cantidad de memoria copiada por memcpy()
será bastante grande y el atacante podrá desbordar la pila con los datos de strm
.
77 accept-in PIC 9(10).
77 num PIC X(4) COMP-5. *> native 32-bit unsigned integer
77 mem-size PIC X(4) COMP-5.
...
ACCEPT accept-in
MOVE accept-in TO num
MULTIPLY 4 BY num GIVING mem-size
CALL "CBL_ALLOC_MEM" USING
mem-pointer
BY VALUE mem-size
BY VALUE 0
RETURNING status-code
END-CALL
num
tiene el valor 1073741824
, entonces el resultado de la operación MULTIPLY 4 BY num
desborda, y el argumento mem-size
a malloc()
será 0
. La mayoría de implementaciones de malloc()
ayudarán a la asignación de un búfer de 0 byte, lo que provocará que el búfer de salto mem-pointer
se desborde en declaraciones posteriores.uint256
, significa que se almacena como número sin signo de 256 bits que va de 0 a 2^256-1. Si una operación aritmética da como resultado un número mayor que el límite superior, se produce un desbordamiento por encima y el resto se suma al valor inicial (0). Si una operación aritmética hace que el número sea inferior al límite inferior, se produce un desbordamiento inferior y el resto se resta del valor más grande (2^256-1).uint256
mediante una operación aritmética que puede provocar un desbordamiento superior/inferior de enteros y afectar a indicadores de forma involuntaria en el mapa.
contract overflow {
mapping(uint256 => uint256) map;
function init(uint256 k, uint256 v) public {
map[k] -= v;
}
}
String arg = request.getParameter("arg");
...
Intent intent = new Intent();
...
intent.setClassName(arg);
ctx.startActivity(intent);
...
Intent
anidado de una entrada externa para iniciar una actividad, iniciar un servicio o entregar una transmisión puede permitir que un atacante lance arbitrariamente componentes internos de la aplicación, controle el comportamiento de un componente interno o acceda indirectamente a datos protegidos de un proveedor de contenido a través de concesiones de permisos.Intent
arbitrario anidado en el paquete de extras de un Intent
proporcionado externamente.Intent
arbitrario para iniciar un componente llamando a startActivity
, startService
o sendBroadcast
.Intent
anidado de una fuente externa y usa ese Intent
para iniciar una actividad.
...
Intent nextIntent = (Intent) getIntent().getParcelableExtra("next-intent");
startActivity(nextIntent);
...
username
y password
al archivo JSON ubicado en C:\user_info.json
:
...
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter writer = new JsonTextWriter(sw))
{
writer.Formatting = Formatting.Indented;
writer.WriteStartObject();
writer.WritePropertyName("role");
writer.WriteRawValue("\"default\"");
writer.WritePropertyName("username");
writer.WriteRawValue("\"" + username + "\"");
writer.WritePropertyName("password");
writer.WriteRawValue("\"" + password + "\"");
writer.WriteEndObject();
}
File.WriteAllText(@"C:\user_info.json", sb.ToString());
JsonWriter.WriteRawValue()
, los datos que no son de confianza de username
y password
no se validarán para omitir caracteres especiales relacionados con JSON. Esto permite a un usuario introducir claves JSON de forma arbitraria, posiblemente cambiando la estructura del JSON serializado. En este ejemplo, si el usuario sin privilegios mallory
con la contraseña Evil123!
fuese a agregar ","role":"admin
a su nombre de usuario al introducirlo en la solicitud que establece el valor de la variable username
, el JSON resultante guardado en C:\user_info.json
sería:
{
"role":"default",
"username":"mallory",
"role":"admin",
"password":"Evil123!"
}
Dictionary
con JsonConvert.DeserializeObject()
de este modo:
String jsonString = File.ReadAllText(@"C:\user_info.json");
Dictionary<string, string> userInfo = JsonConvert.DeserializeObject<Dictionary<string, strin>>(jsonString);
username
, password
y role
del objeto Dictionary
serían mallory
, Evil123!
y admin
, respectivamente. Sin más comprobaciones de que los valores JSON deserializados son válidos, la aplicación asignará de forma incorrecta privilegios de "admin" al usuario mallory
.username
y password
al archivo JSON ubicado en ~/user_info.json
:
...
func someHandler(w http.ResponseWriter, r *http.Request){
r.parseForm()
username := r.FormValue("username")
password := r.FormValue("password")
...
jsonString := `{
"username":"` + username + `",
"role":"default"
"password":"` + password + `",
}`
...
f, err := os.Create("~/user_info.json")
defer f.Close()
jsonEncoder := json.NewEncoder(f)
jsonEncoder.Encode(jsonString)
}
username
y password
no se validan a fin de omitir caracteres especiales relacionados con JSON. Esto permite a un usuario introducir claves JSON de forma arbitraria, lo cual posiblemente pueda cambiar la estructura del archivo JSON serializado. En este ejemplo, si el usuario sin privilegios mallory
con la contraseña Evil123!
anexó ","role":"admin
cuando ingresó su nombre de usuario, el archivo JSON resultante guardado en ~/user_info.json
sería el siguiente:
{
"username":"mallory",
"role":"default",
"password":"Evil123!",
"role":"admin"
}
mallory
privilegios de "admin".username
y password
al archivo JSON ubicado en ~/user_info.json
:
...
JsonFactory jfactory = new JsonFactory();
JsonGenerator jGenerator = jfactory.createJsonGenerator(new File("~/user_info.json"), JsonEncoding.UTF8);
jGenerator.writeStartObject();
jGenerator.writeFieldName("username");
jGenerator.writeRawValue("\"" + username + "\"");
jGenerator.writeFieldName("password");
jGenerator.writeRawValue("\"" + password + "\"");
jGenerator.writeFieldName("role");
jGenerator.writeRawValue("\"default\"");
jGenerator.writeEndObject();
jGenerator.close();
JsonGenerator.writeRawValue()
, los datos que no son de confianza de username
y password
no se validarán para omitir caracteres especiales relacionados con JSON. Esto permite a un usuario introducir claves JSON de forma arbitraria, posiblemente cambiando la estructura del JSON serializado. En este ejemplo, si el usuario sin privilegios mallory
con la contraseña Evil123!
fuese a agregar ","role":"admin
a su nombre de usuario al introducirlo en la solicitud que establece el valor de la variable username
, el JSON resultante guardado en ~/user_info.json
sería:
{
"username":"mallory",
"role":"admin",
"password":"Evil123!",
"role":"default"
}
HashMap
con JsonParser
de Jackson de este modo:
JsonParser jParser = jfactory.createJsonParser(new File("~/user_info.json"));
while (jParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jParser.getCurrentName();
if ("username".equals(fieldname)) {
jParser.nextToken();
userInfo.put(fieldname, jParser.getText());
}
if ("password".equals(fieldname)) {
jParser.nextToken();
userInfo.put(fieldname, jParser.getText());
}
if ("role".equals(fieldname)) {
jParser.nextToken();
userInfo.put(fieldname, jParser.getText());
}
if (userInfo.size() == 3)
break;
}
jParser.close();
username
, password
y role
del objeto HashMap
serían mallory
, Evil123!
y admin
, respectivamente. Sin más comprobaciones de que los valores JSON deserializados son válidos, la aplicación asignará de forma incorrecta privilegios de "admin" al usuario mallory
.
var str = document.URL;
var url_check = str.indexOf('name=');
var name = null;
if (url_check > -1) {
name = decodeURIComponent(str.substring((url_check+5), str.length));
}
$(document).ready(function(){
if (name !== null){
var obj = jQuery.parseJSON('{"role": "user", "name" : "' + name + '"}');
...
}
...
});
name
no se validarán para omitir caracteres especiales relacionados con JSON. Esto permite a un usuario introducir claves JSON de forma arbitraria, posiblemente cambiando la estructura del JSON serializado. En este ejemplo, si el usuario sin privilegios mallory
fuese a agregar ","role":"admin
al parámetro de nombre en la dirección URL, el JSON resultante sería:
{
"role":"user",
"username":"mallory",
"role":"admin"
}
jQuery.parseJSON()
y establecido como objeto simple, lo que significa que obj.role
devolverá "admin" en lugar de "user"._usernameField
y _passwordField
:
...
NSString * const jsonString = [NSString stringWithFormat: @"{\"username\":\"%@\",\"password\":\"%@\",\"role\":\"default\"}" _usernameField.text, _passwordField.text];
NSString.stringWithFormat:
, los datos que no son de confianza de _usernameField
y _passwordField
no se validarán para omitir caracteres especiales relacionados con JSON. Esto permite a un usuario introducir claves JSON de forma arbitraria, posiblemente cambiando la estructura del JSON serializado. En este ejemplo, si el usuario sin privilegios mallory
con la contraseña Evil123!
fuese a agregar ","role":"admin
a su nombre de usuario al introducirla en el campo _usernameField
, el JSON resultante sería:
{
"username":"mallory",
"role":"admin",
"password":"Evil123!",
"role":"default"
}
NSDictionary
con NSJSONSerialization.JSONObjectWithData:
de este modo:
NSError *error;
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];
username
, password
y role
en el objeto NSDictionary
serían mallory
, Evil123!
y admin
respectivamente. Sin más comprobaciones de que los valores JSON deserializados son válidos, la aplicación asignará de forma incorrecta privilegios de "admin" al usuario mallory
.
import json
import requests
from urllib.parse import urlparse
from urllib.parse import parse_qs
url = 'https://www.example.com/some_path?name=some_value'
parsed_url = urlparse(url)
untrusted_values = parse_qs(parsed_url.query)['name'][0]
with open('data.json', 'r') as json_File:
data = json.load(json_File)
data['name']= untrusted_values
with open('data.json', 'w') as json_File:
json.dump(data, json_File)
...
name
no se validarán para escapar de los caracteres especiales relacionados con JSON. Esto permite que un usuario inserte arbitrariamente claves JSON, posiblemente cambiando la estructura del JSON serializado. En este ejemplo, si el usuario sin privilegios mallory
agregara ","role":"admin
al parámetro de nombre en la URL, el JSON se convertiría en:
{
"role":"user",
"username":"mallory",
"role":"admin"
}
usernameField
y passwordField
:
...
let jsonString : String = "{\"username\":\"\(usernameField.text)\",\"password\":\"\(passwordField.text)\",\"role\":\"default\"}"
usernameField
y passwordField
no se validarán para omitir caracteres especiales relacionados con JSON. Esto permite a un usuario introducir claves JSON de forma arbitraria, posiblemente cambiando la estructura del JSON serializado. En este ejemplo, si el usuario sin privilegios mallory
con la contraseña Evil123!
fuese a agregar ","role":"admin
a su nombre de usuario al introducirla en el campo usernameField
, el JSON resultante sería:
{
"username":"mallory",
"role":"admin",
"password":"Evil123!",
"role":"default"
}
NSDictionary
con NSJSONSerialization.JSONObjectWithData:
de este modo:
var error: NSError?
var jsonData : NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonString.dataUsingEncoding(NSUTF8StringEncoding), options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
username
, password
y role
en el objeto NSDictionary
serían mallory
, Evil123!
y admin
respectivamente. Sin más comprobaciones de que los valores JSON deserializados son válidos, la aplicación asignará de forma incorrecta privilegios de "admin" al usuario mallory
.
def searchUserDetails(key:String) = Action.async { implicit request =>
val user_json = getUserDataFor(user)
val value = (user_json \ key).get.as[String]
...
}
key
es controlable por el usuario, un atacante puede aprovecharse de esto para acceder a las contraseñas del usuario y cualquier otro dato privado que pueda contener el documento JSON.returningObjectFlag
en true
en la instancia de javax.naming.directory.SearchControls
pasada al método search
o mediante el uso de una función de biblioteca que establece esta marca en su nombre.
<beans ... >
<authentication-manager>
<ldap-authentication-provider
user-search-filter="(uid={0})"
user-search-base="ou=users,dc=example,dc=org"
group-search-filter="(uniqueMember={0})"
group-search-base="ou=groups,dc=example,dc=org"
group-role-attribute="cn"
role-prefix="ROLE_">
</ldap-authentication-provider>
</authentication-manager>
</beans>
...
DirectorySearcher src =
new DirectorySearcher("(manager=" + managerName.Text + ")");
src.SearchRoot = de;
src.SearchScope = SearchScope.Subtree;
foreach(SearchResult res in src.FindAll()) {
...
}
(manager=Smith, John)
managerName
no contiene metacaracteres LDAP. Si un usuario malintencionado introduce la cadena Hacker, Wiley)(|(objectclass=*)
para managerName
, entonces la consulta será de la siguiente forma:
(manager=Hacker, Wiley)(|(objectclass=*))
|(objectclass=*)
hace que el filtro busque coincidencias en todas las entradas del directorio y permite al atacante recuperar información acerca de todo el grupo de usuarios. En función de los permisos con los que se realice la consulta LDAP, la amplitud de este ataque puede quedar limitada. Sin embargo, si el atacante es capaz de controlar la estructura de comando de la consulta, un ataque puede afectar como mínimo a tantos registros como el usuario de la consulta LDAP que se ejecuta pueda acceder.
fgets(manager, sizeof(manager), socket);
snprintf(filter, sizeof(filter, "(manager=%s)", manager);
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 ) {
...
}
(manager=Smith, John)
manager
no contiene metacaracteres LDAP. Si un usuario malintencionado introduce la cadena Hacker, Wiley)(|(objectclass=*)
para manager
, entonces la consulta será de la siguiente forma:
(manager=Hacker, Wiley)(|(objectclass=*))
|(objectclass=*)
hace que el filtro busque coincidencias en todas las entradas del directorio y permite al atacante recuperar información acerca de todo el grupo de usuarios. En función de los permisos con los que se realice la consulta LDAP, la amplitud de este ataque puede quedar limitada. Sin embargo, si el atacante es capaz de controlar la estructura de comando de la consulta, un ataque puede afectar como mínimo a tantos registros como el usuario de la consulta LDAP que se ejecuta pueda acceder.
...
DirContext ctx = new InitialDirContext(env);
String managerName = request.getParameter("managerName");
//retrieve all of the employees who report to a manager
String filter = "(manager=" + managerName + ")";
NamingEnumeration employees = ctx.search("ou=People,dc=example,dc=com",
filter);
...
(manager=Smith, John)
managerName
no contiene metacaracteres LDAP. Si un usuario malintencionado introduce la cadena Hacker, Wiley)(|(objectclass=*)
para managerName
, entonces la consulta será de la siguiente forma:
(manager=Hacker, Wiley)(|(objectclass=*))
|(objectclass=*)
hace que el filtro busque coincidencias en todas las entradas del directorio y permite al atacante recuperar información acerca de todo el grupo de usuarios. En función de los permisos con los que se realice la consulta LDAP, la amplitud de este ataque puede quedar limitada. Sin embargo, si el atacante es capaz de controlar la estructura de comando de la consulta, un ataque puede afectar como mínimo a tantos registros como el usuario de la consulta LDAP que se ejecuta pueda acceder.
...
$managerName = $_POST["managerName"]];
//retrieve all of the employees who report to a manager
$filter = "(manager=" . $managerName . ")";
$result = ldap_search($ds, "ou=People,dc=example,dc=com", $filter);
...
(manager=Smith, John)
managerName
no contiene metacaracteres LDAP. Si un usuario malintencionado introduce la cadena Hacker, Wiley)(|(objectclass=*)
para managerName
, entonces la consulta será de la siguiente forma:
(manager=Hacker, Wiley)(|(objectclass=*))
|(objectclass=*)
hace que el filtro busque coincidencias en todas las entradas del directorio y permite al atacante recuperar información acerca de todo el grupo de usuarios. En función de los permisos con los que se realice la consulta LDAP, la amplitud de este ataque puede quedar limitada. Sin embargo, si el atacante es capaz de controlar la estructura de comando de la consulta, un ataque puede afectar como mínimo a tantos registros como el usuario de la consulta LDAP que se ejecuta pueda acceder.