response.sendRedirect("j_security_check?j_username="+usr+"&j_password="+pass);
...
var fs:FileStream = new FileStream();
fs.open(new File("config.properties"), FileMode.READ);
var decoder:Base64Decoder = new Base64Decoder();
decoder.decode(fs.readMultiByte(fs.bytesAvailable, File.systemCharset));
var password:String = decoder.toByteArray().toString();
URLRequestDefaults.setLoginCredentialsForHost(hostname, usr, password);
...
config.properties
具有访问权限的人都能读取 password
的值,并且很容易确定这个值是否经过 64 位基址编码。任何心怀不轨的雇员可以利用手中掌握的信息访问权限入侵系统。
...
string value = regKey.GetValue(passKey).ToString());
byte[] decVal = Convert.FromBase64String(value);
NetworkCredential netCred =
new NetworkCredential(username,decVal.toString(),domain);
...
password
的值。任何心怀不轨的雇员可以利用手中掌握的信息访问权限入侵系统。
...
RegQueryValueEx(hkey, TEXT(.SQLPWD.), NULL,
NULL, (LPBYTE)password64, &size64);
Base64Decode(password64, size64, (BYTE*)password, &size);
rc = SQLConnect(*hdbc, server, SQL_NTS, uid,
SQL_NTS, password, SQL_NTS);
...
password64
的值,并且很容易确定这个值是否经过 64 位基址编码。任何心怀不轨的雇员可以利用手中掌握的信息访问权限入侵系统。
...
01 RECORDX.
05 UID PIC X(10).
05 PASSWORD PIC X(10).
05 LEN PIC S9(4) COMP.
...
EXEC CICS
READ
FILE('CFG')
INTO(RECORDX)
RIDFLD(ACCTNO)
...
END-EXEC.
CALL "g_base64_decode_inplace" using
BY REFERENCE PASSWORD
BY REFERENCE LEN
ON EXCEPTION
DISPLAY "Requires GLib library" END-DISPLAY
END-CALL.
EXEC SQL
CONNECT :UID
IDENTIFIED BY :PASSWORD
END-EXEC.
...
CFG
具有访问权限的人都能读取密码值,并且很容易确定这个值是否经过 64 位基址编码。任何心怀不轨的雇员可以利用手中掌握的信息访问权限入侵系统。
...
file, _ := os.Open("config.json")
decoder := json.NewDecoder(file)
decoder.Decode(&values)
password := base64.StdEncoding.DecodeString(values.Password)
request.SetBasicAuth(values.Username, password)
...
config.json
具有访问权限的人都能读取 password
的值,并且很容易确定这个值是否经过 64 位基址编码。任何心怀不轨的雇员可以利用手中掌握的信息访问权限入侵系统。
...
Properties prop = new Properties();
prop.load(new FileInputStream("config.properties"));
String password = Base64.decode(prop.getProperty("password"));
DriverManager.getConnection(url, usr, password);
...
config.properties
具有访问权限的人都能读取 password
的值,并且很容易确定这个值是否经过 64 位基址编码。任何心怀不轨的雇员可以利用手中掌握的信息访问权限入侵系统。
...
webview.setWebViewClient(new WebViewClient() {
public void onReceivedHttpAuthRequest(WebView view,
HttpAuthHandler handler, String host, String realm) {
String[] credentials = view.getHttpAuthUsernamePassword(host, realm);
String username = new String(Base64.decode(credentials[0], DEFAULT));
String password = new String(Base64.decode(credentials[1], DEFAULT));
handler.proceed(username, password);
}
});
...
...
obj = new XMLHttpRequest();
obj.open('GET','/fetchusers.jsp?id='+form.id.value,'true','scott','tiger');
...
plist
文件读取密码,然后使用该密码解压缩受密码保护的文件。
...
NSDictionary *dict= [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Config" ofType:@"plist"]];
NSString *encoded_password = [dict valueForKey:@"encoded_password"];
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:encoded_password options:0];
NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
[SSZipArchive unzipFileAtPath:zipPath toDestination:destPath overwrite:TRUE password:decodedString error:&error];
...
Config.plist
文件具有访问权限的人都能读取 encoded_password
的值,并且很容易确定这个值是否经过 64 位基址编码。
...
$props = file('config.properties', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$password = base64_decode($props[0]);
$link = mysql_connect($url, $usr, $password);
if (!$link) {
die('Could not connect: ' . mysql_error());
}
...
config.properties
具有访问权限的人都能读取 password
的值,并且很容易确定这个值是否经过 64 位基址编码。任何心怀不轨的雇员可以利用手中掌握的信息访问权限入侵系统。
...
props = os.open('config.properties')
password = base64.b64decode(props[0])
link = MySQLdb.connect (host = "localhost",
user = "testuser",
passwd = password,
db = "test")
...
config.properties
具有访问权限的人都能读取 password
的值,并且很容易确定这个值是否经过 64 位基址编码。任何心怀不轨的雇员可以利用手中掌握的信息访问权限入侵系统。
require 'pg'
require 'base64'
...
passwd = Base64.decode64(ENV['PASSWD64'])
...
conn = PG::Connection.new(:dbname => "myApp_production", :user => username, :password => passwd, :sslmode => 'require')
PASSWD64
的值,并且很容易确定这个值是否经过 64 位基址编码。任何心怀不轨的雇员可以利用手中掌握的信息访问权限入侵系统。
...
val prop = new Properties();
prop.load(new FileInputStream("config.properties"));
val password = Base64.decode(prop.getProperty("password"));
DriverManager.getConnection(url, usr, password);
...
config.properties
具有访问权限的人都能读取password
的值,并且很容易确定这个值是否经过 64 位基址编码。任何心怀不轨的雇员可以利用手中掌握的信息访问权限入侵系统。plist
文件读取密码,然后使用该密码解压缩受密码保护的文件。
...
var myDict: NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("Config", ofType: "plist") {
myDict = NSDictionary(contentsOfFile: path)
}
if let dict = myDict {
let password = base64decode(dict["encoded_password"])
zipArchive.unzipOpenFile(zipPath, password:password])
}
...
Config.plist
文件具有访问权限的人都能读取 encoded_password
的值,并且很容易确定这个值是否经过 64 位基址编码。
...
root:qFio7llfVKk.s:19033:0:99999:7:::
...
...
...
Private Declare Function GetPrivateProfileString _
Lib "kernel32" Alias "GetPrivateProfileStringA" _
(ByVal lpApplicationName As String, _
ByVal lpKeyName As Any, ByVal lpDefault As String, _
ByVal lpReturnedString As String, ByVal nSize As Long, _
ByVal lpFileName As String) As Long
...
Dim password As String
...
password = StrConv(DecodeBase64(GetPrivateProfileString("MyApp", "Password", _
"", value, Len(value), _
App.Path & "\" & "Config.ini")), vbUnicode)
...
con.ConnectionString = "Driver={Microsoft ODBC for Oracle};Server=OracleServer.world;Uid=scott;Passwd=" & password &";"
...
Config.ini
具有访问权限的人都能读取 Password
的值,并且很容易确定这个值是否经过 64 位基址编码。任何心怀不轨的雇员可以利用手中掌握的信息访问权限入侵系统。
String password=request.getParameter("password");
...
DefaultUser user = (DefaultUser) ESAPI.authenticator().createUser(username, password, password);
...
*Get the report that is to be deleted
r_name = request->get_form_field( 'report_name' ).
CONCATENATE `C:\\users\\reports\\` r_name INTO dsn.
DELETE DATASET dsn.
...
..\\..\\usr\\sap\\DVEBMGS00\\exe\\disp+work.exe
”的文件夹名,应用程序会删除重要文件,导致 SAP 系统立即崩溃。
...
PARAMETERS: p_date TYPE string.
*Get the invoice file for the date provided
CALL FUNCTION 'FILE_GET_NAME'
EXPORTING
logical_filename = 'INVOICE'
parameter_1 = p_date
IMPORTING
file_name = v_file
EXCEPTIONS
file_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
OPEN DATASET v_file FOR INPUT IN TEXT MODE.
DO.
READ DATASET v_file INTO v_record.
IF SY-SUBRC NE 0.
EXIT.
ELSE.
WRITE: / v_record.
ENDIF.
ENDDO.
...
..\\..\\usr\\sap\\sys\\profile\\default.pfl
”的字符串,而不提供有效日期,应用程序将显示所有默认 SAP 应用程序服务器配置文件参数设置,这可能会导致更精确的攻击。../../tomcat/conf/server.xml
”一样的文件名,从而导致应用程序删除它自己的配置文件。示例 2:下面的代码使用来自于配置文件的输入来决定打开哪个文件,并写入“Debug”控制台或日志文件。如果程序以足够的权限运行,且恶意用户能够篡改配置文件,那么他们可以通过程序读取系统中以扩展名
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var rName:String = String(params["reportName"]);
var rFile:File = new File("/usr/local/apfr/reports/" + rName);
...
rFile.deleteFile();
.txt
结尾的任何文件。
var fs:FileStream = new FileStream();
fs.open(new File(String(configStream.readObject())+".txt"), FileMode.READ);
fs.readBytes(arr);
trace(arr);
public class MyController {
...
public PageRerference loadRes() {
PageReference ref = ApexPages.currentPage();
Map<String,String> params = ref.getParameters();
if (params.containsKey('resName')) {
if (params.containsKey('resPath')) {
return PageReference.forResource(params.get('resName'), params.get('resPath'));
}
}
return null;
}
}
..\\..\\Windows\\System32\\krnl386.exe
”这样的文件名,这会导致应用程序删除重要的 Windows 系统文件。示例 2:以下代码使用来自于配置文件的输入来决定打开哪个文件,并返回给用户。如果程序以足够的权限运行,并且恶意用户能够篡改配置文件,那么他们就可以使用该程序来读取系统中以“.txt”扩展名结尾的任何文件。
String rName = Request.Item("reportName");
...
File.delete("C:\\users\\reports\\" + rName);
sr = new StreamReader(resmngr.GetString("sub")+".txt");
while ((line = sr.ReadLine()) != null) {
Console.WriteLine(line);
}
../../apache/conf/httpd.conf
”一样的文件名,从而导致应用程序删除特定的配置文件。示例 2:以下代码使用来自于命令行的输入来决定该打开哪个文件,并返回到用户。如果程序以足够的权限运行,并且恶意用户能够创建指向文件的软链接,那么他们可以使用程序来读取系统中任何文件的开始部分。
char* rName = getenv("reportName");
...
unlink(rName);
ifstream ifs(argv[0]);
string s;
ifs >> s;
cout << s;
...
EXEC CICS
WEB READ
FORMFIELD(FILE)
VALUE(FILENAME)
...
END-EXEC.
EXEC CICS
READ
FILE(FILENAME)
INTO(RECORD)
RIDFLD(ACCTNO)
UPDATE
...
END-EXEC.
...
..\\..\\Windows\\System32\\krnl386.exe
”这样的文件名,这会导致应用程序删除重要的 Windows 系统文件。
<cffile action = "delete"
file = "C:\\users\\reports\\#Form.reportName#">
final server = await HttpServer.bind('localhost', 18081);
server.listen((request) async {
final headers = request.headers;
final path = headers.value('path');
File(path!).delete();
}
Example 1
中,在对文件执行删除功能之前未验证 headers.value('path')
。../../tomcat/conf/server.xml
”一样的文件名,从而导致应用程序删除它自己的配置文件。示例 2:下面的代码使用来自于配置文件的输入来决定打开哪个文件,并返回给用户。如果程序以足够的权限运行,且恶意用户能够篡改配置文件,那么他们可以通过程序读取系统中以扩展名
rName := "/usr/local/apfr/reports/" + req.FormValue("fName")
rFile, err := os.OpenFile(rName, os.O_RDWR|os.O_CREATE, 0755)
defer os.Remove(rName);
defer rFile.Close()
...
.txt
结尾的任何文件。
...
config := ReadConfigFile()
filename := config.fName + ".txt";
data, err := ioutil.ReadFile(filename)
...
fmt.Println(string(data))
../../tomcat/conf/server.xml
”一样的文件名,从而导致应用程序删除它自己的配置文件。示例 2:以下代码使用来自于配置文件的输入来决定打开哪个文件,并返回给用户。如果程序以足够的权限运行,且恶意用户能够篡改配置文件,那么他们可以通过程序读取系统中以扩展名
String rName = request.getParameter("reportName");
File rFile = new File("/usr/local/apfr/reports/" + rName);
...
rFile.delete();
.txt
结尾的任何文件。
fis = new FileInputStream(cfg.getProperty("sub")+".txt");
amt = fis.read(arr);
out.println(arr);
Example 1
以适应 Android 平台。
...
String rName = this.getIntent().getExtras().getString("reportName");
File rFile = getBaseContext().getFileStreamPath(rName);
...
rFile.delete();
...
../../tomcat/conf/server.xml
”一样的文件名,从而导致应用程序删除它自己的配置文件。示例 2:以下代码使用来自于本地存储的输入来决定该打开哪个文件,并返回到用户。如果恶意用户能够更改本地存储的内容,就可以使用该程序来读取系统中扩展名为
...
var reportNameParam = "reportName=";
var reportIndex = document.indexOf(reportNameParam);
if (reportIndex < 0) return;
var rName = document.URL.substring(reportIndex+reportNameParam.length);
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
fs.root.getFile('/usr/local/apfr/reports/' + rName, {create: false}, function(fileEntry) {
fileEntry.remove(function() {
console.log('File removed.');
}, errorHandler);
}, errorHandler);
}, errorHandler);
.txt
的任何文件。
...
var filename = localStorage.sub + '.txt';
function oninit(fs) {
fs.root.getFile(filename, {}, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function(e) {
var txtArea = document.createElement('textarea');
txtArea.value = this.result;
document.body.appendChild(txtArea);
};
reader.readAsText(file);
}, errorHandler);
}, errorHandler);
}
window.requestFileSystem(window.TEMPORARY, 1024*1024, oninit, errorHandler);
...
../../tomcat/conf/server.xml
”一样的文件名,从而导致应用程序删除它自己的配置文件。示例 2:下面的代码使用来自于配置文件的输入来决定打开哪个文件,并返回给用户。如果程序以足够的权限运行,且恶意用户能够篡改配置文件,那么他们可以通过程序读取系统中以扩展名
val rName: String = request.getParameter("reportName")
val rFile = File("/usr/local/apfr/reports/$rName")
...
rFile.delete()
.txt
结尾的任何文件。
fis = FileInputStream(cfg.getProperty("sub").toString() + ".txt")
amt = fis.read(arr)
out.println(arr)
Example 1
以适应 Android 平台。
...
val rName: String = getIntent().getExtras().getString("reportName")
val rFile: File = getBaseContext().getFileStreamPath(rName)
...
rFile.delete()
...
- (NSData*) testFileManager {
NSString *rootfolder = @"/Documents/";
NSString *filePath = [rootfolder stringByAppendingString:[fileName text]];
NSFileManager *fm = [NSFileManager defaultManager];
return [fm contentsAtPath:filePath];
}
../../tomcat/conf/server.xml
”一样的文件名,从而导致应用程序删除它自己的配置文件。示例 2:以下代码使用来自于配置文件的输入来决定打开哪个文件,并返回给用户。如果程序以足够的权限运行,且恶意用户能够篡改配置文件,那么他们可以通过程序读取系统中以扩展名
$rName = $_GET['reportName'];
$rFile = fopen("/usr/local/apfr/reports/" . rName,"a+");
...
unlink($rFile);
.txt
结尾的任何文件。
...
$filename = $CONFIG_TXT['sub'] . ".txt";
$handle = fopen($filename,"r");
$amt = fread($handle, filesize($filename));
echo $amt;
...
../../tomcat/conf/server.xml
”一样的文件名,从而导致应用程序删除它自己的配置文件。示例 2:以下代码使用来自于配置文件的输入来决定打开哪个文件,并返回给用户。如果程序以足够的权限运行,且恶意用户能够篡改配置文件,那么他们可以通过程序读取系统中以扩展名
rName = req.field('reportName')
rFile = os.open("/usr/local/apfr/reports/" + rName)
...
os.unlink(rFile);
.txt
结尾的任何文件。
...
filename = CONFIG_TXT['sub'] + ".txt";
handle = os.open(filename)
print handle
...
../../tomcat/conf/server.xml
”一样的文件名,从而导致应用程序删除它自己的配置文件。示例 2:以下代码使用来自于配置文件的输入来决定打开哪个文件,并返回给用户。如果程序以足够的权限运行,且恶意用户能够篡改配置文件,那么他们可以通过程序读取系统中以扩展名
rName = req['reportName']
File.delete("/usr/local/apfr/reports/#{rName}")
.txt
结尾的任何文件。
...
fis = File.new("#{cfg.getProperty("sub")}.txt")
amt = fis.read
puts amt
../../tomcat/conf/server.xml
”一样的文件名,从而导致应用程序删除它自己的配置文件。示例 2:以下代码使用来自于配置文件的输入来决定打开哪个文件,并返回给用户。如果程序以足够的权限运行,且恶意用户能够篡改配置文件,那么他们可以通过程序读取系统中以扩展名
def readFile(reportName: String) = Action { request =>
val rFile = new File("/usr/local/apfr/reports/" + reportName)
...
rFile.delete()
}
.txt
结尾的任何文件。
val fis = new FileInputStream(cfg.getProperty("sub")+".txt")
val amt = fis.read(arr)
out.println(arr)
func testFileManager() -> NSData {
let filePath : String = "/Documents/\(fileName.text)"
let fm : NSFileManager = NSFileManager.defaultManager()
return fm.contentsAtPath(filePath)
}
..\conf\server.xml
”一样的文件名,从而导致应用程序删除它自己的配置文件。示例 2:以下代码使用来自于配置文件的输入来决定打开哪个文件,并返回给用户。如果程序以足够的权限运行,且恶意用户能够篡改配置文件,那么他们可以通过程序读取系统中以扩展名
Dim rName As String
Dim fso As New FileSystemObject
Dim rFile as File
Set rName = Request.Form("reportName")
Set rFile = fso.GetFile("C:\reports\" & rName)
...
fso.DeleteFile("C:\reports\" & rName)
...
.txt
结尾的任何文件。
Dim fileName As String
Dim tsContent As String
Dim ts As TextStream
Dim fso As New FileSystemObject
fileName = GetPrivateProfileString("MyApp", "sub", _
"", value, Len(value), _
App.Path & "\" & "Config.ini")
...
Set ts = fso.OpenTextFile(fileName,1)
tsContent = ts.ReadAll
Response.Write tsContent
...
...
" Add Binary File to
CALL METHOD lr_abap_zip->add
EXPORTING
name = p_ifile
content = lv_bufferx.
" Read Binary File to
CALL METHOD lr_abap_zip->get
EXPORTING
name = p_ifile
IMPORTING
content = lv_bufferx2.
...
Example 1
中,在对此条目中的数据执行读取/写入函数之前未验证 p_ifile
。如果 ZIP 文件最初放置在基于 Unix 的计算机的 "/tmp/
" 目录中,并且 ZIP 条目为 "../etc/hosts
",而应用程序在必要的权限下运行,则它将覆盖系统的 hosts
文件,从而会使该计算机的流量进入攻击者所需的任何位置,例如返回至攻击者的计算机。
public static void UnzipFile(ZipArchive archive, string destDirectory)
{
foreach (var entry in archive.Entries)
{
string file = entry.FullName;
if (!string.IsNullOrEmpty(file))
{
string destFileName = Path.Combine(destDirectory, file);
entry.ExtractToFile(destFileName, true);
}
}
}
Example 1
中,在对此条目中的数据执行读取/写入操作之前不会对 entry.FullName
进行验证。如果此 Zip 文件最初放置在“C:\TEMP
”目录中,并且某个 Zip 条目名称包含“..\
segments”,而应用程序在所需的权限下运行,则它可以随意覆盖系统文件。
func Unzip(src string, dest string) ([]string, error) {
var filenames []string
r, err := zip.OpenReader(src)
if err != nil {
return filenames, err
}
defer r.Close()
for _, f := range r.File {
// Store filename/path for returning and using later on
fpath := filepath.Join(dest, f.Name)
filenames = append(filenames, fpath)
if f.FileInfo().IsDir() {
// Make Folder
os.MkdirAll(fpath, os.ModePerm)
continue
}
// Make File
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return filenames, err
}
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return filenames, err
}
rc, err := f.Open()
if err != nil {
return filenames, err
}
_, err = io.Copy(outFile, rc)
// Close the file without defer to close before next iteration of loop
outFile.Close()
rc.Close()
if err != nil {
return filenames, err
}
}
return filenames, nil
}
Example 1
中,在对此条目中的数据执行读取/写入函数之前未验证 f.Name
。如果 Zip 文件最初放置在基于 Unix 的计算机的“/tmp/
”目录中,并且 Zip 条目为“../etc/hosts
”,而应用程序在所需的权限下运行,则它将覆盖系统 hosts
文件。从而可能会使该计算机的流量进入攻击者所需的任何位置,例如返回至攻击者的计算机。
private static final int BUFSIZE = 512;
private static final int TOOBIG = 0x640000;
...
public final void unzip(String filename) throws IOException {
FileInputStream fis = new FileInputStream(filename);
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry zipEntry = null;
int numOfEntries = 0;
long total = 0;
try {
while ((zipEntry = zis.getNextEntry()) != null) {
byte data[] = new byte[BUFSIZE];
int count = 0;
String outFileName = zipEntry.getName();
if (zipEntry.isDirectory()){
new File(outFileName).mkdir(); //create the new directory
continue;
}
FileOutputStream outFile = new FileOutputStream(outFileName);
BufferedOutputStream dest = new BufferedOutputStream(outFile, BUFSIZE);
//read data from Zip, but do not read huge entries
while (total + BUFSIZE <= TOOBIG && (count = zis.read(data, 0, BUFSIZE)) != -1) {
dest.write(data, 0, count);
total += count;
}
...
}
} finally{
zis.close();
}
}
...
Example 1
中,在对此条目中的数据执行读取/写入函数之前未验证 zipEntry.getName()
。如果 Zip 文件最初放置在基于 Unix 的计算机的“/tmp/
”目录中,并且 Zip 条目为“../etc/hosts
”,而应用程序在所需的权限下运行,则它将覆盖系统 hosts
文件。从而可能会使该计算机的流量进入攻击者所需的任何位置,例如返回至攻击者的计算机。
var unzipper = require('unzipper');
var fs = require('fs');
var untrusted_zip = getZipFromRequest();
fs.createReadStream(zipPath).pipe(unzipper.Extract({ path: 'out' }));
ZZArchive* archive = [ZZArchive archiveWithURL:[NSURL fileURLWithPath: zipPath] error:&error];
for (ZZArchiveEntry* entry in archive.entries) {
NSString *fullPath = [NSString stringWithFormat: @"%@/%@", destPath, [entry fileName]];
[[entry newDataWithError:nil] writeToFile:newFullPath atomically:YES];
}
Example 1
中,在对此条目中的数据执行读取/写入函数之前未验证 entry.fileName
。如果 Zip 文件最初放置在 iOS 应用程序的“Documents/hot_patches
”目录中,并且 Zip 条目为“../js/page.js
”,则它将覆盖 page.js
文件,从而可能会使攻击者能够注入可能导致代码执行的恶意代码。
...
$zip = new ZipArchive();
$zip->open("userdefined.zip", ZipArchive::RDONLY);
$zpm = $zip->getNameIndex(0);
$zip->extractTo($zpm);
...
Example 1
中,在对此条目中的数据执行读取/写入函数之前未验证 f.Name
。如果 Zip 文件位于基于 Unix 的计算机的“/tmp/
”目录中,并且 Zip 条目为“../etc/hosts
”,而应用程序在所需的权限下运行,则它将覆盖系统 hosts
文件。这样会使该计算机的流量进入攻击者所需的任何位置,例如返回至攻击者的计算机。
import zipfile
import tarfile
def unzip(archive_name):
zf = zipfile.ZipFile(archive_name)
zf.extractall(".")
zf.close()
def untar(archive_name):
tf = tarfile.TarFile(archive_name)
tf.extractall(".")
tf.close()
示例 2:以下示例从 Zip 文件中提取文件并以不安全的方式将其写入磁盘。
import better.files._
...
val zipPath: File = getUntrustedZip()
val destinationPath = file"out/dest"
zipPath.unzipTo(destination = destinationPath)
import better.files._
...
val zipPath: File = getUntrustedZip()
val destinationPath = file"out/dest"
zipPath.newZipInputStream.mapEntries( (entry : ZipEntry) => {
entry.extractTo(destinationPath, new FileInputStream(entry.getName))
})
Example 2
中,在对此条目中的数据执行读取/写入函数之前未验证 entry.getName
。如果 Zip 文件最初放置在基于 Unix 的计算机的“/tmp/
”目录中,并且 Zip 条目为“../etc/hosts
”,而应用程序在所需的权限下运行,则它将覆盖系统 hosts
文件。从而可能会使该计算机的流量进入攻击者所需的任何位置,例如返回至攻击者的计算机。
let archive = try ZZArchive.init(url: URL(fileURLWithPath: zipPath))
for entry in archive.entries {
let fullPath = URL(fileURLWithPath: destPath + "/" + entry.fileName)
try entry.newData().write(to: fullPath)
}
Example 1
中,在对此条目中的数据执行读取/写入函数之前未验证 entry.fileName
。如果 Zip 文件最初放置在 iOS 应用程序的“Documents/hot_patches
”目录中,并且 Zip 条目为“../js/page.js
”,则它将覆盖 page.js
文件,从而可能会使攻击者能够注入可能导致代码执行的恶意代码。
pass = getPassword();
...
dbmsLog.println(id+":"+pass+":"+type+":"+tstamp);
Example 1
中的代码会将明文密码记录到文件系统中。虽然许多开发人员认为文件系统是存储数据的安全位置,但这不是绝对的,特别是涉及到隐私问题时。
...
webview.setWebViewClient(new WebViewClient() {
public void onReceivedHttpAuthRequest(WebView view,
HttpAuthHandler handler, String host, String realm) {
String[] credentials = view.getHttpAuthUsernamePassword(host, realm);
String username = credentials[0];
String password = credentials[1];
Intent i = new Intent();
i.setAction("SEND_CREDENTIALS");
i.putExtra("username", username);
i.putExtra("password", password);
view.getContext().sendBroadcast(i);
}
});
...
SEND_CREDENTIALS
收听的注册接收者都将收到消息。即使权限限制接收者人数,广播也不会受到保护;既然这样,我们也不建议将权限作为修复方式使用。doExchange()
中很少抛出的异常。
try {
doExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
,程序将继续执行,就像未发生任何异常情况。该程序未记录表明特殊情况的任何证据,这可能会导致以后无法解释该程序的行为。DoExchange()
抛出的罕见异常。
try {
DoExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
异常,程序会继续执行,就像什么都没有发生一样。程序不会记录任何有关这一特殊情况的依据,因而事后再查找这一异常就可能很困难。doExchange()
抛出的罕见异常。
try {
doExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
异常,程序会继续执行,就像什么都没有发生一样。程序不会记录任何有关这一特殊情况的依据,因而事后再查找这一异常就可能很困难。doExchange()
抛出的罕见异常。
try {
doExchange();
}
catch (exception $e) {
// this can never happen
}
RareException
异常,程序会继续执行,就像什么都没有发生一样。程序不会记录任何有关这一特殊情况的依据,因而事后再查找这一异常就可能很困难。open()
抛出的罕见异常。
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except:
# This will never happen
pass
RareException
异常,程序会继续执行,就像什么都没有发生一样。程序不会记录任何有关这一特殊情况的依据,因而事后再查找这一异常就可能很困难。Exception
),可能会混淆那些需要特殊处理的异常,或是捕获了不应在程序中这一点捕获的异常。本质上,捕获范围过大的异常与“.NET 分类定义异常”这一目的是相违背的,随着程序的增加而抛出新异常时,这种做法会十分危险。而新发生的异常类型也不会被注意到。
try {
DoExchange();
}
catch (IOException e) {
logger.Error("DoExchange failed", e);
}
catch (FormatException e) {
logger.Error("DoExchange failed", e);
}
catch (TimeoutException e) {
logger.Error("DoExchange failed", e);
}
try {
DoExchange();
}
catch (Exception e) {
logger.Error("DoExchange failed", e);
}
DoExchange()
,以抛出需要以某种不同的方式处理的新异常类型,则范围过大的 catch 块会阻止编译器指出这一情况(有新的异常抛出)。除此以外,这个新的捕获块还可处理 ApplicationException
和 NullReferenceException
类型的异常,这些异常的发生并不在程序员的意料之内。Exception
),可能会混淆那些需要特殊处理的异常,或是捕获了不应在程序中这一点捕获的异常。本质上,捕获范围过大的异常与“Java 分类定义异常”这一目的是相违背的,随着程序的增加而抛出新异常时,这种做法会十分危险。而新发生的异常类型也不会被注意到。
try {
doExchange();
}
catch (IOException e) {
logger.error("doExchange failed", e);
}
catch (InvocationTargetException e) {
logger.error("doExchange failed", e);
}
catch (SQLException e) {
logger.error("doExchange failed", e);
}
try {
doExchange();
}
catch (Exception e) {
logger.error("doExchange failed", e);
}
doExchange()
,以抛出需要以某种不同的方式处理的新异常类型,则范围过大的 catch 块会阻止编译器指出这一情况(有新的异常抛出)。此外,新 catch 块也将处理那些来自于 RuntimeException
的异常,比如 ClassCastException
和 NullPointerException
,而这些异常的发生是不在程序员的计划之内的。Exception
或 Throwable
异常的方法,从而使调用者很难处理和修复发生的错误。Java 异常机制的设置是:调用者可以方便地预计有可能发生的各种错误,并为每种异常情况编写处理代码。同时声明:一个方法抛出一个过于笼统的异常违反该系统。
public void doExchange()
throws IOException, InvocationTargetException,
SQLException {
...
}
public void doExchange()
throws Exception {
...
}
doExchange()
因为变更了代码,而引入了一个需要不同于之前异常处理方式的新型异常,则不能使用简单的方式来处理该要求。NullPointerException
并不是一个好方法。NullPointerException
:NullPointerException
异常来标记错误状况。NullPointerException
异常。
try {
mysteryMethod();
}
catch (NullPointerException npe) {
}
finally
块中返回会导致异常的丢失。finally
块中的返回指令会导致从 try 块中抛出的异常丢失。doMagic
方法,同时将参数 true
传递给该方法会导致抛出 MagicException
异常,该异常将不会传递给调用者。finally
块中的返回指令会导致异常的丢弃。
public class MagicTrick {
public static class MagicException extends Exception { }
public static void main(String[] args) {
System.out.println("Watch as this magical code makes an " +
"exception disappear before your very eyes!");
System.out.println("First, the kind of exception handling " +
"you're used to:");
try {
doMagic(false);
} catch (MagicException e) {
// An exception will be caught here
e.printStackTrace();
}
System.out.println("Now, the magic:");
try {
doMagic(true);
} catch (MagicException e) {
// No exception caught here, the finally block ate it
e.printStackTrace();
}
System.out.println("tada!");
}
public static void doMagic(boolean returnFromFinally)
throws MagicException {
try {
throw new MagicException();
}
finally {
if (returnFromFinally) {
return;
}
}
}
}
finally
块中返回会导致异常的丢失。finally
块中的返回指令会导致从 try 块中抛出的异常丢失。doMagic
方法,同时将参数 True
传递给该方法会导致抛出 exception
异常,该异常将不会传递给调用者。finally
块中的返回指令会导致异常的丢弃。"disappear before your very eyes!" . PHP_EOL;
echo "First, the kind of exception handling " .
"you're used to:" . PHP_EOL;
try {
doMagic(False);
} catch (exception $e) {
// An exception will be caught here
echo $e->getMessage();
}
echo "Now, the magic:" . PHP_EOL;
try {
doMagic(True);
} catch (exception $e) {
// No exception caught here, the finally block ate it
echo $e->getMessage();
}
echo "Tada!" . PHP_EOL;
function doMagic($returnFromFinally) {
try {
throw new Exception("Magic Exception" . PHP_EOL);
}
finally {
if ($returnFromFinally) {
return;
}
}
}
?>
ThreadDeath
错误,则出现问题的线程可能实际上并未终止。ThreadDeath
错误。如果捕获了 ThreadDeath
错误,则将其重新抛出非常重要,因为这样该线程才真正地终止。抛出 ThreadDeath
的目的是终止线程。如果 ThreadDeath
被抑制,则它可以阻止线程停止并导致意外行为,因为代码最初抛出 ThreadDeath
的目的是希望停止该线程。ThreadDeath
但未将其重新抛出。
try
{
//some code
}
catch(ThreadDeath td)
{
//clean up code
}
finally
块中的 throw
语句会通过 try-catch-finally
破坏逻辑进度。finally
块通常在其相应的 try-catch
块之后执行,该块通常用于自由分配的资源,例如文件句柄或数据库指针。由于破坏了正常的程序执行,在 finally
块中抛出异常会绕过关键的清除代码。 FileNotFoundException
时,将绕过对 stmt.close()
的调用。
public void processTransaction(Connection conn) throws FileNotFoundException
{
FileInputStream fis = null;
Statement stmt = null;
try
{
stmt = conn.createStatement();
fis = new FileInputStream("badFile.txt");
...
}
catch (FileNotFoundException fe)
{
log("File not found.");
}
catch (SQLException se)
{
//handle error
}
finally
{
if (fis == null)
{
throw new FileNotFoundException();
}
if (stmt != null)
{
try
{
stmt.close();
}
catch (SQLException e)
{
log(e);
}
}
}
}
javax.net.ssl.SSLHandshakeException
、javax.net.ssl.SSLKeyException
和 javax.net.ssl.SSLPeerUnverifiedException
都可以传达与 SSL 连接相关的重要错误。如果没有显式地处理这些错误,连接会被处于一种意想不到的、潜在不安全的状态。
private final Logger logger =
Logger.getLogger(MyClass.class);
public class MyClass {
private final static Logger good =
Logger.getLogger(MyClass.class);
private final static Logger bad =
Logger.getLogger(MyClass.class);
private final static Logger ugly =
Logger.getLogger(MyClass.class);
...
}
Console.Out
或 Console.Error
而不是专门的日志记录工具,会导致难以监控程序的运行状况。
public class MyClass {
...
Console.WriteLine("hello world");
...
}
Console.WriteLine()
来编写消息以进行标准输出。Console.WriteLine
的使用可能会在转向结构化日志记录系统的过程中导致一个漏洞。os.Stdout
或 os.Stderr
而不是专门的日志记录工具,会导致难以监控程序的运行状况。
...
func foo(){
fmt.Println("Hello World")
}
fmt.Println()
编写进行标准输出的消息。os.Stdout
或 os.Stderr
进行日志记录使用可能会在转向结构化日志记录系统的过程中导致漏洞。System.out
或 System.err
而不是专门的日志记录工具,会导致难以监控程序的运行状况。
public class MyClass
...
System.out.println("hello world");
...
}
System.out.println()
编写进行标准输出的消息。System.out
或 System.err
的使用可能会在转向结构化日志记录系统的过程中导致漏洞。process.stdout
或 process.stderr
而不是专门的日志记录工具,会导致难以监控程序的运行状况。
process.stdin.on('readable', function(){
var s = process.stdin.read();
if (s != null){
process.stdout.write(s);
}
});
process.stdout.write()
编写标准输出的消息。process.stdout
或 process.stderr
的使用可能会在转向结构化日志记录系统的过程中导致漏洞。print
或 println
而不是专门的日志记录工具,会导致难以监控程序的运行状况。
class MyClass {
...
println("hello world")
...
}
}
print
或 println
编写进行标准输出的消息。
sys.stdout.write("hello world")
sys.stdout
或 sys.stderr
的使用可能会在转向结构化日志记录系统的过程中导致漏洞。Kernel.puts
、Kernel.warn
或 Kernel.printf
而不是专门的日志记录工具,会导致难以监控程序的行为。
...
puts "hello world"
...
Kernel.puts
编写进行标准输出的消息。Kernel.puts
、Kernel.warn
或 Kernel.printf
的使用可能表示转向结构化日志记录系统过程中的一时疏忽。Logger
类,但是将信息记录到系统输出流:
require 'logger'
...
logger = Logger.new($stdout)
logger.info("hello world")
...
public class Totaller {
private int total;
public int total() {
...
}
}
synchronized(this) { }
finalize()
只能在对象回收后才能由 JVM 进行调用。finalize()
方法,但这其实并不是一个好办法。例如,直接调用 finalize()
意味着要不止一次地调用 finalize()
方法:第一次将会直接调用,而最后一次调用会在对象回收之后执行。finalize()
方法:
// time to clean up
widget.finalize();