信呼OA办公系统sql注入漏洞分析

漏洞描述

信呼OA办公系统uploadAction存在SQL注入漏洞,攻击者可利用该漏洞获取数据库敏感信息。

环境搭建

源码下载地址:https://github.com/rainrocka/xinhu
下载后解压到本地网站根目录下,配置好数据库,然后安装即可
图片.png
图片.png
默认密码是admin/123456,登录进去得更改一次密码

路由分析

在include/View.php中详细介绍了路由的定义

<?php  
if(!isset($ajaxbool))$ajaxbool = $rock->jm->gettoken('ajaxbool', 'false');  
$ajaxbool   = $rock->get('ajaxbool', $ajaxbool);  
$p  = PROJECT;//define('PROJECT', 'webmain');  
if(!isset($m))$m='index';  
if(!isset($a))$a='default';  
if(!isset($d))$d='';  
$m  = $rock->get('m', $m);  
$a  = $rock->get('a', $a);  
$d  = $rock->get('d', $d);define('M', $m);  
define('A', $a);  
define('D', $d);  
define('P', $p);$_m = $m;  
if($rock->contain($m, '|')){  $_mas = explode('|', $m);//以|分割变量m  $m= $_mas[0];  $_m = $_mas[1];  
}  
include_once($rock->strformat('?0/?1/?1Action.php',ROOT_PATH, $p));//调用strformat进行格式化,其中?0、?1 等是占位符  
$rand   = date('YmdHis').rand(1000,9999);//随机值  
if(substr($d,-1)!='/' && $d!='')$d.='/';//若$d最后一个字符不是/且$d不是空就在$d后面加一个/  
$errormsg   = '';  
$methodbool = true;  
$actpath    = $rock->strformat('?0/?1/?2?3',ROOT_PATH, $p, $d, $_m);//$actpath:根目录/webmain/$d/$_m  
define('ACTPATH', $actpath);  
$actfile    = $rock->strformat('?0/?1Action.php',$actpath, $m);//$actfile:根目录/webmain/$d/$_m/$mAction.php  
$actfile1   = $rock->strformat('?0/?1Action.php',$actpath, $_m);//$actfile1:根目录/webmain/$d/$_m/$_mAction.php  
$actbstr = null;  
//依次判断$actfile1以及$actfile哪个文件存在,哪个存在包含哪个  
if(file_exists($actfile1))  include_once($actfile1);  
if(file_exists($actfile)){  include_once($actfile);  $clsname    = ''.$m.'ClassAction';  $xhrock = new $clsname();//创建一个与$m相关类的对象  $actname    = ''.$a.'Action';//在$a后接一个Action  if($ajaxbool == 'true')//判断ajaxbool是否为true  $actname    = ''.$a.'Ajax';//在$a后接一个Ajax  if(method_exists($xhrock, $actname)){//检测类中是否存在该方法  $xhrock->beforeAction();  $actbstr = $xhrock->$actname();  $xhrock->bodyMessage = $actbstr;  if(is_string($actbstr)){echo $actbstr;$xhrock->display=false;}  if(is_array($actbstr)){echo json_encode($actbstr);$xhrock->display=false;}  }else{  $methodbool = false;  if($ajaxbool == 'false')echo ''.$actname.' not found;';  }  $xhrock->afterAction();  
}else{  echo 'actionfile not exists;';  $xhrock = new Action();  
}$_showbool = false;  
if($xhrock->display && ($ajaxbool == 'html' || $ajaxbool == 'false')){  $xhrock->smartydata['p']    = $p;  $xhrock->smartydata['a']    = $a;  $xhrock->smartydata['m']    = $m;  $xhrock->smartydata['d']    = $d;  $xhrock->smartydata['rand'] = $rand;  $xhrock->smartydata['qom']  = QOM;  $xhrock->smartydata['path'] = PATH;  $xhrock->smartydata['sysurl']= SYSURL;  $temppath   = ''.ROOT_PATH.'/'.$p.'/';  $tplpaths   = ''.$temppath.'/'.$d.''.$m.'/';  $tplname    = 'tpl_'.$m.'';  if($a!='default')$tplname  .= '_'.$a.'';  $tplname       .= '.'.$xhrock->tpldom.'';  $mpathname  = $tplpaths.$tplname;  if($xhrock->displayfile!='' && file_exists($xhrock->displayfile))$mpathname = $xhrock->displayfile;  if(!file_exists($mpathname) || !$methodbool){  if(!$methodbool){  $errormsg   = 'in ('.$m.') not found Method('.$a.');';  }else{  $errormsg   = ''.$tplname.' not exists;';  }  echo $errormsg;  }else{  $_showbool = true;  }  
}  
if($xhrock->display && ($ajaxbool == 'html' || $xhrock->tpltype=='html' || $ajaxbool == 'false') && $_showbool){  $xhrock->setHtmlData();  $da = $xhrock->smartydata;  foreach($xhrock->assigndata as $_k=>$_v)$$_k=$_v;  include_once($mpathname);  $_showbool = false;  
}

这里用get方式会接收m,d,a,ajaxbool参数

  • a j a x b o o l :用于判断请求是否为 A J A X 请求,默认值从 ajaxbool:用于判断请求是否为AJAX请求,默认值从 ajaxbool:用于判断请求是否为AJAX请求,默认值从rock->jm->gettoken获取。当ajaxbool为false时,是对xxxAction.php的内容访问,当ajaxbool为true时,是对xxxAjax.php的内容进行访问
  • $m, $a, $d:分别代表php文件名(不含Action)、动作名(action)、目录名(webadmin下的子目录),默认值分别为index,default、空字符串。

举例:index.php?a=deluser&m=imgroup&d=&ajaxbool=true&gid=38&sid=1

  • $m:user,表示请求的是webadmin下的imgroup 目录。
  • $a:list,表示请求的方法是 deluser。
  • ajaxbool:true,表示这是一个 AJAX 请求
    图片.png

漏洞分析

漏洞的位置在webmain/task/api/uploadAction.php中
核心代码在getmfilvAction()方法里边

	public function getmfilvAction(){$fileid = (int)$this->get('fileid','0');$frs 	= m('file')->getone($fileid);if(!$frs)return returnerror('不存在');$lujing	= $frs['filepathout'];if(isempt($lujing)){$lujing = $frs['filepath'];if(substr($lujing,0,4)!='http' && !file_exists($lujing))return returnerror('文件不存在了');}$fileext = $frs['fileext'];$fname = $this->jm->base64decode($this->get('fname'));$fname = (isempt($fname)) ? $frs['filename'] : ''.$fname.'.'.$fileext.'';$filepath = ''.UPDIR.'/'.date('Y-m').'/'.date('d').'_rocktpl'.rand(1000,9999).'_'.$fileid.'.'.$fileext.'';$this->rock->createtxt($filepath, file_get_contents($lujing));$uarr = array('filename' => $fname,'fileext' => $fileext,'filepath' => $filepath,'filesize' => filesize($filepath),'filesizecn' => $this->rock->formatsize(filesize($filepath)),'optid' 	=> $this->adminid,'optname' 	=> $this->adminname,'adddt' 	=> $this->rock->now,'ip' 		=> $this->rock->ip,'web' 		=> $this->rock->web,);$uarr['id'] = m('file')->insert($uarr);return returnsuccess($uarr);}

getmfilvAction 方法的主要功能是从数据库中获取文件信息,读取文件内容,生成新的文件,并将新文件的信息记录到数据库中。最后,返回生成文件的信息。
在该方法中有两个可以控制的参数,一个是fileid另一个是fname,但是fileid参数会进行类型转换为int类型存在注入几率几乎为零,其中fname还进行了base64解码操作,最后将两个参数的内容连同其他文件基本信息进行数据库的插入操作,在这个地方想要确定有sql注入需要确定get方法以及insert方法是否存在sql语句的过滤
进入Model.php中的inser()方法

	public function insert($arr){$nid = 0;if($this->record($arr, ''))$nid = $this->db->insert_id();return $nid;}

对传入的参数进行record方法的校验若不为false,那么就获取到其id值
跟进record方法
图片.png
再跟进 public function record( t a b l e , table, table,array,$where=‘’)

	{$addbool  	= true;if(!$this->isempt($where))$addbool=false;$cont		= '';if(is_array($array)){foreach($array as $key=>$val){$cont.=",`$key`=".$this->toaddval($val)."";}$cont	= substr($cont,1);}else{$cont	= $array;}$table = $this->gettables($table);if($addbool){$sql="insert into $table set $cont";}else{$where = $this->getwhere($where);$sql="update $table set $cont where $where";}return $this->tranbegin($sql);}

代码解读:该方法首先是是对where参数进行非空判断,前面代码是将where设置为空了,那么 a d d b o o l 就是 f a l s e 。接着就是判断 addbool就是false。接着就是判断 addbool就是false。接着就是判断array是否为数组,若是数组就进行遍历将每个字段和对应的值拼接到 c o n t 字符串中并调用 t o a d d v a l 方法确保传入的字符串被正确地格式化为 S Q L 语句中的字符串值,但该方法并没有对 s q l 进行任何过滤 ; 然后调用 g e t t a b l e s 设置表名,接着进入 e l s e 语句,我们清晰的看到 cont字符串中并调用toaddval方法确保传入的字符串被正确地格式化为 SQL 语句中的字符串值,但该方法并没有对sql进行任何过滤;然后调用gettables设置表名,接着进入else语句,我们清晰的看到 cont字符串中并调用toaddval方法确保传入的字符串被正确地格式化为SQL语句中的字符串值,但该方法并没有对sql进行任何过滤;然后调用gettables设置表名,接着进入else语句,我们清晰的看到sql变量直接将$cont语句拼接到了sql语句中
接着我们去get方法中看看该方法对传入的内容有什么过滤,来到rockClass.php中

	public function get($name,$dev='', $lx=0){$val=$dev;if(isset($_GET[$name]))$val=$_GET[$name];if($this->isempt($val))$val=$dev;return $this->jmuncode($val, $lx, $name);}

这个方法只是判断是否进行get传参如果传参成功就进行赋值操作,之后进行非空判断,调用jmucade方法()将其值返回。该方法中并没有对sql语句进行过滤
这个文件里有个construct()方法,实例化rockClass对象就会触发

	public function __construct(){		$this->ip		= $this->getclientip();$this->host		= isset($_SERVER['HTTP_HOST'])		? $_SERVER['HTTP_HOST']		: '' ;if($this->host && substr($this->host,-3)==':80')$this->host = str_replace(':80', '', $this->host);$this->url		= '';$this->isqywx	= false;$this->win		= php_uname();$this->HTTPweb	= isset($_SERVER['HTTP_USER_AGENT'])? $_SERVER['HTTP_USER_AGENT']	: '' ;$this->web		= $this->getbrowser();$this->unarr	= explode(',','1,2');$this->now		= $this->now();$this->date		= date('Y-m-d');$this->lvlaras  = explode(',','select ,alter table,delete ,drop ,update ,insert into,load_file,/*,*/,union,<script,</script,sleep(,outfile,eval(,user(,phpinfo(),select*,union%20,sleep%20,select%20,delete%20,drop%20,and%20');$this->lvlaraa  = explode(',','select,alter,delete,drop,update,/*,*/,insert,from,time_so_sec,convert,from_unixtime,unix_timestamp,curtime,time_format,union,concat,information_schema,group_concat,length,load_file,outfile,database,system_user,current_user,user(),found_rows,declare,master,exec,(),select*from,select*');$this->lvlarab	= array();foreach($this->lvlaraa as $_i)$this->lvlarab[]='';}

这里过滤大部分sql注入一些敏感字符,通过以上分析发现这个fname参数经过get传参后会进行base64decode方法进行base64解密,那么如果我们将filename传入恶意的sql语句进行base64编码,就会绕过rockClass.php中的construct方法中的sql语句的过滤,之后进行base64解密又拼接到sql语句造成sql注入的形成

漏洞验证

payload:

api.php?a=getmfilv&m=upload|api&d=task&fileid=1&fname=MScgYW5kIHNsZWVwKDMpIw==

payload解释:漏洞的位置在webmain/task/api/uploadAction.php中的getmfilv方法中,d传task参数表示在webadmin/task目录下,m传upload|api,第一部分 upload 会被赋值给 $m,第二部分 api 会被赋值给 $_m,表示
api下的uploadAction.php文件,a传getmfilv文件表示调用uploadAction.php的、getmfilv()方法,fname传sql注入的payload,进行base64编码

成功延时
图片.png
图片.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/17630.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot如何将lib和jar分离

遇到一个问题&#xff0c;就是每次maven package或者maven install后target中的jar很大&#xff0c;少的50几MB&#xff0c;大的100多兆 优化前&#xff1a; 优化后&#xff1a; 优化前 优化后压缩率77.2MB4.65MB93% 具体方案&#xff1a; pom.xml中 <build><…

ThreadLocal源码分析

文章目录 1.核心数据结构 ThreadLocalMap1.静态内部类 Entry2.真正存储数据的是table数组 2.ThreadLocal.set()方法源码详解1.set2.getMap3.ThreadLocalMap.set4.createMap5.rehash6.resize 3.ThreadLocalMap.get()详解1.get2.ThreadLocalMap.getEntry3.getEntryAfterMiss 4.Th…

VUE环境搭建

node.js安装 node npm – node Package Management 安装完成后&#xff0c;需要设置&#xff1a; npm config set prefix "D:\nodejs"注意&#xff1a;“D:\nodejs” 此处为自己安装的node.js路径。管理员身份运行 切换镜像源 npm config set registry https://r…

卷积神经网络实战人脸检测与识别

文章目录 前言一、人脸识别一般过程二、人脸检测主流算法1. MTCNN2. RetinaFace3. CenterFace4. BlazeFace5. YOLO6. SSD7. CascadeCNN 三、人脸识别主流算法1.deepface2.FaceNet3.ArcFace4.VGGFace5.DeepID 四、人脸识别系统实现0.安装教程与资源说明1. 界面采用PyQt5框架2.人…

深度学习框架探秘|Keras 应用案例解析以及 Keras vs TensorFlow vs PyTorch

引言 上一篇文章《深度学习框架探秘&#xff5c;Keras&#xff1a;深度学习的魔法钥匙》 我们初步学习了 Keras&#xff0c;包括它是什么、具备哪些优势&#xff08;简洁易用的 API、强大的兼容性、广泛的应用领域&#xff09;&#xff0c;以及基本使用方法。本文&#xff0c;…

在Win11电脑上安装mysql并成功登录

首先,参照菜鸟教程的mysql安装教程https://www.runoob.com/mysql/mysql-install.html,进行的步骤如下: 1.进入mysql官网https://dev.mysql.com/downloads/mysql/,如下图所示,选择需要的版本并下载。 2.点击 Download 按钮进入下载页面,点击下图中的 No thanks, just sta…

如何正确安装Stable Diffusion Web UI以及对应的xFormers

本文是我总结的步骤&#xff0c;验证了几次保证是对的。因为正确的安装 Stable Diffusion Web UI 以及对应的 xFormers 实在是太麻烦了&#xff0c;官方和网上的步骤都是残缺和分散的&#xff0c;加上国内网络速度不理想&#xff0c;所以需要一些额外步骤&#xff0c;之前研究出…

大模型WebUI:Gradio全解12——使用Agents和Tools智能代理工具构建UI(1)

大模型WebUI&#xff1a;Gradio全解12——使用Agents和Tools智能代理工具构建UI&#xff08;1&#xff09; 前言本篇摘要12. 使用Agents和Tools智能代理工具构建UI12.1 transformers.agents原理及示例12.1.1 代理概念、类型和构建1. 代理概念2. 代理类型3. 如何构建代理&#x…

图像变换:了解透视变换原理及OpenCV实现

图像透视变换是一种将图像从一个视角转换到另一个视角的技术&#xff0c;通常用于校正拍摄角度引起的变形&#xff0c;或者模拟不同视角下的场景。 一、图像透视变换的原理 定义 透视变换&#xff08;Perspective Transformation&#xff09;是将一个平面内的点映射到另一个平…

超纯水设备的智能化控制系统为用户带来安全简便的操作体验

随着信息技术的发展&#xff0c;智能化已经成为工业装备的重要发展方向之一。超纯水设备在这方面也走在了前列&#xff0c;配备了高性能的PLC控制系统及人机交互界面&#xff0c;实现了全方位的智能监控和自动化操作。本文将重点介绍该设备的智能化控制系统&#xff0c;探讨它如…

Cursor AI开发微信小程序教程

1. 准备工作 在开始开发之前&#xff0c;需要完成以下准备工作&#xff1a; 1.1 安装微信开发者工具 前往微信开发者工具官网下载并安装适合操作系统的开发者工具。注册微信小程序账号&#xff0c;登录微信公众平台&#xff08;https://mp.weixin.qq.com&#xff09;&#…

数仓:核心概念,数仓系统(ETL,数仓分层,数仓建模),数仓建模方法(星型模型,雪花模型,星座模型)和步骤

数仓建模的核心概念 事实表&#xff08;Fact Table&#xff09;&#xff1a; 存储业务过程的度量值&#xff08;如销售额、订单数量等&#xff09;。 通常包含外键&#xff0c;用于关联维度表。 维度表&#xff08;Dimension Table&#xff09;&#xff1a; 存储描述性信息&…

jsp页面跳转失败

今天解决一下jsp页面跳转失败的问题 在JavaWeb的学习过程中&#xff0c;编写了这样一段代码&#xff1a; <html> <body> <h2>Hello World!</h2><%--这里提交的路径&#xff0c;需要寻找到项目的路径--%> <%--${pageContext.request.context…

Linux Mem -- Where the mte store and check in the real hardware platform

目录 1 前言 2 MTE tag分类 3 Address tag 4 Memory tag 5 Tag Check 6 Cortex-A710 和 CI-700 系统示例&#xff1a; 1 前言 ARM的MTE允许分配、设置、比较一个 4bit的allocation tag 为16字节粒度的物理地址。当对MTE有一定了解后&#xff0c;应该会产生如下疑问&#…

Day1 25/2/14 FRI

【一周刷爆LeetCode&#xff0c;算法大神左神&#xff08;左程云&#xff09;耗时100天打造算法与数据结构基础到高级全家桶教程&#xff0c;直击BTAJ等一线大厂必问算法面试题真题详解&#xff08;马士兵&#xff09;】https://www.bilibili.com/video/BV13g41157hK?p3&v…

Windows环境管理多个node版本

前言 在实际工作中&#xff0c;如果我们基于Windows系统开发&#xff0c;同时需要维护老项目&#xff0c;又要开发新项目&#xff0c;且不同项目依赖的node版本又不同时&#xff0c;那么就需要根据项目切换不同的版本。本文使用Node Version Manager&#xff08;nvm&#xff0…

前端包管理器的发展以及Npm、Yarn和Pnpm对比

在现代前端开发中&#xff0c;包管理器是不可或缺的核心工具。随着 JavaScript 生态的快速发展&#xff0c;开发者经历了从 npm 一统天下到 Yarn 挑战格局&#xff0c;再到 pnpm 创新突破的技术演进。这里将对三种主流包管理器&#xff08;npm/Yarn/pnpm&#xff09;进行全方位…

leetcode 2915. 和为目标值的最长子序列的长度

题目如下 数据范围 本题就是典型的背包问题target就是容量&#xff0c;nums[i]就是第i个物品的重量。其实就是选最多的物品使得背包刚好装满。 令f(i,j)为当考虑到i - 1物品时刚好装到j重量的物品数。 当j > nums[j]时 有f(i,j) max(f(i - 1,j - nums[i - 1]) 1,f(i -…

ASP.NET Core 面试宝典【刷题系列】

文章目录 引言1、什么是 dot net core 的 startup class?2、什么是中间件?3、application builder 的 use 和 run 方法有什么区别?4、dot net core 管道里面的map拓展有什么作用?5、dot net core 里面的路径是如何处理的?6、如何在 dot net core 中激活 session 功能?7、…

BFS 走迷宫

#include<bits/stdc.h> using namespace std; int a[100][100],v[100][100];//访问数组 n,m<100 struct point {int x;int y;int step; }; queue<point> r;//申请队列 int dx[4]{0,1,0,-1};//四个方向 右下左上 int dy[4]{1,0,-1,0}; int main() { /* 5 4 1 …