Day 1
Jörn Schneeweisz
© 2018
From the Training description:
The more you are able to see, the more bugs may appear under the hood.
Reading (and understanding) source code is a time-consuming task. The effort is rewarded in multiple ways.
But I don’t know how to code in $LANGUAGE!
Me neither ;-).
Not much is needed to read code, less source.php
will do the job. But there are quite some things which help a lot to understand much quicker what’s going on.
int
main(int argc, char *argv[])
{
/* Important!! *
if (argc > 1) * Please note: *
for (;;) * This code is *
puts(argv[1]); * NOT optimized *
else * in any way. */
for (;;)
puts("y");
}
A very simple, yet quite effective measure to understand code faster.
Being able to search within a codebase is essential for an audit.
Besides grep
there are more specialized tools:
Just to name a few.
Even tough simple text base search might suffice in a lot of cases some IDE-like features are really nice to have:
There are a lot of static code analyzers out there. They might help a lot to get to some bugs faster. They won’t be covered here for obvious reasons.
Common Pitfalls:
Your job is to think about things the developer didn’t have time to think about.
Being able to read the code comments is actually a huge benefit. Even if you’re able to perfectly decompile e.g. a .jar
file you won’t get the comments from the original source code.
Have a look here:
src/first/StringStuff.java
while (true) {
s = readLine();
if (s != null) {
s = s.trim();
}
if (s == null || s.length() < 1) {
continue;
}
if (s.contains("a")) {
return true;
} else {
return false;
}
}
What’s wrong with this code?
Let’s dissect
Note the new StringBuffer()
is just fine.
An empty file will result in an endless loop:
Quite a lot of issue are based on some kind of injection. So for instance:
Injections can be seen as a form of in-band signaling. An attacker is able to alter some semantics within the underlying operation. This is possible, as some attacker controlled input is injected in a way which allows those semantical changes.
A very basic example:
Just have a look here
The general injection pattern:
Some user controlled variable is ending up (being injected) in an operation which subsequently will do something beyond its intended purpose.
Most prominent and easy to spot root cause is string concatenation.
<?php
$id = $_GET['p_id'];
$query = "SELECT name FROM products WHERE id=" . $id . ";" ;
$result = pg_query($conn, $query);
?>
Guess how it looks :)
def grep(query, options={})
ref = options[:ref] ? options[:ref] : "HEAD"
args = [{}, '-I', '-i', '-c', query, ref, '--']
args << options[:path] if options[:path]
result = @git.grep(*args).split("\n")
result.map do |line|
branch_and_name, _, count = line.rpartition(":")
branch, _, name = branch_and_name.partition(':')
{:name => name, :count => count}
end
end
-O [<pager>], –open-files-in-pager [<pager>] Open the matching files in the pager (not the output of grep). If the pager happens to be “less” or “vi”, and the user specified only one pattern, the first file is positioned at the first match automatically.
PHP’s mail()
When PHP is configured to invoke a local MTA $additional_parameters
will be sanitized by escapeshellcmd()
.
➡️ Arguments to the MTA can be still injected.
Let’s think about the Injections from a high-level perspective.
$PATH_SEPARATOR
(‘/’ on Unix, ‘\’ on Windows)Turns out, this got quite some hype
.zip
:
Even simple boolean logic is hard, trust me 😂!
def check
fullpath = request.path_info
hmaced = "#{params[:email]}/#{params[:expire]}/"
email = Base64.urlsafe_decode64 params[:email]
expire = params[:expire].to_i
digest = OpenSSL::Digest.new('sha512')
hmac = OpenSSL::HMAC.hexdigest(digest, File.read("secret"), hmaced)
t = Time.now()
time_left = Time.at(expire) > t
if not hmac == params[:hmac] and not time_left
return false
end
return [email,expire]
end
There’s stuff to be found in code repositories which isn’t code, but still that stuff might introduce security issues.
Every language has some specific pitfalls/ways to shoot yourself in the foot.
Example taken from here
Further reading: Greg’s Presentation
uniqid()
:Gets a prefixed unique identifier based on the current time in microseconds.
+
operator is for Numbers:
php > echo("admin" + "1337wtf");
1337
The usual RegEx Anchors ^
and $
are multiline by default.
Which means:
/^[a-zA-Z]$/
matches perfectly on the following input:
hallo
!@#$WTF**
send(string [, args…]) → obj
method_missing(symbol [, *args] ) → result
More on that later during this training.
Reflect.java
a very basic example:
“Remote Timing Attacks are Practical” - are they?
Basic pattern/assumption:
==
, .equals()
,…) is not time constant