zoukankan      html  css  js  c++  java
  • 博客园自定义博客侧边栏公告的过滤漏洞

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

            来博客园已经有些日子了,博客早就申请了下来,在后台偶然看到了可以自定义博客的样式,觉得很有趣,犹记得上小学的时候新浪博客就支持自定义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 + "
    ")
            },
            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 + "
    "
            }
            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[sS]*?>)([sS]*?)</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 + "
    ")
            };
            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

  • 相关阅读:
    HDU 1058 Humble Numbers
    HDU 1160 FatMouse's Speed
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1003 Max Sum
    HDU 1297 Children’s Queue
    UVA1584环状序列 Circular Sequence
    UVA442 矩阵链乘 Matrix Chain Multiplication
    DjangoModels修改后出现You are trying to add a non-nullable field 'download' to book without a default; we can't do that (the database needs something to populate existing rows). Please select a fix:
    opencv做的简单播放器
    c++文件流输入输出
  • 原文地址:https://www.cnblogs.com/libook/p/3186762.html
Copyright © 2011-2022 走看看