专栏首页FreeBuf渗透测试TIPS之删除、伪造Linux系统登录日志

渗透测试TIPS之删除、伪造Linux系统登录日志

0x00. 引言

擦除日志在渗透测试中是非常重要的一个阶段,这样可以更好地隐藏入侵痕迹,做到不被系统管理人员察觉,实现长期潜伏的目的。 前段时间NSA泄露的渗透测试工具中就有一款wtmp日志的擦除,非常好用,这引起了我的兴趣,于是研究了一下linux 登录相关二进制日志的文件格式,用python写了一个日志擦除,伪造的工具(末尾附源码)

0x01. Linux中与登录有关的日志及其格式分析

Linux中涉及到登录的二进制日志文件有

    /var/run/utmp

    /var/log/wtmp

    /var/log/btmp

    /var/log/lastlog

其中 utmp 对应w 和 who命令; wtmp 对应last命令;btmp对应lastb命令;lastlog 对应lastlog命令

经查Linux man 手册,

/var/run/utmp
/var/log/wtmp
/var/log/btmp

的二进制格式都是一样的, 我们姑且称之为xtmp 格式

而/var/log/lastlog 文件的格式与之不同,需单独分析,下面我们先分析xtmp的文件格式吧,这里以utmp 格式为例

UTMP 文件格式

utmp 文件格式是这样的:

    #define UT_LINESIZE     32

    #define UT_NAMESIZE     32

    #define UT_HOSTSIZE     256

        struct utmp {

            short   ut_type;              /* Type of record */

            pid_t   ut_pid;               /* PID of login process */

            char    ut_line[UT_LINESIZE]; /* Device name of tty - "/dev/" */

            char    ut_id[4];             /* Terminal name suffix,

                                             or inittab(5) ID */

            char    ut_user[UT_NAMESIZE]; /* Username */

            char    ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or

                                             kernel version for run-level

                                             messages */

            struct  exit_status ut_exit;  /* Exit status of a process

                                             marked as DEAD_PROCESS; not

                                             used by Linux init(8) */

            /* The ut_session and ut_tv fields must be the same size when

               compiled 32- and 64-bit.  This allows data files and shared

               memory to be shared between 32- and 64-bit applications. */

        #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32

            int32_t ut_session;           /* Session ID (getsid(2)),

                                             used for windowing */

            struct {

                int32_t tv_sec;           /* Seconds */

                int32_t tv_usec;          /* Microseconds */

            } ut_tv;                      /* Time entry was made */

        #else

             long   ut_session;           /* Session ID */

             struct timeval ut_tv;        /* Time entry was made */

        #endif

           int32_t ut_addr_v6[4];        /* Internet address of remote

                                             host; IPv4 address uses

                                             just ut_addr_v6[0] */

            char __unused[20];            /* Reserved for future use */

        };

    其中 exit_status 结构为:

    struct exit_status {              /* Type for ut_exit, below */

        short int e_termination;      /* Process termination status */

        short int e_exit;             /* Process exit status */

    };

其中 ut_type 为日志记录的类型,主要有以下几种日志

    #define EMPTY         0 /* Record does not contain valid info

                               (formerly known as UT_UNKNOWN on Linux) */

    #define RUN_LVL       1 /* Change in system run-level (see

                               init(8)) */

    #define BOOT_TIME     2 /* Time of system boot (in ut_tv) */

    #define NEW_TIME      3 /* Time after system clock change

                               (in ut_tv) */

    #define OLD_TIME      4 /* Time before system clock change

                               (in ut_tv) */

    #define INIT_PROCESS  5 /* Process spawned by init(8) */

    #define LOGIN_PROCESS 6 /* Session leader process for user login */

    #define USER_PROCESS  7 /* Normal process */

    #define DEAD_PROCESS  8 /* Terminated process */

    #define ACCOUNTING    9 /* Not implemented */

    #define UT_LINESIZE      32

    #define UT_NAMESIZE      32

    #define UT_HOSTSIZE     256

utmp 记录例子(二进制内容解析处理后):

对比utmp的文件格式结构,挑几个重要的字段解释下

第1个字段7 表示这条记录类型,一般的用户正常登录记录类型都是7,错误登录是6 ,也就是btmp所记录的类型

第2个字段1497 是pid ,截图中我是用ssh远程登录linux,这里指的就是sshd的子进程bash的pid

第3个字段pts/0 表示的登录的伪终端 ,后面一串\0是填充的数据

第4个字段 ts/0表示的伪终端的后缀

第5个字段root 表示登录用户名,后面一串\0是填充数据,因为这个字段为32个字节大小

第6个字段10.1.100.1 表示的是登录主机,后面一串\0是填充数据,因为这个字段为256个字节大小

第10个字段表示的是登录时间,精确到秒

第11个字段表示的是登录时间中微妙部分

第12个字段表示的是登录sessionid

lastlog 文件格式:

    #define UT_LINESIZE     32
    #define UT_HOSTSIZE     256
    struct lastlog
      {
        __time_t ll_time;
        char ll_line[UT_LINESIZE];
        char ll_host[UT_HOSTSIZE];
      };

lastlog 记录例子(二进制内容解析处理后):

第1个字段表示最后一次登录时间

第2个字段表示最后一次登录的终端

第3个字段表示最后一次登录的IP

0x02. 擦除,伪造登录日志的测试

1.删除utmp记录,将自己从w或者who输出中隐藏

比如此时有两个登录记录,一个是root(要删除的记录),一个是f3

删除前:

删除后:

  1. 添加utmp记录,伪造登录信息

添加前:

添加后:

注: 添加Fake 在线记录的时候,pid必须可以找到相应进程,一般可以使用sshd的或者是bash的相关PID

2.删除历史登录记录(wtmp)

删除前:

删除指定用户,指定host的历史登录记录

删除后:

3.添加wtmp记录

4.删除btmp记录

删除前

hacker 这个账户有很多次尝试登录记录

删除后:

5.添加btmp 伪造记录

6.删除lastlog 记录

hacker 用户最后一次登录记录,删除前:

删除后:

7.添加伪造的lastlog记录

python fake_login_log.py —mode add —type=lastlog —user=hacker —date=”2017-7-24 14:22:07

这里说明一下:lastlog中并不记录用户名,而是根据文件偏移位置来计算当前记录的用户名是多少,比如当前用户是f3,其UID为1001,那么lastlog 日志从头开始向后移动 1001 × LAST_STRUCT_SIZE处的位置则为f3用户最后一次登录记录写入处(用户即使没有最后一次登录记录,在相应的偏移处都会有记录,这就是我们使用lastlog看到的never login的记录)

0x03. 源码

直接帖源码,格式上可能会影响阅读体验,帖下我的在线源码地址吧:点击打开在线源码

0x04. 总结

目前此工具可以实现对:

/var/run/utmp

/var/log/wtmp

/var/log/btmp

/var/log/lastlog

进行删除,添加伪造记录功能,并且在修改相关文件后恢复其时间属性值(比如文件访问时间和文件修改时间),有人会说了,直接echo “” >/var/log/xtmp 不就行了吗,干嘛这么麻烦,直接删除是很好,不过有点粗暴。 本工具不仅可以实现按照 登录主机,登录用户, 时间戳等条件进行按需删除,还可以添加伪造登录记录,以达到迷惑系统管理员之目的。需要补充一点的是,目前还未实现根据时间区间来删除指定记录,也希望有兴趣的同学补充一下

参考:

1)https://linux.die.net/man/5/utmp
2)https://github.com/krig/lastlog/blob/master/lastlog.c

本文分享自微信公众号 - FreeBuf(freebuf),作者:knpewg85942

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-07-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 企业级渗透测试服务思考

    随着企业组织的业务规模不断扩大,信息化运用快速发展,业务与数据安全已经被推上战争的高地,成为企业保护自身安全的重中之重,成为企业信息安全官在战略计划汇报中不得不...

    FB客服
  • 如何在网络中追踪入侵者(三):主机追踪

    在之前的文章中,我们专注于追踪和分析从网络中得到的数据。但事实上,在网络中追踪不是唯一的选项。在企业的主机和服务器上有大量的数据集来发掘未知的恶意行为,包括运行...

    FB客服
  • GnuRadio Hacking ①:使用GnuRadio+SDR破解固定码无线遥控

    *Author:雪碧0xroot @漏洞盒子安全团队 0×01 信号捕获 在这篇文章中,我们将使用GnuRadio+SDR硬件对某品牌型号的无线跳蛋进行...

    FB客服
  • 网页顶部加载进度条NProgress

    Add [nprogress.js] and [nprogress.css] to your project.

    小贝壳
  • Lucene学习总结之三:Lucene的索引文件格式(1)

    Lucene的索引里面存了些什么,如何存放的,也即Lucene的索引文件格式,是读懂Lucene源代码的一把钥匙。

    Hongten
  • Lucene学习总结之三:Lucene的索引文件格式(1)

    Lucene的索引里面存了些什么,如何存放的,也即Lucene的索引文件格式,是读懂Lucene源代码的一把钥匙。

    杉枫
  • 浅谈MySQL中的事务隔离级别(r11笔记第86天)

    之前写了一篇浅谈事务(一),算是对事务的一个基本认识,今天来简单总结一下事务的隔离级别,虽然是老掉牙的知识点,重温一下还是值得的。 在MySQL中基...

    jeanron100
  • python之next和send用法详解

    如果send不携带参数,那么send(None) 和next()的作用的相同的,如:

    py3study
  • very-easyUI 框架快速上手文档

    这是我自己闲暇之余封装的一个工具,当然还有一大堆BUG,但是对于自己接接小活还是挺方便的,分享出来。后面会慢慢持续更新。

    剽悍一小兔
  • ACL 2019 | AI2等提出自动知识图谱构建模型COMET,接近人类表现

    链接:https://arxiv.org/pdf/1906.05317v1.pdf

    机器之心

扫码关注云+社区

领取腾讯云代金券