/* Client-side web tripwire script to detect page modifications.
 * Charles Reis, University of Washington, 2007.
 */

WebTripwire = new Object();

// URL of the page to test:
WebTripwire.targetPageURL = "web-tripwire.html";

// HTML of the page to test, as an encodedURI:
WebTripwire.encodedTargetPageHTML = "%3C!DOCTYPE%20HTML%20PUBLIC%20%22-//W3C//DTD%20HTML%204.0%20Transitional//EN%22%0A%20%22http://www.w3.org/TR/REC-html40/loose.dtd%22%3E%0A%3Chtml%3E%0A%3Chead%3E%0A%3C!--%20THIS%20IS%20A%20MACHINE-GENERATED/MAINTAINED%20FILE.%20YOU%20CAN%20MANUALLY%20EDIT%20CONTENT%0A%20%20%20-%20ONLY%20BETWEEN%20HTML%20COMMENTS%20%22begin%20HTML%20content%22%20AND%20%22end%20HTML%20content%22%0A%20%20%20-%20OTHER%20CHANGES%20WILL%20BE%20LOST!%20TO%20MAINTAIN,%20%0A%20%20%20-%20USE%20http://www.cs.washington.edu/htbin-post/content-tool.cgi.%20--%3E%0A%20%3Ctitle%3EDetecting%20In-Flight%20Page%20Changes%20with%20Web%20Tripwires%3C/title%3E%0A%20%3Clink%20rel=%22stylesheet%22%20href=%22/home/cse.css%22%20type=%22text/css%22%3E%0A%20%3Cscript%20src=%22/home/cse2.js%22%20type=%22text/javascript%22%3E%3C/script%3E%0A%3C/head%3E%0A%0A%3Cbody%20bgcolor=%22#ffffff%22%3E%0A%3Ctable%20border=%220%22%20cellpadding=%220%22%20cellspacing=%220%22%20width=%22100%25%22%3E%0A%20%3Ctr%3E%0A%20%20%3Ctd%3E%0A%20%20%20%3Ctable%20width=%22100%25%22%20cellpadding=%2210%22%3E%0A%20%20%20%20%3Ctr%3E%0A%20%20%20%20%20%3Ctd%3E%3Cimg%20src=%22/images/cse_logo_133.gif%22%20width=%22133%22%20height=%22100%22%20border=%220%22%20alt=%22CSE%20logo%22%20/%3E%0A%3C/td%3E%0A%20%20%20%20%20%3Ctd%20width=%22100%25%22%3E%3Cimg%20src=%22/images/csehead3.png%22%20width=%22440%22%20height=%2270%22%20alt=%22University%20of%20Washington%20Computer%20Science%20&amp;%20Engineering%22%20/%3E%0A%20%20%20%20%20%20%3Chr%20noshade=%22noshade%22%20/%3E%0A%20%20%20%20%20%20%3Cspan%20class=%22myH2%22%20size=%225%22%3E&nbsp;Detecting%20In-Flight%20Page%20Changes%20with%20Web%20Tripwires%3C/span%3E%0A%20%20%20%20%20%3C/td%3E%0A%20%20%20%20%3C/tr%3E%0A%20%20%20%3C/table%3E%0A%20%20%3C/td%3E%0A%20%3C/tr%3E%0A%3C/table%3E%0A%0A%3Ctable%20cellspacing=%220%22%20cellpadding=%220%22%20border=%220%22%20bgcolor=%22#666600%22%20width=%22100%25%22%3E%0A%3Ctr%20valign=%22middle%22%3E%0A%20%3Ctd%20align=%22left%22%3E%3Ca%20onmouseover=%22m('cse',1)%22%20onmouseout=%22m('cse',0)%22%20href=%22http://www.cs.washington.edu/%22%20class=%22barlink%22%3E&nbsp;%3Cimg%20src=%22/images/wharrow.gif%22%20name=%22cse%22%20border=%220%22%20alt=%22%22%20/%3E&nbsp;CSE&nbsp;Home&nbsp;%3C/a%3E%3C/td%3E%0A%20%3Ctd%20width=%22100%25%22%3E%3Ca%20onmouseover=%22m('x0',1)%22%20onmouseout=%22m('x0',0)%22%20href=%22http://www.cs.washington.edu/research/security.intro.html%22%20class=%22barlink%22%3E&nbsp;&nbsp;%3Cimg%20src=%22/images/wharrow.gif%22%20name=%22x0%22%20border=%220%22%20alt=%22%22%20/%3E&nbsp;Security&nbsp;and&nbsp;Privacy%3C/a%3E%3C/td%3E%0A%20%3Ctd%3E%3Ca%20onmouseover=%22m('about',1)%22%20onmouseout=%22m('about',0)%22%20href=%22http://www.cs.washington.edu/info/aboutus/%22%20class=%22barlink%22%3E%3Cimg%20src=%22/images/wharrow.gif%22%20name=%22about%22%20border=%220%22%20alt=%22%22%20/%3E&nbsp;About&nbsp;Us%3C/a%3E%3C/td%3E%0A%20%3Ctd%3E%3Ca%20onmouseover=%22m('search',1)%22%20onmouseout=%22m('search',0)%22%20href=%22http://www.cs.washington.edu/info/search/%22%20class=%22barlink%22%3E&nbsp;&nbsp;%3Cimg%20src=%22/images/wharrow.gif%22%20name=%22search%22%20border=%220%22%20alt=%22%22%20/%3E&nbsp;Search%3C/a%3E%3C/td%3E%0A%20%3Ctd%3E%3Ca%20onmouseover=%22m('contact',1)%22%20onmouseout=%22m('contact',0)%22%20href=%22http://www.cs.washington.edu/info/contact/%22%20class=%22barlink%22%3E&nbsp;&nbsp;%3Cimg%20src=%22/images/wharrow.gif%22%20name=%22contact%22%20border=%220%22%20alt=%22%22%20/%3E&nbsp;Contact&nbsp;Info&nbsp;%3C/a%3E%3C/td%3E%0A%20%3C/tr%3E%0A%3C/table%3E%0A%3Cp%3E%0A%3C!--begin%20HTML%20content--%3E%0A%0A%3Ch1%3EDetecting%20In-Flight%20Page%20Changes%20with%20Web%20Tripwires%3C/h1%3E%0A%0A%3Ca%20href=%22http://www.cs.washington.edu/homes/creis/%22%3ECharles%20Reis%3C/a%3E,%0A%3Ca%20href=%22http://www.cs.washington.edu/homes/gribble/%22%3ESteven%20D.%20Gribble%3C/a%3E,%0A%3Ca%20href=%22http://www.cs.washington.edu/homes/yoshi/%22%3ETadayoshi%20Kohno%3C/a%3E,%0AUniversity%20of%20Washington%20(UW).%3Cbr%3E%20%0A%3Ca%20href=%22http://www.icsi.berkeley.edu/~nweaver/%22%3ENicholas%20C.%20Weaver%3C/a%3E,%0AInternational%20Computer%20Science%20Institute%20(ICSI).%0A%3Cbr%3E%0AFebruary%2029,%202008.%20%20(Updated%20July%202,%202009.)%0A%3C!--%20Originally%20posted%20November%206,%202007.%20--%3E%0A%0A%3Ccenter%3E%0A%5B%0A%3Ca%20href=%22#overview%22%3EOverview%3C/a%3E%20%7C%0A%3Ca%20href=%22#detecting-changes%22%3EDetecting%20Changes%3C/a%3E%20%7C%0A%3Ca%20href=%22#measurement%22%3EMeasurement%20Study%3C/a%3E%20%7C%0A%3Ca%20href=%22#toolkit%22%3EWeb%20Tripwire%20Toolkit%3C/a%3E%20%7C%0A%3Ca%20href=%22web-tripwire/nsdi-2008.pdf%22%3ENSDI%202008%20Paper%3C/a%3E%0A%5D%0A%3C/center%3E%0A%0A%3Cp%3E%0A%3C!--%20Web%20tripwire%20--%3E%0A%3Cstyle%3E%0A.webtripwire%20%7B%0A%20%20width:%2090%25;%0A%20%20background-color:%20#eeeeee;%0A%20%20border:%201px%20solid%20black;%0A%20%20text-align:%20left;%0A%20%20font-family:%20verdana,%20bitstream%20vera%20sans,%20helvetica,%20arial,%20san-serif;%0A%7D%0A%0A.webtripwire-nochange%20%7B%0A%20%20color:%20#006600;%0A%7D%0A%0A.webtripwire-changed%20%7B%0A%20%20color:%20#990000;%0A%20%20font-style:%20italic;%0A%7D%0A%3C/style%3E%0A%3Ccenter%3E%0A%3Cdiv%20class=%22webtripwire%22%3E%0A%20%20%3Cb%3EWeb%20tripwire%20result%20for%20this%20page%20visit:%3C/b%3E%3Cbr%3E%0A%20%20%3Cdiv%20id=%22webtripwire-results%22%3E%3C/div%3E%0A%20%20%3Cnoscript%3E(Could%20not%20run.%20%20JavaScript%20must%20be%20enabled%20to%20run%20web%20tripwires.)%3C/noscript%3E%0A%3C/div%3E%0A%3C/center%3E%0A%3Cscript%20src=%22web-tripwire/webtripwire.js%22%3E%3C/script%3E%0A%0A%3Cp%3E%0A%3Ca%20name=%22overview%22%3E%3C/a%3E%0A%3Ch2%3EOverview%3C/h2%3E%0A%0AOur%20research%20group%20was%20surprised%20to%20hear%20that%20some%20ISPs%20have%20been%20%22injecting%20advertisements%20into%20web%20pages%20requested%20by%20their%20end%20users,%22%20according%20to%20a%20%3Ca%20href=%22http://yro.slashdot.org/yro/07/06/23/1233212.shtml%22%3Erecent%20Slashdot%20article%3C/a%3E.%20%20As%20a%20result,%20we%20set%20out%20to%20measure%20how%20often%20web%20pages%20are%20changed%20after%20leaving%20the%20server%20and%20before%20arriving%20in%20the%20user's%20browser.%0A%3Cp%3E%0A%0AWith%20a%20web-based%20measurement%20tool%20called%20a%20%22web%20tripwire,%22%20we%20found%20that%20approximately%201%25%20of%2050,000%20visitors%20received%20pages%20that%20had%20been%20changed%20%22in-flight.%22%20%20Most%20of%20these%20changes%20were%20caused%20by%20software%20that%20users%20installed%20on%20their%20computer%20(such%20as%20personal%20firewalls%20or%20ad%20blockers),%20but%20many%20were%20caused%20by%20agents%20in%20the%20network,%20such%20as%20ISPs%20and%20enterprise%20firewalls.%20%20Worse,%20we%20found%20that%20many%20of%20the%20products%20that%20users%20installed%20introduced%20bugs%20or%20security%20vulnerabilities%20into%20the%20web%20pages%20they%20requested.%0A%3Cp%3E%0A%0ATo%20address%20this%20problem,%20publishers%20could%20choose%20to%20serve%20their%20pages%20over%20HTTPS%20rather%20than%20HTTP,%20using%20encryption%20to%20preserve%20page%20integrity.%20%20However,%20this%20is%20an%20expensive%20solution%20in%20many%20respects,%20and%20it%20may%20not%20always%20be%20practical.%20%20Web%20tripwires%20offer%20publishers%20a%20less%20expensive%20(but%20non-cryptographically%20secure)%20form%20of%20a%20page%20integrity%20check.%20%20A%20web%20tripwire%20uses%20JavaScript%20code%20to%20detect%20textual%20changes%20to%20an%20HTTP%20web%20page,%20with%20the%20ability%20to%20report%20any%20changes%20to%20the%20user%20and%20to%20the%20publisher.%0A%3Cp%3E%0A%0AThe%20rest%20of%20this%20page%20provides%20more%20information%20about%20the%20results%20of%20the%20measurement%20study%20we%20conducted%20with%20web%20tripwires%20(once%20hosted%20on%20vancouver.cs.washington.edu),%20and%20how%20you%20can%20use%20web%20tripwires%20on%20your%20own%20web%20pages.%20%20We%20have%20a%20web%20tripwire%20installed%20on%20this%20page,%20and%20its%20results%20should%20be%20shown%20at%20the%20top%20of%20the%20page.%20%20Further%20details%20about%20our%20study%20are%20available%20in%20several%20forms:%0A%3Cul%3E%0A%20%20%3Cli%3EOur%20NSDI%202008%20paper,%20entitled%20%3Ca%20href=%22web-tripwire/nsdi-2008.pdf%22%3EDetecting%20In-Flight%20Page%20Changes%20with%20Web%20Tripwires%3C/a%3E%20(PDF).%0A%20%20%3Cli%3EOur%20%3Ca%20href=%22web-tripwire/webtripwire-talk-20071030.pdf%22%3Etalk%20slides%3C/a%3E%20(PDF)%20and%20%3Ca%20href=%22web-tripwire/webtripwire-poster-20071030-small.pdf%22%3Eposter%3C/a%3E%20(PDF)%20from%20our%20department's%20%3Ca%20href=%22http://www.cs.washington.edu/affiliates/%22%3EIndustrial%20Affiliates%20Meeting%3C/a%3E.%0A%20%20%3Cli%3EOur%20downloadable%20%3Ca%20href=%22#toolkit%22%3Eweb%20tripwire%20toolkit%3C/a%3E.%0A%3C/ul%3E%0A%0A%3Cp%3E%0A%3Ca%20name=%22detecting-changes%22%3E%3C/a%3E%0A%3Ch2%3EDetecting%20Page%20Changes%3C/h2%3E%0A%0ATo%20measure%20the%20in-flight%20page%20changes%20that%20users%20see%20in%20practice,%20we%20developed%20JavaScript%20code%20for%20our%20own%20web%20page%20that%20can%20detect%20if%20the%20page%20is%20changed%20after%20leaving%20our%20server%20and%20before%20arriving%20in%20the%20user's%20browser.%20%20This%20JavaScript%20code%20runs%20in%20the%20user's%20browser%20and%20compares%20the%20page%20the%20user%20received%20to%20what%20we%20expected%20it%20to%20be.%20%20We%20refer%20to%20this%20check%20as%20a%20%3Cb%3Eweb%20tripwire%3C/b%3E,%20and%20we%20put%20it%20online%20at%20vancouver.cs.washington.edu%20during%20our%20measurement%20study.%0A%3Cp%3E%0A%0AMore%20information%20about%20how%20the%20web%20tripwire%20works%20can%20be%20found%20on%20the%20page%20linked%20above.%20%20At%20a%20basic%20level,%20it%20detects%20most%20textual%20changes%20to%20the%20page's%20HTML.%20%20It%20is%20not%20triggered%20by%20browser%20extensions%20(which%20are%20part%20of%20the%20browser),%20but%20it%20will%20detect%20proxy%20software%20installed%20on%20the%20user's%20computer.%20%20It%20is%20also%20not%20secure:%20adversaries%20could%20tamper%20with%20or%20remove%20the%20web%20tripwire%20if%20they%20wish%20to%20avoid%20detection.%20%20In%20most%20current%20cases,%20however,%20it%20will%20detect%20any%20changes%20to%20the%20page.%0A%0A%0A%3Cp%3E%0A%3Ca%20name=%22measurement%22%3E%3C/a%3E%0A%3Ch2%3EMeasurement%20Study%3C/h2%3E%0A%0AWe%20used%20the%20web%20page%20described%20above%20to%20conduct%20a%20measurement%20study%20of%20web%20page%20changes%20in%20practice.%20%20We%20needed%20to%20attract%20a%20large%20number%20of%20users%20on%20diverse%20networks%20to%20our%20page,%20so%20we%20posted%20stories%20on%20%3Ca%20href=%22http://yro.slashdot.org/article.pl?sid=07/07/25/155200%22%3ESlashdot%3C/a%3E,%20%3Ca%20href=%22http://digg.com/security/Are_ISPs_modifying_your_web_pages%22%3EDigg%3C/a%3E,%20and%20similar%20web%20sites%20on%20July%2024,%202007.%20%20Over%20the%20following%2020%20days,%20we%20received%20visits%20from%2050,171%20unique%20IP%20addresses.%0A%3Cp%3E%0A%0A%3Cb%3EResults%3C/b%3E%3Cp%3E%0A%0AWe%20were%20surprised%20to%20find%20that%20clients%20at%20657%20of%20those%20IP%20addresses%20(1.3%25)%20reported%20some%20in-flight%20change%20to%20our%20page.%20%20This%20is%20a%20much%20larger%20number%20of%20changes%20than%20we%20expected.%20%20The%20vast%20majority%20of%20changes%20were%20caused%20by%20proxy%20software%20on%20the%20user's%20machine,%20such%20as%20popup%20blockers%20and%20ad%20blockers.%20%20However,%20we%20also%20observed%20ISPs%20that%20injected%20ads%20(e.g.,%20through%20companies%20like%20NebuAd),%20enterprise%20firewalls%20that%20removed%20meta%20tags%20and%20inserted%20JavaScript%20security%20checks%20(e.g.,%20with%20products%20like%20BlueCoat%20Web%20Filter),%20and%20malware%20that%20injected%20either%20exploit%20code%20or%20ads.%20%20Our%20findings%20are%20summarized%20in%20the%20table%20below.%0A%3Cp%3E%0A%0A%3Ctable%20border=1%20cellspacing=0%20cellpadding=5%3E%0A%3Ctr%3E%0A%20%20%3Ctd%3E%3Cb%3ECategory%3C/b%3E%3C/td%3E%3Ctd%3E%3Cb%3EIPs%3C/b%3E%3C/td%3E%3Ctd%3E%3Cb%3EExamples%3C/b%3E%3C/td%3E%0A%3C/tr%3E%0A%3Ctr%3E%0A%20%20%3Ctd%3EPopup%20Blocker%3C/td%3E%3Ctd%3E277%3C/td%3E%3Ctd%3EZone%20Alarm%20(210),%20%3Cb%3ECA%20Personal%20Firewall%20(17)%3C/b%3E,%20Sunbelt%20Popup%20Killer%20(12)%3C/td%3E%0A%3C/tr%3E%0A%3Ctr%3E%0A%20%20%3Ctd%3EAd%20Blocker%3C/td%3E%3Ctd%3E188%3C/td%3E%3Ctd%3E%3Cb%3EAd%20Muncher%20(99)%3C/b%3E,%20Privoxy%20(58),%20%3Cb%3EProxomitron%20(25)%3C/b%3E%3C/td%3E%0A%3C/tr%3E%0A%3Ctr%3E%0A%20%20%3Ctd%3EProblem%20in%20Transit%3C/td%3E%3Ctd%3E118%3C/td%3E%3Ctd%3EBlank%20Page%20(107),%20Incomplete%20Page%20(7)%3C/td%3E%0A%3C/tr%3E%0A%3Ctr%3E%0A%20%20%3Ctd%3ECompression%3C/td%3E%3Ctd%3E30%3C/td%3E%3Ctd%3E%3Cb%3Ebmi.js%20(23)%3C/b%3E,%20Newlines%20removed%20(6),%20%3Cb%3EImage%20Distillation%20(1)%3C/b%3E%3C/td%3E%0A%3C/tr%3E%0A%3Ctr%3E%0A%20%20%3Ctd%3ESecurity%20or%20Privacy%3C/td%3E%3Ctd%3E17%3C/td%3E%3Ctd%3EBlue%20Coat%20(15),%20%3Cb%3EThe%20Cloak%20(1)%3C/b%3E,%20AnchorFree%20(1)%3C/td%3E%0A%3C/tr%3E%0A%3Ctr%3E%0A%20%20%3Ctd%3EAd%20Injector%3C/td%3E%3Ctd%3E16%3C/td%3E%3Ctd%3EMetroFi%20(6),%20FairEagle/NebuAd%20(5),%20LokBox%20(1),%20Front%20Porch%20(1),%20PerfTech%20(1),%20Edge%20Technologies%20(1)%3C/td%3E%0A%3C/tr%3E%0A%3Ctr%3E%0A%20%20%3Ctd%3EMeta%20Tag%20Changes%3C/td%3E%3Ctd%3E12%3C/td%3E%3Ctd%3ERemoved%20meta%20tags%20(8),%20Reformatted%20meta%20tags%20(4)%3C/td%3E%0A%3C/tr%3E%0A%3Ctr%3E%0A%20%20%3Ctd%3EMalware%3C/td%3E%3Ctd%3E3%3C/td%3E%3Ctd%3EW32.Arpiframe%20(2),%20Adware.LinkMaker%20(1)%3C/td%3E%0A%3C/tr%3E%0A%3Ctr%3E%0A%20%20%3Ctd%3EMiscellaneous%3C/td%3E%3Ctd%3E3%3C/td%3E%3Ctd%3ENew%20background%20color%20(1),%20%3Cb%3EIE%20Mark%20of%20the%20Web%20(1)%3C/b%3E%3C/td%3E%0A%3C/tr%3E%0A%3C/table%3E%0A%3Ci%3EThis%20table%20shows%20the%20categories%20of%20observed%20page%20changes,%20the%20number%20of%20client%20IP%20addresses%20affected%20by%20each,%20and%20examples.%20%20Each%20example%20is%20followed%20by%20the%20number%20of%20IP%20addresses%20that%20reported%20it;%20examples%20listed%20in%20bold%20introduced%20bugs%20or%20vulnerabilities%20into%20our%20page.%3C/i%3E%0A%3Cp%3E%0A%0AThese%20changes%20were%20made%20by%20agents%20that%20had%20incentives%20to%20change%20the%20page,%20but%20their%20goals%20were%20not%20always%20in%20line%20with%20the%20goals%20of%20the%20user%20or%20the%20publisher.%20%20For%20example:%0A%3Cul%3E%0A%3Cli%3EISPs%20sought%20to%20increase%20revenue%20from%20ads.%20%20These%20ads%20could%20annoy%20the%20user%20or%20dilute%20the%20impact%20of%20the%20publisher's%20own%20ads.%0A%3Cli%3EEnterprise%20proxies%20sought%20to%20reduce%20traffic%20by%20removing%20cache-related%20meta%20tags,%20which%20could%20affect%20whether%20a%20user%20sees%20a%20stale%20copy%20of%20the%20page.%0A%3Cli%3EUsers%20sought%20to%20remove%20annoyances%20like%20popups%20and%20ads,%20which%20may%20affect%20the%20publisher's%20revenue%20stream.%0A%3Cli%3EMalware%20authors%20sought%20to%20spread%20worms%20and%20make%20money%20off%20injected%20ads.%0A%3C/ul%3E%0A%0A%3Cb%3EBugs%20and%20Vulnerabilities%3C/b%3E%3Cp%3E%0A%0AWe%20found%20that%20many%20in-flight%20changes%20inadvertently%20broke%20web%20pages.%20%20For%20example,%20both%20CA%20Personal%20Firewall%20and%20some%20ISP-based%20changes%20caused%20a%20JavaScript%20stack%20overflow%20error%20when%20the%20scripts%20they%20inserted%20interfered%20with%20the%20code%20on%20our%20page.%20%20CA%20Personal%20Firewall%20also%20interfered%20with%20many%20web%20forums,%20including%20MySpace.%20%20MySpace%20users%20would%20post%20blog%20entries%20and%20comments,%20and%20they%20would%20find%20popup%20blocking%20code%20(i.e.,%20%22%3Ctt%3E_popupControl()%3C/tt%3E%22)%20inadvertently%20injected%20into%20their%20post.%0A%3Cp%3E%0A%0AWorse%20than%20this,%20we%20found%20several%20types%20of%20page%20changes%20that%20caused%20our%20page%20to%20become%20vulnerable%20to%20a%20cross%20site%20scripting%20(XSS)%20attack.%20%20Products%20such%20as%20%3Ca%20href=%22http://www.admuncher.com%22%3EAd%20Muncher%3C/a%3E%20and%20the%20%3Ca%20href=%22http://www.geocities.com/sidki3003/prox.html%22%3ESidki%3C/a%3E%20and%20%3Ca%20href=%22http://www.castlecops.com/t124920-About_Grypens_Filter_Set.html%22%3EGrypen%3C/a%3E%20filter%20sets%20for%20%3Ca%20href=%22http://www.proxomitron.info%22%3EProxomitron%3C/a%3E%20introduced%20code%20that%20was%20vulnerable%20to%20attack.%20%20These%20vulnerabilities%20were%20significant%20because%20they%20affected%20%3Cb%3Emost%20or%20all%3C/b%3E%20of%20the%20web%20pages%20that%20a%20user%20visited.%20%20In%20the%20case%20of%20Proxomitron%20(but%20not%20Ad%20Muncher),%20the%20vulnerabilities%20could%20affect%20HTTPS%20traffic%20as%20well.%20%20This%20type%20of%20problem%20is%20analogous%20to%20a%20root%20exploit%20for%20an%20operating%20system,%20because%20it%20can%20potentially%20affect%20all%20pages%20that%20a%20user%20visits.%0A%3Cp%3E%0A%0AIn%20these%20cases,%20an%20attacker%20could%20convince%20a%20user%20to%20follow%20a%20link%20that%20injected%20script%20code%20into%20almost%20any%20web%20page.%20%20This%20script%20code%20could%20steal%20a%20user's%20session%20cookie%20(e.g.,%20on%20Facebook),%20modify%20login%20forms%20to%20steal%20passwords%20(e.g.,%20on%20many%20banks),%20or%20manipulate%20the%20contents%20of%20any%20page%20(e.g.,%20search%20results%20on%20Google).%0A%3Cp%3E%0A%0AWe%20have%20reported%20the%20vulnerabilities%20we%20found,%20and%20the%20developers%20have%20released%20versions%20that%20fix%20the%20vulnerabilities%20as%20of%20Fall%202007.%20%20If%20you%20are%20using%20older%20versions%20of%20the%20products%20above,%20be%20sure%20to%20update%20as%20soon%20as%20possible.%0A%3Cp%3E%0A%20%20%0AOverall,%20these%20problems%20indicate%20that%20web%20page%20rewriting%20software%20can%20have%20dangerous%20consequences%20if%20it%20is%20not%20carefully%20analyzed.%20%20Users%20should%20understand%20these%20consequences%20when%20using%20web%20proxies.%0A%0A%0A%3Cp%3E%0A%3Ca%20name=%22toolkit%22%3E%3C/a%3E%0A%3Ch2%3EWeb%20Tripwire%20Toolkit%3C/h2%3E%0A%0ABecause%20many%20of%20the%20changes%20we%20found%20can%20have%20negative%20consequences%20for%20web%20publishers%20or%20their%20users,%20we%20recommend%20that%20publishers%20take%20steps%20to%20understand%20what%20changes%20are%20made%20to%20their%20pages.%20%20Encrypting%20pages%20with%20HTTPS%20prevents%20changes,%20but%20it%20can%20be%20overly%20expensive%20in%20terms%20of%20CPU%20overhead,%20latency,%20and%20certificate%20costs.%20%20Thus,%20in%20many%20cases%20we%20suggest%20that%20publishers%20deploy%20%3Cb%3Eweb%20tripwires%3C/b%3E%20similar%20to%20those%20used%20in%20our%20measurement%20study.%20%20Although%20web%20tripwires%20are%20not%20secure%20and%20may%20miss%20some%20types%20of%20changes%20(e.g.,%20full%20page%20substitutions),%20they%20can%20effectively%20detect%20most%20page%20modifications%20in%20practice.%0A%3Cp%3E%0A%0ATo%20make%20web%20tripwires%20easy%20to%20deploy,%20we%20have%20developed%20a%20%3Cb%3Econfigurable%20toolkit%3C/b%3E%20that%20can%20be%20hosted%20by%20a%20web%20publisher.%20%20The%20toolkit%20is%20available%20under%20a%20BSD-style%20open%20source%20license,%20and%20it%20is%20effective%20for%20most%20web%20pages%20with%20static%20content.%20%20It%20consists%20of%20two%20Perl%20CGI%20scripts%20that%20integrate%20web%20tripwires%20into%20a%20given%20web%20page.%0A%3Cp%3E%0A%0A%3Ca%20href=%22web-tripwire/toolkit-0.5.zip%22%3EDownload%20Web%20Tripwire%20Toolkit%3C/a%3E%0A%3Cp%3E%0A%0A%3Cb%3EWeb%20Tripwire%20Toolkit%20License%3C/b%3E%3Cp%3E%0A%3Cpre%3E%0ACopyright%20(c)%202007%20Charles%20Reis%0AAll%20rights%20reserved.%0A%0ARedistribution%20and%20use%20in%20source%20and%20binary%20forms,%20with%20or%20without%0Amodification,%20are%20permitted%20provided%20that%20the%20following%20conditions%0Aare%20met:%0A1.%20Redistributions%20of%20source%20code%20must%20retain%20the%20above%20copyright%0A%20%20%20notice,%20this%20list%20of%20conditions%20and%20the%20following%20disclaimer.%0A2.%20Redistributions%20in%20binary%20form%20must%20reproduce%20the%20above%20copyright%0A%20%20%20notice,%20this%20list%20of%20conditions%20and%20the%20following%20disclaimer%20in%20the%0A%20%20%20documentation%20and/or%20other%20materials%20provided%20with%20the%20distribution.%0A3.%20Neither%20the%20name%20of%20the%20University%20of%20Washington%20nor%20the%20names%20of%0A%20%20%20its%20contributors%20may%20be%20used%20to%20endorse%20or%20promote%20products%20derived%0A%20%20%20from%20this%20software%20without%20specific%20prior%20written%20permission.%0A%0ATHIS%20SOFTWARE%20IS%20PROVIDED%20BY%20THE%20COPYRIGHT%20HOLDERS%20AND%20CONTRIBUTORS%20%22AS%0AIS%22%20AND%20ANY%20EXPRESS%20OR%20IMPLIED%20WARRANTIES,%20INCLUDING,%20BUT%20NOT%20LIMITED%0ATO,%20THE%20IMPLIED%20WARRANTIES%20OF%20MERCHANTABILITY%20AND%20FITNESS%20FOR%20A%0APARTICULAR%20PURPOSE%20ARE%20DISCLAIMED.%20IN%20NO%20EVENT%20SHALL%20THE%20COPYRIGHT%20OWNER%0AOR%20CONTRIBUTORS%20BE%20LIABLE%20FOR%20ANY%20DIRECT,%20INDIRECT,%20INCIDENTAL,%20SPECIAL,%0AEXEMPLARY,%20OR%20CONSEQUENTIAL%20DAMAGES%20(INCLUDING,%20BUT%20NOT%20LIMITED%20TO,%0APROCUREMENT%20OF%20SUBSTITUTE%20GOODS%20OR%20SERVICES;%20LOSS%20OF%20USE,%20DATA,%20OR%0APROFITS;%20OR%20BUSINESS%20INTERRUPTION)%20HOWEVER%20CAUSED%20AND%20ON%20ANY%20THEORY%20OF%0ALIABILITY,%20WHETHER%20IN%20CONTRACT,%20STRICT%20LIABILITY,%20OR%20TORT%20(INCLUDING%0ANEGLIGENCE%20OR%20OTHERWISE)%20ARISING%20IN%20ANY%20WAY%20OUT%20OF%20THE%20USE%20OF%20THIS%0ASOFTWARE,%20EVEN%20IF%20ADVISED%20OF%20THE%20POSSIBILITY%20OF%20SUCH%20DAMAGE.%0A%3C/pre%3E%0A%3Cp%3E%0A%0A%0A%3Cb%3EToolkit%20Examples%3C/b%3E%3Cp%3E%0ATwo%20examples%20of%20pages%20that%20use%20the%20toolkit%20are%20linked%20below.%0A%3Cul%3E%0A%3Cli%3E%20%3Ca%20href=%22http://abstract.cs.washington.edu/~creis/webtripwire/sample.html%22%3EThis%20page%3C/a%3E%20has%20a%20live%20web%20tripwire.%20%20It%20will%20only%20be%20noticeable%20to%20the%20user%20if%20the%20page%20is%20modified%20in%20flight.%0A%3Cli%3E%20%3Ca%20href=%22http://abstract.cs.washington.edu/~creis/webtripwire/sample-mod.html%22%3EThis%20page%3C/a%3E%20simulates%20a%20page%20that%20has%20been%20changed%20in%20flight,%20so%20that%20you%20can%20see%20how%20the%20web%20tripwire%20reports%20a%20change%20to%20the%20user.%0A%3C/ul%3E%0A%3Cp%3E%0A%0A%3C!--%0AOur%20original%20measurement%20tool%20at%20%3Ca%20href=%22http://vancouver.cs.washington.edu%22%3Ehttp://vancouver.cs.washington.edu%3C/a%3E%20also%20provides%20an%20example%20of%20web%20tripwires.%20%20This%20tool%20records%20any%20detected%20changes%20for%20use%20in%20our%20study.%20%20We%20encourage%20users%20to%20visit%20this%20page%20periodically%20to%20detect%20changes%20to%20their%20own%20web%20page%20requests.%0A--%3E%0A%0A%3C!--%0AThe%20web%20tripwire%20service%20is%20no%20longer%20active.%0A%0A%3Cp%3E%0A%3Ca%20name=%22service%22%3E%3C/a%3E%0A%3Ch2%3EWeb%20Tripwire%20Service%3C/h2%3E%0AIn%20some%20situations,%20web%20publishers%20may%20wish%20to%20add%20web%20tripwires%20to%20their%20pages%20but%20cannot%20run%20CGI%20scripts%20on%20their%20web%20server.%20%20To%20help%20such%20publishers,%20we%20also%20offer%20a%20convenient%20%3Cb%3Eweb%20tripwire%20service%3C/b%3E%20that%20is%20hosted%20by%20our%20own%20server.%0A%3Cp%3E%0A%20%20%0AMuch%20like%20%3Ca%20href=%22http://www.google.com/analytics/%22%3EGoogle%20Analytics%3C/a%3E,%20we%20offer%20a%20JavaScript%20file%20that%20publishers%20can%20add%20to%20their%20own%20page.%20%20This%20requires%20a%20one-line%20change%20to%20a%20web%20page%20that%20causes%20browsers%20to%20fetch%20an%20active%20web%20tripwire%20from%20our%20server.%20%20The%20web%20tripwire%20will%20detect%20in-flight%20modifications%20to%20the%20page,%20report%20them%20to%20our%20server,%20and%20optionally%20display%20a%20message%20to%20the%20user.%20%20We%20can%20then%20log%20the%20changes%20and%20provide%20reports%20to%20the%20publisher.%0A%3Cp%3E%0A%20%20%0ATo%20use%20our%20web%20tripwire%20service,%20just%20follow%20these%20steps:%0A%3Col%3E%0A%20%20%3Cli%3EAdd%20the%20following%20line%20to%20your%20web%20page,%20replacing%20%3Ctt%3E%3Cb%3EYOUR_URL%3C/b%3E%3C/tt%3E%20with%20the%20full%20URL%20to%20your%20page.%20%20(Note%20that%20your%20web%20page%20must%20be%20static,%20such%20that%20two%20back-to-back%20requests%20for%20the%20page%20will%20receive%20identical%20contents.)%3Cbr%3E%0A%20%20%20%20%3Ctt%3E&lt;script%20src=%22http://vancouver.cs.washington.edu/service/webtripwire.cgi?page=%3Cb%3EYOUR_URL%3C/b%3E%22&gt;&lt;/script&gt;%3C/tt%3E%0A%20%20%3Cli%3E(Optional)%20If%20you%20would%20not%20like%20a%20message%20to%20be%20displayed%20to%20your%20visitors%20when%20a%20modification%20is%20detected,%20add%20%3Ctt%3Esilentmode=1&amp;%3C/tt%3E%20after%20the%20%3Ctt%3E?%3C/tt%3E%20in%20the%20above%20line.%0A%20%20%3Cli%3E%3Ca%20href=%22/htbin-post/unrestricted/mailto2.pl?to=creis;sub=UW+CSE+Web:+Web+Tripwire+Service%22%3EContact%20us%3C/a%3E%20to%20tell%20us%20your%20email%20address%20and%20the%20full%20URL%20to%20your%20page.%20%20We%20will%20only%20activate%20our%20service%20for%20your%20page%20once%20we%20verify%20that%20you%20have%20added%20the%20above%20line.%20%20(This%20step%20ensures%20that%20our%20service%20will%20not%20be%20misused%20as%20an%20open%20proxy.)%0A%20%20%3Cli%3EWe%20will%20arrange%20to%20provide%20you%20with%20reports%20of%20what%20modifications%20were%20made%20to%20your%20page,%20as%20seen%20by%20your%20page's%20visitors.%0A%3C/ol%3E%0A%3Cp%3E%0A%0AOne%20caveat:%20the%20tripwire%20service%20is%20not%20yet%20compatible%20with%20non-ASCII%20characters.%20%20Pages%20with%20non-ASCII%20characters%20will%20cause%20false%20positives%20in%20some%20browsers.%20%20You%20can%20avoid%20this%20problem%20by%20replacing%20such%20characters%20with%20the%20equivalent%20HTML%20entities%20(e.g.,%20&amp;eacute;%20for%20&eacute;).%20%20You%20can%20find%20a%20list%20of%20such%20entities%20%3Ca%20href=%22http://www.w3schools.com/tags/ref_entities.asp%22%3Ehere%3C/a%3E.%0A%3Cp%3E%0A%0A%3Cb%3EService%20Examples%3C/b%3E%3Cp%3E%0ATwo%20examples%20of%20pages%20that%20use%20the%20service%20are%20linked%20below.%20%20These%20pages%20are%20hosted%20on%20a%20server%20that%20does%20not%20allow%20CGI%20scripts,%20so%20using%20the%20service%20is%20necessary.%0A%3Cul%3E%0A%3Cli%3E%20%3Ca%20href=%22http://www.cs.washington.edu/research/security/web-tripwire/sample-service.html%22%3EThis%20page%3C/a%3E%20has%20a%20live%20web%20tripwire.%20%20It%20will%20only%20be%20noticeable%20to%20the%20user%20if%20the%20page%20is%20modified%20in%20flight.%0A%3Cli%3E%20%3Ca%20href=%22http://www.cs.washington.edu/research/security/web-tripwire/sample-service-mod.html%22%3EThis%20page%3C/a%3E%20simulates%20a%20page%20that%20has%20been%20changed%20in%20flight,%20so%20that%20you%20can%20see%20how%20the%20web%20tripwire%20reports%20a%20change%20to%20the%20user.%0A%3C/ul%3E%0A%3Cp%3E%0A%0A--%3E%0A%0A%3C!--end%20HTML%20content--%3E%0A%0A%3Cp%3E%0A%3Ctable%20width=%22100%25%22%20cellpadding=%220%22%20border=%220%22%20cellspacing=%220%22%3E%0A%3Ctr%3E%3Ctd%20colspan=%222%22%3E%3Chr%20noshade=%22noshade%22%20size=%222%22%20/%3E%3C/td%3E%3C/tr%3E%0A%3Ctr%20align=%22center%22%20valign=%22middle%22%3E%0A%20%3Ctd%20width=%2215%25%22%3E%3Ca%20href=%22/%22%3E%3Cimg%20src=%22/images/logo.png%22%20width=%2234%22%20height=%2233%22%20%0A%20%20alt=%22CSE%20logo%22%20border=%220%22%20/%3E%3C/a%3E%3C/td%3E%0A%20%3Ctd%20width=%2285%25%22%3E%3Cspan%20style=%22font-family:%20helvetica,%20arial,%20sans-serif;%20font-size:%2013px;%20text-decoration:%20none%22%3E%0A%20Computer&nbsp;Science&nbsp;&amp;&nbsp;Engineering%3Cbr%20/%3E%0A%20University&nbsp;of&nbsp;Washington%3Cbr%20/%3E%0A%20Box&nbsp;352350%3Cbr%20/%3E%0A%20Seattle,&nbsp;WA&nbsp;&nbsp;98195-2350%3Cbr%20/%3E%0A%20(206)&nbsp;543-1695&nbsp;voice,&nbsp;(206)&nbsp;543-2969&nbsp;FAX%3Cbr%20/%3E%0A%5Bcomments%20to%20%3Cem%3E%3Ca%20href=%22/htbin-post/unrestricted/mailto2.pl?to=creis;sub=UW+CSE+Web:+Detecting+In-Flight+Page+Changes+with+Web+Tripwires%22%3Ecreis%3C/a%3E%3C/em%3E%5D%3C/span%3E%0A%20%3C/td%3E%3C/tr%3E%0A%3C/table%3E%0A%3C/body%3E%0A%3C/html%3E%0A";

/* Fetches the target page with an XmlHttpRequest and compares it to the
 * expected HTML string.  If they differ, report the modified HTML to
 * the server and optionally the user.
 * The callback argument is invoked if a change is detected.
 */
WebTripwire.detect = function(callback) {
  var req = WebTripwire.newXHR();
  
  // Create a handler for the test page request
  var handler = function() {
    // Check if the request state is loaded and OK
    if (req.readyState == 4 && req.status == 200) {
    
      // See if the actual HTML is the same as the expected HTML.
      var targetPageHTML = decodeURI(WebTripwire.encodedTargetPageHTML);
      if (req.responseText != targetPageHTML) {
        // Detected modification
        //alert(encodeURI(req.responseText));  // for debugging
        
        // Notify the user
        var message = "<h1>Page Modification Detected</h1>\n" +
          "We have detected that our web page was modified between leaving our server and\n" +
          "arriving in your browser.  There are many possible causes for such a modification,\n" +
          "ranging from the use of personal firewalls to Internet Service Providers that\n" +
          "inject advertisements.<p>\n" +
          "For your reference, the actual HTML your browser received is shown below,\n" +
          "with the modifications highlighted in red and green.<p>\n";
        WebTripwire.react(targetPageHTML, req.responseText, message);
        
      }
      else {
        // No change detected
        var resultsDiv = document.getElementById("webtripwire-results");
        resultsDiv.innerHTML = "<div class='webtripwire-nochange'>No in-flight change detected on this page.</div>";
      }
    }
  };
  
  // Display an in-progress message
  var resultsDiv = document.getElementById("webtripwire-results");
  resultsDiv.innerHTML = "Our web tripwire is testing for in-flight changes...";
        
  // Make an asynchronous request for the test page
  req.onreadystatechange = handler;
  req.open("GET", WebTripwire.targetPageURL, true);
  req.send(null);
};

/* Function to display a message to the user when a change is detected.
 */
WebTripwire.react = function(expected, actual, message) {
  if (message == null) {
    // Don't print anything
    return;
  }
  // Escape angle brackets for printing HTML source code
  expected = expected.replace(/</g, '&lt;').replace(/>/g, '&gt;');
  actual = actual.replace(/</g, '&lt;').replace(/>/g, '&gt;');
  var insObj = { text:"" };
  var diff = jsd_diffString(expected, actual, insObj);
  diff = diff.replace(/\n/g, "<br>\n").replace(/"/g, "&quot;");
  
  WebTripwire.diff = "<html><body>\n" + message +
    "<hr>\n" + diff + "\n</body></html>";
    
  // Display a message to the user
  var resultsDiv = document.getElementById("webtripwire-results");
  resultsDiv.innerHTML = '<div class="webtripwire-changed">We have detected that this page has been modified in flight.  For more information, click <a onclick="javascript:w=window.open();w.document.write(WebTripwire.diff);w.document.close()"><u>here</u></a>.</div>';
}

/* Copied cross-browser code for getting an XMLHttpRequest object.
 * Source: http://www.hackorama.com/ajax/
 */
WebTripwire.newXHR = function() {
  var xmlreq = false;
  if (window.XMLHttpRequest) {
    xmlreq = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    // Try ActiveX
    try { 
      xmlreq = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e1) { 
      // first method failed 
      try {
        xmlreq = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e2) {
        // both methods failed 
      } 
    }
  }
  return xmlreq;
};


/* Add an onload handler to run the tripwire. 
 * Credit: http://simonwillison.net/2004/May/26/addLoadEvent/
 */
WebTripwire.addLoadEvent = function(newonload) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = newonload;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      newonload();
    }
  }
}
WebTripwire.addLoadEvent(WebTripwire.detect);

/*
 * Javascript Diff Algorithm
 *  By John Resig (http://ejohn.org/)
 *  Modified by Chu Alan "sprite"
 *  Modified by Charles Reis
 *
 * More Info:
 *  http://ejohn.org/projects/javascript-diff-algorithm/
 */

function jsd_escape(s) {
    var n = s;
    //n = n.replace(/&/g, "&amp;");
    n = n.replace(/</g, "&lt;");
    n = n.replace(/>/g, "&gt;");
    n = n.replace(/"/g, "&quot;");

    return n;
}

function jsd_diffString( o, n, insObj ) {
  o = o.replace(/\s+$/, '');
  n = n.replace(/\s+$/, '');
  if (insObj == null) insObj = new Object();

  var out = jsd_diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
  var str = "";

  var oSpace = o.match(/\s+/g);
  if (oSpace == null) {
    oSpace = ["\n"];
  } else {
    oSpace.push("\n");
  }
  var nSpace = n.match(/\s+/g);
  if (nSpace == null) {
    nSpace = ["\n"];
  } else {
    nSpace.push("\n");
  }

  if (out.n.length == 0) {
      for (var i = 0; i < out.o.length; i++) {
        str += "<del style='background:#FFE6E6;'>" + jsd_escape(out.o[i]) + oSpace[i] + "</del>";
      }
  } else {
    if (out.n[0].text == null) {
      for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
        str += "<del style='background:#FFE6E6;'>" + jsd_escape(out.o[n]) + oSpace[n] + "</del>";
      }
    }

    for ( var i = 0; i < out.n.length; i++ ) {
      if (out.n[i].text == null) {
        str += "<ins style='background:#E6FFE6;'>" + jsd_escape(out.n[i]) + nSpace[i] + "</ins>";
        insObj.text += jsd_escape(out.n[i]) + nSpace[i];
      } else {
        var pre = "";

        for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
          pre += "<del style='background:#FFE6E6;'>" + jsd_escape(out.o[n]) + oSpace[n] + "</del>";
        }
        str += " " + out.n[i].text + nSpace[i] + pre;
      }
    }
  }
  
  return str;
}

function jsd_diff( o, n ) {
  var ns = new Object();
  var os = new Object();
  
  for ( var i = 0; i < n.length; i++ ) {
    if ( ns[ n[i] ] == null )
      ns[ n[i] ] = { rows: new Array(), o: null };
    ns[ n[i] ].rows.push( i );
  }
  
  for ( var i = 0; i < o.length; i++ ) {
    if ( os[ o[i] ] == null )
      os[ o[i] ] = { rows: new Array(), n: null };
    os[ o[i] ].rows.push( i );
  }
  
  for ( var i in ns ) {
    if ( ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1 ) {
      n[ ns[i].rows[0] ] = { text: n[ ns[i].rows[0] ], row: os[i].rows[0] };
      o[ os[i].rows[0] ] = { text: o[ os[i].rows[0] ], row: ns[i].rows[0] };
    }
  }
  
  for ( var i = 0; i < n.length - 1; i++ ) {
    if ( n[i].text != null && n[i+1].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null && 
         n[i+1] == o[ n[i].row + 1 ] ) {
      n[i+1] = { text: n[i+1], row: n[i].row + 1 };
      o[n[i].row+1] = { text: o[n[i].row+1], row: i + 1 };
    }
  }
  
  for ( var i = n.length - 1; i > 0; i-- ) {
    if ( n[i].text != null && n[i-1].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null && 
         n[i-1] == o[ n[i].row - 1 ] ) {
      n[i-1] = { text: n[i-1], row: n[i].row - 1 };
      o[n[i].row-1] = { text: o[n[i].row-1], row: i - 1 };
    }
  }
  
  return { o: o, n: n };
}


