• CTF之PHP特性与绕过


    目录

    1、PHP中的 $_SERVER 函数

    2、PHP中的三元运算符

    3、PHP中的strpos() 函数

    4、PHP中的数组

    5、PHP中的非法参数名传参


    知识铺垫:

    1、PHP中的 $_SERVER 函数

    $_SERVER存储当前服务器信息,包括:

    1. $_SERVER["QUERY_STRING"]:查询(query)的字符串
    2. $_SERVER["REQUEST_URI"]:访问此页面所需的URI
    3. $_SERVER["SCRIPT_NAME"]:包含当前脚本的路径
    4. $_SERVER["PHP_SELF"]:当前正在执行脚本的文件名

    比如我们访问页面:https://www.xxx.com/index.php?id=1 ,则:

    1. $_SERVER["QUERY_STRING"] = "id=1" # 获取查询语句,即?后面的值
    2. $_SERVER["REQUEST_URI"] = "/index.php?id=1" # 获取https://www.xxx.com后面的内容,包括/
    3. $_SERVER["SCRIPT_NAME"] = "/index.php" # 获取当前脚本的路径
    4. $_SERVER["PHP_SELF"] = "/index.php" # 获取当前正在执行脚本的文件名

    2、PHP中的三元运算符

    形如 XXXX?XX:xx

    如果条件XXXX成立,则执行冒号前边的XX,否则执行冒号后面的xx

    比如:isset($_GET['id']) ? $_GET['id'] : 1;

    isset()函数用于检查变量是否设置,如果设置了,则 id=$_GET['id'],否则 id=1

    3、PHP中的strpos() 函数

    该函数用于查找字符串在另一字符串中第一次出现的位置,并且对大小写敏感。

    用法:strpos(string,find,start)

    参数描述
    string必需。规定要搜索的字符串。
    find必需。规定要查找的字符串。
    start可选。规定在何处开始搜索。

    查找后会返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回 FALSE。

    4、PHP中的数组

    数组在进行string强制转换时,会将数组转换为NULL类型;

    无论多大的数字,对于数组而言总是比数组小的。

    5、PHP中的非法参数名传参

    在给参数传值时,如果参数名中存在非法字符,比空格和点,则参数名中的点和空格等非法字符都会被替换成下划线。

    并且,在PHP8之前,如果参数中出现中括号[,那么中括号会被转换成下划线_,但是会出现转换错误,导致如果参数名后面还存在非法字符,则不会继续转换成下划线。也就是说,我们可以刻意拼接中括号制造这种错误,来保留后面的非法字符不被替换,因为中括号导致只会替换一次。

    综合上述知识,来看一道例题:

    1. highlight_file(__FILE__);
    2. ini_set("display_error", false);
    3. error_reporting(0);
    4. $str = isset($_GET['A_A'])?$_GET['A_A']:'A_A';
    5. if (strpos($_SERVER['QUERY_STRING'], "A_A") !==false) {
    6. echo 'A_A,have fun';
    7. }
    8. elseif ($str<9999999999) {
    9. echo 'A_A,too small';
    10. }
    11. elseif ((string)$str>0) {
    12. echo 'A_A,too big';
    13. }
    14. else{
    15. echo file_get_contents('flag.php');
    16. }
    17. ?>

    构造payload:

    ?A.A[]=1

    关于payload的解释:

    1、A.A用于绕过$_SERVER["QUERY_STRING"]

    A.A被传到URL中是A.A,但是到了php里面则会被转换为A_A,即保证了参数的传递,也避免了被strpos函数查找到;(strpos($_SERVER['QUERY_STRING'], "A_A") !==false)则是要求传入的A_A在http..../?后面的值里找不到,找不到则会返回False,false!==false并不成立,才会继续执行elseif里的语句。

    2、这里使用数组,绕过了elseif ($str<9999999999) 和 elseif ((string)$str>0) 

    数组大于任何一个数,并且进行string强制转换时,会将数组转换为NULL类型,即返回0,

    0并不大于0,不符合条件,因此会继续执行后面的语句。

    关于strpos函数还有一个常见的就是利用换行(%0a)绕过

  • 相关阅读:
    springboot海纳部门人事管理系统毕业设计源码
    jsencrypt 公私钥解加密
    反欺诈模型常用开发工具
    xxl-job环境搭建详细
    【Linux网络编程】Socket-UDP实例
    数据结构— —双向链表
    vue2+elementUI,vue3+elementPlus解决form中的下拉列表回写显示id,不显示label
    图像的表示方法
    Linux高性能服务器编程 学习笔记 第一章 TCP/IP协议族
    【算法与数据结构】回溯算法、贪心算法、动态规划、图论(笔记三)
  • 原文地址:https://blog.csdn.net/Myon5/article/details/134159586