~# n0tr00t Security Team

Esotalk v1.0.0g4 最新版反射型跨站漏洞

05 Nov 2014 - evi1m0

[+] Author: evi1m0
[+] Team: n0tr00t security team 
[+] From: http://www.n0tr00t.com
[+] Create: 2014-11-05

0x01 about

esoTalk是一款国外拥有众多优势的免费,开源的基于PHP和MySQL下的网页应用。 她的设计极为简介,速度极快,超轻量级别并且有良好的可拓展性。

Website: [http://esotalk.org/]

Github: [https://github.com/esotalk/esoTalk]

0x02 漏洞分析

文件:/var/www/esotalk/core/lib/functions.general.php

/**
 * Get a request input value, falling back to a default value if it is not set. POST will be searched first,
 * then GET, and then the fallback will be used.
 *
 * @param string $key The request input key.
 * @param mixed $default The fallback value.
 * @return mixed
 *
 * @package esoTalk
 */
function R($key, $default = "")
{
  if (!empty($_POST[$key])) return $_POST[$key];
  elseif (isset($_GET[$key])) return $_GET[$key];
  else return $default;
}

其中R将传值获取并return,查找用例到:

/var/www/esotalk/core/controllers/ETMembersController.class.php

/**
 * Show the member list page.
 *
 * @param string $orderBy What to sort the members by.
 * @param mixed $start Where to start the results from. This can be:
 *    - An integer, in which case it will be used as a numerical offset.
 *    - pX, where X is the "page" number.
 *    - A letter to start from, if $orderBy is "name".
 * @return void
 */
public function action_index($orderBy = false, $start = 0)
{
  if (!$this->allowed("esoTalk.members.visibleToGuests")) return;

  // Begin constructing a query to fetch results.
  $sql = ET::SQL()->from("member m");

  // If we've limited results by a search string...
  if ($searchString = R("search")) {
  .........

其中searchString变量=R,所以找到搜索会员处,修改payload:

http://127.0.0.1/esotalk/index.php/members/?search=bb2'><svg/onload=alert(1)>

其中ETMemersController.class.php action_index函数也应存在sqli,但esotalk采用pdo机制进行了防御,未能注入。

0x03 Fix

文件:/var/www/esotalk/core/lib/functions.general.php

function R($key, $default = "")
{
  if (!empty($_POST[$key])) return htmlspecialchars($_POST[$key]);
  elseif (isset($_GET[$key])) return htmlspecialchars($_GET[$key]);
  else return $default;
}

Github issue: https://github.com/esotalk/esoTalk/issues/378