温馨提示:本文章所提到的相关技术以及代码仅供学习交流,不可用来做违法或违反博客园相关规定的事情哦~而且本文章不许转载哦,请使用超链接。

 

        来博客园已经有些日子了,博客早就申请了下来,在后台偶然看到了可以自定义博客的样式,觉得很有趣,犹记得上小学的时候新浪博客就支持自定义CSS了,那时还很好奇:“CSS是什么?可以爆头和投手雷吗?”如今度过了i个快乐而又痛苦的日子,终于知道CSS是什么了(我有说我是在吐槽吗?)。

        好了,言归正传,首先引出一句话:“黑客是一种态度。”

        关于“黑客”一词的解释我稍后会发到Hack分类中,现在我们讲博客园的自定义样式。

        其他几个就不说了,基本上是限定在HTML和CSS代码上,我们说“自定义博客侧边栏公告”这一栏,我们可以在其中写javascript代码,比如如下一行:

<script type="text/javascript">
    document.write("你好!");
</script>

保存后看博客主页效果:

嘿嘿,下面我们来试试常玩的alert方法:

<script type="text/javascript">
    alert("你好!");
</script>

并没有在主页看到效果,回来看代码,发现输入框中的代码在提交后变成了:

<script type="text/javascript">
    ;
</script>

很显然,过滤程序将alert函数过滤掉了,不过这点难不倒我,还记得我们上面用到的document.write方法吗?我们可以这样来写:

<script type="text/javascript">
    var hehele2='<scr'+'ipt ty'+'pe="tex'+'t/java'+'script">'+'a'+'l'+'e'+'r'+'t'+'('+'"'+'呵呵了'+'"'+')'+';'+'</sc'+'ript>';
    document.write(hehele2);
</script>

测试结果如下:

呵呵了吧!其实分析了一下博客园的部分源代码大体情况是这样的:

        在输入框中写入代码点击“保存”后,后端程序会将用户所提交的代码进行一遍过滤,一些敏感代码会被使用正则表达式replace掉,就比如alert(*****)这样的代码;过滤后就写进数据库,在用户打开自己的博客首页的时候,会将数据库中的自定义代码读出来运行,这时候会有一个坏坏的jquery.writeCapture-min.js文件来检测当前页面的代码是否合法,一旦遇到非法代码就会抛出异常,让非法代码中断执行,比如:

<script type="text/javascript">
    var hehele2='<script type="text/javascript"></script>';
    document.write(hehele2);
</script>

这段代码,因为其中的“<script type="text/javascript">”被列为 非法代码,所以当保存并打开博客主页的时候会看到浏览器的Console中会出现异常:

我看了jquery.writeCapture-min.js这个文件,整理一下格式把代码贴在这,有兴趣的朋友可以研究一下:

(function(E, a) {
    var j = a.document;

    function A(Q) {
        var Z = j.createElement("div");
        j.body.insertBefore(Z, null);
        E.replaceWith(Z, '<script type="text/javascript">' + Q + "<\/script>")
    }
    E = E || (function(Q) {
        return {
            ajax: Q.ajax,
            $: function(Z) {
                return Q(Z)[0]
            },
            replaceWith: function(Z, ad) {
                var ac = Q(Z)[0];
                var ab = ac.nextSibling,
                    aa = ac.parentNode;
                Q(ac).remove();
                if (ab) {
                    Q(ab).before(ad)
                } else {
                    Q(aa).append(ad)
                }
            },
            onLoad: function(Z) {
                Q(Z)
            },
            copyAttrs: function(af, ab) {
                var ad = Q(ab),
                    aa = af.attributes;
                for (var ac = 0, Z = aa.length; ac < Z; ac++) {
                    if (aa[ac] && aa[ac].value) {
                        try {
                            ad.attr(aa[ac].name, aa[ac].value)
                        } catch (ae) {}
                    }
                }
            }
        }
    })(a.jQuery);
    E.copyAttrs = E.copyAttrs ||
    function() {};
    E.onLoad = E.onLoad ||
    function() {
        throw "error: autoAsync cannot be used without jQuery or defining writeCaptureSupport.onLoad"
    };

    function P(ab, aa) {
        for (var Z = 0, Q = ab.length; Z < Q; Z++) {
            if (aa(ab[Z]) === false) {
                return
            }
        }
    }
    function v(Q) {
        return Object.prototype.toString.call(Q) === "[object Function]"
    }
    function p(Q) {
        return Object.prototype.toString.call(Q) === "[object String]"
    }
    function u(aa, Z, Q) {
        return Array.prototype.slice.call(aa, Z || 0, Q || aa && aa.length)
    }
    function D(ab, aa) {
        var Q = false;
        P(ab, Z);

        function Z(ac) {
            return !(Q = aa(ac))
        }
        return Q
    }
    function L(Q) {
        this._queue = [];
        this._children = [];
        this._parent = Q;
        if (Q) {
            Q._addChild(this)
        }
    }
    L.prototype = {
        _addChild: function(Q) {
            this._children.push(Q)
        },
        push: function(Q) {
            this._queue.push(Q);
            this._bubble("_doRun")
        },
        pause: function() {
            this._bubble("_doPause")
        },
        resume: function() {
            this._bubble("_doResume")
        },
        _bubble: function(Z) {
            var Q = this;
            while (!Q[Z]) {
                Q = Q._parent
            }
            return Q[Z]()
        },
        _next: function() {
            if (D(this._children, Q)) {
                return true
            }
            function Q(aa) {
                return aa._next()
            }
            var Z = this._queue.shift();
            if (Z) {
                Z()
            }
            return !!Z
        }
    };

    function i(Q) {
        if (Q) {
            return new L(Q)
        }
        L.call(this);
        this.paused = 0
    }
    i.prototype = (function() {
        function Q() {}
        Q.prototype = L.prototype;
        return new Q()
    })();
    i.prototype._doRun = function() {
        if (!this.running) {
            this.running = true;
            try {
                while (this.paused < 1 && this._next()) {}
            } finally {
                this.running = false
            }
        }
    };
    i.prototype._doPause = function() {
        this.paused++
    };
    i.prototype._doResume = function() {
        this.paused--;
        this._doRun()
    };

    function M() {}
    M.prototype = {
        _html: "",
        open: function() {
            this._opened = true;
            if (this._delegate) {
                this._delegate.open()
            }
        },
        write: function(Q) {
            if (this._closed) {
                return
            }
            this._written = true;
            if (this._delegate) {
                this._delegate.write(Q)
            } else {
                this._html += Q
            }
        },
        writeln: function(Q) {
            this.write(Q + "\n")
        },
        close: function() {
            this._closed = true;
            if (this._delegate) {
                this._delegate.close()
            }
        },
        copyTo: function(Q) {
            this._delegate = Q;
            Q.foobar = true;
            if (this._opened) {
                Q.open()
            }
            if (this._written) {
                Q.write(this._html)
            }
            if (this._closed) {
                Q.close()
            }
        }
    };
    var e = (function() {
        var Q = {
            f: j.getElementById
        };
        try {
            Q.f.call(j, "abc");
            return true
        } catch (Z) {
            return false
        }
    })();

    function I(Q) {
        P(Q, function(Z) {
            var aa = j.getElementById(Z.id);
            if (!aa) {
                l("<proxyGetElementById - finish>", "no element in writen markup with id " + Z.id);
                return
            }
            P(Z.el.childNodes, function(ab) {
                aa.appendChild(ab)
            });
            if (aa.contentWindow) {
                a.setTimeout(function() {
                    Z.el.contentWindow.document.copyTo(aa.contentWindow.document)
                }, 1)
            }
            E.copyAttrs(Z.el, aa)
        })
    }
    function s(Z, Q) {
        if (Q && Q[Z] === false) {
            return false
        }
        return Q && Q[Z] || o[Z]
    }
    function x(Z, ai) {
        var ae = [],
            ad = s("proxyGetElementById", ai),
            ag = s("writeOnGetElementById", ai),
            Q = {
                write: j.write,
                writeln: j.writeln,
                finish: function() {},
                out: ""
            };
        Z.state = Q;
        j.write = ah;
        j.writeln = aa;
        if (ad || ag) {
            Q.getEl = j.getElementById;
            j.getElementById = ab;
            if (ag) {
                findEl = af
            } else {
                findEl = ac;
                Q.finish = function() {
                    I(ae)
                }
            }
        }
        function ah(aj) {
            Q.out += aj
        }
        function aa(aj) {
            Q.out += aj + "\n"
        }
        function ac(ak) {
            var aj = j.createElement("div");
            ae.push({
                id: ak,
                el: aj
            });
            aj.contentWindow = {
                document: new M()
            };
            return aj
        }
        function af(al) {
            var aj = E.$(Z.target);
            var ak = j.createElement("div");
            aj.parentNode.insertBefore(ak, aj);
            E.replaceWith(ak, Q.out);
            Q.out = "";
            return e ? Q.getEl.call(j, al) : Q.getEl(al)
        }
        function ab(ak) {
            var aj = e ? Q.getEl.call(j, ak) : Q.getEl(ak);
            return aj || findEl(ak)
        }
        return Q
    }
    function V(Q) {
        j.write = Q.write;
        j.writeln = Q.writeln;
        if (Q.getEl) {
            j.getElementById = Q.getEl
        }
        return Q.out
    }
    function N(Q) {
        return Q && Q.replace(/^\s*<!(\[CDATA\[|--)/, "").replace(/(\]\]|--)>\s*$/, "")
    }
    function b() {}
    function d(Z, Q) {
        console.error("Error", Q, "executing code:", Z)
    }
    var l = v(a.console && console.error) ? d : b;

    function S(aa, Z, Q) {
        var ab = x(Z, Q);
        try {
            A(N(aa))
        } catch (ac) {
            l(aa, ac)
        } finally {
            V(ab)
        }
        return ab
    }
    function O(Z) {
        var Q = /^(\w+:)?\/\/([^\/?#]+)/.exec(Z);
        return Q && (Q[1] && Q[1] != location.protocol || Q[2] != location.host)
    }
    function T(Q) {
        return new RegExp(Q + "=(?:([\"'])([\\s\\S]*?)\\1|([^\\s>]+))", "i")
    }
    function k(Q) {
        var Z = T(Q);
        return function(aa) {
            var ab = Z.exec(aa) || [];
            return ab[2] || ab[3]
        }
    }
    var r = /(<script[\s\S]*?>)([\s\S]*?)<\/script>/ig,
        n = T("src"),
        X = k("src"),
        q = k("type"),
        Y = k("language"),
        C = "__document_write_ajax_callbacks__",
        B = "__document_write_ajax_div-",
        g = "window['" + C + "']['%d']();",
        m = a[C] = {},
        w = '<script type="text/javascript">' + g + "<\/script>",
        H = 0;

    function c() {
        return (++H).toString()
    }
    function G(Z, aa) {
        var Q;
        if (v(Z)) {
            Q = Z;
            Z = null
        }
        Z = Z || {};
        Q = Q || Z && Z.done;
        Z.done = aa ?
        function() {
            aa(Q)
        } : Q;
        return Z
    }
    var z = new i();
    var y = [];
    var f = window._debugWriteCapture ?
    function() {} : function(Q, aa, Z) {
        y.push({
            type: Q,
            src: aa,
            data: Z
        })
    };
    var K = window._debugWriteCapture ?
    function() {} : function() {
        y.push(arguments)
    };

    function W(Q) {
        var Z = c();
        m[Z] = function() {
            Q();
            delete m[Z]
        };
        return Z
    }
    function J(Q) {
        return w.replace(/%d/, W(Q))
    }
    function R(ac, ag, aa, ae) {
        var ad = aa && new i(aa) || z;
        ag = G(ag);
        var ab = s("done", ag);
        var Q = "";
        var Z = s("fixUrls", ag);
        if (!v(Z)) {
            Z = function(ah) {
                return ah
            }
        }
        if (v(ab)) {
            Q = J(function() {
                ad.push(ab)
            })
        }
        return ac.replace(r, af) + Q;

        function af(aj, av, ai) {
            var an = X(av),
                am = q(av) || "",
                aB = Y(av) || "",
                aA = (!am && !aB) || am.toLowerCase().indexOf("javascript") !== -1 || aB.toLowerCase().indexOf("javascript") !== -1;
            f("replace", an, aj);
            if (!aA) {
                return aj
            }
            var aw = W(ap),
                ao = B + aw,
                au, al = {
                    target: "#" + ao,
                    parent: ae
                };

            function ap() {
                ad.push(au)
            }
            if (an) {
                an = Z(an);
                av = av.replace(n, "");
                if (O(an)) {
                    au = az
                } else {
                    if (s("asyncAll", ag)) {
                        au = ay()
                    } else {
                        au = at
                    }
                }
            } else {
                au = ax
            }
            function ax() {
                ah(ai)
            }
            function at() {
                E.ajax({
                    url: an,
                    type: "GET",
                    dataType: "text",
                    async: false,
                    success: function(aC) {
                        ah(aC)
                    }
                })
            }
            function ak(aE, aC, aD) {
                l("<XHR for " + an + ">", aD);
                ad.resume()
            }
            function aq() {
                return J(function() {
                    ad.resume()
                })
            }
            function ay() {
                var aE, aD;

                function aC(aG, aF) {
                    if (!aE) {
                        aD = aG;
                        return
                    }
                    try {
                        ah(aG, aq())
                    } catch (aH) {
                        l(aG, aH)
                    }
                }
                E.ajax({
                    url: an,
                    type: "GET",
                    dataType: "text",
                    async: true,
                    success: aC,
                    error: ak
                });
                return function() {
                    aE = true;
                    if (aD) {
                        ah(aD)
                    } else {
                        ad.pause()
                    }
                }
            }
            function az(aC) {
                var aE = x(al, ag);
                ad.pause();
                f("pause", an);
                E.ajax({
                    url: an,
                    type: "GET",
                    dataType: "script",
                    success: aD,
                    error: ak
                });

                function aD(aH, aG, aF) {
                    f("out", an, aE.out);
                    ar(V(aE), J(aE.finish) + aq());
                    f("resume", an)
                }
            }
            function ah(aD, aC) {
                var aE = S(aD, al, ag);
                aC = J(aE.finish) + (aC || "");
                ar(aE.out, aC)
            }
            function ar(aD, aC) {
                E.replaceWith(al.target, R(aD, null, ad, al) + (aC || ""))
            }
            return '<div style="display: none" id="' + ao + '"></div>' + av + g.replace(/%d/, aw) + "<\/script>"
        }
    }
    function F(Z, aa) {
        var Q = z;
        P(Z, function(ab) {
            Q.push(ac);

            function ac() {
                ab.action(R(ab.html, ab.options, Q), ab)
            }
        });
        if (aa) {
            Q.push(aa)
        }
    }
    function U(Q) {
        var Z = Q;
        while (Z && Z.nodeType === 1) {
            Q = Z;
            Z = Z.lastChild;
            while (Z && Z.nodeType !== 1) {
                Z = Z.previousSibling
            }
        }
        return Q
    }
    function h(Q) {
        var aa = j.write,
            ad = j.writeln,
            Z, ab = [];
        j.writeln = function(ae) {
            j.write(ae + "\n")
        };
        var ac;
        j.write = function(af) {
            var ae = U(j.body);
            if (ae !== Z) {
                Z = ae;
                ab.push(ac = {
                    el: ae,
                    out: []
                })
            }
            ac.out.push(af)
        };
        E.onLoad(function() {
            var ah, ak, af, aj, ai;
            Q = G(Q);
            ai = Q.done;
            Q.done = function() {
                j.write = aa;
                j.writeln = ad;
                if (ai) {
                    ai()
                }
            };
            for (var ag = 0, ae = ab.length; ag < ae; ag++) {
                ah = ab[ag].el;
                ak = j.createElement("div");
                ah.parentNode.insertBefore(ak, ah.nextSibling);
                af = ab[ag].out.join("");
                aj = ae - ag === 1 ? R(af, Q) : R(af);
                E.replaceWith(ak, aj)
            }
        })
    }
    var t = "writeCapture";
    var o = a[t] = {
        _original: a[t],
        fixUrls: function(Q) {
            return Q.replace(/&amp;/g, "&")
        },
        noConflict: function() {
            a[t] = this._original;
            return this
        },
        debug: y,
        proxyGetElementById: false,
        _forTest: {
            Q: i,
            GLOBAL_Q: z,
            $: E,
            matchAttr: k,
            slice: u,
            capture: x,
            uncapture: V,
            captureWrite: S
        },
        replaceWith: function(Q, aa, Z) {
            E.replaceWith(Q, R(aa, Z))
        },
        html: function(Q, ab, Z) {
            var aa = E.$(Q);
            aa.innerHTML = "<span/>";
            E.replaceWith(aa.firstChild, R(ab, Z))
        },
        load: function(Q, aa, Z) {
            E.ajax({
                url: aa,
                dataType: "text",
                type: "GET",
                success: function(ab) {
                    o.html(Q, ab, Z)
                }
            })
        },
        autoAsync: h,
        sanitize: R,
        sanitizeSerial: F
    }
})(this.writeCaptureSupport, this);
(function(g, d, n) {
    var c = {
        html: h
    };
    g.each(["append", "prepend", "after", "before", "wrap", "wrapAll", "replaceWith", "wrapInner"], function() {
        c[this] = i(this)
    });

    function a(q) {
        return Object.prototype.toString.call(q) == "[object String]"
    }
    function p(u, t, s, r) {
        if (arguments.length == 0) {
            return o.call(this)
        }
        var q = c[u];
        if (u == "load") {
            return l.call(this, t, s, r)
        }
        if (!q) {
            j(u)
        }
        return b.call(this, t, s, q)
    }
    g.fn.writeCapture = p;
    var k = "__writeCaptureJsProxied-fghebd__";

    function o() {
        if (this[k]) {
            return this
        }
        var r = this;

        function q() {
            var t = this,
                s = false;
            this[k] = true;
            g.each(c, function(v) {
                var u = r[v];
                if (!u) {
                    return
                }
                t[v] = function(y, x, w) {
                    if (!s && a(y)) {
                        try {
                            s = true;
                            return p.call(t, v, y, x, w)
                        } finally {
                            s = false
                        }
                    }
                    return u.apply(t, arguments)
                }
            });
            this.pushStack = function() {
                return o.call(r.pushStack.apply(t, arguments))
            };
            this.endCapture = function() {
                return r
            }
        }
        q.prototype = r;
        return new q()
    }
    function b(t, s, u) {
        var q, r = this;
        if (s && s.done) {
            q = s.done;
            delete s.done
        } else {
            if (g.isFunction(s)) {
                q = s;
                s = null
            }
        }
        d.sanitizeSerial(g.map(this, function(v) {
            return {
                html: t,
                options: s,
                action: function(w) {
                    u.call(v, w)
                }
            }
        }), q &&
        function() {
            q.call(r)
        } || q);
        return this
    }
    function h(q) {
        g(this).html(q)
    }
    function i(q) {
        return function(r) {
            g(this)[q](r)
        }
    }
    function l(t, s, v) {
        var r = this,
            q, u = t.indexOf(" ");
        if (u >= 0) {
            q = t.slice(u, t.length);
            t = t.slice(0, u)
        }
        if (g.isFunction(v)) {
            s = s || {};
            s.done = v
        }
        return g.ajax({
            url: t,
            type: s && s.type || "GET",
            dataType: "html",
            data: s && s.params,
            complete: f(r, s, q)
        })
    }
    function f(r, s, q) {
        return function(u, t) {
            if (t == "success" || t == "notmodified") {
                var v = m(u.responseText, q);
                b.call(r, v, s, h)
            }
        }
    }
    var e = /jquery-writeCapture-script-placeholder-(\d+)-wc/g;

    function m(s, r) {
        if (!r || !s) {
            return s
        }
        var t = 0,
            q = {};
        return g("<div/>").append(s.replace(/<script(.|\s)*?\/script>/g, function(u) {
            q[t] = u;
            return "jquery-writeCapture-script-placeholder-" + (t++) + "-wc"
        })).find(r).html().replace(e, function(u, v) {
            return q[v]
        })
    }
    function j(q) {
        throw "invalid method parameter " + q
    }
    g.writeCapture = d
})(jQuery, writeCapture.noConflict());
jquery.writeCapture-min.js

在这个文件中,映入眼帘的是闭包结构,什么?不知道闭包结构?其实我也刚刚知道而已,大体了解了一下,大概是这个意思:

(function(E, a){
    var s="aaa";
    function f2(){
        s+="bbb";
    }
    return f2;
}
)(f2());//这里相当于f2被浏览器对象当作全局变量进行调用

        用括号的格式声明一个匿名函数,在匿名函数中有一些变量和一个子函数f2,匿名函数返回子函数f2,而f2同时又被当作全局变量调用,于是发生了一个很有趣的事情:f2被当作全局变量,所以不会被GC回收,而匿名函数因为被子函数f2访问,所以也不会被GC回收,导致这个匿名函数常驻内存之中,但由于没有名字,所以我们无法再找到并调用这个匿名函数,只能通过预先在f2中所写的语句来对匿名函数中的变量进行操作。基本上效果是:1.匿名函数及其中的局部变量被隐藏。2.匿名函数及其子成员常驻内存,直到页面关闭。(本段抛砖引玉啦~~~)

        就是这个可恶的家伙导致我接下来的工作很难开展。

        销毁原有的jQuery:

<script type="text/javascript">
    //删除旧jQuery
    $=jQuery;
    delete $;
    delete jQuery;
</script>

        接下来的工作很难开展了,都是因为那个jquery.writeCapture-min.js,怎么样才能销毁这个文件产生的对象呢?有待研究。

 

  本文章系受著作权法保护,未经著作人同意,不得盗用;使用或引用本文章内容请注明作者名、原地址:书中叶http://www.cnblogs.com/libook

posted on 2013-07-12 19:28  书中叶  阅读(1826)  评论(15编辑  收藏  举报