天涯论坛

 找回密码
 立即注册
搜索
查看: 19|回复: 0

命令执行底层原理探究-PHP(一)

[复制链接]

2991

主题

330

回帖

9919万

积分

论坛元老

Rank: 8Rank: 8

积分
99199252
发表于 2024-11-3 12:19:12 | 显示全部楼层 |阅读模式

前言

针对区别平台/语言下的命令执行是不相同的,存在很大的差异性。因此呢这儿区别平台/语言下的命令执行函数进行深入的探究分析。

文案开头会对区别平台(Linux、Windows)下:终端的指令执行、语言(PHP、Java、Python)的命令执行进行介绍分析。后面,重点以PHP语言为对象,针对区别平台,对命令执行函数进行底层深入分析,这个过程包含:PHP内核源码的编译、运行、调试、审计等,其它语言分析原理思路类似。19

该系列分析文案重点分为四部分,如下:

第1部分:命令执行底层原理探究-PHP (一)

针对区别平台(Linux、Windows)下:终端的指令执行、语言(PHP、Java、Python)的命令执行进行介绍分析。

第二部分:命令执行底层原理探究-PHP (二)

重点以PHP语言为对象,针对区别平台,进行环境准备、PHP内核源码的编译、运行、调试等。

第三部分:命令执行底层原理探究-PHP (三)

针对Windows平台下,PHP命令执行函数的底层原理分析。

第四部分:命令执行底层原理探究-PHP (四)

针对Linux平台下,PHP命令执行函数的底层原理分析。

本文《 命令执行底层原理探究-PHP (一) 》重点讲述的是第1部分:针对区别平台(Linux、Windows)下:终端的指令执行、语言(PHP、Java、Python)的命令执行进行介绍分析。

平台语言

区别平台终端指令执行

区别平台终端中执行的命令方式通常有两种:自己终端封装的指令(内置)、终端下调用其它目录下的可执行程序(外边)。

Linux

Linux下终端通常/bin/bash/bin/sh/bin/zsh等,这儿bash终端为例测试。

以Linux为例【Windows等平台原理同Linux类似】,Linux下终端内建(内置)的指令类型为:shell built-in command

所说shell built-in command便是哪些内建在linux shell里面的command指令。

一般状况下,在linux shell下面执行一个command指令,shell会查询command是不是built-in command类型,针对built-in command指令类型,shell会自己解释执行,而无需fork一个child process子进程来执行该command指令;针对,不是built-in command指令类型,shell会从环境变量中按次序搜索该command指令,倘若能查到则会fork一个child process子进程来执行该command指令;然而,针对找不到的command指令,通常为:执行的指令不存在、指令未加入到环境变量中。

那样怎样进行终端内建指令的判断与查看呢,针对内建指令能够运用type指令去判断

┌──(roottoor)-[~/桌面] └─# type echo echo is a shell builtin ┌──(roottoor)-[~/桌面] └─# type whoami whoami is /usr/bin/whoami ┌──(roottoor)-[~/桌面] └─#

或着能够运用其它指令进行查询判断:which、where

┌──(roottoor)-[~/桌面] └─# which echo echo: shell built-in command ┌──(roottoor)-[~/桌面] └─# which whoami/usr/bin/whoami ┌──(roottoor)-[~/桌面] └─# ┌──(roottoor)-[~/桌面] └─# where echo echo: shell built-in command echo /bin/echo ┌──(roottoor)-[~/桌面] └─# where whoami/usr/bin/whoami /bin/whoami ┌──(roottoor)-[~/桌面] └─#

重视:在Linux平台,有些命令虽然为内建命令,然则系统关键目录存在其可执行文件。

这儿能够运用enablehelp指令,查看终端内建的所有指令

第1种:enable指令┌──(roottoor)-[~/桌面] └─# enable - . : [ alias autoload bg bindkey break builtin bye cd chdir command compadd comparguments compcall compctl compdescribe compfiles compgroups compquote compset comptags comptry compvalues continue declare dirs disable disown echo echotc echoti emulate enable eval exec exit export false fc fg float functions getln getopts hash history integer jobs kill let limit local log logout noglob popd print printf private pushd pushln pwd r read readonly rehash return sched set setopt shift source suspend test times trap true ttyctl type typeset ulimit umask unalias unfunction unhash unlimit unset unsetopt vared wait whence where which zcompile zformat zle zmodload zparseopts zregexparse zstat zstyle ┌──(roottoor)-[~/桌面] └─# 第二种:help指令

接着对终端(内置|外置)命令进行测试,测试终端/bin/zsh

测试:whoami指令

先对whoami指令进行类型探测与指令定位查找

# 指令探测:非内置指令 ┌──(roottoor)-[~/桌面] └─# type whoami whoami is /usr/bin/whoami ┌──(roottoor)-[~/桌面] └─# # 指令定位查找:搜索发掘系统特殊目录存在`whoami`可执行程序 ┌──(roottoor)-[~/桌面] └─# where whoami /usr/bin/whoami /bin/whoami ┌──(roottoor)-[~/桌面] └─#

重视/bin目录为/usr/bin目录的链接

而后,在zsh终端写入For循环执行whoami指令查看是不是为内部执行或外边调用

for n in {0..10000000}; do whoami ; done

一边运用htop动态进程监控程序对该终端进行监控,可发掘whoami指令并非zsh终端内置封装的指令

测试:echo指令

一样,对echo指令进行类型探测与指令定位查找

# 指令探测:内置指令 ┌──(roottoor)-[~/桌面] └─# type echo echo is a shell builtin ┌──(roottoor)-[~/桌面] └─# # 指令定位查找:搜索发掘系统特殊目录存在`echo`可执行程序,同期发掘存在`echo: shell built-in command`【终端内置指令】 ┌──(roottoor)-[~/桌面] └─# where echo echo: shell built-incommand /usr/bin/echo /bin/echo ┌──(roottoor)-[~/桌面] └─#

而后,在zsh终端写入For循环执行echo指令查看是不是为内部执行或外边调用

for n in {0..10000000}; do echo 1 ; done

一边运用htop动态进程监控程序对该终端进行监控,能够发掘echo指令为zsh终端内置封装的指令,并未显现外边调用

Windows

Windows下终端通常cmd.exepowershell.exe等,这儿cmd来测试。终端指令执行原理同以上Linux讲解原理相同,分为终端内置指令与外边调用指令。

那样,针对Windows平台可执行终端,怎样进行终端内建指令的判断与查看呢。可惜Windows平台终端不像Linux终端存在相应的type指令进行判断与enablehelp指令查看所有内建指令。不外在Windows终端里能够借助whereset PATH指令进行指令判断。

第1种:where指令【不太友好】

从系统环境变量PATH里面定位查找重视人为增添的环境变量的影响),倘若能查到通常来讲能够判定为外边调用指令(排除非系统特殊目录),否则为内部调用指令(排除不存在指令)

# 外边调用指令 C:\Users\Qftm>where whoami C:\Windows\System32\whoami.exe C:\Users\Qftm> # 内部调用指令 C:\Users\Qftm>where cd INFO: Could not find files for the given pattern(s). C:\Users\Qftm> # 不存在指令 C:\Users\Qftm>where qftm INFO: Could not find files for the given pattern(s). C:\Users\Qftm> # 内部调用指令(排除人为增添的环境变量的影响)(排除非系统特殊目录) C:\Users\Qftm>where echo D:\QSoftware\W3Server\phpstudy2019\Extensions\MySQL5.7.26\bin\echo.exe C:\Users\Qftm> 第二种:set path指令【友好】

将系统环境变量临时设置为null而后对指令进行帮忙查找倘若能查到则判定为内置指令,否则为外边调用。

# path置空C:\Users\Qftm>set path= C:\Users\Qftm>path PATH=(null) C:\Users\Qftm># 内部调用指令C:\Users\Qftm>cd /? Displays the name of or changes the current directory. CHDIR [/D] [drive:][path] CHDIR [..] CD [/D] [drive:][path] CD [..] .. Specifies that you want to change to the parent directory. Type CD drive: to display the current directory in the specified drive. Type CD without parameters to display the current drive and directory. Use the /D switch to change current drive in addition to changing current directory for a drive. If Command Extensions are enabled CHDIR changes as follows: The current directory string is converted to use the same case as the on disk names. So CD C:\TEMP would actually set the current directory to C:\Temp if that is the case on disk. CHDIR command does not treat spaces as delimiters, so it is possible to CD into a subdirectory name that contains a space without surrounding the name with quotes. For example: cd \winnt\profiles\username\programs\start menuis the same as: cd "\winnt\profiles\username\programs\start menu" which is what you would have to type if extensions were disabled. C:\Users\Qftm> # 外边调用指令 C:\Users\Qftm>whoami /? whoami is not recognized as an internal or external command, operable program or batch file. C:\Users\Qftm> # 不存在指令 C:\Users\Qftm>qftm /? qftm is not recognized as an internal or external command, operable program or batch file. C:\Users\Qftm>

重视:Windows下终端help指令并不可查找终端内建指令:首要help指令为外边调用指令,而后help指令查找出的所有指令=(内建指令+外边指令)

# help:属于外边指令 C:\Users\Qftm>where help C:\Windows\System32\help.exe C:\Users\Qftm> # help:内建指令+外边指令(区别于Linux下bash等终端) C:\Users\Qftm>help For more information on a specific command, type HELP command-name ASSOC Displays or modifies file extension associations. ATTRIB Displays or changes file attributes. BREAK Sets or clears extended CTRL+C checking. BCDEDIT Sets properties in boot database to control boot loading. CACLS Displays or modifies access control lists (ACLs) of files. CALL Calls one batch program from another. CD Displays the name of or changes the current directory. CHCP Displays or sets the active code page number. CHDIR Displays the name of or changes the current directory. CHKDSK Checks a disk and displays a status report. CHKNTFS Displays or modifies the checking of disk at boot time. CLS Clears the screen. CMD Starts a new instance of the Windows command interpreter. COLOR Sets the default console foreground and bac公斤round colors. COMP Compares the contents of two files or sets of files. COMPACT Displays or alters the compression of files on NTFS partitions. CONVERT Converts FAT volumes to NTFS. You cannot convert the current drive. COPY Copies one or more files to another location. DATE Displays or sets the date. DEL Deletes one or more files. DIR Displays a list of files and subdirectories in a directory. DISKPART Displays or configures Disk Partition properties. DOSKEY Edits command lines, recalls Windows commands, and creates macros. DRIVERQUERY Displays current device driver status and properties. ECHO Displays messages, or turns command echoing on or off. ENDLOCAL Ends localization of environment changes in a batch file. ERASE Deletes one or more files. EXIT Quits the CMD.EXE program (command interpreter). FC Compares two files or sets of files, and displays the differences between them. FIND Searches for a text string in a file or files. FINDSTR Searches for strings in files. FOR Runs a specified command for each file in a set of files. FORMAT Formats a disk for use with Windows. FSUTIL Displays or configures the file system properties. FTYPE Displays or modifies file types used in file extension associations. GOTO Directs the Windows command interpreter to a labeled line in a batch program. GPRESULT Displays Group Policy information for machine or user. GRAFTABL Enables Windows to display an extended character set in graphics mode. HELP Provides Help information for Windows commands. ICACLS Display, modify, backup, or restore ACLs for files and directories. IF Performs conditional processing in batch programs. LABEL Creates, changes, or deletes the volume label of a disk. MD Creates a directory. MKDIR Creates a directory. MKLINK Creates Symbolic Links and Hard Links MODE Configures a system device. MORE Displays output one screen at a time. MOVE Moves one or more files from one directory to another directory. OPENFILES Displays files opened by remote users for a file share. PATH Displays or sets a search path for executable files. PAUSE Suspends processing of a batch file and displays a message. POPD Restores the previous value of the current directory saved by PUSHD. PRINT Prints a text file. PROMPT Changes the Windows command prompt. PUSHD Saves the current directory then changes it. RD Removes a directory. RECOVER Recovers readable information from a bad or defective disk. REM Records comments (remarks) in batch files or CONFIG.SYS. REN Renames a file or files. RENAME Renames a file or files. REPLACE Replaces files. RMDIR Removes a directory. ROBOCOPY Advanced utility to copy files and directory trees SET Displays, sets, or removes Windows environment variables. SETLOCAL Begins localization of environment changes in a batch file. SC Displays or configures services (bac公斤round processes). SCHTASKS Schedules commands and programs to run on a computer. SHIFT Shifts the position of replaceable parameters in batch files. SHUTDOWN Allows proper local or remote shutdown of machine. SORT Sorts input. START Starts a separate window to run a specified program or command. SUBST Associates a path with a drive letter. SYSTEMINFO Displays machine specific properties and configuration. TASKLIST Displays all currently running tasks including services. TASKKILL Kill or stop a running process or application. TIME Displays or sets the system time. TITLE Sets the window title for a CMD.EXE session. TREE Graphically displays the directory structure of a drive or path. TYPE Displays the contents of a text file. VER Displays the Windows version. VERIFY Tells Windows whether to verify that your files are written correctly to a disk. VOL Displays a disk volume label and serial number. XCOPY Copies files and directory trees. WMIC Displays WMI information inside interactive command shell. For more information on tools see the command-line reference in the online help. C:\Users\Qftm>

接着对终端(内置|外置)命令进行测试,测试终端cmd.exe

测试:whoami指令

先对whoami指令进行类型探测与指令定位查找

# 类型探测:外边调用指令 # 定位查找:系统可执行程序 C:\Users\Qftm>where whoami C:\Windows\System32\whoami.exe C:\Users\Qftm>

而后,在cmd终端写入For循环执行whoami指令查看是不是为内部执行或外边调用

C:\Users\Qftm>for /l %i in (1,1,1000000) do whoami

一边,打开任务管理进行cmd终端的监控,可发掘whoami指令并非cmd.exe终端内置封装的指令

测试:echo指令

一样,对echo指令进行类型探测与指令定位查找

# 类型探测:内部调用指令 # 定位查找:非系统可执行程序 C:\Users\Qftm>where echo D:\QSoftware\W3Server\phpstudy2019\Extensions\MySQL5.7.26\bin\echo.exe C:\Users\Qftm>

而后,在cmd终端写入For循环执行echo指令查看是不是为内部执行或外边调用

for /l %i in (1,1,1000000) do echo 1

一边,打开任务管理进行cmd终端的监控,能够发掘echo指令为终端内置封装的指令,并未显现外边调用

语言差异

针对命令执行函数,底层实现上是不是存在命令执行程序 cmd.exe/bin/sh/bin/bash等,去执行命令执行函数传入的参数【系统命令】。这个过程相当于底层是不是引入第三方可执行终端去执行相应命令。

例如可执行函数(系统命令)

CommandExecFunc(echo 111 > shell.txt); //echo是一个可执行程序

以上命令执行函数模型在【Linux平台/windows平台】区别语言下面执行效果区别

PHP

PHP - 底层调用系统终端,执行命令 Mode => Window:cmd.exe /c Command || Linux:sh -c Command

PHP语言里面,针对Linux平台,系统命令echo 111 > shell.txt传入CommandExecFunc函数,最后在底层相当于执行/bin/sh -c echo 111 > shell.txt。成功创建文件shell.txt【执行过程相当于:在/bin/sh终端下执行命令echo 111,并将echo结果经过重定向符写入文件shell.txt中。这儿的重定向符不是echo中的参数或字符串,而是在/bin/sh下面起特殊功效这儿的echo并不是可执行程序/bin/echo,而是/bin/sh执行终端中的内建命令】【进程关联:一个进程/bin/sh,在/bin/sh进程中执行系统命令,而不是执行系统程序】

跟踪一下程序执行流程:For Linux

利用strace程序执行监测可知,底层经过execve系统调用来起步关联进程、而后经过/bin/sh进程来执行关联指令(此处echosh内置指令)。

┌──(roottoor)-[~/桌面/CodeDebug/php] └─# strace -f -e execve php -r "system(echo 111 > shell.txt);" execve("/usr/bin/php", ["php", "-r", "system(echo 111 > shell.txt);"], 0x7ffd51277198 /* 53 vars */) = 0 strace: Process 3436 attached [pid 3436] execve("/bin/sh", ["sh", "-c", "echo 111 > shell.txt"], 0x562c96ef1eb0 /* 53 vars */) = 0 [pid 3436] +++ exited with 0 +++ --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=3436, si_uid=0, si_status=0, si_utime=0, si_stime=0} --- +++ exited with 0 +++ ┌──(roottoor)-[~/桌面/CodeDebug/php] └─# ls shell.txt ┌──(roottoor)-[~/桌面/CodeDebug/php] └─#

同理,针对Windows平台:系统命令echo 111 > shell.txt传入CommandExecFunc函数,最后在底层相当于执行cmd.exe /c echo 111 > shell.txt。成功创建文件shell.txt【执行过程相当于:在cmd终端下执行命令echo 111,并将echo结果经过重定向符写入文件shell.txt中。【进程关联:一个进程cmd.exe,在cmd.exe进程中执行系统命令,而不是执行系统程序】

跟踪一下程序执行流程:For Windows

运用OD动态调试,加载php.exe程序,对关联创建进程的系统API下断点(倘若晓得是那个CreateProcess API能够查找到的都进行断点就可

断点之后,F9使程序运行至用户交互处,而后输入PHP执行指令system(echo 111 > shell.txt);

运行PHP执行指令后,程序可到断点处,而后经过调用栈可知:底层经过CreateProcessW系统API调用来起步关联进程、而后经过cmd进程来执行关联指令(此处echocmd内置指令)(重视这儿可查看到PHP程序的完整调用链)

Java

Java - 底层不调用系统终端,自己起步传入的可执行程序 Mode => Window:Command || Linux:Command

然则Java语言里面,针对Linux平台,系统命令echo 111 > shell.txt传入CommandExecFunc函数,最后在底层相当于执行/bin/echo 111 > shell.txt成功打印一个字符串"111 > shell.txt"创建文件shell.txt。【执行过程相当于:运行可执行程序/bin/echo并传入参数111 > shell.txt进行打印输出,这儿的特殊字符>被当作普通字符串被echo程序打印。这儿echo做为可执行程序显现,而不是终端中的命令】【进程关联:一个进程/bin/echo,在/bin/echo进程中传入字符串参数111 > shell.txt进行打印输出】【相关可执行程序怎么查找:从环境变量中进行查找

测试代码如下

import org.apache.commons.io.IOUtils; import java.lang.Runtime; public class CommandExec1 { public static void main(String[] args) { try{ String str = IOUtils.toString(Runtime.getRuntime().exec("whoami").getInputStream()); System.out.println(str); } catch(Exception a){ System.out.println(a); } } } 跟踪一下程序执行流程:For Linux

程序执行监测状况:从系统环境变量中查询输入的指令可执行程序位置,而后execve系统调用来起步关联程序进程(并未触及系统终端调用)。

┌──(roottoor)-[~/桌面/CodeDebug/java] └─# strace -f -e execve java CommandExec1 execve("/usr/bin/java", ["java", "CommandExec1"], 0x7ffdb259ee90 /* 53 vars */) = 0 strace: Process 3923 attached Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true [pid 3923] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=NULL} --- strace: Process 3924 attached strace: Process 3925 attached strace: Process 3926 attached strace: Process 3927 attached strace: Process 3928 attached strace: Process 3929 attached strace: Process 3930 attached strace: Process 3931 attached strace: Process 3932 attached [pid 3932] execve("/mnt/hgfs/QSec/Pentest/Red-Team/\347\245\236\345\205\265\345\210\251\345\231\250/Windows/VSCode/VSCode-linux-x64/whoami", ["whoami"], 0x7ffd28368b80 /* 53 vars */) = -1 ENOENT (那个文件或目录) [pid 3932] execve("/usr/local/sbin/whoami", ["whoami"], 0x7ffd28368b80 /* 53 vars */) = -1 ENOENT (那个文件或目录) [pid 3932] execve("/usr/local/bin/whoami", ["whoami"], 0x7ffd28368b80 /* 53 vars */) = -1 ENOENT (那个文件或目录) [pid 3932] execve("/usr/sbin/whoami", ["whoami"], 0x7ffd28368b80 /* 53 vars */) = -1 ENOENT (那个文件或目录) [pid 3932] execve("/usr/bin/whoami", ["whoami"], 0x7ffd28368b80 /* 53 vars */) = 0 [pid 3932] +++ exited with 0 +++ [pid 3923] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=3932, si_uid=0, si_status=0, si_utime=0, si_stime=0} --- strace: Process 3933 attached root [pid 3931] +++ exited with 0 +++ [pid 3927] +++ exited with 0 +++ [pid 3924] +++ exited with 0 +++ [pid 3923] +++ exited with 0 +++ [pid 3933] +++ exited with 0 +++ [pid 3930] +++ exited with 0 +++ [pid 3929] +++ exited with 0 +++ [pid 3928] +++ exited with 0 +++ [pid 3926] +++ exited with 0 +++ [pid 3925] +++ exited with 0 +++ +++ exited with 0 +++ ┌──(roottoor)-[~/桌面/CodeDebug/java] └─#

同理,针对Windows平台,系统命令echo 111 > shell.txt传入CommandExecFunc函数,最后在底层相当于执行系统环境变量/echo.exe 111 > shell.txt成功打印一个字符串"111 > shell.txt"创建文件shell.txt

然则,正常状况下,这儿执行以上指令会报错,由于Windows平台,默认状况下系统环境变量中不存在echo.exe可执行程序,引起指令没法正常执行

# 没法定位echo可执行程序 D:\QSec\Code-Audit\Tools\Java\Kits\RCE>where echo INFO: Could not find files for the given pattern(s). D:\QSec\Code-Audit\Tools\Java\Kits\RCE>where whoami C:\Windows\System32\whoami.exe D:\QSec\Code-Audit\Tools\Java\Kits\RCE> # 执行报错 D:\QSec\Code-Audit\Tools\Java\Kits\RCE>javac RuntimeRCE.java D:\QSec\Code-Audit\Tools\Java\Kits\RCE>java RuntimeRCE java.io.IOException: Cannot run program "echo": CreateProcess error=2, The system cannot find the file specified D:\QSec\Code-Audit\Tools\Java\Kits\RCE>

Python

Python - 底层调用系统终端,执行命令 Mode => Window:cmd.exe /c Command || Linux:sh -c Command

Python语言,命令执行函数底层原理实现同PHP语言。

总结起来,便是,命令执行函数执行分为两类,一类:传入的命令仅仅做为可执行终端中的命令执行;另一类:传入的命令仅仅是运行传入的命令中的可执行程序。对象区别,一类:是底层语言系统终端帮咱们执行传入的命令;另一类:是自己起步传入的可执行程序。

参考链接

Build your own PHP on WindowsVisual Studio docsVisual Studio Code docs《PHP 7底层设计与源码实现+PHP7内核剖析》深入理解 PHP 内核WINDOWS下用VSCODE调试PHP7源代码调式PHP源码用vscode调试php源码GDB: The GNU Project DebuggerCreateProcessW function命令注入成因小谈浅谈从PHP内核层面防范PHP WebShellProgram execution Functionslinux系统调用system calls




上一篇:PHP代码审计中你不晓得的牛叉技术点
下一篇:深入解析PHP代码审计技术与实战【网络安全】
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站点统计|Archiver|手机版|小黑屋|天涯论坛 ( 非经营性网站 )|网站地图

GMT+8, 2024-11-23 00:17 , Processed in 0.121914 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.