当前位置:首页 > 百科

一元购php源码

去年帮朋友看了一个“一元购”的元购p源站点,服务器还挂着,元购p源数据库里躺着两万多条参与记录,元购p源后台管理员账号密码居然是元购p源admin/123456。这套源码在网上流传很广,元购p源PHP写的元购p源,结构粗糙但功能齐全——用户充值、元购p源参与夺宝、元购p源开奖公告、元购p源晒单分享,元购p源该有的元购p源模块一个不少。

我拉下来读了一遍,元购p源核心逻辑集中在ajax.php和pay.php两个文件里。元购p源用户花一块钱买一个“人次”,元购p源每个商品预设总人次,元购p源比如一部iPhone设定8000人次,卖完就开奖。开奖算法用的是mt_rand(1, $total),然后去匹配中奖号码。问题在于,这个随机数种子没有做任何额外处理,服务器时间戳直接作为seed传入。理论上只要知道开奖那一刻的大致时间窗口,就能暴力枚举出中奖号码。

更离谱的是支付回调。源码里pay.php接收第三方支付的异步通知,验证签名那段代码被注释掉了。注释掉的。也就是说,任何人构造一个带out_trade_no和total_fee的POST请求,就能白嫖充值。我本地搭了一套测试,用Postman发了个请求,账户余额直接从0跳到500。朋友看完沉默了半天,说了句“难怪之前有人充了十万”。

这套源码的目录结构倒是挺规整:/admin放后台,/includes放数据库连接和公共函数,/templates放前端模板,/data里是SQLite数据库文件——对,SQLite,不是MySQL。这意味着整站数据就是一个文件,谁拿到这个文件谁就拿到一切。我见过有人把/data目录直接暴露在公网上,浏览器访问/data/db.sqlite就能下载。里面包含所有用户的手机号、充值记录、收货地址。

前端交互用的是jQuery,版本1.9,2013年的东西。index.php里有一段计算“剩余人次”的JS,每次页面加载都去请求get_remain.php,这个接口没有做频率限制。写个脚本每秒请求一百次,能把剩余人次刷到负数——然后系统会认为商品已售罄,提前开奖。开奖结果?当然是脚本控制的那个账号中奖。

后台管理页面更随意。admin/goods.php里添加商品的表单,价格字段没有做类型校验,填个-1进去,商品价格变成负一块。用户购买时反而会倒扣余额变成正数。我试过填0.0001,系统四舍五入后显示“0元购”,但实际扣款还是按0.0001算。这种细节上的疏忽,在正规项目里活不过code review,但在这类源码里遍地都是。

数据库表设计也很有意思。users表里有个is_vip字段,默认值0,但没有任何代码去更新它。orders表里status字段用枚举,却只定义了0和1两个状态,退款流程压根没写。我翻遍所有PHP文件,找不到一个refund相关的函数。用户想退钱?只能找站长手动转账。而站长可能早就跑路了。

这套源码在GitHub上还有几个fork,有人加了Redis缓存,有人换了MySQL,但核心的支付验证和开奖逻辑几乎没人动过。改的人大概只关心页面好不好看,不关心钱会不会丢。我后来在本地把支付回调的签名验证补上了,用hash_hmac重新算了一遍,再测试就正常了。但那个mt_rand的开奖算法我没动——真要修,得引入random_int加外部熵源,工作量不小,而且改了之后历史数据对不上。

最后朋友没继续运营那个站。他把数据库导出来,给每个充值超过一千的用户发了短信,按比例退了钱。服务器关掉那天,他跟我说:“这东西就是个筛子,到处是洞。能跑起来全靠运气。”

分享到: