• 服务器入侵之找出隐藏字符的原理


    一、文章起源

    我在文章 一次服务器被入侵的处理过程分享 中间有提及到我通过 cat/more 等命令查看文件,以及通过crontab -l 命令查看,一些定时任务和文件内容被隐藏了。

    二、细讲问题

    image-20220906152249147

    文件内容为何显示不了,究竟是什么东西在作怪,让我们一探究竟。

    为了让大家也可以一起了解下, 文件我放到 阿里云oss 上, 有兴趣的可以下载下来看下。 隐藏文件内容示例

    2.1、 文件在不同环境下的不同编译器打开的显示情况

    Linux 通过 cat/more 打开

    image-20220904224957123

    Linux 通过 vim 打开

    image-20220904225044057

    Notepad++ 显示所有字符模式打开

    image-20220904172411710

    开始自己网上查了一下, 没有查到原因。凭借着做多年运维解决问题的经验,已经对问题的那种直觉感, 总觉得应该是 ;^M(我装到了)。

    三、 借助场外资源

    为了一探究竟,特意叫一个朋友拉我进了一个安全群,在群里询问下安全大佬。

    3.1、双向文本(Bidirectional tex)

    具体可以看下这个文章 https://tttang.com/archive/1339/

    在安全群里问了一下,有位大佬提了一句 双向文本方向。 我都没有听说过这个东西。 双向文本到底是啥,科普下:双向文本就是一个字符串里面,包含了两种文字,既包含从左到右的文字,又包含从右向左的文字。

    示例1:

    文本中是

    RLI a b c PDI
    

    而显示实际是

    c b a
    

    示例2:

    文本中是

    RLI LRI a b c PDI LRI d e f PDI PDI
    

    而实际上显示的是

    d e f a b c
    

    示例3:

    代码显示内容为

    1.png

    实际执行的内容是

    2.png

    细看,这好像跟我们的场景还是不一样。 这个只是调换文字的顺序。饭可以乱吃,路不能乱走啊,得走正道。 继续瞅瞅。

    3.2、 看看^M

    有另外一个大佬说出来了一个问题, 所有的问题原因是 跟^M 有关。

    如何在vim 中打出 ^M, ctrl + v +m 可以输出 ^M

    大佬说到 ^M 是回车换行符。 cat 带有^M的一行字符串时,屏幕上会把 ^M 之后的内容在同一行换行后输出,这样就会覆盖掉^M之前的内容,导致你看到的这个内容效果。

    我产生了疑问, ^M 是回车换行符, 这个有依据吗? 在下面有解释。

    先不管这个,我们先测试一波。

    示例一

    [root@vm-12-12-centos tmp]# cat test 
    1bc
    [root@vm-12-12-centos tmp]# cat -A test 
    abc^M1$
    

    示例二

    [root@vm-12-12-centos tmp]# cat -A test 
    abc^M123$
    [root@vm-12-12-centos tmp]# cat  test 
    123
    

    示例三

    [root@vm-12-12-centos tmp]# cat -A test 
    abc^M1    45$
    [root@vm-12-12-centos tmp]# cat test 
    1    45
    

    通过上面的示例,我们可以知道,^M 后面的内容会覆盖 ^M 前面的内容, 入侵者就是利用这个原理,在 ^M 后面打了很多个空格覆盖掉前面实际定时任务的内容。 哎,这入侵者真是个人才。

    img

    3.3、真相大白

    前面我产生了疑问, ^M 是回车换行符, 这个有依据吗? 我该怎么去查看这cat 命令把这个 ^M 给识别成啥了?

    在憋了几天之后,终于想到了一个大器(strace)。 有点相见恨晚的感觉。

    img

    [root@vm-12-12-centos tmp]# strace cat test 
    execve("/bin/cat", ["cat", "test"], 0x7ffe1d047e08 /* 19 vars */) = 0
    brk(NULL)                               = 0x1c0d000
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f14da021000
    access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
    open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=22981, ...}) = 0
    mmap(NULL, 22981, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f14da01b000
    close(3)                                = 0
    open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
    read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`&\2\0\0\0\0\0"..., 832) = 832
    fstat(3, {st_mode=S_IFREG|0755, st_size=2156592, ...}) = 0
    mmap(NULL, 3985920, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f14d9a33000
    mprotect(0x7f14d9bf7000, 2093056, PROT_NONE) = 0
    mmap(0x7f14d9df6000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c3000) = 0x7f14d9df6000
    mmap(0x7f14d9dfc000, 16896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f14d9dfc000
    close(3)                                = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f14da01a000
    mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f14da018000
    arch_prctl(ARCH_SET_FS, 0x7f14da018740) = 0
    access("/etc/sysconfig/strcasecmp-nonascii", F_OK) = -1 ENOENT (No such file or directory)
    access("/etc/sysconfig/strcasecmp-nonascii", F_OK) = -1 ENOENT (No such file or directory)
    mprotect(0x7f14d9df6000, 16384, PROT_READ) = 0
    mprotect(0x60b000, 4096, PROT_READ)     = 0
    mprotect(0x7f14da022000, 4096, PROT_READ) = 0
    munmap(0x7f14da01b000, 22981)           = 0
    brk(NULL)                               = 0x1c0d000
    brk(0x1c2e000)                          = 0x1c2e000
    brk(NULL)                               = 0x1c2e000
    open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=106176928, ...}) = 0
    mmap(NULL, 106176928, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f14d34f0000
    close(3)                                = 0
    fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
    open("test", O_RDONLY)                  = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=12, ...}) = 0
    fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
    read(3, "abc\r1    45\n", 65536)        = 12
    1    45, "abc\r1    45\n", 12abc
    )          = 12
    read(3, "", 65536)                      = 0
    close(3)                                = 0
    close(1)                                = 0
    close(2)                                = 0
    exit_group(0)                           = ?
    +++ exited with 0 +++
    

    我们注意看, read 这里的内容。

    read(3, "abc\r1    45\n", 65536)        = 12
    

    我们发现 ^Mcat 命令执行过程中,转换为 \r , 那么 \r 又是什么? 接下来需要去翻阅 新华字典了。

    image-20220905163052796

    数据来源 https://man7.org/linux/man-pages/man7/ascii.7.html

    \r : 回车符(carriage ret), 对应ASCII值13(缩写:CR)。 它的含义是什么: 回车 (控制字元)。

    image-20220905163530438

    https://zh.wikipedia.org/zh-cn/回车符

    那我们前面通过 notepad++ 打开的线上的 CR 是不是就对上了。

    image-20220905161721683

    最终我们可以得出一个初步结论, 也就是:

    • 在 Linux Vim 中打印出来的 ^M cat 等一些命令会转换为 \r\r 也就是回车 在Linuxunix 中 表示它將光标返回到行首。 \r之后的内容也就会覆盖前面的内容。

    四、注意

    1. 以后服务器如果入侵了,建议我们使用 cat -A 命令来查看。这样一些隐藏字符就可以看到了。

    image-20220905172331875

    参考文章:https://man7.org/linux/man-pages/man7/ascii.7.html

  • 相关阅读:
    机器学习笔记之概率图模型(十)因子图
    华为数通方向HCIP-DataCom H12-831题库(多选题:41-60)
    【Python21天学习挑战赛】-爬虫(B站)程序示例
    react路由01——react-routerV6 中路由传递参数的几种方式
    【web前端期末大作业】html网上在线书城大学生静态网页 大学生html当当书城仿站 网上书城购物网页作业HTML
    Redis之hash类型
    d3力导向图
    JPA 和 EclipseLink 如何使用数据库审计、数据库安全、代理身份验证和 VPD
    若依(ruoyi)之thymeleaf与jsp共存解决方案
    C++ 如何根据地理坐标范围获取瓦片地图并使用CImage库实现多张图片(瓦片地图)的快速合并
  • 原文地址:https://www.cnblogs.com/operationhome/p/16658941.html