Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #61

Merged
merged 11 commits into from
Apr 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ src/report/html/looty.js
*.exe
src/test-apk/
src/test-apk_apk/
.temp_thread_file


# OS generated files #
Expand Down
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ For the impatient ones, grab the download on the [releases page](https://github.
*: note that currently only apk files are supported, but ipa files will follow very shortly.
</p>

An example report can be found here: [example report](https://github.com/vincentcox/StaCoAn/blob/master/resources/example-report.zip)
An example report can be found [here](https://github.com/vincentcox/StaCoAn/raw/master/resources/example-report.zip).


## Table of Contents
<!-- TOC depthFrom:2 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 -->
Expand Down Expand Up @@ -86,6 +87,10 @@ The reports are made to fit on all screens.

![](resources/responsive.gif)

## How does the tool works?

![Pipeline tool](resources/pipeline.png)

## Limitations
This tool will have trouble with [obfuscated](https://en.wikibooks.org/wiki/Introduction_to_Software_Engineering/Tools/Obfuscation) code. If you are a developer try to compile without obfuscation turned on before running this tool. If you are on the offensive side, good luck bro.

Expand Down Expand Up @@ -116,17 +121,17 @@ The report will be put inside a folder with a name corresponding to the apk.
```
cd docker
```

```
docker build . -t stacoan
```
_Make sure that your application is at the location `/yourappsfolder`._

```
docker run -e JAVA_OPTS="-Xms2048m -Xmx2048m" -p 8000:8000 -p 8080:8080 -i -t stacoan
docker run -e JAVA_OPTS="-Xms2048m -Xmx2048m" -p 8888:8888 -p 7777:7777 -i -t stacoan
```

Drag and drop your application via: http://127.0.0.1:8000.
Drag and drop your application via: http://127.0.0.1:7777.


### From source
```
Expand All @@ -149,14 +154,14 @@ Install the required python packages:
pip3 install -r requirements.txt
```

Run StaCoAn:
Run StaCoAn via commandline:

```
python3 stacoan.py -p yourApp.apk
```
__Or__ if you rather use the drag and drop interface:
```
python3 stacoan.py -p yourApp.apk --disable-browser --enable-server
python3 stacoan.py
```
### Building the executable
Make sure that you are in the `src` folder.
Expand Down Expand Up @@ -263,6 +268,7 @@ If the contribution is high enough, you will be mentioned in the `authors` secti
<a href="https://github.com/Kevin-De-Koninck"><img src="resources/authors/Kevin-De-Koninck.png" width="100px"></a>
<a href="https://github.com/BBerastegui"><img src="resources/authors/BBerastegui.png" width="100px"></a>
<a href="https://github.com/adi0x90"><img src="resources/authors/adi0x90.png" width="100px"></a>
<a href="https://github.com/Ayowel"><img src="resources/authors/Ayowel.png" width="100px"></a>

## License
The following projects were used in this project:
Expand Down
Binary file added resources/authors/Ayowel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/pipeline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 4 additions & 3 deletions src/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ log_file = log.html
config_folder = config
src_search_words = src_search_words.txt
db_search_words = db_search_words.txt
owasp_search_words = owasp_static_android.txt
exclusion_filename = exclusion_list.txt
limit_top_findings = 3
apptypes = [".apk", ".ipa"]
src_filetypes = [".java", ".html", ".xml", ".js", ".plist"]
db_filetypes = [".db"]
query_importance = 0
code_offset = 3
server_enabled = 0
server_disabled = 0
loglevel = 3

[Server]
report_server_port = 8080
drag_drop_server_port = 8000
report_server_port = 8888
drag_drop_server_port = 7777

28 changes: 10 additions & 18 deletions src/config/db_search_words.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
password|||10|||triggers unwanted classes like password reset, hence the low score
privatekey|||80
private_key|||80
apikey|||75
http:|||10
https:|||7
database_secret|||80
database_password|||80
databasepassword|||80
databasesecret|||80
(https|http):\/\/.*api.*|||60||| This regex matches any URL containing 'api'
(https|http):\/\/.*test.*|||60||| This regex matches any URL containing 'test'
(https|http):\/\/.*uat.*|||60||| This regex matches any URL containing 'uat'
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|||40||| Matching IP adresses
^[a-f0-9]{32}$|||70||| MD5 hash
\b([a-f0-9]{40})\b|||70||| SHA1 hash
^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$|||70||| base64 string
Authorization: Basic|||95||| Basic authentication
passw(d|ord)?|||10|||Sensitive parameters which can contain hardcoded credentials. The score is quite low because this query is often a false-positive.
(private|secret|api|aws)[_-]?key|||50|||Sensitive parameters which can contain hardcoded credentials. The score is quite low because this query is often a false-positive.
https?:|||7|||An URL was found, this might be an API endpoint or just a link to documentation. Hopefully the first one.
(db|database)[_-]?(passw(d|ord)?|secret)|||80|||This match probably contains hardcoded database credentials.
https?:\/\/.*(uat|test|api).*|||60||| This regex matches any URL containing 'api|uat|test'
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|||40|||An IP address was found, this might be a server (where the API is hosted). Or this might be a link to documentation, however chances are low.
^[a-f0-9]{32}$|||70|||An MD5 hash was found! You are lucky because MD5 is easily crack-able. Just google for "MD5 decrypt online" and you will come a long end.
\b([a-f0-9]{40})\b|||70|||A SHA1 hash was found! You are lucky because SHA1 is easily crack-able. Just google for "SHA1 decrypt online" and you will come a long end.
^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$|||70|||A base64 string was found. Go to https://www.base64decode.org/ and paste your value. This decrypted value is in most cases very interesting.
Authorization: Basic|||95|||Basic authentication was found. Apart from the fact that API communication should be with OAUTH or something similar, it contains hardcoded credentials.
4 changes: 2 additions & 2 deletions src/config/exclusion_list.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
http:|||"res","layout"||| Suggested by Adi
(https|http):\/\/.*api.*|||"res","layout"||| Suggested by Adi
http:\/\/schemas\.android\.com\/apk\/res\/android||||||
https?:\/\/.*api.*|||"res","layout"||| Suggested by Adi
http:\/\/schemas\.android\.com\/apk\/res\/android||||||
61 changes: 61 additions & 0 deletions src/config/owasp_static_android.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import dexguard.util|RootDetector.isDeviceRooted||||||Root Activity: dexguard root detection code
com.noshufou.android.su|com.thirdparty.superuser|eu.chainfire.supersu|com.koushikdutta.superuser|eu.chainfire.||||||Root Activity: the app may request root/superuser privileges
test-keys|/system/app/Superuser.apk|isDeviceRooted|/system/bin/failsafe/su|/system/sd/xbin/su|"/system/xbin/which"|"su"|RootTools.isAccessGiven|/system/bin/su|/system/xbin/su||||||Root Activity: the app may have root detection capabilities
dalvik.system.DexClassLoader|java.security.ClassLoader|java.net.URLClassLoader|java.security.SecureClassLoader||||||Dynamic Loading: the app can dynamically load classes
dalvik.system.PathClassLoader|dalvik.system.DexFile|dalvik.system.DexPathList|dalvik.system.DexClassLoader|loadDex|loadClass|DexClassLoader|loadDexFile||||||Dynamic Loading: the app can load and manipulate Dex files
getRuntime().exec|getRuntime||||||Dynamic Loading: the app executes system commands
Log[.][vdiwe]|System.out.print||||||Insecure Data Storage: the app logs information
rawQuery|SQLiteDatabase|execSQL|android.database.sqlite||||||Insecure Data Storage: the app uses SQLite Database
content://||||||Insecure Data Storage: Checking for content providers
MODE_WORLD_READABLE|Context.MODE_WORLD_READABLE||||||Filesystem Access: the Object is World Readable by any App.
MODE_WORLD_WRITABLE|Context.MODE_WORLD_WRITABLE||||||Filesystem Access: the Object is World Writable by any app.
MODE_private_ip|Context.MODE_private_ip||||||Filesystem Access: app can write to app directory.
net.URL|openStream|||55|||Insecure Communication: the app URL can connect to http/https/ftp/jar
net.JarURL|JarURL|jar:|||55|||Insecure Communication: The app URL can connect to JAR url
HttpURL|org.apache.http|HttpRequest||||||Insecure Communication: the app initiate HTTP network_communications
javax.net.ssl.HttpsURL|HttpsURL||||||Insecure Communication: the app URL can initiate a HTTPS network_communication
http.client.HttpClient|net.http.AndroidHttpClient|http.impl.client.AbstractHttpClient||||||Insecure Communication: the app facilitates HTTP Requests, network_communications and Sessions
android.webkit||||||Webview Implementation and Javascript: the app uses Webkit
loadData||||||Webview Implementation and Javascript: the app uses WebView and can load HTML/JavaScript
setJavaScriptEnabled|.addJavascriptInterface||||||Webview Implementation and Javascript: Insecure WebView Implementation.
.setWebContentsDebuggingEnabled(true)||||||Webview Implementation and Javascript: remote WebView debugging is enabled
postUrl||||||Webview Implementation and Javascript: the app can perform WebView POST Request
javax.crypto|kalium.crypto|bouncycastle.crypto||||||Insufficient Cryptography: the app uses crypto
org.thoughtcrime.ssl.pinning|PinningHelper.getPinnedHttpsURLConnection|PinningHelper.getPinnedHttpClient|PinningSSLSocketFactory||||||Insufficient Cryptography: Checking for SSL pinning libraries
java.lang.reflect.Method|java.lang.reflect.Field|Class.forName||||||Code Tampering: the app uses java reflection
import dexguard.util|TamperDetector.checkApk||||||Code Tampering: dexguard tamper detection code
import dexguard.util|CertificateChecker.checkCertificate||||||Code Tampering: dexguard signer certificate tamper detection code
import dexguard.util|TamperDetector.checkApk||||||Reverse Engineering: Checking for dexguard tamper detection code
import dexguard.util|CertificateChecker.checkCertificate||||||Reverse Engineering: Checking for dexguard signer certificate tamper detection code
import dexguard.util|DebugDetector.isDebuggerConnected||||||Reverse Engineering: Checking for Checking for dexguard debugger detection code
import dexguard.util|EmulatorDetector.isRunningInEmulator||||||Reverse Engineering: Checking for Checking for dexguard emulator detection code
import dexguard.util|EDebugDetector.isSignedWithDebugKey||||||Reverse Engineering: Signed with Debugkey
java.lang.System|java.lang.Runtime||||||Lack of Code Protection: the app contains native java code
utils.AESObfuscator|getObfuscator||||||Lack of Code Protection: the app uses obfuscation
password =|secret =|username =|key =|||83|||the app contain hardcoded sensitive informations like usernames, passwords, keys etc: Hard coded sensitive information in Application Code (including Crypto)
java.security.MessageDigest|.MessageDigestSpi|MessageDigest||||||Application makes use of Weak Cryptography: the app uses message digest
java.util.Random||||||Application makes use of Weak Cryptography: the app uses an insecure Random Number Generator
javax.net.ssl|TrustAllSSLSocket-Factory|AllTrustSSLSocketFactory|NonValidatingSSLSocketFactory|ALLOW_ALL_HOSTNAME_VERIFIER|.setDefaultHostnameVerifier|NullHostnameVerifier||||||SSL implementation : insecure SSL implementation
onReceivedSslError|.proceed||||||SSL implementation : insecure webview implementation due to certificate errors
(http|https|ftp|ftps)://[^/\n ]*||||||SSL implementation : checking for weak protocols
content.ContentResolver||||||Insecure application permissions: the app queries Database of SMS, Contacts etc.
getSystemService||||||Insecure application permissions: the app gets system services
OpenFileOutput|getSharedPreferences|SharedPreferences.Editor|getCacheDir|getExternalStorageState|openOrCreateDatabase||||||Insecure application permissions: the app performs local file I/O operations
getSubscriberId|getDeviceId|getDeviceSoftwareVersion||||||Device Details: the app gets Device Info
getSimSerialNumber|getSimOperator|getSimOperatorName||||||Device Details: the app gets SIM data
telephony.TelephonyManager||||||Device Details: the app accesses telphony
sendMultipartTextMessage|sendTextMessage|vnd.android-dir/mms-sms|telephony.SmsManager||||||Device Details: the app can send SMS
app.NotificationManager||||||Device Details: the app sends out Android Notifications
getAllCellInfo||||||Location Services: the app gets Cell information
getCellLocation||||||Location Services: the app gets Cell location
android.location|getLastKnownLocation|requestLocationUpdates|getLatitude|getLongitude||||||Location Services: the app gets GPS location
(^127\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.168\.)|||50|||Dump any private IP addresses: Location Services
dexguard.util|sDebugDetector.isDebuggable||||||Debugging: Debug is set to TRUE
IRemoteService|IRemoteService.Stub|IBinder||||||Service Hijacking: the app can communicate with other processes
sendBroadcast|sendOrderedBroadcast|sendStickyBroadcast||||||Broadcast Thief: the app sends broadcasts
startActivity\(|startActivityForResult||||||Malicious Activity/Service Launch: the app starts activties
startService|bindService||||||Malicious Activity/Service Launch: the app starts services
ServerSocket|net.ServerSocket|connect[(][)]|||60|||the app opens TCP Server Sockets: Insecure use of network sockets
DatagramSocket|net.DatagramSocket||||||Insecure use of network sockets: the app can open UDP Datagram Sockets
android.util.Base64|.encodeToString|.encode||||||Application makes use of encoding : the app uses Base64 encoding
android.util.Base64|.decode||||||Application makes use of encoding : the app uses Base64 decoding
17 changes: 17 additions & 0 deletions src/config/script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
filename="owasp_static_android.txt"
try:
with open(filename, "r") as file:
lines_in_file = file.read().splitlines()
except IOError:
print("could not open file '%s'." % filename)
line_index = 1
try:
for line in lines_in_file:
line_index = line_index + 1
if len(line.split('|||'))==3:
print(str(line.split('|||')[2]) + "||||||" + str(line.split('|||')[1]) + "|||" + str(line.split('|||')[0]))
else:
print(str(line.split('|||')[2]) + "|||" + str(line.split('|||')[3]) + "|||" + str(
line.split('|||')[0]) + "|||" + str(line.split('|||')[1]))
except IOError:
print("Format is not readable or file is missing: %s." % filename)
15 changes: 15 additions & 0 deletions src/config/script2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
filename="owasp_static_android.txt"
try:
with open(filename, "r") as file:
lines_in_file = file.read().splitlines()
except IOError:
print("could not open file '%s'." % filename)
line_index = 1
try:
for line in lines_in_file:
line_index = line_index + 1

print(str(line.split('|||')[0]) + "|||" + str(line.split('|||')[1]) + "|||" + str(
line.split('|||')[3]) + ": " + str(line.split('|||')[2]))
except IOError:
print("Format is not readable or file is missing: %s." % filename)
31 changes: 11 additions & 20 deletions src/config/src_search_words.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
password|||10|||triggers unwanted classes like password reset, hence the low score
privatekey|||80
private_key|||80
apikey|||75
http:|||10
https:|||7
database_secret|||80
database_password|||80
databasepassword|||80
databasesecret|||80
(https|http):\/\/.*api.*|||60||| This regex matches any URL containing 'api'
(https|http):\/\/.*test.*|||60||| This regex matches any URL containing 'test'
(https|http):\/\/.*uat.*|||60||| This regex matches any URL containing 'uat'
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|||40||| Matching IP adresses
^[a-f0-9]{32}$|||70||| MD5 hash
\b([a-f0-9]{40})\b|||70||| SHA1 hash
^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$|||70||| base64 string
Authorization: Basic|||95||| Basic authentication
SELECT \* FROM|||40||| Intersting SQL transaction
INSERT INTO .* VALUES|||40||| Intersting SQL transaction
passw(d|ord)?|||10|||Sensitive parameters which can contain hardcoded credentials. The score is quite low because this query is often a false-positive.
(private|secret|api|aws)[_-]?key|||50|||Sensitive parameters which can contain hardcoded credentials. The score is quite low because this query is often a false-positive.
https?:|||7|||An URL was found, this might be an API endpoint or just a link to documentation. Hopefully the first one.
(db|database)[_-]?(passw(d|ord)?|secret)|||80|||This match probably contains hardcoded database credentials.
https?:\/\/.*(uat|test|api).*|||60||| This regex matches any URL containing 'api|uat|test'
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|||40|||An IP address was found, this might be a server (where the API is hosted). Or this might be a link to documentation, however chances are low.
^[a-f0-9]{32}$|||70|||An MD5 hash was found! You are lucky because MD5 is easily crack-able. Just google for "MD5 decrypt online" and you will come a long end.
\b([a-f0-9]{40})\b|||70|||A SHA1 hash was found! You are lucky because SHA1 is easily crack-able. Just google for "SHA1 decrypt online" and you will come a long end.
^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$|||70|||A base64 string was found. Go to https://www.base64decode.org/ and paste your value. This decrypted value is in most cases very interesting.
Authorization: Basic|||95|||Basic authentication was found. Apart from the fact that API communication should be with OAUTH or something similar, it contains hardcoded credentials.
(SELECT\s[\w\*\)\(\,\s]+\sFROM\s[\w]+)| (UPDATE\s[\w]+\sSET\s[\w\,\'\=]+)| (INSERT\sINTO\s[\d\w]+[\s\w\d\)\(\,]*\sVALUES\s\([\d\w\'\,\)]+)| (DELETE\sFROM\s[\d\w\'\=]+)|||40|||Interesting SQL transaction! In most cases a useless finding, but it might lead to something bigger. Might.
Loading