Understand what is written and what is not written application Burger King
This article is a response to the fennikami user’s article about how a bad Burger King records video from a smartphone screen. The original article claims that in this way Burger King can access information about the cards entered, thereby compromising them. I will try to figure out if everything is so.
With the help of a small instruction posted in the comments, you can independently get the video that Appsee sends. And make sure which data is retouched and which is not.
The Android application version 2.2.2 with the update date July 9, 2018 has been analyzed by me. Results on other platforms and in other versions of the application may differ from those shown in this article.
Initialization Appsee
Appsee is one of the analytics systems used to improve the user experience with the client application. It records the screen and your actions when you are in the application. In general, there is nothing terrible in this, on the Web, the WebVizor technology from Yandex is widely spread, which has the same purpose.
At the initial stage of their work, Appsee requests a configuration for a specific application from the server; it is this request that the author caught in the original article; in my case, the answer looked like this:
{
"AutoDetectScreens": true,
"AutoHideWebComponents": true,
"ClientId": "5b47182e7b2f3f1429341f73",
"ClientLogsUploadPolicy": 2,
"ConfigHttpTimeoutInMilliseconds": 5000,
"DetectActions": true,
"DetectCrashes": true,
"DetectGestures": true,
"DetectMenus": true,
"DetectPopups": true,
"HideInput": true,
"HideSensitiveViews": true,
"MaxEventProperties": 5001,
"MaxVideoLength": 0,
"OfflineConfigurationPolicy": 1,
"RecordMetadata": true,
"RecordVideo": true,
"SensitiveMaskingPerWindow": true,
"SessionId": "5b4718ec470302299bdcc04d",
"TrackedOfflineSessions": {},
"UploadAppIcon": false,
"UploadBenchmarks": false,
"UploadTouchEvents": true,
"UploadVideoOnCrash": true,
"UseWebViewSnapshotFullscreen": false,
"VideoBitrate": 56,
"VideoFPS": 3,
"VideoHeight": 320,
"VideoWidth": 160
}
You may notice that the HideInput , HideSensitiveViews parameters are true, thereby hiding important information in the video. The question immediately arises how the importance of the information is determined; for the answer, refer to the Appsee documentation . In short, all fields for data entry are hidden by default, additionally you can configure hiding for other fields or parts of the interface.
Let's also pay attention to the quality of video recording, in my case it was video with a resolution of 320 by 160 pixels, with a frequency of three frames per second.
Real data collected by Appsee
I decided to check what data is actually sent to the Appsee server, for this I used the proxy from Burp Suite. First, the analytics system transmits a file with user actions inside the application, including the coordinates of user clicks, there are no keystrokes on the keyboard.
Data collected by Appsee, custom actions
{"InitialOrientation":1,"InitialAppFrame":[0,0,1080,1776],"Crashed":false,"Duration":143361,"PreSessionDuration":2360,"VideoRecorded":true,"CustomEvents":[{"n":"open_screen","t":9688,"p":{"authorized":"no","screen":"sms","source":"auth_screen1","device_id":"9c843736-8da0-4832-ac9f-de83f5fe889b"}},{"n":"popup_screen","t":38560,"p":{"screen":"PromoGridFragment","device_id":"9c843736-8da0-4832-ac9f-de83f5fe889b","user_name":"Илья","popup":"select_restaurant","authorized":"yes","user_id":258504}},{"n":"open_screen","t":38727,"p":{"screen":"coupons_public","device_id":"9c843736-8da0-4832-ac9f-de83f5fe889b","user_name":"Илья","authorized":"yes","user_id":258504}},{"n":"open_screen","t":44781,"p":{"screen":"my_orders","device_id":"9c843736-8da0-4832-ac9f-de83f5fe889b","user_name":"Илья","authorized":"yes","user_id":258504}},{"n":"open_screen","t":48549,"p":{"screen":"public_coupon_details","device_id":"9c843736-8da0-4832-ac9f-de83f5fe889b","user_name":"Илья","coupon_name":"2 Воппер Обеда","authorized":"yes","user_id":258504}},{"n":"open_screen","t":57971,"p":{"current_restaurant_name":"0632-МУР, Мурманск, просп Ленина 32, ТЦ Мурманск Молл 4 этаж","screen":"cart","device_id":"9c843736-8da0-4832-ac9f-de83f5fe889b","user_name":"Илья","user_id":258504,"authorized":"yes","current_paying_method":"none"}},{"n":"open_screen","t":60413,"p":{"screen":"bank_card","device_id":"9c843736-8da0-4832-ac9f-de83f5fe889b","user_name":"Илья","authorized":"yes","user_id":258504}}],"Screens":[{"n":"AuthActivity","a":true,"p":0,"s":0},{"n":"MainActivity","a":true,"p":0,"s":36819},{"n":"CouponDetailActivity","a":true,"p":0,"s":48749},{"n":"CouponSelectGoodsActivity","a":true,"p":0,"s":50593},{"n":"MainActivity","a":true,"p":0,"s":56982},{"n":"BasketActivity","a":true,"p":0,"s":58115},{"n":"AddCardActivity","a":true,"p":0,"s":60672}],"Popups":[],"Gestures":[{"t":0,"r":1,"s":2274,"e":2332,"g":[2],"b":{"x":0,"y":1011,"w":1080,"h":144}},{"t":0,"r":1,"s":43150,"e":43208,"g":[3],"b":{"x":624,"y":1437,"w":390,"h":102}},{"t":0,"r":1,"s":44717,"e":44720,"g":[4],"b":{"x":216,"y":1608,"w":216,"h":168}},{"t":0,"r":1,"s":50163,"e":50213,"g":[5],"b":{"x":0,"y":1584,"w":1080,"h":192}},{"t":0,"r":1,"s":54105,"e":54135,"g":[6],"b":{"x":540,"y":561,"w":540,"h":636}},{"t":0,"r":1,"s":55250,"e":55291,"g":[7],"b":{"x":540,"y":561,"w":540,"h":636}},{"t":0,"r":1,"s":56430,"e":56480,"g":[8],"b":{"x":0,"y":1584,"w":1080,"h":192}},{"t":4,"r":1,"s":59230,"e":59354,"g":[9]},{"t":0,"r":1,"s":60368,"e":60409,"g":[10],"b":{"x":0,"y":207,"w":1080,"h":1569}},{"t":0,"r":1,"s":61430,"e":61488,"g":[11],"b":{"x":0,"y":207,"w":1080,"h":1569}},{"t":0,"r":1,"s":62273,"e":62356,"g":[12],"b":{"x":0,"y":207,"w":1080,"h":1569}},{"t":0,"r":1,"s":62686,"e":62744,"g":[13],"b":{"x":0,"y":207,"w":1080,"h":1569}},{"t":0,"r":1,"s":70657,"e":70698,"g":[15],"b":{"x":0,"y":207,"w":1080,"h":954}},{"t":0,"r":1,"s":72611,"e":72660,"g":[16],"b":{"x":0,"y":207,"w":1080,"h":954}},{"t":0,"r":1,"s":73344,"e":73394,"g":[17],"b":{"x":120,"y":178,"w":98,"h":862}},{"t":0,"r":1,"s":73757,"e":73825,"g":[18],"b":{"x":0,"y":207,"w":1080,"h":1569}},{"t":0,"r":1,"s":74230,"e":74287,"g":[19],"b":{"x":0,"y":207,"w":1080,"h":1569}},{"t":0,"r":1,"s":74904,"e":74945,"g":[20],"b":{"x":334,"y":178,"w":148,"h":895}},{"t":0,"r":1,"s":75663,"e":75729,"g":[21],"b":{"x":0,"y":207,"w":1080,"h":1569}},{"t":0,"r":1,"s":76346,"e":76386,"g":[22],"b":{"x":334,"y":178,"w":148,"h":895}}],"Actions":[{"t":5,"s":380,"i":"1"},{"t":0,"s":2332,"i":"1","p":"Далее","id":"2131361874","iu":1,"b":{"x":0,"y":1011,"w":1080,"h":144}},{"t":8,"s":9736},{"t":7,"s":9745,"p":"false"},{"t":5,"s":32117,"i":"1"},{"t":8,"s":33907},{"t":5,"s":33910,"i":"1"},{"t":0,"s":44720,"i":"5","p":"Мои заказы","id":"2131361823","iu":1,"b":{"x":216,"y":1608,"w":216,"h":168}},{"t":4,"s":62744,"i":"1"},{"t":7,"s":62746,"p":"false"},{"t":5,"s":63425,"i":"1"},{"t":4,"s":70698,"i":"2"},{"t":5,"s":71401,"i":"1"},{"t":1,"s":73394,"i":"1","p":"0.7"},{"t":8,"s":73877},{"t":1,"s":74945,"i":"1","p":"0.6"},{"t":1,"s":76386,"i":"1","p":"0.5"}],"OrientationEvents":[],"AppFrameEvents":[],"ThirdPartyIds":[],"ANRs":[],"AppUserId":"258504","TouchEvents":[{"g":2,"e":0,"x":942,"y":1059,"t":2274,"k":1},{"g":2,"e":1,"x":942,"y":1059,"t":2332,"k":1},{"g":3,"e":0,"x":872,"y":1510,"t":43150},{"g":3,"e":1,"x":872,"y":1510,"t":43208},{"g":4,"e":0,"x":360,"y":1681,"t":44717},{"g":4,"e":1,"x":360,"y":1681,"t":44720},{"g":5,"e":0,"x":885,"y":1652,"t":50163},{"g":5,"e":1,"x":885,"y":1652,"t":50213},{"g":6,"e":0,"x":690,"y":656,"t":54105},{"g":6,"e":1,"x":690,"y":656,"t":54135},{"g":7,"e":0,"x":660,"y":685,"t":55250},{"g":7,"e":1,"x":660,"y":685,"t":55291},{"g":8,"e":0,"x":813,"y":1719,"t":56430},{"g":8,"e":1,"x":813,"y":1719,"t":56480},{"g":9,"e":0,"x":741,"y":1485,"t":59230},{"g":9,"e":2,"x":741,"y":1484,"t":59246},{"g":9,"e":1,"x":880,"y":893,"t":59354},{"g":10,"e":0,"x":905,"y":1467,"t":60368},{"g":10,"e":1,"x":905,"y":1467,"t":60409},{"g":11,"e":0,"x":644,"y":919,"t":61430},{"g":11,"e":1,"x":644,"y":919,"t":61488},{"g":12,"e":0,"x":633,"y":802,"t":62273},{"g":12,"e":1,"x":633,"y":802,"t":62356},{"g":13,"e":0,"x":636,"y":893,"t":62686},{"g":13,"e":1,"x":636,"y":893,"t":62744},{"g":14,"e":0,"x":717,"y":1059,"t":70151,"k":1},{"g":14,"e":2,"x":716,"y":1058,"t":70168,"k":1},{"g":14,"e":2,"x":760,"y":846,"t":70302,"k":1},{"g":14,"e":1,"x":775,"y":806,"t":70403,"k":1},{"g":15,"e":0,"x":901,"y":887,"t":70657,"k":1},{"g":15,"e":1,"x":901,"y":887,"t":70698,"k":1},{"g":16,"e":0,"x":194,"y":855,"t":72611,"k":1},{"g":16,"e":1,"x":194,"y":855,"t":72660,"k":1},{"g":17,"e":0,"x":153,"y":854,"t":73344,"k":1},{"g":17,"e":1,"x":153,"y":854,"t":73394,"k":1},{"g":18,"e":0,"x":465,"y":853,"t":73757,"k":1},{"g":18,"e":1,"x":465,"y":853,"t":73825,"k":1},{"g":19,"e":0,"x":474,"y":1006,"t":74230},{"g":19,"e":1,"x":474,"y":1006,"t":74287},{"g":20,"e":0,"x":419,"y":719,"t":74904},{"g":20,"e":1,"x":419,"y":719,"t":74945},{"g":21,"e":0,"x":499,"y":996,"t":75663},{"g":21,"e":1,"x":499,"y":996,"t":75729},{"g":22,"e":0,"x":415,"y":597,"t":76346},{"g":22,"e":1,"x":415,"y":597,"t":76386}]}
The video transmitted to the Appsee server, as you would expect most of the data is hidden
See what happens next
It would seem that the appsee is safe and most likely helped the developers to improve the application several times. But let's still check what happens with the card data further. First you need to read the comment of the representative of Burger King in the media about the situation:
“The Burger King mobile application with a remote order does not collect personal data of its subscribers. All transactions are securely protected by one of the best acquirers in the country - Yandex.Cash. Data on user behavior in the application does not contain information on bank cards and is not stored on the server, ”the company said.It sounds convincing enough, and now we look at real traffic. For payment, processing from Yandex is actually used, it can be determined by a request with an address.
https://payment.yandex.net/api/v2/payments/bankCard
The request payload is the request parameter with some data:
Data
eyJhbGciOiJFUzI1NiIsImlzcyI6Imluc3RhbmNlSWQ6cHJHa28rRnNnUlhvZnZwWVBiUDRSeVp0bWs1TkxPTElKRGp
EY1FmMVlzSkFPVjNLUGtGRkJJY0QwRFRzL0t5WSIsImlhdCI6IjE1MzEzODYxNDcwMDAifQ.eyJvcmRlciI6eyJjbGll
bnRPcmRlcklkIjoiMmE2ZGEwMTQtMjhlMC00NTYwLWEwNTctNzYxNjBjOGNjM2NhIiwiY3VzdG9tZXJJZCI6IiIsInZh
bHVlIjp7ImFtb3VudCI6IjEuMDAiLCJjdXJyZW5jeSI6IlJVQiJ9LCJwYXJhbWV0ZXJzIjp7ImNhcmRVVUlEIjoiN2E5MDR
lMTgtZDk0NS00MTI4LTgyMDctMTg3ZDFhMDgxYjM0IiwidXNlcklkIjoyNTg1MDQsImFkZENhcmQiOnRydWV9fSwiZ
XhwaXJ5WWVhciI6IjIwMjUiLCJleHRBdXRoRmFpbFVyaSI6Imh0dHBzOi8vb3JkZXJhcHAuYnVyZ2Vya2luZy5ydS9h
cGkvdjEvcGF5L2ZhaWxlZCIsInNvdXJjZSI6IkJhbmtDYXJkIiwicmVjaXBpZW50Ijp7InNob3BJZCI6IjE0NTM2MyIsInNo
b3BBcnRpY2xlSWQiOiI0NDk1MzIifSwiY3NjIjoiMjIyIiwicGFuIjoiMjIyNTU1NTI1NTM2NjY2NiIsImNyZWF0ZVJlY3Vyc
mluZyI6dHJ1ZSwiZXh0QXV0aFN1Y2Nlc3NVcmkiOiJodHRwczovL29yZGVyYXBwLmJ1cmdlcmtpbmcucnUvYXBpL
3YxL3BheS9zdWNjZXNzIiwiZXhwaXJ5TW9udGgiOiIxMCJ9.s0H0pnOyCJTm9NJjyj0Ixg15IlRzYbpW7HboSwwAUDi
y4KCkeIQul14lL8P6ocPNTI_Y3acG4x_vSo8C0T1qtQ
EY1FmMVlzSkFPVjNLUGtGRkJJY0QwRFRzL0t5WSIsImlhdCI6IjE1MzEzODYxNDcwMDAifQ.eyJvcmRlciI6eyJjbGll
bnRPcmRlcklkIjoiMmE2ZGEwMTQtMjhlMC00NTYwLWEwNTctNzYxNjBjOGNjM2NhIiwiY3VzdG9tZXJJZCI6IiIsInZh
bHVlIjp7ImFtb3VudCI6IjEuMDAiLCJjdXJyZW5jeSI6IlJVQiJ9LCJwYXJhbWV0ZXJzIjp7ImNhcmRVVUlEIjoiN2E5MDR
lMTgtZDk0NS00MTI4LTgyMDctMTg3ZDFhMDgxYjM0IiwidXNlcklkIjoyNTg1MDQsImFkZENhcmQiOnRydWV9fSwiZ
XhwaXJ5WWVhciI6IjIwMjUiLCJleHRBdXRoRmFpbFVyaSI6Imh0dHBzOi8vb3JkZXJhcHAuYnVyZ2Vya2luZy5ydS9h
cGkvdjEvcGF5L2ZhaWxlZCIsInNvdXJjZSI6IkJhbmtDYXJkIiwicmVjaXBpZW50Ijp7InNob3BJZCI6IjE0NTM2MyIsInNo
b3BBcnRpY2xlSWQiOiI0NDk1MzIifSwiY3NjIjoiMjIyIiwicGFuIjoiMjIyNTU1NTI1NTM2NjY2NiIsImNyZWF0ZVJlY3Vyc
mluZyI6dHJ1ZSwiZXh0QXV0aFN1Y2Nlc3NVcmkiOiJodHRwczovL29yZGVyYXBwLmJ1cmdlcmtpbmcucnUvYXBpL
3YxL3BheS9zdWNjZXNzIiwiZXhwaXJ5TW9udGgiOiIxMCJ9.s0H0pnOyCJTm9NJjyj0Ixg15IlRzYbpW7HboSwwAUDi
y4KCkeIQul14lL8P6ocPNTI_Y3acG4x_vSo8C0T1qtQ
Those who have ever worked with JSON Web Token immediately noticed that this is it. With the help of an online decoder, we obtain the original data. In general, nothing surprising to online processing is transmitted information about the card, which is intended for him
{
"order": {
"clientOrderId": "2a6da014-28e0-4560-a057-76160c8cc3ca",
"customerId": "",
"value": {
"amount": "1.00",
"currency": "RUB"
},
"parameters": {
"cardUUID": "7a904e18-d945-4128-8207-187d1a081b34",
"userId": 258504,
"addCard": true
}
},
"expiryYear": "2025",
"extAuthFailUri": "https://orderapp.burgerking.ru/api/v1/pay/failed",
"source": "BankCard",
"recipient": {
"shopId": "145363",
"shopArticleId": "449532"
},
"csc": "222",
"pan": "2225555255366666",
"createRecurring": true,
"extAuthSuccessUri": "https://orderapp.burgerking.ru/api/v1/pay/success",
"expiryMonth": "10"
}
Initially, the next section contained an incorrect assumption about logging all information about the card, after the staticlab comment in the comments, the pro- logging section was changed. I apologize to readers who I misled.
Logs around the head
It would seem that something could go wrong, the card should be reliably processed on Yandex.Kassa. If the developers of the Burger King application did not decide to add some logging on their part. Thereby, nevertheless, collecting some information about the cards, in particular, the last 4 digits of the card, the month and the year of expiry of the card. The log with the information below is sent to:
https://orderapp.burgerking.ru/api/v1/log/requests
[{"created_at":1531386147,"entity":"yandex","method":"POST","request_data":"request=eyJhbGciOiJFUzI1NiIsImlzcyI6Imluc3RhbmNlSWQ6cHJHa28rRnNnUlhvZnZwWVBiUDRSeVp0bWs1TkxPTElKRGpEY1FmMVlzSkFPVjNLUGtGRkJJY0QwRFRzL0t5WSIsImlhdCI6IjE1MzEzODYxNDcwMDAifQ.eyJvcmRlciI6eyJjbGllbnRPcmRlcklkIjoiMmE2ZGEwMTQtMjhlMC00NTYwLWEwNTctNzYxNjBj\nOGNjM2NhIiwiY3VzdG9tZXJJZCI6IiIsInZhbHVlIjp7ImFtb3VudCI6IjEuMDAiLCJjdXJyZW5j\neSI6IlJVQiJ9LCJwYXJhbWV0ZXJzIjp7ImNhcmRVVUlEIjoiN2E5MDRlMTgtZDk0NS00MTI4LTgy\nMDctMTg3ZDFhMDgxYjM0IiwidXNlcklkIjoyNTg1MDQsImFkZENhcmQiOnRydWV9fSwiZXhwaXJ5\nWWVhciI6IjIwMjUiLCJleHRBdXRoRmFpbFVyaSI6Imh0dHBzOi8vb3JkZXJhcHAuYnVyZ2Vya2lu\nZy5ydS9hcGkvdjEvcGF5L2ZhaWxlZCIsInNvdXJjZSI6IkJhbmtDYXJkIiwicmVjaXBpZW50Ijp7\nInNob3BJZCI6IjE0NTM2MyIsInNob3BBcnRpY2xlSWQiOiI0NDk1MzIifSwiY3JlYXRlUmVjdXJy\naW5nIjp0cnVlLCJleHRBdXRoU3VjY2Vzc1VyaSI6Imh0dHBzOi8vb3JkZXJhcHAuYnVyZ2Vya2lu\nZy5ydS9hcGkvdjEvcGF5L3N1Y2Nlc3MiLCJleHBpcnlNb250aCI6IjEwIiwicGFuIjoiKioqKiAq\nKioqICoqKiogNjY2NiJ9\n.s0H0pnOyCJTm9NJjyj0Ixg15IlRzYbpW7HboSwwAUDiy4KCkeIQul14lL8P6ocPNTI_Y3acG4x_vSo8C0T1qtQ","request_headers":"Content-Type: application/x-www-form-urlencoded\nContent-Length: 974\nHost: payment.yandex.net\nConnection: Keep-Alive\nAccept-Encoding: gzip\nUser-Agent: okhttp/3.10.0\n","response_data":"{\"status\":\"Refused\",\"cardAuthorizeResult\":{\"responseCode\":\"BL07\",\"rrn\":\"\",\"authId\":\"\"},\"error\":\"InstrumentNotAllowed\",\"parameterName\":\"country\",\"errorDescription\":\"Card country is forbidden for this merchant\"}","response_error_num":403,"response_error":"{\"status\":\"Refused\",\"cardAuthorizeResult\":{\"responseCode\":\"BL07\",\"rrn\":\"\",\"authId\":\"\"},\"error\":\"InstrumentNotAllowed\",\"parameterName\":\"country\",\"errorDescription\":\"Card country is forbidden for this merchant\"}","response_headers":"403 Content-Type: application/json;charset=UTF-8\nDate: Thu, 12 Jul 2018 09:02:28 GMT\nConnection: close\nContent-Length: 209\n","url":"https://payment.yandex.net/api/v2/payments/bankCard"}]
Data is sent for both successful and unsuccessful attempts to invoke card processing. Almost sure that the logs are saved, otherwise why send them?
findings
- Analytics is normal, of course, I would like a more “bright” warning. Without analytics, the development of large and complex applications is impossible.
- Some data about the maps is still collected, most likely unintentionally.