首先做个说明 ,本文面向Linux运维工程师,属于系统原理与运维排查科普,所有内容用于内部风险识别与系统加固,请勿用于未授权环境。日常运维中,我们更多关注监听端口、登录日志,却常常忽略一类风险:服务器主动向外建立网络会话。很多异常行为,底层只是利用Linux文件描述符做输入输出重定向。搞懂这套机制,可以帮助我们快速识别服务器上的可疑会话,做好事前加固与事后排查。很多运维牛马看到网上各类特殊shell片段,只知道它属于异常行为,却不清楚系统底层发生了什么。网上不少资料偏向开发的演练视角,而我们运维更应该关心的是:进程到底做了什么?线上如何发现?如何规避同类风险。 先理解这两种远程会话模式:正向与反向外联会话,平时我们日常ssh登录服务器,属于正向会话,客户端主动发起连接,服务器开放端口接收访问。还有另一种完全相反的模式:服务器主动向外发起网络连接,把shell的输入输出通道绑定到外部网络套接字。 即使防火墙严格拦截外部访问入站,只要服务器允许访问外网,就会产生这类外联会话,也是线上事件排查中高频遇到的一类现象。这玩意的底层,就是Linux文件描述符。 进程默认的3个基础文件描述符 每个进程启动,会自带3个标准通道,可以指向磁盘文件、管道,也可以指向网络socket> /dev/tcp、/dev/udp是bash内置的伪文件,并不是磁盘上真实存在的设备,仅bash识别。 核心逻辑:将0/1/2这三组输入输出,全部重定向到外部TCP套接字,进程的交互全部走外部网络链路。 1、检查进程文件描述符 进程所有打开句柄全部存放在/proc/<PID>/fd目录ps aux | grep -E 'bash|sh' | grep -v grep
PID 1630:bash ./run svc‑cron PID 130130:‑bash(pts/1,这是我当前的SSH会话)ls -l /proc/1630/fdls -l /proc/6148/fd
- PID 1630(后台服务 bash)
- 0→
/dev/null;1、2→pipe:[xxxx] - pipe 是本机进程管道,不是网络 socket,正常现象。
- PID 6148(交互式 bash)
- 0/1/2 全部指向
/dev/pts/0,本地终端会话,正常。
重点是看fd链接是不是 socket:[数字];pts/*、/dev/null、pipe:[]这些都是均属于正常。
由此可见,我这台服务器的bash 进程没有发现异常网络套接字句柄。
2、检查对外网络连接 ,这类行为是服务器向外发起连接,平时运维牛马99%只看本机Listen监听端口,漏掉出站连接。 ss -antp | grep -E "bash|sh" netstat -antp | grep sh
重点观察STATE为ESTABLISHED,且目标地址为陌生公网IP的会话。3、历史命令与日志检查 检查~/.bash_history,如果出现大量命令记录被清空,本身就是高风险信号。一般哪些场景容易出现此类异常行为呢?无非这几个:1. 应用存在外部输入直接拼接系统命令的缺陷; 2. 对外暴露的接口直接接收外部输入交给shell处理; 3. 低权限账号被突破之后,用来建立外部会话; 4. crontab定时任务被篡改,定时触发外联行为。平时设置防火墙或者云主机的安全组,都是只管控入站流量,绝大多数业务服务器对出站访问几乎没有限制,这就给外联会话留下空间。一些常见的加固建议,也欢迎各位大佬提出更好的建议: 1. 提醒领导要求开发不要直接命令拼接:不要把外部输入直接交给系统shell执行,从根源降低风险。2. 最小权限运行:业务进程账号权限尽量收敛,禁止直接使用root执行业务程序。 3. 做好出站访问管控:核心业务服务器,做出口访问控制;非业务刚需,限制服务器访问公网陌生地址。(这个运维层面很容易实现) 写在最后的一些废话。很多运维会把这类特殊shell当成很神秘的技术,其实本质只是Linux原生的文件描述符与socket重定向能力。