API는 호출자와 피호출자 간의 계약입니다. 가장 흔한 형태의 API 오용은 호출자가 이 계약에서 자신의 몫을 이행하지 못하기 때문에 발생합니다. 예를 들어, 프로그램이 chroot()를 호출한 후 chdir()을 호출하지 못하면 활성 루트 디렉터리를 안전하게 변경하는 방법을 지정하는 계약을 위반하는 것입니다. 라이브러리 오용의 또 다른 좋은 예는 피호출자가 호출자에게 신뢰할 만한 DNS 정보를 반환할 것으로 예상하는 것입니다. 이 경우, 호출자는 자신의 행동에 대해 특정한 가정을 함으로써(반환 값이 인증 목적으로 사용될 것으로 예상) 피호출자 API를 오용합니다. 다른 쪽에서 호출자-피호출자 계약을 위반할 수도 있습니다. 예를 들어, 코더가 하위 클래스 SecureRandom을 지정하고 임의 값이 아닌 값을 반환하는 경우 계약을 위반하는 것입니다.
private
및 final
을 선언한 다음 Set를 변경하는 메서드를 실수로 만듭니다.
@Immutable
public final class ThreeStooges {
private final Set stooges = new HashSet>();
...
public void addStooge(String name) {
stooges.add(name);
}
...
}
final
이 아닙니다.Immutable
주석으로 주석 추가되었습니다. 비 final 필드는 값이 변경되도록 허용하여 클래스의 불변성을 침해합니다.final
이 아닌 public
으로 선언합니다.
@Immutable
public class ImmutableInteger {
public int value;
}
public
및 final
을 선언합니다.
@Immutable
public final class ThreeStooges {
public final Set stooges = new HashSet();
...
}
ctx = new InitialContext();
datasource = (DataSource)ctx.lookup(DB_DATASRC_REF);
conn = datasource.getConnection();
conn = DriverManager.getConnection(CONNECT_STRING);
--auto-tls
플래그를 true
로 설정합니다. 결과적으로 etcd 인스턴스는 클라이언트와의 TLS 연결에 자체 서명된 인증서를 사용합니다.
...
spec:
containers:
- command:
...
- etcd
...
- --auto-tls=true
...
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; }
...
}
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()));
}
clone()
메서드는 super.clone()
을 호출하여 새 개체를 얻어야 합니다.clone()
구현은 super.clone()
을 호출하여 새 개체를 얻어야 합니다. 클래스가 이 규칙을 지키지 않으면 하위 클래스의 clone()
메서드가 잘못된 형식의 개체를 반환합니다.super.clone()
을 호출하지 않아서 발생하는 버그를 보여 줍니다. Kibitzer
가 clone()
을 구현하는 방법으로 인해 FancyKibitzer
의 clone 메서드는 FancyKibitzer
대신 Kibitzer
유형의 개체를 반환합니다.
public class Kibitzer implements Cloneable {
public Object clone() throws CloneNotSupportedException {
Object returnMe = new Kibitzer();
...
}
}
public class FancyKibitzer extends Kibitzer
implements Cloneable {
public Object clone() throws CloneNotSupportedException {
Object returnMe = super.clone();
...
}
}
Equals()
와 GetHashCode()
중 하나만 정의합니다.a.Equals(b) == true
이면 a.GetHashCode() == b.GetHashCode()
이어야 합니다. Equals()
를 오버라이드하지만 GetHashCode()
는 오버라이드하지 않습니다.
public class Halfway() {
public override boolean Equals(object obj) {
...
}
}
equals()
와 hashCode()
중 하나만 정의합니다.a.equals(b) == true
이면 a.hashCode() == b.hashCode()
이어야 합니다. equals()
를 오버라이드하지만 hashCode()
는 오버라이드하지 않습니다.
public class halfway() {
public boolean equals(Object obj) {
...
}
}
saveState()
와 restoreState()
중 하나만 정의합니다.saveState(javax.faces.context.FacesContext)
및 restoreState(javax.faces.context.FacesContext, java.lang.Object)
를 구현하거나 둘 다 구현하지 않아야 합니다. 이 두 가지 메서드는 밀접한 관계가 있으므로 상속 계층의 서로 다른 수준에 saveState(javax.faces.context.FacesContext)
및 restoreState(javax.faces.context.FacesContext, java.lang.Object)
메서드를 두는 것은 허용되지 않습니다.saveState()
를 정의해도 restoreState()
는 정의하지 않으므로 해당 클래스를 확장하는 클래스의 모든 작업에서 항상 오류가 발생합니다.
public class KibitzState implements StateHolder {
public Object saveState(FacesContext fc) {
...
}
}
checkCallingOrSelfPermission()
또는 checkCallingOrSelfUriPermission()
함수는 호출 프로그램이 특정 서비스 또는 지정된 URI에 액세스하는 데 필요한 권한이 있는지 확인합니다. 그러나 이러한 함수는 해당 응용 프로그램 권한을 가정하여 적절한 권한이 없는 악성 응용 프로그램에 액세스 권한을 부여할 수 있으므로 조심해서 사용해야 합니다.Assert()
를 사용하면 현재 제어 흐름에 지정된 권한이 있다고 말할 수 있습니다. 이로 인해 필요한 권한이 충족되면 .NET Framework가 더 이상의 권한 검사를 수행하지 않습니다. 즉, Assert()
를 호출하는 코드를 호출하는 코드가 필요한 권한을 갖지 않을 수 있습니다. 일부 경우에는 Assert()
를 사용하는 것이 도움이 되지만 악의적인 사용자가 달리 권한이 없는 리소스를 제어할 수 있도록 허용할 때 취약점이 발생할 수 있습니다.
IPAddress hostIPAddress = IPAddress.Parse(RemoteIpAddress);
IPHostEntry hostInfo = Dns.GetHostByAddress(hostIPAddress);
if (hostInfo.HostName.EndsWith("trustme.com")) {
trusted = true;
}
getlogin()
함수는 스푸핑하기 쉽습니다. 함수가 반환하는 이름을 신뢰하지 마십시오.getlogin()
함수는 현재 터미널에 로그인한 사용자의 이름이 들어 있는 문자열을 반환하는 함수이지만 공격자가 getlogin()
이 시스템에 로그인한 사용자의 이름을 반환하게 만들 수 있습니다. 보안 결정을 내릴 때 getlogin()
이 반환하는 이름에 의존해서는 안 됩니다.getlogin()
에 의존하여 사용자에 대한 신뢰 여부를 결정합니다. 이 함수는 쉽게 조작할 수 있습니다.
pwd = getpwnam(getlogin());
if (isTrustedGroup(pwd->pw_gid)) {
allow();
} else {
deny();
}
String ip = request.getRemoteAddr();
InetAddress addr = InetAddress.getByName(ip);
if (addr.getCanonicalHostName().endsWith("trustme.com")) {
trusted = true;
}
Boolean.getBoolean()
메서드는 Boolean.valueOf()
또는 Boolean.parseBoolean()
메서드 호출과 혼동하는 경우가 많습니다.Boolean.getBoolean()
에 대한 호출은 지정된 문자열 인수로 나타내는 부울 값을 반환하는 것으로 가정하기 때문에 자주 오용됩니다. 그러나 Javadoc에 언급된 것처럼 Boolean.getBoolean(String)
메서드는 "해당 인수에 의해 명명된 시스템 속성이 존재하고 'true' 문자열과 동일한 경우에만 true를 반환합니다."Boolean.valueOf(String)
또는 Boolean.parseBoolean(String)
메서드 호출이었습니다.Boolean.getBoolean(String)
이 String 기본 형식을 변환하지 못하기 때문에 "FALSE"를 출력합니다. 이 코드는 시스템 속성만 변환합니다.
...
String isValid = "true";
if ( Boolean.getBoolean(isValid) ) {
System.out.println("TRUE");
}
else {
System.out.println("FALSE");
}
...
Decoder
및 Encoding
클래스의 GetChars
메서드와 .NET Framework의 Encoder
및 Encoding
클래스의 GetBytes
메서드는 문자 및 바이트 배열에 대해 내부적으로 포인터 산술을 수행하여 문자 범위를 바이트 범위로 변환하거나 그 반대로 수행합니다.
out.println("x = " + encoder.encodeForJavaScript(input) + ";");
...
unichar ellipsis = 0x2026;
NSString *myString = [NSString stringWithFormat:@"My Test String%C", ellipsis];
NSData *asciiData = [myString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *asciiString = [[NSString alloc] initWithData:asciiData encoding:NSASCIIStringEncoding];
NSLog(@"Original: %@ (length %d)", myString, [myString length]);
NSLog(@"Best-fit-mapped: %@ (length %d)", asciiString, [asciiString length]);
// output:
// Original: My Test String... (length 15)
// Best-fit-mapped: My Test String... (length 17)
...
...
let ellipsis = 0x2026;
let myString = NSString(format:"My Test String %C", ellipsis)
let asciiData = myString.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion:true)
let asciiString = NSString(data:asciiData!, encoding:NSASCIIStringEncoding)
NSLog("Original: %@ (length %d)", myString, myString.length)
NSLog("Best-fit-mapped: %@ (length %d)", asciiString!, asciiString!.length)
// output:
// Original: My Test String ... (length 16)
// Best-fit-mapped: My Test String ... (length 18)
...