MAC Address - Privacy - network-programming

I wrote a program which checks for updates on my server, but I want every request to be logged on the server.
Therefore I want to see which request belongs to which computer, I want to use the MAC address for this task.
Now my question, if my program sends its MAC address to the server and it's logged there, would this be a violation of privacy? I mean is it allowed that my application reads out the MAC address (from an external computer which is not mine) and sends it to my server?

With a MAC address you can uniquely identify a device as, from factory, every network interface has a unique MAC address. Of course, there are especial cases where you can modify the MAC address in a device but this is not for the normal user.
Said this, it is your call if you want to send and keep this data or not. I'd recommend not doing it unless you have explicit opt-in from the user.

Related

Apple's advertisingIdentifier vs mac address?

What are the differences between Apple's advertisingIdentifier and the mac address? Can it replace the mac address? Can Routers read it? e.g. advertisingIdentifier is in the application layer of the stack.
From the Apple documentation on this topic:
Unlike the identifierForVendor property of the UIDevice, the same value is returned to all vendors. This identifier may change—for example, if the user erases the device—so you should not cache it.
If the identifier can change, then there are little chances to be equivalent of the mac address of your device.
If the value is nil, wait and get the value again later. This happens, for example, after the device has been restarted but before the user has unlocked the device.
So Apple computes this value when iOS starts, it might use the mac address when computing the identifier (among other info), however this doesn't guarantee the two are the same.
Routers might see it as part of the network traffic (if you're not using SSL) but they can't know that thats an advertisingIdentifier.

How to identify users in IOS

We are developing an app for IOS.
Is there anyway I can check that the "identifierForVendor" that the device sends me in it's first connection to my server is actually valid?
If there isn't a way, how can I make sure someone is not just sending POSTS to my server and so making me create Device DB Objects that don't really exist?
The only secure way I have found is:
1- Make the App ask for a Device Token to APNs
2- Send it on it's first connection to my server.
3- Check with APNs Feedback Service
4- If token is ok, create the Device DB Object and continue from there.
Apple should let you know some Device-Vendor Id in a communication between Apple and your server every time someone downloads an app.
Thank you.
The simplest solution would be to append the "identifierForVendor" with something you can identify from your app. For example, if you append an alphanumeric string that looks like this: "A1B2C3D4E5F6G7" to be "A1B2C3D4E5F6G7-fromMyApp", then there is no way for someone to know what the custom appended string is, unless they have access to your code.
Of course there are more complex solutions, if you are genuinely concerned of people going so far as to monitor traffic from your app just to find the string.
Are you aware that registering for remote notifications prompts the user if they want to allow remote notifications for the app. If they choose no, there is no token generated.
Besides, they can sniff the token off the wire. Do you plan on tracking abuse and blocking users based on their token? Do you know that some actions cause a new token to be generated, such as resetting the device?
You can generate a unique ID (UUID) or use identifierForVendor, and store it in the user's key store and use that to track by device. It's still anonymous, and resetting the device resets this, but if you're tracking abusers, you can block them and they have to reset their device to try it again. This isn't much different from an APN token. It can still be sniffed, and they can still reset it. But at least the user doesn't have to say yes to allowing remote notifications.
If you're sending any kind of token, you should use HTTPS (SSL/TLS), not to protect the user from themselves (they can still sniff the token by doing their own man in the middle attack unless you are verifying the identify of the server), but this is to protect people from malicious users on the same network. You don't want to block some innocent user because they happened to use your app on a public network and inadvertently shared their token.
Of course, if we're talking a jail-broken device, all bets are off.

Push Notifications through BES/BIS , BlackBerry

I am trying to use push notifications for OS < 7.X .
I downloaded the sample server / client code. I deployed the client code on my device and the low-level-sample code on the tomcat provided.
For the record , when i registered for push notifications here i registered using the BIS option. Now that i was actually given a blackberry i was informed it is using BES ( i dont think though this is the root of the problem that i am going to describe..).
On the device , in the sample application i put all the correct settings given from the email i received.
Both my pc which is running the tomcat server and my phone are connected to the same wifi.
I am trying from the device browser to connect to the server , eg https://196.84.32.112:8443/low-level-sample
and the browser opens the page normally , meaning that i am able to connect to my server from the mobile.
Now when i hit register from the device sample app ( i have tried both BIS/BES options on the settings ) , i always get the following error :
Request to register failed. Cause by java.io.IOException: Network operation[Subscribe] failed. Make sure that Content Provider URL is accessible.
In the log i get :
Opening URL: my server url appended with info like username/password/model/connection type etc
Content Provider network command [ Subscribe] failed , caused by could not connect to 196.84.32.112:8443
Command "register" failed with error: java.io.IOException: Network operation[Subscribe] failed. Make sure that Content Provider URL is accessible.
A thought is that i should register again for new push keys and use the BIS/BES option instead of only BIS , but here the problem seems to be no connectivity with the local server , not the RIM server. I already tried to register though and i am waiting for the mail with the new settings.
Also i am a bit confused with the BIS / BES option. I have no idea if my users will have BIS or BES enabled so what do i put in my code ?! In the sample application it asks me to select between BIS or BES but when the app is going to production and i need to programmatically make that choice what will i choose?! Or this choice is made only for the evaluation/development of the app and on production there is another server ?
I think all the right things have been said here, but I'm hoping we can consolidate some of the answers, and wrap this question up.
You haven't shared your code, which makes things more difficult, but many people use the RIM/BlackBerry provided PushDemo source, where a connection suffix is hardcoded in /pushdemo/com/rim/samples/device/push/PushUtils.java:
private static String getConnectionSuffix() {
return ";deviceside=false;ConnectionType=mds-public";
}
I'm also guessing this from having read your other question.
By doing this, you've hardcoded the BlackBerry transport type of BIBS. BlackBerry supports many different transports, like BES, BIS, BIBS, or WAP. The BIBS transport will send the request from your device, out to BlackBerry's servers, which are on the internet. (Note: this part is probably confusing to an iOS/Android developer, since those platforms don't provide Apple/Google network intermediaries to relay normal HTTP/S traffic)
Then, the request is relayed to your server, which is at:
196.84.32.112:8443
I'm pretty sure that TCP/IP endpoint is not available from the Internet (I can't reach it). So, that's why it fails for you.
You can take this URL
https://196.84.32.112:8443/low-level-sample
and paste it into your BlackBerry device's browser, and it will work. Your device is configured for BES, which uses your company's internal servers. Those internal servers can reach the 196.84.32.112:8443 endpoint, so it seems to work for you. But, that's because you haven't hardcoded the transport, as you have in the push code that uses getConnectionSuffix(). The device browser is smart enough to figure out a transport that works, and BES works to reach that intranet server.
Hopefully, that explains the confusing part.
Solutions
As others have said, a solution is to get your company's IT people to make IP address 196.84.32.112 and port 8443 accessible through their firewall. That would allow the BlackBerry servers to reach it successfully.
Another solution would be to change the PushUtils.java code to avoid the BIBS transport:
private static String getConnectionSuffix() {
return ";deviceside=false";
}
If you want really flexible code, then I'd suggest rewriting that PushUtils.java code, because it appears to use the pre-5.0 HTTP connection logic. ConnectionFactory in OS 5.0+ makes this easier, and more robust, when supporting multiple transports ...
To answer your question about supporting users with multiple transports, take a look at this blackberry.com example, specifically the MyConnectionFactory class. It allows you to select which transports your app allows, and which it tries first.
Ultimately, the decision to make your server public or not depends on how it's going to be used, and whether you'll have non-corporate internet clients trying to register with your corporate server.
Let me first explain the registration flow for BB Push Demo:
When you click on Register the device will
Inform your web application that the device wants to register. For this it will send the information about the device to your Web Application (the so called ContentProvider). You are expected to store that information in your database. This step happens in the ContentProviderProtocol.performCommand() method of the push demo.
Inform the BB Push Server that the device wants to register for receiving push notifications from your application. This happens in the BpasProtocol.register() method of the push sdk.
Step 1 is only necessary if you want to know who all are registered for push notifications (maybe if you want to send individual push notifications to each device and not broadcast the message to all registered users). In that case, you will probably need other information like that user's preferences etc for customizing the push anyway.
Now the error you are getting is from the step 1. For step 1 to succeed, your device should be able to connect to your web app which it is not able to.
To solve this problem, either you have to make your web app publicly accessible (and be ready to handle the load) or comment out the step 1 from the app by making ContentProviderProtocol.performCommand() return without doing anything.
PS: The webapp used in step 1 need not be same as your push initiator. The webapp is simply being used for tracking who all is registered for receiving the push and should ideally be located in the cloud on a distributed architecture if you expect a lot of users.

How to create an unique identifier for an IOS device from a HTML aplication

We are building a web based system where there are money involved and we want to avoid fraud implementing a system that is able to identify the IOS device from where the requests are sent.
The reason of this security is because we offer money for execute actions from a mobile and we only want the user to obtain the money once, if we are not able to identify the device the user can execute the action several times.
This unique identifier can use any HTML, JS, server side technique, but not any native IOS call due the application is web based and it runs in a normal Safari instance.
The unique identifier is not needed to be the official UUID.
The system doesn't need to be bullet-proof just a few more difficult to cheat than a normal cookie.
The system should works in separate sessions, like if the user comes back after one week.
Heuristic based systems are welcome, also any combination of LocalStorage with Cookies, ...
The only ways you can identify a unique user/device in a web application is to use cookies and or track the user's IP address.
Of course, the IP address of a device will change as the owner moves around and cookies can be cleared/disabled or will expire after a set time.
Letting web sites access a device unique identifier such as the UDID would be a huge security risk / privacy invasion. If you were to find such a way, I would say that you found a severe security hole in iOS.
If you are only interested in triggering i.e. an email alert when an account is suspected of being stolen, you could use a heuristic based on device type (user agent string) and geo-ip-lookup to detect if the user has suddenly changed device type and continent and ask the user to confirm that this is really the case. I believe this is what e.g. Google and Facebook does.

CFUUIDCreate, iOS version usage statistics and User Permission

I'm considering using the CFUUIDCreate API to build a database in my server to measure what percentage of users of each of my apps are running which version of iOS (to help me make a decision on iOS minimum supported version for future development).
My question is: Should I ask the user for permission to send the (anonymous) UUID / iOS version data pair to my server, or is it OK to do it automatically?
I ask because I could bet on the safe side and ask anyway, but most users would feel intimidated by the technical details and most likely decline. Also, the longer the text in an UIAlertView, the more likely the user won't read it.
Will Apple reject my app if I don't ask? Even if they don't, do you think I should always ask the user for permission to send this anonymous data?
What's everyone's experience implementing this kind of functionality?
OK, this is what I'm going to do, based on Nikolai Ruhe's answer but improving on a pitfall I just discovered.
Suppose user John Doe installed my app on his iPhone running iOS 5.0.
On the first launch, the app sends an anonymous request to my server that effectively increases by one the counter for 'Devices running iOS 5.0'. The app records this event and the iOS version (in User Defaults or Keychain) and does not send any further requests as long as the locally stored OS version string and the current one (returned by the system) are equal.
The next week, John upgrades to iOS 5.1 and launches my app. The app detects the OS version discrepancy and sends a new request to my server.
But if this only adds one device to the 'iOS 5.1' population, John's iPhone is now being counted twice: once as "Devices running 5.0" and once as "Devices running 5.1".
So to fix this, my HTTP request should look like this:
http://myserver.com/my_stats_scripts/index.php?app_id=com.myCompany.myApp&new_os_ver=5.1&old_os_ver=5.0
So my database can increase the number of 5.1 devices and decrease the number of 5.0 devices by one.
Of course, on the first request, the HTTP parameter old_os_ver is set to empty, and the server treats it like a new device.
If I pull this right, I no longer need UUIDs. But I am still sending system info covertly to my server. I think I'll also disclose this on the Terms of Use.
You should definitely ask for permission. The crucial bit here is that your data collecting might be anonymous, yet it can be used it to track individual users.
Web browsers send a user-agent string with every request. The difference is that they do not send a universally trackable id that would never change.
So the problematic piece in your proposal is the UUID. Why not just leaving it out? Your app would send an anonymous request once and locally store the transmitted iOS version. When the user upgrades the OS, you send another request with the new iOS version and an update count.
Using this scheme you would not transmit trackable data and still get a proper usage-by-os statistic.

Resources