📜 ⬆️ ⬇️

Curious perversions from the IT world - 4

image

The Daily WTF website has been collecting funny, wild and / or sad stories from the IT world for 15 years. I translated several stories that seemed interesting to me. All company names have been changed. Previous issues can be found under the label " curious perversions ."

The first story. End of the world month


[Original]

If you ask a development engineer whether it is safe to walk across a bridge, he will be happy to tell you how reliable bridges are, how mathematics works in them, how far we have come in building safety issues. After talking with him, you will get the impression that not a single bridge on Earth will ever fall apart. But if you ask a software development engineer about banks, then you will most likely be horrified, and with a 50/50 probability, convince yourself to invest all the money in Bitcoin. Banks are notorious for making bad software decisions when creating software — not because these solutions are disgusting, but because most people assume banks are more careful and attentive to security.
')
Kato works at Inibank, where a commercial product called T24 is used as the core of the banking system. The T24 system is used by hundreds of banks around the world. It can be customized for a wide range of banking solutions. As is the case with most custom packages. there are programmers specializing in writing code for it, and consultants who assist banks in making major updates.

Inibank staff was loaded with work, so the bank invited a consultant to participate in a special project. At the end of the working day, the bank conducted a process of completion of work, which is necessary for all the money to go where it was sent, recalculate all the necessary output data and run all the required reports. In banks, this process also changes the system date to the next working day. That is why when you do online banking on Sunday, no operation begins to be processed until Monday morning. The consultant was to create a new report that would be performed during the completion process and included additional processing if the date was at the end of the month.

Kato showed the new consultant how the end of the day reports are set up in the bank. “You see, we have global variables for the previous working day, for today, and for the next working day. They are in YYMMDD format so that it’s easier to work with them. ”

“Yeah, yeah, got it. Got it. What format are they in? ”

"... Uh-uh ... I can only assume that it is a year, a month and a day."

“Yeah, yeah, okay. Fine. Then I get to work. ”

After this conversation, Kato got a bad feeling. but he tried to get rid of him. The consultant said that everything is set up and ready. He knows exactly what he is doing, right? Kato threw it out of his head and stopped worrying until it was time for code review and he didn’t find such a gem:

 TH.DATE = R.DATES(EB.DAT.NEXT.WORKING.DAY)[1,6]:"01" CALL CDT('ES00',TH.DATE,"-1C") WTODAY = OCONV(DATE(),"DY") : FMT(OCONV(DATE(),"DM"),'R%2') : FMT(OCONV(DATE(),"DD"),'R%2') IF TH.DATE EQ WTODAY THEN 

We will explain briefly what is happening here:

  1. We take the next working day and change the day to 01 to get the first day of the month.
  2. We change this date by subtracting 1 calendar day in Spain.
  3. We take the date from the server and translate it into the YYYYMMDD format by calling the Date command three times.
  4. If the date calculated in step 2 is equal to the date calculated in step 3, start the process.

Well, in general it ... works. Mostly. Unless for some reason the end of the day does not happen after midnight of the penultimate day of the month - and this is not so rare. In this case, the code will mistakenly think that this is the last day of the month, and will start the creation of the report. What goes well with another problem: if the same thing happens on the last day of the month, then the report creation will not be mistakenly launched. And the best bug: if the last day of the month was Sunday, then the server calendar will never be installed on it, because it skips non-working days.

Speaking of non-working days: since Inibank is in the USA, there is no reason to use the calendar of Spain. Yes, the months and weeks will be the same, but in the Spanish software calendar you need to specify a bank holiday in the USA, otherwise the program will continue to work. Finally, as if all this was not enough, a triple call to Date means that disagreements may arise when starting exactly at midnight: the month is requested before midnight and the day after.

Kato added a comment suggesting how to change the code:

 IF R.DATES(EB.DAT.TODAY)[5,2] # R.DATES(EB.DAT.LAST.WORKING.DAY)[5,2] THEN 

Five minutes later, the consultant went to his desk. "What does this edit mean?"

Kato was in no mood to argue at that moment. “Your code is broken, friend. All this is not necessary. "

“I see, I see. In fact, this is just a standard operating procedure for our industry. Anyway".

Kato doubted this, but he just shrugged. “Then the industry is wrong. I explained everything in the comments. ”

“Yeah. Yes, I read it. But I will read it again. ” And he disappeared just as suddenly as he appeared.

The edits were made, Kato approved the code and the consultant disappeared into a fog.

Sometimes, lying in bed at night, Kato wondered: did the consultant really understand what he had done wrong, or did he simply agree for the show, received his check and continued to write a terrible code somewhere for a price twice as high as Kato? In those banks where there are no employees capable of checking the code.

But do not invest all the money in Bitcoin. It's still worse there.

The second story. How is it done


[Original]

People love eating hot dogs until they know how they are prepared. Most do not ask because they do not want to know and continue to eat hot dogs. When developing software, we sometimes have to ask. Not only to solve problems, but also because some programmers are afraid that the software in their cars, rushing along the highway at a speed of 100 km / h, is assembled from electrical tape and sticks. Our entire industry is not doing its job well .

Brett worked as a systems analyst at the MedStitute Medical Research Center. MedStitute used proprietary software called MedTech to store and analyze data. Doctors and researchers liked the results of MedTech, but colleague Brett Tyree knew how they were created.

The software did not have access to the backend, and the entire development process took place in a “programmable mouse” GUI. This interface looked as if it had been written by a person who studied the programming by copying and pasting the websites of the 1990s, who had looked at the ten minutes of the Jurassic Park and had been looking for answers to StackOverflow, until something could be compiled. The “programming language” also demonstrated a similar level of forethought of the design philosophy. Every if had to have else . Some modules used boolean values, while others returned empty lines to indicate false values. From the documentation it was not clear in what situation one or the other happened. In fact, each if turned into three statements.

Brett needed to start a new study. It was based on a simple set of statistics and grouped patients using a randomized variable. Brett looked for a variable in the list that could be randomized, but could not find it. He assumed that he had made a mistake and went back on several screens to check her name by copying it for searching. Brett returned to the list of randomized variables. She was not there. He took a closer look at the list and noticed that the list of randomized variables contained data from multiple-choice fields. The field he needed to randomize was based on a calculated field.

Brett knew that Tyree was working on another project that was randomized by a calculated field, so I contacted him on Slack. “How did you code this random variable? Doesn't Medtech allow this? ”

“I speak from a conference call, call back later,” wrote Tyree.

A few minutes later, Tyree called Brett.

“You need to start with two fields. Let's say. let's call them $variable_choice , that is, a multiple choice question, and $variable_calced , that is, your calculated field. When you want to create a variable that performs a random selection based on a calculated field, you tell Medtech that this random variable is based on $variable_choice . Then you delete $variable_choice , and rename $variable_calced to $variable_choice »

“Stop, the system allows you to do this, but does not allow you to randomize the calculated fields in some other way? And she doesn't check it? ”

“I hope nothing changes, and she will not begin to verify this until the completion of my project,” Tyri replied.

“This study should take place over ten years. And its successful completion depends on whether the developers consider this trick to be a bug? ”

“I managed to find only such a solution. Let me know if you find something better. ”

Brett did not satisfy such a hack, and he returned to studying the documentation. He found a better solution: you can create a read-only multiple choice field with a single default value option — the value of the calculated field. Unfortunately, the user could inadvertently change the list by answering a multiple-choice question before calculating the value of the calculated field.

In the end, the only thing Brett left was to take a break, go to the cafeteria and buy a couple of hot dogs.

The third story. Portability and hardware


[Original]


Many moons ago, when the PCs had heavy metal and plastic cases, Matt and his colleague were assigned to evaluate the software package for the upcoming sales department operation. Unfortunately, he and his colleague worked in different offices within the same city. At that time, effective online collaboration tools did not exist, so Matt had to travel to another office regularly, taking PCs with him. This meant that each time it was necessary to disconnect the peripherals from the 473 cable body, carry the computer along the corridors and down the stairs, catch the bus to get to the other office in which he did all this in the reverse order. Sometimes the wrong organization of labor forced this couple to work on weekends, which means carrying the working machines home.

In the process, the hard disk of 20 MB in Matt's computer overflowed. From his office, he sent a request to the IT department. To fulfill the application, Gary's technician was appointed, which after some time appeared in Matt's cubic, holding a new hard drive and a screwdriver. Gary sent Matt over coffee to focus on his “patient.” After a small surgery, Matt's PC turned on and started working with a large hard drive.

The day before the project's deadline, Matt almost completed his share of the work. He had only to make a few additions to his report, and then copy it to floppy disks and send it to the sales department. Returning his PC to the cubicle and connecting the wires, he turned on the power and heard the clap. The PC was dead and showed no signs of life.

After a panic call to the IT department, Gary again appeared in his office with a screwdriver. Having opened the PC case, he immediately yelled: “Wait a minute! Did you drag a computer somewhere? ”

Matt frowned. "Well yes. What's the matter? ”

“Yes of course! You shouldn't have done that! ”Gary began to curse. “The hard drive started to hang out and shorted everything inside!”

Matt leaned over Gary to see the inside of the computer himself. He immediately noticed that the new hard drive was "fixed" on the tape.

"Stop! You should n't have done this! ”Matt pointed to a piece of scotch. “Do I just need to contact your supervisor just in case?”

Gary's face wrinkled. "I do not give the necessary attachments!"

"Then find the one who has them!"

Given the impending deadline, with the permission of the chief, Matt passed on his application even higher. Almost immediately, the adhesive tape was replaced with a real fastener. He never understood why the IT staff did not have access to the necessary equipment; He suggested that it was a brilliant idea of ​​some kind of idiot to save money. Matt could only guess what other desperate improvisations made it possible to ensure the efficiency of their IT infrastructure, and how long they would go unnoticed if his PC had not broken down.

The fourth story. This is how PL / SQL affects your brain.


[Original]

The eternal champion among the strangest and most unsuccessful decisions will always be Oracle . Today we look at a little PL / SQL code.

PL / SQL is a strange language, a mixture of SQL and P rocedural (procedural) L anguage (language) with side-oriented object orientation. The syntax perfectly succeeds in creating the impression that it was developed in the 1970s, and each new function or language change continues this tradition.

The structure of each PL / SQL code module is based on blocks . Each block is an independent namespace. In short, his anatomy looks like this:

 DECLARE -- variable declarations go here BEGIN -- code goes here EXCEPTIONS -- exception handling code goes here, using WHEN clauses END; 

If you are writing a stored procedure or event handler, then replace the DECLARE keyword with CREATE [OR REPLACE] . You can also nest blocks inside other blocks, so you can often see code that is structured as follows:

 BEGIN DECLARE --stuff BEGIN --actions END; --more actions END; 

Yes, pretty quickly it starts to get confusing. And yes, if you want to provide at least approximately structured error handling, you must begin to put blocks into each other.

Language and database have other fun features. Prior to version 12c, they did not have an IDENTITY column type. In previous versions, it was necessary to use the SEQUENCE object and write procedures or event handlers that perform forced automatic numbering. Usually, a SELECT INTO… used to assign a value to a variable. Bonus: Oracle SQL always requires the specification of a table in the FROM , so you need to use the invented dual table, like this:

 CREATE TRIGGER "SOME_TABLE_AUTONUMBER" BEFORE INSERT ON "SOME_TABLE" FOR EACH ROW BEGIN SELECT myseq.nextval INTO :new.id FROM dual; END; 

:new in this context denotes a string for which we perform automatic numbering. In older versions of Oracle, this was the “usual” way to create columns with automatic numbering. Benoit discovered another, slightly less common way of performing the same operation:

 CREATE OR REPLACE TRIGGER "SCHEMA1"."TABLE1_TRIGGER" BEFORE INSERT ON "SCHEMA1"."TABLE1" FOR EACH ROW BEGIN DECLARE pl_error_id table1.error_id%TYPE; CURSOR get_seq IS SELECT table1_seq.nextval FROM dual; BEGIN OPEN get_seq; FETCH get_seq INTO pl_error_id; IF get_seq%NOTFOUND THEN raise_application_error(-20001, 'Sequence TABLE1_SEQ does not exist'); CLOSE get_seq; END IF; CLOSE get_seq; :new.error_id := pl_error_id; END; END table1_trigger; 

There is a lot going on here. First, note that the DECLARE section contains a CURSOR statement. Cursors allow you to iterate between records. They are very expensive and in the Oracle world it is a resource that needs to be freed.

This event handler (trigger) uses a nested block for no reason at all. It also uses the additional variable pl_error_id , which you can do without.

But the really weird part is the IF get_seq%NOTFOUND . Everything is quite simple: it checks the condition that the cursor did not return a string. This for this cursor can not happen even theoretically , so the operations inside are never performed. A sequence always returns a value. And this is good , given the code that goes on.

raise_application_error is the “throw” equivalent in Oracle. This statement climbs the stack of executable blocks until it finds the EXCEPTIONS section for handling the error. Notice that we close the cursor after this statement — that is, in fact, we never close the cursor. Cursors, as mentioned above, are expensive, and Oracle allows you to use only a limited number of them.

Here we see a strange example of how a developer tries to defend himself against an error that cannot occur, in a way that will eventually lead to new errors.

The fifth story. Logins with double encryption


[Original]

Creating authentication for a web API is a difficult task, but it has many well-established solutions. The most difficult thing is to choose one of the various options, after which you simply add the component.

When properly implemented, the system does not depend on the type of client. I can access the service through a browser, in a thick client, or through cURL. With incorrect implementation, you get what happened to Amira .

She solved the problem of pulling out the statistics she needed from the backend, but she could not figure out how to authenticate. Therefore, she studied the frontend code to understand how it performs authentication:

 crypt = new JSEncrypt(); crypt.setPublicKey('<removed>'); challenge = "<removed>"; function doChallengeResponse() { document.loginForm.password.value.replace(/&/g, '%26'); document.loginForm.password.value.replace(/\\+/g, '%2B'); document.loginForm.password.value = crypt.encrypt(document.loginForm.password.value); document.loginForm.response.value = document.loginForm.password.value; document.loginForm.password.value = ''; document.loginForm.submit(); } 

On the one hand, I can assume that this code is very old, given the document.loginForm used for interactions with DOM elements. On the other hand, JSEncrypt was first released in 2013, which gives us the maximum age bar.

We pass the access parameters to the backend by sending the form, which, according to the code developer, required clearing - all & and + are replaced in the password, but ... this is not necessary because the form must perform a POST request and, in addition, we encrypted the data .

That's what I think. The code is really quite old. The developer copied it from the post to StackOverflow in about 2005, which did not use encryption and form sending via POST . Year after year small changes were added to it. but the basic mechanism has never changed.

Amira checked the story, and found that encryption was not used in the previous version.The code concatenated the password with a variable challenge, both of them were hashed by MD5, after which it transmitted it to the network, and everything seemed to work, if you did not think too much about it.

There was a good side of things: when Amira figured out how to get the cookies she needed, the token life on the server never expired, so she could store it, send requests through cURL and no longer contact the web form. She did not have to worry about compromising cookies during transmission, because the application uses and has always used SSL / TLS .

Source: https://habr.com/ru/post/446714/


All Articles