Problemas de validação e representação da entrada são causados por metacaracteres, codificações alternativas e representações numéricas. Confiar na entrada resulta em problemas de segurança. Os problemas incluem: “Buffer Overflows”, ataques de “Cross-Site Scripting”, “SQL Injection”, entre outros.
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
tiver o valor 1073741824
e sizeof(char*)
tiver seu valor típico de 4
, ocorrerá o estouro do resultado da operação nresp*sizeof(char*)
, e o argumento para xmalloc()
será 0
. A maioria das implementações de malloc()
permitirá a alocação de um buffer de 0 byte, fazendo com que as iterações de loop subsequentes estourem o buffer de heap 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
, a entrada não será processada. O problema é que len
é um inteiro com sinal e, portanto, a verificação do comprimento máximo da estrutura é feita com inteiros com sinal, mas len
é convertido em um inteiro sem sinal na chamada para memcpy()
. Se len
for negativo, parecerá que a estrutura tem um tamanho apropriado (a ramificação if
será usada), mas a quantidade de memória copiada por memcpy()
será muito grande, e o invasor será capaz de estourar a pilha com dados em 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
tiver o valor 1073741824
, o resultado da operação MULTIPLY 4 BY num
causará um estouro de inteiros, e o argumento mem-size
de malloc()
será 0
. A maioria das implementações de malloc()
permite a alocação de um buffer de 0 bytes, provocando o estouro do mem-pointer
do buffer da pilha em declarações subsequentes.uint256
, isso significará que é armazenado como um número sem sinal de 256 bits que varia de 0 a 2^256-1. Se uma operação aritmética resultar em um número maior do que o limite superior, ocorrerá um overflow e o restante será adicionado a partir do valor inicial (0). Se uma operação aritmética fizer com que o número fique abaixo do limite inferior, ocorrerá um underflow e o restante será subtraído do maior valor (2^256-1).uint256
usando uma operação aritmética que pode levar ao overflow/underflow de inteiros e afetar índices não intencionais no 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
aninhado de uma entrada externa para iniciar uma atividade, iniciar um serviço ou realizar uma transmissão pode permitir que um invasor inicie arbitrariamente componentes de aplicativos internos, controle o comportamento de um componente interno ou acesse indiretamente dados protegidos de um provedor de conteúdo por meio de concessões de permissão temporárias.Intent
arbitrário aninhado no pacote de extras de um Intent
fornecido externamente.Intent
arbitrário para iniciar um componente chamando startActivity
, startService
ou sendBroadcast
.Intent
aninhado de uma fonte externa e usa esse Intent
para iniciar uma atividade.
...
Intent nextIntent = (Intent) getIntent().getParcelableExtra("next-intent");
startActivity(nextIntent);
...
username
e password
para o arquivo JSON localizado em 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()
, os dados não confiáveis em username
e password
não serão validados para o escape de caracteres especiais relacionados ao JSON. Isso permite que um usuário insira chaves JSON arbitrariamente, possivelmente mudando a estrutura do JSON serializado. Neste exemplo, se o usuário não privilegiado mallory
com a senha Evil123!
fosse acrescentar ","role":"admin
ao seu nome de usuário ao inseri-lo no prompt que define o valor da variável username
, o JSON salvo em C:\user_info.json
seria:
{
"role":"default",
"username":"mallory",
"role":"admin",
"password":"Evil123!"
}
Dictionary
com JsonConvert.DeserializeObject()
, da seguinte maneira:
String jsonString = File.ReadAllText(@"C:\user_info.json");
Dictionary<string, string> userInfo = JsonConvert.DeserializeObject<Dictionary<string, strin>>(jsonString);
username
, password
e role
no objeto Dictionary
seriam mallory
, Evil123!
e admin
, respectivamente. Sem a verificação adicional de que os valores JSON desserializados são válidos, o aplicativo atribuirá incorretamente os privilégios "admin" ao usuário mallory
.username
e password
para o arquivo JSON localizado em ~/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
e password
não serão validados para realizar escape de caracteres especiais relacionados a JSON. Isso permite que um usuário insira chaves JSON arbitrárias, podendo modificar a estrutura serializada JSON. Neste exemplo, se o usuário não privilegiado mallory
com a senha Evil123!
anexou ","role":"admin
quando ela inseriu seu nome de usuário, o JSON resultante salvo para ~/user_info.json
seria:
{
"username":"mallory",
"role":"default",
"password":"Evil123!",
"role":"admin"
}
mallory
.username
e password
para o arquivo JSON localizado em ~/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()
, os dados não confiáveis em username
e password
não serão validados para o escape de caracteres especiais relacionados ao JSON. Isso permite que um usuário insira chaves JSON arbitrariamente, possivelmente mudando a estrutura do JSON serializado. Neste exemplo, se o usuário não privilegiado mallory
com a senha Evil123!
fosse acrescentar ","role":"admin
ao seu nome de usuário ao inseri-lo no prompt que define o valor da variável username
, o JSON salvo em ~/user_info.json
seria:
{
"username":"mallory",
"role":"admin",
"password":"Evil123!",
"role":"default"
}
HashMap
com JsonParser
do Jackson, da seguinte maneira:
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
e role
no objeto HashMap
seriam mallory
, Evil123!
e admin
, respectivamente. Sem a verificação adicional de que os valores JSON desserializados são válidos, o aplicativo atribuirá incorretamente os privilégios "admin" ao usuário 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
não serão validados para escapar dos caracteres especiais relacionadas com o JSON. Isso permite que um usuário insira chaves JSON arbitrariamente, possivelmente mudando a estrutura do JSON serializado. Neste exemplo, se o usuário não privilegiado mallory
acrescentasse ","role":"admin
ao parâmetro nome na URL, o JSON se tornaria:
{
"role":"user",
"username":"mallory",
"role":"admin"
}
jQuery.parseJSON()
e definido como um objeto simples, o que significa que obj.role
retornaria agora "admin" em vez de "user"_usernameField
e _passwordField
:
...
NSString * const jsonString = [NSString stringWithFormat: @"{\"username\":\"%@\",\"password\":\"%@\",\"role\":\"default\"}" _usernameField.text, _passwordField.text];
NSString.stringWithFormat:
, os dados não confiáveis em _usernameField
e _passwordField
não serão validados para o escape de caracteres especiais relacionados ao JSON. Isso permite que um usuário insira chaves JSON arbitrariamente, possivelmente mudando a estrutura do JSON serializado. Nesse exemplo, se o usuário não privilegiado mallory
com a senha Evil123!
anexasse ","role":"admin
ao nome de usuário dele ao digitá-lo no campo _usernameField
, o JSON resultante seria:
{
"username":"mallory",
"role":"admin",
"password":"Evil123!",
"role":"default"
}
NSDictionary
com NSJSONSerialization.JSONObjectWithData:
desta maneira:
NSError *error;
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];
username
, password
, e role
no objeto NSDictionary
seriam mallory
, Evil123!
, e admin
respectivamente. Sem a verificação adicional de que os valores JSON desserializados são válidos, o aplicativo atribuirá incorretamente os privilégios "admin" ao usuário 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
não serão validados para aplicar o escape de caracteres especiais relacionados a JSON. Isso permite que um usuário insira chaves JSON arbitrariamente, possivelmente alterando a estrutura do JSON serializado. Nesse exemplo, se o usuário não privilegiado mallory
anexasse ","role":"admin
ao parâmetro name na URL, o JSON se tornaria:
{
"role":"user",
"username":"mallory",
"role":"admin"
}
usernameField
e passwordField
:
...
let jsonString : String = "{\"username\":\"\(usernameField.text)\",\"password\":\"\(passwordField.text)\",\"role\":\"default\"}"
usernameField
e passwordField
não serão validados para realizar escape dos caracteres especiais relacionados a JSON. Isso permite que um usuário insira chaves JSON arbitrariamente, possivelmente mudando a estrutura do JSON serializado. Nesse exemplo, se o usuário não privilegiado mallory
com a senha Evil123!
anexasse ","role":"admin
ao nome de usuário dele ao digitá-lo no campo usernameField
, o JSON resultante seria:
{
"username":"mallory",
"role":"admin",
"password":"Evil123!",
"role":"default"
}
NSDictionary
com NSJSONSerialization.JSONObjectWithData:
desta maneira:
var error: NSError?
var jsonData : NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonString.dataUsingEncoding(NSUTF8StringEncoding), options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
username
, password
, e role
no objeto NSDictionary
seriam mallory
, Evil123!
, e admin
respectivamente. Sem a verificação adicional de que os valores JSON desserializados são válidos, o aplicativo atribuirá incorretamente os privilégios "admin" ao usuário mallory
.
def searchUserDetails(key:String) = Action.async { implicit request =>
val user_json = getUserDataFor(user)
val value = (user_json \ key).get.as[String]
...
}
key
pode ser controlada pelo usuário, um usuário mal-intencionado pode tirar proveito disso para acessar as senhas do usuário e todos os outros dados privados que possam estar contidos no documento JSON.returningObjectFlag
como true
na instãncia javax.naming.directory.SearchControls
passada para o método search
ou usando uma função de biblioteca que define este sinalizador em seu nome.
<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
não contiver metacaracteres LDAP. Se um invasor inserir a string Hacker, Wiley)(|(objectclass=*)
para managerName
, a consulta se tornará a seguinte:
(manager=Hacker, Wiley)(|(objectclass=*))
|(objectclass=*)
faz com que o filtro seja correspondido com todas as entradas do diretório e permite que o invasor recupere informações sobre o grupo inteiro de usuários. A amplitude desse ataque pode ser limitada dependendo das permissões com as quais a consulta LDAP é realizada. Porém, se o invasor puder controlar a estrutura de comandos da consulta, esse ataque poderá afetar pelo menos todos os registros que podem ser acessados pelo usuário com base no qual a consulta LDAP é executada.
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
não contiver metacaracteres LDAP. Se um invasor inserir a string Hacker, Wiley)(|(objectclass=*)
para manager
, a consulta se tornará a seguinte:
(manager=Hacker, Wiley)(|(objectclass=*))
|(objectclass=*)
faz com que o filtro seja correspondido com todas as entradas do diretório e permite que o invasor recupere informações sobre o grupo inteiro de usuários. A amplitude desse ataque pode ser limitada dependendo das permissões com as quais a consulta LDAP é realizada. Porém, se o invasor puder controlar a estrutura de comandos da consulta, esse ataque poderá afetar pelo menos todos os registros que podem ser acessados pelo usuário com base no qual a consulta LDAP é executada.
...
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
não contiver metacaracteres LDAP. Se um invasor inserir a string Hacker, Wiley)(|(objectclass=*)
para managerName
, a consulta se tornará a seguinte:
(manager=Hacker, Wiley)(|(objectclass=*))
|(objectclass=*)
faz com que o filtro seja correspondido com todas as entradas do diretório e permite que o invasor recupere informações sobre o grupo inteiro de usuários. A amplitude desse ataque pode ser limitada dependendo das permissões com as quais a consulta LDAP é realizada. Porém, se o invasor puder controlar a estrutura de comandos da consulta, esse ataque poderá afetar pelo menos todos os registros que podem ser acessados pelo usuário com base no qual a consulta LDAP é executada.
...
$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
não contiver metacaracteres LDAP.Se um invasor inserir a string Hacker, Wiley)(|(objectclass=*)
para managerName
, a consulta se tornará a seguinte:
(manager=Hacker, Wiley)(|(objectclass=*))
|(objectclass=*)
faz com que o filtro seja correspondido com todas as entradas do diretório e permite que o invasor recupere informações sobre o grupo inteiro de usuários.A amplitude desse ataque pode ser limitada dependendo das permissões com as quais a consulta LDAP é realizada. Porém, se o invasor puder controlar a estrutura de comandos da consulta, esse ataque poderá afetar pelo menos todos os registros que podem ser acessados pelo usuário com base no qual a consulta LDAP é executada.