Software security is not security software. Here we're concerned with topics like authentication, access control, confidentiality, cryptography, and privilege management.
...
<cfquery name = "GetSSNs" dataSource = "users"
username = "scott" password = "tiger">
SELECT SSN
FROM Users
</cfquery>
...
...
Credentials.basic("hardcoded-username", password);
...
http://www.example.com/sws/manager.pl?add&pass=PassWord
...
PARAMETERS: p_input TYPE sy-mandt.
SELECT *
FROM employee_records
CLIENT SPECIFIED
INTO TABLE tab_output
WHERE mandt = p_input.
...
SY-MANDT
.SECRET_KEY
setting. If the SECRET_KEY
is leaked, an attacker cannot only falsify session data, but if application uses Pickle to serialize session data into cookies, an attacker will be able to craft malicious pickled data that will execute arbitrary code upon deserialization.Host
header can allow an attacker to send a fake Host
value that can be used for Cross-Site Request Forgery, cache poisoning attacks, and poisoning links in emails.*
" as an entry in the ALLOWED_HOSTS
setting. This setting is used by django.http.HttpRequest.get_host()
to validate the Host
header. A value of "*
" will allow any host in the Host
header. An attacker may use this in cache poisoning attacks or for poisoning links in emails.Host
value to reference the site that serves the reset password feature in order to avoid hardcoded URLs. For example:
...
def reset_password(request):
url = "http://%s/new_password/?token=%s" % (request.get_host(), generate_token())
send_email(reset_link=url)
redirect("home")
...
Host
header value pointing to a server he controls. The victim will receive an email with a link to the reset password system and if he decides to visit the link, she will be visiting the attacker-controlled site which will serve a fake form to collect the victim's credentials.SECRET_KEY
is leaked, an attacker will be able to store arbitrary data in the session cookie which will be deserialized in the server leading to arbitrary code execution.SECRET_KEY
if it is hardcoded in settings.py
configuration file:
...
def some_view_method(request):
url = request.GET['url']
if "http://" in url:
content = urllib.urlopen(url)
return HttpResponse(content)
...
Example 1
method checks that the url
parameter is a valid URL by checking that "http://" is present in the URL. A malicious attacker may send the following URL to leak the settings.py
configuration file that may contain the SECRET_KEY
:
file://proc/self/cwd/app/settings.py#http://
script
tag:
<script src="http://www.example.com/js/fancyWidget.js"></script>
www.example.com
to load their own JavaScript.
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
, such as "../../localuser/public_html/.htpasswd
", the application will make the specified file readable to the attacker.
...
$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
, such as "../../localuser/public_html/.htpasswd
", the application will make the specified file readable to the attacker.
...
mask = config_params['perms']
File.chmod(filename, mask)
...
if (password eq '783-1') {
getURL('http://.../client_pages/.../783.html', '');
}
else {
if (password eq '771-2 Update') {
getURL('http://.../client_pages/.../771.html', '');
}
else {
if (password eq '7990') {
getURL('http://.../client_pages/.../799.html', '');
}
}
ExternalInterface
, fscommand
or getURL
. XML.load
, loadVariables
, LoadVars.load
etc. If a Flash application should not communicate with the browser or needs to make any networking calls, the AllowNetworkingAccess
tag must be set to "none".AllowNetworkingAccess
tag must be set to "none"
. AllowNetworkingAccess
tag should be set to "internal"
. AllowNetworkingAccess
tag must be set to "all"
.
SECURE_CROSS_ORIGIN_OPENER_POLICY = 'unsafe-none'
<authorization>
<allow verbs="GET,POST" users="admin"/>
<deny verbs="GET,POST"users="*" />
</authorization>
<security-constraint>
<display-name>Admin Constraint</display-name>
<web-resource-collection>
<web-resource-name>Admin Area</web-resource-name>
<url-pattern>/pages/index.jsp</url-pattern>
<url-pattern>/admin/*.do</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<description>only admin</description>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<http-method>
tag in this configuration, it might be possible to exercise administrative functionality by substituting GET or POST requests with HEAD requests. For HEAD requests to exercise administrative functionality, condition 3 must hold - the application must carry out commands based on verbs other than POST. Some web/application servers will accept arbitrary non-standard HTTP verbs and respond as if they were given a GET request. If that is the case, an attacker would be able to view administrative pages by using an arbitrary verb in a request.
GET /admin/viewUsers.do HTTP/1.1
Host: www.example.com
FOO /admin/viewUsers.do HTTP/1.1
Host: www.example.com
FORM GenerateReceiptURL CHANGING baseUrl TYPE string.
DATA: r TYPE REF TO cl_abap_random,
var1 TYPE i,
var2 TYPE i,
var3 TYPE n.
GET TIME.
var1 = sy-uzeit.
r = cl_abap_random=>create( seed = var1 ).
r->int31( RECEIVING value = var2 ).
var3 = var2.
CONCATENATE baseUrl var3 ".html" INTO baseUrl.
ENDFORM.
CL_ABAP_RANDOM->INT31
function to generate "unique" identifiers for the receipt pages it generates. Since CL_ABAP_RANDOM
is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers, such as a cryptographic PRNG.
string GenerateReceiptURL(string baseUrl) {
Random Gen = new Random();
return (baseUrl + Gen.Next().toString() + ".html");
}
Random.Next()
function to generate "unique" identifiers for the receipt pages it generates. Since Random.Next()
is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers, such as a cryptographic PRNG.
char* CreateReceiptURL() {
int num;
time_t t1;
char *URL = (char*) malloc(MAX_URL);
if (URL) {
(void) time(&t1);
srand48((long) t1); /* use time to set seed */
sprintf(URL, "%s%d%s", "http://test.com/", lrand48(), ".html");
}
return URL;
}
lrand48()
function to generate "unique" identifiers for the receipt pages it generates. Since lrand48()
is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers.
<cfoutput>
Receipt: #baseUrl##Rand()#.cfm
</cfoutput>
Rand()
function to generate "unique" identifiers for the receipt pages it generates. Since Rand()
is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers, such as a cryptographic PRNG.
import "math/rand"
...
var mathRand = rand.New(rand.NewSource(1))
rsa.GenerateKey(mathRand, 2048)
rand.New()
function to generate randomness for an RSA key. Since rand.New()
is a statistical PRNG, it is easy for an attacker to guess the value it generates.
String GenerateReceiptURL(String baseUrl) {
Random ranGen = new Random();
ranGen.setSeed((new Date()).getTime());
return (baseUrl + ranGen.nextInt(400000000) + ".html");
}
Random.nextInt()
function to generate "unique" identifiers for the receipt pages it generates. Since Random.nextInt()
is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers, such as a cryptographic PRNG.
function genReceiptURL (baseURL){
var randNum = Math.random();
var receiptURL = baseURL + randNum + ".html";
return receiptURL;
}
Math.random()
function to generate "unique" identifiers for the receipt pages it generates. Since Math.random()
is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers, such as a cryptographic PRNG.
fun GenerateReceiptURL(baseUrl: String): String {
val ranGen = Random(Date().getTime())
return baseUrl + ranGen.nextInt(400000000).toString() + ".html"
}
Random.nextInt()
function to generate "unique" identifiers for the receipt pages it generates. Since Random.nextInt()
is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers, such as a cryptographic PRNG.
function genReceiptURL($baseURL) {
$randNum = rand();
$receiptURL = $baseURL . $randNum . ".html";
return $receiptURL;
}
rand()
function to generate "unique" identifiers for the receipt pages it generates. Since rand()
is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers, such as a cryptographic PRNG.
CREATE or REPLACE FUNCTION CREATE_RECEIPT_URL
RETURN VARCHAR2
AS
rnum VARCHAR2(48);
time TIMESTAMP;
url VARCHAR2(MAX_URL)
BEGIN
time := SYSTIMESTAMP;
DBMS_RANDOM.SEED(time);
rnum := DBMS_RANDOM.STRING('x', 48);
url := 'http://test.com/' || rnum || '.html';
RETURN url;
END
DBMS_RANDOM.SEED()
function to generate "unique" identifiers for the receipt pages it generates. Since DBMS_RANDOM.SEED()
is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers.
def genReceiptURL(self,baseURL):
randNum = random.random()
receiptURL = baseURL + randNum + ".html"
return receiptURL
rand()
function to generate "unique" identifiers for the receipt pages it generates. Since rand()
is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers, such as a cryptographic PRNG.
def generateReceiptURL(baseUrl) {
randNum = rand(400000000)
return ("#{baseUrl}#{randNum}.html");
}
Kernel.rand()
function to generate "unique" identifiers for the receipt pages it generates. Since Kernel.rand()
is a statistical PRNG, it is easy for an attacker to guess the strings it generates.
def GenerateReceiptURL(baseUrl : String) : String {
val ranGen = new scala.util.Random()
ranGen.setSeed((new Date()).getTime())
return (baseUrl + ranGen.nextInt(400000000) + ".html")
}
Random.nextInt()
function to generate "unique" identifiers for the receipt pages it generates. Since Random.nextInt()
is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers, such as a cryptographic PRNG.
sqlite3_randomness(10, &reset_token)
...
Function genReceiptURL(baseURL)
dim randNum
randNum = Rnd()
genReceiptURL = baseURL & randNum & ".html"
End Function
...
Rnd()
function to generate "unique" identifiers for the receipt pages it generates. Since Rnd()
is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers, such as a cryptographic PRNG.CL_ABAP_RANDOM
class or its variants) is seeded with a specific constant value, the values returned by GET_NEXT
, INT
and similar methods which return or assign values are predictable for an attacker that can collect a number of PRNG outputs.random_gen2
are predictable from the object random_gen1
.
DATA: random_gen1 TYPE REF TO cl_abap_random,
random_gen2 TYPE REF TO cl_abap_random,
var1 TYPE i,
var2 TYPE i.
random_gen1 = cl_abap_random=>create( seed = '1234' ).
DO 10 TIMES.
CALL METHOD random_gen1->int
RECEIVING
value = var1.
WRITE:/ var1.
ENDDO.
random_gen2 = cl_abap_random=>create( seed = '1234' ).
DO 10 TIMES.
CALL METHOD random_gen2->int
RECEIVING
value = var2.
WRITE:/ var2.
ENDDO.
random_gen1
and random_gen2
were identically seeded, so var1 = var2
rand()
) is seeded with a specific value (using a function like srand(unsigned int)
), the values returned by rand()
and similar methods which return or assign values are predictable for an attacker that can collect a number of PRNG outputs.
srand(2223333);
float randomNum = (rand() % 100);
syslog(LOG_INFO, "Random: %1.2f", randomNum);
randomNum = (rand() % 100);
syslog(LOG_INFO, "Random: %1.2f", randomNum);
srand(2223333);
float randomNum2 = (rand() % 100);
syslog(LOG_INFO, "Random: %1.2f", randomNum2);
randomNum2 = (rand() % 100);
syslog(LOG_INFO, "Random: %1.2f", randomNum2);
srand(1231234);
float randomNum3 = (rand() % 100);
syslog(LOG_INFO, "Random: %1.2f", randomNum3);
randomNum3 = (rand() % 100);
syslog(LOG_INFO, "Random: %1.2f", randomNum3);
randomNum1
and randomNum2
were identically seeded, so each call to rand()
after the call which seeds the pseudorandom number generator srand(2223333)
, will result in the same outputs in the same calling order. For example, the output might resemble the following:
Random: 32.00
Random: 73.00
Random: 32.00
Random: 73.00
Random: 15.00
Random: 75.00
math.Rand.New(Source)
), the values returned by math.Rand.Int()
and similar methods which return or assign values are predictable for an attacker that can collect a number of PRNG outputs.
randomGen := rand.New(rand.NewSource(12345))
randomInt1 := randomGen.nextInt()
randomGen.Seed(12345)
randomInt2 := randomGen.nextInt()
nextInt()
after the call that seeded the pseudorandom number generator (randomGen.Seed(12345)
), results in the same outputs and in the same order.Random
) is seeded with a specific value (using a function such as Random.setSeed()
), the values returned by Random.nextInt()
and similar methods which return or assign values are predictable for an attacker that can collect a number of PRNG outputs.Random
object randomGen2
are predictable from the Random
object randomGen1
.
Random randomGen1 = new Random();
randomGen1.setSeed(12345);
int randomInt1 = randomGen1.nextInt();
byte[] bytes1 = new byte[4];
randomGen1.nextBytes(bytes1);
Random randomGen2 = new Random();
randomGen2.setSeed(12345);
int randomInt2 = randomGen2.nextInt();
byte[] bytes2 = new byte[4];
randomGen2.nextBytes(bytes2);
randomGen1
and randomGen2
were identically seeded, so randomInt1 == randomInt2
, and corresponding values of arrays bytes1[]
and bytes2[]
are equal.Random
) is seeded with a specific value (using function such as Random(Int)
), the values returned by Random.nextInt()
and similar methods which return or assign values are predictable for an attacker that can collect a number of PRNG outputs.Random
object randomGen2
are predictable from the Random
object randomGen1
.
val randomGen1 = Random(12345)
val randomInt1 = randomGen1.nextInt()
val byteArray1 = ByteArray(4)
randomGen1.nextBytes(byteArray1)
val randomGen2 = Random(12345)
val randomInt2 = randomGen2.nextInt()
val byteArray2 = ByteArray(4)
randomGen2.nextBytes(byteArray2)
randomGen1
and randomGen2
were identically seeded, so randomInt1 == randomInt2
, and corresponding values of arrays byteArray1
and byteArray2
are equal.
...
import random
random.seed(123456)
print "Random: %d" % random.randint(1,100)
print "Random: %d" % random.randint(1,100)
print "Random: %d" % random.randint(1,100)
random.seed(123456)
print "Random: %d" % random.randint(1,100)
print "Random: %d" % random.randint(1,100)
print "Random: %d" % random.randint(1,100)
...
randint()
after the call that seeded the pseudorandom number generator (random.seed(123456)
), will result in the same outputs in the same output in the same order. For example, the output might resemble the following:
Random: 81
Random: 80
Random: 3
Random: 81
Random: 80
Random: 3
Random
) is seeded with a specific value (using a function like Random.setSeed()
), the values returned by Random.nextInt()
and similar methods which return or assign values are predictable for an attacker that can collect a number of PRNG outputs.Random
object randomGen2
are predictable from the Random
object randomGen1
.
val randomGen1 = new Random()
randomGen1.setSeed(12345)
val randomInt1 = randomGen1.nextInt()
val bytes1 = new byte[4]
randomGen1.nextBytes(bytes1)
val randomGen2 = new Random()
randomGen2.setSeed(12345)
val randomInt2 = randomGen2.nextInt()
val bytes2 = new byte[4]
randomGen2.nextBytes(bytes2)
randomGen1
and randomGen2
were identically seeded, so randomInt1 == randomInt2
, and corresponding values of arrays bytes1[]
and bytes2[]
are equal.