#
characters, as follows:
<select id="getItems" parameterType="domain.company.MyParamClass" resultType="MyResultMap">
SELECT *
FROM items
WHERE owner = #{userName}
</select>
#
character with braces around the variable name indicate that MyBatis will create a parameterized query with the userName
variable. However, MyBatis also allows you to concatenate variables directly to SQL statements using the $
character, opening the door for SQL injection.
<select id="getItems" parameterType="domain.company.MyParamClass" resultType="MyResultMap">
SELECT *
FROM items
WHERE owner = #{userName}
AND itemname = ${itemName}
</select>
itemName
does not contain a single-quote character. If an attacker with the user name wiley
enters the string "name' OR 'a'='a
" for itemName
, then the query becomes the following:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
condition causes the WHERE
clause to always evaluate to true, so the query becomes logically equivalent to the much simpler query:
SELECT * FROM items;
items
table, regardless of their specified owner.Example 1
. If an attacker with the user name wiley
enters the string "name'; DELETE FROM items; --
" for itemName
, then the query becomes the following two queries:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. If an attacker enters the string "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", the following three valid statements will be created:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
owner
matches the user name of the currently-authenticated user.
...
string userName = ctx.GetAuthenticatedUserName();
string query = "SELECT * FROM items WHERE owner = '"
+ userName + "' AND itemname = '"
+ ItemName.Text + "'";
List items = sess.CreateSQLQuery(query).List();
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
ItemName
does not contain a single-quote character. If an attacker with the user name wiley
enters the string "name' OR 'a'='a
" for ItemName
, then the query becomes the following:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
condition causes the where clause to always evaluate to true, so the query becomes logically equivalent to the much simpler query:
SELECT * FROM items;
items
table, regardless of their specified owner.Example 1
. If an attacker with the user name wiley
enters the string "name'; DELETE FROM items; --
" for ItemName
, then the query becomes the following two queries:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. If an attacker enters the string "name'; DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", the following three valid statements will be created:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
...
String userName = ctx.getAuthenticatedUserName();
String itemName = request.getParameter("itemName");
String query = "SELECT * FROM items WHERE owner = '"
+ userName + "' AND itemname = '"
+ itemName + "'";
ResultSet rs = stmt.execute(query);
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
does not contain a single-quote character. If an attacker with the user name wiley
enters the string "name' OR 'a'='a
" for itemName
, then the query becomes the following:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
condition causes the where clause to always evaluate to true, so the query becomes logically equivalent to the much simpler query:
SELECT * FROM items;
items
table, regardless of their specified owner.Example 1
. If an attacker with the user name wiley
enters the string "name'; DELETE FROM items; --
" for itemName
, then the query becomes the following two queries:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. If an attacker enters the string "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", the following three valid statements will be created:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
Example 1
to the Android platform.
...
PasswordAuthentication pa = authenticator.getPasswordAuthentication();
String userName = pa.getUserName();
String itemName = this.getIntent().getExtras().getString("itemName");
String query = "SELECT * FROM items WHERE owner = '"
+ userName + "' AND itemname = '"
+ itemName + "'";
SQLiteDatabase db = this.openOrCreateDatabase("DB", MODE_PRIVATE, null);
Cursor c = db.rawQuery(query, null);
...
owner
matches the user name of the currently-authenticated user.
...
string userName = ctx.getAuthenticatedUserName();
string query = "SELECT * FROM items WHERE owner = '"
+ userName + "' AND itemname = '"
+ ItemName.Text + "'";
IDataReader responseReader = new InlineQuery().ExecuteReader(query);
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
does not contain a single-quote character. If an attacker with the user name wiley
enters the string "name' OR 'a'='a
" for itemName
, then the query becomes the following:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
condition causes the where clause to always evaluate to true, so the query becomes logically equivalent to the much simpler query:
SELECT * FROM items;
items
table, regardless of their specified owner.Example 1
. If an attacker with the user name wiley
enters the string "name'); DELETE FROM items; --
" for itemName
, then the query becomes the following two queries:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. If an attacker enters the string "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", the following three valid statements will be created:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
ViewController.h
...
@property (nonatomic, retain) IBOutlet UITextField *ssnField;
...
Example 1
indicates that the app utilizes an input control designed to collect sensitive information. As iOS caches input into text fields in order to improve the performance of its autocorrection feature, any information recently entered into such an input control may be cached within a keyboard cache file saved to the file system. Because the keyboard cache file is stored on the device, if the device is lost, it may be recovered, thereby revealing any sensitive information contained within.
...
@IBOutlet weak var ssnField: UITextField!
...
Example 1
indicates that the app utilizes an input control designed to collect sensitive information. As iOS caches input into text fields in order to improve the performance of its autocorrection feature, any information recently entered into such an input control may be cached within a keyboard cache file saved to the file system. Because the keyboard cache file is stored on the device, if the device is lost, it may be recovered, thereby revealing any sensitive information contained within.
ViewController.h
...
@property (nonatomic, retain) IBOutlet UITextField *ssnField;
...
Example 1
indicates that the app utilizes an input control designed to collect sensitive information. As iOS takes a screenshot of the active view of an app when it is backgrounded in order to improve animation performance, any information displayed in such input controls during the background event may be cached within an image saved to the file system. Because these screen cache screenshots are stored on the device, if the device is lost, they may be recovered, thereby revealing any sensitive information contained within.
...
@IBOutlet weak var ssnField: UITextField!
...
Example 1
indicates that the app utilizes an input control designed to collect sensitive information. As iOS takes a screenshot of the active view of an app when it is backgrounded in order to improve animation performance, any information displayed in such input controls during the background event may be cached within an image saved to the file system. Because these screen cache screenshots are stored on the device, if the device is lost, they may be recovered, thereby revealing any sensitive information contained within.kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:ThisDeviceOnly
will be backed up to iCloud and backed up to iTunes even if using unencrypted backups which can be restored to any device. Depending on how sensitive and private the stored data is, this may raise a privacy concern.
...
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *token = [@"secret" dataUsingEncoding:NSUTF8StringEncoding];
// Configure KeyChain Item
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id) kSecClass];
[dict setObject:token forKey:(__bridge id)kSecValueData];
...
[dict setObject:(__bridge id)kSecAttrAccessibleWhenUnlocked forKey:(__bridge id) kSecAttrAccessible];
OSStatus error = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
...
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:ThisDeviceOnly
will be backed up to iCloud and backed up to iTunes even if using unencrypted backups which can be restored to any device. Depending on how sensitive and private the stored data is, this may raise a privacy concern.
...
// Configure KeyChain Item
let token = "secret"
var query = [String : AnyObject]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecValueData as String] = token as AnyObject?
...
query[kSecAttrAccessible as String] = kSecAttrAccessibleWhenUnlocked
SecItemAdd(query as CFDictionary, nil)
...
#
characters, as follows:
<select id="getItems" parameterClass="MyClass" resultClass="items">
SELECT * FROM items WHERE owner = #userName#
</select>
#
characters around the variable name indicate that iBatis will create a parameterized query with the userName
variable. However, iBatis also allows you to concatenate variables directly to SQL statements using $
characters, opening the door for SQL injection.
<select id="getItems" parameterClass="MyClass" resultClass="items">
SELECT * FROM items WHERE owner = #userName# AND itemname = '$itemName$'
</select>
itemName
does not contain a single-quote character. If an attacker with the user name wiley
enters the string "name' OR 'a'='a
" for itemName
, then the query becomes the following:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
condition causes the where clause to always evaluate to true, so the query becomes logically equivalent to the much simpler query:
SELECT * FROM items;
items
table, regardless of their specified owner.Example 1
. If an attacker with the user name wiley
enters the string "name'; DELETE FROM items; --
" for itemName
, then the query becomes the following two queries:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. If an attacker enters the string "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", the following three valid statements will be created:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
...
String userName = ctx.getAuthenticatedUserName();
String itemName = request.getParameter("itemName");
String sql = "SELECT * FROM items WHERE owner = '"
+ userName + "' AND itemname = '"
+ itemName + "'";
Query query = pm.newQuery(Query.SQL, sql);
query.setClass(Person.class);
List people = (List)query.execute();
...
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
itemName
does not contain a single-quote character. If an attacker with the user name wiley
enters the string "name' OR 'a'='a
" for itemName
, then the query becomes the following:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';
OR 'a'='a'
condition causes the where clause to always evaluate to true, so the query becomes logically equivalent to the much simpler query:
SELECT * FROM items;
items
table, regardless of their specified owner.Example 1
. If an attacker with the user name wiley
enters the string "name'; DELETE FROM items; --
" for itemName
, then the query becomes the following two queries:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
--'
Example 1
. If an attacker enters the string "name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a
", the following three valid statements will be created:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name';
DELETE FROM items;
SELECT * FROM items WHERE 'a'='a';
kSecAttrAccessible
key in the Keychain attribute dictionary. The definitions for the various Keychain accessibility constants are as follows:kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAfterFirstUnlock
will afford it encryption using a key derived from the user's passcode and the device's UID, the data will still remain accessible under certain circumstances. As such, usages of kSecAttrAccessibleAfterFirstUnlock
should be carefully reviewed to determine if further protection is warranted.
...
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *token = [@"secret" dataUsingEncoding:NSUTF8StringEncoding];
// Configure KeyChain Item
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id) kSecClass];
[dict setObject:token forKey:(__bridge id)kSecValueData];
...
[dict setObject:(__bridge id)kSecAttrAccessibleAfterFirstUnlock forKey:(__bridge id) kSecAttrAccessible];
OSStatus error = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
...
kSecAttrAccessible
key in the Keychain attribute dictionary. The definitions for the various Keychain accessibility constants are as follows:kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAfterFirstUnlock
will afford it encryption using a key derived from the user's passcode and the device's UID, the data will still remain accessible under certain circumstances. As such, usages of kSecAttrAccessibleAfterFirstUnlock
should be carefully reviewed to determine if further protection is warranted.
...
// Configure KeyChain Item
let token = "secret"
var query = [String : AnyObject]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecValueData as String] = token as AnyObject?
...
query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
SecItemAdd(query as CFDictionary, nil)
...
kSecAttrAccessible
key in the Keychain attribute dictionary. The definitions for the various Keychain accessibility constants are as follows:kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAlways
results in encryption using a key derived solely based on the device's UID. This leaves such files accessible any time the device is powered on, including when locked with a passcode or when booting. As such, usages of kSecAttrAccessibleAlways
should be carefully reviewed to determine if further protection with a stricter Keychain accessibility level is warranted.
...
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *token = [@"secret" dataUsingEncoding:NSUTF8StringEncoding];
// Configure KeyChain Item
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id) kSecClass];
[dict setObject:token forKey:(__bridge id)kSecValueData];
...
[dict setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id) kSecAttrAccessible];
OSStatus error = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
...
kSecAttrAccessible
key in the Keychain attribute dictionary. The definitions for the various Keychain accessibility constants are as follows:kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAlways
results in encryption using a key derived solely based on the device's UID. This leaves such files accessible any time the device is powered on, including when locked with a passcode or when booting. As such, usages of kSecAttrAccessibleAlways
should be carefully reviewed to determine if further protection with a stricter Keychain accessibility level is warranted.
...
// Configure KeyChain Item
let token = "secret"
var query = [String : AnyObject]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecValueData as String] = token as AnyObject?
...
query[kSecAttrAccessible as String] = kSecAttrAccessibleAlways
SecItemAdd(query as CFDictionary, nil)
...
<script runat="server">
...
var retrieveOperation = TableOperation.Retrieve<EmployeeInfo>(partitionKey, rowKey);
var retrievedResult = employeeTable.Execute(retrieveOperation);
var employeeInfo = retrievedResult.Result as EmployeeInfo;
string name = employeeInfo.Name
...
EmployeeName.Text = name;
</script>
EmployeeName
is a form control defined as follows:Example 2: The following ASP.NET code segment is functionally equivalent to
<form runat="server">
...
<asp:Label id="EmployeeName" runat="server">
...
</form>
Example 1
, but implements all of the form elements programmatically.
protected System.Web.UI.WebControls.Label EmployeeName;
...
var retrieveOperation = TableOperation.Retrieve<EmployeeInfo>(partitionKey, rowKey);
var retrievedResult = employeeTable.Execute(retrieveOperation);
var employeeInfo = retrievedResult.Result as EmployeeInfo;
string name = employeeInfo.Name
...
EmployeeName.Text = name;
Name
are well-behaved, but they do nothing to prevent exploits if they are not. This code can appear less dangerous because the value of Name
is read from a cloud-provided storage service, whose contents are apparently managed by the distributed application. However, if the value of Name
originates from user-supplied data, then the cloud-provided storage service can be a conduit for malicious content. Without proper input validation on all data stored in the database, an attacker may execute malicious commands in the user's web browser. This type of exploit, known as Inter-Component Communication Cloud XSS, is particularly insidious because the indirection caused by the data store makes it difficult to identify the threat and increases the possibility that the attack might affect multiple users. XSS got its start in this form with web sites that offered a "guestbook" to visitors. Attackers would include JavaScript in their guestbook entries, and all subsequent visitors to the guestbook page would execute the malicious code.
<script runat="server">
...
EmployeeID.Text = Login.Text;
...
</script>
Login
and EmployeeID
are form controls defined as follows:Example 4: The following ASP.NET code segment shows the programmatic way to implement
<form runat="server">
<asp:TextBox runat="server" id="Login"/>
...
<asp:Label runat="server" id="EmployeeID"/>
</form>
Example 3
.
protected System.Web.UI.WebControls.TextBox Login;
protected System.Web.UI.WebControls.Label EmployeeID;
...
EmployeeID.Text = Login.Text;
Example 1
and Example 2
, these examples operate correctly if Login
contains only standard alphanumeric text. If Login
has a value that includes metacharacters or source code, then the code will be executed by the web browser as it displays the HTTP response.Example 1
and Example 2
, the application stores dangerous data in a database or other trusted data store. The dangerous data is subsequently read back into the application and included in dynamic content. Inter-Component Communication Cloud XSS exploits occur when an attacker injects dangerous content into a data store that is later read and included in dynamic content. From an attacker's perspective, the optimal place to inject malicious content is in an area that is displayed to either many users or particularly interesting users. Interesting users typically have elevated privileges in the application or interact with sensitive data that is valuable to the attacker. If one of these users executes malicious content, the attacker may be able to perform privileged operations on behalf of the user or gain access to sensitive data belonging to the user.Example 3
and Example 4
, data is read directly from the HTTP request and reflected back in the HTTP response. Reflected XSS exploits occur when an attacker causes a user to supply dangerous content to a vulnerable web application, which is then reflected back to the user and executed by the web browser. The most common mechanism for delivering malicious content is to include it as a parameter in a URL that is posted publicly or emailed directly to victims. URLs constructed in this manner constitute the core of many phishing schemes, whereby an attacker convinces victims to visit a URL that refers to a vulnerable site. After the site reflects the attacker's content back to the user, the content is executed and proceeds to transfer private information, such as cookies that might include session information, from the user's machine to the attacker or perform other nefarious activities.eid
, from an HTTP request and displays it to the user.
req = self.request() # fetch the request object
eid = req.field('eid',None) # tainted request message
...
self.writeln("Employee ID:" + eid)
eid
contains only standard alphanumeric text. If eid
has a value that includes metacharacters or source code, then the code is executed by the web browser as it displays the HTTP response.
...
cursor.execute("select * from emp where id="+eid)
row = cursor.fetchone()
self.writeln('Employee name: ' + row["emp"]')
...
Example 1
, this code functions correctly when the values of name
are well-behaved, but it does nothing to prevent exploits if they are not. Again, this code can appear less dangerous because the value of name
is read from a database, whose contents are apparently managed by the application. However, if the value of name
originates from user-supplied data, then the database can be a conduit for malicious content. Without proper input validation on all data stored in the database, an attacker may execute malicious commands in the user's web browser. This type of exploit, known as Persistent (or Stored) XSS, is particularly insidious because the indirection caused by the data store makes it difficult to identify the threat and increases the possibility that the attack might affect multiple users. XSS got its start in this form with web sites that offered a "guestbook" to visitors. Attackers would include JavaScript in their guestbook entries, and all subsequent visitors to the guestbook page would execute the malicious code.Example 1
, data is read directly from the HTTP request and reflected back in the HTTP response. Reflected XSS exploits occur when an attacker causes a user to supply dangerous content to a vulnerable web application, which is then reflected back to the user and executed by the web browser. The most common mechanism for delivering malicious content is to include it as a parameter in a URL that is posted publicly or emailed directly to victims. URLs constructed in this manner constitute the core of many phishing schemes, whereby an attacker convinces victims to visit a URL that refers to a vulnerable site. After the site reflects the attacker's content back to the user, the content is executed and proceeds to transfer private information, such as cookies that might include session information, from the user's machine to the attacker or perform other nefarious activities.Example 2
, the application stores dangerous data in a database or other trusted data store. The dangerous data is subsequently read back into the application and included in dynamic content. Persistent XSS exploits occur when an attacker injects dangerous content into a data store that is later read and included in dynamic content. From an attacker's perspective, the optimal place to inject malicious content is in an area that is displayed to either many users or particularly interesting users. Interesting users typically have elevated privileges in the application or interact with sensitive data that is valuable to the attacker. If one of these users executes malicious content, the attacker may be able to perform privileged operations on behalf of the user or gain access to sensitive data belonging to the user.
...
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()
...
text/html
MIME type. Therefore, XSS is only possible if the response uses this MIME type or any other that also forces the browser to render the response as HTML or other document that may execute scripts such as SVG images (image/svg+xml
), XML documents (application/xml
), etc. application/octet-stream
. However, some browsers such as Internet Explorer perform what is known as Content Sniffing
. Content Sniffing involves ignoring the provided MIME type and attempting to infer the correct MIME type by the contents of the response.text/html
is only one such MIME type that may lead to XSS vulnerabilities. Other documents that may execute scripts such as SVG images (image/svg+xml
), XML documents (application/xml
), as well as others may lead to XSS vulnerabilities regardless of whether the browser performs Content Sniffing. <html><body><script>alert(1)</script></body></html>
, could be rendered as HTML even if its content-type
header is set to application/octet-stream
, multipart-mixed
, and so on.application/octet-stream
response.
@RestController
public class SomeResource {
@RequestMapping(value = "/test", produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE})
public String response5(@RequestParam(value="name") String name){
return name;
}
}
name
parameter set to <html><body><script>alert(1)</script></body></html>
, the server will produce the following response:
HTTP/1.1 200 OK
Content-Length: 51
Content-Type: application/octet-stream
Connection: Closed
<html><body><script>alert(1)</script></body></html>
text/html
MIME type. Therefore, XSS is only possible if the response uses this MIME type or any other that also forces the browser to render the response as HTML or other document that may execute scripts such as SVG images (image/svg+xml
), XML documents (application/xml
), etc. application/json
. However, some browsers such as Internet Explorer perform what is known as Content Sniffing
. Content Sniffing involves ignoring the provided MIME type and attempting to infer the correct MIME type by the contents of the response.text/html
is only one such MIME type that may lead to XSS vulnerabilities. Other documents that may execute scripts such as SVG images (image/svg+xml
), XML documents (application/xml
), as well as others may lead to XSS vulnerabilities regardless of whether the browser performs Content Sniffing. <html><body><script>alert(1)</script></body></html>
, could be rendered as HTML even if its content-type
header is set to application/json
.application/json
response.
def mylambda_handler(event, context):
name = event['name']
response = {
"statusCode": 200,
"body": "{'name': name}",
"headers": {
'Content-Type': 'application/json',
}
}
return response
name
parameter set to <html><body><script>alert(1)</script></body></html>
, the server will produce the following response:
HTTP/1.1 200 OK
Content-Length: 88
Content-Type: application/json
Connection: Closed
{'name': '<html><body><script>alert(1)</script></body></html>'}
eid
, from an HTTP request and displays it to the user.
String queryString = Window.Location.getQueryString();
int pos = queryString.indexOf("eid=")+4;
HTML output = new HTML();
output.setHTML(queryString.substring(pos, queryString.length()));
eid
contains only standard alphanumeric text. If eid
has a value that includes metacharacters or source code, then the code is executed by the web browser as it displays the HTTP response.eid
, from a URL and displays it to the user.Example 2: Consider the HTML form:
<SCRIPT>
var pos=document.URL.indexOf("eid=")+4;
document.write(document.URL.substring(pos,document.URL.length));
</SCRIPT>
<div id="myDiv">
Employee ID: <input type="text" id="eid"><br>
...
<button>Show results</button>
</div>
<div id="resultsDiv">
...
</div>
$(document).ready(function(){
$("#myDiv").on("click", "button", function(){
var eid = $("#eid").val();
$("resultsDiv").append(eid);
...
});
});
eid
contains only standard alphanumeric text. If eid
has a value that includes metacharacters or source code, then the code will be executed by the web browser as it displays the HTTP response.
let element = JSON.parse(getUntrustedInput());
ReactDOM.render(<App>
{element}
</App>);
Example 3
, if an attacker can control the entire JSON object retrieved from getUntrustedInput()
, they may be able to make React render element
as a component, and therefore can pass an object with dangerouslySetInnerHTML
with their own controlled value, a typical cross-site scripting attack.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.kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
, then if your device gets stolen and a passcode is set, the theft will need to unlock the device in order for the Keychain items to be decrypted. Failing to enter the right passcode will block the theft from decrypting the Keychain items. However, if the passcode is not set, the attacker just needs to slide his finger to unlock the device and get the Keychain to decrypt its items. Therefore, failing to enforce a passcode in the device may weaken the Keychain encryption mechanism.
...
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *token = [@"secret" dataUsingEncoding:NSUTF8StringEncoding];
// Configure KeyChain Item
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id) kSecClass];
[dict setObject:token forKey:(__bridge id)kSecValueData];
...
[dict setObject:(__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly forKey:(__bridge id) kSecAttrAccessible];
OSStatus error = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
...
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
, then if your device gets stolen and a passcode is set, the theft will need to unlock the device in order for the Keychain items to be decrypted. Failing to enter the right passcode will block the theft from decrypting the Keychain items. However, if the passcode is not set, the attacker just needs to slide his finger to unlock the device and get the Keychain to decrypt its items. Therefore, failing to enforce a passcode in the device may weaken the Keychain encryption mechanism.
...
// Configure KeyChain Item
let token = "secret"
var query = [String : AnyObject]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecValueData as String] = token as AnyObject?
...
query[kSecAttrAccessible as String] = kSecAttrAccessibleWhenUnlockedThisDeviceOnly
SecItemAdd(query as CFDictionary, nil)
...
if (fitz == null) {
synchronized (this) {
if (fitz == null) {
fitz = new Fitzer();
}
}
}
return fitz;
Fitzer()
object is ever allocated, but does not want to pay the cost of synchronization every time this code is called. This idiom is known as double-checked locking.Fitzer()
objects can be allocated. See The "Double-Checked Locking is Broken" Declaration for more details [1].