PageSourceSearch

https://zoomgov.com/csrf_js

js zoomgov.com collected 2026-09-24 08:37:32 UTC 15,722 bytes, 442 lines download raw bytes

1/**
2 * The OWASP CSRFGuard Project, BSD License
3 * Eric Sheridan ([email protected]), Copyright (c) 2011
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 *    1. Redistributions of source code must retain the above copyright notice,
10 *       this list of conditions and the following disclaimer.
11 *    2. Redistributions in binary form must reproduce the above copyright
12 *       notice, this list of conditions and the following disclaimer in the
13 *       documentation and/or other materials provided with the distribution.
14 *    3. Neither the name of OWASP nor the names of its contributors may be used
15 *       to endorse or promote products derived from this software without specific
16 *       prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29(function() {
30
31    function addEvent( obj, type, fn ) {
32        if (obj.addEventListener) {
33            obj.addEventListener( type, fn, false );
34            EventCache.add(obj, type, fn);
35        }
36        else if (obj.attachEvent) {
37            obj["e"+type+fn] = fn;
38            obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
39            obj.attachEvent( "on"+type, obj[type+fn] );
40            EventCache.add(obj, type, fn);
41        }
42        else {
43            obj["on"+type] = obj["e"+type+fn];
44        }
45    }
46
47    var EventCache = function(){
48        var listEvents = [];
49        return {
50            listEvents : listEvents,
51            add : function(node, sEventName, fHandler){
52                listEvents.push(arguments);
53            },
54            flush : function(){
55                var i, item;
56                for(i = listEvents.length - 1; i >= 0; i = i - 1){
57                    item = listEvents[i];
58                    if(item[0].removeEventListener){
59                        item[0].removeEventListener(item[1], item[2], item[3]);
60                    }
61                    if(item[1].substring(0, 2) != "on"){
62                        item[1] = "on" + item[1];
63                    }
64                    if(item[0].detachEvent){
65                        item[0].detachEvent(item[1], item[2]);
66                    }
67                }
68            }
69        };
70    }();
71
72    /** string utility functions * */
73    if(typeof String.prototype.startsWith !== "function") {
74        String.prototype.startsWith = function(prefix) {
75            return this.indexOf(prefix) === 0;
76        };
77    }
78    if(typeof String.prototype.endsWith !== "function") {
79        String.prototype.endsWith = function(suffix) {
80            return this.match(suffix+"$") == suffix;
81        };
82    }
83
84    /** hook using standards based prototype * */
85    function hijackStandard() {
86        XMLHttpRequest.prototype._open = XMLHttpRequest.prototype.open;
87        XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
88            this.url = url;
89
90            this._open.apply(this, arguments);
91        };
92
93        XMLHttpRequest.prototype._send = XMLHttpRequest.prototype.send;
94        XMLHttpRequest.prototype.send = function(data) {
95            if(this.onsend != null) {
96                this.onsend.apply(this, arguments);
97            }
98
99            this._send.apply(this, arguments);
100        }
101    }
102
103    /** ie does not properly support prototype - wrap completely * */
104    function hijackExplorer() {
105        var _XMLHttpRequest = window.XMLHttpRequest;
106
107        function alloc_XMLHttpRequest() {
108            this.base = _XMLHttpRequest ? new _XMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
109        }
110
111        function init_XMLHttpRequest() {
112            return new alloc_XMLHttpRequest;
113        }
114
115        init_XMLHttpRequest.prototype = alloc_XMLHttpRequest.prototype;
116
117        /** constants * */
118        init_XMLHttpRequest.UNSENT = 0;
119        init_XMLHttpRequest.OPENED = 1;
120        init_XMLHttpRequest.HEADERS_RECEIVED = 2;
121        init_XMLHttpRequest.LOADING = 3;
122        init_XMLHttpRequest.DONE = 4;
123
124        /** properties * */
125        init_XMLHttpRequest.prototype.status = 0;
126        init_XMLHttpRequest.prototype.statusText = "";
127        init_XMLHttpRequest.prototype.readyState = init_XMLHttpRequest.UNSENT;
128        init_XMLHttpRequest.prototype.responseText = "";
129        init_XMLHttpRequest.prototype.responseXML = null;
130        init_XMLHttpRequest.prototype.onsend = null;
131
132        init_XMLHttpRequest.url = null;
133        init_XMLHttpRequest.onreadystatechange = null;
134
135        /** methods * */
136        init_XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
137            var self = this;
138            this.url = url;
139
140            this.base.open(method, url, async, user, pass);
141
142            this.base.onreadystatechange = function() {
143                try { self.status = self.base.status; } catch (e) { }
144                try { self.statusText = self.base.statusText; } catch (e) { }
145                try { self.readyState = self.base.readyState; } catch (e) { }
146                try { self.responseText = self.base.responseText; } catch(e) { }
147                try { self.responseXML = self.base.responseXML; } catch(e) { }
148
149                if(self.onreadystatechange != null) {
150                    self.onreadystatechange.apply(this, arguments);
151                }
152            }
153        };
154
155        init_XMLHttpRequest.prototype.send = function(data) {
156            if(this.onsend != null) {
157                this.onsend.apply(this, arguments);
158            }
159
160            this.base.send(data);
161        };
162
163        init_XMLHttpRequest.prototype.abort = function() {
164            this.base.abort();
165        };
166
167        init_XMLHttpRequest.prototype.getAllResponseHeaders = function() {
168            return this.base.getAllResponseHeaders();
169        };
170
171        init_XMLHttpRequest.prototype.getResponseHeader = function(name) {
172            return this.base.getResponseHeader(name);
173        };
174
175        init_XMLHttpRequest.prototype.setRequestHeader = function(name, value) {
176            return this.base.setRequestHeader(name, value);
177        };
178
179        /** hook * */
180        window.XMLHttpRequest = init_XMLHttpRequest;
181    }
182
183    /** check if valid domain based on domainStrict * */
184    function isValidDomain(current, target) {
185        var result = false;
186
187        /** check exact or subdomain match * */
188        if(current == target) {
189            result = true;
190        } else if(false == false) {
191            if(target.charAt(0) == '.') {
192                result = current.endsWith(target);
193            } else {
194                result = current.endsWith('.' + target);
195            }
196        }
197
198        return result;
199    }
200
201    /** determine if uri/url points to valid domain * */
202    function isValidUrl(src) {
203        var result = false;
204
205        /** parse out domain to make sure it points to our own * */
206        if(src.substring(0, 7) == "http://" || src.substring(0, 8) == "https://") {
207            var token = "://";
208            var index = src.indexOf(token);
209            var part = src.substring(index + token.length);
210            var domain = "";
211
212            /** parse up to end, first slash, or anchor * */
213            for(i=0; i<part.length; i++) {
214                var character = part.charAt(i);
215
216                if(character == '/' || character == ':' || character == '#') {
217                    break;
218                } else {
219                    domain += character;
220                }
221            }
222
223            result = isValidDomain(document.domain, domain);
224            /** explicitly skip anchors * */
225        } else if(src.charAt(0) == '#') {
226            result = false;
227            /** ensure it is a local resource without a protocol * */
228        } else if(!src.startsWith("//") && (src.charAt(0) == '/' || src.indexOf(':') == -1)) {
229            result = true;
230        }
231
232        return result;
233    }
234
235    /** parse uri from url * */
236    function parseUri(url) {
237        var uri = "";
238        var token = "://";
239        var index = url.indexOf(token);
240        var part = "";
241
242        /**
243         * ensure to skip protocol and prepend context path for non-qualified
244         * resources (ex: "protect.html" vs
245         * "/Owasp.CsrfGuard.Test/protect.html").
246         */
247        if(index > 0) {
248            part = url.substring(index + token.length);
249        } else if(url.charAt(0) != '/') {
250            part = "/" + url;
251        } else {
252            part = url;
253        }
254
255        /** parse up to end or query string * */
256        var uriContext = (index == -1);
257
258        for(var i=0; i<part.length; i++) {
259            var character = part.charAt(i);
260
261            if(character == '/') {
262                uriContext = true;
263            } else if(uriContext == true && (character == '?' || character == '#')) {
264                uriContext = false;
265                break;
266            }
267
268            if(uriContext == true) {
269                uri += character;
270            }
271        }
272
273        return uri;
274    }
275
276    /** inject tokens as hidden fields into forms **/
277    function injectTokenForm(form, tokenName, tokenValue, pageTokens,injectGetForms) {
278
279        if (!injectGetForms) {
280            var method = form.getAttribute("method");
281
282            if ((typeof method != 'undefined') && method != null && method.toLowerCase() == "get") {
283                return;
284            }
285        }
286
287        var value = tokenValue;
288        var action = form.getAttribute("action");
289
290        if(action != null && isValidUrl(action)) {
291            var uri = parseUri(action);
292            value = pageTokens[uri] != null ? pageTokens[uri] : tokenValue;
293        }
294
295        var hidden = document.createElement("input");
296
297        hidden.setAttribute("type", "hidden");
298        hidden.setAttribute("name", tokenName);
299        hidden.setAttribute("value", value);
300
301        form.appendChild(hidden);
302    }
303
304    /** inject tokens as query string parameters into url **/
305    function injectTokenAttribute(element, attr, tokenName, tokenValue, pageTokens) {
306        var location = element.getAttribute(attr);
307
308        if(location != null && isValidUrl(location)) {
309            var uri = parseUri(location);
310            var value = (pageTokens[uri] != null ? pageTokens[uri] : tokenValue);
311
312            if(location.indexOf('?') != -1) {
313                location = location + '&' + tokenName + '=' + value;
314            } else {
315                location = location + '?' + tokenName + '=' + value;
316            }
317
318            try {
319                element.setAttribute(attr, location);
320            } catch (e) {
321                // attempted to set/update unsupported attribute
322            }
323        }
324    }
325
326    /** inject csrf prevention tokens throughout dom **/
327    function injectTokens(tokenName, tokenValue) {
328        /** obtain reference to page tokens if enabled **/
329        var pageTokens = {};
330
331        if(false == true) {
332            pageTokens = requestPageTokens();
333        }
334
335        /** iterate over all elements and injection token **/
336        var all = document.all ? document.all : document.getElementsByTagName('*');
337        var len = all.length;
338
339        for(var i=0; i<len; i++) {
340            var element = all[i];
341
342            /** inject into form **/
343            if(element.tagName.toLowerCase() == "form") {
344                if(true) {
345                    injectTokenForm(element, tokenName, tokenValue, pageTokens,false);
346
347                    /** adjust array length after addition of new element **/
348                    len = all.length;
349                }
350                if (false) {
351                    injectTokenAttribute(element, "action", tokenName, tokenValue, pageTokens);
352                }
353                /** inject into attribute **/
354            } else if(false) {
355                injectTokenAttribute(element, "src", tokenName, tokenValue, pageTokens);
356                injectTokenAttribute(element, "href", tokenName, tokenValue, pageTokens);
357            }
358        }
359    }
360
361    /** obtain array of page specific tokens **/
362    function requestPageTokens() {
363        var xhr = window.XMLHttpRequest ? new window.XMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
364        var pageTokens = {};
365
366        xhr.open("POST", "/csrf_js"+(typeof(resourceAccountIdRoutingURl)!="undefined"?"?"+resourceAccountIdRoutingURl:""), false);
367        xhr.send(null);
368
369        var text = xhr.responseText;
370        var name = "";
371        var value = "";
372        var nameContext = true;
373
374        for(var i=0; i<text.length; i++) {
375            var character = text.charAt(i);
376
377            if(character == ':') {
378                nameContext = false;
379            } else if(character != ',') {
380                if(nameContext == true) {
381                    name += character;
382                } else {
383                    value += character;
384                }
385            }
386
387            if(character == ',' || (i + 1) >= text.length) {
388                pageTokens[name] = value;
389                name = "";
390                value = "";
391                nameContext = true;
392            }
393        }
394
395        return pageTokens;
396    }
397
398
399    /**
400     * Only inject the tokens if the JavaScript was referenced from HTML that
401     * was served by us. Otherwise, the code was referenced from malicious HTML
402     * which may be trying to steal tokens using JavaScript hijacking
403     * techniques.
404     */
405    if(isValidDomain(document.domain, "zoomgov.com")) {
406        /** optionally include Ajax support * */
407        if(true == true) {
408            if(navigator.appName == "Microsoft Internet Explorer") {
409                hijackExplorer();
410            } else {
411                hijackStandard();
412            }
413
414            var xhr = window.XMLHttpRequest ? new window.XMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
415            var csrfToken = {};
416            xhr.open("POST", "/csrf_js"+(typeof(resourceAccountIdRoutingURl)!="undefined"?"?"+resourceAccountIdRoutingURl:""), false);
417            xhr.setRequestHeader("FETCH-CSRF-TOKEN", "1");
418            xhr.send(null);
419
420            var token_pair = xhr.responseText;
421            token_pair = token_pair.split(":");
422            var token_name = token_pair[0];
423            var token_value = token_pair[1];
424
425            XMLHttpRequest.prototype.onsend = function(data) {
426                if(isValidUrl(this.url)) {
427                    this.setRequestHeader("X-Requested-With", "XMLHttpRequest");
428                    this.setRequestHeader("X-Requested-With", "OWASP CSRFGuard Project");
429                    this.setRequestHeader(token_name, token_value);
430                }
431            };
432        }
433
434        /** update nodes in DOM after load **/
435        addEvent(window,'unload',EventCache.flush);
436        addEvent(window,'load', function() {
437            injectTokens(token_name, token_value);
438        });
439    } else {
440        alert("OWASP CSRFGuard JavaScript was included from within an unauthorized domain!");
441    }
442})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.