public
Last active

This is the code Comcast is injecting into its users web traffic.

  • Download Gist
ComcastInject.html
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
<script language="JavaScript" type="text/javascript">
// Comcast Cable Communications, LLC Proprietary. Copyright 2012.
// Intended use is to display browser notifications for critical and time sensitive alerts.
var SYS_URL='/e8f6b078-0f35-11de-85c5-efc5ef23aa1f/aupm/notify.do';
// var image_url='http://servicealerts.comcast.net:8080/images/mt';
var image_url='http://xfinity.comcast.net/constantguard/BotAssistance/notice/images';
var headertext1='<strong>Comcast Courtesy Notice</strong>';
var textline1='You have reached 90% of your <b>monthly data usage allowance</b>.';
var textline2='Please sign in for more information and to remove this alert.';
var acknowledgebutton='<a href=\"#\" onClick="document.location.href=\''+SYS_URL+'?dispatch=redirect&redirectName=login&paramName=bmUid\'" title="Sign in to acknowledge" style="color: #FFFFFF;"><img alt="Sign in to acknowledge" src="'+image_url+'/mt_signin.png"/></a>';
var verifybulletin='<a href="http://customer.comcast.com/help-and-support/internet/data-usage-plans-nash/" target="_new">How do I know this message is from Comcast?</a>';
 
if(self.location==top.location) {
document.write('<style type="text/css">');
document.write('#comcast_content {width: 600px; height:240px; box-shadow: 10px 10px 5px #888; background: #fff; border: 1px solid #454545; position:absolute; top:50px; left:100px; zoom:1; z-index: 9999999; opacity:0.90; filter:alpha(opacity=90);}');
document.write('#comcast_content .header {height: 35px; background:url('+image_url+'/headerbg.gif) repeat-x;}');
document.write('#comcast_content .a {color: #00a3e0;}');
document.write('#comcast_content .logo {float:left;}');
document.write('#comcast_content .content-wrapper {padding-left: 18px; padding-right: 15px; padding-bottom: 12px;}');
document.write('#comcast_content .headerimage { margin-top: 15px;}');
document.write('#comcast_content .header1 {margin: 18px 0 0 0; color: #C00000; padding: 3px; font: 23px/24px bold Arial, Helvetica, sans-serif;}');
document.write('#comcast_content .textcontent {margin: 12px 0 0 0; text-align: center; color: #303030; word-spacing: 0px; font: 14px/15px Arial, Helvetica, sans-serif; line-height: 1.20;}');
document.write('#comcast_content .acknowledge {padding-top:6px; text-align: center;}');
document.write('#comcast_content .how-do-i {float:left; position:absolute; bottom:20px; left:18px; margin: 12px 0 0 0; font: 13px/14px bold Arial, Helvetica, sans-serif; text-align: bottom;}');
document.write('#comcast_content .comcast-wrapper {float:right; position:absolute; bottom:15px; right:18px; padding-top:0px; text-align: right;}');
document.write('</style>');
document.write('<div class="main-wrapper" id="comcast_content">');
document.write('<div class="header" onmousedown="javascript:dragStart(event,\'comcast_content\')">');
document.write('<img src="'+image_url+'/xfinity-logo.gif" alt="Xfinity" class="logo"/>');
document.write('</div>');
document.write('<div class="content-wrapper">');
document.write('<p class="header1">');
document.write(headertext1);
document.write('</p>');
document.write('<p class="textcontent">');
document.write(textline1);
document.write('</p>');
document.write('<p class="textcontent">');
document.write(textline2);
document.write('</p>');
document.write('<p class="how-do-i">');
document.write(verifybulletin);
document.write('</p>');
document.write('<div class="acknowledge">');
document.write(acknowledgebutton);
document.write('</div>');
document.write('<div class="comcast-wrapper">');
document.write('<img src="'+image_url+'/message-by-comcast.gif" alt="Message by Comcast"/>');
document.write('</div>');
document.write('</div>');
document.write('</div>');
}
 
// Function to Determine browser and version. Copyright 2001 by Mike Hall.
// See http://www.brainjar.com for terms of use.
 
function Browser() {
var ua, s, i;
this.isIE = false;
this.isNS = false;
this.version = null;
ua = navigator.userAgent;
s = "MSIE";
if ((i = ua.indexOf(s)) >= 1) {
this.isIE = true; this.version = parseFloat(ua.substr(i + s.length)); return;
}
s = "Netscape6/";
if ((i = ua.indexOf(s)) >= 0) {
this.isNS = true; this.version = parseFloat(ua.substr(i + s.length)); return;
}
s = "Gecko";
if ((i = ua.indexOf(s)) >= 0) {
this.isNS = true; this.version = 6.1; return;
}
}
var browser1 = new Browser();
var dragObj = new Object();
dragObj.zIndex = 99999;
function dragStart(event, id) {
var el;
var x, y;
if (id) dragObj.elNode = document.getElementById(id);
else {
if (browser1.isIE) dragObj.elNode = window.event.srcElement;
if (browser1.isNS) dragObj.elNode = event.target;
if (dragObj.elNode.nodeType == 3) dragObj.elNode = dragObj.elNode.parentNode;
}
if (browser1.isIE) {
x = window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
y = window.event.clientY + document.documentElement.scrollTop + document.body.scrollTop;
}
if (browser1.isNS) {
x = event.clientX + window.scrollX;
y = event.clientY + window.scrollY;
}
dragObj.cursorStartX = x;
dragObj.cursorStartY = y;
dragObj.elStartLeft = parseInt(dragObj.elNode.style.left, 10);
dragObj.elStartTop = parseInt(dragObj.elNode.style.top, 10);
if (isNaN(dragObj.elStartLeft)) dragObj.elStartLeft = 100;
if (isNaN(dragObj.elStartTop)) dragObj.elStartTop = 50;
if (browser1.isIE) {
document.attachEvent("onmousemove", dragGo);
document.attachEvent("onmouseup", dragStop);
window.event.cancelBubble = true;
window.event.returnValue = false; }
if (browser1.isNS) {
document.addEventListener("mousemove", dragGo, true);
document.addEventListener("mouseup", dragStop, true);
event.preventDefault();
}
}
 
// End Function
 
function dragGo(event) {
var x, y;
if (browser1.isIE) {
x = window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
y = window.event.clientY + document.documentElement.scrollTop + document.body.scrollTop;
}
if (browser1.isNS) {
x = event.clientX + window.scrollX; y = event.clientY + window.scrollY;
}
dragObj.elNode.style.left = (dragObj.elStartLeft + x - dragObj.cursorStartX) + "px";
dragObj.elNode.style.top = (dragObj.elStartTop + y - dragObj.cursorStartY) + "px";
if (browser1.isIE) { window.event.cancelBubble = true; window.event.returnValue = false; }
if (browser1.isNS) event.preventDefault(); }
 
function dragStop(event) {
if (browser1.isIE) {
document.detachEvent("onmousemove", dragGo);
document.detachEvent("onmouseup", dragStop);
}
if (browser1.isNS) {
document.removeEventListener("mousemove", dragGo, true);
document.removeEventListener("mouseup", dragStop, true);
}
}
 
var xmlhttp=false; /*@cc_on @*/ /*@if (@_jscript_version >= 5) try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { xmlhttp = false; } } @end @*/ if (!xmlhttp && typeof XMLHttpRequest!='undefined') { try { xmlhttp = new XMLHttpRequest(); } catch (e) { xmlhttp=false; } } if (!xmlhttp && window.createRequest) { try { xmlhttp = window.createRequest(); } catch (e) { xmlhttp=false; } }
 
function acknowledge() { sendAck(); document.getElementById('comcast_content').style.display="none"; }
function sendAck(){ xmlhttp.open("GET", SYS_URL+'?dispatch=ackBulletin',true); xmlhttp.send(null) }
 
var comcastCheck=1;
var comcastTimer;
function checkBulletin(){
if(comcastCheck==0) { return; }
xmlhttp.open("GET", SYS_URL+'?dispatch=checkBulletin',true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if(xmlhttp.responseText.indexOf('43a1028c-7d11-11de-b687-1f15c5ad6a13')==-1){
document.getElementById('comcast_content').style.display="none";
comcastCheck=1;
}
comcastTimer=setTimeout("checkBulletin()",5000);
};
};
xmlhttp.send(null);
}
checkBulletin();
</script>
README.md
Markdown

Above is the code Comcast is injecting into their customers web traffic when they need to display an "important message".

Feel free to read the blog post that goes along with this code.

Wow. Comcast really sucks at JS.

Browser detection from the days of IE and Netscape battles, 2001 browser detect script. Surprised there isn't a check for document.layer or document.all.

and a domain-relative link that will request a file from the domain you're currently on instead of one controlled by comcast... good job.

JSHint Report

/*jshint forin:true, noarg:true, eqeqeq:true, evil:true, bitwise:true, browser:true, devel:true, jquery:true, indent:4, maxerr:50 */
Errors:

Line 12: if(self.location==top.location) {

Expected '===' and instead saw '=='.

Line 76: var dragObj = new Object();

The object literal notation {} is preferrable.

Line 85: if (dragObj.elNode.nodeType == 3) dragObj.elNode = dragObj.elNode.parentNode;

Expected '===' and instead saw '=='.

Line 140: var xmlhttp=false; /@cc_on @/ /@if (@_jscript_version >= 5) try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { xmlhttp = false; } } @end @/ if (!xmlhttp && typeof XMLHttpRequest!='undefined') { try { xmlhttp = new XMLHttpRequest(); } catch (e) { xmlhttp=false; } } if (!xmlhttp && window.createRequest) { try { xmlhttp = window.createRequest(); } catch (e) { xmlhttp=false; } }

Expected '!==' and instead saw '!='.

Line 143: function sendAck(){ xmlhttp.open("GET", SYS_URL+'?dispatch=ackBulletin',true); xmlhttp.send(null) }

Missing semicolon.

Line 148: if(comcastCheck==0) { return; }

Expected '===' and instead saw '=='.

Line 151: if (xmlhttp.readyState == 4) {

Expected '===' and instead saw '=='.

Line 152: if(xmlhttp.responseText.indexOf('43a1028c-7d11-11de-b687-1f15c5ad6a13')==-1){

Expected '===' and instead saw '=='.

Line 157: };

Unnecessary semicolon.

what does this do guys?noob here hehe...thnks!:)

@VirtualApe

// Comcast Cable Communications, LLC Proprietary. Copyright 2012.
// Intended use is to display browser notifications for critical and time sensitive alerts.

I wonder if Mike Hall. See http://www.brainjar.com for terms of use.

Works for them and this is his code or if they just copy pasta'd.

brainjar has been around for forever, I doubt he works for them. Likely a copy/paste job

http://www.brainjar.com/terms.asp

Apparently, the code they copied is under GPL2. So, they are in violation unless they have permission from the author.

See more on why this is awful - including how it causes every page served on your system to pop an AJAX request to the wrong URL every 5 seconds, forever.

https://news.ycombinator.com/item?id=5482512

Is there a way to "Like" or up-vote @drawcode's comment?

@drawcode :+1: is the best ur gonna do @iknowkungfoo

Never thought anyone would stumble across this!

Here's my brief writeup for those interested

http://blog.ryankearney.com/2013/01/comcast-caught-intercepting-and-altering-your-web-traffic/

@iknowkungfoo @kulte there's always gittip.

Good thing my neighbor doesn't have comcast.............YEAH, I steal his WiFi :)

Obviously I'm kidding, I don't want the christian mingle freaks to attack me! HAHAHHAA

The idea that my ISP is injecting JS into my traffic is very unsettling.

I'm adding the URL /e8f6b078-0f35-11de-85c5-efc5ef23aa1f/aupm/notify.do to my site right now!

Do they inject a script-tag that points to this file? i.e. do they point to JS that is hosted on an external domain, like xfinity.comcast.net?

@michiel3 No. They hijack your HTTP connection, intercept the GET request, and inject this code into the web page before delivering it to your browser.

Would using Comcast's DNS play any part in this?

@nicinabox It doesn't matter which DNS you use since they're hijacking your entire connection, not just the DNS response. You could enter in the IP address directly and completely bypass DNS all together and Comcast would still end up hijacking your traffic.

@nicinabox I doubt it. They are the MITM as your ISP, which makes it easy to sniff your traffic.

@ryankearney @dansimpson As I suspected :/

How does an average joe with a modicum of linux skills stop this? Do VPN connections help?

That's it, VPN'ing everywhere.

A case for end to end encryption.
This is what metered payment models lead to. The stunning part is that they are so disconnected from their customers that they might think this is just being helpful.

Yet another reason to move everything to SSL. If it doesn't start with https:// then don't trust it.

Although "I second this!" Isn't really github-style, is there anyone who can confirm they're seeing injected js?

LOL.
document.write causes the page to re-render. This code re-renders the page like 50 times.

Do they also intercept requests to the SYS_URL and inject the appropriate response from their own system or does it actually cause a 404 on the remote server (when you run this on comcasts network) ?

Has anybody else on Comcast confirmed this? I'm on Comcast Xfinity in Conyers, GA... Just SSH'ed home and wget'ed a few URLs of mine, no such injection. Maybe they're smart enough to limit it to certain User-Agent strings, or certain major dmains... or this isn't implemented everywhere yet? Or just a hoax...?

@jantman based upon the content of the notice, it isnt doing this for all requests it runs across it's wires - it looks like this is only injected upon 'reaching 90% of your monthly data usage allowance'.

Rogers Cable here in Canada has been doing the same thing for a while, as while has inserting their own ad filled 'search' pages for DNS and 404 errors.

@vfulco Yes, a VPN, tunnel or similar connection would bypass this. You could also get around it with either layer7 filtering or a browser script/extension. Or if you're really paranoid, disable javascript or use a text browser.

Even for someone that doesn't do any web coding for a living this looks like utter crap.
Is the hmm... coding style original, or was identation messed up when copypasting?

@bparker06 any ideas what Chrome extensions might address this?

Another point in favor of https

Dat // End Function

$('#comcast_content').remove();

Simply inspirational

@nitelite Nope, it actually causes a 404 on your server.

@nekromant This is exactly how it appears when injected into the page. Nothing has been changed.

I'm releasing a Chrome extension to block this injection. You can expect it to be released by 2pm PST today. You can follow me on Twitter for updates: @ChristianBundy

Done!

How can a chrome extension stop a MITM without using some 3rd party service? Sure, you can remove it after it's already there, but that isn't really the issue here.

Everyone here is bitching about how bad this is (I agree) but no one's actually checked.

I'm on comcast, just fired up firebug and took a look at a few pages - they aren't injecting anything. I think this only happens if you absolutely DESTROY your bandwidth allotment. I go around 500gb+ a month and haven't had any warnings. So as much as I hate comcast I have to give them the benefit of the doubt here.

@Sushisource When you say that everyone is bitching about it and you agree, this implies you're bitching too. That and people don't need to check because the injected code obviously only appears when you're out of bandwidth.

As a point of interest, Cox did something very similar to this when their email servers blew up not too long ago.

Here's a Google Chrome extension to block this injection!

The document.write method is just too easy to block.

if (div = document.getElementById('comcast_content')) {
  div.parentNode.removeChild(div);
}

Tweet at me for love/hate/boredom.

@Sushisource Incorrect. I was around 280GB when this message started appearing. I live in the Nashville area where they actually enforce a hard cap, not a soft cap.

You can read more about it here: http://customer.comcast.com/help-and-support/internet/data-usage-what-are-the-different-plans-launching

Charter injects a frame into the top of your pages when your bill is past due.

:beer: reminds me 90s primary school coding challenge.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.