Data Breach: Dogness IOT gets put in the Dog House

Summary

Pet focused IoT manufacturer Dogness, has left exposed it's unsecured ElasticSearch server, that contained the usernames, emails, clear-text passwords, and session cookies of it's users. The unprotected information has lead to the complete exposure of it's production SQL database, application source code, and  the complete takeover and control of it's pet feeding devices and associated accounts.

TLDR; Highlights for the impatient

  • ElasticSearch - Clear Text User/Passwords = Stepping stone to the keys of the kingdom
  • Mobile Application Analysis - why are developers still using http????
  • OSINT - Github - all your base are belong to us
  • Mysql - All data exposed
    • Full Name
    • Email Address
    • DOB
    • Gender
    • Home address
    • Precise GPS location history
  • Device Firmware
Discloure Disclaimer

Prior to the publishing of this blog, Dogness International was given 30 days notice of any issues found. Even though an initial response from Dogness was not recieved, follow up emails were sent in order to ensure they were aware of the issue and took immediate actions to protect thier users.
Timeline:
  • On Janurary 28th an initial notice to Dogness was sent - No response
  • On Janurary 30th a followup was sent - No reponse
  • Approx Feb 4th ElasticSearch server protected
  • Feb 6th - Further issues found with Dogness Github, and Mysql and notified Dogness
  • Feb 7th - received response from Dogness
  • Feb 28h - Publishing deadline extended due to COVID-19 and it's impact to getting the issues resolved quickly

Background Info

Dogness (International) Corporation  is a manufacturer based out of Dongguan, China, (offices in US) that designs, manufactures and distributes pet related products to major retail stores and wholesalers around the world.  Dogness has created and sold several  IoT devices used for the entertainment and feeding of pets such as the Dogness Smart Cam Treater and the Dogness Smart Cam Feeder.  

As well as several IoT devices, Dogness also has a Mobile Applicaiton used for the control and monitoring of the feeding devices.

ElasticSearch - Stepping stone to the keys of the kingdom

In early January, as part of my ongoing research into ElasticSearch servers, I came across a server with the indexes of "dogness-microservice" which contained several interesting records that held diagnostic logs for API calls.  After several minutes of reviewing the records, it became evident that the level of detail being exposed could lead to a complete takeover of all user accounts/devices.

Note: all json/code samples have been redacted/simplified for atricle purposes

Sample ElasticSearch API Record

{
  "_index": "dogness-microservice-2020.01.07",
  "_source": {
    "message": "9kXXXX@gmail.com-3478423991 请求 ▶▶▶▶▶▶▶▶▶ url: /service/user/authUserInfo/get | params: {\"params\":\"*\"} | access-domain: http://apius.dogness.com | client-ip: XX.XX.93.95 | headers: {\"content-length\":\"10\",\"os\":\"ios\",\"accept-language\":\"en-US;q=1\",\"timezone\":\"-5\",\"x-forwarded-for\":\"XX.XX.93.95\", \"x-auth-token\":\"4r10aa304ceXXXXXXe48g444@300g609m01cae8bi177l95f.e11c3:docp3m9p::9ak\",   "accept\":\"*/*\",\"app-version\":\"184\",\"x-real-ip\":\"XX.XX.93.95\",\"host\":\"apius.dogness.com\",\"connection\":\"close\",\"content-t
ype\":\"application/x-www-form-urlencoded\",\"lang\":\"en\",\"accept-encoding\":\"gzip, deflate\",\"user-agent\":\"DOGNESS/1.8.4 (iPhone; iOS 12.2; Scale/2.00)\"}",
    "thread_name": "http-nio-8961-exec-27",
    "host": "54.184.52.74",
    "application.name": "gateway-service",
    "@timestamp": "2020-01-07T02:49:18.451Z",
    "gateway_track": "3478423991",
    "port": 34506,
    "account": "9kXXXXX@gmail.com",
  }
}

Taking a closer look at the various record types, a login record was observed with a clear-text password

{
  "_source": {
    "message": "wyf@XXXXX.com-3800307162 请求 ▶▶▶▶▶▶▶▶▶ url: /service/authentication/login/password | params: {\"password\":\"(CLEARTEXT)\",\"username\":\"wyf@XXXXX.com\"} | access-domain: http://apius.dogness.com | client-ip: 119.28.213.253 ,\"content-length\":\"0\",\"host\": \"apius.dogness.com\",\"connection\":\"close\",\"x-forwarded-for\":\"119.28.213.253\",\"accept-encoding\":\"gzip,deflate\",\"user-agent\":\"Apache-HttpClient/4.5.6 (Java/1.8.0_161)\"}",
    "account": "wyf@XXXXX.com"
  }
}
*leaving session tokens or passwords in unredacted form, is a major risk when logging API calls

At this point in time it because obvious that a full in-depth look at the entire dogness infrastructure, servers, and mobile applicaiton was prudent.  

The in-depth investigation lead to several major issues with regards to the Dogness servers and mobile application such as:

  1. Use of HTTP in mobile application
  2. Server source code was easily found on github including database credentials and private keys
  3. Use of MD5 with a static salt for password hasing lead to quick brute force cracking of over 1500 user accounts.

Mobile Application Analysis - why are developers still using HTTP????

Running the Android Dogness mobile application through the typical tools (Packet Capture, and apktool) you can see where API calls to the Dogness server, are made via HTTP instead of a more secure HTTPS protocol.

Issues found with the mobile application include:

  1. Simple passwords are allowed to be used when registering new users
  2. Application uses http and sends clear text passwords to "Login" which can be intercepted.

Since the Dogness API server was not running a parallel port using HTTPS, it is assumed that the customers feeders are also not using HTTPS.

OSINT - Github - all your base are belong to us

Based on the exposure of the ElasticSearch data, and the use of HTTP, I wanted to see if it was possible to locate a firmware image of the feeders to confirm if similiar security issues existed there.  Using the typical searches on Google, and looking within the ElasticSearch data, I was unable to locate a firmware image.  After striking out in the usual locations, I checked GitHub on the odd chance that I might find something.  Bingo.  There were several user repositories which contained references to "Dogness" or "Dogness International", and while most of them where over 2 years old, there was one repository which are approx 8 months old.  

After reviwing the repository there was several significant discoveries in the source code.

github - Private Keys

Several private keys were found in the source code:

public static String privStr = "-----BEGIN PRIVATE KEY-----\n" +
    "MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgkc58pesww9cUKFnqmaoX\n" +
    "BcHIIN63gdhPttZB62XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXgVVFc+cR7rCXvH\n" +
	"tBUtBoA3RBgB1FVUJuwRiWW9fVob2QyHowJacLYE5pFnwgN3kb5j\n" +
    "-----END PRIVATE KEY-----";

//change public pem string to public string
public static String pubStr = "-----BEGIN PUBLIC KEY-----\n"+
	"MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAESSCBHd5SN9uOZoybLtlIFVRXPnEe6wl7\n"+
	"x7QVLQaAN0QYAdRVVCbsEYllvXXXXXXXXX6MCWnC2BOaRZ8IDd5G+Yw==\n"+
	"-----END PUBLIC KEY-----";

Including one for the Dogness Alipay account:

Alipay private key and application ID

     public static String getAlipayOrderinfo(String order_number, BigDecimal total_money, String title){
            final String APPID = "2017020605537253";
            final String RSA2_PRIVATE = "" +
                    "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCs/sD5wxZ5Kpb2" +
                    "ZDIL2WIXJG/46J2YfCrIdkHvs4RySV/TAKbpx4KANHlS2BeoRnrAuKXsnLoCYrc0" +
                    "pRqzPixhAEvtiwIf1PmtvWtgBAVQ/kUp0AqZlvTWAUYfRc7ISfxlZXKv+heVlVD4" +
                    "8gBibJPqLwZhTeygCmhiV8P0cUsELZhJUAQtHAZwWw5osDP/lKmVkmPFJxjVENLz" +
                    "zCpyMW6KdfCv6APMOJgB93FwIcJr9uWskQP1uj9tCvKRSLb9/uB22UxIlUUHLXSK" +
                    "OM1blRQmrCe9akPDUqsngpQg0oDfSY+xuwZXc3E0imSAb5lW3uGuWA8cadJokymM" +
                    "tan7w2G1AgMBAAECggEAPC531aufktFVKSwcGPEr5Z8gcPgDczum6ovxTkEmT1fl" +
                    "Unk7ZpW5pVRhj4rGt0sh4g3QYLwHcQeGqmgdwZTw2zx1LFm9gcCKBy8Z8MEdT/uE" +
                    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
                    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
                    "Xk7RaHHGAchung83n7uBnPZ4WtsFhUhYJYJdzoKcEve4hbQOCtDuu4+FAoGBAI+O" +
                    "bbHqWc3rQ+7b7X3Uvhcj3IL5etBZqMNVQRJi0eDLr9/+rUMIJ3F0n8eh+qdRI5PN" +
                    "KTVTeUyAbhg3/7tkwDtrosj/tEKNSiCqwVudx7TlTzZ/jlXFu/xSybh2jfjYdPc+" +
                    "fToWIGeunDtSpHZ2dCBwMnl6WAPBTcqEcZcfMvl/AoGBAJrTcbPxISQJygKAj+qs" +
                    "FtHdWs9QG3l44dAmHkGcpULqsw/j2g5ODB+I8nziQHeDucdfL4iuNQfeg0bd8G+c" +
                    "5caIFoFNxjeOhZKtwVgyoxLmm0Wv4q7Db2CUk90jton3gjlvde4L39dtWv3vd7BI" +
                    "GWW+AgBFaCFZxzK3Lfh/6K67";^M
            final String RSA_PRIVATE = "";^M

github - yaml config files

yaml configuration files which contained information about thier current production environment.

Mysql - Access granted and more problems revealed.

While several older yaml files held "dummy" login and paswords for the various internal Dogness services, there were a few which did contain uptodate credentials for Mysql and Redis in both thier US and Chinese production environments.  After confirming the SQL credentials where correct. I wanted to ensure it was for a production database, and not a development/staging system.  Below is a query which shows the user I had just created on thier platform using thier mobile application.

For those with keen eyes, you will noticed that the password field looks like an MD5 hash. (Why are people still using MD?).   As I knew the original password when registering, I was able to confirm that the known password and the hash did not match.  This lead to another idea, and back to the github repository to see what how passwords were being handled on the server side.

public class MD5Util {

    private static final String SALT = "XXXXXXXXXXXXXX";

    public static String encode(String password) {
        password = password + SALT;
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        char[] charArray = password.toCharArray();
        byte[] byteArray = new byte[charArray.length];

        for (int i = 0; i < charArray.length; i++)
            byteArray[i] = (byte) charArray[i];
        byte[] md5Bytes = md5.digest(byteArray);
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }

            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }
    ```

After a quick test I was able to confirm that the MD5 + Static Salt model was in fact used in thier current production system.

API - open to abuse

As part of the inital investigation into the mobile applicaiton and ElasticSearch data, I was able to take a sample set of API calls and use it to perform "basic" account operations (as I did not have a physical device I could not test it against a feeder device) listed below if a list of actions which could be taken using the data available via ES/SQL/Source code

  1. Login with clear text password used in ElasticSearch records
  2. Use "recent" session tokens to make api calls on behalf of users
  3. Using "older" tokens, I Was able to request a token refresh to gain a new token to issue commands.

Even without MySQL access, using the 3 methods above, I was able to use the "getUser" API endpoint to obtain the MD5 hashed password for users which would be run against standard databases using John the Ripper.

Approx 1500 account passwords where guessed in less than 60 seconds.

Wrap up summary

The analysis above did not go into the "admin interface" which had several references in the github respositories, as well as the stored userid/passwords in the Mysql database. A quick analysis of admin users in SQL revealed several which had guessable passwords.

Based on the items listed above, and the assumption that admin users in the Mysql database were could be used in the production system, I think it's safe to say that complete access to the Dogness system was possible,  not just by myself, but by another others which could easily disccover either the ElasticSearch server or the source code on Github.

 

Show Comments