### 简要描述:
php云人才系统 小漏洞一步步getshell,这里包含了php与mysql交互时候的特性(也算一个漏洞),还有phpyun自身图片的验证机制问题,等等,步骤比较艰辛,本来想在这里搞一个csrf呢,找了半天没有找到,到时找到一大堆xss,这里就不利用xss了,且看分析
### 详细说明:
首先我们做一个小测试:
对于mysql存储来说,建站者都会给每一个字段设置长度,然后当我们插入进去的数据长度超过了设置的长度,那么mysql是不会报错,然而会自然截断存储,这个就给我们编写程序的人留下了隐患。
利用场景分析
1.如果你上传的目录会保存到数据库里面,并且这里上传的文件采用白名单,那么我们就可以根据数据库这个特性绕过程序判断,然后进入数据库,存储一个不在白名单内的文件路径
2.当我们二次利用这个东西的时候,比如说include 或者required 就会执行php代码
发散思考,其实这个思路不仅仅利用在文件这里,我只是举个例子,比如说如果么有对email的长度做验证,那么我们就可以注册一个和管理员一样的email,当后续用这个email查询验证时候,我们所有的回话就是管理员的,这里不做赘述
开始进行测试:
[<img src="https://images.seebug.org/upload/201409/102341421e6a3d435eea659037e129ac8ce1a1fc.png" alt="3.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/102341421e6a3d435eea659037e129ac8ce1a1fc.png)
这里我们创建一个有两列,长度为5的字段,然后我们插入一个大于5的姓名,看看效果会怎样
insert into vff values('xxxxxxxxxx','xx')
我们发现结果里面就只有五个长度:
[<img src="https://images.seebug.org/upload/201409/10234455490607aa355c8ea50a77516a29e5e313.png" alt="4.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/10234455490607aa355c8ea50a77516a29e5e313.png)
这里我们在延伸一下,我们插入
insert into vff values('123 sdsd','xx')
[<img src="https://images.seebug.org/upload/201409/1023464264423f6bb27bae92ab0961c84ff3b3cc.png" alt="5.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/1023464264423f6bb27bae92ab0961c84ff3b3cc.png)
我们在用
select * from vff where name = '123'
这个是可以取出来的
[<img src="https://images.seebug.org/upload/201409/1023483824d0984e1ee48e44de086cfc737c5f23.png" alt="6.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/1023483824d0984e1ee48e44de086cfc737c5f23.png)
这里的东西不多赘述,下来我们直接看phpyun里面的代码:
corn.class.php:(line:94-100):
```
function run_action(){
if($_GET['id'])
{
$this->cron($_GET['id']);
}
$this->layer_msg('计划任务(ID:'.$_GET["id"].')执行成功!',9,0,"index.php?m=cron");
}
```
我们跟到$this->cron里面去看看:
common.php:(lines:1987-1999):
```
if($timestamp)
{
krsort($timestamp);
$croncache = current($timestamp);
ignore_user_abort();
set_time_limit(600);
if(file_exists(LIB_PATH.'cron/'.$croncache['dir']))
{
include(LIB_PATH.'cron/'.$croncache['dir']);
}
$nexttime = $this->nextexe($croncache);
```
看到了LIB_PATH.'cron/'.$croncache['dir'],然后如果存在则进入到了引用函数,执行了,
那么我们来分析一下$croncache['dir'],从哪里来的.......
cron.class.php:(lines:63-67):
```
if(!$id){
$_POST["ctime"]=mktime();
$nbid=$this->obj->insert_into("cron",$_POST);
$alert="计划任务(id:".$nbid.")添加成功!";
$this->croncache();
```
这里明显就是保存之后,然后生成缓存文件,跟到缓存文件继续查看:
cache.class.php:(lines:38-55)
```
public function cron_cache($dir){
$rows=$this->obj->DB_select_all("cron","`display`='1' order by id asc");
if(is_array($rows)){
foreach($rows as $key=>$value){
$cron_cache[$key]['id']=$value["id"];
$cron_cache[$key]['dir']=$value["dir"];
$cron_cache[$key]['type']=$value["type"];
$cron_cache[$key]['week']=$value["week"];
$cron_cache[$key]['month']=$value["month"];
$cron_cache[$key]['hour']=$value["hour"];
$cron_cache[$key]['minute']=$value["minute"];
$cron_cache[$key]['nexttime']=$value["nexttime"];
}
}
$data['cron']=ArrayToString2($cron_cache);
return $this->obj->made_web_array($this->cachedir.$dir,$data);
}
```
看到这里大家都明白了$cron_cache[$key]['dir']=$value["dir"];是从我们刚才存储到数据库里面的dir取出来的,我们在回头看看,刚才的那个有什么限制,
cron.class.php:(line:56-59):
```
$dirArr = explode('.',$_POST['dir']);
if(end($dirArr)!='php'){
$this->obj->ACT_layer_msg("无效的执行文件!",8,"index.php?m=cron");
}
```
发现这里只能是php文件,当然了根据刚才我们的思路,我们可以绕过去的,我们进入后台:
[<img src="https://images.seebug.org/upload/201409/11000013e37e8fe746b4f4bf57a2556bea71d8ae.png" alt="7.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/11000013e37e8fe746b4f4bf57a2556bea71d8ae.png)
[<img src="https://images.seebug.org/upload/201409/1100005356630fe8703ecf47bd1f9305f284e0c9.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/1100005356630fe8703ecf47bd1f9305f284e0c9.png)
这样一来这两张图,就可以把一个vvvv.png,存储到数据库中了,我们重新上传一个:
[<img src="https://images.seebug.org/upload/201409/110001516412b38298425db3a9cedf47315e708b.png" alt="2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/110001516412b38298425db3a9cedf47315e708b.png)
然后我们查看数据库,
[<img src="https://images.seebug.org/upload/201409/11000312a5f441236d65e2b2bd48440be4a5e616.png" alt="8.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/11000312a5f441236d65e2b2bd48440be4a5e616.png)
我们在去界面的另外一个地方点击执行
[<img src="https://images.seebug.org/upload/201409/11000454ca735374a069d32fc1252201f5faab39.png" alt="9.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/11000454ca735374a069d32fc1252201f5faab39.png)
[<img src="https://images.seebug.org/upload/201409/11000811a1002d47ced25050f3b7f9c35ffc1bdc.png" alt="10.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/11000811a1002d47ced25050f3b7f9c35ffc1bdc.png)
前面的着所有的一切,已经正式一个东西,此处可以绕过,并且通过文件包含可以执行代码
那么这个图片码怎么搞定,我们经过尝试,phpyun测试了上传头像和上传身份证一边,只有上传身份证没有对图片的内容做深度校验:
[<img src="https://images.seebug.org/upload/201409/110010551d899c5cae9726bd46e09e317777fece.png" alt="11.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/110010551d899c5cae9726bd46e09e317777fece.png)
我们上传后,看看上传上去的文件路径,
[<img src="https://images.seebug.org/upload/201409/11001230738bc92c2b1a5b6402f292a87494405c.png" alt="12.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/11001230738bc92c2b1a5b6402f292a87494405c.png)
我们看看图片内容改变了没有:
[<img src="https://images.seebug.org/upload/201409/110013410abfe8347fe09e582a84364b7c9f896c.png" alt="13.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/110013410abfe8347fe09e582a84364b7c9f896c.png)
果真这里没有变化,后续的我就不多说了,直接把那个shell.png换掉就可以了
### 漏洞证明:
暂无评论