尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Kali与Ubuntu权限命令进程日志实战避坑指南

Kali与Ubuntu权限命令进程日志实战避坑指南 1. 项目概述这不是“Linux入门”而是安全从业者每天睁眼就要面对的生存现场你刚打开Kali或Ubuntu终端输入ls -l看到一长串drwxr-xr-x却不知道第三组里的x到底管不管用你执行sudo apt update时顺手加了-y结果某天在客户生产环境里误删了关键日志目录只因没看清rm -rf /var/log/*后面那个空格你用ps aux | grep python找进程却漏掉了容器里静默运行的python3 -m http.server 8000你查/var/log/auth.log想确认谁昨晚连过SSH却发现日志被轮转了三次而journalctl -u ssh --since 2 days ago返回空——这些不是教科书里的练习题是我在红队渗透、蓝队值守、CTF备赛和甲方安全加固现场真实踩过的坑。本篇不讲“Linux是什么”只讲Kali与Ubuntu双环境下的命令、权限、进程、日志四大模块如何在真实攻防场景中不出错、不误判、不背锅。核心关键词全部来自一线高频痛点Kali渗透测试主力系统、Ubuntu企业服务与开发主流发行版、命令不是罗列是组合逻辑、权限不只是chmod是UID/GID/SUID/SGID/ACL/capabilities全链路、进程不只是ps/top是cgroup限制、namespace隔离、ptrace调试、进程树溯源、日志管理不只是tail -f是rsyslog规则编写、journald二进制日志解析、logrotate策略失效排查。适合三类人刚装好Kali虚拟机但总卡在Permission denied的新手已会写Python脚本却搞不定Docker容器内进程权限的老手正在为等保2.0日志留存6个月要求焦头烂额的运维同事。下面所有内容都来自我过去三年在17个真实项目中的操作记录、错误截图和复盘笔记。2. 命令层深度拆解为什么ls -la比dir重要100倍以及90%的人根本没用对find2.1 命令设计底层逻辑Shell不是“输入框”而是进程调度器很多人把终端当成Windows的CMD敲完命令就等结果。但在Kali/Ubuntu里每个命令本质都是一个独立进程由Shellbash/zshforkexec启动。这意味着|管道符不是“传递文本”而是创建匿名管道pipe让前一个进程的stdout直接连接后一个进程的stdin零拷贝传输;是顺序执行但前后命令无依赖是短路执行前命令exit code为0才执行后命令||则相反——这直接决定你写apt update apt upgrade还是apt update; apt upgrade$()和的区别在于前者支持嵌套后者不支持且$()更易读如for i in $(ls *.txt); do echo $i; donealias llls -alF这类别名本质是Shell函数的简化版但不会继承到子Shell比如你写bash -c ll会报错真正跨Shell生效要用export或写入~/.bashrc并source。我见过最典型的误操作在Kali里用sudo su切root后执行cd /opt/metasploit-framework ./msfconsole结果报错Permission denied。原因sudo su创建的是新Shell但当前工作目录仍是普通用户权限的/home/kali而./msfconsole需要读取/opt下文件——路径权限和进程权限必须同时满足。正确做法是sudo -i模拟完整登录环境或直接sudo /opt/metasploit-framework/msfconsole。2.2 文件操作命令的实战陷阱rm -rf不是万能钥匙cp可能悄悄改权限rm -rf被称作“删库跑路”神器但它的危险性远超想象。在Ubuntu服务器上我曾执行rm -rf /var/log/nginx/*清理日志结果Nginx服务崩溃。排查发现/var/log/nginx/目录本身被logrotate配置为create 0640 www-data adm但rm -rf *只删了文件没删空目录导致新日志无法写入权限不足。真正的清理逻辑应该是先find /var/log/nginx -name *.log -mtime 7 -delete再logrotate -f /etc/logrotate.d/nginx强制轮转。cp命令更隐蔽。默认cp file1 file2会保留源文件的mtime/atime但不保留所有权和权限。如果你在Kali里cp /usr/bin/nmap /tmp/mytool然后chmod us /tmp/mytool再给其他用户执行权限——恭喜你造出了一个SUID提权漏洞。而cp -ppreserve参数才是关键它保留mode, ownership, timestamps但不保留ACL和扩展属性需cp -a即archive模式。实测对比# 源文件权限 $ ls -l /usr/bin/python3 -rwxr-xr-x 1 root root 5432104 Jan 10 10:23 /usr/bin/python3 # cp 默认行为权限丢失 $ cp /usr/bin/python3 /tmp/py3_default $ ls -l /tmp/py3_default -rw-r--r-- 1 kali kali 5432104 Jun 15 14:00 /tmp/py3_default # cp -p 行为权限保留 $ cp -p /usr/bin/python3 /tmp/py3_preserve $ ls -l /tmp/py3_preserve -rwxr-xr-x 1 root root 5432104 Jun 15 14:01 /tmp/py3_preserve2.3 网络与调试命令的精准用法telnet不是“连通性测试”netstat已被淘汰telnet常被误认为“测试端口是否开放”但它本质是明文协议客户端。在Kali里执行telnet 192.168.1.100 22如果返回Connected to 192.168.1.100.说明TCP三次握手成功但无法判断SSH服务是否真在监听可能是防火墙放行但服务未启。更可靠的是nc -zv 192.168.1.100 22netcat zero-I/O mode它只做连接测试不发送应用层数据且返回明确状态码。netstat在Ubuntu 20.04已标记为deprecated官方推荐sssocket statistics。两者差异极大netstat -tuln显示所有监听端口但需root权限才能看到进程名-p参数ss -tuln执行速度提升3倍以上且ss -tulnp无需root即可显示进程依赖/proc/net/权限关键区别ss能识别TIME-WAIT状态连接而netstat常将其归为CLOSE_WAIT导致误判连接泄漏。我在线上排查一个Web服务响应慢问题时用netstat -an | grep :80 | wc -l统计连接数为2000但ss -s显示tcp: 2000 (estab) 100 (closed)最终发现是netstat把大量TIME-WAIT连接计入了活跃数实际ESTABLISHED仅100个。真实负载评估必须用ss -tuln替代netstat。2.4 文本处理命令的组合艺术grep的-E不是可选awk的字段分隔是生死线grep的-E扩展正则是必须掌握的。基础grep error /var/log/syslog只能匹配字面量但grep -E (error|fail|denied) /var/log/auth.log能一次性捕获认证失败全貌。更关键的是-oonly-matching参数grep -oE [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} /var/log/apache2/access.log可精准提取所有IP避免grep -E 192\.168\.[0-9]\.[0-9]的误匹配。awk的字段分隔符FS决定一切。默认空格分隔但日志格式千差万别Apache access.logawk -F {print $2} /var/log/apache2/access.log提取User-Agent用双引号分隔/etc/passwdawk -F: {print $1,$3,$7} /etc/passwd提取用户名、UID、shell致命陷阱awk {print $1}处理ls -l输出时若文件名含空格如my report.pdf$1只取my$2才是report.pdf。正确做法是ls -l | awk {print $NF}NFNumber of Fields取最后一列。我曾用awk {print $9} /var/log/nginx/access.log提取HTTP状态码结果大量404被漏掉——因为Nginx日志格式为$remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent状态码是第9字段没错但$request含空格导致字段偏移。必须先用awk -F {print $2}提取request字段再用awk {print $1}取方法awk {print $2}取状态码。3. 权限体系全景透视从chmod 755到capabilities为什么root不是万能钥匙3.1 经典权限模型的三大盲区rwx只是冰山一角chmod 755是新手最熟悉的权限但它的局限性在安全场景中暴露无遗第一盲区目录的x权限决定“能否进入”而非“能否列出内容”。chmod 750 /opt/tool用户属于tool组有r-x权限但ls /opt/tool会报Permission denied——因为缺少x执行权限无法进入目录。r权限只影响ls -l查看文件详情x才是门禁卡。第二盲区SUID/SGID的隐式提权风险。/usr/bin/passwd设置SUID-rwsr-xr-x普通用户执行时以root身份运行从而修改/etc/shadow。但若攻击者控制了/usr/bin/python3的SUID位chmod us /usr/bin/python3就能执行python3 -c import os; os.system(bash -p)获得root shell。Kali默认禁用SUID Python但Ubuntu桌面版常开启。第三盲区粘滞位Sticky Bit不是“防删除”而是“防覆盖”。/tmp目录权限为drwxrwxrwt末尾t表示粘滞位。它规定只有文件所有者、目录所有者或root才能删除该目录下的文件即使其他用户对该目录有rwx权限。这是防止/tmp被恶意清空的关键机制。我在线下培训中让学员执行chmod 777 /var/www/html结果第二天网站被挂马。原因777赋予组和其他用户写权限而Apache默认以www-data用户运行其所属组也是www-data。攻击者上传shell.php后通过Web访问即可执行任意命令——权限最小化原则在此刻崩塌。3.2 ACL访问控制列表当chmod不够用时的终极方案当标准rwx无法满足复杂需求时ACL是唯一选择。例如需让开发组dev和运维组ops都能读写/var/www/project但dev不能删除ops上传的备份文件。chmod无法实现ACL可以# 启用ACLext4文件系统需挂载选项default_acl $ sudo mount -o remount,acl / # 临时启用 $ sudo tune2fs -o acl /dev/sda1 # 永久启用 # 设置ACLdev组读写执行ops组读写执行但禁止删除 $ sudo setfacl -m g:dev:rwx /var/www/project $ sudo setfacl -m g:ops:rwx /var/www/project $ sudo setfacl -m d:g:dev:rwx /var/www/project # 默认ACL对新建文件生效 $ sudo setfacl -m d:g:ops:rwx /var/www/project # 验证 $ getfacl /var/www/project # file: /var/www/project # owner: root # group: root # flags: -s- # user::rwx # group::r-x # group:dev:rwx # group:ops:rwx # mask::rwx # other::r-x # default:user::rwx # default:group::r-x # default:group:dev:rwx # default:group:ops:rwx # default:mask::rwx # default:other::r-x注意mask::rwx字段它是ACL的“最大权限掩码”所有named user/group的权限不能超过mask。若后续执行setfacl -m m::rx则dev和ops的w权限将失效——这是ACL最易忽略的机制。3.3 capabilities机制比SUID更精细的权限拆分Linux 2.2引入capabilities将root的超级权限拆分为38个独立能力如CAP_NET_BIND_SERVICE允许绑定1024以下端口CAP_SYS_ADMIN管理挂载等。ping命令就是经典案例/bin/ping拥有cap_net_rawep能力普通用户执行时无需SUID即可发送ICMP包。在Kali中nmap -sSSYN扫描需原始套接字权限传统做法是chmod us /usr/bin/nmap但这样赋予了nmap全部root权限。更安全的方式是$ sudo setcap cap_net_rawep /usr/bin/nmap $ getcap /usr/bin/nmap /usr/bin/nmap cap_net_rawep此时nmap只能进行网络扫描无法读取/etc/shadow。capabilities是容器安全的核心Docker默认禁用CAP_SYS_ADMIN但若运行docker run --cap-addSYS_ADMIN ubuntu容器内进程即可执行mount命令突破容器隔离。我曾为某金融客户加固Kali镜像移除了所有SUID二进制文件find /usr -perm -4000 -type f 2/dev/null改用capabilities精确授权。结果渗透测试人员反馈sqlmap --os-shell无法执行系统命令——排查发现sqlmap依赖/bin/bash的CAP_SYS_CHROOT能力来chroot最终通过setcap cap_sys_chrootep /bin/bash解决。权限加固不是简单删文件而是能力映射重构。3.4 SELinux/AppArmor强制访问控制MAC的落地阵痛Ubuntu默认启用AppArmorKali默认禁用SELinux但可手动安装。二者原理相似为进程定义安全策略限制其能访问的文件、网络端口、系统调用。AppArmor策略文件位于/etc/apparmor.d/以abstractions抽象规则和profiles具体策略组织。例如/etc/apparmor.d/usr.sbin.mysqld规定MySQL只能读/etc/mysql/**、写/var/lib/mysql/**、监听3306端口。若攻击者通过SQL注入执行SELECT LOAD_FILE(/etc/shadow)AppArmor会拦截——因为策略未授权读取/etc/shadow。但落地难点在于策略编写是黑盒艺术。我为客户部署Apache时启用/etc/apparmor.d/usr.sbin.apache2后PHP脚本无法写入/var/www/uploads/。dmesg | grep apparmor显示apparmorDENIED operationopen profile/usr/sbin/apache2 name/var/www/uploads/。解决方案不是关闭AppArmor而是# 编辑策略 $ sudo nano /etc/apparmor.d/usr.sbin.apache2 # 在文件末尾添加 /var/www/uploads/** rw, # 重新加载 $ sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.apache2关键经验永远先看dmesg日志再修改策略而非盲目禁用。4. 进程管理实战精要从ps aux到systemd如何揪出隐藏的挖矿进程4.1 进程状态与生命周期R S D Z T背后的内核真相ps aux输出的STAT列如S、R、Z是理解进程健康度的关键RRunning正在CPU上运行或等待运行run queueSSleeping可中断睡眠等待I/O如磁盘读写、网络响应DUninterruptible Sleep不可中断睡眠通常在等待磁盘I/O完成kill -9也无法唤醒常见于坏块硬盘ZZombie僵尸进程子进程已终止但父进程未调用wait()回收占用进程表项TStopped被信号如SIGSTOP暂停或被调试器gdb中断。我处理过一个Kali虚拟机卡死问题top显示CPU使用率0%但系统无响应。ps aux | grep D 发现kswapd0进程状态为D进一步iostat -x 1显示%util持续100%定位到虚拟磁盘I/O瓶颈。D状态是硬件级故障的早期信号而非软件问题。4.2 进程树与父子关系pstree比ps更能揭示攻击链ps aux是扁平列表pstree则展示进程树结构这对溯源至关重要。例如发现可疑python3进程$ pstree -p | grep python3 ├─sshd(845)───sshd(1203)───bash(1205)───python3(1207) └─systemd(1)───python3(999)左侧分支是SSH会话启动的python3正常右侧是systemd直接启动的python3高危。进一步ps -o pid,ppid,comm -p 999确认PPID1再ls -l /proc/999/exe发现指向/tmp/.cache/update.py——典型的持久化后门。systemd的--user实例常被忽视。普通用户执行systemctl --user start myservice服务进程PPID为systemd --userPID1001而非bash。ps aux | grep myservice可能漏掉但systemctl --user list-units --typeservice必现。红队常用此方式隐藏C2进程蓝队必须检查用户级systemd。4.3 cgroup与资源限制用systemd-run给进程戴紧箍咒systemd-run可为单次命令创建临时scope限制CPU、内存、IO。例如运行一个可能失控的漏洞扫描工具# 限制CPU使用率不超过50%内存不超过1GIO权重为50默认100 $ systemd-run --scope -p CPUQuota50% -p MemoryLimit1G -p IOWeight50 -- bash -c nmap -sV 192.168.1.0/24 # 查看实时资源使用 $ systemd-cgtopcgroup是容器技术的基石。Docker容器本质是systemd下的cgroup scope。docker stats显示的CPU%、MEM USAGE底层就是读取/sys/fs/cgroup/memory/docker/container-id/memory.usage_in_bytes。我曾为某云平台加固要求所有后台任务必须受cgroup约束。原脚本/opt/backup.sh直接运行改为# 创建持久化slice $ sudo systemctl edit --force --full backup.slice # 内容 [Unit] DescriptionBackup Service Slice [Slice] MemoryLimit512M CPUQuota30% # 应用 $ sudo systemctl daemon-reload # 运行脚本 $ systemd-run --scope --slicebackup.slice /opt/backup.sh资源限制不是性能优化而是安全边界内存限制可防OOM Killer误杀关键进程CPU配额可阻断挖矿程序耗尽算力。4.4 进程调试与内存分析gdb和/proc/pid/是逆向利器/proc/pid/是进程的“数字孪生”包含全部运行时信息/proc/pid/cmdline启动命令null分隔需tr \0 /proc/123/cmdline/proc/pid/environ环境变量同样null分隔/proc/pid/maps内存映射可识别动态库加载地址、堆栈范围/proc/pid/fd/打开的文件描述符ls -l /proc/123/fd/可看到进程正在读写的文件。gdb调试是高级技能。例如某Java进程频繁GC怀疑内存泄漏# 附加到进程 $ gdb -p 1234 (gdb) info proc mappings # 查看内存布局 (gdb) dump memory /tmp/java_heap.bin 0x7f0000000000 0x7f0000fffff0 # 转储堆内存 (gdb) quit # 用MATMemory Analyzer Tool分析dump文件对于无调试符号的二进制strace -p 1234可追踪系统调用lsof -p 1234查看打开的文件和网络连接。进程分析不是猜谜而是证据链构建ps找异常pstree看关系/proc查细节strace抓行为。5. 日志管理工程实践从journalctl到rsyslog如何让日志成为你的攻防雷达5.1 systemd-journald二进制日志的威力与陷阱journalctl是现代Linux日志核心但其二进制格式.journal带来独特挑战优势结构化存储字段如_PID,_COMM,PRIORITY支持高效过滤journalctl _COMMsshd PRIORITY3陷阱默认日志保存在/run/log/journal/内存文件系统重启即丢失持久化需创建/var/log/journal/目录并重启journald。配置持久化$ sudo mkdir -p /var/log/journal $ sudo systemd-tmpfiles --create --prefix /var/log/journal $ sudo systemctl restart systemd-journaldjournalctl的-o json-pretty输出JSON可被ELK栈消费。但最大风险是日志轮转策略失效。/etc/systemd/journald.conf中SystemMaxUse1G限制总日志大小MaxFileSec1month单个日志文件最长保留时间若SystemMaxUse设为0不限制磁盘可能被撑爆。我处理过一个Ubuntu服务器磁盘告警df -h显示/var使用率100%。du -sh /var/log/journal/*发现单个.journal~文件达20G。原因是MaxFileSec未配置且/var/log/journal/目录权限为755导致journald无法自动清理旧文件。修复步骤sudo chmod 2755 /var/log/journalsetgid确保新文件属组为systemd-journal再sudo journalctl --vacuum-size1G强制清理。5.2 rsyslog高级配置如何让/var/log/auth.log不再被刷屏rsyslog是传统日志守护进程Kali/Ubuntu均预装。默认配置/etc/rsyslog.conf将auth.*写入/var/log/auth.log但暴力破解SSH时每秒数百条Failed password for root from 192.168.1.100 port 54321 ssh2会淹没有效日志。解决方案基于规则的过滤。在/etc/rsyslog.d/50-auth-filter.conf中# 忽略重复的失败登录每分钟最多10条 :msg, contains, Failed password ~ # 或更精准同一IP每分钟最多5条 if $fromhost-ip 192.168.1.100 and $msg contains Failed password then { if $year 2023 and $month 06 and $day 15 and $hour 14 then { if $msg contains 192.168.1.100 then { stop } } } # 将高危事件单独存档 if $msg contains Invalid user or $msg contains Connection closed by invalid user then { action(typeomfile file/var/log/auth_critical.log) }重启sudo systemctl restart rsyslog。过滤不是删除而是分流auth.log保持可读auth_critical.log专供SOC分析。5.3 logrotate实战为什么/var/log/nginx/access.log轮转后网站就挂了logrotate配置不当是线上事故高发区。典型错误配置# /etc/logrotate.d/nginx 错误示例 /var/log/nginx/*.log { daily missingok rotate 52 compress delaycompress notifempty create 0640 www-data adm sharedscripts postrotate [ -f /var/run/nginx.pid ] kill -USR1 cat /var/run/nginx.pid endscript }问题在于create 0640 www-data adm轮转后新日志文件权限为0640但Nginx主进程以root运行worker进程以www-data运行www-data组有读权限但Nginx worker需要写权限。正确应为create 0644 www-data www-data。更致命的是postrotate脚本kill -USR1通知Nginx重新打开日志文件但如果Nginx未运行/var/run/nginx.pid不存在脚本会报错退出导致logrotate中断。健壮写法postrotate if [ -f /var/run/nginx.pid ]; then kill -USR1 cat /var/run/nginx.pid 2/dev/null || true fi endscript2/dev/null || true确保脚本永不失败。5.4 日志集中化与SIEM对接用rsyslog直传Elasticsearch企业级日志管理需集中化。rsyslog可通过omelasticsearch模块直传ES# 安装模块 $ sudo apt install rsyslog-elasticsearch # /etc/rsyslog.d/99-es.conf module(loadomelasticsearch) template(namees-json typelist) { constant(value{) constant(value\timestamp\:\) property(nametimereported dateFormatrfc3339) constant(value\,\host\:\) property(namehostname) constant(value\,\severity\:\) property(namesyslogseverity-text) constant(value\,\facility\:\) property(namesyslogfacility-text) constant(value\,\program\:\) property(nameprogramname) constant(value\,\message\:\) property(namemsg formatjson) constant(value\}) } *.* action( typeomelasticsearch serveres-server.internal serverport9200 searchIndexsyslog-%$YEAR%.%$MONTH%.%$DAY% templatees-json bulkmodeon queue.typeDisk queue.filenamersyslog-es-queue queue.maxdiskspace1g )重启后所有日志自动索引到ES的syslog-2023.06.15索引。关键点queue.typeDisk确保网络中断时日志不丢失bulkmodeon提升吞吐量。6. 常见问题与排查技巧实录那些让你凌晨三点爬起来的“小问题”6.1 “Permission denied”终极排查清单当sudo也报错时按此顺序排查文件系统只读mount | grep $(df . | tail -1 | awk {print $1}) | grep ro若输出含ro执行sudo mount -o remount,rw /SELinux/AppArmor阻止sudo ausearch -m avc -ts recent | audit2whySELinux或dmesg | grep -i avcAppArmorcapability缺失getcap /path/to/binary若需CAP_SYS_ADMIN但未设置则sudo setcap cap_sys_adminep /path/to/binaryumask干扰umask值影响新建文件权限umask 0022时touch file生成644umask 0077则为600挂载选项noexec/nosuidmount | grep $(dirname /path)若含noexec则无法执行该目录下二进制。我遇到最诡异的一次sudo systemctl restart nginx报Failed to reload daemon: Permission denied。strace -e traceaccess,openat sudo systemctl restart nginx发现尝试访问/run/systemd/private失败。最终发现/run被noexec挂载——sudo mount -o remount,exec /run解决。6.2 进程“消失”之谜ps找不到但top能看到现象ps aux | grep myapp无输出但top中CPU占用200%。原因通常是进程名被篡改恶意程序执行prctl(PR_SET_NAME, apache2)ps显示apache2但实际是挖矿木马线程模式ps默认不显示线程ps -eLf | grep myapp可查看LWP轻量级进程PID namespace隔离容器内进程PID为1宿主机ps看不到。排查命令# 查看所有线程 $ ps -eLf | grep myapp # 查看进程名可能被prctl修改 $ cat /proc/$(pgrep myapp)/comm # 查看完整命令行 $ cat /proc/$(pgrep myapp)/cmdline | tr \0 # 检查是否在容器中 $ cat /proc/$(pgrep myapp)/cgroup | head -56.3 日志“断更”故障树日志停止写入的5大原因原因检查命令解决方案rsyslog服务崩溃sudo systemctl status rsyslogsudo systemctl restart rsyslog磁盘空间满df -h /var/logsudo journalctl --vacuum-size100M日志文件被rm但句柄未释放sudo lsof L1 /var/log/sudo kill -HUP $(pgrep rsyslog)rsyslog配置语法错误sudo rsyslogd -N1修复/etc/rsyslog.d/*.confjournald日志目录权限错误ls -ld /var/log/journalsudo chmod 2755 /var/log/journal我曾用sudo lsof L1 /var/log/auth.log发现rsyslogd仍持有已删除日志文件的句柄df显示磁盘满但ls -lh /var/log/auth.log显示文件大小为0。sudo kill -HUP $(pgrep rsyslog)强制rsyslog重新打开日志文件释放磁盘空间。6.4 Kali/Ubuntu双环境权限差异速查场景Kali LinuxUbuntu Desktop/Server原因SUID Python默认状态禁用
返回列表