@GetMapping("/prompt_injection_persistent")
String generation(String userInput1, ...) {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users WHERE ...");
String userName = "";
if (rs != null) {
rs.next();
userName = rs.getString("userName");
}
return this.clientBuilder.build().prompt()
.system("Assist the user " + userName)
.user(userInput1)
.call()
.content();
}
client = new Anthropic();
# Simulated attacker's input attempting to inject a malicious system prompt
attacker_query = ...;
attacker_name = db.qyery('SELECT name FROM user_profiles WHERE ...');
response = client.messages.create(
model = "claude-3-5-sonnet-20240620",
max_tokens=2048,
system = "Provide assistance to the user " + attacker_name,
messages = [
{"role": "user", "content": attacker_query}
]
);
...
client = OpenAI()
# Simulated attacker's input attempting to inject a malicious system prompt
attacker_name = cursor.fetchone()['name']
attacker_query = ...
completion = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "Provide assistance to the user " + attacker_name},
{"role": "user", "content": attacker_query}
]
)
select()
查詢,以搜尋符合使用者指定產品類別的清單。使用者還可以指定欄按結果排序。假設應用程式已經過適當驗證,並已在此程式碼片段之前設定 customerID
的值。
...
String customerID = getAuthenticatedCustomerID(customerName, customerCredentials);
...
AmazonSimpleDBClient sdbc = new AmazonSimpleDBClient(appAWSCredentials);
String query = "select * from invoices where productCategory = '"
+ productCategory + "' and customerID = '"
+ customerID + "' order by '"
+ sortColumn + "' asc";
SelectResult sdbResult = sdbc.select(new SelectRequest(query));
...
select * from invoices
where productCategory = 'Fax Machines'
and customerID = '12345678'
order by 'price' asc
productCategory
和 price
不包含單引號字元的時候,查詢才會正確執行。但是,如果攻擊者提供「Fax Machines' or productCategory = \"
」字串給 productCategory
和「\" order by 'price
」字串給 sortColumn
,那麼查詢將會變為:
select * from invoices
where productCategory = 'Fax Machines' or productCategory = "'
and customerID = '12345678'
order by '" order by 'price' asc
select * from invoices
where productCategory = 'Fax Machines'
or productCategory = "' and customerID = '12345678' order by '"
order by 'price' asc
customerID
所需的 Authentication,並允許攻擊者檢視所有符合 'Fax Machines'
清單記錄的客戶。customerID
的值。
...
productCategory = this.getIntent().getExtras().getString("productCategory");
sortColumn = this.getIntent().getExtras().getString("sortColumn");
customerID = getAuthenticatedCustomerID(customerName, customerCredentials);
c = invoicesDB.query(Uri.parse(invoices), columns, "productCategory = '" + productCategory + "' and customerID = '" + customerID + "'", null, null, null, "'" + sortColumn + "'asc", null);
...
select * from invoices
where productCategory = 'Fax Machines'
and customerID = '12345678'
order by 'price' asc
productCategory
所動態建構而成,所以只有在 productCategory
和 sortColumn
不包含單引號字元時,查詢才會正確執行。如果攻擊者提供「Fax Machines' or productCategory = \"
」字串給 productCategory
和「\" order by 'price
」字串給 sortColumn
,那麼查詢將會變為:
select * from invoices
where productCategory = 'Fax Machines' or productCategory = "'
and customerID = '12345678'
order by '" order by 'price' asc
select * from invoices
where productCategory = 'Fax Machines'
or productCategory = "' and customerID = '12345678' order by '"
order by 'price' asc
customerID
所需的 Authentication,並允許攻擊者檢視所有符合 'Fax Machines'
清單記錄的客戶。
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/" + "app.apk")), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
...
public class Box{
public int area;
public static final int width = 10;
public static final Box box = new Box();
public static final int height = (int) (Math.random() * 100);
public Box(){
area = width * height;
}
...
}
...
Example 1
中,開發人員預期 box.area
會是一個隨機整數,這正好是 10 的倍數,因為 width
等於 10。然而實際上,它的硬式編碼值始終是 0。使用編譯時間常數宣告的靜態 final 欄位會先進行初始化,然後依序執行每個欄位。這表示,由於 height
不是編譯時間常數,所以會在宣告 box
之後宣告,因此,會在初始化 height
欄位之前呼叫建構函式。
...
class Foo{
public static final int f = Bar.b - 1;
...
}
...
class Bar{
public static final int b = Foo.f + 1;
...
}
This example is perhaps easier to identify, but would be dependent on which class is loaded first by the JVM. In this exampleFoo.f
could be either -1 or 0, andBar.b
could be either 0 or 1.
java.text.Format
中的 parse()
和 format()
方法有設計上的缺陷,可能導致使用者看見其他使用者的資料。java.text.Format
中的 parse()
和 format()
方法有 race condition,可能導致使用者看見其他使用者的資料。
public class Common {
private static SimpleDateFormat dateFormat;
...
public String format(Date date) {
return dateFormat.format(date);
}
...
final OtherClass dateFormatAccess=new OtherClass();
...
public void function_running_in_thread1(){
System.out.println("Time in thread 1 should be 12/31/69 4:00 PM, found: "+ dateFormatAccess.format(new Date(0)));
}
public void function_running_in_thread2(){
System.out.println("Time in thread 2 should be around 12/29/09 6:26 AM, found: "+ dateFormatAccess.format(new Date(System.currentTimeMillis())));
}
}
format()
時發生 race condition,第一個執行緒的日期會在第二個執行緒的輸出中顯示。
public class GuestBook extends HttpServlet {
String name;
protected void doPost (HttpServletRequest req, HttpServletResponse res) {
name = req.getParameter("name");
...
out.println(name + ", thanks for visiting!");
}
}
Dick
」指派至 name
Jane
」指派至 name
Jane, thanks for visiting!
」Jane, thanks for visiting!
」
public class ConnectionManager {
private static Connection conn = initDbConn();
...
}
null
之前先解除參照可能為 null
的指標,將會造成「解除參照之後檢查」的錯誤。當程式執行明確的 null
檢查,但仍繼續解除參照已知為 null
的指標時,將會造成「檢查後解除參照」的錯誤。這種類型的錯誤通常是打字錯誤或程式設計師的疏忽所造成。當程式明確的將某指標設定為 null
,卻在之後解除參考該指標,則會發生儲存後解除參照錯誤。這種錯誤通常是由於程式設計師在宣告變數時將變數初始化為 null
所致。foo
是 null
,並在之後以錯誤的方式解除參照。在 if
陳述式中檢查 foo
時,若其為 null
,便會發生 null
解除參照,因此造成 Null 指標異常。範例 2:在以下程式碼中,程式設計師會假設
if (foo is null) {
foo.SetBar(val);
...
}
foo
變數不是 null
,並解除參照物件來確認這項假設。不過,程式設計師之後將對照 null
檢查 foo
,來反駁這項假設。在 if
陳述式中檢查 foo
時,若其為 null
,則在解除參照時也可為 null
,並有可能會造成 Null 指標異常。解除參照不安全,後續檢查也不必要。範例 3:在以下程式碼中,程式設計師明確地將變數
foo.SetBar(val);
...
if (foo is not null) {
...
}
foo
設定為 null
。之後,程式設計師先解除參照 foo
,再檢查物件是否為 null
值。
Foo foo = null;
...
foo.SetBar(val);
...
}
null
之前先解除參照可能為 null
的指標,將會造成「解除參照之後檢查」的錯誤。當程式執行明確的 null
檢查,但仍繼續解除參照已知為 null
的指標時,將會造成「檢查後解除參照」的錯誤。這種類型的錯誤通常是打字錯誤或程式設計師的疏忽所造成。當程式明確的將某指標設定為 null
,卻在之後解除參考該指標,則會發生儲存後解除參照錯誤。這種錯誤通常是由於程式設計師在宣告變數時將變數初始化為 null
所致。ptr
不是 NULL
。當程式設計師取消參照指標時,這個假設就變得清楚。當程式設計師檢查 ptr
為 NULL
時,這個假設其實就出現其矛盾之處。若在 if
指令中檢查 ptr
時,其可為 NULL
,則解除參照時也可為 NULL
,並產生分段錯誤。範例 2:在以下程式碼中,程式設計師確定變數
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
是 NULL
,並在之後以錯誤的方式解除參照。若在 if
陳述式中檢查 ptr
時,其非 NULL
,就會發生 null
解除參照,從而導致分段錯誤。範例 3:在以下程式碼中,程式設計師忘記了字串
if (ptr == null) {
ptr->field = val;
...
}
'\0'
實際上是 0 還是 NULL
,因此解除參照 Null 指標,並導致分段錯誤。範例 4:在以下程式碼中,程式設計師明確地將變數
if (ptr == '\0') {
*ptr = val;
...
}
ptr
設定為 NULL
。之後,程式設計師先解除參照 ptr
,再檢查物件是否為 null
值。
*ptr = NULL;
...
ptr->field = val;
...
}
null
檢查,但仍繼續解除參照已知為 null
的物件時,將會造成「解除參照之後檢查」的錯誤。這種類型的錯誤通常是打字錯誤或程式設計師的疏忽所造成。foo
是 null
,並在之後以錯誤的方式解除參照。在 if
陳述式中檢查 foo
時,若其為 null
,便會發生 null
解除參照,因此造成 Null 指標異常。
if (foo == null) {
foo.setBar(val);
...
}
Content-Disposition
表頭設定錯誤,從而讓攻擊者可控制 HTTP 回應中的 Content-Type
和/或 Content-Disposition
表頭,或者目標應用程式所包含的 Content-Type
預設並非在瀏覽器中轉譯。ContentNegotiationManager
來動態產生不同的回應格式,則滿足使 RFD 攻擊成為可能所需的條件。ContentNegotiationManager
設定為根據要求路徑副檔名來決定回應格式,並使用 Java Activation Framework (JAF) 尋找更為符合用戶端所要求之格式的 Content-Type
。它還允許用戶端透過在要求的 Accept
表頭中傳送的媒體類型來指定回應內容類型。範例 2:在以下範例中,應用程式設定為允許要求的
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="true" />
<property name="useJaf" value="true" />
</bean>
Accept
表頭來決定回應的內容類型:
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="ignoreAcceptHeader" value="false" />
</bean>
ContentNegotiationManagerFactoryBean
屬性預設值如下:useJaf
:true
favorPathExtension
:true
ignoreAcceptHeader
:false
Example 1
中所顯示的配置可讓攻擊者製作惡意 URL,如:ContentNegotiationManager
使用 Java Activation Framework (如果在類別路徑中找到 activation.jar) 嘗試解析指定副檔名的媒體類型,並相應設定回應的 ContentType
表頭。此範例中的副檔名為「.bat」,從而產生 application/x-msdownload
的 Content-Type
表頭 (儘管確切的 Content-Type
可能依據伺服器 OS 和 JAF 組態而有所不同)。因此,一旦受害者造訪此惡意 URL,他/她的機器便會自動開始下載包含攻擊者控制內容的「.bat」檔案。如果隨後執行此檔案,受害者機器便會執行攻擊者承載所指定的任意指令。
...
host_name = request->get_form_field( 'host' ).
CALL FUNCTION 'FTP_CONNECT'
EXPORTING
USER = user
PASSWORD = password
HOST = host_name
RFC_DESTINATION = 'SAPFTP'
IMPORTING
HANDLE = mi_handle
EXCEPTIONS
NOT_CONNECTED = 1
OTHERS = 2.
...
int rPort = Int32.Parse(Request.Item("rPort"));
...
IPEndPoint endpoint = new IPEndPoint(address,rPort);
socket = new Socket(endpoint.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
socket.Connect(endpoint);
...
...
char* rPort = getenv("rPort");
...
serv_addr.sin_port = htons(atoi(rPort));
if (connect(sockfd,&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
...
...
ACCEPT QNAME.
EXEC CICS
READQ TD
QUEUE(QNAME)
INTO(DATA)
LENGTH(LDATA)
END-EXEC.
...
ServerSocket
物件,並使用從 HTTP 要求讀取的連接埠號碼來建立通訊端。
<cfobject action="create" type="java" class="java.net.ServerSocket" name="myObj">
<cfset srvr = myObj.init(#url.port#)>
<cfset socket = srvr.accept()>
Passing user input to objects imported from other languages can be very dangerous.
final server = await HttpServer.bind('localhost', 18081);
server.listen((request) async {
final remotePort = headers.value('port');
final serverSocket = await ServerSocket.bind(host, remotePort as int);
final httpServer = HttpServer.listenOn(serverSocket);
});
...
func someHandler(w http.ResponseWriter, r *http.Request){
r.parseForm()
deviceName := r.FormValue("device")
...
syscall.BindToDevice(fd, deviceName)
}
String remotePort = request.getParameter("remotePort");
...
ServerSocket srvr = new ServerSocket(remotePort);
Socket skt = srvr.accept();
...
WebView
。
...
WebView webview = new WebView(this);
setContentView(webview);
String url = this.getIntent().getExtras().getString("url");
webview.loadUrl(url);
...
var socket = new WebSocket(document.URL.indexOf("url=")+20);
...
char* rHost = getenv("host");
...
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)rHost, 80, &readStream, &writeStream);
...
<?php
$host=$_GET['host'];
$dbconn = pg_connect("host=$host port=1234 dbname=ticketdb");
...
$result = pg_prepare($dbconn, "my_query", 'SELECT * FROM pricelist WHERE name = $1');
$result = pg_execute($dbconn, "my_query", array("ticket"));
?>
...
filename := SUBSTR(OWA_UTIL.get_cgi_env('PATH_INFO'), 2);
WPG_DOCLOAD.download_file(filename);
...
host=request.GET['host']
dbconn = db.connect(host=host, port=1234, dbname=ticketdb)
c = dbconn.cursor()
...
result = c.execute('SELECT * FROM pricelist')
...
def controllerMethod = Action { request =>
val result = request.getQueryString("key").map { key =>
val user = db.getUser()
cache.set(key, user)
Ok("Cached Request")
}
Ok("Done")
}
...
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
var inputStream : NSInputStream?
var outputStream : NSOutputStream?
...
var readStream : Unmanaged<CFReadStream>?
var writeStream : Unmanaged<CFWriteStream>?
let rHost = getQueryStringParameter(url.absoluteString, "host")
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, rHost, 80, &readStream, &writeStream);
...
}
func getQueryStringParameter(url: String?, param: String) -> String? {
if let url = url, urlComponents = NSURLComponents(string: url), queryItems = (urlComponents.queryItems as? [NSURLQueryItem]) {
return queryItems.filter({ (item) in item.name == param }).first?.value!
}
return nil
}
...
...
Begin MSWinsockLib.Winsock tcpServer
...
Dim Response As Response
Dim Request As Request
Dim Session As Session
Dim Application As Application
Dim Server As Server
Dim Port As Variant
Set Response = objContext("Response")
Set Request = objContext("Request")
Set Session = objContext("Session")
Set Application = objContext("Application")
Set Server = objContext("Server")
Set Port = Request.Form("port")
...
tcpServer.LocalPort = Port
tcpServer.Accept
...
@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {
super("callback");
}
}
GET /api/latest.json?callback=myCallbackFunction
的要求,控制項方法會產生一個諸如以下內容的回應:
HTTP/1.1 200 Ok
Content-Type: application/json; charset=utf-8
Date: Tue, 12 Dec 2017 16:16:04 GMT
Server: nginx/1.12.1
Content-Length: 225
Connection: Close
myCallbackFunction({<json>})
Script
標籤從 JSONP 端點載入回應,其會變成執行 myCallbackFunction
函數。 攻擊者可以使用不同的回呼名稱來導覽 DOM 並與之互動。 例如,opener.document.body.someElemnt.firstChild.nextElementSibling.submit
可用來在目標頁面中尋找表單並進行提交。
def myJSONPService(callback: String) = Action {
val json = getJSONToBeReturned()
Ok(Jsonp(callback, json))
}
GET /api/latest.json?callback=myCallbackFunction
的要求,Example 1
中所述的控制項方法會產生一個諸如以下內容的回應:
HTTP/1.1 200 Ok
Content-Type: application/json; charset=utf-8
Date: Tue, 12 Dec 2017 16:16:04 GMT
Server: nginx/1.12.1
Content-Length: 225
Connection: Close
myCallbackFunction({<json>})
Script
標籤從 JSONP 端點載入回應,其會變成執行 myCallbackFunction
函數。 攻擊者可以使用不同的回呼名稱來導覽 DOM 並與之互動。 例如,opener.document.body.someElemnt.firstChild.nextElementSibling.submit
可用來在目標頁面中尋找表單並進行提交。
...
lv_uri = request->get_form_field( 'uri' ).
CALL METHOD cl_http_utility=>set_request_uri
EXPORTING
request = lo_request
uri = lv_uri.
...
http
或 https
的通訊協定,例如:
...
PageReference ref = ApexPages.currentPage();
Map<String,String> params = ref.getParameters();
HttpRequest req = new HttpRequest();
req.setEndpoint(params.get('url'));
HTTPResponse res = new Http().send(req);
http
或 https
的通訊協定,例如:
string url = Request.Form["url"];
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(url);
http
或 https
的通訊協定,例如:
char *url = maliciousInput();
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
CURLcode res = curl_easy_perform(curl);
http
或 https
的通訊協定,例如:
...
final server = await HttpServer.bind('localhost', 18081);
server.listen((request) async {
final headers = request.headers;
final url = headers.value('url');
final client = IOClient();
final response = await client.get(Uri.parse(url!));
...
}
http
或 https
的通訊協定,例如:
url := request.Form.Get("url")
res, err =: http.Get(url)
...
http
或 https
的通訊協定,例如:
String url = request.getParameter("url");
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response1 = httpclient.execute(httpGet);
http
或 https
的通訊協定,例如:
var http = require('http');
var url = require('url');
function listener(request, response){
var request_url = url.parse(request.url, true)['query']['url'];
http.request(request_url)
...
}
...
http.createServer(listener).listen(8080);
...
http
或 https
的通訊協定,例如:
val url: String = request.getParameter("url")
val httpclient: CloseableHttpClient = HttpClients.createDefault()
val httpGet = HttpGet(url)
val response1: CloseableHttpResponse = httpclient.execute(httpGet)
http
或 https
的通訊協定,例如:
$url = $_GET['url'];
$c = curl_init();
curl_setopt($c, CURLOPT_POST, 0);
curl_setopt($c,CURLOPT_URL,$url);
$response=curl_exec($c);
curl_close($c);
http
或 https
的通訊協定,例如:
url = request.GET['url']
handle = urllib.urlopen(url)
http
或 https
的通訊協定,例如:
url = req['url']
Net::HTTP.get(url)
http
或 https
的通訊協定,例如:
def getFile(url: String) = Action { request =>
...
val url = request.body.asText.getOrElse("http://google.com")
ws.url(url).get().map { response =>
Ok(s"Request sent to $url")
}
...
}
http
或 https
的通訊協定,例如:
// Set up the context data
VelocityContext context = new VelocityContext();
context.put( "name", user.name );
// Load the template
String template = getUserTemplateFromRequestBody(request);
RuntimeServices runtimeServices = RuntimeSingleton.getRuntimeServices();
StringReader reader = new StringReader(template);
SimpleNode node = runtimeServices.parse(reader, "myTemplate");
template = new Template();
template.setRuntimeServices(runtimeServices);
template.setData(node);
template.initDocument();
// Render the template with the context data
StringWriter sw = new StringWriter();
template.merge( context, sw );
Example 1
使用 Velocity
做為範本引擎。對於該引擎,攻擊者可提交下列範本以在伺服器上執行任意指令:
$name.getClass().forName("java.lang.Runtime").getRuntime().exec(<COMMAND>)
app.get('/', function(req, res){
var template = _.template(req.params['template']);
res.write("<html><body><h2>Hello World!</h2>" + template() + "</body></html>");
});
Example 1
使用 Underscore.js
做為 Node.js
應用程式內的範本引擎。對於該引擎,攻擊者可提交下列範本以在伺服器上執行任意指令:
<% cp = process.mainModule.require('child_process');cp.exec(<COMMAND>); %>
Jinja2
範本引擎轉譯範本。
from django.http import HttpResponse
from jinja2 import Template as Jinja2_Template
from jinja2 import Environment, DictLoader, escape
def process_request(request):
# Load the template
template = request.GET['template']
t = Jinja2_Template(template)
name = source(request.GET['name'])
# Render the template with the context data
html = t.render(name=escape(name))
return HttpResponse(html)
Example 1
使用 Jinja2
做為範本引擎。對於該引擎,攻擊者可提交下列範本以從伺服器讀取任意檔案:範例 2:以下範例顯示如何從 HTTP 要求擷取範本並使用
template={{''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}}
Django
範本引擎轉譯範本。
from django.http import HttpResponse
from django.template import Template, Context, Engine
def process_request(request):
# Load the template
template = source(request.GET['template'])
t = Template(template)
user = {"name": "John", "secret":getToken()}
ctx = Context(locals())
html = t.render(ctx)
return HttpResponse(html)
Example 2
使用 Django
做為範本引擎。對於該引擎,攻擊者將無法執行任意指令,但其能夠存取範本內容中的所有物件。在此範例中,已在內容中提供了秘密權杖,該權杖可能會被攻擊者洩漏。
<http auto-config="true">
...
<session-management session-fixation-protection="none"/>
</http>
Example 1
中,攻擊者使用直接明顯的方法並不高明,對於攻擊知名度較低的網站並不適用。但是,千萬不要過於大意,攻擊者有許多手段來突破上述攻擊的限制。攻擊者最常採用的技術包括:利用目標網站中的 Cross-Site Scripting 或 HTTP Response Splitting 弱點 [1]。透過誘使受害者向一個易受攻擊的應用程式提交惡意要求,讓應用程式將 JavaScript 或者其他程式碼反映到受害者的瀏覽器,這樣一來,攻擊者就可以建立 Cookie,使受害者重新使用受攻擊者控制的階段作業識別碼。bank.example.com
和 recipes.example.com
),其中一個應用程式存在弱點,那麼攻擊者便可以透過此弱點設定一個 Cookie,並在其中包含已修改的階段作業識別碼,且該階段作業識別碼可以在 example.com
[2] 網域上的所有應用程式中交互使用。use_strict_mode
屬性。
ini_set("session.use_strict_mode", "0");
@SessionAttributes
註解的類別,意味著 Spring 複製了對階段作業物件中的模型屬性的變更。如果攻擊者能夠在模型屬性內儲存任意值,將會在可能受應用程式信任的階段作業物件中複製這些變更。如果階段作業屬性透過使用者無法修改的信任資料初始化,則攻擊者可以執行階段作業疑難攻擊並濫用應用程式邏輯。
@Controller
@SessionAttributes("user")
public class HomeController {
...
@RequestMapping(value= "/auth", method=RequestMethod.POST)
public String authHandler(@RequestParam String username, @RequestParam String password, RedirectAttributes attributes, Model model) {
User user = userService.findByNamePassword(username, password);
if (user == null) {
// Handle error
...
} else {
// Handle success
attributes.addFlashAttribute("user", user);
return "redirect:home";
}
}
...
}
@SessionAttributes("user")
註解,將嘗試從階段作業載入 User
實例,並使用它來驗證重設密碼問題。
@Controller
@SessionAttributes("user")
public class ResetPasswordController {
@RequestMapping(value = "/resetQuestion", method = RequestMethod.POST)
public String resetQuestionHandler(@RequestParam String answerReset, SessionStatus status, User user, Model model) {
if (!user.getAnswer().equals(answerReset)) {
// Handle error
...
} else {
// Handle success
...
}
}
}
user
實例從登入程序期間儲存所在的階段作業載入。但是,Spring 將會檢查要求並嘗試將其資料繫結至模型 user
實例。如果收到的要求包含可繫結至 User
類別的資料,Spring 會將收到的資料合併到使用者階段作業屬性。透過在 answerReset
查詢參數中提交任意答覆和相同的值覆寫階段作業中儲存的值,可濫用此案例。這樣一來,攻擊者可以為隨機使用者設定任意新密碼。
...
taintedConnectionStr = request->get_form_field( 'dbconn_name' ).
TRY.
DATA(con) = cl_sql_connection=>get_connection( `R/3*` && taintedConnectionStr ).
...
con->close( ).
CATCH cx_sql_exception INTO FINAL(exc).
...
ENDTRY.
...
sethostid(argv[1]);
...
sethostid()
,但是沒有被賦予權限的使用者也可能呼叫程式。這個範例中的程式碼允許使用者輸入直接控制系統設定的值。如果攻擊者向主機 ID 提供一個惡意值,攻擊者可能會誤認網路上受影響的機器,或者引發其他意料之外的行為。
...
ACCEPT OPT1.
ACCEPT OPT2
COMPUTE OPTS = OPT1 + OPT2.
CALL 'MQOPEN' USING HCONN, OBJECTDESC, OPTS, HOBJ, COMPOCODE REASON.
...
...
<cfset code = SetProfileString(IniPath,
Section, "timeout", Form.newTimeout)>
...
Form.newTimeout
的值用於定義逾時時間,所以攻擊者可以藉由定義超大的數值來啟動 denial of service (DoS),破壞應用程式的正常運作。
...
catalog := request.Form.Get("catalog")
path := request.Form.Get("path")
os.Setenv(catalog, path)
...
HttpServletRequest
讀取字串,並將該字串設定為資料庫 Connection
使用中的目錄。
...
conn.setCatalog(request.getParamter("catalog"));
...
http.IncomingMessage
要求變數中讀取字串,並使用它來設定額外的 V8 指令行旗標。
var v8 = require('v8');
...
var flags = url.parse(request.url, true)['query']['flags'];
...
v8.setFlagsFromString(flags);
...
<?php
...
$table_name=$_GET['catalog'];
$retrieved_array = pg_copy_to($db_connection, $table_name);
...
?>
...
catalog = request.GET['catalog']
path = request.GET['path']
os.putenv(catalog, path)
...
Connection
的使用中目錄。
def connect(catalog: String) = Action { request =>
...
conn.setCatalog(catalog)
...
}
...
sqlite3(SQLITE_CONFIG_LOG, user_controllable);
...
Request
物件讀取字串,並將該字串設定為資料庫 Connection
使用中的目錄。
...
Dim conn As ADODB.Connection
Set conn = New ADODB.Connection
Dim rsTables As ADODB.Recordset
Dim Catalog As New ADOX.Catalog
Set Catalog.ActiveConnection = conn
Catalog.Create Request.Form("catalog")
...
String beans = getBeanDefinitionFromUser();
GenericApplicationContext ctx = new GenericApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new UrlResource(beans));
ctx.refresh();
ACTUATOR
角色的使用者才能存取。
management.security.enabled=false
endpoints.health.sensitive=false
@Component
public class CustomEndpoint implements Endpoint<List<String>> {
public String getId() {
return "customEndpoint";
}
public boolean isEnabled() {
return true;
}
public boolean isSensitive() {
return false;
}
public List<String> invoke() {
// Custom logic to build the output
...
}
}