CTF中PHP常见漏洞及利用(未完待续)

本文详细探讨了PHP中的弱类型漏洞及其利用,包括数组比较、布尔类型问题和弱类型函数的利用,如md5()和sha1()。还介绍了变量覆盖漏洞、正则表达式和PHP伪协议在文件包含漏洞中的作用,如php://input和php:filter。此外,还提到了执行系统外部命令的函数和PHP别名。
摘要由CSDN通过智能技术生成

一、 PHP弱类型漏洞及其利用

先看一下弱类型的定义:

PHP是弱类型语言,不需要明确的定义变量的类型,变量的类型根据使用时的上下文所决定,也就是变量会根据不同表达式所需要的类型自动转换,比如求和,PHP会将两个相加的值转为long、double再进行加和。每种类型转为另外一种类型都有固定的规则,当某个操作发现类型不符时就会按照这个规则进行转换,这个规则正是弱类型实现的基础。

1.1 基本弱类型漏洞

1.1.1 数组比较

  • 在php手册中写道,当数组(array)与任何非数组进行比较时,数组总是最大的,所以有以下结果:

      var_dump([]>0);		//bool(true)
      var_dump([]>9999);	//bool(true)
      var_dump([]>'a');		//bool(true) #数组大于字符串
      var_dump([[]]>[]);	//bool(true)  #自然二位数组大于一维数组
    

1.1.2 bool类型的true比较

  • bool类型的true跟任意字符可以弱类型相等

      var_dump(true == 'a');		//bool(true)
    

1.1.3 =====的区别

==
  • 在进行比较时,向将两边的类型转化成相同类型再进行比较,如果涉及到数值内容的字符串,则字符串会被转化成数值(通过intval()函数),并且按照数值大小进行比较(><同理)。

    补充

    1. “根据php手册中所讲,字符串的开头决定了它转换后的值,如果该字符串以合法的数值开始,则使用该合法数值,否则其值为0”

    2. 如果字符创中没有包含.eE并且其数值在整形范围内,该字符被当做int来取值,其他所有情况都被作为float来取值。

    3. 0e开头的字符串被认为是科学技术计数法,且0e开头的数值为0

    4. 当一个整形与其他类型进行比较时,会先把其他类型进行intval()后再进行比较

    所以有如下结果:

      var_dump(1 == '1');		//bool(true)
      var_dump(1 == '1a');		//bool(true)
      var_dump(0 == '0exxx');	//bool(true)
      var_dump(0 == 'a1');		//bool(true)
      
      var_dump(1 + '1');		//int(2)
      var_dump(1 + '1a');		//int(2)
      var_dump(1 + '0exxx');	//int(1)
      var_dump(1 + 'a1');		//int(1)
    
===
  • 先判断两边类型是否相同,再比较大小。

    ===是防止了==弱类型比较漏洞,弱两边类型不同,则直接false而不会再进行比较。

      var_dump(1 === '1');		//bool(false)
      var_dump(1 === '1a');		//bool(false)
      var_dump(0 === '0exx');	//bool(false)
      var_dump(0 === 'a1');		//bool(false)
    

1.2 弱类型的函数漏洞利用

1.2.1 md5()sha1()函数

  • 函数介绍
    md5()函数计算字符串的MD5散列,使用RSA数据安全,包括MD5报文摘要算法。

    语法:md5(string,raw)
    在这里插入图片描述
    md5 和 sha1 无法处理数组,但是 php 没有抛出异常,直接返回 fasle。

      sha1([]) === false
      md5([]) === false
    
  • md5()应用

    1. md5()绕过==

    PHP在处理哈希字符串时,会利用!===来对哈希值进行比较,如上所示它把每一个以“0e”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都以“0e”开头,那么PHP将会认为他们相同,都是0。

    如下例:

      var_dump(md5('QNKCDZO') == md5(240610708))		//bool(true)
      var_dump(md5('QNKCDZO') === md5(240610708))	//bool(false)
    

    上面两个值可使md5()的开头为0e,通过==弱类型比较可输出‘yes’,但无法通过===

    常用md5()开头为“0e”的字符:

      md5('QNKCDZO')			//0e830400451993494058024219903391
      md5('240610708')			//0e462097431906509019562988736854
      md5('s878926199a')		//0e545993274517709034328855841020
      md5('s155964671a')		//0e342768416822451524974117254469
      md5('s214587387a')		//0e848240448830537924465865611904
      md5('s878926199a')		//0e545993274517709034328855841020
      md5('s1091221200a')		//0e940624217856561557816327384675
      md5('s1885207154a')		//0e509367213418206700842008763514
    
    1. md5([])绕过===

    由于md5()函数不能处理数组,所以在md5()遇到数组时会警告并且返回null,然而可以忽略警告并通过数组绕过===,如下:

      var_dump(@md5([]) == @md5([]))	//bool(true)
      var_dump(@md5([]) === @md5([]))	//bool(true),@表示忽略警告
      var_dump(null === null);		//bool(true)
    
    1. md5()函数sql绕过

    md5 和 sha1 支持第二个参数,如果为 true,则会将 hash 后的 16 进制字符串以 16 进制转成字符串的形式返回,如果在 SQL 语句中这样写,会存在注入的问题。

    提供一个字符串:ffifdyop,md5后,276f722736c95d99e921722cf9ed621c
    再转成字符串:'or'6É]™é!r,ùíb,即md5('ffifdyop',true) = 'or'6É]™é!r,ùíb

      // 可以实现绕过
      $password = "ffifdyop";
      $sql = "SELECT * FROM admin WHERE pass = '".md5($password,true)."'";
      var_dump($sql);
    
  • sha1()函数

    sha1()与md5()基本原理相同,所以此处仅列出sha1()开头为“0e”的字符串。

      sha1('aaroZmOk')	//0e66507019969427134894567494305185566735
      sha1('aaK1STfY')	//0e76658526655756207688271159624026011393
      sha1('aaO8zKZF')	//0e89257456677279068558073954252716165668
      sha1('aa3OFF9m')	//0e36977786278517984959260394024281014729
    

1.2.2 strcmp()strcasecmp()函数

  • strcmp(string1, string2)strcasecmp(string1, string2)

    比较两个字符串,前者不区分大小写,后者区分大小写。若string1 > string2,返回> 0;若string1 < string2,返回< 0;若string1 = string2,返回0。然而该函数无法处理数组,当出现数组时,返回null。(下例中@表示忽略警告)

      var_dump(@strcmp([],1));				//NULL
      var_dump(@strcmp([],'flag') == 0);	//bool(true)
      var_dump(@strcmp([],'flag') === 0);	//bool(false)
    

1.2.3 switch()函数

  • switch()语句用于根据多个不同的条件执行不同的动作。

      $n = '2a';
      switch($n){
      	case 2:
      		echo 'yes';
      		break;
      	default:
      		echo 'no';
      		break;
      }
    
      //yes
    

    此例中,为数值类型的case,switch会将参数转换为数值(此处可理解为通过==进行比较。)。

1.2.4 is_numeric()函数

  • is_numeric()函数判断变量是否为数字&#

### 回答1: CTF 比赛常见的文件包含漏洞的做法包括: 1. 在文件嵌入恶意代码,例如 PHP 文件嵌入 PHP 后门。 2. 在文件嵌入解压后执行恶意代码的压缩包,例如在一个图片文件嵌入 zip 压缩包。 3. 在文件包含指向恶意网站的链接。 4. 在文件包含指向恶意文件的路径,例如在一个文本文件包含指向加密垃圾文件的路径。 最常见的文件包含漏洞的类型是 PHP 和其他服务器端脚本语言,因为它们可以在服务器上执行恶意代码。但也有可能在其他类型的文件发现文件包含漏洞,例如 PDF、Office 文档等。 ### 回答2: 在CTF比赛,文件包含漏洞是一种常见的攻击方式。文件包含漏洞主要出现在动态网页,它指的是在文件引用其他文件时,未经有效的过滤或验证,导致恶意用户可以通过构造特定的请求,获取系统的敏感信息或执行任意代码。 首先,一个常见的做法是利用路径遍历来获取敏感文件。攻击者通过构造包含../的文件路径,让服务器读取到位于网站根目录之外的敏感文件。例如,攻击者可能会访问config.php,其包含数据库的用户名和密码。 其次,攻击者也可能利用文件包含漏洞实现远程文件包含,进一步扩大攻击面。如在引入文件的地方,通过传递网络路径的方式,将远程服务器上的恶意文件包含到受影响的网站上,从而执行任意代码。这种方式被称为远程文件包含(RFI)攻击。 除此之外,攻击者还可以通过利用用户的输入来实现文件包含漏洞。在某些情况下,网站可能会动态地引入用户提交的内容,例如通过GET或POST参数。攻击者可以构造恶意的参数值,使得网站将用户输入的内容当作文件路径进行解析,从而执行恶意代码或访问敏感文件。 为了防止文件包含漏洞,开发者需要进行严格的输入验证和过滤。例如,可以使用白名单机制,只允许系统访问指定目录内的文件。此外,对于用户输入的参数,要进行充分的校验和过滤,确保其只包含允许的字符和路径。 总之,在CTF比赛常见的文件包含漏洞攻击方式主要包括路径遍历、远程文件包含和用户输入导致的漏洞。为了保护系统安全,开发者需要进行合适的输入验证、输出过滤和权限控制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值