HTTP
. Isso expõe os dados a acesso não autorizado, adulteração e possível roubo.protocol
de um HTTP Listener Connector (listener-connection
) como HTTP
. Como resultado, as conexões ao HTTP Listener são inseguras.
<http:listener-config name="http_listener_config">
<http:listener-connection host="example.com" port="8080" protocol="HTTP">
...
</http:listener-connection>
</http:listener-config>
tls:context
define um conjunto de configurações de conexão TLS. Entre as configurações, o elemento tls:trust-store
especifica um arquivo que contém certificados de Autoridades de Certificação confiáveis que um cliente usa para verificar um certificado apresentado por um servidor. Por padrão, o mecanismo de tempo de execução do Mule verifica o certificado do servidor para cada conexão TLS.insecure
do elemento tls:trust-store
for true
, os certificados do servidor serão aceitos sem verificação.insecure
como true
. Como resultado, o mecanismo de tempo de execução do Mule não verifica o certificado do servidor de nenhuma conexão com o contexto de TLS chamado demoTlsContext
. Essa conexão é vulnerável a um ataque man-in-the-middle.
...
<tls:context name="demoTlsContext">
...
<tls:trust-store ... insecure="true" ... />
...
<tls:context/>
...
...
String userName = User.Identity.Name;
String emailId = request["emailId"];
var client = account.CreateCloudTableClient();
var table = client.GetTableReference("Employee");
var query = table.CreateQuery<EmployeeEntity>().Where("user == '" + userName + "' AND emailId == '" + emailId "'");
var results = table.ExecuteQuery(query);
...
user == "<userName>" && emailId == "<emailId>"
emailId
não contiver um caractere de aspas simples. Se um invasor com o nome de usuário wiley
inserir a cadeia de caracteres "123' || '4' != '5
" para emailId
, a consulta se tornará a seguinte:
user == 'wiley' && emailId == '123' || '4' != '5'
|| '4' != '5'
faz com que a cláusula where sempre seja avaliada como true
e, portanto, a consulta retorna todas as entradas armazenadas na coleção emails
, independentemente do proprietário do e-mail.
...
// "type" parameter expected to be either: "Email" or "Username"
string type = request["type"];
string value = request["value"];
string password = request["password"];
var ddb = new AmazonDynamoDBClient();
var attrValues = new Dictionary<string,AttributeValue>();
attrValues[":value"] = new AttributeValue(value);
attrValues[":password"] = new AttributeValue(password);
var scanRequest = new ScanRequest();
scanRequest.FilterExpression = type + " = :value AND Password = :password";
scanRequest.TableName = "users";
scanRequest.ExpressionAttributeValues = attrValues;
var scanResponse = await ddb.ScanAsync(scanRequest);
...
Email = :value AND Password = :password
Username = :value AND Password = :password
type
contiver apenas um dos valores esperados. Se um invasor fornecer um valor type como :value = :value OR :value
, a consulta se transforma no seguinte::value = :value OR :value = :value AND Password = :password
:value = :value
faz com que a cláusula "where" sempre seja avaliada como "true" e, portanto, a consulta retorna todas as entradas armazenadas na coleção users
, independentemente do proprietário do email.
...
// "type" parameter expected to be either: "Email" or "Username"
String type = request.getParameter("type")
String value = request.getParameter("value")
String password = request.getParameter("password")
DynamoDbClient ddb = DynamoDbClient.create();
HashMap<String, AttributeValue> attrValues = new HashMap<String,AttributeValue>();
attrValues.put(":value", AttributeValue.builder().s(value).build());
attrValues.put(":password", AttributeValue.builder().s(password).build());
ScanRequest queryReq = ScanRequest.builder()
.filterExpression(type + " = :value AND Password = :password")
.tableName("users")
.expressionAttributeValues(attrValues)
.build();
ScanResponse response = ddb.scan(queryReq);
...
Email = :value AND Password = :password
Username = :value AND Password = :password
type
contiver apenas um dos valores esperados. Se um invasor fornecer um valor type como :value = :value OR :value
, a consulta se transforma no seguinte::value = :value OR :value = :value AND Password = :password
:value = :value
faz com que a cláusula "where" sempre seja avaliada como "true" e, portanto, a consulta retorna todas as entradas armazenadas na coleção users
, independentemente do proprietário do email.
...
function getItemsByOwner(username: string) {
db.items.find({ $where: `this.owner === '${username}'` }).then((orders: any) => {
console.log(orders);
}).catch((err: any) => {
console.error(err);
});
}
...
db.items.find({ $where: `this.owner === 'john'; return true; //` })
...
String userName = User.Identity.Name;
String emailId = request["emailId"];
var coll = mongoClient.GetDatabase("MyDB").GetCollection<BsonDocument>("emails");
var docs = coll.Find(new BsonDocument("$where", "this.name == '" + name + "'")).ToList();
...
this.owner == "<userName>" && this.emailId == "<emailId>"
emailId
não contiver um caractere de aspas simples. Se um invasor com o nome de usuário wiley
inserir a cadeia de caracteres "123' || '4' != '5
" para emailId
, a consulta se tornará a seguinte:
this.owner == 'wiley' && this.emailId == '123' || '4' != '5'
|| '4' != '5'
faz com que a cláusula where sempre seja avaliada como true
e, portanto, a consulta retorna todas as entradas armazenadas na coleção emails
, independentemente do proprietário do e-mail.
...
String userName = ctx.getAuthenticatedUserName();
String emailId = request.getParameter("emailId")
MongoCollection<Document> col = mongoClient.getDatabase("MyDB").getCollection("emails");
BasicDBObject Query = new BasicDBObject();
Query.put("$where", "this.owner == \"" + userName + "\" && this.emailId == \"" + emailId + "\"");
FindIterable<Document> find= col.find(Query);
...
this.owner == "<userName>" && this.emailId == "<emailId>"
emailId
não contiver um caractere de aspas duplas. Se um invasor com o nome de usuário wiley
inserir a string "123" || "4" != "5
" para emailId
, a consulta se tornará a seguinte:
this.owner == "wiley" && this.emailId == "123" || "4" != "5"
|| "4" != "5"
faz com que a cláusula "where" sempre seja avaliada como "true" e, portanto, a consulta retorna todas as entradas armazenadas na coleção emails
, independentemente do proprietário do email.
...
userName = req.field('userName')
emailId = req.field('emaiId')
results = db.emails.find({"$where", "this.owner == \"" + userName + "\" && this.emailId == \"" + emailId + "\""});
...
this.owner == "<userName>" && this.emailId == "<emailId>"
emailId
não contiver um caractere de aspas duplas. Se um invasor com o nome de usuário wiley
inserir a string "123" || "4" != "5
" para emailId
, a consulta se tornará a seguinte:
this.owner == "wiley" && this.emailId == "123" || "4" != "5"
|| "4" != "5"
faz com que a cláusula "where
" sempre seja avaliada como "true" e, portanto, a consulta retorna todas as entradas armazenadas na coleção emails
, independentemente do proprietário do email.
...
NSString *emailId = [self getEmailIdFromUser];
NSString *query = [NSString stringWithFormat:@"id == '%@'", emailId];
RLMResults<Email *> *emails = [Email objectsInRealm:realm where:query];
...
id == '<emailId value>'
emailId
não contiver um caractere de aspas simples. Se um invasor inserir a string 123' or '4' != '5
para emailId
, a consulta se tornará a seguinte:
id == '123' or '4' != '5'
or '4' != '5'
faz com que a cláusula where
sempre seja avaliada como "true" e, com isso, a consulta retorna todas as entradas armazenadas na coleção emails
, independentemente do proprietário do email.
...
let emailId = getFromUser("emailId")
let email = realm.objects(Email.self).filter("id == '" + emailId + "'")
...
id == '<emailId value>'
emailId
não contiver um caractere de aspas simples. Se um invasor inserir a string 123' or '4' != '5
para emailId
, a consulta se tornará a seguinte:
id == '123' or '4' != '5'
or '4' != '5'
faz com que a cláusula filter
sempre seja avaliada como "true" e, com isso, a consulta retorna todas as entradas armazenadas na coleção emails
, independentemente do proprietário do email.NullException
.cmd
" definida. Se um invasor puder controlar o ambiente do programa de forma que "cmd
" não seja definido, o programa lançará uma exceção de ponteiro nulo quando tentar chamar o método Trim()
.
string cmd = null;
...
cmd = Environment.GetEnvironmentVariable("cmd");
cmd = cmd.Trim();
null
antes que seja verificado se ele é realmente null
. Erros de desreferência após a verificação ocorrem quando um programa faz uma verificação explícita em busca de valores null
, mas prossegue para desreferenciar o ponteiro quando se sabe que ele é null
. Erros desse tipo são frequentemente o resultado de um erro de digitação ou de uma desatenção do programador. Um erro de desreferência após o armazenamento ocorre quando um programa define explicitamente um ponteiro como null
e o desreferencia mais tarde. Esse erro é frequentemente o resultado de um programador inicializar uma variável como null
quando ela é declarada.ptr
não seja NULL
. Essa suposição se torna explícita quando o programador desreferencia o ponteiro. Mais tarde, essa suposição é contrariada quando o programador verifica ptr
contra NULL
. Se a variável ptr
puder ser NULL
quando for verificada na instrução if
, ela também poderá ser NULL
quando desreferenciada, podendo causar uma falha de segmentação.Exemplo 2: No código a seguir, o programador confirma que a variável
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
é NULL
e depois a desreferencia erroneamente. Se a variável ptr
for NULL
quando for verificada na instrução if
, ocorrerá uma desreferência null
, causando assim uma falha de segmentação.Exemplo 3: No código a seguir, o programador se esquece de que a cadeia de caracteres
if (ptr == null) {
ptr->field = val;
...
}
'\0'
é, na verdade, 0 ou NULL
, desreferenciando assim um ponteiro nulo e provocando uma falha de segmentação.Exemplo 4: No código a seguir, o programador define explicitamente a variável
if (ptr == '\0') {
*ptr = val;
...
}
ptr
como NULL
. Mais tarde, o programador desreferencia ptr
antes de verificar o objeto em busca de um valor null
.
*ptr = NULL;
...
ptr->field = val;
...
}
NullPointerException
.cmd
" definida. Se um invasor puder controlar o ambiente do programa de forma que "cmd
" não seja definido, o programa lançará uma exceção de ponteiro nulo quando tentar chamar o método trim()
.
String val = null;
...
cmd = System.getProperty("cmd");
if (cmd)
val = util.translateCommand(cmd);
...
cmd = val.trim();
unserialize()
. Os invasores poderiam passar cadeias de caracteres serializadas criadas especialmente para uma chamada unserialize()
vulnerável, resultando em uma injeção de objeto(s) PHP arbitrário(s) no escopo do aplicativo. A gravidade da vulnerabilidade depende das classes disponíveis no escopo de aplicativo. As classes que estão implementando método de mágica PHP, como __wakeup
ou __destruct
, serão interessantes para os invasores, já que eles serão capazes de executar o código nesses métodos.__destruct()
e executando um comando do sistema definido como uma propriedade de classe. Há também uma chamada insegura para unserialize()
com dados fornecidos pelo usuário.
...
class SomeAvailableClass {
public $command=null;
public function __destruct() {
system($this->command);
}
}
...
$user = unserialize($_GET['user']);
...
Example 1
, o aplicativo pode estar esperando um objeto User
serializado, mas um invasor pode na verdade fornecer uma versão serializada de SomeAvailableClass
com um valor predefinido para sua propriedade command
:
GET REQUEST: http://server/page.php?user=O:18:"SomeAvailableClass":1:{s:7:"command";s:8:"uname -a";}
$user
e ele executará o comando fornecido pelo invasor.unserialize()
vulnerável está sendo chamado usando uma técnica conhecida como "Programação orientada à propriedade", que foi introduzida por Stefan Esser durante a conferência BlackHat de 2010. Essa técnica permite que um invasor reutilize o código existente para criar a sua própria carga de trabalho.YAML.load()
. Os invasores podem transmitir cadeias especialmente projetadas para uma chamada vulnerável YAML.load()
, resultando na injeção de objetos arbitrários Ruby no programa, desde que a classe seja carregada no aplicativo no momento da desserialização. Isso pode permitir uma vasta gama de oportunidades de ataque, como ignorar a lógica de validação para encontrar vulnerabilidades de cross-site scripting, permitis a SQL Injection por meio do que parecem ser valores codificados ou mesmo uma execução de código completo.YAML.load()
com dados fornecidos pelo usuário.
...
class Transaction
attr_accessor :id
def initialize(num=nil)
@id = num.is_a?(Numeric) ? num : nil
end
def print_details
unless @id.nil?
print $conn.query("SELECT * FROM transactions WHERE id=#{@id}")
end
end
end
...
user = YAML.load(params[:user]);
user.print_details
...
Example 1
, o aplicativo pode estar esperando um objeto User
serializado, o qual também tem uma função chamada print_details
, mas um invasor pode de fato fornecer uma versão serializada de um objeto Transaction
com um valor predefinido para o respectivo atributo @id
. Uma solicitação como essa pode, portanto, permitir que se ignore a verificação de validação que tenta se certificar de que @id
seja um valor numérico
GET REQUEST: http://server/page?user=!ruby%2Fobject%3ATransaction%0Aid%3A4%20or%205%3D5%0A
user
é atribuído !ruby/object:Transaction\nid:4 or 5=5\n
.Transaction
, definindo como @id
para "4 or 5=5"
. Quando o desenvolvedor acreditar que está chamando User#print_details()
, na verdade estará chamando Transaction#print_details()
e a interpolação de cadeia do Ruby significará que a consulta SQL será alterada para executar a consulta: SELECT * FROM transactions WHERE id=4 or 5=5
. Devido à cláusula extra adicionada, a consulta é avaliada como true
e retornará tudo dentro da tabela transactions
em vez da única linha pretendida pelo desenvolvedor.YAML.load()
vulnerável está sendo chamado usando uma técnica conhecida como "Programação orientada à propriedade", que foi introduzida por Stefan Esser durante a conferência BlackHat de 2010. Essa técnica permite que um invasor reutilize o código existente para criar a sua própria carga de trabalho.clone()
deve chamar super.clone()
para obter o novo objeto.clone()
devem obter o novo objeto chamando super.clone()
. Se uma classe não seguir essa convenção, o método clone()
de uma subclasse retornará um objeto do tipo errado.super.clone()
. Devido à forma como Kibitzer
implementa clone()
, o método clone de FancyKibitzer
retornará um objeto do tipo Kibitzer
em vez de FancyKibitzer
.
public class Kibitzer implements Cloneable {
public Object clone() throws CloneNotSupportedException {
Object returnMe = new Kibitzer();
...
}
}
public class FancyKibitzer extends Kibitzer
implements Cloneable {
public Object clone() throws CloneNotSupportedException {
Object returnMe = super.clone();
...
}
}
Equals()
ou GetHashCode()
.a.Equals(b) == true
, a.GetHashCode() == b.GetHashCode()
.Equals()
, mas não GetHashCode()
.
public class Halfway() {
public override boolean Equals(object obj) {
...
}
}
equals()
ou hashCode()
.a.equals(b) == true
, a.hashCode() == b.hashCode()
.equals()
, mas não hashCode()
.
public class halfway() {
public boolean equals(Object obj) {
...
}
}
saveState()
ou restoreState()
.saveState(javax.faces.context.FacesContext)
quanto restoreState(javax.faces.context.FacesContext, java.lang.Object)
ou implementar nenhum dos dois. Como esses dois métodos têm uma relação fortemente acoplada, não é permitido que os métodos saveState(javax.faces.context.FacesContext)
e restoreState(javax.faces.context.FacesContext, java.lang.Object)
residam em diferentes níveis da hierarquia de herança.saveState()
e não restoreState()
e, por isso, é sempre um erro, não importa o que qualquer classe que a estende possa fazer.
public class KibitzState implements StateHolder {
public Object saveState(FacesContext fc) {
...
}
}
SqlClientPermission
que regula como os usuários podem se conectar a um banco de dados. Neste exemplo, o programa transmite false
como o segundo parâmetro para o construtor, que controla se os usuários têm permissão para se conectarem com senhas em branco. A transmissão de "false" para esse parâmetro indica que senhas em branco não devem ser permitidas.
...
SCP = new SqlClientPermission(pstate, false);
...
PermissionState
transmitido como o primeiro parâmetro substitui qualquer valor transmitido ao segundo parâmetro, o construtor permite senhas em branco para conexões de banco de dados, o que contradiz o segundo argumento. Para proibir senhas em branco, o programa deve transmitir PermissionState.None
ao primeiro parâmetro do construtor. Devido à ambiguidade na sua funcionalidade, a versão de dois parâmetros do construtor SqlClientPermission
foi preterida a favor da versão de parâmetro único, que transmite o mesmo grau de informações sem o risco de má interpretação.getpw()
para verificar se a senha de texto sem formatação corresponde à senha criptografada de um usuário. Se a senha for válida, a função definirá result
como 1; caso contrário, ele será definido como 0.
...
getpw(uid, pwdline);
for (i=0; i<3; i++){
cryptpw=strtok(pwdline, ":");
pwdline=0;
}
result = strcmp(crypt(plainpw,cryptpw), cryptpw) == 0;
...
getpw(
) pode ser uma estratégia problemática sob o ponto de vista da segurança, pois pode estourar o buffer transmitido para seu segundo parâmetro. Devido a essa vulnerabilidade, getpw()
foi suplantado por getpwuid()
, que executa a mesma pesquisa que getpw()
, mas retorna um ponteiro para uma estrutura estaticamente alocada a fim de atenuar o risco.
...
String name = new String(nameBytes, highByte);
...
nameBytes
. Devido à evolução dos charsets utilizados para codificar strings, este construtor foi descontinuado e substituído por um construtor que aceita como um de seus parâmetros o nome do charset
usado para codificar os bytes para conversão.Digest::HMAC
, cujo uso é explicitamente desencorajado na documentação devido ao envolvimento acidental em uma versão.
require 'digest/hmac'
hmac = Digest::HMAC.new("foo", Digest::RMD160)
...
hmac.update(buf)
...
Digest::HMAC
foi preterida imediatamente após o envolvimento devido à inclusão acidental em uma versão. Devido à possibilidade de ela não funcionar como o esperado por causa de um código experimental e não testado apropriadamente, a utilização é extremamente desencorajada, especialmente considerando-se a relação que os HMACs têm com a funcionalidade criptográfica.IsBadXXXPtr()
. Essas funções:IsBadWritePtr()
em uma tentativa de impedir gravações de memória inválidas.
if (IsBadWritePtr(ptr, length))
{
[handle error]
}
checkCallingOrSelfPermission()
ou checkCallingOrSelfUriPermission()
determina se o programa de chamada tem a permissão necessária para acessar um determinado serviço ou URI. No entanto, essas funções devem ser usadas com cautela, pois podem conceder acesso a aplicativos mal-intencionados, que não possuem as permissões apropriadas, assumindo as permissões do seu aplicativo.