Vulnerabilidad de reproducción de firma en contrato inteligente | BlockAudit

Nov 30 2022
Un truco útil es firmar mensajes fuera de la cadena y tener un contrato que exija esa firma antes de realizar una función. Por ejemplo, esta técnica se usa para: -- reducir el número de transacciones en una transacción sin gas en cadena, llamada meta transacción Veamos de qué estamos hablando Las cadenas de bloques dependen en gran medida de las firmas criptográficas.

Un truco útil es firmar mensajes fuera de la cadena y tener un contrato que exija esa firma antes de realizar una función.

Por ejemplo, esta técnica se usa para: -
- reducir el número de transacciones en la cadena
- transacción sin gas, llamada
meta transaction

A ver de que hablamos

Las cadenas de bloques dependen en gran medida de las firmas criptográficas. Las transacciones se firman con las claves privadas correspondientes, lo que permite asociar los remitentes de las transacciones a sus cuentas. La contabilidad de la cadena de bloques sería inoperable sin esta función.

Las firmas digitales también se validan con frecuencia directamente en los contratos inteligentes de Ethereum, lo que permite que uno o más verificadores autoricen acciones mediante el envío de firmas fuera de la cadena ( o incluso firmas generadas por otro contrato inteligente ).

Esto se usa con frecuencia en bóvedas de firmas múltiples o contratos de votación para enviar varias firmas al mismo tiempo o para delegar la autorización.
Los ataques de reproducción de firmas son una vulnerabilidad común en tales implementaciones.

A veces se requiere la verificación de firmas en los contratos inteligentes para mejorar la usabilidad o ahorrar costos de gasolina. Una implementación segura debería evitar los ataques de reproducción de firmas.

Por ejemplo: -
Hacer un seguimiento de todos los hashes de mensajes procesados ​​y permitir que solo se procesen nuevos hashes de mensajes. Un usuario malintencionado podría atacar un contrato que carece de dicho control y obtener un hash de mensaje enviado por otro usuario y procesado varias veces.

Firmas digitales criptográficas

Las firmas digitales son las primitivas de clave pública de autenticación de mensajes. En el mundo físico, las firmas manuscritas se usan comúnmente en mensajes escritos a mano o mecanografiados. Se utilizan para vincular al firmante al mensaje.

Una firma digital es un valor criptográfico generado por datos y una clave secreta conocida solo por el firmante.

Modelo de Firma Digital

El procedimiento completo se explica detalladamente en los siguientes puntos:

Fuente de la imagen: Wikipedia
  • Cada usuario de este esquema tiene un conjunto de claves públicas y privadas.
  • Los pares de claves utilizados para el cifrado/descifrado y la firma/verificación suelen ser distintos entre sí. La clave pública se denomina clave de verificación y la clave privada se denomina clave de firma.
  • El firmante envía los datos a la función hash, que produce el hash.
  • Luego, el algoritmo de firma genera la firma digital en el hash proporcionado utilizando el valor hash y la clave de firma. Los datos se firman y ambos se envían posteriormente al verificador.
  • El algoritmo de verificación es alimentado por el verificador junto con la firma digital y la clave de verificación. El resultado del algoritmo de verificación es algo útil. En los datos que recibe, el verificador también usa el mismo algoritmo hash para producir un valor hash.
  • Este valor hash y los resultados del proceso de verificación se comparan para la verificación. El verificador determina si la firma digital es legítima en función de los resultados de la comparación.
  • Nadie más puede utilizar la clave "privada" del firmante para establecer una firma digital, por lo que el firmante no puede retractarse posteriormente de su firma de los datos.

La capa de protocolo

Solo las transacciones con firmas válidas se incluyen en bloques nuevos, gracias a la red Ethereum . Para las transacciones, esto ofrece los siguientes atributos de seguridad:

  • Autenticación : los nodos de Ethereum utilizan la firma para confirmar que la persona que firma la transacción es el propietario de la clave privada conectada a su dirección pública. Por lo tanto, los desarrolladores pueden estar seguros de que msg.sender es genuino.
  • Integridad : La integridad es la condición de que la transacción no haya cambiado después de haber sido firmada; de lo contrario, la firma es nula.
  • No repudio: la firma de una transacción y cualquier cambio de estado realizado por la parte firmante en posesión de la clave privada no se puede impugnar. La clave privada pertenece a la dirección pública que figura en el campo de .

La misma firma se puede utilizar varias veces para ejecutar una función. Esto puede ser dañino si la intención del firmante era aprobar una transacción una vez.

Ejemplo de código

Examinemos el error.

function unlock(
  address _to,
  uint256 _amount,
  uint8[] _v,
  bytes32[] _r,
  bytes32[] _s
)
  external
{
  require(_v.length >= 20);
  bytes32 hashData = keccak256(_to, _amount);
  for (uint i = 0; i < _v.length; i++) {
    address recAddr = ecrecover(hashData, _v[i], _r[i], _s[i]);
    require(_isValidator(recAddr));
  }
  to.transfer(_amount);
}

El mensaje que firman los validadores utilizando la técnica ECDSA es donde radica el problema con el código mencionado. La dirección del destinatario y el dinero requerido son la única información en el mensaje. No se puede utilizar nada en el mensaje para evitar usar la misma firma más de una vez. Considere el siguiente caso:

  • Sam transfiere 2000 ETH desde la red vinculada a la cadena Ethereum usando la misma cantidad de moneda.
  • Tom, un retransmisor, está procesando esta transacción entre cadenas de bloques. Para liberar 2000 ETH del contrato y enviárselos a Sam, reúne las firmas de validación requeridas, bloquea la cantidad correcta en la cadena conectada y luego usa la función de desbloqueo.
  • En la cadena de bloques, todos ven la transacción que contiene los conjuntos de valores de firma.
  • Ahora que Sam ha copiado las matrices de firmas, puede enviar de forma independiente una llamada de desbloqueo. Una vez más, el proceso de desbloqueo será exitoso y dará como resultado la transferencia de 2000 ETH a Sam.
  • Sam puede continuar de esta manera hasta que se agote el contrato.

Un ataque de repetición característico es lo que se describe en el ejemplo anterior. Es concebible ya que no hay forma de determinar si este mensaje firmado específico es único o si se ha utilizado anteriormente.

Firmar mensajes con noncey dirección del contrato.

public uint256 nonce;
function unlock(
  address _to,
  uint256 _amount, 
  uint256 _nonce,
  uint8[] _v,
  bytes32[] _r,
  bytes32[] _s
)
  external
{
  require(_v.length >= 20);
  require(_nonce == nonce++);
  bytes32 hashData = keccak256(_to, _amount, _nonce);
  for (uint i = 0; i < _v.length; i++) {
    address recAddr = ecrecover(hashData, _v[i], _r[i], _s[i]);
    require(_isValidator(recAddr));
  }
  to.transfer(_amount);
}

Para protegerse contra los ataques de reproducción de firmas, tenga en cuenta las siguientes recomendaciones:

  • Almacene cada hash de mensaje que haya sido procesado por el contrato inteligente. Cuando se reciben nuevos mensajes, verifique los que ya existen y solo continúe con la lógica comercial si se trata de un hash de mensaje nuevo.
  • Incluya la dirección del contrato que procesa el mensaje. Esto asegura que el mensaje solo se puede usar en un solo contrato.
  • En ningún caso generar el hash del mensaje incluyendo la firma. La ecrecoverfunción es susceptible a la maleabilidad de la firma.

Las firmas no únicas se pueden reproducir en una variedad de situaciones, como se ve en el ejemplo anterior. Para evitar ataques repetidos, en la mayoría de las situaciones es crucial asegurarse de que las firmas coincidan específicamente con cada llamada. Además, por esta razón, se incluye un nonce en cada transacción de Ethereum.

Referencias: -

https://solidity-by-example.org/hacks/signature-replay/
https://blog.finxter.com/smart-contract-replay-attack-solidity/
https://swcregistry.io/docs/SWC-121

¡¡¡Apresurándose con web3 Security!!! ¡¡¡Conéctate con nosotros!!!

BlockAudit : - ¿Por qué nosotros?
BlockAudit tiene los recursos y el conocimiento para crear soluciones de ciberseguridad que ahorran millones de dólares.
Linkedin | Sitio web | Gorjeo