1

Suppose you are given a python API:

def onArgumentReceived(x):
    doWhatever(x) # expects a unicode string

I am not a security expert by any stretch of the imagination, however on the face of this, without explicit checking, this just instinctively feels like an obvious place to find a vulnerability laid bare.

Whereas:

void onArgumentReceived( const QString &x )
{
    doWhatever(x); 
}

seems inherently safe because the static typing will prevent strange types being fed into the function.

  • Am I right to assume the latter probably is more secure?
  • Is the former a good place to discover vectors of attack?

Thanks.

6
  • 1
    If your threat model includes being able to run arbitrary code on the target platform, why do you care about the details of the API? If your threat model does not include being able to run arbitrary code on the target platform, how are you going to pass arbitrary types to the function? Jan 23, 2023 at 9:32
  • @PhilipKendall 1: The API would hint to you what types it expects, and what it plans to do with that type. That could be discovery for maybe a buffer overflow? 2: You would pass arbitrary types if the api had interchangeable types?
    – Anon
    Jan 23, 2023 at 9:58
  • @PhilipKendall I think it's a little dangerous to start from a point of assuming that 'something could only happen if X' when considering such questions. We have no context to understand how the wrong type might be applied. Running arbitrary code isn't the only possibility.
    – JimmyJames
    Jan 23, 2023 at 18:17
  • 1
    @JimmyJames really the point I'm making is that you shouldn't ask any questions about security without having a threat model. Jan 23, 2023 at 18:27
  • 1
    Actually the C code could be more insecure than the python code since you could cast a pointer of a different type and possibly trigger a segfault, possibly even a buffer overflow exploit. Of course, that still requires getting past the initial security boundary at which point it's basically game over anyways.
    – mousetail
    Jan 26, 2023 at 9:40

3 Answers 3

4

If you're calling a Python API, you're already inside the security boundary. This cannot be a meaningful security risk. Only things from outside the program entirely count as security risks. Such as data from I/O.

What is more dangerous is implicit conversion. Automatically converting strings to numbers or boolean values. For example, this discussion of DOS and security issues arising from string to int conversions. Automatically converting "0" or "false" or "null" to 0 or false or null can cause problems.

See also NULL license plate

See also WAT

(more generally, to look for attack vectors, look over the list of CVEs and see what techniques come up again and again. Can you find one which relies on type confusion?)

2
  • Implicit conversions are a security risk - if you have dynamic typing (C++ doesn't). Guessing (input-format) is a sure way to guess wrong - at least some of the time. Jan 23, 2023 at 12:27
  • Although it can't be a security risk in the sense that the bad guy can't pass the wrong type on purpose because he can't pass anything because he can't access the code, it's still possible that you (the programmer) pass the wrong type by mistake and this can cause security bugs.
    – user253751
    Jan 23, 2023 at 15:49
3

Am I right to assume the latter probably is more secure?

This is the wrong question. First of all, there's no linear scale of security. There are approaches that are more robust to certain classes of errors. But an approach can be less vulnerable to one kind of attack and more vulnerable to another. That's why it's important to have some idea of your threat model.

Given that we don't know anything about the context of how the code would used it's impossible to say.

Consider a scenario, such as in a drag-and-drop interface where a type B ends up being passed into a function designed to work with type A. In Python that might 'work' and do something unexpected (perhaps completely benign) or it might fail because the type supplied doesn't support the necessary methods. In the alternate strong-typing path, let's assume a cast fails. All of these could represent security vulnerabilities and there's no way to say which is worse, in general.

The only thing I would say is that the scenario where passing the wrong type 'works' might present more interesting types of vulnerabilities than an exception/fault. The Log4Script vulnerability comes to mind. Generally speaking, it's better to crash than do something unknown and strong-typing can facilitate crashes. Strong-typing can also help protect against other programming errors. But it is not a panacea and thinking that it's better in general is wrong.

Is the former a good place to discover vectors of attack?

Perhaps but I would think it's better to take it up one level and look for ways you might end up with the wrong type of thing being passed into a method and how you can prevent that.

1

Am I right to assume the latter probably is more secure?

No, it is not "more or less secure", whatever that means.

If doWhatever interprets x as an sql string and runs it against a database without any previous validation, this would be a security risk, regardless if it is done in Python or C++, and the security risk would not be smaller in C++.

To be fair, as JimmyJames pointed out, passing a non-string into a function which expects a string in Python can have a certain risk of causing some unexpected behaviour, in case the function starts to iterate over the content of the string (or what it expects to be a string).

So in the end, it boils down to two things:

  • what happens inside the function in stake?

  • in what context is the function called, and is x some input created by an unreliable source?

Both questions are mostly language agnostic, and are not really restricted just by typesafety.

5
  • I'm not sure I follow the second point, or perhaps there is a third option. If the processing of the (expected) string involved looping over e.g.: for c in x: you could pass in any sequence type and have unexpected results. It's really hard to say whether that could happen without more context around the application and its usage.
    – JimmyJames
    Jan 23, 2023 at 18:11
  • @JimmyJames: ok, I admit, in Python there are some things possible with untyped parameters which won't happen in C++ with typed strings. Still the for loop alone does not introduce a security risk as long as noone starts to make a semantic interpretation of those elements "c", except that those are strings themselves.
    – Doc Brown
    Jan 23, 2023 at 20:59
  • I know this is stretching the limits of credulity a bit but please humor me for a moment: suppose the __iter__ method on some opens a connection to a DB and runs a query, returning tuples of username/passwords which get logged to an aggregator. Again, I'm just making up hypotheticals here but it's the weird stuff that no one would think to do normally that can T-bone you as you are pulling into the intersection, so to speak.
    – JimmyJames
    Jan 23, 2023 at 21:08
  • Also I should note that this aspect of Python is one of it's strengths, IMO. But I think we need to keep in mind that being able to do things you never thought of is great, until it is terrible.
    – JimmyJames
    Jan 23, 2023 at 21:10
  • @JimmyJames: ok, I rewrote my answer.
    – Doc Brown
    Jan 24, 2023 at 9:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.