4

We are all familiar with the problem of mixed scheme (http / https) content on a page.

enter image description here

I'm working on a site on which this is unavoidable. I do not want to prevent this. I know there are a ton of questions / answers on that.

What I need is simply to detect this (via JavaScript?) so I can tweak the page behavior (show a notice of degraded behavior or something). Any help?

Michael Kennedy
  • 3,202
  • 2
  • 25
  • 34
  • 1
    I don't think I understand? You are serving up a page with mixed content but don't know it? How would you not know if the page contains unsecure content? Are you not the site serving the page up? – Brad Cunningham Aug 30 '12 at 19:28
  • 1
    Hey Brad! I'm serving up a page which has an iframe with variable content in it. So ``. I don't control the value of `SOME_RANDOM_WEBSITE` which can be http. That's fine, but I want to make sure the user knows they are missing what's in the iframe until the press 'show all content'. Make sense? – Michael Kennedy Aug 30 '12 at 19:35
  • So you are saying you want to append some information to the native security alert saying, "This is what you are missing" ? not append literally but someway through js alert etc. – Prasanth Aug 30 '12 at 19:45
  • Hi goldenparrot. No, not exactly. Just another element in the page saying "please allow unsecured content to fully use this page". – Michael Kennedy Aug 30 '12 at 19:48
  • Keep in mind that the "show all content" option may not exist in some current or future browsers. For instance, some mobile browsers may not have such an option, and Chrome is moving in the direction of removing it. –  Aug 30 '12 at 20:24
  • +duskwuff Thanks. Good point. In Chrome & FF there is no problem. It loads fine. It's just IE I have to deal with (hmm, where have I heard that before?) – Michael Kennedy Aug 30 '12 at 21:22
  • Thanks guys. See my proposed answer below. – Michael Kennedy Aug 30 '12 at 23:18

2 Answers2

5

Using jQuery you can find out if any insecure items are present on a page using the following piece of code:

var flag = false;
if($("script[src^='http:']").length > 0
    || $("link[type='text/css'][href^='http:']").length > 0
    || $("img[src^='http:']").length > 0
    || $("iframe[src^=http:]").length > 0)
    flag = true; // insecure content :(
else
    // yay!

Images, JS, CSS are all the insecure content that I could think of. Perhaps there are more, but you could easily add'em up as you find.

Prasanth
  • 5,230
  • 2
  • 29
  • 61
  • Cool, thank you. I definitely can KNOW the content is insecure. What I want to know is two things. 1. Is the browser one which shows this prompt (only IE in my case) 2. Has the user clicked it or is it still displaying. So then I can show an alert, add a bit of a note to the screen near the IFRAME etc. – Michael Kennedy Aug 30 '12 at 21:09
  • 1
    That's not a bad approach, but it can be tricky to catch dynamic content: XHR requests or content loaded later asynchronously. – Bruno Aug 30 '12 at 21:26
3

It's hacky, but I managed to fix this in all browsers with just JavaScript. Let me see if I can sketch it out.

We have this basic encrypted page:

<html> 
   <body>
        <div> stuff </div>
        <iframe src="URL_WHICH_IS_MAYBE_INSECURE"></iframe>
   </body>
</html>

When URL_WHICH_IS_MAYBE_INSECURE is https, all is good. But when URL_WHICH_IS_MAYBE_INSECURE is http, IE will not load the content unless the user OK's insecure/mixed content. I want to tell the user the page is kinda busted until they click allow. For reasons I can't go into, I know all the sites are trustworthy. Just some of them do not support SSL and the parent site needs to.

AFAIK, I cannot detect this dialog / semi-loaded state with JS. But what I can do is run JS over an insecure connection IF they allow it (which also makes the iframe go). So only when URL_WHICH_IS_MAYBE_INSECURE is http & the site is https (mixed) I add two bits of code + HTML.

<html> 
   <body>
        <div> stuff </div>
        @if(needSpecialHandlingForMixedMode) {
            <div id="secureWarn">
                 WARNING: This page has limited functionality, allow mixed content
             </div>
        }
        <iframe src="URL_WHICH_IS_MAYBE_INSECURE"></iframe>
   </body>

   @if (needSpecialHandlingForMixedMode)
   {
      string baseUrl = Request.Url.SchemeAndHostAndPort().Replace("https", "http");
      <script src="@baseUrl/scripts/security-warning.js"></script>
   }
</html>

and the script is

$(document).ready(function(e) {
    $("#secureWarn").remove();
});

So it works like this.

  1. If mixed-mode both the iframe and script will only load if the user allows it. This is not allowed by default in IE and is allowed by default in Chrome & FireFox.
  2. If they do nothing (don't allow in IE, for example), it will keep the warning div visible.
  3. If they do click it, the iframe loads, and now the script also runs (because it was insecure back to my server), this removes the warning from the page.
  4. Happiness commences...

Hope this helps someone.

Cheers, Michael

Michael Kennedy
  • 3,202
  • 2
  • 25
  • 34
  • The problem with this is that it will try to load some potentially insecure content anyway: this should trigger a browser warning in all cases (unless the user has disabled them). This is generally a bad idea. "*I want to tell the user the page is kinda busted until they click allow. For reasons I can't go into, I know all the sites are trustworthy.*": your reasoning is flawed here unfortunately: you can't know whether there's a MITM between your users and that other content provider. Encouraging users to click on allow is never a good idea, since you're not in control of their network. – Bruno Aug 31 '12 at 09:40
  • Hi Bruno. I do hear what you are saying about encouraging users to skip security prompts. But you're missing the point about "this should trigger a browser warning in all cases" which is simply not true. It only adds the HTTP script over HTTPS when the underlying content is also HTTP over HTTPS. When the content is HTTPS, then nothing is added and all is well. Cheers, Michael. – Michael Kennedy Aug 31 '12 at 15:27