• 博客园自定义博客侧边栏公告的过滤漏洞


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

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

  • 相关阅读:
    python 利用pyspark读取HDFS中CSV文件的指定列 列名重命名 并保存回HDFS
    python 利用pandas读取本地中CSV文件的指定列 列名重命名 并保存回本地
    CDH版本Hbase二级索引详细配置方案Solr key value index(二)中文分词
    CDH版本Hbase二级索引详细配置方案Solr key value index
    Seccon2017-pwn500-video_player
    Linux ASLR的实现
    0ctf2017-pages-choices
    33c3-pwn500-recurse
    关于C++中的string的小知识点
    Apache Kylin(三)Kylin上手
  • 原文地址:https://www.cnblogs.com/libook/p/3186762.html
Copyright © 2020-2023  润新知