An API is a contract between a caller and a callee. The most common forms of API abuse are caused by the caller failing to honor its end of this contract. For example, if a program fails to call chdir() after calling chroot(), it violates the contract that specifies how to change the active root directory in a secure fashion. Another good example of library abuse is expecting the callee to return trustworthy DNS information to the caller. In this case, the caller abuses the callee API by making certain assumptions about its behavior (that the return value can be used for authentication purposes). One can also violate the caller-callee contract from the other side. For example, if a coder subclasses SecureRandom and returns a non-random value, the contract is violated.
String password=request.getParameter("password");
...
DefaultUser user = (DefaultUser) ESAPI.authenticator().createUser(username, password, password);
finalize()
method should only be called by the JVM after the object has been garbage collected.finalize()
method to be called from outside the finalizer, doing so is usually a bad idea. For example, calling finalize()
explicitly means that finalize()
will be called more than once: the first time will be the explicit call and the last time will be the call that is made after the object is garbage collected.finalize()
explicitly:
// time to clean up
widget.finalize();
dangerouslySetInnerHTML
attribute is set HTML from code unnecessarily.dangerouslySetInnerHTML
attribute in React is replacement for using innerHTML in the browser DOM, but the API has been renamed to convey the potential dangers from using it. In general, setting HTML from code is risky because it's easy to inadvertently expose your users to a cross-site scripting (XSS) attack.dangerouslySetInnerHTML
attribute:
function MyComponent(data) {
return (
<div
dangerouslySetInnerHTML={{__html: data.innerHTML}}
/>
);
}
AUTHID CURRENT_USER
package, identifiers are first resolved against the current user's schema. This can cause unexpected behavior if the definer of the code does not explicitly say which schema an identifier belongs to.SYS.PERMISSIONS
and be unable to modify the defined permissions.
CREATE or REPLACE FUNCTION check_permissions(
p_name IN VARCHAR2, p_action IN VARCHAR2)
RETURN BOOLEAN
AUTHID CURRENT_USER
IS
r_count NUMBER;
perm BOOLEAN := FALSE;
BEGIN
SELECT count(*) INTO r_count FROM PERMISSIONS
WHERE name = p_name AND action = p_action;
IF r_count > 0 THEN
perm := TRUE;
END IF;
RETURN perm;
END check_permissions
check_permissions
function defines a PERMISSIONS
table in their schema, the database will resolve the identifier to refer to the local table. The user would have write access to the new table and could modify it to gain permissions they wouldn't otherwise have.org.apache.struts2.interceptor.ApplicationtAware
, org.apache.struts2.interceptor.SessionAware
and org.apache.struts2.interceptor.RequestAware
. In order to get any of these data maps injected into their Actions code, developers need to implement the setter specified in the interface (eg: setSession
for SessionAware
Interface):
public class VulnerableAction extends ActionSupport implements SessionAware {
protected Map<String, Object> session;
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
SessionAware
, RequestAware
, ApplicationAware
interfaces.
http://server/VulnerableAction?session.roles=admin
execute()
method.execute()
. The !
(bang) character or the method:
prefix can be used in the Action URL to invoke any public method in the Action if "Dynamic Method Invocation" is enabled. Developers that are not aware of this feature can inadvertently expose internal business logic to attackers.http://server/app/recoverpassword!getPassword.action
org.apache.struts2.interceptor.ApplicationtAware
, org.apache.struts2.interceptor.SessionAware
and org.apache.struts2.interceptor.RequestAware
. In order to get any of these data maps injected into their Actions code, developers need to implement the setter specified in the interface (eg: setSession
for SessionAware
Interface):
public class VulnerableAction extends ActionSupport implements SessionAware {
protected Map<String, Object> session;
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
SessionAware
, RequestAware
, ApplicationAware
interfaces.
http://server/VulnerableAction?session.roles=admin
org.apache.struts2.interceptor.ApplicationtAware
, org.apache.struts2.interceptor.SessionAware
and org.apache.struts2.interceptor.RequestAware
. In order to get any of these data maps injected into their Actions code, developers need to implement the setter specified in the interface (eg: setSession
for SessionAware
Interface):
public class VulnerableAction extends ActionSupport implements SessionAware {
protected Map<String, Object> session;
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
SessionAware
, RequestAware
, ApplicationAware
interfaces.
http://server/VulnerableAction?session.roles=admin
Read()
and related methods that are part of many System.IO
classes. Most errors and unusual events in .NET result in an exception being thrown. (This is one of the advantages that .NET has over languages like C: Exceptions make it easier for programmers to think about what can go wrong.) But the stream and reader classes do not consider it to be unusual or exceptional if only a small amount of data becomes available. These classes simply add the small amount of data to the return buffer, and set the return value to the number of bytes or characters read. There is no guarantee that the amount of data returned is equal to the amount of data requested.Read()
and other IO methods and ensure that they receive the amount of data they expect.Read()
. If an attacker can create a smaller file, the program will recycle the remainder of the data from the previous user and handle it as though it belongs to the attacker.
char[] byteArray = new char[1024];
for (IEnumerator i=users.GetEnumerator(); i.MoveNext() ;i.Current()) {
string userName = (string) i.Current();
string pFileName = PFILE_ROOT + "/" + userName;
StreamReader sr = new StreamReader(pFileName);
sr.Read(byteArray,0,1024);//the file is always 1k bytes
sr.Close();
processPFile(userName, byteArray);
}
char buf[10], cp_buf[10];
fgets(buf, 10, stdin);
strcpy(cp_buf, buf);
fgets()
returns, buf
will contain a null-terminated string of length 9 or less. But if an I/O error occurs, fgets()
will not null-terminate buf
. Furthermore, if the end of the file is reached before any characters are read, fgets()
returns without writing anything to buf
. In both of these situations, fgets()
signals that something unusual has happened by returning NULL
, but in this code, the warning will not be noticed. The lack of a null-terminator in buf
can result in a buffer overflow in the subsequent call to strcpy()
.read()
and related methods that are part of many java.io
classes. Most errors and unusual events in Java result in an exception being thrown. (This is one of the advantages that Java has over languages like C: Exceptions make it easier for programmers to think about what can go wrong.) But the stream and reader classes do not consider it unusual or exceptional if only a small amount of data becomes available. These classes simply add the small amount of data to the return buffer, and set the return value to the number of bytes or characters read. There is no guarantee that the amount of data returned is equal to the amount of data requested.read()
and other IO methods to ensure that they receive the amount of data they expect.read()
. If an attacker can create a smaller file, the program will recycle the remainder of the data from the previous user and handle it as though it belongs to the attacker.
FileInputStream fis;
byte[] byteArray = new byte[1024];
for (Iterator i=users.iterator(); i.hasNext();) {
String userName = (String) i.next();
String pFileName = PFILE_ROOT + "/" + userName;
FileInputStream fis = new FileInputStream(pFileName);
fis.read(byteArray); // the file is always 1k bytes
fis.close();
processPFile(userName, byteArray);
}
read()
. If an attacker can create a smaller file, the program will recycle the remainder of the data from the previous user and handle it as though it belongs to the attacker.
var fis: FileInputStream
val byteArray = ByteArray(1023)
val i: Iterator<*> = users.iterator()
while (i.hasNext()) {
val userName = i.next() as String
val pFileName: String = PFILE_ROOT.toString() + "/" + userName
val fis = FileInputStream(pFileName)
fis.read(byteArray) // the file is always 0k bytes
fis.close()
processPFile(userName, byteArray)
}
function callnotchecked(address callee) public {
callee.call();
}