Google Play Cross App Scripting Vulnerability: How do I protect calls to evaluateJavascript? - android-security

My app is caught up in Google's Cross App Scripting security warning and I can't seem to get a version of the app that doesn't trigger Google's warning.
The majority of the functionality is a WebView wrapper for a web app. That's where the warning is.
I think I've followed the directions in Google's tutorial for Option 2, which are as follows:
1. Update your targetSdkVersion.
It has to be above 16 and I've done that.
2. Protect calls to evaluateJavascript
The WebView does accept URL's from Intents, but those are checked ahead of time to always be trusted. And all external URLs that might appear inside the app are opened externally, i.e. in Chrome.
3. Prevent unsafe file loads
The WebView never opens file:// URIs.
The code below is the relevant section from the class and method that Google is indicating has a problem. I think I've correctly filtered out all code paths there so that the only URIs that open would be my own domain.
I've already been through two levels of Google support and all they say is to follow the directions in their tutorial. I think I've done that:
https://support.google.com/faqs/answer/9084685
rootUrl = "https://example.com"
Intent intent = getIntent();
if (intent.getStringExtra("action_url") != null) {
if (intent.getStringExtra(NotificationIntentService.NOTIFICATIONS_DESTINATION) != null) {
myWebView.loadUrl(rootUrl + intent.getStringExtra(NotificationIntentService.NOTIFICATIONS_DESTINATION));
} else if (
intent.getStringExtra("action_url").matches("^https://example.com/")) {
myWebView.loadUrl(intent.getStringExtra("action_url"));
}
} else {
if (retrieveHasRegistered(context)) {
myWebView.loadUrl(rootUrl + "/android?registered");
} else {
myWebView.loadUrl(rootUrl + "/android");
}
}
}

Related

Xamarin Forms Maps Geocoder Not Working on UWP Device

My app uses Xamarin.Forms.Maps to display a map and also for geocoding. The map is displayed on a separate page when the user navigates to it from the main page. I use the geocoder to reverse geocode the current location so that I have the address. This is done from various places other than the map page.
When I run the app on a device (even in debug mode) the geocoder works right away in iOS and Android, but does not work in UWP. After I navigate to the map page and display the map, then go back to a different page to use the geocoder it starts working.
I saw a thread about the map not working with release build so I added the following code:
var laRendererAssemblies = new[] { typeof(Xamarin.Forms.Maps.UWP.MapRenderer).GetTypeInfo().Assembly };
Xamarin.Forms.Forms.Init(e, laRendererAssemblies);
//Xamarin.Forms.Forms.Init(e);
Xamarin.FormsMaps.Init("MyBingMapsKey");
This has not helped the issue with the Xamarin.Forms.Maps.Geocoder. I also tried creating an instance of Xamarin.Forms.Maps.Map in my main page, but that did not help either. Is there a way to prime the map component so that the Geocoder will work on a device? (My test device is ARM, but it happens when I run on Local
Machine (Win 10) too)
Following is a snippet of the call to the Geocoder (which works fine once the user has navigated to the Map page and back - and it works fine in iOS and Android - and as such I don't believe it is a problem with the code, but here it is):
public static async Task<Plugin.Geolocator.Abstractions.Position> Geocode(string address)
{
try
{
var loGeocoder = new Xamarin.Forms.Maps.Geocoder();
System.Diagnostics.Debug.WriteLine("Get Lat/Lon");
var lcolPositions = await loGeocoder.GetPositionsForAddressAsync(address);
if (lcolPositions != null)
After doing some research and ensuring that your geodecode class being static wouldn't mess with the async/await pattern in the UWP build. I've come across a few references to this particular problem with the built in Forms.Map geodecoder elsewhere, not just for UWP it has also been noted for android‡.
I took some time to have a look at one of our current cross-platform applications that we have in the app stores, and according to our internal documentation we switched out both the xamarin.forms map, and the geodecoder for custom ones.
The plugin that we use for our cross-platform application is the 'GelocatorPlugin' created by james montemagno, and can be found here.
It can be added to your project as a Nuget package if you prefer, and the implementation of it is very similar to the default one, so there's very little code to change. The primary benefit is that the UWP element of the geodecode plugin has been modified to take into account windows advanced tracking scenarios (details found here).
It should be a lot more stable than the one your using, once installed you simply use it like so:
Reverse Geocoding
Based on a location that is passed in, thi swill grab a list of
addresses.
UWP requires a Bing Map Key, which you can acquire by reading this
piece of documentation.
try
{
var addresses = await locator.GetAddressesForPositionAsync (position, string mapKey = null);
var address = addresses.FirstOrDefault();
if(address == null)
Console.WriteLine ("No address found for position.");
else
Console.WriteLine ("Addresss: {0} {1} {2}", address.Thoroughfare, address.Locality, address.Country);
}
catch(Exception ex)
{
Debug.WriteLine("Unable to get address: " + ex);
}
‡ Links to similar problems - Link 1, Link 2
resolved after added following lines in APP.xaml.cs (UWP project)
Xamarin.FormsMaps.Init("bingmapkey");
Windows.Services.Maps.MapService.ServiceToken = "bingmapkey";

Sometimes Initialization of Google Earth Plugin fails in IE10

This is my code for the initialization of google earth plugin.
Sometimes Initialization of Google Earth Plugin fails in IE10(I have it in compatability mode) IE7 Standards. This error happens only in IE and no other browser.
90% of the time createInstance() method creates the google earth plugin instance and control goes to mygeeEarthPluginInitCb() method but few times mostly after restarting the machine or after few hours of inactivity if I load the page createInstance fails and control goes to geeEarthPluginFailureCb() method.
This is causing an error page, a very intermittent one.
function geeInit() {
alert("google.earth.createInstance : Start");
google.earth.createInstance(geeDivIds.map, mygeeEarthPluginInitCb,
geeEarthPluginFailureCb, earthArgs);
alert("google.earth.createInstance : End");
}
function mygeeEarthPluginInitCb(object) {
alert("Success mygeeEarthPluginInitCb: Inside");
geeEarthPluginInitCb(object);
gex = new GEarthExtensions(ge);
createSearchResultsMarkers(null, 'results');
var lookAt = ge.createLookAt('');
lookAt.setLongitude(Number('-73.784190'));
lookAt.setLatitude(Number('42.643446'));
lookAt.setRange(25000.00);
ge.getView().setAbstractView(lookAt);
initRadSearchValsOnLoad();
}
function geeEarthPluginFailureCb(message) {
alert("Failure geeEarthPluginFailureCb: Inside" + message);
if (google.earth.isInstalled()) {
} else {
var result = confirm('Google Earth Plugin is not'
+ ' installed.Please download and install it.');
if (result == true) {
window.location.href = 'install.html';
}
}
}
Remove all the alert lines, e.g.
alert("google.earth.createInstance : Start");
and
alert("google.earth.createInstance : End");
alert is a special method that blocks execution and user interaction - it could well be that it is blocking the initialisation of the plugin. This is something I have seen before.
Perhaps try using the console, or else outputting data to the document in some way that avoids blocking. e.g.
console && console.log("google.earth.createInstance, "End");
Google acknowledged the issue and mentioned they are working on a fix.
For right now there is a temporary fix below is the shorter version of Google's response.
******** Start Google's Response *************
"We have been able to reproduce this issue, intermittently. It is now pending additional investigation for the Google Earth client team, to find the root cause here. Unfortunately, it is not possible to provide an estimate for a deadline when this will be fixed. This issue definitely has a high priority since it impacts all Google Earth users with custom globes (GEE, and GME), and we have let the team know that this is now critical for your applications.
The only workaround that we can see, right now, is to refresh the page when the plugin fails to load (or you could do that programmatically: implement a timeout, and if after 5 seconds, the Earth API has not yet loaded, reload the plugin, or refresh the page). You could also consider using the Google Earth client, but I'm not sure if this is something that would be applicable to your use case."
**********End Google's Response ***************

How to store translations in a phonegap application and save the user preferences?

I'm developing a Phonegap application using jQuery Mobile. It's a very basic application, its purpose is to show information about a big organization in Spanish and English. On the first page the application shows 2 options, Spanish and English. If the user selects Spanish, the information displayed must be Spanish and vice versa.
Using SQLite DB will probably give some problems on Windows Phones since it is not yet supported (see Phonegap Storage).
There is the File Storage option too. And raw JSON files, as well.
The way I do it is to create a language specific json file to hold all my strings. In this case english.json and spanish.json. Structure the json like:
{
help: "Help",
ok: "Okay"
}
On the first page of your app when the user clicks the Spanish button for instance it should set a value in localStorage.
localStorage.setItem("lang", "spanish");
Then in the second page once you get the "deviceready" event you should load the correct json file using XHR.
var request = new XMLHttpRequest();
request.open("GET", localStorage.getItem("lang") + ".json", true);
request.onreadystatechange = function(){//Call a function when the state changes.
if (request.readyState == 4) {
if (request.status == 200 || request.status == 0) {
langStrings = JSON.parse(request.responseText);
}
}
}
request.send();
Now whenever you want to use a translated string you get it from langStrings.
langStrings.ok;
Make sense?
For persistance I successfully used Html5 Local Storage.
It works on Android, iOS and Windows Phone 7(I tried it on these platforms).
I use it like this.
For i18n you can use any javascript i18n library. I created own simple solution.

presence control in asp.net web applications

I've managed to implement the Name.NameCtrl.1 active x used in sharepoint in my own custom built apps for presence. All is working fine and I'm updating presence status correctly based on a users status on Office Comunication Server. However I'm not getting any other details on the user propulated in the presence control like it does in SharePoint. All I get is the sip address in the email field (rather than the real default email address in AD) and a link to schedule a meeting.
Can anyone tell me how to get the control to populate with details from AD (dept, email, phone etc) like it does in sharepoint?? Also I don't get an organization tab in the control like sharepoint.
Any ideas?
Thanks,
Keeney
NameCtrl gets the majority of its data from the running instance of Communicator (or Lync, if you're using that) on the client machine. No data is directly pulled back from SharePoint. To have NameCtrl work properly on your web pages, you need to make sure that:
Communicator (or Lync) is running on the client, and signed in
The web page you are calling NameCtrl from is in the Intranet or Trusted Sites zone in your browser
The recommended pattern is to call PresenceEnabled on the NameCtrl object before calling any other methods - if this returns false, then one (or both) of the above prereqs is false. The code below generally works for me
<script>
var sipUri = "your.contact#your.domain.com";
var nameCtrl = new ActiveXObject('Name.NameCtrl.1');
if (nameCtrl.PresenceEnabled)
{
nameCtrl.OnStatusChange = onStatusChange;
nameCtrl.GetStatus(sipUri, "1");
}
function onStatusChange(name, status, id)
{
// This function is fired when the contacts presence status changes.
// In a real world solution, you would want to update an image to reflect the users presence
alert(name + ", " + status + ", " + id);
}
function ShowOOUI()
{
nameCtrl.ShowOOUI(sipUri, 0, 15, 15);
}
function HideOOUI()
{
nameCtrl.HideOOUI();
}
</script>
<span onmouseover="ShowOOUI()" onmouseout="HideOOUI()" style="border-style:solid">Your Contact</span>
In case you haven't already seen it, there is a good(ish) NameCtrl reference here
I think in SharePoint, the control is populated with data that exists in the user profile service. If you want this in a non-sharepoint ASP.NET web app, then you'd have to build a repository of user profile details from AD (and cache it!) which your control will look to to display that information.

Silverlight MediaElement refusing to play audio

I am having the hardest time figuring this problem out. I have a Silverlight 4 application that loads audio and video files from URLs. The URLs are the same domain as the application is hosted on and it works great for video.
The URLs are actually asp.net mvc controllers that are responsible for reading the file from a shared location on and the server and serving back a filestream. The URLs look something like this:
http://localhost:31479/CourseMedia?path=\omnisandbox1\ILMSShare2\Demo-Fire+Behavior\media\Disclaim.wma&encrypted=False&id=00000000-0000-0000-0000-000000000000
If I put the URL directly into the browser the file loads and plays in windows media player just fine, and if I use a separate test silverlight project to load the url it also works, but for the life of me I can not get it to work properly in my main project.
This is the routine I use to actually do the source setting:
protected void SetPlayerURL(MediaElement player, string url)
{
if (player != null && url.Length > 0)
{
player.ClearValue(MediaElement.SourceProperty);
player.Source = new Uri(this.Packet.GetMediaUrl(url, false, Guid.Empty));
}
}
and the GetMediaURL function simply builds the URL format seen above:
public string GetMediaUrl(
string path,
bool encrypted,
Guid key)
{
StringBuilder builder = new StringBuilder();
builder.AppendFormat("http://{0}/CourseMedia?path={1}&encrypted={2}&id={3}",
this.Host,
System.Windows.Browser.HttpUtility.UrlEncode(path),
encrypted,
key);
return builder.ToString();
}
The request to the controller is never made for the media when it is audio. Seems odd to me as this exact code works fine for video. The MediaElement state never leaves "Closed" and the CurrentStateChanged,, MediaOpened, and MediaFailed events are never triggered.
I am at a loss!
Try setting ScrubbingEnabled of the MediaElement to false, there were some problems with Framework version 3.5 and audio and the workaround was setting that to false. Might be worth trying.
Also try capturing BufferingStarted, BufferingEnded, MediaEnded along with your MediaFailed and MediaOpened events. I'm curious if it is a buffering issue.

Resources