Path.Combine
takes several file paths as arguments. It concatenates them to get a full path, which is typically followed by a call to read()
or write()
to that file. The documentation describes several different scenarios based on whether the first or remaining parameters are absolute paths. Given an absolute path for the second or remaining parameters, Path.Combine()
will return that absolute path. The previous parameters will be ignored. The implications here are significant for applications that have code similar to the following example.
// Called with user-controlled data
public static bytes[] getFile(String filename)
{
String imageDir = "\\FILESHARE\images\";
filepath = Path.Combine(imageDir, filename);
return File.ReadAllBytes(filepath);
}
C:\\inetpub\wwwroot\web.config
), an attacker could control which file gets returned by the application.
public static void UnzipFile(ZipArchive archive, string destDirectory)
{
foreach (var entry in archive.Entries)
{
string file = entry.FullName;
if (!string.IsNullOrEmpty(file))
{
string destFileName = Path.Combine(destDirectory, file);
entry.ExtractToFile(destFileName, true);
}
}
}
Example 1
, there is no validation of entry.FullName
prior to performing read/write operations on the data within this entry. If the Zip file was originally placed in the directory "C:\TEMP
", a Zip entry name contained "..\
segments", and the application was run under the necessary permissions, it could arbitrarily overwrite system files.
func Unzip(src string, dest string) ([]string, error) {
var filenames []string
r, err := zip.OpenReader(src)
if err != nil {
return filenames, err
}
defer r.Close()
for _, f := range r.File {
// Store filename/path for returning and using later on
fpath := filepath.Join(dest, f.Name)
filenames = append(filenames, fpath)
if f.FileInfo().IsDir() {
// Make Folder
os.MkdirAll(fpath, os.ModePerm)
continue
}
// Make File
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return filenames, err
}
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return filenames, err
}
rc, err := f.Open()
if err != nil {
return filenames, err
}
_, err = io.Copy(outFile, rc)
// Close the file without defer to close before next iteration of loop
outFile.Close()
rc.Close()
if err != nil {
return filenames, err
}
}
return filenames, nil
}
Example 1
, there is no validation of f.Name
prior to performing read/write functions on the data within this entry. If the Zip file was originally placed in the directory "/tmp/
" of a Unix-based machine, a Zip entry was "../etc/hosts
", and the application was run under the necessary permissions, it would overwrite the system hosts
file. This in turn would allow traffic from the machine to go anywhere the attacker wants, such as back to the attacker's machine.
private static final int BUFSIZE = 512;
private static final int TOOBIG = 0x640000;
...
public final void unzip(String filename) throws IOException {
FileInputStream fis = new FileInputStream(filename);
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry zipEntry = null;
int numOfEntries = 0;
long total = 0;
try {
while ((zipEntry = zis.getNextEntry()) != null) {
byte data[] = new byte[BUFSIZE];
int count = 0;
String outFileName = zipEntry.getName();
if (zipEntry.isDirectory()){
new File(outFileName).mkdir(); //create the new directory
continue;
}
FileOutputStream outFile = new FileOutputStream(outFileName);
BufferedOutputStream dest = new BufferedOutputStream(outFile, BUFSIZE);
//read data from Zip, but do not read huge entries
while (total + BUFSIZE <= TOOBIG && (count = zis.read(data, 0, BUFSIZE)) != -1) {
dest.write(data, 0, count);
total += count;
}
...
}
} finally{
zis.close();
}
}
...
Example 1
, there is no validation of zipEntry.getName()
prior to performing read/write functions on the data within this entry. If the Zip file was originally placed in the directory "/tmp/
" of a Unix-based machine, a Zip entry was "../etc/hosts
", and the application was run under the necessary permissions, it would overwrite the system hosts
file. This in turn would allow traffic from the machine to go anywhere the attacker wants, such as back to the attacker's machine.
var unzipper = require('unzipper');
var fs = require('fs');
var untrusted_zip = getZipFromRequest();
fs.createReadStream(zipPath).pipe(unzipper.Extract({ path: 'out' }));
ZZArchive* archive = [ZZArchive archiveWithURL:[NSURL fileURLWithPath: zipPath] error:&error];
for (ZZArchiveEntry* entry in archive.entries) {
NSString *fullPath = [NSString stringWithFormat: @"%@/%@", destPath, [entry fileName]];
[[entry newDataWithError:nil] writeToFile:newFullPath atomically:YES];
}
Example 1
, there is no validation of entry.fileName
prior to performing read/write functions on the data within this entry. If the Zip file was originally placed in the directory "Documents/hot_patches
" of an iOS application, a Zip entry was "../js/page.js
", it would overwrite the page.js
file. This in turn would enable an attacker to inject malicious code that might result in code execution.
...
$zip = new ZipArchive();
$zip->open("userdefined.zip", ZipArchive::RDONLY);
$zpm = $zip->getNameIndex(0);
$zip->extractTo($zpm);
...
Example 1
, there is no validation of f.Name
before performing read/write functions on the data within this entry. If the Zip file is in the directory "/tmp/
" of a Unix-based machine, a Zip entry is "../etc/hosts
", and the application is run under the necessary permissions, it will overwrite the system hosts
file. This allows traffic from the machine to go anywhere the attacker wants, such as back to the attacker's machine.
import zipfile
import tarfile
def unzip(archive_name):
zf = zipfile.ZipFile(archive_name)
zf.extractall(".")
zf.close()
def untar(archive_name):
tf = tarfile.TarFile(archive_name)
tf.extractall(".")
tf.close()
Example 2: The following example extracts files from a Zip file and insecurely writes them to disk.
import better.files._
...
val zipPath: File = getUntrustedZip()
val destinationPath = file"out/dest"
zipPath.unzipTo(destination = destinationPath)
import better.files._
...
val zipPath: File = getUntrustedZip()
val destinationPath = file"out/dest"
zipPath.newZipInputStream.mapEntries( (entry : ZipEntry) => {
entry.extractTo(destinationPath, new FileInputStream(entry.getName))
})
Example 2
, there is no validation of entry.getName
prior to performing read/write functions on the data within this entry. If the Zip file was originally placed in the directory "/tmp/
" of a Unix-based machine, a Zip entry was "../etc/hosts
", and the application was run under the necessary permissions, it would overwrite the system hosts
file. This in turn would allow traffic from the machine to go anywhere the attacker wants, such as back to the attacker's machine.
let archive = try ZZArchive.init(url: URL(fileURLWithPath: zipPath))
for entry in archive.entries {
let fullPath = URL(fileURLWithPath: destPath + "/" + entry.fileName)
try entry.newData().write(to: fullPath)
}
Example 1
, there is no validation of entry.fileName
prior to performing read/write functions on the data within this entry. If the Zip file was originally placed in the directory "Documents/hot_patches
" of an iOS application, a Zip entry was "../js/page.js
", it would overwrite the page.js
file. This in turn would enable an attacker to inject malicious code that might result in code execution.FileIOPermissions
required in the application.
...
String permissionsXml = GetPermissionsFromXmlFile();
FileIOPermission perm = new FileIOPermission(PermissionState.None);
perm.FromXml(permissionsXml);
perm.Demand();
...
...
CrytoKeyAuditRule auditRule = new CryptoKeyAuditRule(IdRef, (CryptoKeyRights) input, AuditFlags.Success);
...
input
then they can specify what type of operation can be logged. If the user can manipulate this to CryptoKeyRights.Delete
, then they may be able to read the encryption key without it being logged, making you unaware that an attacker has stolen your encryption keys.doExchange()
.
try {
doExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
were to ever be thrown, the program would continue to execute as though nothing unusual had occurred. The program records no evidence indicating the special situation, potentially frustrating any later attempt to explain the program's behavior.DoExchange()
.
try {
DoExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
were to ever be thrown, the program would continue to execute as though nothing unusual had occurred. The program records no evidence indicating the special situation, potentially frustrating any later attempt to explain the program's behavior.doExchange()
.
try {
doExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
were to ever be thrown, the program would continue to execute as though nothing unusual had occurred. The program records no evidence indicating the special situation, potentially frustrating any later attempt to explain the program's behavior.doExchange()
.
try {
doExchange();
}
catch (exception $e) {
// this can never happen
}
RareException
were to ever be thrown, the program would continue to execute as though nothing unusual had occurred. The program records no evidence indicating the special situation, potentially frustrating any later attempt to explain the program's behavior.open()
.
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except:
# This will never happen
pass
RareException
were to ever be thrown, the program would continue to execute as though nothing unusual had occurred. The program records no evidence indicating the special situation, potentially frustrating any later attempt to explain the program's behavior.Exception
can obscure exceptions that deserve special treatment or that should not be caught at this point in the program. Catching an overly broad exception essentially defeats the purpose of .NET's typed exceptions, and can become particularly dangerous if the program grows and begins to throw new types of exceptions. The new exception types will not receive any attention.
try {
DoExchange();
}
catch (IOException e) {
logger.Error("DoExchange failed", e);
}
catch (FormatException e) {
logger.Error("DoExchange failed", e);
}
catch (TimeoutException e) {
logger.Error("DoExchange failed", e);
}
try {
DoExchange();
}
catch (Exception e) {
logger.Error("DoExchange failed", e);
}
DoExchange()
is modified to throw a new type of exception that should be handled in some different kind of way, the broad catch block will prevent the compiler from pointing out the situation. Further, the new catch block will now also handle exceptions of types ApplicationException
and NullReferenceException
, which is not the programmer's intent.Exception
can obscure exceptions that deserve special treatment or that should not be caught at this point in the program. Catching an overly broad exception essentially defeats the purpose of Java's typed exceptions, and can become particularly dangerous if the program grows and begins to throw new types of exceptions. The new exception types will not receive any attention.
try {
doExchange();
}
catch (IOException e) {
logger.error("doExchange failed", e);
}
catch (InvocationTargetException e) {
logger.error("doExchange failed", e);
}
catch (SQLException e) {
logger.error("doExchange failed", e);
}
try {
doExchange();
}
catch (Exception e) {
logger.error("doExchange failed", e);
}
doExchange()
is modified to throw a new type of exception that should be handled in some different kind of way, the broad catch block will prevent the compiler from pointing out the situation. Further, the new catch block will now also handle exceptions derived from RuntimeException
such as ClassCastException
, and NullPointerException
, which is not the programmer's intent.NullReferenceException
.NullReferenceException
under three circumstances:NullReferenceException
to signal an error condition.NullReferenceException
.
try {
MysteryMethod();
}
catch (NullReferenceException npe) {
}
Console.Out
or Console.Error
rather than a dedicated logging facility makes it difficult to monitor the program behavior.
public class MyClass {
...
Console.WriteLine("hello world");
...
}
Console.WriteLine()
.Console.WriteLine
may indicate an oversight in the move to a structured logging system.os.Stdout
or os.Stderr
rather than a dedicated logging facility makes it difficult to monitor the program behavior.
...
func foo(){
fmt.Println("Hello World")
}
fmt.Println()
.os.Stdout
or os.Stderr
might indicate an oversight in the move to a structured logging system.System.out
or System.err
rather than a dedicated logging facility makes it difficult to monitor the program behavior.
public class MyClass
...
System.out.println("hello world");
...
}
System.out.println()
.System.out
or System.err
may indicate an oversight in the move to a structured logging system.process.stdout
or process.stderr
rather than a dedicated logging facility makes it difficult to monitor the behavior of the program.
process.stdin.on('readable', function(){
var s = process.stdin.read();
if (s != null){
process.stdout.write(s);
}
});
process.stdout.write()
.process.stdout
or process.stderr
may indicate an oversight in the move to a structured logging system.print
or println
rather than a dedicated logging facility makes it difficult to monitor the program behavior.
class MyClass {
...
println("hello world")
...
}
}
print
or println
.
sys.stdout.write("hello world")
sys.stdout
or sys.stderr
may indicate an oversight in the move to a structured logging system.Kernel.puts
,Kernel.warn
or Kernel.printf
rather than a dedicated logging facility makes it difficult to monitor the behavior of the program.
...
puts "hello world"
...
Kernel.puts
.Kernel.puts
,Kernel.warn
or Kernel.printf
may indicate an oversight in the move to a structured logging system.Logger
class, but logs information to a system output stream:
require 'logger'
...
logger = Logger.new($stdout)
logger.info("hello world")
...
...
var file:File = new File(directoryName + "\\" + fileName);
...
...
FileStream f = File.Create(directoryName + "\\" + fileName);
...
...
File file = new File(directoryName + "\\" + fileName);
...
...
os.open(directoryName + "\\" + fileName);
...
...
uid = 'scott'.
password = 'tiger'.
WRITE: / 'Default username for FTP connection is: ', uid.
WRITE: / 'Default password for FTP connection is: ', password.
...
pass = getPassword();
...
trace(id+":"+pass+":"+type+":"+tstamp);
Example 1
logs a plain text password to the file system. Although many developers trust the file system as a safe storage location for data, it should not be trusted implicitly, particularly when privacy is a concern.
...
ResetPasswordResult passRes = System.resetPassword(id1, true);
System.Debug('New password: '+passRes.getPassword());
...
pass = GetPassword();
...
dbmsLog.WriteLine(id+":"+pass+":"+type+":"+tstamp);
Example 1
logs a plain text password to the file system. Although many developers trust the file system as a safe storage location for data, it should not be trusted implicitly, particularly when privacy is a concern.get_password()
function returns the user-supplied plain text password associated with the account.
pass = get_password();
...
fprintf(dbms_log, "%d:%s:%s:%s", id, pass, type, tstamp);
Example 1
logs a plain text password to the file system. Although many developers trust the file system as a safe storage location for any and all data, it should not be trusted implicitly, particularly when privacy is a concern.
...
MOVE "scott" TO UID.
MOVE "tiger" TO PASSWORD.
DISPLAY "Default username for database connection is: ", UID.
DISPLAY "Default password for database connection is: ", PASSWORD.
...
Session.pword
variable contains the plain text password associated with the account.
<cflog file="app_log" application="No" Thread="No"
text="#Session.uname#:#Session.pword#:#type#:#Now()#">
Example 1
logs a plain text password to the file system. Although many developers trust the file system as a safe storage location for data, it should not be trusted implicitly, particularly when privacy is a concern.
var pass = getPassword();
...
dbmsLog.println(id+":"+pass+":"+type+":"+tstamp);
Example 1
logs a plain text password to the file system. Although many developers trust the file system as a safe storage location for data, it should not be trusted implicitly, particularly when privacy is a concern.GetPassword()
function, which returns user-supplied plain text password associated with the account.
pass = GetPassword();
...
if err != nil {
log.Printf('%s: %s %s %s', id, pass, type, tsstamp)
}
Example 1
logs a plain text password to the application eventlog. Although many developers trust the eventlog as a safe storage location for data, it should not be trusted implicitly, particularly when privacy is a concern.
pass = getPassword();
...
dbmsLog.println(id+":"+pass+":"+type+":"+tstamp);
Example 1
logs a plain text password to the file system. Although many developers trust the file system as a safe storage location for data, it should not be trusted implicitly, particularly when privacy is a concern.
...
webview.setWebViewClient(new WebViewClient() {
public void onReceivedHttpAuthRequest(WebView view,
HttpAuthHandler handler, String host, String realm) {
String[] credentials = view.getHttpAuthUsernamePassword(host, realm);
String username = credentials[0];
String password = credentials[1];
Intent i = new Intent();
i.setAction("SEND_CREDENTIALS");
i.putExtra("username", username);
i.putExtra("password", password);
view.getContext().sendBroadcast(i);
}
});
...
SEND_CREDENTIALS
action will receive the message. The broadcast is not even protected with a permission to limit the number of recipients, although in this case we do not recommend using permissions as a fix.
localStorage.setItem('password', password);
pass = getPassword()
...
dbmsLog.println("$id:$pass:$type:$tstamp")
Example 1
logs a plain text password to the file system. Although many developers trust the file system as a safe storage location for data, it should not be trusted implicitly, particularly when privacy is a concern.
...
webview.webViewClient = object : WebViewClient() {
override fun onReceivedHttpAuthRequest(view: WebView,
handler: HttpAuthHandler, host: String, realm: String
) {
val credentials = view.getHttpAuthUsernamePassword(host, realm)
val username = credentials!![0]
val password = credentials[1]
val i = Intent()
i.action = "SEND_CREDENTIALS"
i.putExtra("username", username)
i.putExtra("password", password)
view.context.sendBroadcast(i)
}
}
...
SEND_CREDENTIALS
action will receive the message. The broadcast is not even protected with a permission to limit the number of recipients, although in this case we do not recommend using permissions as a fix.
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
CLLocation *location = [locationManager location];
// Configure the new event with information from the location
CLLocationCoordinate2D coordinate = [location coordinate];
NSString *latitude = [NSString stringWithFormat:@"%f", coordinate.latitude];
NSString *longitude = [NSString stringWithFormat:@"%f", coordinate.longitude];
NSLog(@"dLatitude : %@", latitude);
NSLog(@"dLongitude : %@",longitude);
NSString *urlWithParams = [NSString stringWithFormat:TOKEN_URL, latitude, longitude];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlWithParams]];
[request setHTTPMethod:@"GET"];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// Add password to user defaults
[defaults setObject:@"Super Secret" forKey:@"passwd"];
[defaults synchronize];
getPassword()
function that returns user-supplied plain text password associated with the account.
<?php
$pass = getPassword();
trigger_error($id . ":" . $pass . ":" . $type . ":" . $tstamp);
?>
Example 1
logs a plain text password to the application eventlog. Although many developers trust the eventlog as a safe storage location for data, it should not be trusted implicitly, particularly when privacy is a concern.OWA_SEC.get_password()
function returns the user-supplied plain text password associated with the account, which is then printed to the HTTP response.
...
HTP.htmlOpen;
HTP.headOpen;
HTP.title (.Account Information.);
HTP.headClose;
HTP.bodyOpen;
HTP.br;
HTP.print('User ID: ' ||
OWA_SEC.get_user_id || '');
HTP.print('User Password: ' ||
OWA_SEC.get_password || '');
HTP.br;
HTP.bodyClose;
HTP.htmlClose;
...
getPassword()
function that returns user-supplied plain text password associated with the account.
pass = getPassword();
logger.warning('%s: %s %s %s', id, pass, type, tsstamp)
Example 1
logs a plain text password to the application eventlog. Although many developers trust the eventlog as a safe storage location for data, it should not be trusted implicitly, particularly when privacy is a concern.get_password()
function returns the user-supplied plain text password associated with the account.
pass = get_password()
...
dbms_logger.warn("#{id}:#{pass}:#{type}:#{tstamp}")
Example 1
logs a plain text password to the file system. Although many developers trust the file system as a safe storage location for data, it should not be trusted implicitly, particularly when privacy is a concern.
val pass = getPassword()
...
dbmsLog.println(id+":"+pass+":"+type+":"+tstamp)
Example 1
logs a plain text password to the file system. Although many developers trust the file system as a safe storage location for data, it should not be trusted implicitly, particularly when privacy is a concern.
import CoreLocation
...
var locationManager : CLLocationManager!
var seenError : Bool = false
var locationFixAchieved : Bool = false
var locationStatus : NSString = "Not Started"
seenError = false
locationFixAchieved = false
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.locationServicesEnabled
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
...
if let location: CLLocation! = locationManager.location {
var coordinate : CLLocationCoordinate2D = location.coordinate
let latitude = NSString(format:@"%f", coordinate.latitude)
let longitude = NSString(format:@"%f", coordinate.longitude)
NSLog("dLatitude : %@", latitude)
NSLog("dLongitude : %@",longitude)
let urlString : String = "http://myserver.com/?lat=\(latitude)&lon=\(longitude)"
let url : NSURL = NSURL(string:urlString)
let request : NSURLRequest = NSURLRequest(URL:url)
var err : NSError?
var response : NSURLResponse?
var data : NSData = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error:&err)
} else {
println("no location...")
}
let defaults : NSUserDefaults = NSUserDefaults.standardUserDefaults()
// Add password to user defaults
defaults.setObject("Super Secret" forKey:"passwd")
defaults.synchronize()
getPassword
function returns the user-supplied plain text password associated with the account.
pass = getPassword
...
App.EventLog id & ":" & pass & ":" & type & ":" &tstamp, 4
...
Example 1
logs a plain text password to the application eventlog. Although many developers trust the eventlog as a safe storage location for data, it should not be trusted implicitly, particularly when privacy is a concern.
...
HKHealthStore healthStore = new HKHealthStore();
HKBloodTypeObject blood = healthStore.GetBloodType(null);
NSLog("%@", blood.BloodType);
var urlWithParams = String.format(TOKEN_URL, block.BloodType);
var responseString = await client.GetStringAsync(urlWithParams);
...
NSLog
function, allows a developer to create an app which may read all logs on the device (even when they don't own the other apps).
...
HKHealthStore healthStore = new HKHealthStore();
HKBloodTypeObject blood = healthStore.GetBloodType(null);
// Add blood type to user defaults
NSUserDefaults.StandardUserDefaults.SetString(blood.BloodType, "bloodType");
...
...
HKHealthStore *healthStore = [[HKHealthStore alloc] init];
HKBloodTypeObject *blood = [healthStore bloodTypeWithError:nil];
NSLog(@"%@", [blood bloodType]);
NSString *urlWithParams = [NSString stringWithFormat:TOKEN_URL, [blood bloodType]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlWithParams]];
[request setHTTPMethod:@"GET"];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
...
NSLog
function, allows a developer to create an app which may read all logs on the device (even when they don't own the other apps).
...
HKHealthStore *healthStore = [[HKHealthStore alloc] init];
HKBloodTypeObject *blood = [healthStore bloodTypeWithError:nil];
// Add blood type to user defaults
[defaults setObject:[blood bloodType] forKey:@"bloodType"];
[defaults synchronize];
...
...
let healthStore = HKHealthStore()
let blood = try healthStore.bloodType()
print(blood.bloodType)
let urlString : String = "http://myserver.com/?data=\(blood.bloodType)"
let url : NSURL = NSURL(string:urlString)
let request : NSURLRequest = NSURLRequest(URL:url)
var err : NSError?
var response : NSURLResponse?
var data : NSData = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error:&err)
...
NSLog
function, allows a developer to create an app which may read all logs on the device (even when they don't own the other apps).
...
let healthStore = HKHealthStore()
let blood = try healthStore.bloodType()
print(blood.bloodType)
// Add blood type to user defaults
defaults.setObject("BloodType" forKey:blood.bloodType)
defaults.synchronize()
...
String
object.
public static String getPassword() {
String inputPassword = "";
ConsoleKeyInfo nextKey = Console.ReadKey(true);
while (nextKey.Key != Console.ReadKey(true)) {
inputPassword.AppendChar(nextKey.KeyChar);
Console.Write("*");
nextKey = Console.ReadKey(true);
}
return inputPassword;
}
String
is an immutable object, the contents cannot be nullified, meaning that the sensitive data is open to anyone able to inspect the heap prior to garbage collection.String
object makes it impossible to reliably purge the data from memory.String
s are used to store sensitive data, however, becauseString
objects are immutable, only the JVM garbage collector can remove the value of a String
from memory can only be done by the JVM garbage collector. The garbage collector is not required to run unless the JVM is low on memory, so there is no guarantee as to when garbage collection will take place. In the event of an application crash, a memory dump of the application might reveal sensitive data.String
.
private JPasswordField pf;
...
final char[] password = pf.getPassword();
...
String passwordAsString = new String(password);
String
object makes it impossible to reliably purge the data from memory.String
s are used to store sensitive data, however, since String
objects are immutable, assigning a new value to them will create a new String
and assign its reference to the one being assigned. The original value will be kept in memory until ARC
(Automatic Reference Counting) deallocates the object and releases its memory. Swift makes no guarantee about the lifetime of an object until the end of the closest surrounding scope. If an attacker dumps the contents of memory before the object is deallocated, the contents can be read.String
.
let password = passwordTextField.text!
// use the password
DataVisualization
control that generates a graph of sensitive financial information from the XML Data Source SensitiveXMLData
:
<asp:Chart ID="Chart1" runat="server" ImageLocation="~/Temporary/Graph"
ImageType="Jpeg" DataSourceID="SensitiveXMLData" ImageStorageMode="UseImageLocation">
<series>
.
.
.
</series>
<chartareas>
<asp:ChartArea Name="ChartArea1">
</asp:ChartArea>
</chartareas>
</asp:Chart>
Example 1
instructs the Chart
control to produce a JPEG image of the bar graph and write it to the temporary directory ~/Temporary/Graph
. After the control writes the image to disk, the user's browser will make a subsequent request of the file and display it to the user. The image is not written securely to disk. Also, the code assumes that the underlying infrastructure will protect the file from unauthorized access by another user.DataType
as a password, meaning that by default it will be shown when displayed:
public class User
{
[Required]
public int ID { get; set; }
public string Title { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime DateOfEmployment { get; set; }
[DataType(DataType.Currency)]
public decimal Salary { get; set; }
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
...
}
Password
in Example 1
did not specify the attribute [DataType(DataType.Password)]
, it will not be hidden by default when displayed in the UI.TextField
widget does not obscure a user's password as they type it at the input prompt:
class SelectionContainerDisabledExampleApp extends StatelessWidget {
const SelectionContainerDisabledExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(
hintText: "Please enter your password",
),
),
],
),
),
),
);
}
}
TextField
widget in Example 1
was not instantiated with obscureText
property, set to true
, the password is not obscured when the user types it at the "Please enter your password: " prompt.PasswordCallback pc = new PasswordCallback("Please enter your password: ", true);
pc
in Example 1
was instantiated with its second parameter, onEcho
, set to true
, the password is not obscured when the user types it at the "Please enter your password: " prompt.
ViewController.h:
...
@property (nonatomic, retain) IBOutlet UITextField *passwordField;
...
ViewController.m:
...
NSString *password = _passwordField.text;
...
passwordField
in Example 1
did not have its secureTextEntry
property set to true
, the password is not obscured when the user types it into the text field.
...
@IBOutlet weak var passwordField: UITextField!
...
let password = passwordField.text
...
passwordField
in Example 1
did not have its secureTextEntry
property set to true
, the password is not obscured when the user types it into the text field.
...
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.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.null
before checking if the pointer is null
. Dereference-after-check errors occur when a program makes an explicit check for null
, but proceeds to dereference the pointer when it is known to be null
. Errors of this type are often the result of a typo or programmer oversight. A dereference-after-store error occurs when a program explicitly sets a pointer to null
and dereferences it later. This error is often the result of a programmer initializing a variable to null
when it is declared.foo
is null
and subsequently dereferences it erroneously. If foo
is null
when it is checked in the if
statement, then a null
dereference occurs, which causes a null-pointer exception.Example 2: In the following code, the programmer assumes that the variable
if (foo is null) {
foo.SetBar(val);
...
}
foo
is not null
and confirms this assumption by dereferencing the object. However, the programmer later contradicts the assumption by checking foo
against null
. If foo
can be null
when it is checked in the if
statement then it can also be null
when it is dereferenced and might cause a null-pointer exception. Either the dereference is unsafe or the subsequent check is unnecessary.Example 3: In the following code, the programmer explicitly sets the variable
foo.SetBar(val);
...
if (foo is not null) {
...
}
foo
to null
. Later, the programmer dereferences foo
before checking the object for a null
value.
Foo foo = null;
...
foo.SetBar(val);
...
}
null
before checking if the pointer is null
. Dereference-after-check errors occur when a program makes an explicit check for null
, but proceeds to dereference the pointer when it is known to be null
. Errors of this type are often the result of a typo or programmer oversight. A dereference-after-store error occurs when a program explicitly sets a pointer to null
and dereferences it later. This error is often the result of a programmer initializing a variable to null
when it is declared.ptr
is not NULL
. That assumption is made explicit when the programmer dereferences the pointer. This assumption is later contradicted when the programmer checks ptr
against NULL
. If ptr
can be NULL
when it is checked in the if
statement then it can also be NULL
when it dereferenced and may cause a segmentation fault.Example 2: In the following code, the programmer confirms that the variable
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
is NULL
and subsequently dereferences it erroneously. If ptr
is NULL
when it is checked in the if
statement, then a null
dereference will occur, thereby causing a segmentation fault.Example 3: In the following code, the programmer forgets that the string
if (ptr == null) {
ptr->field = val;
...
}
'\0'
is actually 0 or NULL
, thereby dereferencing a null-pointer and causing a segmentation fault.Example 4: In the following code, the programmer explicitly sets the variable
if (ptr == '\0') {
*ptr = val;
...
}
ptr
to NULL
. Later, the programmer dereferences ptr
before checking the object for a null
value.
*ptr = NULL;
...
ptr->field = val;
...
}
null
, but proceeds to dereference the object when it is known to be null
. Errors of this type are often the result of a typo or programmer oversight.foo
is null
and subsequently dereferences it erroneously. If foo
is null
when it is checked in the if
statement, then a null
dereference will occur, thereby causing a null-pointer exception.
if (foo == null) {
foo.setBar(val);
...
}
...
host_name = request->get_form_field( 'host' ).
CALL FUNCTION 'FTP_CONNECT'
EXPORTING
USER = user
PASSWORD = password
HOST = host_name
RFC_DESTINATION = 'SAPFTP'
IMPORTING
HANDLE = mi_handle
EXCEPTIONS
NOT_CONNECTED = 1
OTHERS = 2.
...
int rPort = Int32.Parse(Request.Item("rPort"));
...
IPEndPoint endpoint = new IPEndPoint(address,rPort);
socket = new Socket(endpoint.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
socket.Connect(endpoint);
...
...
char* rPort = getenv("rPort");
...
serv_addr.sin_port = htons(atoi(rPort));
if (connect(sockfd,&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
...
...
ACCEPT QNAME.
EXEC CICS
READQ TD
QUEUE(QNAME)
INTO(DATA)
LENGTH(LDATA)
END-EXEC.
...
ServerSocket
object and uses a port number read from an HTTP request to create a socket.
<cfobject action="create" type="java" class="java.net.ServerSocket" name="myObj">
<cfset srvr = myObj.init(#url.port#)>
<cfset socket = srvr.accept()>
Passing user input to objects imported from other languages can be very dangerous.
final server = await HttpServer.bind('localhost', 18081);
server.listen((request) async {
final remotePort = headers.value('port');
final serverSocket = await ServerSocket.bind(host, remotePort as int);
final httpServer = HttpServer.listenOn(serverSocket);
});
...
func someHandler(w http.ResponseWriter, r *http.Request){
r.parseForm()
deviceName := r.FormValue("device")
...
syscall.BindToDevice(fd, deviceName)
}
String remotePort = request.getParameter("remotePort");
...
ServerSocket srvr = new ServerSocket(remotePort);
Socket skt = srvr.accept();
...
WebView
.
...
WebView webview = new WebView(this);
setContentView(webview);
String url = this.getIntent().getExtras().getString("url");
webview.loadUrl(url);
...
var socket = new WebSocket(document.URL.indexOf("url=")+20);
...
char* rHost = getenv("host");
...
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)rHost, 80, &readStream, &writeStream);
...
<?php
$host=$_GET['host'];
$dbconn = pg_connect("host=$host port=1234 dbname=ticketdb");
...
$result = pg_prepare($dbconn, "my_query", 'SELECT * FROM pricelist WHERE name = $1');
$result = pg_execute($dbconn, "my_query", array("ticket"));
?>
...
filename := SUBSTR(OWA_UTIL.get_cgi_env('PATH_INFO'), 2);
WPG_DOCLOAD.download_file(filename);
...
host=request.GET['host']
dbconn = db.connect(host=host, port=1234, dbname=ticketdb)
c = dbconn.cursor()
...
result = c.execute('SELECT * FROM pricelist')
...
def controllerMethod = Action { request =>
val result = request.getQueryString("key").map { key =>
val user = db.getUser()
cache.set(key, user)
Ok("Cached Request")
}
Ok("Done")
}
...
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
var inputStream : NSInputStream?
var outputStream : NSOutputStream?
...
var readStream : Unmanaged<CFReadStream>?
var writeStream : Unmanaged<CFWriteStream>?
let rHost = getQueryStringParameter(url.absoluteString, "host")
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, rHost, 80, &readStream, &writeStream);
...
}
func getQueryStringParameter(url: String?, param: String) -> String? {
if let url = url, urlComponents = NSURLComponents(string: url), queryItems = (urlComponents.queryItems as? [NSURLQueryItem]) {
return queryItems.filter({ (item) in item.name == param }).first?.value!
}
return nil
}
...
...
Begin MSWinsockLib.Winsock tcpServer
...
Dim Response As Response
Dim Request As Request
Dim Session As Session
Dim Application As Application
Dim Server As Server
Dim Port As Variant
Set Response = objContext("Response")
Set Request = objContext("Request")
Set Session = objContext("Session")
Set Application = objContext("Application")
Set Server = objContext("Server")
Set Port = Request.Form("port")
...
tcpServer.LocalPort = Port
tcpServer.Accept
...
...
PageReference ref = ApexPages.currentPage();
Map<String,String> params = ref.getParameters();
HttpRequest req = new HttpRequest();
req.setEndpoint(params.get('url'));
HTTPResponse res = new Http().send(req);
http
or https
such as:
string url = Request.Form["url"];
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(url);
http
or https
like:
char *url = maliciousInput();
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
CURLcode res = curl_easy_perform(curl);
http
or https
such as:
...
final server = await HttpServer.bind('localhost', 18081);
server.listen((request) async {
final headers = request.headers;
final url = headers.value('url');
final client = IOClient();
final response = await client.get(Uri.parse(url!));
...
}
http
or https
such as:
url := request.Form.Get("url")
res, err =: http.Get(url)
...
http
or https
like:
String url = request.getParameter("url");
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response1 = httpclient.execute(httpGet);
http
or https
like:
var http = require('http');
var url = require('url');
function listener(request, response){
var request_url = url.parse(request.url, true)['query']['url'];
http.request(request_url)
...
}
...
http.createServer(listener).listen(8080);
...
http
or https
like:
val url: String = request.getParameter("url")
val httpclient: CloseableHttpClient = HttpClients.createDefault()
val httpGet = HttpGet(url)
val response1: CloseableHttpResponse = httpclient.execute(httpGet)
http
or https
like:
$url = $_GET['url'];
$c = curl_init();
curl_setopt($c, CURLOPT_POST, 0);
curl_setopt($c,CURLOPT_URL,$url);
$response=curl_exec($c);
curl_close($c);
http
or https
like:
url = request.GET['url']
handle = urllib.urlopen(url)
http
or https
like:
url = req['url']
Net::HTTP.get(url)
http
or https
like:
def getFile(url: String) = Action { request =>
...
val url = request.body.asText.getOrElse("http://google.com")
ws.url(url).get().map { response =>
Ok(s"Request sent to $url")
}
...
}
http
or https
like:Example 2: A few examples of how an attacker that has control over the
POST /checkDetails HTTP/1.1
url=https://example.com/product/1
url
parameter can tamper the request in Example 1
.
POST /checkDetails HTTP/1.1
url=https://localhost.com/admin
POST /checkDetails HTTP/1.1
url=file:///etc/passwd
http
or https
like: