RegisterModel
o Details
:
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
try
{
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", "");
}
}
return View(model);
}
RegisterModel
se define 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
se define como:Ejemplo 2: Al utilizar
public class Details
{
public bool IsAdmin { get; set; }
...
}
TryUpdateModel()
o UpdateModel()
en ASP.NET MVC o aplicaciones web API, el enlazador de modelos intentará enlazar automáticamente todos los parámetros de solicitud HTTP de forma predeterminada:Ejemplo 3: En las aplicaciones de formulario web ASP.NET, el enlazador de modelos intentará enlazar automáticamente todos los parámetros de solicitud HTTP cuando se utilice
public ViewResult Register()
{
var model = new RegisterModel();
TryUpdateModel<RegisterModel>(model);
return View("detail", model);
}
TryUpdateModel()
o UpdateModel()
con la interfaz IValueProvider.
Employee emp = new Employee();
TryUpdateModel(emp, new System.Web.ModelBinding.FormValueProvider(ModelBindingExecutionContext));
if (ModelState.IsValid)
{
db.SaveChanges();
}
Employee
se define 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
se define 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
y Profile
son clases persistentes de Microsoft .NET Entity.
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
es la clase controlador MVC de ASP.NET que trata la solicitud:
public class OrderController : Controller{
StoreEntities db = new StoreEntities();
...
public String updateOrder(Order order) {
...
db.Orders.Add(order);
db.SaveChanges();
}
}
Order
, Customer
y Profile
son clases Hibernate 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
es la clase de controlador que administra la solicitud:
@Controller
public class OrderController {
...
@RequestMapping("/updateOrder")
public String updateOrder(Order order) {
...
session.save(order);
}
}
Register
) desde un formulario web que pide a los usuarios que registren una cuenta proporcionando su nombre y contraseña:
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
try
{
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", "");
}
}
return View(model);
}
RegisterModel
se define 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
se define como:
public class Details
{
public bool IsAdmin { get; set; }
...
}
Example 1
, un atacante puede ser capaz de explorar la aplicación y detectar si hay un atributo de Details
en el modelo RegisterModel
. Si este fuera el caso, el atacante puede entonces intentar volver a escribir los valores actuales asignados a sus 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
se define como:
public class User {
private String name;
private String lastname;
private int age;
private Details details;
// Public Getters and Setters
...
}
Details
se define como:
public class Details {
private boolean is_admin;
private int id;
private Date login_date;
// Public Getters and Setters
...
}
Example 1
, un atacante puede ser capaz de explorar la aplicación y detectar si hay un atributo de details
en el modelo User
. Si este fuera el caso, el atacante puede entonces intentar volver a escribir los valores actuales asignados a sus atributos.
type=free&user.name=John&user.lastname=Smith&age=22&details.is_admin=true
null
.Item
es null
antes de llamar a la función miembro Equals()
, lo que podría provocar una eliminación de referencia de un valor 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()
presentó errores debido a que req_size
era demasiado grande o a que se estaban administrando demasiadas solicitudes al mismo tiempo? ¿O el error lo provocó una pérdida de memoria que se acumuló a lo largo de un periodo? Si no se administra el error, es imposible saberlo.null
.getParameter()
es null
antes de llamar a la función miembro compareTo()
, lo que podría provocar una desreferencia de null
.Ejemplo 2:. en el siguiente código se muestra una propiedad del sistema que se establece en un valor
String itemName = request.getParameter(ITEM_NAME);
if (itemName.compareTo(IMPORTANT_ITEM)) {
...
}
...
null
y un programador elimina posteriormente su referencia al presuponer de forma incorrecta que siempre está 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()
y Comparator.compare()
devuelvan un valor especificado si sus parámetros son null
. De no cumplir el contrato se daría lugar a un comportamiento inesperado.equals()
no compara su parámetro con null
.
public boolean equals(Object object)
{
return (toString().equals(object.toString()));
}
FormAction
de Spring WebFlow que no valida los datos contra los requisitos esperados:Ejemplo 2: El siguiente código define un estado de acción de Spring WebFlow que no valida los datos con respecto a los requisitos esperados:
<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()
de la clase, no se invoca el constructor para la clase que se está clonando. Así pues, si hay una comprobación SecurityManager o AccessController en el constructor de una clase clonable, debe estar presente la misma comprobación en el método de clonación de la clase. De no ser así, la comprobación de seguridad se derivará cuando se clone la clase.SecurityManager
en el constructor, pero no en el 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
en su constructor tiene que realizar la misma comprobación en sus métodos readObject()
y readObjectNoData
.readObject()
de una clase serializable, no se invoca el constructor para la clase que se está deserializando. Así pues, si hay una comprobación SecurityManager
en el constructor de una clase serializable, también debe estar presente la misma comprobación SecurityManager
en los métodos readObject()
y readObjectNoData()
. De no ser así, la comprobación de seguridad se derivará cuando la clase se deserialice.SecurityManager
en el constructor, pero no en los métodos readObject()
y 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
contiene alguno de los valores esperados. Si un usuario malintencionado introduce un valor de tipo como :value = :value OR :value
, entonces la consulta será como se muestra a continuación::value = :value OR :value = :value AND Password = :password
:value = :value
hace que la cláusula where siempre se evalúe como true, por lo que la consulta devuelve todas las entradas almacenadas en la colección users
, sin importar el propietario del correo electrónico.
...
// "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
contiene alguno de los valores esperados. Si un usuario malintencionado introduce un valor de tipo como :value = :value OR :value
, entonces la consulta será como se muestra a continuación::value = :value OR :value = :value AND Password = :password
:value = :value
hace que la cláusula where siempre se evalúe como true, por lo que la consulta devuelve todas las entradas almacenadas en la colección users
, sin importar el propietario del correo electrónico.
...
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
no contiene un carácter de comilla simple. Si un atacante con el nombre de usuario wiley
introduce la cadena "123' || '4' != '5
" para emailId
, la consulta se convertirá en lo siguiente:
this.owner == 'wiley' && this.emailId == '123' || '4' != '5'
|| '4' != '5'
hace que la cláusula where siempre se evalúe como true
, por lo que la consulta devuelve todas las entradas almacenadas en la colección emails
, independientemente del propietario del correo electrónico.
...
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
no contiene un carácter de comilla doble. Si un atacante con el nombre de usuario wiley
introduce la cadena "123" || "4" != "5
" para emailId
, la consulta se convertirá en lo siguiente:
this.owner == "wiley" && this.emailId == "123" || "4" != "5"
|| "4" != "5"
hace que la cláusula where siempre se evalúe como true, por lo que la consulta devuelve todas las entradas almacenadas en la colección emails
, sin importar el propietario del correo electrónico.
...
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
no contiene un carácter de comilla doble. Si un atacante con el nombre de usuario wiley
introduce la cadena "123" || "4" != "5
" para emailId
, la consulta se convertirá en lo siguiente:
this.owner == "wiley" && this.emailId == "123" || "4" != "5"
|| "4" != "5"
, la cláusula where
siempre se evalúa como true, por lo que la consulta devuelve todas las entradas almacenadas en la colección emails
, sin importar el propietario del correo electrónico.NullException
.cmd
". Si un usuario malintencionado puede controlar el entorno del programa para que no se defina "cmd
", el programa genera una excepción de puntero nulo al intentar llamar al método Trim()
.
string cmd = null;
...
cmd = Environment.GetEnvironmentVariable("cmd");
cmd = cmd.Trim();
null
antes de comprobar si es null
o no. Los errores de desreferencia tras la comprobación se producen cuando un programa realiza una comprobación explícita de null
y procede a desreferenciar el puntero cuando se sabe que es null
. Los errores de este tipo son normalmente el resultado de errores de escritura o descuidos del programador. Los errores de desreferencia tras el almacenamiento se producen cuando un programa establece de forma explícita un puntero en null
y luego lo desreferencia. Con frecuencia, el error es el resultado de que un programador inicialice una variable en null
cuando se declara.ptr
no es NULL
. Esta suposición se hace explícita cuando el programador desreferencia el puntero. Esta suposición luego queda contradicha cuando el programador contrasta ptr
y NULL
. Si ptr
puede ser NULL
al comprobarla en la instrucción if
, entonces también puede ser NULL
cuando se desreferencia y podría ocasionar un error de segmentación.Ejemplo 2: En el código siguiente, el programador confirma que la variable
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
es NULL
y por eso lo desreferencia erróneamente. Si ptr
es NULL
cuando se comprueba en la instrucción if
, entonces se produce una desreferencia de null
que provocará un error de segmentación.Ejemplo 3: En el código siguiente, el programador olvida que la cadena
if (ptr == null) {
ptr->field = val;
...
}
'\0'
es en realidad 0 o NULL
; por lo tanto, puede desreferenciar un puntero nulo y provocar un fallo de segmentación.Ejemplo 4: En el código siguiente, el programador establece explícitamente la variable
if (ptr == '\0') {
*ptr = val;
...
}
ptr
en NULL
. A continuación, el programador desreferencia ptr
antes de comprobar si en el objeto hay un valor null
.
*ptr = NULL;
...
ptr->field = val;
...
}
NullPointerException
.cmd
". Si un usuario malintencionado puede controlar el entorno del programa para que no se defina "cmd
", el programa genera una excepción de puntero nulo al intentar llamar al método trim()
.
String val = null;
...
cmd = System.getProperty("cmd");
if (cmd)
val = util.translateCommand(cmd);
...
cmd = val.trim();
clone()
debe llamar super.clone()
para obtener el nuevo objeto.clone()
deben obtener el nuevo objeto llamando super.clone()
. Si una clase no puede seguir esta convención, un método clone()
de subclase devolverá un objeto del tipo incorrecto.super.clone()
. Dada la forma en que Kibitzer
implementa clone()
, el método de clonación de FancyKibitzer
devolverá un objeto de tipo Kibitzer
en lugar 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()
y hashCode()
.a.equals(b) == true
, entonces a.hashCode() == b.hashCode()
. equals()
pero no hashCode()
.
public class halfway() {
public boolean equals(Object obj) {
...
}
}
saveState()
y restoreState()
.saveState(javax.faces.context.FacesContext)
como restoreState(javax.faces.context.FacesContext, java.lang.Object)
, o no implementar ninguna de ellos. Como estos dos métodos tienen una relación estrecha, no se pueden tener los métodos saveState(javax.faces.context.FacesContext)
y restoreState(javax.faces.context.FacesContext, java.lang.Object)
residiendo en diferentes niveles de la jerarquía de herencia.saveState()
y no restoreState()
, de forma que siempre está equivocada, independientemente de lo que pueda hacer cualquier clase
public class KibitzState implements StateHolder {
public Object saveState(FacesContext fc) {
...
}
}
SqlClientPermission
, que controla el modo en el que los usuarios pueden conectarse a una base de datos. En este ejemplo, el programa transfiere false
como segundo parámetro al constructor, que controla si los usuarios tienen permiso para establecer conexión con contraseñas en blanco. Al transferir el valor false a este parámetro, se indica que no deben permitirse contraseñas en blanco.
...
SCP = new SqlClientPermission(pstate, false);
...
PermissionState
transferido como primer parámetro reemplaza cualquier valor transferido al segundo parámetro, el constructor permite el uso de contraseñas en blanco para las conexiones de base de datos, lo que contradice el segundo argumento. Para rechazar las contraseñas en blanco, el programa debe transferir PermissionState.None
al primer parámetro del constructor. Debido a la ambigüedad en su funcionalidad, la versión de dos parámetros del constructor SqlClientPermission
se ha dejado de utilizar en favor de la versión de un único parámetro, que transmite el mismo grado de información sin el riesgo de interpretaciones erróneas.getpw()
para comprobar que una contraseña de texto sin formato coincide con una contraseña cifrada del usuario. Si la contraseña es válida, la función establece result
en 1; de lo contrario, se establece en 0.
...
getpw(uid, pwdline);
for (i=0; i<3; i++){
cryptpw=strtok(pwdline, ":");
pwdline=0;
}
result = strcmp(crypt(plainpw,cryptpw), cryptpw) == 0;
...
getpw(
) puede provocar problemas desde el punto de vista de la seguridad, ya que puede desbordar el búfer que pasa a su segundo parámetro. Debido a esta vulnerabilidad, getpw()
se ha sustituido por getpwuid()
, que realiza la misma búsqueda que getpw()
, pero que devuelve un puntero a una estructura asignada estadísticamente para mitigar el riesgo.
...
String name = new String(nameBytes, highByte);
...
nameBytes
. Debido a la evolución de los juegos de caracteres utilizados para codificar cadenas, este constructor quedó obsoleto y reemplazado por un constructor que acepta como uno de sus parámetros el nombre del charset
que se utiliza para codificar los bytes para la conversión.Digest::HMAC
, cuyo uso está explícitamente contraindicado en la documentación debido a su implicación accidental dentro de una versión.
require 'digest/hmac'
hmac = Digest::HMAC.new("foo", Digest::RMD160)
...
hmac.update(buf)
...
Digest::HMAC
dejó de utilizarse de forma inmediata al estar implicada en una inclusión accidental dentro de una versión. Debido a la posibilidad de que no funcione según lo previsto a causa del código experimental o no probado adecuadamente, su uso está fuertemente contraindicado, especialmente si consideramos la relación que tienen los códigos HMAC con la funcionalidad criptográfica.checkCallingOrSelfPermission()
o checkCallingOrSelfUriPermission()
determina si el programa que realiza la llamada cuenta con el permiso necesario para acceder a determinado servicio o URI. Sin embargo, estas funciones deben utilizarse con cuidado, ya que pueden conceder acceso a aplicaciones malintencionadas, que carecen de los permisos correspondientes, adoptando los permisos de las aplicaciones.
IPAddress hostIPAddress = IPAddress.Parse(RemoteIpAddress);
IPHostEntry hostInfo = Dns.GetHostByAddress(hostIPAddress);
if (hostInfo.HostName.EndsWith("trustme.com")) {
trusted = true;
}
getlogin()
es fácil de reemplazar. Por eso, no confíe en el nombre que devuelva.getlogin()
devuelve una cadena que contiene el nombre del usuario registrado actualmente en el terminal. Sin embargo, un atacante podría hacer que getlogin()
devuelva el nombre de todos los usuarios registrado en el equipo. No confíe en el nombre devuelto por getlogin()
cuando tome decisiones relacionadas con la seguridad.getlogin()
para determinar si un usuario es de confianza o no. Es fácil de subvertir.
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()
se confunde a menudo con las llamadas a métodos Boolean.valueOf()
o Boolean.parseBoolean()
.Boolean.getBoolean()
se usa a menudo incorrectamente, ya que se presupone que devuelve el valor booleano representado por el argumento de cadena especificado. Sin embargo, como se indica en el método Boolean.getBoolean(String)
de Javadoc: "Devuelve el valor 'true' solo si existe la propiedad del sistema a la que el argumento ha asignado un nombre y esta es igual a la cadena 'true'".Boolean.valueOf(String)
o Boolean.parseBoolean(String)
.Boolean.getBoolean(String)
no convierte un primitivo de cadena, sino únicamente la propiedad del sistema.
...
String isValid = "true";
if ( Boolean.getBoolean(isValid) ) {
System.out.println("TRUE");
}
else {
System.out.println("FALSE");
}
...