Because there are not many Crypto listed in the "Stock Market", I decided to join our Webb-expert Web-expert Ozetta for bounty hunting in web, and we got all web challenges done this time. The writeup of the web challenges can be found here.

### Challenge Summary#

The challenge defines a signature algorithm $\mathcal{S}$, where a key generated with elliptic curve parameter P-256 (the public and private keys are respectively $Q$ and $d$). The signing algorithm for a message $m$ is specified below ($\text{H}$ is the SHA3-256 algorithm that returns an integer given an array of bytes):

1. Compute $r = \text{H}(m) \cdot Q$
2. Compute $r' = r\cdot d^{-1}\ \text{mod}\ q$, where $q$ is the order of the curve
3. Define $z = n_\text{nonce} | t$, where $n_\text{once} \in [1, q)$ and $t$ is the timestamp in seconds
4. Compute $R = r' + \text{H}(z) \cdot G$
5. Compute $s = [d - \text{H}(z)]\ \text{mod}\ q$
6. Return $(R, s)$ as the signature.

Also the verifying algorithm for a message $m$ and signature $(R, s)$:

1. If $s = 0\ \text{or}\ 1$ and $s > 0$ then the signature is considered invalid.
2. The signature is valid only if

$s \cdot G - Q + R = \text{H}(m) \cdot G$

There are three functions those we can use when connected to the server:

1. [Show] Prints the public key.
2. [Sign] Signs one of the four commands: id, uname, ls and date with $\mathcal{S}$.
3. [Run] Takes a signed command and executes if the signature is valid.

### Solution#

The verify method they implemented is really fishy:

def verify(msg, sig, pub):
R, s = sig

# 👇 This is sus
if s in [0,1,''] and s > 0:
return False

tmp1 = s * pub._curve.G
tmp2 = - pub.pointQ
tmp3 = tmp2 + R

return tmp1 + tmp3 == hash(msg) * pub._curve.G

From the line specified, it seemed to me that $s$ should be nonzero. I tried putting $s = 0$ and found $R = Q + \text{H}(m)$. That said, we can simply send $(R, s) = (Q + \text{H}(m), 0)$ as an signature to execute arbitrary commands. With that said, we can simply craft a signature for cat flag and read the flag.

### Postmortem#

$\mathcal{S}$ is not secure at all. It does not help even if $s \neq 0$ is enforced. $R$ can be easily crafted given arbitrary $m$ and $s$:

$R = [\text{H}(m) - s] \cdot G + Q$

For instance, @RBTree_ could execute arbitrary commands with $(R, s) = (Q, \text{H}(m))$.