zmNinja, Privacy and Your Data

oZoneDev
oZoneDev
Jun 19, 2018 · 10 min read
Image for post
Image for post
Photo by Josh Edgoose on Unsplash

Record of changes: (started Oct 17, 2020)

  • Oct 17, 2020 updated information about intermediary server that routes your push messages. Also updated note on firebasex plugin and features that zmNinja disables

This post is intended to provide more details on how zmNinja engages (or not) with data that may be personal to you.

Image for post
Image for post
Image for post
Image for post

1 What is zmNinja?

  • zmNinja is an open source client app for the popular and open source ZoneMinder home security server. If you use ZoneMinder, zmNinja offers a convenient mobile first front end that allows you to view your security cameras via ZoneMinder, which is much more convenient that trying to open the ZoneMinder web portal on a device.
Image for post
Image for post

2 Contact

Image for post
Image for post

3 Data collection, reporting & purpose

  • Due to the way zmNinja needs to interact with ZoneMinder, it necessarily needs to store data about the following items of your ZoneMinder configuration: Portal URL, API URL, Cgi-bin URL, username, password (if you are using passwords) . Besides these parameters, other app related settings are also stored
  • zmNinja stores this user configuration in a sqlite database in iOS and an indexDB database in Android devices (I don’t use sqlite in Android due to this issue). Certain android devices don’t seem to work with indexDB due to which a fallback is to write to a localStorage DB. This database is encrypted, but please see Design Considerations note later
  • In addition to this data, zmNinja also stores the following cookies: ZMSESSID — used to indentify a session with ZoneMinder — this is created by ZoneMinder. zmCSS and zmSkin — the ZoneMinder style & skin that is used. zmNinja doesn’t use this, but ZoneMinder automatically sets this as zmNinja uses the web portal to login (there is no login API defined today in ZoneMinder)
  • User data storage (Mobile app) — Removing the app from the device automatically removes the data if you have disabled cloud sync. Starting version 1.3.021 of zmNinja you now have an option to sync your profile data with your Android or iOS personal cloud (GDrive or iCloud respectively). This option is enabled by default and can be turned off in Menu->Settings. While it is enabled, your login data will be synced with your personal cloud account using the platform backup service. This data is not accessible to me — it is your personal space that Android and iOS offers to their users. I’d recommend you leave this on because if the app gets deleted, you can recover the data from your cloud. It also has the benefit of retrieving the data when you install the app on another device using the same cloud login.
  • User data storage (Desktop app) — As far as the desktop version is concerned, the data is stored in a different location based on your OS, and you can manually remove it. The paths, typically, are: %APPDATA%/zmNinjaDesktop for Windows, $XDG_CONFIG_HOME/zmNinjaDesktop or ~/.config/zmNinjaDesktop for Linux and ~/Library/Application Support/zmNinjaDesktop for OSX
  • The push-plugin library that zmNinja uses for push notifications in turn uses the Firebase library that seems to collect advertising IDs, for the Android platform. zmNinja itself doesn’t use it for any purpose. Staring release 1.3.027 and beyond this will be disabled. Updated: Starting 1.6 of zmNinja, I now use an alternate plugin (firebasex) and zmNinja configures it with the following flags disabled:
"FIREBASE_ANALYTICS_COLLECTION_ENABLED": "false",        "FIREBASE_PERFORMANCE_COLLECTION_ENABLED": "false",        "FIREBASE_CRASHLYTICS_COLLECTION_ENABLED": "false",
  • zmNinja, by itself, DOES NOT collect any other analytics/telemetry information, trend information or usage information for its own purpose.
  • None of this information is transmitted to any 3rd party server — any and all user profile data lies strictly inside the app database and is only transmitted to the ZoneMinder server of your choice. That being said, if you are using zmNinja on mobile devices, any information collected by Google and Apple may be sent to their respective servers. Please see privacy policies of Google and Android below. Note however, if you are using my open source Event Server for push notification, some elements of information are sent out to an intermediary server which is necessary to make push work. Please read section on Push Notifications below.
  • Privacy Policies of Google and Apple: If you are not building zmNinja from source, and purchase the app from either Google or Apple, then you should know both Google and Apple may collect data about you. This is not unique to zmNinja, but applies to any app you may download from these stores. Read more about Google’s Privacy Policy and Apple’s Privacy Policy respectively.
  • zmNinja DOES NOT use any embedded advertising SDKs (please see firebase library note above).
Image for post
Image for post

4 Data & transport security

  • To communicate with ZoneMinder, zmNinja uses either HTTP or HTTPS. Which protocol to use is configured by you. I strongly recommend that you use HTTPS
  • zmNinja does not use any other ports other than the port that is used to access ZoneMinder web console (the exception here is if you enable push notifications, in which case, see the Push Notifications section later)
  • Some users prefer to not use ZoneMinder authentication at all, and/or use tools such as OpenVPN to create a secure tunnel from the mobile app to the server. How you choose to set up transport security between zmNinja and ZoneMinder is upto you
  • While not related to zmNinja, when you first install ZoneMinder, it generates a self-signed certificate. I’d recommend you use a trusted SSL certificate instead. Let’s Encrypt offers a free SSL certificate
  • If you use basic-authentication with ZoneMinder then you should consider upgrading to zmNinja 1.3.0 or above. Earlier versions of zmNinja embedded basic credentials as part of the URL (example admin:password@yourZMurl). Starting 1.3.0, zmNinja properly converts basic authentication credentials to an Authorization header. Due to a platform limitation, however, zmNinja uses a query parameter to transmit the Authorization token when displaying images, if basic auth is used. Note that it is trivial to decode Authorization headers too, so SSL is strongly recommended anyway (And you should know, in general, basic authentication is not intended as a secure mechanism)
Image for post
Image for post

5 Third party plugins & frameworks

  • zmNinja relies on several 3rd party plugins for critical functionality. A complete list is provided here and here. In addition to these, zmNinja also uses some additional packages mentioned here (these are packages that are manually included and therefore not listed in the previous links)
  • zmNinja is as web app, and uses Ionic as a UI layer and Cordova to package the web app into an installable app
  • zmNinja Desktop uses Electron as an app wrapper
  • To the best of my knowledge none of these packages contact any 3rd party server not under your control during execution of the app, with the exception of phonegap-plugin-push that offers Push Notification functionality and necessarily needs to contact Google’s FCM servers for push (more on this later)
  • If you are compiling zmNinja from source, obviously, you will need other packages and dependencies that do involve contacting 3rd party services (such as npm registry, cordova, github and other sources as outlined in the link above)
Image for post
Image for post

6 Logging

  • Storing app logs is a critical part of being able to debug when things go wrong. The app logs are stored in a text file called zmNinjaLog.txt as part of the app data. The log file is not encrypted, but the code removes passwords before storing into the file
  • You can delete the logs at any time by going to the logs view and tapping on the “trash” icon on the top right
Image for post
Image for post

7 Design considerations

  • zmNinja is a web application. By nature, it is therefore possibe to decode or decompile the app if anyone had physical access to your phone and is able to access zmNinja. However, I already publish the source code for everyone, so I don’t consider this to be an issue
  • ZoneMinder today does not provide any token based login API. This is also why I need to store your username/password. This data is transmitted to ZoneMinder using an HTTPS or HTTP (depending on how you’ve configured ZoneMinder) POST method with the username and password as a data field
  • The database encryption uses a static cipher key. In other words, if someone adept at debugging were to access your phone, bypass any credentials of your phone, they will be able to extract your zmNinja database and decrypt it. I haven’t found a good mechanism to generate a portable device specific cipher key that works reliably across iOS and Android. Even if I did, if the goal is to decrypt the DB without prompting the user, and we can’t make assumptions about the presence of fingerprint or face auth, that cipher will need to be stored somewhere, so not sure how that will help. Therefore, the ciphering of the DB is only meant as a thin layer of protection so as not to store the user data in clear text. It is strongly recommended you use device specific password protection such as fingerprint auth/ password auth/face ID and similar means
Image for post
Image for post

8 Push notifications

  • zmNinja works with my open source event notification server to deliver push notifications to iOS and Android devices (and any other consumers that register with it). If you enable this functionality, a unique token, generated by Google’s FCM server is exchanged between your server and Google Firebase. This is required to transmit push messages from your event server to your device. Please refer to this link to read about Firebase and FCM (Cloud Messaging) privacy guidelines from Google. If you are an iOS users, Google’s FCM will in turn proxy the message to Apple’s APNS servers so that your phone receives the message
  • The event notification server (zmeventnotification.pl) can be configured using secure web sockets or websockets. I’d strongly recommend secure web sockets. Please see its install guide for more details
  • The event notification server communicates with the following servers: a) With ZoneMinder over shared/mapped memory to access alarm details, b) (updated for ES 6) An intermediary Google Cloud function server I wrote as a push proxy and, c) Google FCM servers to send push notifications to your device
  • If you don’t use the event server, then this functionality is disabled and no data is transmitted or exchanged with the FCM servers or my intermediary server
  • Note that desktop zmNinja does not use FCM. It simply sets up a websocket connection directly between your installed zmeventnotification.pl and the zmNinja desktop app. No intermediate servers are used (which also means push notifications don’t get delivered if the desktop app is not running)
Image for post
Image for post

9 App permissions

zmNinja mobile apps need the following permissions:

  • Read/Write storage — to save snapshots of events, save data
  • Network access — to access ZM, read connection type for low bandwidth switching
  • Send receive data over the network — basic operation, with ZM
  • Control Vibration — for push notifications
  • Prevent Device from Sleeping — to keep screen on in montage and other screens

You can see a comprehensive list here for Android. iOS is similar.

Image for post
Image for post

10 Peace of mind

  • zmNinja is open source. Feel free to audit the code anytime you want
  • If you are so inclined, you can always build your own version of the app for all platforms and completely avoid downloading the app/play store version
  • If you run the desktop version, you can hit Ctrl+Alt+D to open a debug window and inspect the network or sources tabs to look at any external domains it is contacting/communicating with at any time (should only be your ZoneMinder server)
Image for post
Image for post

11 Have suggestions? Disagree? Agree? Think I missed something?

I’m not perfect, and may have missed something that should be here. If you feel so inclined, please email or comment here!

“Have no fear of perfection — you’ll never reach it.”
Salvador Dalí

zmNinja

zmNinja — the best open source surveillance mobile app for…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store