目录
源码
PHP7版本
PHP5版本
发现的现象和思考
源码
<?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__);
}
限制条件:
- webshell长度不超过35位
- 除了不包含字母数字,还不能包含
$
和_
PHP7版本
PHP修改了表达式的执行顺序,所以可以使用($a)()
这样的方式来执行函数,例('phpinfo')()
。但是这样的执行顺序在7版本前是不允许的
解决办法:($a)()
(~%8F%97%8F%96%91%99%90)(); //(phpinfo)()
PHP5版本
思路:利用文件上传生成一个临时文件,然后利用点‘.’执行生成的临时文件
/???/????????[@-[],该正则匹配的是/tmp/目录下的临时文件,临时文件一般是9位,最后以为字母为大写(不一定)
该部分上传的是文件中的内容,以id命令为例
发现的现象和思考
执行的命令需要紧跟文件内容的下线,当命令与下线有空行时,会不执行命令。并且有多条命令时,也只有紧靠着下线的命令会执行
当命令不紧跟着下线时,查看临时文件中的内容
创建一个a文件,并编写内容
使用diff命令进行临时文件与自己的文件对比
查看十六进制格式
可以发现自己编写的文件中只有0a,而临时文件中是0d0a
在hex编码中,0a代表换行符,0d代表回车符
通过查略知道,在Linux系统中,文件内容的换行符通常只使用换行符,其十六进制表示为0A,而不包含回车符,其十六进制表示为0D。这是因为Linux系统遵循的是Unix的传统,即使用LF(0A)作为行的结束符.
相比之下,Windows系统中的文本文件通常使用CR+LF(0D0A)作为行的结束符。如果你在Windows系统上编辑了一个文本文件,并将其传输到Linux系统上,然后使用`xxd`命令查看,你可能会在原本应该是LF(0A)的位置看到CR+LF(0D0A),除非你在传输或保存文件时进行了转换,以符合Linux的标准。
处理跨平台的文本文件时遇到了换行符不一致的问题,你可以使用各种工具来转换文件的换行符格式,比如`dos2unix`(将Windows风格的换行符转换为Unix/Linux风格的换行符)和`unix2dos`(将Unix/Linux风格的换行符转换为Windows风格的换行符)等。这些工具可以帮助你确保文件在不同操作系统之间正确地显示和处理。
通过执行文件,可以发现id这个命令收到了后面0d的影响
查略了一下网上,解释为:
Linux系统通常使用LF(0A)作为行的结束符。因此,如果文件原本是为Windows系统编写的(即使用CR+LF作为行的结束符),那么在Linux中直接查看或处理该文件时可能会遇到问题。
如果文件是二进制文件,并且包含`0D`作为数据的一部分(而不是作为行的结束符),那么这些`0D`字符将按原样保留,并在执行文件时作为数据的一部分进行处理
如果你尝试在Linux中执行一个包含`0D`字符的文本文件(而不是二进制文件),并且该文件没有被正确转换为Unix/Linux风格的换行符,那么执行操作可能会失败,因为Linux通常不会将文本文件作为可执行文件来处理。