CodeSOD collection



  • When you need a Hammer, get a HammerFactory first. For a HammerFactory you obviously need a HammerFactoryFactory. Etc.

    deploy the application to Azure Kubernetes Services (AKS). Helm, a Kubernetes deployment tool, is available to reduce deployment complexity

    Before that, you need to get you application split up into Microservices which are containered individually in Docker containers...

    Wow. Cloud Native is a great idea.
    :yell-at-cloud: ☁ 🌧 🌨 🌩 ⛈ :yell-at-cloud:



  • @BernieTheBernie said in CodeSOD collection:

    Azure Kubernetes Services (AKS)

    That … just works. So far so good.

    @BernieTheBernie said in CodeSOD collection:

    Helm, a Kubernetes deployment tool, is available to reduce deployment complexity

    Everybody hates helm, with passion, but everybody uses it, because it kinda is the only tool that addresses the problem, though it does so in the worst way possible.

    And no, it does not actually reduce complexity of deployments. An extra layer always adds complexity, not removes it. What it does instead is allow you to define a set of parameters for a larger software components in one place and have them scatter to the appropriate places in the kubernetes manifests. But the way it does it is by generating YAML—with it's 2-dimensional syntax—using go (mustche-style) templates. :vomit: 🤮 :vomit:

    I even started thinking about rewriting my kubernetes manifests to terraform. At least it allows me to actually cross-reference values instead of relying on typing the same name in a dozen places (but don't get me started on the azure provider—it's buggy as an anthill).

    @BernieTheBernie said in CodeSOD collection:

    Before that, you need to get you application split up into Microservices which are containered individually in Docker containers...

    Not really. You can take the big thing and just install it in a container. And a container is just a Linux system (well, there are Windows containers too, but they are rarely used) installed using a good old package manager (dpkg, rpm, apk) and built by a shell script.

    The point of splitting up an application into Microservices is that you can then scale and/or optimize the parts that need to handle big volumes of traffic, but are relatively simple, independently of the parts that are complex, but not very busy. It follows that splitting up a typical internal corporate application to microservices is 0verkill.



  • @Bulb Well, I ought to have mentioned that I started reading
    "Architecting Cloud-Native .Net Apps for Azure"
    which is freely available from Microsoft. That's where the quoted line comes from, and other chapters were summed up in the following line.
    I read that because there seems to be a demand for people knowing that crap. In my previous work environment, I could not use that at all: software bound to physical devices like infrared cameras or CAN bus (likely located in nowhere province, internet via slowest mobile connection only) just cannot be elastically scaled with a cloud subscription...



  • @BernieTheBernie said in CodeSOD collection:

    @Bulb Well, I ought to have mentioned that I started reading
    "Architecting Cloud-Native .Net Apps for Azure"
    which is freely available from Microsoft. That's where the quoted line comes from, and other chapters were summed up in the following line.

    Ok … yeah, sounds like them. They are selling something after all.

    I read that because there seems to be a demand for people knowing that crap.

    Yeah, there is.

    I would, however, say that there isn't much of a difference from how server apps were written for years. You write a normal ADO.NET web application, install it in a container—Visual Studio can helpfully produce initial Dockerfile for that—and then you deploy it into the kubernetes cluster with a bit of ugly yaml or a bit of even more uglier templates producing yaml.

    The difficult thing in my experience is that the libraries for accessing the managed resources like message queues and data storage change a lot and suffer from :shipit: mentality so they break all the time and you spend a lot of time upgrading and downgrading, hunting for a version that works for your use-case. But that isn't anything to learn, just a thing that happens.

    Plus there are the “serverless” installations—which are no different from when you used to drop a .war into a JBoss managed by the ICT department. The main pain there is that the libraries have the same issue again. In fact “serverless” .NET apps on Azure (functionapp) are the worst. They could have reused the ADO.NET interfaces, because it's mostly the same thing anyway, but instead they created a separate framework and there is at least a third major release, where everything is changed, in a few years in the pipeline. With ADO.NET in a container you can run it in another cloud easily, but with the “serverless” you are tied to the specific cloud provider and still have to play catch up with the API changes all the time.

    In my previous work environment, I could not use that at all: software bound to physical devices like infrared cameras or CAN bus (likely located in nowhere province, internet via slowest mobile connection only) just cannot be elastically scaled with a cloud subscription...

    My project involves both software bound to a CAN bus somewhere (not in a fixed location), but also software in cloud. And I am involved in the Azure deployment, spending most of my time fighting fragile tooling.


  • Discourse touched me in a no-no place

    @BernieTheBernie said in CodeSOD collection:

    I read that because there seems to be a demand for people knowing that crap. In my previous work environment, I could not use that at all: software bound to physical devices like infrared cameras or CAN bus (likely located in nowhere province, internet via slowest mobile connection only) just cannot be elastically scaled with a cloud subscription...

    I've got that. One of the things I've been working on is a service that lets outside software get access to the public parts of that system. With that in place, we can allow services in the cloud to reach our special hardware (provided they talk the right protocols). It's good because it also means we don't have problems with IP address allocations and routing the outside world to our internal stuff. (It also stops users from interfering with each other's allocations.)

    The management backplane is not part of that offering, but that's because it's very fragile/buggy and we have to ensure that only one thread anywhere is accessing it at a time so that the [equivalent of DRAC cards] don't crash and require an in-person reboot of something that's otherwise mostly a lights-out service. Part of the complicated part of my service is implementing that super-single-threaded constraint. I've managed to not cause too many crashes during testing, but it certainly was "amusing" when half the test cluster was sold out from under my feet and just vanished one day...



  • Another gem from "Architecting Cloud-Native .Net Apps for Azure":

    Within Kubernetes, there’s a similar service for maintaining small pieces of secret information. Kubernetes Secrets can be set via the typical kubectl executable.
    Creating a secret is as simple as finding the base64 version of the values to be stored:

    echo -n 'admin' | base64 
    YWRtaW4= 
    echo -n '1f2d1e2e67df' | base64 
    MWYyZDFlMmU2N2Rm 
    

    Then adding it to a secrets file...

    base64 encryption - that even exceeds Kevin levels of sehcuhreety.


  • 🚽 Regular

    @BernieTheBernie That's not encryption. It's encoding.



  • @BernieTheBernie It's not encryption, and is not really meant to be one. You need the secrets in plain text in the application, so the API has to allow reading them. You can restrict the permissions who can read them, but the admin will always be able to.

    Consider this the equivalent of *-ing out the password when typing it so nobody can read it over your shoulder. That's all it really is (with a benefit that there does not have to be a special case for binary values that'd have to be base64-encoded for yaml or json serialization anyway).

    Note that Azure Keyvaults don't bother with even that. In the portal, the secrets are *-ed out unless you click the or , but if you query them with the cli, you just get the plain-text values.



  • Note that for purpose of keeping the secrets file versioned somewhere there are sealed secrets. But what that does is allow you to have the secrets lying around somewhere relatively accessible, like in the code repository, but not readable by anything but the cluster.

    But you still have to mind what it does and does not protect against. They are encrypted for a key that the cluster holds, so the cluster can decrypt the secret, and then any administrator can read it out of there anyway.



  • @Zecc said in CodeSOD collection:

    @BernieTheBernie That's not encryption. It's encoding.

    :thats_the_joke: :thats_the_joke: :thats_the_joke: :thats_the_joke: :thats_the_joke: :thats_the_joke: :thats_the_joke:

    base 64 encoding is so much helpful here, why don't we use Sütterlin encoding instead?

    And by the way, a "normal" .config file of a .Net application has a connection string section for holding encrypted values...


  • Considered Harmful

    @BernieTheBernie Eh, I don't see the problem. Base64 is charset-agnostic, which could be important for text files. Well, until someone fucks up the encoded string thinking it's the actual password.



  • @Applied-Mediocrity You mean: the yaml file does not know the concept of an encoding?
    Well, that could be true, and :trwtf: at the same time.



  • @BernieTheBernie said in CodeSOD collection:

    @Applied-Mediocrity You mean: the yaml file does not know the concept of an encoding?
    Well, that could be true, and :trwtf: at the same time.

    YAML assumes UTF-8, but can be either that, UTF-16 or UTF-32.

    There is explicit support for base64 encoded binary blobs in the format.



  • @BernieTheBernie said in CodeSOD collection:

    @Zecc said in CodeSOD collection:

    @BernieTheBernie That's not encryption. It's encoding.

    :thats_the_joke: :thats_the_joke: :thats_the_joke: :thats_the_joke: :thats_the_joke: :thats_the_joke: :thats_the_joke:

    base 64 encoding is so much helpful here, why don't we use Sütterlin encoding instead?

    And by the way, a "normal" .config file of a .Net application has a connection string section for holding encrypted values...

    And you should store the encrypted password in the Kubernetes secret if the app can decrypt it. But that's application specific. Kubernetes does not encrypt it, because it would be pointless at that level. If it was encrypted, that would be a :wtf:.



  • @Arantor said in CodeSOD collection:

    @BernieTheBernie said in CodeSOD collection:

    @Applied-Mediocrity You mean: the yaml file does not know the concept of an encoding?
    Well, that could be true, and :trwtf: at the same time.

    YAML assumes UTF-8, but can be either that, UTF-16 or UTF-32.

    There is explicit support for base64 encoded binary blobs in the format.

    I would like to add that these secrets are quite often encryption keys == binary values. The base64 is specifically used to provide standardized handling of such values and somewhat prevent the "standard practice" (yes, :wtf: indeed) of using plaintext password directly as, say, AES key.


  • Considered Harmful

    @BernieTheBernie said in CodeSOD collection:

    And by the way, a "normal" .config file of a .Net application has a connection string section for holding encrypted values...

    Yeah, MS is generally piss-poor at security.



  • @Kamil-Podlesak said in CodeSOD collection:

    and somewhat prevent the "standard practice" (yes, :wtf: indeed) of using plaintext password directly as, say, AES key.

    It does not do that because the base64 is only used in the yaml and json serialization of the object. When you bind the secret to an environment variable or to a file and read it from there, you'll get the raw form.


  • Considered Harmful

    @Bulb said in CodeSOD collection:

    @Kamil-Podlesak said in CodeSOD collection:

    and somewhat prevent the "standard practice" (yes, :wtf: indeed) of using plaintext password directly as, say, AES key.

    It does not do that because the base64 is only used in the yaml and json serialization of the object. When you bind the secret to an environment variable or to a file and read it from there, you'll get the raw form.

    I think the point was that you can store the binary result of a key derivation function and have something close to the key length in entropy instead of just padding a bunch of ASCII characters with zeroes and do that 1337omatic "256bit AES" with effectively 50 bit or so of entropy.
    Of course you could have the KDF in your application, too …


  • Discourse touched me in a no-no place

    @BernieTheBernie said in CodeSOD collection:

    base 64 encoding is so much helpful here, why don't we use Sütterlin encoding instead?

    It's just an encoding scheme, a way of writing down binary data in text that doesn't get mangled quite so easily, and isn't intended to offer any security at all. Could use hex digits instead, or uuencode (though that's messy with longer data).

    At some point, something has to actually see the real secret info because it needs to actually know it in order to act on it. We try to limit the amount of code that sees the real secrets, but it cannot usefully be zero. The magic tokens in configs can be the main secrets, or they can be the passwords to unlock the main secrets held elsewhere (a good idea with larger key materials). To avoid oopsies, many management UIs default to concealing the magic tokens that they know about, but ultimately these are systems intended to be used by those who are authorized to know the secrets; you can't avoid that without making a system that is far too fragile to work in reality.



  • @dkf said in CodeSOD collection:

    We try to limit the amount of code that sees the real secrets, but it cannot usefully be zero.

    It's very useful if you're a :trolley-garage: poster pretending you know a secret that you don't really know.



  • @LaoC said in CodeSOD collection:

    I think the point was that you can store the binary result of a key derivation function and have something close to the key length in entropy instead of just padding a bunch of ASCII characters with zeroes and do that 1337omatic "256bit AES" with effectively 50 bit or so of entropy.
    Of course you could have the KDF in your application, too …

    If you feed 50 bits of entropy through a KDF, you still only have 50 bits of entropy, even though it is now stretched over 256 bits.

    What you really want to do is just generate a long enough random string (head -c 16 /dev/random | base64) and use that—it's not like anybody is ever expected to type this kind of secret, all that has to be done with it is copy-pasting it between the configs of the services that need to share a secret.



  • @Bulb said in CodeSOD collection:

    @Kamil-Podlesak said in CodeSOD collection:

    and somewhat prevent the "standard practice" (yes, :wtf: indeed) of using plaintext password directly as, say, AES key.

    It does not do that because the base64 is only used in the yaml and json serialization of the object. When you bind the secret to an environment variable or to a file and read it from there, you'll get the raw form.

    Yes, that's exactly how it does it: it decodes the base64 to raw binary octets. If it accepted raw binary octets, people would feed it base64 (or even hexadecimal) strings of the same length as the defined octet length. Don't tell me you haven't seen that.


  • Notification Spam Recipient

    Decompiled, so it might not actually be the written code, but holy fuck...

    629a6fb7-581f-47df-b0b1-a3b0ac67f163-image.png

    I don't know why they reimplemented a single standard UI interaction, but it's fucking noticeable when the rest don't work because apparently everything else about this textbox is disabled...



  • @Tsaukpaetra said in CodeSOD collection:

    Decompiled, so it might not actually be the written code

    Looking at that, I'd guess probably not. That looks like something that's been optimized by the compiler.

    I don't know why they reimplemented a single standard UI interaction

    This is :trwtf:.


  • Notification Spam Recipient

    @HardwareGeek said in CodeSOD collection:

    probably not.

    Though, honestly, how far off could it really be?



  • @Tsaukpaetra said in CodeSOD collection:

    @HardwareGeek said in CodeSOD collection:

    probably not.

    Though, honestly, how far off could it really be?

    I can easily see a compiler turning something like

    private void txt...
    {
      if (e.KeyCode == Keys.A && e.Modifiers == Keys.Control)
        this.txtTechGistoryEditor.SelectAll();
    }
    

    into something like this pseudo-assembly (my apologies for the many errors I'm sure are in here; it's been decades since I hand-wrote any assembly):

    txtTecHistoryEditor_KeyDown:
    mov al,[rbp+something that points to KeyCode in the e structure];
    sub al,whatever the keycode of 'A' is;
    jnz label;
    mov al,[rbp+something that points to Modifiers in the e structure];
    sub al, whatever the value of Keys.Control is;
    jnz label;
    push this;
    call this.txtTecHistoryEditor.SelectAll();
    label:
    ret;
    

    The code returns if the keycode != the keycode for A or the modifier isn't Ctrl, the key being the jnz jumps to the ret instruction if the values are not equal. And the decompiler generates the inverted logic that matches the actual machine code. I don't guarantee this is what's going on, but it sure looks reasonable to me.


  • Notification Spam Recipient

    @HardwareGeek said in CodeSOD collection:

    inverted logic

    :same-picture.jpg:

    😉😉


  • Considered Harmful

    Lippert's Razor - the one who wrote the code is wrong, and so are you

    As you can see in SharpLab - edited, see below, .НЕТ keeps to a fairly literal translation of the code as written, as far as putting two return & cleanups in the stupid variant.



  • @Applied-Mediocrity Does it?
    2d6e1924-5b06-47b8-a8c2-23ab3e0dc475-image.png

    I clicked on your link and (in Release) it's showing me the sane form for both variants.


  • Considered Harmful

    @Bulb Mundane detail :sadface:


  • Notification Spam Recipient

    @Tsaukpaetra said in CodeSOD collection:

    Though, honestly

    Status: So, this application is directly connecting to an SQL server. Naturally, they embed the connection string somehow. They take great care to use the DataProtectionConfigurationProvider to protect said connection string.

    ....

    ...

    After first launch. :facepalm:

    Oh! And since apparently configuration is hard, the connection string is stored twice (because the app is semi-DLL'd and :raisins: it needs it twice I guess).

    Guess if the connection string is protected in both places?

    c8c23c42-37a7-46ea-a340-4c1676a41ea2-image.png

    NOPE!

    Un. Fucking. Believable.


  • Notification Spam Recipient

    @Tsaukpaetra said in CodeSOD collection:

    why they reimplemented a single standard UI interaction,

    Fucker of $deity, they're insane!

    9c36e141-fa7c-4881-acf0-47db3ecad0ca-image.png

    Someone tell me that the decompiler is just having fun and the code doesn't actually do this!

    I have half a mind to slide into the dev's machine (because this was very clearly not build by any CI suite) and see....



  • @Tsaukpaetra said in CodeSOD collection:

    Naturally, they embed the connection string somehow.

    Why? Usually, connection string would be injected through the environment. Because it needs to be different on each server anyway, and that's what environment is best suited for.

    I am also gradually replacing the connection strings that contain a passwords with ones that just say Authentication=Active Directory Default and then rely on whichever of the five or so methods of getting an OAuth2 token it tries to handle the actual secrets.

    Oh, or you mean it's an application distributed to users that connects to the database with the same connection string for each and every of them? That's a :wtf:, but if they all have the same permissions, I guess it's not a problem if they find the password.

    Oh, you mean they don't have the same permissions and the application running on their computers checks it? :doh: That's :trwtf:. It's :doing_it_wrong: and can't really be fixed with encryption, because the users can still debug the application or use similar tools.

    It could be fixed by using above mentioned Authentication=Active Directory Default and using the user's credential to access the database, with suitable authorization rules and possibly authorization hooks set up on the server.


  • Notification Spam Recipient

    @Bulb said in CodeSOD collection:

    Why? Usually, connection string would be injected through the environment. Because it needs to be different on each server anyway, and that's what environment is best suited for.

    Because it's not running on the server. This is a client application. :headdesk: :headdesk: :headdesk: :headdesk:

    @Bulb said in CodeSOD collection:

    if they all have the same permissions,

    They do not, but the client is what is deciding what permissions to apply. :headdesk: 😤 ❗ 💥

    @Bulb said in CodeSOD collection:

    because the users can still debug the application or use similar tools.

    Which is how I found out it does this in the first place before discovering the second copy of the connection string right there in plain text. Really should have just read the human-readable stuff first. :this_is_fine:

    @Bulb said in CodeSOD collection:

    possibly authorization hooks set up on the server.

    About that...

    92254e44-e895-47db-a02f-ba16d7a7e2a8-image.png



  • @Tsaukpaetra A client application should be logging into the database server with the user's credentials and they should be checked there. Anything else is a wide open security barn door.



  • @Bulb said in CodeSOD collection:

    @Tsaukpaetra A client application should be logging into the database server with the user's credentials and they should be checked there. Anything else is a wide open security barn door.

    Or...maybe client apps shouldn't be logging in directly to a database server at all. Keep those credentials on an API server and use some other protocol/method (ie REST, etc) to fetch the needed data in a way that doesn't expose the database to grubby users' hands directly.


  • Notification Spam Recipient

    @Bulb said in CodeSOD collection:

    Anything else is a wide open security barn door.

    I said above this is a theater. I was wrong. This here is satire!



  • @Benjamin-Hall said in CodeSOD collection:

    @Bulb said in CodeSOD collection:

    @Tsaukpaetra A client application should be logging into the database server with the user's credentials and they should be checked there. Anything else is a wide open security barn door.

    Or...maybe client apps shouldn't be logging in directly to a database server at all. Keep those credentials on an API server and use some other protocol/method (ie REST, etc) to fetch the needed data in a way that doesn't expose the database to grubby users' hands directly.

    That's more work and less secure, not more. Databases have fine-grained permission systems and having the checking integrated into the data access minimizes the risk the check will be missed in some corner case.

    For corporate applications with complex access rules (often per-row), not too many users, and the database within reach (not trying to cross the wild internet), implementing the API in the database and just connecting to it directly with the user's credentials is a good approach.

    But of course whether you go for API of views and stored procedures or a code layer over the database providing API over http, checking the permissions server-side, well out of reach of the user's grubby hands is the imperative.



  • @Bulb I'm more concerned with not having a single source of truth as to what's allowed in the domain model, what with allowing client apps to reach in and change the database directly.

    If it's all just crud with no business rules, that's one thing. But if a user can directly log into the database with their credentials, then your data model has to be fully implemented in SQL, and that's a nightmare. Especially if you also need it application side.



  • @Benjamin-Hall said in CodeSOD collection:

    @Bulb I'm more concerned with not having a single source of truth as to what's allowed in the domain model,

    Which is exactly why I want to enforce all the constraints in the database engine itself.

    what with allowing client apps to reach in and change the database directly.

    API implemented in SQL ≠ change the database directly. The application is only allowed to access views and stored procedures it is supposed to access.

    If it's all just crud with no business rules, that's one thing. But if a user can directly log into the database with their credentials, then your data model has to be fully implemented in SQL, and that's a nightmare.

    On the contrary. SQL is great. It is declarative. It is optimized by the server without much of your involvement. The only downside is that it is a bit verbose. But verbose compared to a relational algebra notation – any procedural code is inevitably much longer and hard to read as it now has to concern itself with iterations and stuff. No, you can get very far with SQL if you know it well.

    And the better databases allow stored procedures in Java or C# or Python or something when the procedural extension of SQL gets too unwieldy, because those are not that pretty indeed.

    Especially if you also need it application side.

    That's what stored procedures are for.


  • Notification Spam Recipient

    @Bulb said in CodeSOD collection:

    Anything else is a wide open security barn door.

    I've had enough of this code. Every function I get deeper into the "This is insane and stupid!" hole and I don't like how angry I'm getting....


  • Considered Harmful

    @Bulb said in CodeSOD collection:

    Oh, or you mean it's an application distributed to users that connects to the database with the same connection string for each and every of them? That's a :wtf:, but if they all have the same permissions, I guess it's not a problem if they find the password.

    * Siemens has entered the chat


  • Considered Harmful

    @Benjamin-Hall said in CodeSOD collection:

    Or...maybe client apps shouldn't be logging in directly to a database server at all. Keep those credentials on an API server and use some other protocol/method (ie REST, etc) to fetch the needed data in a way that doesn't expose the database to grubby users' hands directly.

    Please don't mention the word "API server", it gives me bad dreams and piles.



  • @LaoC said in CodeSOD collection:

    Siemens

    It's a big company that, as any big company, makes its share of :wtf:, so which particular :wtf: are you hinting at?


  • Considered Harmful

    @Bulb said in CodeSOD collection:

    @LaoC said in CodeSOD collection:

    Siemens

    It's a big company that, as any big company, makes its share of :wtf:, so which particular :wtf: are you hinting at?

    The POS that got stuxnetted, partly because their instructions to the clients were "those are the default passwords, and don't even think about changing them because shit will break"



  • @Tsaukpaetra said in CodeSOD collection:

    @Tsaukpaetra said in CodeSOD collection:

    why they reimplemented a single standard UI interaction,

    Fucker of $deity, they're insane!

    9c36e141-fa7c-4881-acf0-47db3ecad0ca-image.png

    Someone tell me that the decompiler is just having fun and the code doesn't actually do this!

    I have half a mind to slide into the dev's machine (because this was very clearly not build by any CI suite) and see....

    Security by Obscurity.
    That's real world programming.
    As demonstrated by Kevin and Fritz...


  • Notification Spam Recipient

    @BernieTheBernie said in CodeSOD collection:

    Security by Obscurity.

    status: made a sketch using the decrypt snippet and their own values.

    I can now literally retrieve any password currently active, and from the server's perspective I'm not doing anything weird, because all of the password Cipher texts are included in the basic ticket listing.

    I give up. Sending a massive email to the IT head.

    And to think, none of this would have been revealed if there wasn't a bug when you selected "this is a desktop" in the password submission website.... Well, it would still be like that, but I never would have investigated the WetYeti.


  • Notification Spam Recipient

    Status: Mother. Fuckers.

    d7b97182-7330-4719-8875-e0747514edc1-image.png


  • Notification Spam Recipient

    @Tsaukpaetra said in CodeSOD collection:

    there wasn't a bug when you selected "this is a desktop" in the password submission website

    One of these things is not like the others...

    574269af-b3e0-413b-ab42-faac95ae17d0-image.png


  • Notification Spam Recipient

    @Tsaukpaetra said in CodeSOD collection:

    And to think, none of this would have been revealed if there wasn't a bug when you selected "this is a desktop" in the password submission website.... Well, it would still be like that, but I never would have investigated the WetYeti.

    This just in!

    70328a46-3a42-4550-9583-7249f2eb29a6-image.png

    I am now unbelievably curious what the previous algo was if AES is considered the "new" one.

    My bet is an XOR...


Log in to reply