Every Android device has system logs just like any other operating system. Thanks to Wazuh, we can extract beneficial information from these logs by sending them to a Wazuh manager instance and adding custom decoders and rules.

Think about an Android device used for work purposes that should not be altered with the installation of any application. Now think about a thousand of those devices. Having an alert system to send a notification if an application is installed would be invaluable for your business.

Requirements

  • Android Syslog client
  • Permissions for the Android Syslog client to read system logs
  • A Wazuh manager configured to listen to syslog events
  • The Android device needs a network address pointing to the Wazuh manager
  • Optional: ADB CLI in a personal laptop (one-time usage)

How to configure the Wazuh manager instance

Include the next block in the local configuration (/var/ossec/etc/ossec.conf):

<remote>
  <connection>syslog</connection>
  <port>514</port>
  <protocol>udp</protocol>
  <allowed-ips>192.168.0.0/24</allowed-ips>
  <local_ip>192.168.0.200</local_ip>
</remote>

Where 192.168.0.200 is the Wazuh manager address and 192.168.0.0/24 is the network it accepts as the source addresses for our Android devices. So 192.168.0.139 would be an accepted address.

Restart the service so the changes take effect:

$ sudo systemctl restart wazuh-manager

How to configure our Android device

First of all, you will need to install a Syslog client. The Play Store has plenty of options. For this example guide we’ve installed LogcatUDP. It’s free and easy to use.

Once installed, your device must grant read permission for the system log, and there are different ways to do this. The easiest way is by using ADB. Install ADB CLI in a Linux laptop. Connect your Android device with USB debugging activated. Then execute the next command in your Linux laptop:

adb shell pm grant sk.madzik.android.logcatudp android.permission.READ_LOGS

Now the app LogcatUDP can read the system logs.

The last step is to open the LogcatUPD app and set the Wazuh manager address and port (192.168.0.200 as address and 514 as port). Then press Save and (re)start. It’s now sending everything to the Wazuh manager instance.

Note: You can make the permissions change by using a shell in the Android device, but using ADB is fast and easy.

Hands-on with Android events

Just to be sure your Wazuh manager is receiving events from a remote Android device. You then activate the verbose output enabling the next option in the local configuration:

<logall_json>yes</logall_json>

After restarting the service and performing some actions on your Android device, you should begin to see events coming in /var/ossec/logs/archives/archives.json:

{"timestamp":"2019-07-26T12:01:28.130+0000","agent":{"id":"000","name":"master"},"manager":{"name":"master"},"id":"1564142488.2661882","cluster":{"name":"wazuh","node":"node01"},"full_log":"07-26 14:01:27.025 991 1009 D : DpmQmiMgr areAllIfaceActive ","decoder":{},"location":"192.168.0.139"}
{"timestamp":"2019-07-26T12:01:28.130+0000","agent":{"id":"000","name":"master"},"manager":{"name":"master"},"id":"1564142488.2661882","cluster":{"name":"wazuh","node":"node01"},"full_log":"07-26 14:01:27.009 809 834 E ANDR-PERF-MPCTL: Invalid profile no. 0, total profiles 0 only","decoder":{},"location":"192.168.0.139"}
{"timestamp":"2019-07-26T12:01:28.130+0000","agent":{"id":"000","name":"master"},"manager":{"name":"master"},"id":"1564142488.2661882","cluster":{"name":"wazuh","node":"node01"},"full_log":"07-26 14:01:27.004 1123 1291 D [GF_HAL][gf_hal_device]: [gf_handle_thread] ignore screen off msg.","decoder":{},"location":"192.168.0.139"}
{"timestamp":"2019-07-26T12:01:28.130+0000","agent":{"id":"000","name":"master"},"manager":{"name":"master"},"id":"1564142488.2661882","cluster":{"name":"wazuh","node":"node01"},"full_log":"07-26 14:01:27.004 828 828 D SurfaceFlinger: Finished set power mode=0, type=0","decoder":{},"location":"192.168.0.139"}
{"timestamp":"2019-07-26T12:01:38.178+0000","agent":{"id":"000","name":"master"},"manager":{"name":"master"},"id":"1564142498.2661882","cluster":{"name":"wazuh","node":"node01"},"full_log":"07-26 14:01:29.105 991 1009 D : DpmQmiMgr areAllIfaceActive ","decoder":{},"location":"192.168.0.139"}

The location tells us the Android device address, which in this case is "location":"192.168.0.139", so we can see that the Wazuh manager is receiving events properly.

Custom decoders and rules for detecting installations

By taking a look at the archives.json output, we can filter those messages that would be useful for us. For example, once a user installs a new application on the device, it will print a reasonable number of logs. More than one kind of log would be valid, but for this example, we selected the following one:

07-26 12:40:28.938 16091 16091 I Finsky : [2] lex.c(48): Successful install of com.sonelli.juicessh (isid: Ucttmpa0Q1q3I88s_410tg)

From that logline, we can see Successful install of com.sonelli.juicessh which means the application with the package name com.sonelli.juicessh was installed.

Let’s add the next custom decoder in /var/ossec/etc/decoders/local_decoder.xml:

<decoder name="android_decoder_02">
   <prematch>\.*Finsky</prematch>
   <regex>\.*Successful (install) of (\.+) \.*</regex>
   <order>action_name,package_name</order>
</decoder>

We can try some log samples using the built-in tool named ossec-logtest:

# /var/ossec/bin/ossec-logtest
2019/07/26 12:11:54 ossec-testrule: INFO: Started (pid: 28554).
ossec-testrule: Type one log per line.

07-26 12:40:28.938 16091 16091 I Finsky : [2] lex.c(48): Successful install of com.sonelli.juicessh (isid: Ucttmpa0Q1q3I88s_410tg)

**Phase 1: Completed pre-decoding.
full event: '07-26 12:40:28.938 16091 16091 I Finsky : [2] lex.c(48): Successful install of com.sonelli.juicessh (isid: Ucttmpa0Q1q3I88s_410tg)'
timestamp: '(null)'
hostname: 'master'
program_name: '(null)'
log: '07-26 12:40:28.938 16091 16091 I Finsky : [2] lex.c(48): Successful install of com.sonelli.juicessh (isid: Ucttmpa0Q1q3I88s_410tg)'

**Phase 2: Completed decoding.
decoder: 'android_decoder_02'
action_name: 'install'
package_name: 'com.sonelli.juicessh'

So our custom decoder works because it’s extracting the fields action_name and package_name with the desired values.

Now let’s create a custom rule in /var/ossec/etc/rules/local_rules.xml:

<rule id="100003" level="5">
  <decoded_as>android_decoder_02</decoded_as>
  <description>App installed</description>
  <field name="action_name">install</field>
  <group>android_install,</group>
</rule>

If we try the tool ossec-logtest one more time,

# /var/ossec/bin/ossec-logtest -a
2019/07/26 12:14:46 ossec-testrule: INFO: Started (pid: 28575).
07-26 12:40:28.938 16091 16091 I Finsky : [2] lex.c(48): Successful install of com.sonelli.juicessh (isid: Ucttmpa0Q1q3I88s_410tg)
** Alert 1564143288.1: - android,android_install,
2019 Jul 26 12:14:48 master->stdin
Rule: 100003 (level 5) -> '(null)'
07-26 12:40:28.938 16091 16091 I Finsky : [2] lex.c(48): Successful install of com.sonelli.juicessh (isid: Ucttmpa0Q1q3I88s_410tg)
action_name: install
package_name: com.sonelli.juicessh

We can see if an alert is being generated properly. Now try to install a real application on your Android device. The Wazuh manager should generate an alert.

{
   "timestamp":"2019-07-26T12:18:08.538+0000",
   "rule":{
      "level":5,
      "description":"App installed",
      "id":"100003",
      "firedtimes":1,
      "mail":false,
      "groups":[
         "android",
         "android_install"
      ]
   },
   "agent":{
      "id":"000",
      "name":"master"
   },
   "manager":{
      "name":"master"
   },
   "id":"1564143488.2683756",
   "cluster":{
      "name":"wazuh",
      "node":"node01"
   },
   "full_log":"07-26 14:17:00.810 16091 16091 I Finsky : [2] lex.c(48): Successful install of com.airbnb.android (isid: c0whUj4AQ5C5HvBUpKinxg)",
   "decoder":{
      "name":"android_decoder_02"
   },
   "data":{
      "action_name":"install",
      "package_name":"com.airbnb.android"
   },
   "location":"192.168.0.139"
}

Avoid flooding

LogcatUDP and other similar applications may flood the agent’s alert queue with a lot of events per second. It works like Audit in Linux. Luckily, we can add filters just like Audit does. Those filters commonly work using tag:priority pairs.

For example, let’s say we want to only receive the events from the ActivityManager and only those events that are warning messages. Our filter would be ActivityManager:W.

As we’ve seen, this connection between Android devices and Wazuh can generate infinite combinations in your ruleset which can be adapted to fit your needs.

Here are some other useful Android activities that you might want to analyze using Wazuh:

  • Unlock screen
  • Incoming/Outcoming calls
  • Notifications
  • App installations and removals
  • Hardware usage

Contributing to Wazuh Android monitoring

We are open source, and we are grateful for your contributions related to Android monitoring. Tell us about your use cases in our #community Slack channel and in our mailing list, or what you would like to see. You can also make a pull request in our ruleset repository. All ideas are welcome, so feel free to reach out to us with your thoughts.

References