XNUCA 部分 write up

xnuca的游戏体验并不是很好,首先感觉有搅屎的嫌疑,其次,下午到比赛结束平台就陷入半崩溃局面这一度让我很是抓狂,另外,题量太大,基本上都是搜poc然后直接打,,,总而言之,可能因为我是个彩笔2333

言归正传,我还是把xnuca里的ctf题记录一下吧。

web 你喜欢颜文字吗

貌似在重置密码时重置拿到flag

web 让你无语的md5

题目中表示数据库用的latin1的编码方式,而另外一人则set了utf-8,这样可以用admin%2c绕过,原理是在utf-8的编码方式允许汉字字符,但是在latin1编码中会将%2c作为无用字符舍去,于是便可以进行绕过。

web x-nuca 2017 secrets

一扫就炸, 不做了

web Pav1和xxxx.avi

ffmpeg的一个洞漏洞,任意文件读取。 原理在这里:http://www.freebuf.com/column/142775.html 通过搜到的poc来构造文件,从而实现文件泄露

web lucky number calc

进入题目以后就只有一个输入框,抓包分析后得到<user><name>123</name></user>,很明确的知道这代考查的是xxe,直接构造payload,得到源码还是不行2333

最后,还是学长在/etc/host中找到了flag。

web xblog

存在www.zip 其中存在源码 对源码进行分析 首先有一个register的函数

<?php
include_once("common.php");
$dbh = new PDO(DSN, DB_USER, DB_PASSWD);
$sql = "select * from user where username = :username";
$sth = $dbh->prepare($sql);
$sth->execute(array(':username'=>$username));
$res = $sth->fetch(PDO::FETCH_ASSOC);
if($res !== false) {
    header("Location: error.php?msg=username%20has%20been%20used!");
    die();
}
$sql = "insert into user (username, password, role) values(:username, :password, 1)";
$sth = $dbh->prepare($sql);
$res = $sth->execute(array(':username'=>$username, ':password'=>$password));
if($res === false) {
    header("Location: error.php?msg=register%20error!");
    die();
}

$sql = "select * from user where username = :username and password = :password";
$sth = $dbh->prepare($sql);
$sth->execute(array(':username'=>$username, ':password' => $password));
$res = $sth->fetch(PDO::FETCH_ASSOC);
if($res === false) {
    header("Location: error.php?msg=register%20error!");
    die();
}
$userinfo["id"] = $res["id"];
$userinfo["username"] = $username;
$userinfo["password"] = $password;
$_SESSION["userinfo"] = $userinfo;
$userinfo["role"] = $res["role"];
header("Location: index.php");
?>

changepass.php

<?php
include_once("common.php");
if(!isset($_SESSION["userinfo"])) {
    header("Location: login.php");
    die();
}
$userinfo = $_SESSION["userinfo"];
if($old_pass = $userinfo['password']) {
    if($userinfo["id"] == 1) {
        echo "flag{xxx}";
        die();
    }
    $dbh = new PDO(DSN, DB_USER, DB_PASSWD);
    $sql = "update user set password = :password where id=:id";
    $sth = $dbh->prepare($sql);
    $res = $sth->execute((array(':password'=>$new_pass, ':id'=>$userinfo['id'])));
    if($res === false) {
        header("Location: error.php?msg=changepass%20error!");
        die();
    }
    $userinfo["password"] = $new_pass;
    $_SESSION['userinfo'] = $userinfo;
    header("Location: index.php");
} else {
    header("Location: error.php?msg=invalid%20old%20pass!");
    die();
}
?>

可以看到如果id=1即可echo出flag 在common.php中,foreach先取出cookie,post最后get,如果有重复直接进行覆盖,最后由session起决定性作用。 正常来说,应该直接传入userinfo[id]=1,但是由于session中有重名变量,所以大概需要一些trick来看一下。 如果我们在session start之前,将userinfo作为字符串传入,那么$userinfo会将其变成字符数组,里面没有id这个键,于是$userinfo['id']就跟$userinfo[0]等同,userinfo="$res['id']",只改变第一个字符,接下来的变量赋值,都只改变了第一个字符,所以最后字符由res['role']构成,那么我们使其为一,就可以echo出flag了 payload:userinfo["id"]=userinfo[0]=res["role"]=1