webview
로 페이지를 로드하지만 악성 사이트 방문 시 자동 다이얼링 공격을 방지하는 어떠한 제어도 구현하지 않습니다.webview
를 사용하여 신뢰할 수 없는 링크가 포함되어 있을 수 있는 사이트를 로드하지만 이 webview
에서 시작된 요청을 검증할 수 있는 대리자를 지정하지 않습니다.
...
NSURL *webUrl = [[NSURL alloc] initWithString:@"https://some.site.com/"];
NSURLRequest *webRequest = [[NSURLRequest alloc] initWithURL:webUrl];
[_webView loadRequest:webRequest];
...
webview
로 페이지를 로드하지만 악성 사이트 방문 시 자동 다이얼링 공격을 방지하는 어떠한 제어도 구현하지 않습니다.webview
를 사용하여 신뢰할 수 없는 링크가 포함되어 있을 수 있는 사이트를 로드하지만 이 webview
에서 시작된 요청을 검증할 수 있는 대리자를 지정하지 않습니다.
...
let webUrl : NSURL = NSURL(string: "https://some.site.com/")!
let webRequest : NSURLRequest = NSURLRequest(URL: webUrl)
webView.loadRequest(webRequest)
...
webview
로 페이지를 로드하지만 사용자가 클릭할 수 있는 링크를 확인 또는 검증하는 제어를 구현하지 않습니다.webview
를 사용하여 신뢰할 수 없는 링크가 포함되어 있을 수 있는 사이트를 로드하지만 이 webview
에서 시작된 요청을 검증할 수 있는 대리자를 지정하지 않습니다.
...
NSURL *webUrl = [[NSURL alloc] initWithString:@"https://some.site.com/"];
NSURLRequest *webRequest = [[NSURLRequest alloc] initWithURL:webUrl];
[webView loadRequest: webRequest];
webview
로 페이지를 로드하지만 사용자가 클릭할 수 있는 링크를 확인 또는 검증하는 제어를 구현하지 않습니다.webview
를 사용하여 신뢰할 수 없는 링크가 포함되어 있을 수 있는 사이트를 로드하지만 이 webview
에서 시작된 요청을 검증할 수 있는 대리자를 지정하지 않습니다.
...
let webUrl = URL(string: "https://some.site.com/")!
let urlRequest = URLRequest(url: webUrl)
webView.load(webRequest)
...
...
DATA log_msg TYPE bal_s_msg.
val = request->get_form_field( 'val' ).
log_msg-msgid = 'XY'.
log_msg-msgty = 'E'.
log_msg-msgno = '123'.
log_msg-msgv1 = 'VAL: '.
log_msg-msgv2 = val.
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
I_S_MSG = log_msg
EXCEPTIONS
LOG_NOT_FOUND = 1
MSG_INCONSISTENT = 2
LOG_IS_FULL = 3
OTHERS = 4.
...
val
에 문자열 "FOO
"을 전송하면 다음 항목이 기록됩니다.
XY E 123 VAL: FOO
FOO XY E 124 VAL: BAR
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
XY E 123 VAL: FOO XY E 124 VAL: BAR
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var val:String = String(params["username"]);
var value:Number = parseInt(val);
if (value == Number.NaN) {
trace("Failed to parse val = " + val);
}
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
Failed to parse val=twenty-one
User logged out=badguy
...
string val = (string)Session["val"];
try {
int value = Int32.Parse(val);
}
catch (FormatException fe) {
log.Info("Failed to parse val= " + val);
}
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
long value = strtol(val, &endPtr, 10);
if (*endPtr != '\0')
syslog(LOG_INFO,"Illegal value = %s",val);
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
Illegal value=twenty-one
twenty-one\n\nINFO: User logged out=evil
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Illegal value=twenty-one
INFO: User logged out=evil
...
01 LOGAREA.
05 VALHEADER PIC X(50) VALUE 'VAL: '.
05 VAL PIC X(50).
...
EXEC CICS
WEB READ
FORMFIELD(NAME)
VALUE(VAL)
...
END-EXEC.
EXEC DLI
LOG
FROM(LOGAREA)
LENGTH(50)
END-EXEC.
...
VAL
에 문자열 "FOO
"을 전송하면 다음 항목이 기록됩니다.
VAL: FOO
FOO VAL: BAR
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
VAL: FOO VAL: BAR
<cflog file="app_log" application="No" Thread="No"
text="Failed to parse val="#Form.val#">
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
"Information",,"02/28/01","14:50:37",,"Failed to parse val=twenty-one"
twenty-one%0a%0a%22Information%22%2C%2C%2202/28/01%22%2C%2214:53:40%22%2C%2C%22User%20logged%20out:%20badguy%22
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
"Information",,"02/28/01","14:50:37",,"Failed to parse val=twenty-one"
"Information",,"02/28/01","14:53:40",,"User logged out: badguy"
func someHandler(w http.ResponseWriter, r *http.Request){
r.parseForm()
name := r.FormValue("name")
logout := r.FormValue("logout")
...
if (logout){
...
} else {
log.Printf("Attempt to log out: name: %s logout: %s", name, logout)
}
}
logout
에 대해 "twenty-one
" 문자열을 제출하고 "admin
"이라는 이름을 가진 사용자를 생성할 수 있는 경우 다음 항목이 기록됩니다.
Attempt to log out: name: admin logout: twenty-one
admin+logout:+1+++++++++++++++++++++++
"라는 사용자 이름을 생성할 수 있으면 다음 항목이 기록됩니다.
Attempt to log out: name: admin logout: 1 logout: twenty-one
...
String val = request.getParameter("val");
try {
int value = Integer.parseInt(val);
}
catch (NumberFormatException nfe) {
log.info("Failed to parse val = " + val);
}
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
Example 1
을 Android 플랫폼에 맞게 조정합니다.
...
String val = this.getIntent().getExtras().getString("val");
try {
int value = Integer.parseInt();
}
catch (NumberFormatException nfe) {
Log.e(TAG, "Failed to parse val = " + val);
}
...
var cp = require('child_process');
var http = require('http');
var url = require('url');
function listener(request, response){
var val = url.parse(request.url, true)['query']['val'];
if (isNaN(val)){
console.log("INFO: Failed to parse val = " + val);
}
...
}
...
http.createServer(listener).listen(8080);
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val = twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
long value = strtol(val, &endPtr, 10);
if (*endPtr != '\0')
NSLog("Illegal value = %s",val);
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Illegal value=twenty-one
twenty-one\n\nINFO: User logged out=evil
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Illegal value=twenty-one
INFO: User logged out=evil
<?php
$name =$_GET['name'];
...
$logout =$_GET['logout'];
if(is_numeric($logout))
{
...
}
else
{
trigger_error("Attempt to log out: name: $name logout: $val");
}
?>
logout
에 대해 "twenty-one
" 문자열을 제출하고 "admin
"이라는 이름을 가진 사용자를 생성할 수 있는 경우 다음 항목이 기록됩니다.
PHP Notice: Attempt to log out: name: admin logout: twenty-one
admin+logout:+1+++++++++++++++++++++++
"라는 사용자 이름을 생성할 수 있으면 다음 항목이 기록됩니다.
PHP Notice: Attempt to log out: name: admin logout: 1 logout: twenty-one
name = req.field('name')
...
logout = req.field('logout')
if (logout):
...
else:
logger.error("Attempt to log out: name: %s logout: %s" % (name,logout))
logout
에 대해 "twenty-one
" 문자열을 제출하고 "admin
"이라는 이름을 가진 사용자를 생성할 수 있는 경우 다음 항목이 기록됩니다.
Attempt to log out: name: admin logout: twenty-one
admin+logout:+1+++++++++++++++++++++++
"라는 사용자 이름을 생성할 수 있으면 다음 항목이 기록됩니다.
Attempt to log out: name: admin logout: 1 logout: twenty-one
...
val = req['val']
unless val.respond_to?(:to_int)
logger.info("Failed to parse val")
logger.info(val)
end
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val
INFO: twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val
INFO: twenty-one
INFO: User logged out=badguy
...
let num = Int(param)
if num == nil {
NSLog("Illegal value = %@", param)
}
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Illegal value = twenty-one
twenty-one\n\nINFO: User logged out=evil
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Illegal value=twenty-one
INFO: User logged out=evil
...
Dim Val As Variant
Dim Value As Integer
Set Val = Request.Form("val")
If IsNumeric(Val) Then
Set Value = Val
Else
App.EventLog "Failed to parse val=" & Val, 1
End If
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
Failed to parse val=twenty-one
twenty-one%0a%0a+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
Failed to parse val=twenty-one
User logged out=badguy
@HttpGet
global static void doGet() {
RestRequest req = RestContext.request;
String val = req.params.get('val');
try {
Integer i = Integer.valueOf(val);
...
} catch (TypeException e) {
System.Debug(LoggingLevel.INFO, 'Failed to parse val: '+val);
}
}
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
Failed to parse val: twenty-one
twenty-one%0a%0aUser+logged+out%3dbadguy
" 문자열을 다음 항목이 기록됩니다.
Failed to parse val: twenty-one
User logged out=badguy
...
String val = request.Params["val"];
try {
int value = Int.Parse(val);
}
catch (FormatException fe) {
log.Info("Failed to parse val = " + val);
}
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
Example 1
을 Android 플랫폼에 맞게 조정합니다.
...
String val = this.Intent.Extras.GetString("val");
try {
int value = Int.Parse(val);
}
catch (FormatException fe) {
Log.E(TAG, "Failed to parse val = " + val);
}
...
...
var idValue string
idValue = req.URL.Query().Get("id")
num, err := strconv.Atoi(idValue)
if err != nil {
sysLog.Debug("Failed to parse value: " + idValue)
}
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
...
String val = request.getParameter("val");
try {
int value = Integer.parseInt(val);
}
catch (NumberFormatException nfe) {
log.info("Failed to parse val = " + val);
}
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
Example 1
을 Android 플랫폼에 맞게 조정합니다.
...
String val = this.getIntent().getExtras().getString("val");
try {
int value = Integer.parseInt();
}
catch (NumberFormatException nfe) {
Log.e(TAG, "Failed to parse val = " + val);
}
...
var cp = require('child_process');
var http = require('http');
var url = require('url');
function listener(request, response){
var val = url.parse(request.url, true)['query']['val'];
if (isNaN(val)){
console.error("INFO: Failed to parse val = " + val);
}
...
}
...
http.createServer(listener).listen(8080);
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
...
val = request.GET["val"]
try:
int_value = int(val)
except:
logger.debug("Failed to parse val = " + val)
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
...
val = req['val']
unless val.respond_to?(:to_int)
logger.debug("Failed to parse val")
logger.debug(val)
end
...
val
에 문자열 "twenty-one
"을 전송하면 다음 항목이 기록됩니다.
DEBUG: Failed to parse val
DEBUG: twenty-one
twenty-one%0a%DEBUG:+User+logged+out%3dbadguy
" 문자열을 전송하는 경우 다음 항목이 기록됩니다.
DEBUG: Failed to parse val
DEBUG: twenty-one
DEBUG: User logged out=badguy
CREATE
명령을 만듭니다. 공격자는 이 매개 변수를 사용하여 서버로 전송되는 명령을 수정하고 CRLF 문자를 사용하여 새 명령을 삽입할 수 있습니다.
...
final String foldername = request.getParameter("folder");
IMAPFolder folder = (IMAPFolder) store.getFolder("INBOX");
...
folder.doCommand(new IMAPFolder.ProtocolCommand() {
@Override
public Object doCommand(IMAPProtocol imapProtocol) throws ProtocolException {
try {
imapProtocol.simpleCommand("CREATE " + foldername, null);
} catch (Exception e) {
// Handle Exception
}
return null;
}
});
...
USER
및 PASS
명령을 만듭니다. 공격자는 이 매개 변수를 사용하여 서버로 전송되는 명령을 수정하고 CRLF 문자를 사용하여 새 명령을 삽입할 수 있습니다.
...
String username = request.getParameter("username");
String password = request.getParameter("password");
...
POP3SClient pop3 = new POP3SClient(proto, false);
pop3.login(username, password)
...
VRFY
명령을 작성합니다. 공격자는 이 매개 변수를 사용하여 서버로 전송된 명령을 수정하고 CRLF 문자를 사용하는 새 명령을 주입할 수 있습니다.
...
c, err := smtp.Dial(x)
if err != nil {
log.Fatal(err)
}
user := request.FormValue("USER")
c.Verify(user)
...
VRFY
명령을 만듭니다. 공격자는 이 매개 변수를 사용하여 서버로 전송되는 명령을 수정하고 CRLF 문자를 사용하여 새 명령을 삽입할 수 있습니다.
...
String user = request.getParameter("user");
SMTPSSLTransport transport = new SMTPSSLTransport(session,new URLName(Utilities.getProperty("smtp.server")));
transport.connect(Utilities.getProperty("smtp.server"), username, password);
transport.simpleCommand("VRFY " + user);
...
VRFY
명령을 만듭니다. 공격자는 이 매개 변수를 사용하여 서버로 전송되는 명령을 수정하고 CRLF 문자를 사용하여 새 명령을 삽입할 수 있습니다.
...
user = request.GET['user']
session = smtplib.SMTP(smtp_server, smtp_tls_port)
session.ehlo()
session.starttls()
session.login(username, password)
session.docmd("VRFY", user)
...
RegisterModel
또는Details
클래스에서 모든 속성으로 HTTP 요청 매개 변수를 바인딩합니다.
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
try
{
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", "");
}
}
return View(model);
}
RegisterModel
클래스는 다음과 같이 정의됩니다.
public class RegisterModel
{
[BindRequired]
[Display(Name = "User name")]
public string UserName { get; set; }
[BindRequired]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
public string ConfirmPassword { get; set; }
public Details Details { get; set; }
public RegisterModel()
{
Details = new Details();
}
}
Details
클래스는 다음과 같이 정의됩니다.예제 2: ASP.NET MVC 또는 Web API 응용 프로그램에서
public class Details
{
public bool IsAdmin { get; set; }
...
}
TryUpdateModel()
또는UpdateModel()
을 사용하는 경우 모델 바인더는 기본적으로 모든 HTTP 요청 매개 변수를 자동 바인딩하려고 합니다.예제 3: ASP.NET Web Form 응용 프로그램에서 모델 바인더는 IValueProvider 인터페이스로
public ViewResult Register()
{
var model = new RegisterModel();
TryUpdateModel<RegisterModel>(model);
return View("detail", model);
}
TryUpdateModel()
또는UpdateModel()
을 사용하는 경우 모든 HTTP 요청 매개 변수를 자동으로 바인딩하려고 시도합니다.
Employee emp = new Employee();
TryUpdateModel(emp, new System.Web.ModelBinding.FormValueProvider(ModelBindingExecutionContext));
if (ModelState.IsValid)
{
db.SaveChanges();
}
Employee
클래스는 다음과 같이 정의됩니다.
public class Employee
{
public Employee()
{
IsAdmin = false;
IsManager = false;
}
public string Name { get; set; }
public string Email { get; set; }
public bool IsManager { get; set; }
public bool IsAdmin { get; set; }
}
Booking
클래스의 모든 속성에 바인딩합니다.
<view-state id="enterBookingDetails" model="booking">
<on-render>
<render fragments="body" />
</on-render>
<transition on="proceed" to="reviewBooking">
</transition>
<transition on="cancel" to="cancel" bind="false" />
</view-state>
Booking
클래스는 다음으로 정의됩니다.
public class Booking implements Serializable {
private Long id;
private User user;
private Hotel hotel;
private Date checkinDate;
private Date checkoutDate;
private String creditCard;
private String creditCardName;
private int creditCardExpiryMonth;
private int creditCardExpiryYear;
private boolean smoking;
private int beds;
private Set<Amenity> amenities;
// Public Getters and Setters
...
}
Order
, Customer
및 Profile
은 Microsoft .NET Entity 지속형 클래스입니다.
public class Order {
public string ordered { get; set; }
public List<LineItem> LineItems { get; set; }
pubilc virtual Customer Customer { get; set; }
...
}
public class Customer {
public int CustomerId { get; set; }
...
public virtual Profile Profile { get; set; }
...
}
public class Profile {
public int profileId { get; set; }
public string username { get; set; }
public string password { get; set; }
...
}
OrderController
는 요청을 처리하는 ASP.NET MVC 컨트롤러 클래스입니다.
public class OrderController : Controller{
StoreEntities db = new StoreEntities();
...
public String updateOrder(Order order) {
...
db.Orders.Add(order);
db.SaveChanges();
}
}
Order
, Customer
및 Profile
은 Hibernate 지속형 클래스입니다.
public class Order {
String ordered;
List lineItems;
Customer cust;
...
}
public class Customer {
String customerId;
...
Profile p;
...
}
public class Profile {
String profileId;
String username;
String password;
...
}
OrderController
는 요청을 처리하는 Spring 컨트롤러 클래스입니다.
@Controller
public class OrderController {
...
@RequestMapping("/updateOrder")
public String updateOrder(Order order) {
...
session.save(order);
}
}
[FromBody]
주석이 사용되는 경우 Input Formatter에 의존합니다[FromBody]
주석이 작업의 복잡한 매개 변수에 적용되고나면 매개 변수 유형이나 해당 필드에 적용된 [Bind]
또는[BindNever]
같은 다른 바인딩 속성은 사실상 무시됩니다. 이는 바인딩 주석을 사용한 완화가 불가능함을 의미합니다.[FromBody]
주석이 작업의 매개 변수에 적용되면 모델 바인더는 Input Formatter를 사용하여 요청 본문에 지정된 모든 매개 변수를 자동으로 바인딩하려고 시도합니다. 기본적으로 바인더는 JSON Input Formatter를 사용하여 요청 본문에서 나오는 가능한 모든 매개 변수를 바인딩하려고 시도합니다.
[HttpPost]
public ActionResult Create([FromBody] Product p)
{
return View(p.Name);
}
Product
유형에 적용되는 [Bind]
또는 [BindNever]
같은 바인딩 주석은 [FromBody]
주석이 있으면 사용되는 Input Formatters로 인해 무시됩니다.
public class Product
{
...
public string Name { get; set; }
public bool IsAdmin { get; set; }
...
}
Register
)는 이름 및 암호를 제공하여 계정을 등록하도록 사용자에게 묻는 웹 폼에서 액세스됩니다.
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
try
{
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", "");
}
}
return View(model);
}
RegisterModel
클래스는 다음과 같이 정의됩니다.
public class RegisterModel
{
[BindRequired]
[Display(Name = "User name")]
public string UserName { get; set; }
[BindRequired]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
public string ConfirmPassword { get; set; }
public Details Details { get; set; }
public RegisterModel()
{
Details = new Details();
}
}
Details
클래스는 다음과 같이 정의됩니다.
public class Details
{
public bool IsAdmin { get; set; }
...
}
Example 1
에 제공된 시나리오와 같이 공격자는 응용 프로그램을 탐색하고 RegisterModel
모델에 Details
속성이 있는지 발견할 수 있습니다. 이러한 경우 공격자는 속성에 할당된 현재 값을 덮어쓰려 할 수도 있습니다.
name=John&password=****&details.is_admin=true
<struts-config>
<form-beans>
<form-bean name="dynaUserForm"
type="org.apache.struts.action.DynaActionForm" >
<form-property name="type" type="java.lang.String" />
<form-property name="user" type="com.acme.common.User" />
</form-bean>
...
User
클래스는 다음으로 정의됩니다.
public class User {
private String name;
private String lastname;
private int age;
private Details details;
// Public Getters and Setters
...
}
Details
클래스는 다음으로 정의됩니다.
public class Details {
private boolean is_admin;
private int id;
private Date login_date;
// Public Getters and Setters
...
}
Example 1
에 제공된 시나리오와 같이 공격자는 응용 프로그램을 탐색하고 User
모델에 details
속성이 있는지 발견할 수 있습니다. 이러한 경우 공격자는 속성에 할당된 현재 값을 덮어쓰려 할 수도 있습니다.
type=free&user.name=John&user.lastname=Smith&age=22&details.is_admin=true
...
TextClient tc = (TextClient)Client.GetInstance("127.0.0.1", 11211, MemcachedFlags.TextProtocol);
tc.Open();
string id = txtID.Text;
var result = get_page_from_somewhere();
var response = Http_Response(result);
tc.Set("req-" + id, response, TimeSpan.FromSeconds(1000));
tc.Close();
tc = null;
...
set req-1233 0 1000 n
<serialized_response_instance>
n
은 응답의 길이입니다.ignore 0 0 1\r\n1\r\nset injected 0 3600 10\r\n0123456789\r\nset req-
를 보낼 수 있으며, 그러면 작업이 다음과 같이 됩니다.
set req-ignore 0 0 1
1
set injected 0 3600 10
0123456789
set req-1233 0 0 n
<serialized_response_instance>
injected=0123456789
캐시에 새 키/값 쌍을 추가하며, 공격자가 이 캐시를 감염시킬 수 있습니다.
...
def store(request):
id = request.GET['id']
result = get_page_from_somewhere()
response = HttpResponse(result)
cache_time = 1800
cache.set("req-" % id, response, cache_time)
return response
...
set req-1233 0 0 n
<serialized_response_instance>
ignore 0 0 1\r\n1\r\nset injected 0 3600 10\r\n0123456789\r\nset req-
를 보낼 수 있으며, 그러면 작업이 다음과 같이 됩니다.
set req-ignore 0 0 1
1
set injected 0 3600 10
0123456789
set req-1233 0 0 n
<serialized_response_instance>
injected=0123456789
캐시에 새 키/값 쌍을 성공적으로 추가합니다. 페이로드에 따라 다르지만 공격자는 역직렬화 시 임의의 코드를 실행하며 Pickle을 통해 직렬화된 페이로드를 주입하여 임의의 코드를 실행하거나 캐시를 감염시킬 수 있습니다.read()
호출이 예상 바이트 수를 반환하지 않으면 할당된 메모리 블록을 누출합니다.
char* getBlock(int fd) {
char* buf = (char*) malloc(BLOCK_SIZE);
if (!buf) {
return NULL;
}
if (read(fd, buf, BLOCK_SIZE) != BLOCK_SIZE) {
return NULL;
}
return buf;
}
CALL "CBL_ALLOC_MEM"
USING mem-pointer
BY VALUE mem-size
BY VALUE flags
RETURNING status-code
END-CALL
IF status-code NOT = 0
DISPLAY "Error!"
GOBACK
ELSE
SET ADDRESS OF mem TO mem-pointer
END-IF
PERFORM write-data
IF ws-status-code NOT = 0
DISPLAY "Error!"
GOBACK
ELSE
DISPLAY "Success!"
END-IF
CALL "CBL_FREE_MEM"
USING BY VALUE mem-pointer
RETURNING status-code
END-CALL
GOBACK
.
dealloc()
메서드에서 해제하지 못합니다.init()
메서드에서 메모리를 할당하지만 deallocate()
메서드에서 해제하지 못하여 이로 인해 memory leak이 발생합니다.
- (void)init
{
myVar = [NSString alloc] init];
...
}
- (void)dealloc
{
[otherVar release];
}
realloc()
호출이 원래의 할당에 대한 크기 조절이 실패하면 할당된 메모리 블록을 누출합니다.
char* getBlocks(int fd) {
int amt;
int request = BLOCK_SIZE;
char* buf = (char*) malloc(BLOCK_SIZE + 1);
if (!buf) {
goto ERR;
}
amt = read(fd, buf, request);
while ((amt % BLOCK_SIZE) != 0) {
if (amt < request) {
goto ERR;
}
request = request + BLOCK_SIZE;
buf = realloc(buf, request);
if (!buf) {
goto ERR;
}
amt = read(fd, buf, request);
}
return buf;
ERR:
if (buf) {
free(buf);
}
return NULL;
}
realloc()
호출이 실패할 경우 할당된 메모리 블록의 누수를 야기합니다.
CALL "malloc" USING
BY VALUE mem-size
RETURNING mem-pointer
END-CALL
ADD 1000 TO mem-size
CALL "realloc" USING
BY VALUE mem-pointer
BY VALUE mem-size
RETURNING mem-pointer
END-CALL
IF mem-pointer <> null
CALL "free" USING
BY VALUE mem-pointer
END-CALL
END-IF
null
을 반환하는 함수의 반환 값을 확인하지 않으므로 null 포인터를 역참조할 수도 있습니다.Equals()
를 호출하기 전에 Item
속성이 반환한 문자열이 null
인지 검사하지 않기 때문에 null
dereference가 발생할 수 있습니다.
string itemName = request.Item(ITEM_NAME);
if (itemName.Equals(IMPORTANT_ITEM)) {
...
}
...
null
값을 역참조하다가 중지해도 상관 없습니다.”null
을 반환하는 함수의 반환 값을 확인하지 않으므로 null 포인터를 역참조할 수도 있습니다.malloc()
이 반환하는 포인터를 사용하기 전에 메모리 할당이 성공했는지 확인하지 않습니다.
buf = (char*) malloc(req_size);
strncpy(buf, xfer, req_size);
req_size
가 너무 크거나 동시에 처리해야 할 요청이 너무 많아서 malloc()
호출이 실패했습니까? 또는 시간이 흐르면서 누적된 memory leak 때문에 발생했습니까? 오류를 처리하지 않고는 알 방법이 없습니다.null
을 반환하는 함수의 반환 값을 확인하지 않으므로 null 포인터를 역참조할 수도 있습니다.compareTo()
를 호출하기 전에 getParameter()
가 반환한 문자열이 null
인지 검사하지 않기 때문에 null
dereference가 발생할 수 있습니다.예제 2: 다음 코드는
String itemName = request.getParameter(ITEM_NAME);
if (itemName.compareTo(IMPORTANT_ITEM)) {
...
}
...
null
로 설정되면 해당 속성이 항상 정의된다는 잘못된 가정을 하는 프로그래머가 역참조하는 시스템 속성을 보여줍니다.
System.clearProperty("os.name");
...
String os = System.getProperty("os.name");
if (os.equalsIgnoreCase("Windows 95") )
System.out.println("Not supported");
null
값을 역참조하다가 중지해도 상관 없습니다.”null
을 비교해야 하는 약정을 위반합니다.null
인 경우 Object.equals()
, Comparable.compareTo()
및 Comparator.compare()
의 구현은 지정된 값을 반환해야 합니다. 이 약정을 따르지 않으면 예기치 못한 동작이 발생할 수 있습니다.equals()
메서드의 구현은 해당 매개 변수와 null
을 비교하지 않습니다.
public boolean equals(Object object)
{
return (toString().equals(object.toString()));
}
def form = Form(
mapping(
"name" -> text,
"age" -> number
)(UserData.apply)(UserData.unapply)
)
FormAction
을 정의합니다.예제 2: 다음 코드는 예상된 요구 사항을 기준으로 데이터를 검증하지 않는 Spring WebFlow 작업 상태를 정의합니다.
<bean id="customerCriteriaAction" class="org.springframework.webflow.action.FormAction">
<property name="formObjectClass"
value="com.acme.domain.CustomerCriteria" />
<property name="propertyEditorRegistrar">
<bean
class="com.acme.web.PropertyEditors" />
</property>
</bean>
<action-state>
<action bean="transferMoneyAction" method="bind" />
</action-state>
def form = Form(
mapping(
"name" -> text,
"age" -> number
)(UserData.apply)(UserData.unapply)
)
clone()
메서드에서 동일한 검사를 수행해야 합니다.clone()
메서드가 호출될 때 복제될 클래스에 대한 구성자는 호출되지 않습니다. 따라서, SecurityManager 또는 AccessController 검사가 cloneable 클래스의 구성자에 존재하는 경우, 동일한 검사가 클래스의 clone 메서드에도 존재해야 합니다. 그렇지 않으면, 클래스가 복제될 때 보안 검사가 무시됩니다.clone()
메서드가 아니라 구성자의 SecurityManager
검사가 포함되어 있습니다.
public class BadSecurityCheck implements Cloneable {
private int id;
public BadSecurityCheck() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new BadPermission("BadSecurityCheck"));
}
id = 1;
}
public Object clone() throws CloneNotSupportedException {
BadSecurityCheck bsm = (BadSecurityCheck)super.clone();
return null;
}
}
SecurityManager
검사를 수행하는 serializable 클래스는 readObject()
및 readObjectNoData
메서드에서 동일한 검사를 수행해야 합니다.readObject()
메서드가 호출될 때 역직렬화될 클래스에 대한 구성자는 호출되지 않습니다. 따라서, SecurityManager
검사가 serializable 클래스의 구성자에 존재하는 경우, 동일한 SecurityManager
검사가 readObject()
및 readObjectNoData()
메서드에도 존재해야 합니다. 그렇지 않으면, 클래스가 역직렬화될 때 보안 검사가 무시됩니다.readObject()
및 readObjectNoData()
메서드가 아니라 구성자의 SecurityManager
검사가 포함됩니다.
public class BadSecurityCheck implements Serializable {
private int id;
public BadSecurityCheck() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new BadPermission("BadSecurityCheck"));
}
id = 1;
}
public void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
in.defaultReadObject();
}
public void readObjectNoData(ObjectInputStream in) throws ClassNotFoundException, IOException {
in.defaultReadObject();
}
}