攻防世界: ics-05
本文知识点
preg_replace可执行代码漏洞的使用
preg_replace有三个参数,第一个参数是正则的模式字符串,第二个是替换的数据,第三个是正则模式字符串要去匹配的字符串。
当正则的模式字符串与要匹配的字符串匹配时(即第一个参数与第三个参数匹配),就会使用替换数据(第二个参数)进行替换。
当正则的第一个参数包含
/e的时候就能触发代码执行的逻辑,具体可看后文。
题目总览
点击下图中的红框位置,跳转到设备维护中心的页面
然后再次点击云平台设备维护中心,可以看到浏览器中出现了page参数,因此怀疑其是一个文件包含的漏洞。
原始文件获取
使用前面提到过的php伪协议,将index.php转换为base64的编码输出。(为什么转换为base64, 因为文件包含漏洞的后端代码可能是include $page,如果这是一个php的代码,php代码的执行引擎会直接执行,而不会将原始文件返回给我们)
我们希望得到原始的文件,方便我们分析怎么绕过,得到flag。
将上述的base64解码,得到下面的php内容:
<?phperror_reporting(0);@session_start();posix_setuid(1000);?><!DOCTYPEHTML><html><head><meta charset="utf-8"><meta name="renderer"content="webkit"><meta http-equiv="X-UA-Compatible"content="IE=edge,chrome=1"><meta name="viewport"content="width=device-width, initial-scale=1, maximum-scale=1"><link rel="stylesheet"href="layui/css/layui.css"media="all"><title>设备维护中心</title><meta charset="utf-8"></head><body><ulclass="layui-nav"><liclass="layui-nav-item layui-this"><a href="?page=index">云平台设备维护中心</a></li></ul><fieldsetclass="layui-elem-field layui-field-title"style="margin-top: 30px;"><legend>设备列表</legend></fieldset><tableclass="layui-hide"id="test"></table><script type="text/html"id="switchTpl"><!--这里的 checked 的状态只是演示--><input type="checkbox"name="sex"value="{{d.id}}"lay-skin="switch"lay-text="开|关"lay-filter="checkDemo"{{d.id==10003?'checked':''}}></script><script src="layui/layui.js"charset="utf-8"></script><script>layui.use('table',function(){vartable=layui.table,form=layui.form;table.render({elem:'#test',url:'/somrthing.json',cellMinWidth:80,cols:[[{type:'numbers'},{type:'checkbox'},{field:'id',title:'ID',width:100,unresize:true,sort:true},{field:'name',title:'设备名',templet:'#nameTpl'},{field:'area',title:'区域'},{field:'status',title:'维护状态',minWidth:120,sort:true},{field:'check',title:'设备开关',width:85,templet:'#switchTpl',unresize:true}]],page:true});});</script><script>layui.use('element',function(){varelement=layui.element;//导航的hover效果、二级菜单等功能,需要依赖element模块//监听导航点击element.on('nav(demo)',function(elem){//console.log(elem)layer.msg(elem.text());});});</script><?php$page=$_GET[page];if(isset($page)){if(ctype_alnum($page)){?><br/><br/><br/><br/><div style="text-align:center"><pclass="lead"><?phpecho$page;die();?></p><br/><br/><br/><br/><?php}else{?><br/><br/><br/><br/><div style="text-align:center"><pclass="lead"><?phpif(strpos($page,'input')>0){die();}if(strpos($page,'ta:text')>0){die();}if(strpos($page,'text')>0){die();}if($page==='index.php'){die('Ok');}include($page);die();?></p><br/><br/><br/><br/><?php}}//方便的实现输入输出的功能,正在开发中的功能,只能内部人员测试if($_SERVER['HTTP_X_FORWARDED_FOR']==='127.0.0.1'){echo"<br >Welcome My Admin ! <br >";$pattern=$_GET[pat];$replacement=$_GET[rep];$subject=$_GET[sub];if(isset($pattern)&&isset($replacement)&&isset($subject)){preg_replace($pattern,$replacement,$subject);}else{die();}}?></body></html>代码分析
重点关注下面的代码,前面提到的知识点,我们可以利用preg_replace函数的可执行漏洞,执行我们想执行的任何代码。
HTTP_X_FORWARDED_FOR这个请求头就是客户端的ip地址,我们知道这个地址是能通过x-forwarded-for的请求头进行伪造的。
`if($_SERVER['HTTP_X_FORWARDED_FOR']==='127.0.0.1'){echo"<br >Welcome My Admin ! <br >";$pattern=$_GET[pat];$replacement=$_GET[rep];$subject=$_GET[sub];if(isset($pattern)&&isset($replacement)&&isset($subject)){preg_replace($pattern,$replacement,$subject);}else{die();}}破解思路
通过前面的分析,我能想到的一条路径就是发送一个x-forwarded-for的请求头,到达preg_replace函数的处理逻辑,然后利用这个函数的漏洞,执行任意代码,从而拿到flag。
尝试执行
ls系统命令,得到对应的文件名或则文件夹名称。(如果你不知道谁是文件还是文件夹,可以执行ls -l命令)使用
cat命令查看flag。
注意:
这里我有几个踩坑的地方
- pat参数不能够匹配sub参数,导致代码没有得到执行。(最简单的情况就是pat是sub 的子字符串)
- 由于我直接在burp suite中进行改包,忘记将参数进行uri的编码了,导致执行失败
uri编码小知识
- 对Url进行编码后可以将一些特殊字符和汉字变为Encode编码格式
- encodeURI方法不会对下列字符编码 ASCII字母、数字、~!@#$&*()=:/,;?+’
- encodeURIComponent方法不会对下列字符编码 ASCII字母、数字、~!*()’
- encodeURIComponent编码的范围更广,会将http://XXX中的//也编码,会导致URL不可用。