輸入驗證和表示法問題是由中繼字元、替代編碼和數值表示法引起的。信任輸入會導致安全問題。問題包括:「Buffer Overflows」、「Cross-Site Scripting」攻擊、「SQL Injection」及其他許多問題。
validate()
方法,無法呼叫 super.validate()
。validate()
方法,對照那些在相關驗證表單中定義的約束來檢查表單屬性的內容。這表示以下這些類別擁有一個 validate()
方法,該方法是屬於驗證框架的一部分:
ValidatorForm
ValidatorActionForm
DynaValidatorForm
DynaValidatorActionForm
validate()
方法而執行自訂的驗證邏輯,則您必須在 validate()
執行中呼叫 super.validate()
。如果您不這麼做,驗證框架就不能對照驗證表單驗證表單中的內容。也就是說,會針對該提供的表單而停用驗證框架。
ValidatorForm
ValidatorActionForm
DynaValidatorActionForm
DynaValidaorForm
validate()
方法,而與應用程式連結。
ActionForm
DynaActionForm
ActionForm
來實行多個用途。在這種情況下,某些欄位在某些操作對應中可能會沒有使用。對沒有使用的欄位也進行驗證是很重要的。最好是對沒有使用的欄位進行嚴格控制,讓它們只能處於空白或未定義的狀態。如果沒有使用的欄位沒有經過驗證,操作中的共用商業邏輯可能會允許攻擊者略過針對表單其他應用所進行的驗證檢查。form-bean
項目進行 HTML 型式與動作的對應。如果 Struts 組態設定檔案的 <action-mappings>
元素不包含對應經由 <form-bean>
標籤所定義的相關操作表單的項目,應用程式邏輯可能已過時。bean2
的對應。
<form-beans>
<form-bean name="bean1" type="coreservlets.UserFormBean1" />
<form-bean name="bean2" type="coreservlets.UserFormBean2" />
</form-beans>
<action-mappings>
<action path="/actions/register1" type="coreservlets.RegisterAction1" name="bean1" scope="request" />
</action-mappings>
validate()
方法。
<action path="/download"
type="com.website.d2.action.DownloadAction"
name="downloadForm"
scope="request"
input=".download"
validate="false">
</action>
ActionForm
類別進行修改後,很容易忘記去更新驗證邏輯。如果沒有適當的維護驗證邏輯,操作表單和驗證表單之間會出現不一致的現象。
public class DateRangeForm extends ValidatorForm {
String startDate, endDate;
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
}
startDate
和 endDate
) 的操作表單。
<form name="DateRangeForm">
<field property="startDate" depends="date">
<arg0 key="start.date"/>
</field>
<field property="endDate" depends="date">
<arg0 key="end.date"/>
</field>
<field property="scale" depends="integer">
<arg0 key="range.scale"/>
</field>
</form>
scale
。第三個欄位的存在表示 DateRangeForm
是在沒有考慮驗證的情況下修正的。
app.get('/', function(req, res){
let param = req.params['template']
let val = req.params['templateVal']
let template = Handlebars.compile('{{user}}: {{' + param + '}}');
let templateInput = {}
templateInput['user'] = 'John'
templateInput[param] = val
let result = template(templateInput)
//...
});
Example 1
使用 Handlebars
做為範本引擎,並將使用者控制的資料串聯到編譯後的範本中,從而使攻擊者能夠執行任意 JavaScript。Echo
的類別。此類別使用一種原生方法,使用 C 將在主控台輸入的指令回傳給使用者。
class Echo {
public native void runEcho();
static {
System.loadLibrary("echo");
}
public static void main(String[] args) {
new Echo().runEcho();
}
}
Echo
類別中執行的原生方法:
#include <jni.h>
#include "Echo.h" //the java class fromExample 1
compiled with javah
#include <stdio.h>
JNIEXPORT void JNICALL
Java_Echo_runEcho(JNIEnv *env, jobject obj)
{
char buf[64];
gets(buf);
printf(buf);
}
gets()
。 Example 1
中存在的弱點。根據是否可使用 C 來源程式碼以及專案建立的方式而定,這個方法不一定可行,但在許多情況下,它是可行的。然而,這種可以在 Java 和原生方法間共用物件的機制,會把潛在的風險擴大為更嚴重的風險。在 Java 中不當處理資料可能會導致在原生程式碼中產生無法預期的弱點,或在原生程式碼中的不安全操作可能會破壞 Java 中的資料結構。Redirect
的類別。此類別會宣告一個原生的 JavaScript 方法,該方法使用 JavaScript 來變更文件位置。
import com.google.gwt.user.client.ui.UIObject;
class MyDiv {
...
public static void changeName(final UIObject object, final String name) {
changeName(object.getElement(), url);
}
public static native void changeName(final Element e, final String name) /*-{
$wnd.jQuery(e).html(name);
}-*/;
...
}
Echo
的類別。此類別使用一種原生方法,使用 C 將在主控台輸入的指令回傳給使用者。
class Echo
{
[DllImport("mylib.dll")]
internal static extern void RunEcho();
static void main(String[] args)
{
RunEcho();
}
}
Echo
類別中執行的原生方法:
#include <stdio.h>
void __stdcall RunEcho()
{
char* buf = (char*) malloc(64 * sizeof(char));
gets(buf);
printf(buf);
}
gets()
。此外,buf
雖被分配但並未空出,因此是記憶體洩露。Example 1
中存在的弱點。根據是否可使用來源程式碼以及專案建立的方式而定,這個方法不一定可行,但在許多情況下,它是可行的。然而,這種可以在受管與原生環境間共用物件的機制,會把潛在的風險擴大為更嚴重的風險。在受管程式碼中不當處理資料可能會導致在原生程式碼中產生無法預期的弱點,或導致在原生程式碼中的不安全操作,造成受管程式碼中的資料結構毀損。
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var ctl:String = String(params["ctl"]);
var ao:Worker;
if (ctl == "Add) {
ao = new AddCommand();
} else if (ctl == "Modify") {
ao = new ModifyCommand();
} else {
throw new UnknownActionError();
}
ao.doAction(params);
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var ctl:String = String(params["ctl"]);
var ao:Worker;
var cmdClass:Class = getDefinitionByName(ctl + "Command") as Class;
ao = new cmdClass();
ao.doAction(params);
if/else
區塊已完全刪除,且現在可以在不修改指令發送器的情況下增加新的指令類型。Worker
介面的物件。如果指令發送器仍然負責 Access Control,那麼無論程式設計師何時建立執行 Worker
介面的新類別,他們都必須記得要去修改發送器的 Access Control 程式碼。如果他們無法修改 Access Control 程式碼,那麼部分 Worker
類別將不會擁有任何 Access Control 權限。Worker
物件負責執行存取控制檢查。重新修改的程式碼的範例如下:
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var ctl:String = String(params["ctl"]);
var ao:Worker;
var cmdClass:Class = getDefinitionByName(ctl + "Command") as Class;
ao = new cmdClass();
ao.checkAccessControl(params);
ao.doAction(params);
Continuation
物件的回呼方法,可能會在應用程式中建立意外的控制流程路徑,從而可能繞過安全檢查。continuationMethod
屬性,決定收到回應時要呼叫的方法名稱。
public Object startRequest() {
Continuation con = new Continuation(40);
Map<String,String> params = ApexPages.currentPage().getParameters();
if (params.containsKey('contMethod')) {
con.continuationMethod = params.get('contMethod');
} else {
con.continuationMethod = 'processResponse';
}
HttpRequest req = new HttpRequest();
req.setMethod('GET');
req.setEndpoint(LONG_RUNNING_SERVICE_URL);
this.requestLabel = con.addHttpRequest(req);
return con;
}
continuationMethod
屬性,進而讓攻擊者能呼叫與名稱相符的任何函數。
...
Dim ctl As String
Dim ao As New Worker()
ctl = Request.Form("ctl")
If (String.Compare(ctl,"Add") = 0) Then
ao.DoAddCommand(Request)
Else If (String.Compare(ctl,"Modify") = 0) Then
ao.DoModifyCommand(Request)
Else
App.EventLog("No Action Found", 4)
End If
...
...
Dim ctl As String
Dim ao As New Worker()
ctl = Request.Form("ctl")
CallByName(ao, ctl, vbMethod, Request)
...
if/else
區塊已完全刪除,且現在可以在不修改指令發送器的情況下增加新的指令類型。Worker
物件執行的方法。如果指令發送器負責 Access Control,那麼無論程式設計師何時在 Worker
類別內建立新方法,他們都必須記得要修改發送器的 Access Control 邏輯。如果此 Access Control 邏輯已經過時,部份的 Worker
方法將不會擁有任何 Access Control。Worker
物件負責執行存取控制檢查。重新修改的程式碼的範例如下:
...
Dim ctl As String
Dim ao As New Worker()
ctl = Request.Form("ctl")
If (ao.checkAccessControl(ctl,Request) = True) Then
CallByName(ao, "Do" & ctl & "Command", vbMethod, Request)
End If
...
clazz
中的函數。
char* ctl = getenv("ctl");
...
jmethodID mid = GetMethodID(clazz, ctl, sig);
status = CallIntMethod(env, clazz, mid, JAVA_ARGS);
...
範例 2:在此範例中,應用程式使用
...
func beforeExampleCallback(scope *Scope){
input := os.Args[1]
if input{
scope.CallMethod(input)
}
}
...
reflect
套件,從指令行引數中擷取要呼叫的函數名稱。
...
input := os.Args[1]
var worker WokerType
reflect.ValueOf(&worker).MethodByName(input).Call([]reflect.Value{})
...
String ctl = request.getParameter("ctl");
Worker ao = null;
if (ctl.equals("Add")) {
ao = new AddCommand();
} else if (ctl.equals("Modify")) {
ao = new ModifyCommand();
} else {
throw new UnknownActionError();
}
ao.doAction(request);
String ctl = request.getParameter("ctl");
Class cmdClass = Class.forName(ctl + "Command");
Worker ao = (Worker) cmdClass.newInstance();
ao.doAction(request);
if/else
區塊已完全刪除,且現在可以在不修改指令發送器的情況下增加新的指令類型。Worker
介面的物件。如果指令發送器仍然負責 Access Control,那麼無論程式設計師何時建立執行 Worker
介面的新類別,他們都必須記得要去修改發送器的 Access Control 程式碼。如果他們無法修改 Access Control 程式碼,那麼部分 Worker
類別將不會擁有任何 Access Control 權限。Worker
物件負責執行存取控制檢查。重新修改的程式碼的範例如下:
String ctl = request.getParameter("ctl");
Class cmdClass = Class.forName(ctl + "Command");
Worker ao = (Worker) cmdClass.newInstance();
ao.checkAccessControl(request);
ao.doAction(request);
Worker
介面的物件;攻擊者可以叫用系統中任何物件的預設建構函式。如果物件不實作 Worker
介面,將會在指派到 ao
之前拋出 ClassCastException
。但是如果建構函式執行了有利於攻擊者的作業,則傷害可能已經造成。雖然這種情況在簡易的應用程式中的影響相對不大,但是對於日趨複雜的較大型應用程式而言,做出攻擊者可以找到一個建構函式來作為攻擊一部分的假設也十分合理。performSelector
方法的引數,這會讓他們透過應用程式建立非預期的控制流路徑,這可能會避開安全檢查。UIApplicationDelegate
類別中定義之方法簽章的函數。
...
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
NSString *query = [url query];
NSString *pathExt = [url pathExtension];
[self performSelector:NSSelectorFromString(pathExt) withObject:query];
...
$ctl = $_GET["ctl"];
$ao = null;
if (ctl->equals("Add")) {
$ao = new AddCommand();
} else if ($ctl.equals("Modify")) {
$ao = new ModifyCommand();
} else {
throw new UnknownActionError();
}
$ao->doAction(request);
$ctl = $_GET["ctl"];
$args = $_GET["args"];
$cmdClass = new ReflectionClass(ctl . "Command");
$ao = $cmdClass->newInstance($args);
$ao->doAction(request);
if/else
區塊已完全刪除,且現在可以在不修改指令發送器的情況下增加新的指令類型。Worker
介面的物件。如果指令發送器仍然負責 Access Control,那麼無論程式設計師何時建立執行 Worker
介面的新類別,他們都必須記得要去修改發送器的 Access Control 程式碼。如果他們無法修改 Access Control 程式碼,那麼部分 Worker
類別將不會擁有任何 Access Control 權限。Worker
物件負責執行存取控制檢查。重新修改的程式碼的範例如下:
$ctl = $_GET["ctl"];
$args = $_GET["args"];
$cmdClass = new ReflectionClass(ctl . "Command");
$ao = $cmdClass->newInstance($args);
$ao->checkAccessControl(request);
ao->doAction(request);
Worker
介面的物件;攻擊者可以叫用系統中任何物件的預設建構函式。如果物件不實作 Worker
介面,將會在指派到 $ao
之前拋出 ClassCastException
。但是如果建構函式執行了有利於攻擊者的作業,則傷害可能已經造成。雖然這種情況在簡易的應用程式中的影響相對不大,但是對於日趨複雜的較大型應用程式而言,做出攻擊者可以找到一個建構函式來作為攻擊一部分的假設也十分合理。
ctl = req['ctl']
if ctl=='add'
addCommand(req)
elsif ctl=='modify'
modifyCommand(req)
else
raise UnknownCommandError.new
end
ctl = req['ctl']
ctl << "Command"
send(ctl)
if/else
區塊已完全刪除,且現在可以在不修改指令發送器的情況下增加新的指令類型。define_method()
動態建立這些方法,或可透過取代 missing_method()
來呼叫這些方法。很難稽核和追蹤這些方法以及存取控制程式碼與之搭配使用的方式,考慮執行這些作業的時間取決於載入的其他程式庫程式碼,因此,想要以此種方式正確地執行這些作業更是難上加難。
def exec(ctl: String) = Action { request =>
val cmdClass = Platform.getClassForName(ctl + "Command")
Worker ao = (Worker) cmdClass.newInstance()
ao.doAction(request)
...
}
if/else
區塊已完全刪除,且現在可以在不修改指令發送器的情況下增加新的指令類型。Worker
介面的物件。如果指令發送器仍然負責存取控制,則無論程式設計師何時建立實作 Worker
介面的新類別,他們都必須記得要去修改發送器的存取控制程式碼。如果他們無法修改存取控制程式碼,則部分 Worker
類別將不會擁有任何存取控制。Worker
物件負責執行存取控制檢查。重新修改的程式碼的範例如下:
def exec(ctl: String) = Action { request =>
val cmdClass = Platform.getClassForName(ctl + "Command")
Worker ao = (Worker) cmdClass.newInstance()
ao.checkAccessControl(request);
ao.doAction(request)
...
}
Worker
介面的物件;攻擊者可以叫用系統中任何物件的預設建構函式。如果物件不實作 Worker
介面,將會在指派到 ao
之前拋出 ClassCastException
。但是如果建構函式執行了有利於攻擊者的作業,則傷害可能已經造成。雖然這種情況在簡易的應用程式中的影響相對不大,但是對於日趨複雜的較大型應用程式而言,做出攻擊者可以找到一個建構函式來作為攻擊一部分的假設也十分合理。performSelector
方法的引數,這會讓他們透過應用程式建立非預期的控制流路徑,這可能會避開安全檢查。UIApplicationDelegate
類別中定義之方法簽章的函數。
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
...
let query = url.query
let pathExt = url.pathExtension
let selector = NSSelectorFromString(pathExt!)
performSelector(selector, withObject:query)
...
}
...
Dim ctl As String
Dim ao As new Worker
ctl = Request.Form("ctl")
If String.Compare(ctl,"Add") = 0 Then
ao.DoAddCommand Request
Else If String.Compare(ctl,"Modify") = 0 Then
ao.DoModifyCommand Request
Else
App.EventLog "No Action Found", 4
End If
...
...
Dim ctl As String
Dim ao As Worker
ctl = Request.Form("ctl")
CallByName ao, ctl, vbMethod, Request
...
if/else
區塊已完全刪除,且現在可以在不修改指令發送器的情況下增加新的指令類型。Worker
物件執行的方法。如果指令發送器仍然負責 access control,那麼無論程式設計師何時在 Worker
類別內建立新方法,他們都必須記得要去修改發送器的 access control 程式碼。如果他們無法修改 access control 程式碼,那麼部分 Worker
方法將不會擁有任何 access control 權限。Worker
物件負責執行存取控制檢查。重新修改的程式碼的範例如下:
...
Dim ctl As String
Dim ao As Worker
ctl = Request.Form("ctl")
If ao.checkAccessControl(ctl,Request) = True Then
CallByName ao, "Do" & ctl & "Command", vbMethod, Request
End If
...
HttpRequest
類別以陣列存取形式 (例如 Request["myParam"]
) 提供對 QueryString
、Form
、Cookies
或 ServerVariables
集合中變數的程式化存取。存在多個名稱相同的變數時,.NET Framework 會傳回在集合中以下列順序搜尋時第一個出現的變數值:QueryString
、Form
、Cookies
,然後 ServerVariables
。因為 QueryString
依搜尋順序第一個出現,因此 QueryString
參數可以取代表單、Cookie 及伺服器變數的值。同樣地,表單值可以取代 Cookies
和 ServerVariables
集合中的變數,而 Cookies
集合的變數可取代 ServerVariables
的變數。
...
String toAddress = Request["email"]; //Expects cookie value
Double balance = GetBalance(userID);
SendAccountBalance(toAddress, balance);
...
http://www.example.com/GetBalance.aspx
時執行 Example 1
中的程式碼。若攻擊者能夠使通過驗證的使用者按下要求 http://www.example.com/GetBalance.aspx?email=evil%40evil.com
的連結,則含有使用者帳戶餘額的電子郵件將會送往 evil@evil.com
。HttpRequest
類別以陣列存取形式 (例如 Request["myParam"]
) 提供對 QueryString
、Form
、Cookies
或 ServerVariables
集合中變數的程式化存取。存在多個名稱相同的變數時,.NET Framework 會傳回在集合中以下列順序搜尋時第一個出現的變數值:QueryString
、Form
、Cookies
,然後 ServerVariables
。因為 QueryString
依搜尋順序第一個出現,因此 QueryString
參數可以取代表單、Cookie 及伺服器變數的值。同樣地,表單值可以取代 Cookies
和 ServerVariables
集合中的變數,而 Cookies
集合的變數可取代 ServerVariables
的變數。www.example.com
。
...
if (Request["HTTP_REFERER"].StartsWith("http://www.example.com"))
ServeContent();
else
Response.Redirect("http://www.example.com/");
...
http://www.example.com/ProtectedImages.aspx
時執行 Example 1
中的程式碼。若攻擊者對 URL 做一個直接的要求,則不會設定適當的 Referer 表頭,而要求將失敗。不過,若攻擊者以必要值提交偽造 HTTP_REFERER
參數 (如 http://www.example.com/ProtectedImages.aspx?HTTP_REFERER=http%3a%2f%2fwww.example.com
),則查詢將從 QueryString
傳回值,而不是 ServerVariables
,同時檢查也將成功。
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
...
DATA(ixml) = cl_ixml=>create( ).
DATA(stream_factory) = ixml->create_stream_factory( ).
istream = stream_factory->create_istream_string(
`<?xml version="1.0" encoding="UTF-8"?> ` &&
`<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> ` &&
`<stockCheck>&xxe;</stockCheck>` ).
istream->set_dtd_restriction( level = 0 ).
DATA(document) = ixml->create_document( ).
parser = ixml->create_parser(
stream_factory = stream_factory
istream = istream
document = document ).
parser->set_validating( mode = `0` ).
DATA(rc) = parser->parse( ).
...
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/winnt/win.ini" >]><foo>&xxe;</foo>
- (void) parseSomeXML: (NSString *) rawXml {
BOOL success;
NSData *rawXmlConvToData = [rawXml dataUsingEncoding:NSUTF8StringEncoding];
NSXMLParser *myParser = [[NSXMLParser alloc] initWithData:rawXmlConvToData];
[myParser setShouldResolveExternalEntities:YES];
[myParser setDelegate:self];
}
rawXml
內容,使 XML 與下列相似:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/boot.ini" >]><foo>&xxe;</foo>
boot.ini
檔案的內容。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>
String xml = "...";
...
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.println(new String(ch, start, length));
}
};
saxParser.parse(new InputSource(new StringReader(xml)), handler);
} catch (Exception e) {
e.printStackTrace();
}
...
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>
- (void) parseSomeXML: (NSString *) rawXml {
BOOL success;
NSData *rawXmlConvToData = [rawXml dataUsingEncoding:NSUTF8StringEncoding];
NSXMLParser *myParser = [[NSXMLParser alloc] initWithData:rawXmlConvToData];
[myParser setShouldResolveExternalEntities:YES];
[myParser setDelegate:self];
}
rawXml
內容,使 XML 與下列相似:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/boot.ini" >]><foo>&xxe;</foo>
boot.ini
檔案的內容。
...
<?php
$goodXML = $_GET["key"];
$doc = simplexml_load_string($goodXml);
echo $doc->testing;
?>
...
Example 2
中的程式碼:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/boot.ini" >]><foo>&xxe;</foo>
boot.ini
檔案的內容。攻擊者可能利用傳回到用戶端的 XML 元素竊取資料或取得資訊,以便知道有哪些網路資源。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>
/etc/passwd
的內容並將其包含在文件中。
def readFile() = Action { request =>
val xml = request.cookies.get("doc")
val doc = XMLLoader.loadString(xml)
...
}
func parseXML(xml: String) {
parser = NSXMLParser(data: rawXml.dataUsingEncoding(NSUTF8StringEncoding)!)
parser.delegate = self
parser.shouldResolveExternalEntities = true
parser.parse()
}
rawXml
內容,使 XML 與下列相似:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/boot.ini" >]><foo>&xxe;</foo>
boot.ini
檔案的內容。shoes
:
<order>
<price>100.00</price>
<item>shoes</item>
</order>
shoes
取代 shoes</item><price>1.00</price><item>shoes
。新的 XML 會變成:
<order>
<price>100.00</price>
<item>shoes</item><price>1.00</price><item>shoes</item>
</order>
<price>
的值會覆寫第一個 <price>
標籤的值。因此攻擊者將能以 1 美元購買一雙價值 100 美元的鞋子。shoes
。
<order>
<price>100.00</price>
<item>shoes</item>
</order>
shoes
取代 shoes</item><price>1.00</price><item>shoes
。新的 XML 會變成:
<order>
<price>100.00</price>
<item>shoes</item><price>1.00</price><item>shoes</item>
</order>
<price>
的值會覆寫第一個 <price>
標籤的值。因此攻擊者將能以 1 美元購買一雙價值 100 美元的鞋子。shoes
。
<order>
<price>100.00</price>
<item>shoes</item>
</order>
shoes
取代 shoes</item><price>1.00</price><item>shoes
。新的 XML 會變成:
<order>
<price>100.00</price>
<item>shoes</item><price>1.00</price><item>shoes</item>
</order>
<price>
的值會覆寫第一個 <price>
標籤的值。因此攻擊者將能以 1 美元購買一雙價值 100 美元的鞋子。shoes
:
<order>
<price>100.00</price>
<item>shoes</item>
</order>
shoes
取代 shoes</item><price>1.00</price><item>shoes
。新的 XML 會變成:
<order>
<price>100.00</price>
<item>shoes</item><price>1.00</price><item>shoes</item>
</order>
<price>
的值會覆寫第一個 <price>
標籤的值。因此攻擊者將能以 1 美元購買一雙價值 100 美元的鞋子。shoes
。
<order>
<price>100.00</price>
<item>shoes</item>
</order>
shoes
取代 shoes</item><price>1.00</price><item>shoes
。新的 XML 會變成:
<order>
<price>100.00</price>
<item>shoes</item><price>1.00</price><item>shoes</item>
</order>
<price>
的值會覆寫第一個 <price>
標籤的值。因此攻擊者將能以 1 美元購買一雙價值 100 美元的鞋子。shoes
。
<order>
<price>100.00</price>
<item>shoes</item>
</order>
shoes
取代 shoes</item><price>1.00</price><item>shoes
。新的 XML 會變成:
<order>
<price>100.00</price>
<item>shoes</item><price>1.00</price><item>shoes</item>
</order>
shoes
。
<order>
<price>100.00</price>
<item>shoes</item>
</order>
shoes
取代 shoes</item><price>1.00</price><item>shoes
。新的 XML 會變成:
<order>
<price>100.00</price>
<item>shoes</item><price>1.00</price><item>shoes</item>
</order>
<price>
的值會覆寫第一個 <price>
標籤的值。因此攻擊者將能以 1 美元購買一雙價值 100 美元的鞋子。shoes
。
<order>
<price>100.00</price>
<item>shoes</item>
</order>
shoes
取代 shoes</item><price>1.00</price><item>shoes
。新的 XML 會變成:
<order>
<price>100.00</price>
<item>shoes</item><price>1.00</price><item>shoes</item>
</order>
<price>
的值會覆寫第一個 <price>
標籤的值。因此攻擊者將能以 1 美元購買一雙價值 100 美元的鞋子。
...
<?php
$goodXML = $_GET["key"];
$doc = simplexml_load_string($goodXml);
echo $doc->testing;
?>
...
Example 2
中的程式碼:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/boot.ini" >]><foo>&xxe;</foo>
boot.ini
檔案的內容。攻擊者可能利用傳回到用戶端的 XML 元素竊取資料或取得資訊,以便知道有哪些網路資源。shoes
。
<order>
<price>100.00</price>
<item>shoes</item>
</order>
shoes
取代 shoes</item><price>1.00</price><item>shoes
。新的 XML 會變成:
<order>
<price>100.00</price>
<item>shoes</item><price>1.00</price><item>shoes</item>
</order>
<price>
的值會覆寫第一個 <price>
標籤的值。因此攻擊者將能以 1 美元購買一雙價值 100 美元的鞋子。shoes
。
<order>
<price>100.00</price>
<item>shoes</item>
</order>
shoes
取代 shoes</item><price>1.00</price><item>shoes
。新的 XML 會變成:
<order>
<price>100.00</price>
<item>shoes</item><price>1.00</price><item>shoes</item>
</order>
<price>
的值會覆寫第一個 <price>
標籤的值。因此攻擊者將能以 1 美元購買一雙價值 100 美元的鞋子。shoes
。
<order>
<price>100.00</price>
<item>shoes</item>
</order>
shoes
取代 shoes</item><price>1.00</price><item>shoes
。新的 XML 會變成:
<order>
<price>100.00</price>
<item>shoes</item><price>1.00</price><item>shoes</item>
</order>
<price>
的值會覆寫第一個 <price>
標籤的值。因此攻擊者將能以 1 美元購買一雙價值 100 美元的鞋子。shoes
。
<order>
<price>100.00</price>
<item>shoes</item>
</order>
shoes
取代 shoes</item><price>1.00</price><item>shoes
。新的 XML 會變成:
<order>
<price>100.00</price>
<item>shoes</item><price>1.00</price><item>shoes</item>
</order>
<price>
的值會覆寫第一個 <price>
標籤的值。因此攻擊者將能以 1 美元購買一雙價值 100 美元的鞋子。a:t
標籤。
<a:t>YoY results: up 10%</a:t>