Several kinds of common cryptographic attacks in WEB

reference resources:

Because it involves cryptography, I have a big head. Let's record it.

Padding oracle attack and CBC flip byte attack


What is XOR? XOR is an operation method, which is briefly summarized as the same false different true

true xor true = false; true xor false = true;

In binary:
011 xor 110 = 101; Binary numbers are calculated separately for each digit xor operation
 The operation steps of the above formula are as follows: 0 xor 1 = 1;1 xor 1 = 0;1 xor 0=1
 Then write the calculation results together, which is 101

In higher base:
Take the decimal system as an example: 65 xor 42 = 107; The principle is to change the decimal number into binary number for XOR, and then change the binary number obtained by XOR into decimal number

In character:
XOR operation on characters is actually an operation on characters ascii Code for XOR calculation, and the calculated result is regarded as a new one ascii Code and then convert it into characters.

Another property of xor is Given a xor b = c then b xor c =a; a xor c = b. that is to say, in the XOR operation, you only need to know any two numbers to get another number.

CBC mode

CBC is an encryption model, which adopts packet link mode. The plaintext is divided into groups for encryption

The figure above shows the CBC encryption process. The first special group IV goes to the first ciphertext XOR, and the obtained result is encrypted by the key to obtain the ciphertext of this group. At the same time, this ciphertext will act as the first special group IV to participate in the encryption of the next group, and so on.

The encryption result of each group of CBC can affect the encryption result of the next group, and make the original independent block cipher encryption process form an iteration, which can strengthen the "sensitivity" of the encryption algorithm, that is, realize the so-called "avalanche effect", which is the "disturbance principle" in Xiangnong theory.

CBC is just a pattern. It often uses AES or DES as an encryption algorithm. The DES packet length is eight bytes, while the AES packet length is sixteen bytes.

Next is CBC decryption

The order is still from left to right. After the first group of ciphertext is decrypted by KEY, it gets the first group of plaintext with IV xor. At the same time, the first group of ciphertext participates in the decryption of the next group and acts as IV.


If the CBC mode involves grouping, the last group of bytes will not be full. For example, the original packet is 8 bytes, and we have 15 bytes of plaintext to be encrypted. At this time, the last packet will not be full (one byte is still missing). What should we do at this time?

At this time, you need to fill the last group and fill it up. For the content encrypted by des algorithm, the filling rule is PKC #5, while AES is PKC #7 The only difference between the two is that PKCS #5 padding is an eight byte packet while PKCS #7 is sixteen bytes. Do you remember that DES packet length is eight bytes while AES packet length is sixteen bytes? It is the number of bytes in this packet that affects the filling method.

So how to fill it? Let's take PKC #5 as an example

When the last group has n bytes left unfilled, it will be filled with n 0xn characters The above figure shows PKCS #5. In fact, the principle of PKCS #7 and PKCS #5 is the same, but the number of packet bytes is a little large (0 ~ 16)

Padding oracle attack

The above is just a foreshadowing. It is suggested to look at this attack method after learning it. Otherwise it will be very big.

Example of Padding oracle attack scenario

First, we assume a scenario, which leads to this attack.

Suppose we have an arbitrary file containing the scene


Hackers can easily include the desired files when they see them. The manager found this problem and used CBC encryption for the file parameter, that is, when submitting the request, the value of the file parameter is encrypted, and then the server decrypts the file it wants to contain with the algorithm, and then returns it to the client.

url?file=e28b2e3c972edab8 The first eight digits are IV,The last eight digits are ciphertext. Here is the ciphertext I wrote blindly= =,You just need to understand that this is a CBC Encrypted ciphertext is enough)

So how to realize our arbitrary file inclusion? padding oracle attack appears.

Attack principle

Suppose we submit a ciphertext to the one contained in the arbitrary file just now. The server will try to decrypt, and three results will appear.

1. The ciphertext cannot be decrypted normally because there is an error in the last group of padding bytes 2. The ciphertext can be decrypted normally, but the decrypted file path does not exist 3. The ciphertext can be decrypted normally and successfully contained

The content returned by the web page in case 1 and case 2.3 must be different. For example, the first case may directly return 500, and 2.3 may jump to 302. With the information returned through this page, we have an opportunity.

Let's first experience the decryption process of the first group through a diagram

OK, OK, after feeling the decryption process, let's talk about the attack. If we get the intermediate value and can modify the IV manually, can we construct any Decrypted Value? Therefore, the core of padding oracle attack is to obtain the intermediate value. So how do we get it?

Remember the three situations just mentioned? We can judge the intermediate value by modifying IV and judging the content returned from the web page. The specific methods are as follows:

We first set all the IV to 0x00, and then modify the last number of IV. when the value after the intermediate value XOR is 0x01, the decryption will succeed. If it is not 0x01, the decryption will fail, and the web page will return different contents to judge when the decryption is successful. Then XOR the last digit of IV when decryption is successful with 0x01 to obtain the last digit of the intermediate value

Then we set the last digit of IV as the number that can be XORed with the last digit of the middle value and the value is 0x02. Enumerate the penultimate number of IV to see which number can be XORed with the penultimate number of the middle value and the value is 0x02. Then we can get the penultimate number of the middle value, and so on to get the middle value of the first group (a little winding) Then we crack the intermediate value. We use the initial IV (not the IV constructed later) to XOR with the intermediate value to get the plaintext Of course, you can also construct IV again to construct the decrypted characters (XOR with IV through the intermediate value)

[NPUCTF2020]web 🐕 Padding oracle Attack in

Let's take this topic as the starting point and take a detailed look at how to realize the attack. This problem is the following code. We should try our best to get $flag first

include('config.php');   # $key,$flag
define("METHOD", "aes-128-cbc");  //Define encryption method
define("SECRET_KEY", $key);    //Define key
define("IV","6666666666666666");    //Define 16 initial vectors 6

#var_dump($GLOBALS);   // I hear you want to see this?
function aes_encrypt($iv,$data)
    echo "--------encrypt---------".BR;
    echo 'IV:'.$iv.BR;
    return base64_encode(openssl_encrypt($data, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)).BR;
function aes_decrypt($iv,$data)
    return openssl_decrypt(base64_decode($data),METHOD,SECRET_KEY,OPENSSL_RAW_DATA,$iv) or die('False'); //Only 1 or false can be returned
    $iv = IV;
    $data = $flag;    
    echo aes_encrypt($iv,$data);
} else if($_GET['method']=="decrypt")
    $iv = @$_POST['iv'];
    $data = @$_POST['data'];
    echo aes_decrypt($iv,$data);
echo "I had a showdown, but I didn't bother to write the front end".BR;


Let's get the ciphertext ly7auKVQCZWum/W/4osuPA first== Then it is decrypted by base64 and found that it has exactly 16 bytes. Then we can directly enumerate IV to get the intermediate value, and then XOR with the initial IV (16 6) to get the plaintext $flag

Not much to say, the script arrangement of blasting intermediate value. (borrowed from a big man's WP)

import requests
import base64
import time
def xor(a,b):
    return "".join([chr(ord(a[i])^ord(b[i])) for i in range(len(a))])

for step in range(1,17):
    print("The first%s round"%step)
    for i in range(0,256):
        print(r.text+"The first%s round i=%s "%(step,i))
        if "False" !=  r.text:
for k in range(len(Intermediary)):

Broke the middle value and $flag plaintext

There are some doubts here, why the median value will be 15 It is found that $flag is not the final flag. The next thing to do is CBC byte flip attack

CBC flip byte attack

When decrypting the data encrypted in CBC mode, if iv controllable, the decrypted content can be controlled arbitrarily. CBC flip byte attack is different from padding oracle attack. The core of the latter is to obtain the intermediate value under IV control, so as to obtain the data decrypted by plaintext or arbitrary control ciphertext. The core idea of CBC flip byte attack is not to obtain the intermediate value, but to directly control the decrypted data through algorithm defects when IV is controllable.

Now suppose there are intermediate values A, B1, IV, C1 Then there is


No mistakes at all, right. Now, assuming that there is an intermediate value A, we want to decrypt the plaintext B2 and the corresponding IV C2 Then there is

 Combining the above two formulas, there are
 So there
 or C2=B1^B2^C1
 If we know B1,C1,And C2 controlled,that B2 Can control
 It not only meets what we just said, but also directly controls the decrypted data of ciphertext through algorithm defects.

This is the CBC flip byte attack. It's ok if you don't understand it. Just look at the example

[NPUCTF2020]web 🐕 CBC flip byte attack in

We just followed up, flag PHP, the core code is as follows

include('config.php');    //$fl4g
define("METHOD", "aes-128-cbc");
define("SECRET_KEY", "6666666");

function get_iv(){    //Generate random initial vector IV
    return $random_iv;

$lalala = 'piapiapiapia';

    $_SESSION['iv'] = get_iv();

    $_SESSION['Identity'] = base64_encode(openssl_encrypt($lalala, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $_SESSION['iv']));
echo base64_encode($_SESSION['iv'])."<br>";

    $tmp_id = openssl_decrypt(base64_decode($_SESSION['Identity']), METHOD, SECRET_KEY, OPENSSL_RAW_DATA, base64_decode($_POST['iv']));
    echo $tmp_id."<br>";
    if($tmp_id ==='weber')die($fl4g);


At this time, we know the initial IV and the initial ciphertext, and the IV is controllable, then the CBC flip byte attack condition is established and can be attacked.

Here is a post written by someone else python2 CBC Byte inversion attack script
 Take it yourself python3 I haven't written very well for a long time...
import base64
def bxor(b1, b2): # use xor for bytes
    parts = []
    for b1, b2 in zip(b1, b2):
        parts.append(bytes([b1 ^ b2]))
    return b''.join(parts)
iv = base64.b64decode("h34HL5RbMPw8oTaQ+P58nw==")
text = b"piapiapiapia\x04\x04\x04\x04"
result = b"weber\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
middle = bxor(iv,text)
iv = bxor(middle,result)

POST the results and you'll get the next step

Hash length expansion attack

1 byte=8 bit

hash algorithm

Merkle – Damg å rd structure

Algorithms vulnerable to hash length expansion attack include SHA series and MD series, because they are both constructed based on Merkle – Damg å rd. The specific structure can be felt from the MD5 algorithm below

MD5 algorithm


In MD5 algorithm, groups will be set one by one. The size of each group is 512bit or 64bytes.

Each group consists of 2 parts: 1. Data area, accounting for 56 bytes, to record string data that needs to be encrypted. When the data cannot fill the data area, the "filling" operation will be carried out (see the explanation below) 2. The length descriptor area is used to record the size of "non complementary" data, accounting for 8 byte s, and its value is the hexadecimal value of the bit size of non complementary data in this group of data area. For example, the non complementary data is admin, which accounts for 5 byte s and 40 bit s. The hex of 40 is 28, so its value will be 28. Then this value will be recorded in the length Descriptor Area in a way called small end storage. (non filled data refers to the non filled data of this group, that is, the string that really needs to be encrypted)


Very simply, if the data length of a group is less than 56 bytes, the data area of the group will not be filled, and the data area will be filled automatically.

The rule is to add an 80 byte after the data, and then fill the whole data area with 00 bytes.

Summary of grouping and filling

Before further understanding MD5 algorithm, we need to have a deeper understanding of grouping and filling, otherwise it will be very difficult to understand later.

Encryption process

Here is a picture of the encryption process drawn by yourself

The strings are grouped first, and then the first group performs complex mathematical operations with the initial chain to obtain chain 1 Note that the initial chain here is fixed, and the initial chain of each MD5 operation is fixed, and its value is recorded in the figure. In other words, no matter what data is MD5 encrypted, its initial chain is

0x67452301 0xefcdab89 0x98badcfe 0x10325476

ok. The first set of data performs complex operation with the initial chain to obtain chain 1, and then chain 1 performs complex operation with the second set of data to obtain chain 2, and so on until the penultimate chain performs complex operation with the last set of data to obtain the last chain (chain final)

What is the final low order chain after the low order chain is converted?

If the final chain is

  1. A=0x20f4847a
  2. B=0x42e6abf8
  3. C=0xf9097423
  4. D=0x51a8dad4

The hash is 7a84f420f8abe642237409f9d4daa851

hash length extension attack

Once you have mastered the basic knowledge, you will begin to understand this play.

Take a problem as the starting point (change a problem of the experiment)

Your cookies don't match up! STOP HACKING THIS SITE. <?php
include "flag.php";
//$secret="XXXXXXXXXXXXXXX"; This secret is 15 characters long for security!
$password = $_POST["password"];
if($_POST["getmein"] === md5($secret . urldecode($username . $password))){
    echo "Congratulations! You are a registered user.\n";
    die ("The flag is ". $flag);
    echo("Your cookies don't match up! STOP HACKING THIS SITE.");
echo(md5($secret . urldecode($username . "admin")));
?> 93a5e7bea9c040065617b1a62ffc3d72

From this, we can know that the length of secret is 15, md5($sercet. "Admin") = 93a5e7bea9c040065617b1a62ffc3d72

The meaning of the topic is obvious. We need to pass two parameters, getmein and password, so that

getmein=md5($secret. "admin". password), and the password contains abc characters

Then this is the classic example of hash length extension attack, that is: Know the salt length (here, the length of the secret variable) Know a set of samples whose encrypted string length is less than 56 (md5($sercet. "Admin") You can know the hash of a value encrypted by MD5 together with salt

How did this attack come about? First, we know a set of samples, that is, we know the final chain (high-low transformation) of the sample. At the same time, we know the salt length, that is, we can construct the packet. Then, if we construct a new group, and the previous group is a known sample, then the final chain of known samples is the complex operation with the new group. Given the final chain of samples and the newly grouped string to be encrypted, the final hash can be obtained through complex operation and high-low transformation. Therefore, the hash value of the string to be encrypted in the new packet can be predicted. This is the principle of hash length expansion attack. Maybe it's still in the clouds. It depends on how to solve the problem.

Because the salt length is known, we can predict the grouping of samples Because the length of Salt + admin is 25, its bit is 200 and converted to hexadecimal is c8 Suppose that the salt characters are all x (it's just an assumption, don't think too much), the grouping situation

Then we can pass it on password=admin%80%00*30abc The characters before abc will be assigned to the previous group during MD5 operation, and then chain 1 will be obtained through operation. This chain 1 is the final chain of our known samples. Then we can predict that the final chain and abc perform complex operations, and the hash is obtained by high-low transformation. Then assign the hash to openmein, and the problem is solved.

OK, that's the general principle. At this time, you can write your own script to find the MD5 ciphertext corresponding to a plaintext, or use the tool: hashdump


]( Screenshot 20210217152515 png)

Added by PrinceOfDragons on Fri, 11 Feb 2022 10:14:07 +0200