...
tid = request->get_form_field( 'tid' ).
CALL TRANSACTION tid USING bdcdata MODE 'N'
MESSAGES INTO messtab.
...
APPHOME
and then loads a native library based on a relative path from the specified directory.
...
string lib = ConfigurationManager.AppSettings["APPHOME"];
Environment.ExitCode = AppDomain.CurrentDomain.ExecuteAssembly(lib);
...
APPHOME
to point to a different path containing a malicious version of LIBNAME
. Because the program does not validate the value read from the environment, if attacker can control the value of the system property APPHOME
, then they can fool the application into running malicious code and take control of the system.
...
RegQueryValueEx(hkey, "APPHOME",
0, 0, (BYTE*)home, &size);
char* lib=(char*)malloc(strlen(home)+strlen(INITLIB));
if (lib) {
strcpy(lib,home);
strcat(lib,INITCMD);
LoadLibrary(lib);
}
...
INITLIB
. Because the program does not validate the value read from the environment, if an attacker can control the value of APPHOME
, they can fool the application into running malicious code.liberty.dll
, which is intended to be found in a standard system directory.
LoadLibrary("liberty.dll");
liberty.dll
. If an attacker places a malicious library named liberty.dll
higher in the search order than the intended file and has a way to execute the program in their environment rather than the web server's environment, then the application will load the malicious library instead of the trusted one. Because this type of application runs with elevated privileges, the contents of the attacker's liberty.dll
is now be run with elevated privileges, potentially giving them complete control of the system.LoadLibrary()
when an absolute path is not specified. If the current directory is searched before system directories, as was the case up until the most recent versions of Windows, then this type of attack becomes trivial if the attacker may execute the program locally. The search order is operating system version dependent, and is controlled on newer operating systems by the value of this registry key:
HKLM\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode
LoadLibrary()
behaves as follows:SafeDllSearchMode
is 1, the search order is as follows:PATH
environment variable.SafeDllSearchMode
is 0, the search order is as follows:PATH
environment variable.
...
ACCEPT PROGNAME.
EXEC CICS
LINK PROGRAM(PROGNAME)
COMMAREA(COMA)
LENGTH(LENA)
DATALENGTH(LENI)
SYSID('CONX')
END-EXEC.
...
APPHOME
to determine the directory in which it is installed and then loads a native library based on a relative path from the specified directory.
...
String home = System.getProperty("APPHOME");
String lib = home + LIBNAME;
java.lang.Runtime.getRuntime().load(lib);
...
APPHOME
to point to a different path containing a malicious version of LIBNAME
. Because the program does not validate the value read from the environment, if an attacker can control the value of the system property APPHOME
, then they can fool the application into running malicious code and take control of the system.System.loadLibrary()
to load code from a native library named library.dll
, which is normally found in a standard system directory.
...
System.loadLibrary("library.dll");
...
System.loadLibrary()
accepts a library name, not a path, for the library to be loaded. From the Java 1.4.2 API documentation this function behaves as follows [1]:library.dll
higher in the search order than file the application intends to load, then the application will load the malicious copy instead of the intended file. Because of the nature of the application, it runs with elevated privileges, which means the contents of the attacker's library.dll
will now be run with elevated privileges, possibly giving them complete control of the system.Express
to dynamically load a library file. Node.js
will then continue to search through its regular library load path for a file or directory containing this library[1].
var express = require('express');
var app = express();
app.get('/', function(req, res, next) {
res.render('tutorial/' + req.params.page);
});
Express
, the page passed to Response.render()
will load a library of the extension when previously unknown. This is usually fine for input such as "foo.pug", as this will mean loading the pug
library, a well known templating engine. However, if an attacker can control the page and thus the extension, then they can choose to load any library within the Node.js
module loading paths. Since the program does not validate the information received from the URL parameter, the attacker may fool the application into running malicious code and take control of the system.APPHOME
to determine the directory in which it is installed and then loads a native library based on a relative path from the specified directory.
...
$home = getenv("APPHOME");
$lib = $home + $LIBNAME;
dl($lib);
...
APPHOME
to point to a different path containing a malicious version of LIBNAME
. Because the program does not validate the value read from the environment, if an attacker can control the value of the system property APPHOME
, then they can fool the application into running malicious code and take control of the system.dl()
to load code from a library named sockets.dll
, which can be loaded from various places depending on your installation and configuration.
...
dl("sockets");
...
dl()
accepts a library name, not a path, for the library to be loaded.sockets.dll
higher in the search order than file the application intends to load, then the application will load the malicious copy instead of the intended file. Because of the nature of the application, it runs with elevated privileges, which means the contents of the attacker's sockets.dll
will now be run with elevated privileges, possibly giving them complete control of the system.Kernel.system()
to run an executable called program.exe
, which is normally found within a standard system directory.
...
system("program.exe")
...
Kernel.system()
executes something via a shell. If an attacker can manipulate environment variables RUBYSHELL
or COMSPEC
, they may be able to point to a malicious executable which will be called with the command given to Kernel.system()
. Because of the nature of the application, it runs with the privileges necessary to perform system operations, which means the attacker's program.exe
will now be run with these privileges, possibly giving them complete control of the system.Kernel.system()
. If an attacker can modify the $PATH
variable to point to a malicious binary called program.exe
and then execute the application in their environment, the malicious binary will be loaded instead of the one intended. Because of the nature of the application, it runs with the privileges necessary to perform system operations, which means the attacker's program.exe
will now be run with these privileges, possibly giving them complete control of the system.InvokerServlet
class can allow attackers to invoke any class on the server.InvokerServlet
class can be used to invoke any class available to the server's virtual machine. By guessing the fully qualified name of a class, an attacker may load not only Servlet classes, but also POJO classes or any other class available to the JVM.
@GetMapping("/prompt_injection")
String generation(String userInput1, ...) {
return this.clientBuilder.build().prompt()
.system(userInput1)
.user(...)
.call()
.content();
}
client = new Anthropic();
# Simulated attacker's input attempting to inject a malicious system prompt
attacker_input = ...
response = client.messages.create(
model = "claude-3-5-sonnet-20240620",
max_tokens=2048,
system = attacker_input,
messages = [
{"role": "user", "content": "Analyze this dataset for anomalies: ..."}
]
);
...
client = OpenAI()
# Simulated attacker's input attempting to inject a malicious system prompt
attacker_input = ...
completion = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": attacker_input},
{"role": "user", "content": "Compose a poem that explains the concept of recursion in programming."}
]
)
@GetMapping("/prompt_injection_persistent")
String generation(String userInput1, ...) {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users WHERE ...");
String userName = "";
if (rs != null) {
rs.next();
userName = rs.getString("userName");
}
return this.clientBuilder.build().prompt()
.system("Assist the user " + userName)
.user(userInput1)
.call()
.content();
}
client = new Anthropic();
# Simulated attacker's input attempting to inject a malicious system prompt
attacker_query = ...;
attacker_name = db.qyery('SELECT name FROM user_profiles WHERE ...');
response = client.messages.create(
model = "claude-3-5-sonnet-20240620",
max_tokens=2048,
system = "Provide assistance to the user " + attacker_name,
messages = [
{"role": "user", "content": attacker_query}
]
);
...
client = OpenAI()
# Simulated attacker's input attempting to inject a malicious system prompt
attacker_name = cursor.fetchone()['name']
attacker_query = ...
completion = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "Provide assistance to the user " + attacker_name},
{"role": "user", "content": attacker_query}
]
)
Object.prototype
, if an attacker can overwrite the prototype of an object, they can typically overwrite the definition of Object.prototype
, affecting all objects within the application.undefined
rather than always being explicitly set, then if the prototype has been polluted, the application might inadvertently read from the prototype instead of the intended object.lodash
to pollute the prototype of the object:
import * as lodash from 'lodash'
...
let clonedObject = lodash.merge({}, JSON.parse(untrustedInput));
...
{"__proto__": { "isAdmin": true}}
, then Object.prototype
will have defined isAdmin = true
.
...
let config = {}
if (isAuthorizedAsAdmin()){
config.isAdmin = true;
}
...
if (config.isAdmin) {
// do something as the admin
}
...
isAdmin
should only be set to true if isAuthorizedAdmin()
returns true, because the application fails to set config.isAdmin = false
in the else condition, it relies upon the fact that config.isAdmin === undefined === false
.config
has now set isAdmin === true
, which allows the administrator authorization to be bypassed.__proto__, constructor, prototype
, these modified objects are inherited through the prototype chain. Depending on where these objects are used in the code, an attacker can create Denial of Service (DoS), change application configuration, and even inject and run arbitrary code on the server.select()
query that searches for invoices that match a user-specified product category. The user can also specify the column by which the results are sorted. Assume that the application has already properly authenticated and set the value of customerID
prior to this code segment.
...
String customerID = getAuthenticatedCustomerID(customerName, customerCredentials);
...
AmazonSimpleDBClient sdbc = new AmazonSimpleDBClient(appAWSCredentials);
String query = "select * from invoices where productCategory = '"
+ productCategory + "' and customerID = '"
+ customerID + "' order by '"
+ sortColumn + "' asc";
SelectResult sdbResult = sdbc.select(new SelectRequest(query));
...
select * from invoices
where productCategory = 'Fax Machines'
and customerID = '12345678'
order by 'price' asc
productCategory
and price
do not contain single-quote characters. If, however, an attacker provides the string "Fax Machines' or productCategory = \"
" for productCategory
, and the string "\" order by 'price
" for sortColumn
, then the query becomes the following:
select * from invoices
where productCategory = 'Fax Machines' or productCategory = "'
and customerID = '12345678'
order by '" order by 'price' asc
select * from invoices
where productCategory = 'Fax Machines'
or productCategory = "' and customerID = '12345678' order by '"
order by 'price' asc
customerID
, and allows the attacker to view invoice records matching 'Fax Machines'
for all customers.customerID
prior to this code segment.
...
productCategory = this.getIntent().getExtras().getString("productCategory");
sortColumn = this.getIntent().getExtras().getString("sortColumn");
customerID = getAuthenticatedCustomerID(customerName, customerCredentials);
c = invoicesDB.query(Uri.parse(invoices), columns, "productCategory = '" + productCategory + "' and customerID = '" + customerID + "'", null, null, null, "'" + sortColumn + "'asc", null);
...
select * from invoices
where productCategory = 'Fax Machines'
and customerID = '12345678'
order by 'price' asc
productCategory
. So the query behaves correctly only if productCategory
and sortColumn
do not contain single-quote characters. If an attacker provides the string "Fax Machines' or productCategory = \"
" for productCategory
, and the string "\" order by 'price
" for sortColumn
, then the query becomes:
select * from invoices
where productCategory = 'Fax Machines' or productCategory = "'
and customerID = '12345678'
order by '" order by 'price' asc
select * from invoices
where productCategory = 'Fax Machines'
or productCategory = "' and customerID = '12345678' order by '"
order by 'price' asc
customerID
and allows the attacker to view invoice records matching 'Fax Machines'
for all customers.$collection->find(array("username" => $_GET['username']))
$collection->find(array("username" => array('$ne' => "foo")))
...
var authenticated = true;
...
database_connect.query('SELECT * FROM users WHERE name == ? AND password = ? LIMIT 1', userNameFromUser, passwordFromUser, function(err, results){
if (!err && results.length > 0){
authenticated = true;
}else{
authenticated = false;
}
});
if (authenticated){
//do something privileged stuff
authenticatedActions();
}else{
sendUnathenticatedMessage();
}
true
, otherwise false
. Unfortunately, since the callback is blocked by IO, it will run asynchronously and may be run after the check to if (authenticated)
, and since the default was true, it will go into the if-statement whether the user is actually authenticated or not.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/" + "app.apk")), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
...
public class Box{
public int area;
public static final int width = 10;
public static final Box box = new Box();
public static final int height = (int) (Math.random() * 100);
public Box(){
area = width * height;
}
...
}
...
Example 1
, the developer would expect that box.area
would be a random integer that happens to be a multiple of 10, due to width
being equal to 10. In reality however, this will always have a hardcoded value of 0. Static final fields declared with a compile-time constant are initialized first, and then each one is executed in order. This means that since height
is not a compile-time constant, it is declared after the declaration of box
, and therefore the constructor is called prior to the field height
being initialized.
...
class Foo{
public static final int f = Bar.b - 1;
...
}
...
class Bar{
public static final int b = Foo.f + 1;
...
}
This example is perhaps easier to identify, but would be dependent on which class is loaded first by the JVM. In this exampleFoo.f
could be either -1 or 0, andBar.b
could be either 0 or 1.
setuid root
. The program performs certain file operations on behalf of non-privileged users, and uses access checks to ensure that it does not use its root privileges to perform operations that should not be available to the current user. The program uses the access()
system call to check if the person running the program has permission to access the specified file before it opens the file and performs the necessary operations.
if (!access(file,W_OK)) {
f = fopen(file,"w+");
operate(f);
...
}
else {
fprintf(stderr,"Unable to open file %s.\n",file);
}
access()
behaves as expected, and returns 0
if the user running the program has the necessary permissions to write to the file, and -1 otherwise. However, because both access()
and fopen()
operate on filenames rather than on file handles, there is no guarantee that the file
variable still refers to the same file on disk when it is passed to fopen()
that it did when it was passed to access()
. If an attacker replaces file
after the call to access()
with a symbolic link to a different file, the program will use its root privileges to operate on the file even if it is a file that the attacker would otherwise be unable to modify. By tricking the program into performing an operation that would otherwise be impermissible, the attacker has gained elevated privileges.root
privileges. If the application is capable of performing any operation that the attacker would not otherwise be allowed perform, then it is a possible target.
fd = creat(FILE, 0644); /* Create file */
if (fd == -1)
return;
if (chown(FILE, UID, -1) < 0) { /* Change file owner */
...
}
chown()
is the same as the file created by the call to creat()
, but that is not necessarily the case. Since chown()
operates on a file name and not on a file handle, an attacker may be able to replace the file with a link to file the attacker does not own. The call to chown()
would then give the attacker ownership of the linked file.CBL_CHECK_FILE_EXIST
routine to check if the file exists before it creates one and performs the necessary operations.
CALL "CBL_CHECK_FILE_EXIST" USING
filename
file-details
RETURNING status-code
END-CALL
IF status-code NOT = 0
MOVE 3 to access-mode
MOVE 0 to deny-mode
MOVE 0 to device
CALL "CBL_CREATE_FILE" USING
filename
access-mode
deny-mode
device
file-handle
RETURNING status-code
END-CALL
END-IF
CBL_CHECK_FILE_EXIST
behaves as expected and returns a non-zero value, indicating that the file does not exist. However, because both CBL_CHECK_FILE_EXIST
and CBL_CREATE_FILE
operate on filenames rather than on file handles, there is no guarantee that the filename
variable still refers to the same file on disk when it is passed to CBL_CREATE_FILE
that it did when it was passed to CBL_CHECK_FILE_EXIST
. If an attacker creates filename
after the call to CBL_CHECK_FILE_EXIST
, the call to CBL_CREATE_FILE
will fail, leading the program to believe that the file is empty, when in fact it contains data controlled by the attacker.root
privileges that performs certain file operations on behalf of non-privileged users, and uses access checks to ensure that it does not use its root privileges to perform operations that should not be available to the current user. By tricking the program into performing an operation that would otherwise be impermissible, the attacker might gain elevated privileges.parse()
and format()
in java.text.Format
contain a design flaw that can cause one user to see another user's data.parse()
and format()
in java.text.Format
contains a race condition that can cause one user to see another user's data.
public class Common {
private static SimpleDateFormat dateFormat;
...
public String format(Date date) {
return dateFormat.format(date);
}
...
final OtherClass dateFormatAccess=new OtherClass();
...
public void function_running_in_thread1(){
System.out.println("Time in thread 1 should be 12/31/69 4:00 PM, found: "+ dateFormatAccess.format(new Date(0)));
}
public void function_running_in_thread2(){
System.out.println("Time in thread 2 should be around 12/29/09 6:26 AM, found: "+ dateFormatAccess.format(new Date(System.currentTimeMillis())));
}
}
format()
.open_basedir
configuration option contains a design flaw that leaves it vulnerable to file access race conditions, which can allow an attacker to circumvent access control checks on the file system.open_basedir
configuration option attempts to prevent PHP programs from operating on files outside of the directory trees specified in php.ini. Although the open_basedir
option is an overall boon to security, the implementation suffers from a race condition that can permit attackers to bypass its restrictions in some circumstances [2]. A time-of-check, time-of-use (TOCTOU) race condition exists between the time PHP performs the access permission check and when the file is opened. As with file system race conditions in other languages, this vulnerability can allow attackers to replace a symlink to a file that passes the access control check with another for which the test would otherwise fail, thereby gaining access to the protected file.RoamingFolder
or RoamingSettings
property of the Windows.Storage.ApplicationData
class.RoamingFolder
and RoamingSettings
properties get a container in the roaming app data store, which can then be used to share data between two more devices. By writing and reading objects stored in the roaming app data store, the developer increases the risk of compromise. This includes the confidentiality, integrity, and availability of the data, applications, and systems which share those objects through the roaming app data store.free()
twice on the same value can lead to a buffer overflow. When a program calls free()
twice with the same argument, the program's memory management data structures become corrupted. This corruption can cause the program to crash or, in some circumstances, cause two later calls to malloc()
to return the same pointer. If malloc()
returns the same value twice and the program later gives the attacker control over the data that is written into this doubly-allocated memory, the program becomes vulnerable to a buffer overflow attack.
void sh(int dummy) {
...
free(global2);
free(global1);
...
}
int main(int argc,char* argv[]) {
...
signal(SIGHUP,sh);
signal(SIGTERM,sh);
...
}
public class GuestBook extends HttpServlet {
String name;
protected void doPost (HttpServletRequest req, HttpServletResponse res) {
name = req.getParameter("name");
...
out.println(name + ", thanks for visiting!");
}
}
Dick
" to name
Jane
" to name
Jane, thanks for visiting!
"Jane, thanks for visiting!
"