RegisterModel
ou Details
:
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
try
{
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", "");
}
}
return View(model);
}
RegisterModel
é definida como:
public class RegisterModel
{
[BindRequired]
[Display(Name = "User name")]
public string UserName { get; set; }
[BindRequired]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
public string ConfirmPassword { get; set; }
public Details Details { get; set; }
public RegisterModel()
{
Details = new Details();
}
}
Details
é definida como:Exemplo 2: Ao usar
public class Details
{
public bool IsAdmin { get; set; }
...
}
TryUpdateModel()
ou UpdateModel()
em aplicativos ASP.NET MVC ou Web API, o associador de modelo tentará vincular automaticamente todos os parâmetros de solicitações HTTP por padrão:Exemplo 3: Em aplicativos ASP.NET Web Form, o associador do modelo tentará vincular automaticamente todos os parâmetros de solicitação HTTP ao usar
public ViewResult Register()
{
var model = new RegisterModel();
TryUpdateModel<RegisterModel>(model);
return View("detail", model);
}
TryUpdateModel()
ouUpdateModel()
com a interface IValueProvider.
Employee emp = new Employee();
TryUpdateModel(emp, new System.Web.ModelBinding.FormValueProvider(ModelBindingExecutionContext));
if (ModelState.IsValid)
{
db.SaveChanges();
}
Employee
é definida como:
public class Employee
{
public Employee()
{
IsAdmin = false;
IsManager = false;
}
public string Name { get; set; }
public string Email { get; set; }
public bool IsManager { get; set; }
public bool IsAdmin { get; set; }
}
Booking
:
<view-state id="enterBookingDetails" model="booking">
<on-render>
<render fragments="body" />
</on-render>
<transition on="proceed" to="reviewBooking">
</transition>
<transition on="cancel" to="cancel" bind="false" />
</view-state>
Booking
é definida como:
public class Booking implements Serializable {
private Long id;
private User user;
private Hotel hotel;
private Date checkinDate;
private Date checkoutDate;
private String creditCard;
private String creditCardName;
private int creditCardExpiryMonth;
private int creditCardExpiryYear;
private boolean smoking;
private int beds;
private Set<Amenity> amenities;
// Public Getters and Setters
...
}
Order
, Customer
e Profile
são classes do Microsoft .NET Entity mantidas como persistentes.
public class Order {
public string ordered { get; set; }
public List<LineItem> LineItems { get; set; }
pubilc virtual Customer Customer { get; set; }
...
}
public class Customer {
public int CustomerId { get; set; }
...
public virtual Profile Profile { get; set; }
...
}
public class Profile {
public int profileId { get; set; }
public string username { get; set; }
public string password { get; set; }
...
}
OrderController
é uma de classe de controlador MVC ASP.NET que lida com a solicitação:
public class OrderController : Controller{
StoreEntities db = new StoreEntities();
...
public String updateOrder(Order order) {
...
db.Orders.Add(order);
db.SaveChanges();
}
}
Order
, Customer
e Profile
são classes do Hibernate mantidas como persistentes.
public class Order {
String ordered;
List lineItems;
Customer cust;
...
}
public class Customer {
String customerId;
...
Profile p;
...
}
public class Profile {
String profileId;
String username;
String password;
...
}
OrderController
é uma de classe de controlador Spring que lida com a solicitação:
@Controller
public class OrderController {
...
@RequestMapping("/updateOrder")
public String updateOrder(Order order) {
...
session.save(order);
}
}
Register
) é acessado a partir de um formulário da Web que solicita que os usuários registrem uma conta fornecendo seus nomes e senhas:
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
try
{
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", "");
}
}
return View(model);
}
RegisterModel
é definida como:
public class RegisterModel
{
[BindRequired]
[Display(Name = "User name")]
public string UserName { get; set; }
[BindRequired]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
public string ConfirmPassword { get; set; }
public Details Details { get; set; }
public RegisterModel()
{
Details = new Details();
}
}
Details
é definida como:
public class Details
{
public bool IsAdmin { get; set; }
...
}
Example 1
, um invasor pode ser capaz de explorar o aplicativo e descobrir que existe um atributo Details
no modelo RegisterModel
. Se esse for o caso, o invasor poderá então tentar substituir os valores atuais atribuídos aos seus atributos.
name=John&password=****&details.is_admin=true
<struts-config>
<form-beans>
<form-bean name="dynaUserForm"
type="org.apache.struts.action.DynaActionForm" >
<form-property name="type" type="java.lang.String" />
<form-property name="user" type="com.acme.common.User" />
</form-bean>
...
User
é definida como:
public class User {
private String name;
private String lastname;
private int age;
private Details details;
// Public Getters and Setters
...
}
Details
é definida como:
public class Details {
private boolean is_admin;
private int id;
private Date login_date;
// Public Getters and Setters
...
}
Example 1
, um invasor pode ser capaz de explorar o aplicativo e descobrir que existe um atributo details
no modelo User
. Se esse for o caso, o invasor poderá então tentar substituir os valores atuais atribuídos aos seus atributos.
type=free&user.name=John&user.lastname=Smith&age=22&details.is_admin=true
null
.Item
é null
antes de chamar a função membro Equals()
, causando possivelmente um cancelamento de referência null
string itemName = request.Item(ITEM_NAME);
if (itemName.Equals(IMPORTANT_ITEM)) {
...
}
...
null
."null
.malloc()
.
buf = (char*) malloc(req_size);
strncpy(buf, xfer, req_size);
malloc()
falhou por que req_size
era grande demais ou por que muitas solicitações estavam sendo tratadas ao mesmo tempo? Ou ela foi causada por um vazamento de memória que se acumulou com o passar do tempo? Sem realizar o tratamento do erro, não há como saber.null
.getParameter()
é null
antes de chamar a função membro compareTo()
, causando possivelmente um cancelamento de referência null
.Exemplo 2:. O código a seguir mostra uma propriedade do sistema que é definida como
String itemName = request.getParameter(ITEM_NAME);
if (itemName.compareTo(IMPORTANT_ITEM)) {
...
}
...
null
e, mais tarde, tem sua referência desfeita por um programador, que erroneamente assume que ela sempre será definida.
System.clearProperty("os.name");
...
String os = System.getProperty("os.name");
if (os.equalsIgnoreCase("Windows 95") )
System.out.println("Not supported");
null
."null
.Object.equals()
, Comparable.compareTo()
e Comparator.compare()
retornem um valor especificado se seus parâmetros forem null
. Comportamentos inesperados poderão ocorrer se esse contrato não for seguido.equals()
não compara seu parâmetro com null
.
public boolean equals(Object object)
{
return (toString().equals(object.toString()));
}
FormAction
que não consegue validar os dados em relação às exigências esperadas:Exemplo 2: O código a seguir define o estado de uma ação do Spring WebFlow que não consegue validar os dados em relação às exigências esperadas:
<bean id="customerCriteriaAction" class="org.springframework.webflow.action.FormAction">
<property name="formObjectClass"
value="com.acme.domain.CustomerCriteria" />
<property name="propertyEditorRegistrar">
<bean
class="com.acme.web.PropertyEditors" />
</property>
</bean>
<action-state>
<action bean="transferMoneyAction" method="bind" />
</action-state>
def form = Form(
mapping(
"name" -> text,
"age" -> number
)(UserData.apply)(UserData.unapply)
)
clone()
.clone()
é invocado, o construtor da classe que está sendo clonada não é invocado. Portanto, se uma verificação de SecurityManager ou AccessController estiver presente no construtor de uma classe clonável, a mesma verificação também deverá estar presente no método clone da classe. Caso contrário, a verificação de segurança será ignorada quando a classe for clonada.SecurityManager
no construtor, mas não no método clone()
.
public class BadSecurityCheck implements Cloneable {
private int id;
public BadSecurityCheck() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new BadPermission("BadSecurityCheck"));
}
id = 1;
}
public Object clone() throws CloneNotSupportedException {
BadSecurityCheck bsm = (BadSecurityCheck)super.clone();
return null;
}
}
SecurityManager
em seu construtor precisa realizar a mesma verificação em seus métodos readObject()
e readObjectNoData
.readObject()
de uma classe serializável é invocado, o construtor da classe que está sendo desserializada não é invocado. Portanto, se uma verificação de SecurityManager
estiver presente no construtor de uma classe serializável, a mesma verificação de SecurityManager
também deverá estar presente nos métodos readObject()
e readObjectNoData()
. Caso contrário, a verificação de segurança será ignorada quando a classe for desserializada.SecurityManager
no construtor, mas não nos métodos readObject()
e readObjectNoData()
.
public class BadSecurityCheck implements Serializable {
private int id;
public BadSecurityCheck() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new BadPermission("BadSecurityCheck"));
}
id = 1;
}
public void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
in.defaultReadObject();
}
public void readObjectNoData(ObjectInputStream in) throws ClassNotFoundException, IOException {
in.defaultReadObject();
}
}
...
// "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.
...
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.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();
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 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.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.
IPAddress hostIPAddress = IPAddress.Parse(RemoteIpAddress);
IPHostEntry hostInfo = Dns.GetHostByAddress(hostIPAddress);
if (hostInfo.HostName.EndsWith("trustme.com")) {
trusted = true;
}
getlogin()
é fácil de falsificar. Não confie no nome que ela retorna.getlogin()
deve retornar uma string contendo o nome do usuário atualmente conectado ao terminal, mas um invasor pode fazer com que getlogin()
retorne o nome de qualquer usuário conectado à máquina. Não confie no nome retornado por getlogin()
ao tomar decisões de segurança.getlogin()
para determinar se um usuário é ou não confiável. Isso é facilmente contestado.
pwd = getpwnam(getlogin());
if (isTrustedGroup(pwd->pw_gid)) {
allow();
} else {
deny();
}
String ip = request.getRemoteAddr();
InetAddress addr = InetAddress.getByName(ip);
if (addr.getCanonicalHostName().endsWith("trustme.com")) {
trusted = true;
}
Boolean.getBoolean()
é muitas vezes confundido com chamadas de métodos Boolean.valueOf()
ou Boolean.parseBoolean()
.Boolean.getBoolean()
é muitas vezes má utilizada, pois presume-se que ela retorne o valor booliano representado pelo argumento de string especificado. No entanto, conforme indicado no Javadoc, o método Boolean.getBoolean(String)
"retornará true se, e somente se, a propriedade do sistema nomeada pelo argumento existir e for igual à string 'true'".Boolean.valueOf(String)
ou Boolean.parseBoolean(String)
.Boolean.getBoolean(String)
não converte uma primitiva de String. Ele apenas converte a propriedade do sistema.
...
String isValid = "true";
if ( Boolean.getBoolean(isValid) ) {
System.out.println("TRUE");
}
else {
System.out.println("FALSE");
}
...