diff --git a/.github/workflows/e2e_pr.yaml b/.github/workflows/e2e_pr.yaml new file mode 100644 index 0000000..d3f293f --- /dev/null +++ b/.github/workflows/e2e_pr.yaml @@ -0,0 +1,57 @@ +name: CI for ssh-mapper +on: [push, pull_request] + +jobs: + ssh-mapper-dropbear-server: + if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} + runs-on: ubuntu-latest + # strategy: + # fail-fast: true + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Start learning DropbearSSH server + run: cd experiments/scripts/ && ./start_experiment.sh dropbear + + - name: Verify Result + run: | + # wait for the learning to be over + while [ "$( docker container inspect -f '{{.State.Running}}' dropbear-learner )" = "true" ]; do date; echo "still learning"; sleep 5; done + experiments/scripts/diff_hyps.sh experiments/results/servers/dropbear experiments/orchestration/learner_output_dropbear 3 + + ssh-mapper-openssh7-server: + if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} + runs-on: ubuntu-latest + # strategy: + # fail-fast: true + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Start learning OpenSSH7 server + run: cd experiments/scripts/ && ./start_experiment.sh openssh7 + + - name: Verify Result + run: | + # wait for the learning to be over + while [ "$( docker container inspect -f '{{.State.Running}}' openssh-learner7 )" = "true" ]; do date; echo "still learning"; sleep 5; done + experiments/scripts/diff_hyps.sh experiments/results/servers/openssh7 experiments/orchestration/learner_output_openssh7 3 + + ssh-mapper-openssh8-server: + if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} + runs-on: ubuntu-latest + # strategy: + # fail-fast: true + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Start learning OpenSSH8 server + run: cd experiments/scripts/ && ./start_experiment.sh openssh8 + + - name: Verify Result + run: | + # wait for the learning to be over + while [ "$( docker container inspect -f '{{.State.Running}}' openssh-learner8 )" = "true" ]; do date; echo "still learning"; sleep 5; done + experiments/scripts/diff_hyps.sh experiments/results/servers/openssh8 experiments/orchestration/learner_output_openssh8 2 diff --git a/.gitignore b/.gitignore index 8a982ce..48d1f6a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,5 @@ ssh-mapper/paramiko.egg-info/** ssh-mapper/build/** ssh-mapper/dist/** ssh-mapper/mapper/__pycache__/** -ssh-learner/target/** \ No newline at end of file +ssh-learner/target/** +__pycache__/ \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml deleted file mode 100644 index f30ea29..0000000 --- a/docker-compose.yaml +++ /dev/null @@ -1,51 +0,0 @@ -version: "3.8" - -services: - # Dropbear service - dropbear-ssh: - build: - context: . - dockerfile: Dockerfile.dropbear - container_name: dropbear-ssh - ports: - - "2222:22" - networks: - - fuzzer_network - volumes: - - ./ssh-keys:${HOME}/.ssh/:ro - - # SSH Mapper service - ssh-mapper: - build: - context: ./ssh-mapper - dockerfile: Dockerfile - container_name: ssh-mapper - ports: - - "8080:8080" - depends_on: - - dropbear - networks: - - fuzzer_network - volumes: - - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro - - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro - command: -l 0.0.0.0:8080 -s dropbear-ssh:22 -f server - - # SSH Learner service - ssh-learner: - build: - context: ./ssh-learner - dockerfile: Dockerfile - container_name: ssh-learner - networks: - - fuzzer_network - depends_on: - - dropbear - - ssh-mapper - volumes: - - ./learner_output:/app/output_folder - command: ["state-fuzzer-server", "-connect", "ssh-mapper:8080", "-alphabet", "/app/inputs/alphabets/servers/trans_auth.xml", "-ceReruns", "3", "-depth", "2", "-learningAlgorithm", "LSTAR", "-output", "/app/output_folder", "-ros", "-sshMapperAddress", "ssh-mapper:8080"] - -networks: - fuzzer_network: - driver: bridge diff --git a/experiments/orchestration/docker-compose-dropbear.yaml b/experiments/orchestration/docker-compose-dropbear.yaml new file mode 100644 index 0000000..ad9a510 --- /dev/null +++ b/experiments/orchestration/docker-compose-dropbear.yaml @@ -0,0 +1,52 @@ +version: "3.8" + +services: + dropbear-ssh: + build: + context: . + dockerfile: dockerfiles/Dockerfile.dropbear + container_name: dropbear-ssh + ports: + - "2222:22" + networks: + - dropbear_network + volumes: + - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro + - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro + entrypoint: ["sh", "-c", "cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys && /usr/local/sbin/dropbear -F -E -j -k -s"] + + + dropbear-mapper: + build: + context: ../../ssh-mapper + dockerfile: Dockerfile + container_name: dropbear-mapper + # ports: + # - "8080:8080" + depends_on: + - dropbear-ssh + networks: + - dropbear_network + volumes: + - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro + - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro + command: -l 0.0.0.0:8080 -s dropbear-ssh:22 -f server + + dropbear-learner: + build: + context: ../../ssh-learner + dockerfile: Dockerfile + container_name: dropbear-learner + networks: + - dropbear_network + depends_on: + - dropbear-ssh + - dropbear-mapper + volumes: + - ./learner_output_dropbear:/app/output_folder + - ../../ssh-learner/inputs/alphabets/servers/:/app/inputs/alphabets/servers/ + command: ["state-fuzzer-server", "-connect", "dropbear-mapper:8080", "-alphabet", "/app/inputs/alphabets/servers/trans_auth.xml", "-output", "/app/output_folder", "-sshMapperAddress", "dropbear-mapper:8080", "-roundLimit", "3", "-debug"] + +networks: + dropbear_network: + driver: bridge diff --git a/experiments/orchestration/docker-compose-openssh7.yaml b/experiments/orchestration/docker-compose-openssh7.yaml new file mode 100644 index 0000000..5ea4ff6 --- /dev/null +++ b/experiments/orchestration/docker-compose-openssh7.yaml @@ -0,0 +1,52 @@ +version: "3.8" + +services: + openssh-server7: + build: + context: . + dockerfile: dockerfiles/Dockerfile.openssh7 + container_name: openssh-server7 + # ports: + # - "2222:22" + networks: + - openssh_network7 + volumes: + - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro + - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro + entrypoint: ["sh", "-c", "cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys && /usr/sbin/sshd -D -e"] + + + openssh-mapper7: + build: + context: ../../ssh-mapper + dockerfile: Dockerfile + container_name: openssh-mapper7 + # ports: + # - "8080:8080" + depends_on: + - openssh-server7 + networks: + - openssh_network7 + volumes: + - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro + - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro + command: -l 0.0.0.0:8080 -s openssh-server7:22 -c OpenSSH -f server + + openssh-learner7: + build: + context: ../../ssh-learner + dockerfile: Dockerfile + container_name: openssh-learner7 + networks: + - openssh_network7 + depends_on: + - openssh-server7 + - openssh-mapper7 + volumes: + - ./learner_output_openssh7:/app/output_folder + - ../../ssh-learner/inputs/alphabets/servers/:/app/inputs/alphabets/servers/ + command: ["state-fuzzer-server", "-connect", "openssh-mapper7:8080", "-alphabet", "/app/inputs/alphabets/servers/trans_auth.xml", "-output", "/app/output_folder", "-sshMapperAddress", "openssh-mapper7:8080","-debug", "-roundLimit", "3"] + +networks: + openssh_network7: + driver: bridge diff --git a/experiments/orchestration/docker-compose-openssh8.yaml b/experiments/orchestration/docker-compose-openssh8.yaml new file mode 100644 index 0000000..598dcac --- /dev/null +++ b/experiments/orchestration/docker-compose-openssh8.yaml @@ -0,0 +1,52 @@ +version: "3.8" + +services: + openssh-server8: + build: + context: . + dockerfile: dockerfiles/Dockerfile.openssh8 + container_name: openssh-server8 + # ports: + # - "2222:22" + networks: + - openssh_network8 + volumes: + - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro + - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro + entrypoint: ["sh", "-c", "cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys && /usr/sbin/sshd -D -e"] + + + openssh-mapper8: + build: + context: ../../ssh-mapper + dockerfile: Dockerfile + container_name: openssh-mapper8 + # ports: + # - "8080:8080" + depends_on: + - openssh-server8 + networks: + - openssh_network8 + volumes: + - ./ssh-keys/learner-ssh.pub:/root/.ssh/id_rsa.pub:ro + - ./ssh-keys/learner-ssh:/root/.ssh/id_rsa:ro + command: -l 0.0.0.0:8080 -s openssh-server8:22 -c OpenSSH -f server + + openssh-learner8: + build: + context: ../../ssh-learner + dockerfile: Dockerfile + container_name: openssh-learner8 + networks: + - openssh_network8 + depends_on: + - openssh-server8 + - openssh-mapper8 + volumes: + - ./learner_output_openssh8:/app/output_folder + - ../../ssh-learner/inputs/alphabets/servers/:/app/inputs/alphabets/servers/ + command: ["state-fuzzer-server", "-connect", "openssh-mapper8:8080", "-alphabet", "/app/inputs/alphabets/servers/trans_auth.xml", "-output", "/app/output_folder", "-sshMapperAddress", "openssh-mapper8:8080","-debug", "-roundLimit", "3"] + +networks: + openssh_network8: + driver: bridge diff --git a/Dockerfile.dropbear b/experiments/orchestration/dockerfiles/Dockerfile.dropbear similarity index 93% rename from Dockerfile.dropbear rename to experiments/orchestration/dockerfiles/Dockerfile.dropbear index 4b866a3..3d6422c 100644 --- a/Dockerfile.dropbear +++ b/experiments/orchestration/dockerfiles/Dockerfile.dropbear @@ -42,9 +42,7 @@ RUN dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key && \ # Set Dropbear server to run on port 22 (override in `docker run -p`) EXPOSE 22 -COPY ssh-keys/learner-ssh.pub . - -RUN mkdir ~/.ssh; cat learner-ssh.pub >> ~/.ssh/authorized_keys +RUN mkdir ~/.ssh; chmod 700 ~/.ssh # Command to run Dropbear SSH server CMD ["/usr/local/sbin/dropbear", "-F", "-E", "-j", "-k", "-s"] diff --git a/experiments/orchestration/dockerfiles/Dockerfile.openssh7 b/experiments/orchestration/dockerfiles/Dockerfile.openssh7 new file mode 100644 index 0000000..97ee2b0 --- /dev/null +++ b/experiments/orchestration/dockerfiles/Dockerfile.openssh7 @@ -0,0 +1,16 @@ +FROM ubuntu:bionic + +USER root + +RUN apt-get update && apt-get install -y systemd openssh-server sudo vim + +RUN mkdir /run/sshd + +RUN echo "LogLevel DEBUG3" >> /etc/ssh/sshd_config + +RUN echo "KexAlgorithms +curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1" >> /etc/ssh/sshd_config && \ + echo "PubkeyAcceptedKeyTypes=+ssh-rsa" >> /etc/ssh/sshd_config + +RUN systemctl enable ssh + +CMD ["/usr/sbin/sshd", "-D", "-e"] diff --git a/experiments/orchestration/dockerfiles/Dockerfile.openssh8 b/experiments/orchestration/dockerfiles/Dockerfile.openssh8 new file mode 100644 index 0000000..f60427a --- /dev/null +++ b/experiments/orchestration/dockerfiles/Dockerfile.openssh8 @@ -0,0 +1,16 @@ +FROM ubuntu:focal + +USER root + +RUN apt-get update && apt-get install -y systemd openssh-server sudo vim + +RUN mkdir /run/sshd + +RUN echo "LogLevel DEBUG3" >> /etc/ssh/sshd_config + +RUN echo "KexAlgorithms +curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1" >> /etc/ssh/sshd_config && \ + echo "PubkeyAcceptedKeyTypes=+ssh-rsa" >> /etc/ssh/sshd_config + +RUN systemctl enable ssh + +CMD ["/usr/sbin/sshd", "-D", "-e"] diff --git a/experiments/results/servers/dropbear/alphabet.xml b/experiments/results/servers/dropbear/alphabet.xml new file mode 100644 index 0000000..92ea4e1 --- /dev/null +++ b/experiments/results/servers/dropbear/alphabet.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/experiments/results/servers/dropbear/command.args b/experiments/results/servers/dropbear/command.args new file mode 100644 index 0000000..91964e8 --- /dev/null +++ b/experiments/results/servers/dropbear/command.args @@ -0,0 +1,11 @@ +state-fuzzer-server +-connect +ssh-mapper:8080 +-alphabet +/app/inputs/alphabets/servers/trans_auth.xml +-output +/app/output_folder +-sshMapperAddress +ssh-mapper:8080 +-roundLimit +3 diff --git a/experiments/results/servers/dropbear/hyp1.dot b/experiments/results/servers/dropbear/hyp1.dot new file mode 100644 index 0000000..f56ec16 --- /dev/null +++ b/experiments/results/servers/dropbear/hyp1.dot @@ -0,0 +1,15 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s0 -> s0 [label="KEXINIT / KEXINIT"]; + s0 -> s0 [label="KEX30 / KEXINIT+UNIMPL"]; + s0 -> s0 [label="NEWKEYS / KEXINIT+UNIMPL"]; + s0 -> s0 [label="SR_AUTH / KEXINIT"]; + s0 -> s0 [label="SR_CONN / KEXINIT"]; + s0 -> s0 [label="UA_PK_OK / KEXINIT"]; + s0 -> s0 [label="UA_PK_NOK / KEXINIT"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/results/servers/dropbear/hyp2.dot b/experiments/results/servers/dropbear/hyp2.dot new file mode 100644 index 0000000..ca96235 --- /dev/null +++ b/experiments/results/servers/dropbear/hyp2.dot @@ -0,0 +1,39 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s1 [shape="circle" label="s1"]; + s2 [shape="circle" label="s2"]; + s3 [shape="circle" label="s3"]; + s0 -> s1 [label="KEXINIT / KEXINIT"]; + s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"]; + s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"]; + s0 -> s2 [label="SR_AUTH / KEXINIT"]; + s0 -> s2 [label="SR_CONN / KEXINIT"]; + s0 -> s2 [label="UA_PK_OK / KEXINIT"]; + s0 -> s2 [label="UA_PK_NOK / KEXINIT"]; + s1 -> s2 [label="KEXINIT / NO_CONN"]; + s1 -> s3 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"]; + s1 -> s1 [label="NEWKEYS / UNIMPL"]; + s1 -> s2 [label="SR_AUTH / NO_CONN"]; + s1 -> s2 [label="SR_CONN / NO_CONN"]; + s1 -> s2 [label="UA_PK_OK / NO_CONN"]; + s1 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s2 -> s2 [label="KEXINIT / NO_CONN"]; + s2 -> s2 [label="KEX30 / NO_CONN"]; + s2 -> s2 [label="NEWKEYS / NO_CONN"]; + s2 -> s2 [label="SR_AUTH / NO_CONN"]; + s2 -> s2 [label="SR_CONN / NO_CONN"]; + s2 -> s2 [label="UA_PK_OK / NO_CONN"]; + s2 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s3 -> s2 [label="KEXINIT / NO_CONN"]; + s3 -> s3 [label="KEX30 / UNIMPL"]; + s3 -> s0 [label="NEWKEYS / NO_RESP"]; + s3 -> s2 [label="SR_AUTH / NO_CONN"]; + s3 -> s2 [label="SR_CONN / NO_CONN"]; + s3 -> s2 [label="UA_PK_OK / NO_CONN"]; + s3 -> s2 [label="UA_PK_NOK / NO_CONN"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/results/servers/dropbear/hyp3.dot b/experiments/results/servers/dropbear/hyp3.dot new file mode 100644 index 0000000..87c75d9 --- /dev/null +++ b/experiments/results/servers/dropbear/hyp3.dot @@ -0,0 +1,55 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s1 [shape="circle" label="s1"]; + s2 [shape="circle" label="s2"]; + s3 [shape="circle" label="s3"]; + s4 [shape="circle" label="s4"]; + s5 [shape="circle" label="s5"]; + s0 -> s1 [label="KEXINIT / KEXINIT"]; + s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"]; + s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"]; + s0 -> s2 [label="SR_AUTH / KEXINIT"]; + s0 -> s2 [label="SR_CONN / KEXINIT"]; + s0 -> s2 [label="UA_PK_OK / KEXINIT"]; + s0 -> s2 [label="UA_PK_NOK / KEXINIT"]; + s1 -> s2 [label="KEXINIT / NO_CONN"]; + s1 -> s3 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"]; + s1 -> s1 [label="NEWKEYS / UNIMPL"]; + s1 -> s2 [label="SR_AUTH / NO_CONN"]; + s1 -> s2 [label="SR_CONN / NO_CONN"]; + s1 -> s2 [label="UA_PK_OK / NO_CONN"]; + s1 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s2 -> s2 [label="KEXINIT / NO_CONN"]; + s2 -> s2 [label="KEX30 / NO_CONN"]; + s2 -> s2 [label="NEWKEYS / NO_CONN"]; + s2 -> s2 [label="SR_AUTH / NO_CONN"]; + s2 -> s2 [label="SR_CONN / NO_CONN"]; + s2 -> s2 [label="UA_PK_OK / NO_CONN"]; + s2 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s3 -> s2 [label="KEXINIT / NO_CONN"]; + s3 -> s3 [label="KEX30 / UNIMPL"]; + s3 -> s4 [label="NEWKEYS / NO_RESP"]; + s3 -> s2 [label="SR_AUTH / NO_CONN"]; + s3 -> s2 [label="SR_CONN / NO_CONN"]; + s3 -> s2 [label="UA_PK_OK / NO_CONN"]; + s3 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s4 -> s5 [label="KEXINIT / KEXINIT"]; + s4 -> s2 [label="KEX30 / NO_CONN"]; + s4 -> s2 [label="NEWKEYS / NO_CONN"]; + s4 -> s4 [label="SR_AUTH / SR_ACCEPT"]; + s4 -> s2 [label="SR_CONN / NO_CONN"]; + s4 -> s4 [label="UA_PK_OK / UA_FAILURE"]; + s4 -> s4 [label="UA_PK_NOK / UA_FAILURE"]; + s5 -> s2 [label="KEXINIT / NO_CONN"]; + s5 -> s3 [label="KEX30 / KEX31+NEWKEYS"]; + s5 -> s2 [label="NEWKEYS / UNIMPL"]; + s5 -> s2 [label="SR_AUTH / NO_CONN"]; + s5 -> s2 [label="SR_CONN / NO_CONN"]; + s5 -> s2 [label="UA_PK_OK / NO_CONN"]; + s5 -> s2 [label="UA_PK_NOK / NO_CONN"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/results/servers/dropbear/learnedModel.dot b/experiments/results/servers/dropbear/learnedModel.dot new file mode 100644 index 0000000..87c75d9 --- /dev/null +++ b/experiments/results/servers/dropbear/learnedModel.dot @@ -0,0 +1,55 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s1 [shape="circle" label="s1"]; + s2 [shape="circle" label="s2"]; + s3 [shape="circle" label="s3"]; + s4 [shape="circle" label="s4"]; + s5 [shape="circle" label="s5"]; + s0 -> s1 [label="KEXINIT / KEXINIT"]; + s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"]; + s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"]; + s0 -> s2 [label="SR_AUTH / KEXINIT"]; + s0 -> s2 [label="SR_CONN / KEXINIT"]; + s0 -> s2 [label="UA_PK_OK / KEXINIT"]; + s0 -> s2 [label="UA_PK_NOK / KEXINIT"]; + s1 -> s2 [label="KEXINIT / NO_CONN"]; + s1 -> s3 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"]; + s1 -> s1 [label="NEWKEYS / UNIMPL"]; + s1 -> s2 [label="SR_AUTH / NO_CONN"]; + s1 -> s2 [label="SR_CONN / NO_CONN"]; + s1 -> s2 [label="UA_PK_OK / NO_CONN"]; + s1 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s2 -> s2 [label="KEXINIT / NO_CONN"]; + s2 -> s2 [label="KEX30 / NO_CONN"]; + s2 -> s2 [label="NEWKEYS / NO_CONN"]; + s2 -> s2 [label="SR_AUTH / NO_CONN"]; + s2 -> s2 [label="SR_CONN / NO_CONN"]; + s2 -> s2 [label="UA_PK_OK / NO_CONN"]; + s2 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s3 -> s2 [label="KEXINIT / NO_CONN"]; + s3 -> s3 [label="KEX30 / UNIMPL"]; + s3 -> s4 [label="NEWKEYS / NO_RESP"]; + s3 -> s2 [label="SR_AUTH / NO_CONN"]; + s3 -> s2 [label="SR_CONN / NO_CONN"]; + s3 -> s2 [label="UA_PK_OK / NO_CONN"]; + s3 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s4 -> s5 [label="KEXINIT / KEXINIT"]; + s4 -> s2 [label="KEX30 / NO_CONN"]; + s4 -> s2 [label="NEWKEYS / NO_CONN"]; + s4 -> s4 [label="SR_AUTH / SR_ACCEPT"]; + s4 -> s2 [label="SR_CONN / NO_CONN"]; + s4 -> s4 [label="UA_PK_OK / UA_FAILURE"]; + s4 -> s4 [label="UA_PK_NOK / UA_FAILURE"]; + s5 -> s2 [label="KEXINIT / NO_CONN"]; + s5 -> s3 [label="KEX30 / KEX31+NEWKEYS"]; + s5 -> s2 [label="NEWKEYS / UNIMPL"]; + s5 -> s2 [label="SR_AUTH / NO_CONN"]; + s5 -> s2 [label="SR_CONN / NO_CONN"]; + s5 -> s2 [label="UA_PK_OK / NO_CONN"]; + s5 -> s2 [label="UA_PK_NOK / NO_CONN"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/results/servers/dropbear/statistics.txt b/experiments/results/servers/dropbear/statistics.txt new file mode 100644 index 0000000..f866c84 --- /dev/null +++ b/experiments/results/servers/dropbear/statistics.txt @@ -0,0 +1,89 @@ +=== RUN DESCRIPTION === +Alphabet: [KEXINIT, KEX30, NEWKEYS, SR_AUTH, SR_CONN, UA_PK_OK, UA_PK_NOK] + +StateFuzzerConfig Parameters +Help: false +Debug: false +Quiet: false +Output Directory: /app/output_folder +Fuzzing Client: false + +LearnerConfig Parameters +Alphabet: /app/inputs/alphabets/servers/trans_auth.xml +Learning Algorithm: TTT +Equivalence Algorithms: [RANDOM_WP_METHOD] +Max Depth: 1 +Min Length: 5 +Max Length: 15 +Max Equivalence Queries: 1000 +Runs Per Membership Query: 1 +Random Length: 5 +Membership Query Retries: 3 +Log Queries: false +Prob Reset: 0.0 +Test File: null +Seed: 0 +Cache Tests: false +Ce Sanitization: true +Skip Non Det Tests: false +Ce Reruns: 3 +Probabilistic Sanitization: true +Time Limit: null +Test Limit: null +Round Limit: 3 +IOMode: true +Probability of Choosing a New DataValue: 0.1 +Max Runs: 1 +Max Depth for Register Automata: 1 +Reset Runs: true +Seed transitions: true +Draw symbols uniformly: true + +SulConfig Parameters +Fuzzing Role: client +Fuzzing Client: true +Response Wait: 100 +Input Response Timeout: null +Command: null +Terminate Command: null +Process Dir: null +Redirect Output Streams: false +Process Trigger: NEW_TEST +Start Wait: 0 + +SulServerConfigStandard Parameters +Connect to: ssh-mapper:8080 + +MapperConfig Parameters +Mapper Connection Config: null +Repeating Outputs: null +Socket Closed as Timeout: false +Disabled as Timeout: false +Merge Repeating: true + +SulAdapterConfig Parameters +Adapter Port: null +Adapter Address: localhost + +=== STATISTICS === +Learning finished: false +Reason: hypothesis construction round limit reached +Size of the input alphabet: 7 +Number of states: 6 +Number of hypotheses: 3 +Number of inputs: 584 +Number of tests: 130 +Number of learning inputs: 428 +Number of learning tests: 116 +Number of inputs up to last hypothesis: 584 +Number of tests up to last hypothesis: 130 +Time (ms) to learn model: 833275 +Counterexamples: +CE 1:Query[ε|NEWKEYS SR_CONN NEWKEYS SR_CONN KEXINIT UA_PK_NOK NEWKEYS SR_CONN KEXINIT KEX30 SR_CONN / KEXINIT+UNIMPL NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN] +CE 2:Query[ε|KEXINIT KEX30 NEWKEYS KEX30 UA_PK_NOK SR_CONN SR_AUTH SR_AUTH KEX30 / KEXINIT KEX31+NEWKEYS+BUFFERED NO_RESP NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN] +Number of inputs when hypothesis was generated: [7, 269, 584] +Number of tests when hypothesis was generated: [7, 81, 130] +Time (ms) when hypothesis was generated: [13198, 334418, 833271] +Number of inputs when counterexample was found: [51, 381] +Number of tests when counterexample was found: [11, 91] +Time (ms) when counterexample was found: [33044, 414891] diff --git a/experiments/results/servers/openssh7/alphabet.xml b/experiments/results/servers/openssh7/alphabet.xml new file mode 100644 index 0000000..92ea4e1 --- /dev/null +++ b/experiments/results/servers/openssh7/alphabet.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/experiments/results/servers/openssh7/command.args b/experiments/results/servers/openssh7/command.args new file mode 100644 index 0000000..f280f2f --- /dev/null +++ b/experiments/results/servers/openssh7/command.args @@ -0,0 +1,12 @@ +state-fuzzer-server +-connect +openssh-mapper7:8080 +-alphabet +/app/inputs/alphabets/servers/trans_auth.xml +-output +/app/output_folder +-sshMapperAddress +openssh-mapper7:8080 +-debug +-roundLimit +3 diff --git a/experiments/results/servers/openssh7/error.msg b/experiments/results/servers/openssh7/error.msg new file mode 100644 index 0000000..042f5fe --- /dev/null +++ b/experiments/results/servers/openssh7/error.msg @@ -0,0 +1,21 @@ +Cannot invoke "String.hashCode()" because the return value of "com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.getName()" is null +java.lang.NullPointerException: Cannot invoke "String.hashCode()" because the return value of "com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.getName()" is null + at com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.hashCode(AbstractOutput.java:218) + at net.automatalib.word.Word.hashCode(Word.java:242) + at java.base/java.util.HashMap.hash(HashMap.java:338) + at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1191) + at de.learnlib.datastructure.discriminationtree.SplitData.getIncoming(SplitData.java:110) + at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.prepareSplit(AbstractTTTLearner.java:624) + at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.finalizeDiscriminator(AbstractTTTLearner.java:554) + at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.finalizeAny(AbstractTTTLearner.java:305) + at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.refineHypothesisSingle(AbstractTTTLearner.java:215) + at de.learnlib.algorithm.ttt.mealy.TTTLearnerMealy.refineHypothesisSingle(TTTLearnerMealy.java:67) + at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.refineHypothesis(AbstractTTTLearner.java:163) + at com.github.protocolfuzzing.protocolstatefuzzer.statefuzzer.core.StateFuzzerStandard.inferStateMachine(StateFuzzerStandard.java:164) + at com.github.protocolfuzzing.protocolstatefuzzer.statefuzzer.core.StateFuzzerStandard.startFuzzing(StateFuzzerStandard.java:84) + at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.executeCommand(CommandLineParser.java:355) + at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.parseAndExecuteCommand(CommandLineParser.java:226) + at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.parse(CommandLineParser.java:168) + at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.parse(CommandLineParser.java:212) + at learner.Main.runMealyLearner(Main.java:32) + at learner.Main.main(Main.java:21) diff --git a/experiments/results/servers/openssh7/hyp1.dot b/experiments/results/servers/openssh7/hyp1.dot new file mode 100644 index 0000000..99bfa7f --- /dev/null +++ b/experiments/results/servers/openssh7/hyp1.dot @@ -0,0 +1,15 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s0 -> s0 [label="KEXINIT / KEXINIT"]; + s0 -> s0 [label="KEX30 / KEXINIT+UNIMPL"]; + s0 -> s0 [label="NEWKEYS / KEXINIT+UNIMPL"]; + s0 -> s0 [label="SR_AUTH / KEXINIT+UNIMPL"]; + s0 -> s0 [label="SR_CONN / KEXINIT+UNIMPL"]; + s0 -> s0 [label="UA_PK_OK / KEXINIT"]; + s0 -> s0 [label="UA_PK_NOK / KEXINIT"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/results/servers/openssh7/hyp2.dot b/experiments/results/servers/openssh7/hyp2.dot new file mode 100644 index 0000000..cfb4db3 --- /dev/null +++ b/experiments/results/servers/openssh7/hyp2.dot @@ -0,0 +1,39 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s1 [shape="circle" label="s1"]; + s2 [shape="circle" label="s2"]; + s3 [shape="circle" label="s3"]; + s0 -> s1 [label="KEXINIT / KEXINIT"]; + s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"]; + s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"]; + s0 -> s1 [label="SR_AUTH / KEXINIT+UNIMPL"]; + s0 -> s1 [label="SR_CONN / KEXINIT+UNIMPL"]; + s0 -> s3 [label="UA_PK_OK / KEXINIT"]; + s0 -> s3 [label="UA_PK_NOK / KEXINIT"]; + s1 -> s3 [label="KEXINIT / NO_CONN"]; + s1 -> s2 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"]; + s1 -> s1 [label="NEWKEYS / UNIMPL"]; + s1 -> s1 [label="SR_AUTH / UNIMPL"]; + s1 -> s1 [label="SR_CONN / UNIMPL"]; + s1 -> s3 [label="UA_PK_OK / NO_CONN"]; + s1 -> s3 [label="UA_PK_NOK / NO_CONN"]; + s2 -> s2 [label="KEXINIT / UNIMPL"]; + s2 -> s2 [label="KEX30 / UNIMPL"]; + s2 -> s2 [label="NEWKEYS / NO_RESP"]; + s2 -> s2 [label="SR_AUTH / UNIMPL"]; + s2 -> s2 [label="SR_CONN / UNIMPL"]; + s2 -> s3 [label="UA_PK_OK / NO_CONN"]; + s2 -> s3 [label="UA_PK_NOK / NO_CONN"]; + s3 -> s3 [label="KEXINIT / NO_CONN"]; + s3 -> s3 [label="KEX30 / NO_CONN"]; + s3 -> s3 [label="NEWKEYS / NO_CONN"]; + s3 -> s3 [label="SR_AUTH / NO_CONN"]; + s3 -> s3 [label="SR_CONN / NO_CONN"]; + s3 -> s3 [label="UA_PK_OK / NO_CONN"]; + s3 -> s3 [label="UA_PK_NOK / NO_CONN"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/results/servers/openssh7/hyp3.dot b/experiments/results/servers/openssh7/hyp3.dot new file mode 100644 index 0000000..942e677 --- /dev/null +++ b/experiments/results/servers/openssh7/hyp3.dot @@ -0,0 +1,47 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s1 [shape="circle" label="s1"]; + s2 [shape="circle" label="s2"]; + s3 [shape="circle" label="s3"]; + s4 [shape="circle" label="s4"]; + s0 -> s1 [label="KEXINIT / KEXINIT"]; + s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"]; + s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"]; + s0 -> s1 [label="SR_AUTH / KEXINIT+UNIMPL"]; + s0 -> s1 [label="SR_CONN / KEXINIT+UNIMPL"]; + s0 -> s3 [label="UA_PK_OK / KEXINIT"]; + s0 -> s3 [label="UA_PK_NOK / KEXINIT"]; + s1 -> s3 [label="KEXINIT / NO_CONN"]; + s1 -> s2 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"]; + s1 -> s1 [label="NEWKEYS / UNIMPL"]; + s1 -> s1 [label="SR_AUTH / UNIMPL"]; + s1 -> s1 [label="SR_CONN / UNIMPL"]; + s1 -> s3 [label="UA_PK_OK / NO_CONN"]; + s1 -> s3 [label="UA_PK_NOK / NO_CONN"]; + s2 -> s2 [label="KEXINIT / UNIMPL"]; + s2 -> s2 [label="KEX30 / UNIMPL"]; + s2 -> s4 [label="NEWKEYS / NO_RESP"]; + s2 -> s2 [label="SR_AUTH / UNIMPL"]; + s2 -> s2 [label="SR_CONN / UNIMPL"]; + s2 -> s3 [label="UA_PK_OK / NO_CONN"]; + s2 -> s3 [label="UA_PK_NOK / NO_CONN"]; + s3 -> s3 [label="KEXINIT / NO_CONN"]; + s3 -> s3 [label="KEX30 / NO_CONN"]; + s3 -> s3 [label="NEWKEYS / NO_CONN"]; + s3 -> s3 [label="SR_AUTH / NO_CONN"]; + s3 -> s3 [label="SR_CONN / NO_CONN"]; + s3 -> s3 [label="UA_PK_OK / NO_CONN"]; + s3 -> s3 [label="UA_PK_NOK / NO_CONN"]; + s4 -> s4 [label="KEXINIT / UNIMPL"]; + s4 -> s4 [label="KEX30 / UNIMPL"]; + s4 -> s3 [label="NEWKEYS / UNIMPL"]; + s4 -> s4 [label="SR_AUTH / SR_ACCEPT"]; + s4 -> s3 [label="SR_CONN / DISCONNECT"]; + s4 -> s4 [label="UA_PK_OK / UNIMPL"]; + s4 -> s4 [label="UA_PK_NOK / UNIMPL"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/results/servers/openssh7/learnedModel.dot b/experiments/results/servers/openssh7/learnedModel.dot new file mode 100644 index 0000000..942e677 --- /dev/null +++ b/experiments/results/servers/openssh7/learnedModel.dot @@ -0,0 +1,47 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s1 [shape="circle" label="s1"]; + s2 [shape="circle" label="s2"]; + s3 [shape="circle" label="s3"]; + s4 [shape="circle" label="s4"]; + s0 -> s1 [label="KEXINIT / KEXINIT"]; + s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"]; + s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"]; + s0 -> s1 [label="SR_AUTH / KEXINIT+UNIMPL"]; + s0 -> s1 [label="SR_CONN / KEXINIT+UNIMPL"]; + s0 -> s3 [label="UA_PK_OK / KEXINIT"]; + s0 -> s3 [label="UA_PK_NOK / KEXINIT"]; + s1 -> s3 [label="KEXINIT / NO_CONN"]; + s1 -> s2 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"]; + s1 -> s1 [label="NEWKEYS / UNIMPL"]; + s1 -> s1 [label="SR_AUTH / UNIMPL"]; + s1 -> s1 [label="SR_CONN / UNIMPL"]; + s1 -> s3 [label="UA_PK_OK / NO_CONN"]; + s1 -> s3 [label="UA_PK_NOK / NO_CONN"]; + s2 -> s2 [label="KEXINIT / UNIMPL"]; + s2 -> s2 [label="KEX30 / UNIMPL"]; + s2 -> s4 [label="NEWKEYS / NO_RESP"]; + s2 -> s2 [label="SR_AUTH / UNIMPL"]; + s2 -> s2 [label="SR_CONN / UNIMPL"]; + s2 -> s3 [label="UA_PK_OK / NO_CONN"]; + s2 -> s3 [label="UA_PK_NOK / NO_CONN"]; + s3 -> s3 [label="KEXINIT / NO_CONN"]; + s3 -> s3 [label="KEX30 / NO_CONN"]; + s3 -> s3 [label="NEWKEYS / NO_CONN"]; + s3 -> s3 [label="SR_AUTH / NO_CONN"]; + s3 -> s3 [label="SR_CONN / NO_CONN"]; + s3 -> s3 [label="UA_PK_OK / NO_CONN"]; + s3 -> s3 [label="UA_PK_NOK / NO_CONN"]; + s4 -> s4 [label="KEXINIT / UNIMPL"]; + s4 -> s4 [label="KEX30 / UNIMPL"]; + s4 -> s3 [label="NEWKEYS / UNIMPL"]; + s4 -> s4 [label="SR_AUTH / SR_ACCEPT"]; + s4 -> s3 [label="SR_CONN / DISCONNECT"]; + s4 -> s4 [label="UA_PK_OK / UNIMPL"]; + s4 -> s4 [label="UA_PK_NOK / UNIMPL"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/results/servers/openssh7/statistics.txt b/experiments/results/servers/openssh7/statistics.txt new file mode 100644 index 0000000..a3c07be --- /dev/null +++ b/experiments/results/servers/openssh7/statistics.txt @@ -0,0 +1,89 @@ +=== RUN DESCRIPTION === +Alphabet: [KEXINIT, KEX30, NEWKEYS, SR_AUTH, SR_CONN, UA_PK_OK, UA_PK_NOK] + +StateFuzzerConfig Parameters +Help: false +Debug: true +Quiet: false +Output Directory: /app/output_folder +Fuzzing Client: false + +LearnerConfig Parameters +Alphabet: /app/inputs/alphabets/servers/trans_auth.xml +Learning Algorithm: TTT +Equivalence Algorithms: [RANDOM_WP_METHOD] +Max Depth: 1 +Min Length: 5 +Max Length: 15 +Max Equivalence Queries: 1000 +Runs Per Membership Query: 1 +Random Length: 5 +Membership Query Retries: 3 +Log Queries: false +Prob Reset: 0.0 +Test File: null +Seed: 0 +Cache Tests: false +Ce Sanitization: true +Skip Non Det Tests: false +Ce Reruns: 3 +Probabilistic Sanitization: true +Time Limit: null +Test Limit: null +Round Limit: 3 +IOMode: true +Probability of Choosing a New DataValue: 0.1 +Max Runs: 1 +Max Depth for Register Automata: 1 +Reset Runs: true +Seed transitions: true +Draw symbols uniformly: true + +SulConfig Parameters +Fuzzing Role: client +Fuzzing Client: true +Response Wait: 100 +Input Response Timeout: null +Command: null +Terminate Command: null +Process Dir: null +Redirect Output Streams: false +Process Trigger: NEW_TEST +Start Wait: 0 + +SulServerConfigStandard Parameters +Connect to: openssh-mapper7:8080 + +MapperConfig Parameters +Mapper Connection Config: null +Repeating Outputs: null +Socket Closed as Timeout: false +Disabled as Timeout: false +Merge Repeating: true + +SulAdapterConfig Parameters +Adapter Port: null +Adapter Address: localhost + +=== STATISTICS === +Learning finished: false +Reason: hypothesis construction round limit reached +Size of the input alphabet: 7 +Number of states: 5 +Number of hypotheses: 3 +Number of inputs: 412 +Number of tests: 107 +Number of learning inputs: 328 +Number of learning tests: 99 +Number of inputs up to last hypothesis: 412 +Number of tests up to last hypothesis: 107 +Time (ms) to learn model: 706559 +Counterexamples: +CE 1:Query[ε|NEWKEYS SR_CONN NEWKEYS SR_CONN KEXINIT UA_PK_NOK NEWKEYS SR_CONN KEXINIT KEX30 SR_CONN / KEXINIT+UNIMPL UNIMPL UNIMPL UNIMPL NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN] +CE 2:Query[ε|KEXINIT KEX30 NEWKEYS SR_CONN KEXINIT SR_AUTH KEXINIT KEX30 SR_CONN KEXINIT / KEXINIT KEX31+NEWKEYS+BUFFERED NO_RESP DISCONNECT NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN] +Number of inputs when hypothesis was generated: [7, 262, 412] +Number of tests when hypothesis was generated: [7, 79, 107] +Time (ms) when hypothesis was generated: [15107, 392539, 706550] +Number of inputs when counterexample was found: [51, 302] +Number of tests when counterexample was found: [11, 83] +Time (ms) when counterexample was found: [57282, 436913] diff --git a/experiments/results/servers/openssh8/alphabet.xml b/experiments/results/servers/openssh8/alphabet.xml new file mode 100644 index 0000000..92ea4e1 --- /dev/null +++ b/experiments/results/servers/openssh8/alphabet.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/experiments/results/servers/openssh8/command.args b/experiments/results/servers/openssh8/command.args new file mode 100644 index 0000000..b176dfe --- /dev/null +++ b/experiments/results/servers/openssh8/command.args @@ -0,0 +1,12 @@ +state-fuzzer-server +-connect +openssh-mapper8:8080 +-alphabet +/app/inputs/alphabets/servers/trans_auth.xml +-output +/app/output_folder +-sshMapperAddress +openssh-mapper8:8080 +-debug +-roundLimit +3 diff --git a/experiments/results/servers/openssh8/error.msg b/experiments/results/servers/openssh8/error.msg new file mode 100644 index 0000000..042f5fe --- /dev/null +++ b/experiments/results/servers/openssh8/error.msg @@ -0,0 +1,21 @@ +Cannot invoke "String.hashCode()" because the return value of "com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.getName()" is null +java.lang.NullPointerException: Cannot invoke "String.hashCode()" because the return value of "com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.getName()" is null + at com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.hashCode(AbstractOutput.java:218) + at net.automatalib.word.Word.hashCode(Word.java:242) + at java.base/java.util.HashMap.hash(HashMap.java:338) + at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1191) + at de.learnlib.datastructure.discriminationtree.SplitData.getIncoming(SplitData.java:110) + at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.prepareSplit(AbstractTTTLearner.java:624) + at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.finalizeDiscriminator(AbstractTTTLearner.java:554) + at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.finalizeAny(AbstractTTTLearner.java:305) + at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.refineHypothesisSingle(AbstractTTTLearner.java:215) + at de.learnlib.algorithm.ttt.mealy.TTTLearnerMealy.refineHypothesisSingle(TTTLearnerMealy.java:67) + at de.learnlib.algorithm.ttt.base.AbstractTTTLearner.refineHypothesis(AbstractTTTLearner.java:163) + at com.github.protocolfuzzing.protocolstatefuzzer.statefuzzer.core.StateFuzzerStandard.inferStateMachine(StateFuzzerStandard.java:164) + at com.github.protocolfuzzing.protocolstatefuzzer.statefuzzer.core.StateFuzzerStandard.startFuzzing(StateFuzzerStandard.java:84) + at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.executeCommand(CommandLineParser.java:355) + at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.parseAndExecuteCommand(CommandLineParser.java:226) + at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.parse(CommandLineParser.java:168) + at com.github.protocolfuzzing.protocolstatefuzzer.entrypoints.CommandLineParser.parse(CommandLineParser.java:212) + at learner.Main.runMealyLearner(Main.java:32) + at learner.Main.main(Main.java:21) diff --git a/experiments/results/servers/openssh8/hyp1.dot b/experiments/results/servers/openssh8/hyp1.dot new file mode 100644 index 0000000..99bfa7f --- /dev/null +++ b/experiments/results/servers/openssh8/hyp1.dot @@ -0,0 +1,15 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s0 -> s0 [label="KEXINIT / KEXINIT"]; + s0 -> s0 [label="KEX30 / KEXINIT+UNIMPL"]; + s0 -> s0 [label="NEWKEYS / KEXINIT+UNIMPL"]; + s0 -> s0 [label="SR_AUTH / KEXINIT+UNIMPL"]; + s0 -> s0 [label="SR_CONN / KEXINIT+UNIMPL"]; + s0 -> s0 [label="UA_PK_OK / KEXINIT"]; + s0 -> s0 [label="UA_PK_NOK / KEXINIT"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/results/servers/openssh8/hyp2.dot b/experiments/results/servers/openssh8/hyp2.dot new file mode 100644 index 0000000..4e505b7 --- /dev/null +++ b/experiments/results/servers/openssh8/hyp2.dot @@ -0,0 +1,31 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s1 [shape="circle" label="s1"]; + s2 [shape="circle" label="s2"]; + s0 -> s1 [label="KEXINIT / KEXINIT"]; + s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"]; + s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"]; + s0 -> s1 [label="SR_AUTH / KEXINIT+UNIMPL"]; + s0 -> s1 [label="SR_CONN / KEXINIT+UNIMPL"]; + s0 -> s2 [label="UA_PK_OK / KEXINIT"]; + s0 -> s2 [label="UA_PK_NOK / KEXINIT"]; + s1 -> s1 [label="KEXINIT / UNIMPL"]; + s1 -> s1 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"]; + s1 -> s1 [label="NEWKEYS / UNIMPL"]; + s1 -> s1 [label="SR_AUTH / UNIMPL"]; + s1 -> s1 [label="SR_CONN / UNIMPL"]; + s1 -> s2 [label="UA_PK_OK / NO_CONN"]; + s1 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s2 -> s2 [label="KEXINIT / NO_CONN"]; + s2 -> s2 [label="KEX30 / NO_CONN"]; + s2 -> s2 [label="NEWKEYS / NO_CONN"]; + s2 -> s2 [label="SR_AUTH / NO_CONN"]; + s2 -> s2 [label="SR_CONN / NO_CONN"]; + s2 -> s2 [label="UA_PK_OK / NO_CONN"]; + s2 -> s2 [label="UA_PK_NOK / NO_CONN"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/results/servers/openssh8/hyp3.dot b/experiments/results/servers/openssh8/hyp3.dot new file mode 100644 index 0000000..732715e --- /dev/null +++ b/experiments/results/servers/openssh8/hyp3.dot @@ -0,0 +1,79 @@ +digraph g { + + s0 [shape="circle" label="s0"]; + s1 [shape="circle" label="s1"]; + s2 [shape="circle" label="s2"]; + s3 [shape="circle" label="s3"]; + s4 [shape="circle" label="s4"]; + s5 [shape="circle" label="s5"]; + s6 [shape="circle" label="s6"]; + s7 [shape="circle" label="s7"]; + s8 [shape="circle" label="s8"]; + s0 -> s1 [label="KEXINIT / KEXINIT"]; + s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"]; + s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"]; + s0 -> s1 [label="SR_AUTH / KEXINIT+UNIMPL"]; + s0 -> s1 [label="SR_CONN / KEXINIT+UNIMPL"]; + s0 -> s2 [label="UA_PK_OK / KEXINIT"]; + s0 -> s2 [label="UA_PK_NOK / KEXINIT"]; + s1 -> s4 [label="KEXINIT / UNIMPL"]; + s1 -> s3 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"]; + s1 -> s1 [label="NEWKEYS / UNIMPL"]; + s1 -> s1 [label="SR_AUTH / UNIMPL"]; + s1 -> s1 [label="SR_CONN / UNIMPL"]; + s1 -> s2 [label="UA_PK_OK / NO_CONN"]; + s1 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s2 -> s2 [label="KEXINIT / NO_CONN"]; + s2 -> s2 [label="KEX30 / NO_CONN"]; + s2 -> s2 [label="NEWKEYS / NO_CONN"]; + s2 -> s2 [label="SR_AUTH / NO_CONN"]; + s2 -> s2 [label="SR_CONN / NO_CONN"]; + s2 -> s2 [label="UA_PK_OK / NO_CONN"]; + s2 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s3 -> s3 [label="KEXINIT / UNIMPL"]; + s3 -> s3 [label="KEX30 / UNIMPL"]; + s3 -> s6 [label="NEWKEYS / NO_RESP"]; + s3 -> s3 [label="SR_AUTH / UNIMPL"]; + s3 -> s3 [label="SR_CONN / UNIMPL"]; + s3 -> s2 [label="UA_PK_OK / NO_CONN"]; + s3 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s4 -> s4 [label="KEXINIT / UNIMPL"]; + s4 -> s5 [label="KEX30 / KEX31+NEWKEYS"]; + s4 -> s4 [label="NEWKEYS / UNIMPL"]; + s4 -> s4 [label="SR_AUTH / UNIMPL"]; + s4 -> s4 [label="SR_CONN / UNIMPL"]; + s4 -> s2 [label="UA_PK_OK / NO_CONN"]; + s4 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s5 -> s5 [label="KEXINIT / NO_RESP"]; + s5 -> s5 [label="KEX30 / NO_RESP"]; + s5 -> s2 [label="NEWKEYS / NO_RESP"]; + s5 -> s5 [label="SR_AUTH / NO_RESP"]; + s5 -> s5 [label="SR_CONN / NO_RESP"]; + s5 -> s2 [label="UA_PK_OK / NO_CONN"]; + s5 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s6 -> s6 [label="KEXINIT / UNIMPL"]; + s6 -> s6 [label="KEX30 / UNIMPL"]; + s6 -> s2 [label="NEWKEYS / UNIMPL"]; + s6 -> s7 [label="SR_AUTH / SR_ACCEPT"]; + s6 -> s2 [label="SR_CONN / DISCONNECT"]; + s6 -> s6 [label="UA_PK_OK / UNIMPL"]; + s6 -> s6 [label="UA_PK_NOK / UNIMPL"]; + s7 -> s7 [label="KEXINIT / UNIMPL"]; + s7 -> s7 [label="KEX30 / UNIMPL"]; + s7 -> s2 [label="NEWKEYS / UNIMPL"]; + s7 -> s7 [label="SR_AUTH / SR_ACCEPT"]; + s7 -> s2 [label="SR_CONN / DISCONNECT"]; + s7 -> s7 [label="UA_PK_OK / UA_FAILURE"]; + s7 -> s8 [label="UA_PK_NOK / UA_FAILURE"]; + s8 -> s8 [label="KEXINIT / UNIMPL"]; + s8 -> s8 [label="KEX30 / UNIMPL"]; + s8 -> s2 [label="NEWKEYS / UNIMPL"]; + s8 -> s8 [label="SR_AUTH / SR_ACCEPT"]; + s8 -> s2 [label="SR_CONN / DISCONNECT"]; + s8 -> s2 [label="UA_PK_OK / DISCONNECT"]; + s8 -> s8 [label="UA_PK_NOK / UA_FAILURE"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/results/servers/openssh8/learnedModel.dot b/experiments/results/servers/openssh8/learnedModel.dot new file mode 100644 index 0000000..8c77c41 --- /dev/null +++ b/experiments/results/servers/openssh8/learnedModel.dot @@ -0,0 +1,31 @@ +digraph g { + + s0 [shape="circle" label="0"]; + s1 [shape="circle" label="1"]; + s2 [shape="circle" label="2"]; + s0 -> s1 [label="KEXINIT / KEXINIT"]; + s0 -> s1 [label="KEX30 / KEXINIT+UNIMPL"]; + s0 -> s1 [label="NEWKEYS / KEXINIT+UNIMPL"]; + s0 -> s1 [label="SR_AUTH / KEXINIT+UNIMPL"]; + s0 -> s1 [label="SR_CONN / KEXINIT+UNIMPL"]; + s0 -> s2 [label="UA_PK_OK / KEXINIT"]; + s0 -> s2 [label="UA_PK_NOK / KEXINIT"]; + s1 -> s1 [label="KEXINIT / UNIMPL"]; + s1 -> s1 [label="KEX30 / KEX31+NEWKEYS+BUFFERED"]; + s1 -> s1 [label="NEWKEYS / UNIMPL"]; + s1 -> s1 [label="SR_AUTH / UNIMPL"]; + s1 -> s1 [label="SR_CONN / UNIMPL"]; + s1 -> s2 [label="UA_PK_OK / NO_CONN"]; + s1 -> s2 [label="UA_PK_NOK / NO_CONN"]; + s2 -> s2 [label="KEXINIT / NO_CONN"]; + s2 -> s2 [label="KEX30 / NO_CONN"]; + s2 -> s2 [label="NEWKEYS / NO_CONN"]; + s2 -> s2 [label="SR_AUTH / NO_CONN"]; + s2 -> s2 [label="SR_CONN / NO_CONN"]; + s2 -> s2 [label="UA_PK_OK / NO_CONN"]; + s2 -> s2 [label="UA_PK_NOK / NO_CONN"]; + +__start0 [label="" shape="none" width="0" height="0"]; +__start0 -> s0; + +} diff --git a/experiments/results/servers/openssh8/statistics.txt b/experiments/results/servers/openssh8/statistics.txt new file mode 100644 index 0000000..7f32be3 --- /dev/null +++ b/experiments/results/servers/openssh8/statistics.txt @@ -0,0 +1,89 @@ +=== RUN DESCRIPTION === +Alphabet: [KEXINIT, KEX30, NEWKEYS, SR_AUTH, SR_CONN, UA_PK_OK, UA_PK_NOK] + +StateFuzzerConfig Parameters +Help: false +Debug: true +Quiet: false +Output Directory: /app/output_folder +Fuzzing Client: false + +LearnerConfig Parameters +Alphabet: /app/inputs/alphabets/servers/trans_auth.xml +Learning Algorithm: TTT +Equivalence Algorithms: [RANDOM_WP_METHOD] +Max Depth: 1 +Min Length: 5 +Max Length: 15 +Max Equivalence Queries: 1000 +Runs Per Membership Query: 1 +Random Length: 5 +Membership Query Retries: 3 +Log Queries: false +Prob Reset: 0.0 +Test File: null +Seed: 0 +Cache Tests: false +Ce Sanitization: true +Skip Non Det Tests: false +Ce Reruns: 3 +Probabilistic Sanitization: true +Time Limit: null +Test Limit: null +Round Limit: 3 +IOMode: true +Probability of Choosing a New DataValue: 0.1 +Max Runs: 1 +Max Depth for Register Automata: 1 +Reset Runs: true +Seed transitions: true +Draw symbols uniformly: true + +SulConfig Parameters +Fuzzing Role: client +Fuzzing Client: true +Response Wait: 100 +Input Response Timeout: null +Command: null +Terminate Command: null +Process Dir: null +Redirect Output Streams: false +Process Trigger: NEW_TEST +Start Wait: 0 + +SulServerConfigStandard Parameters +Connect to: openssh-mapper8:8080 + +MapperConfig Parameters +Mapper Connection Config: null +Repeating Outputs: null +Socket Closed as Timeout: false +Disabled as Timeout: false +Merge Repeating: true + +SulAdapterConfig Parameters +Adapter Port: null +Adapter Address: localhost + +=== STATISTICS === +Learning finished: false +Reason: Cannot invoke "String.hashCode()" because the return value of "com.github.protocolfuzzing.protocolstatefuzzer.components.sul.mapper.abstractsymbols.AbstractOutput.getName()" is null +Size of the input alphabet: 7 +Number of states: 3 +Number of hypotheses: 2 +Number of inputs: 300 +Number of tests: 78 +Number of learning inputs: 87 +Number of learning tests: 40 +Number of inputs up to last hypothesis: 131 +Number of tests up to last hypothesis: 44 +Time (ms) to learn model: 528199 +Counterexamples: +CE 1:Query[ε|NEWKEYS SR_CONN NEWKEYS SR_CONN KEXINIT UA_PK_NOK NEWKEYS SR_CONN KEXINIT KEX30 SR_CONN / KEXINIT+UNIMPL UNIMPL UNIMPL UNIMPL UNIMPL NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN NO_CONN] +CE 2:Query[ε|KEX30 NEWKEYS KEX30 NEWKEYS UA_PK_NOK SR_AUTH UA_PK_NOK SR_AUTH UA_PK_NOK NEWKEYS UA_PK_NOK KEXINIT / KEXINIT+UNIMPL UNIMPL KEX31+NEWKEYS+BUFFERED NO_RESP UNIMPL SR_ACCEPT UA_FAILURE SR_ACCEPT UA_FAILURE UNIMPL NO_CONN NO_CONN] +Number of inputs when hypothesis was generated: [7, 131] +Number of tests when hypothesis was generated: [7, 44] +Time (ms) when hypothesis was generated: [15171, 184755] +Number of inputs when counterexample was found: [51, 213] +Number of tests when counterexample was found: [11, 52] +Time (ms) when counterexample was found: [64539, 307408] diff --git a/experiments/scripts/diff_hyps.sh b/experiments/scripts/diff_hyps.sh new file mode 100755 index 0000000..54ac29a --- /dev/null +++ b/experiments/scripts/diff_hyps.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +dir1=$1 +dir2=$2 +num_rounds=$3 + +if [ $# != 3 ]; then + echo "Usage: ${0##*/} dir1 dir2 num_rounds" + echo "Diffs the first num_rounds hypotheses stored in two dirs" + exit 1 +fi + +if [[ ! -d $dir1 ]]; then + echo "$dir1"": No such directory" + exit 1 +fi +if [[ ! -d $dir2 ]]; then + echo "$dir2"": No such directory" + exit 1 +fi + +for ((i = 1 ; i <= num_rounds ; i++)); do + if ! diff --unified=0 "$dir1"/hyp$i.dot "$dir2"/hyp$i.dot; then + exit 1 + fi +done \ No newline at end of file diff --git a/experiments/scripts/start_experiment.sh b/experiments/scripts/start_experiment.sh new file mode 100755 index 0000000..c2249d1 --- /dev/null +++ b/experiments/scripts/start_experiment.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# Define paths +SSH_KEY_DIR="../orchestration/ssh-keys" +SSH_KEY_NAME="learner-ssh" +DOCKER_COMPOSE_DIR="../orchestration" + +# Ensure the ssh-keys directory exists +mkdir -p "${SSH_KEY_DIR}" + +# Check if the SSH keys exist, if not, generate them +if [[ ! -f "${SSH_KEY_DIR}/${SSH_KEY_NAME}" || ! -f "${SSH_KEY_DIR}/${SSH_KEY_NAME}.pub" ]]; then + echo "SSH keys not found. Generating new SSH keys..." + ssh-keygen -t rsa -b 4096 -f "${SSH_KEY_DIR}/${SSH_KEY_NAME}" -N "" + echo "SSH keys generated at ${SSH_KEY_DIR}" +else + echo "SSH keys already exist. Skipping key generation." +fi + +# Check user input +if [[ "$#" -ne 1 ]]; then + echo "Usage: $0 " + exit 1 +fi + +EXPERIMENT=$1 +COMPOSE_FILE="docker-compose-${EXPERIMENT}.yaml" + +# Validate input and start corresponding docker-compose +if [[ "${EXPERIMENT}" == "openssh7" || "${EXPERIMENT}" == "openssh8" || "${EXPERIMENT}" == "dropbear" ]]; then + if [[ -f "${DOCKER_COMPOSE_DIR}/${COMPOSE_FILE}" ]]; then + pushd "${DOCKER_COMPOSE_DIR}" + echo "Starting experiment for ${EXPERIMENT}..." + docker compose -f "${DOCKER_COMPOSE_DIR}/${COMPOSE_FILE}" up --build -d + else + echo "Error: ${COMPOSE_FILE} not found in ${DOCKER_COMPOSE_DIR}" + exit 1 + fi +else + echo "Invalid argument. Use 'openssh' or 'dropbear'." + exit 1 +fi diff --git a/ssh-learner/.gitignore b/ssh-learner/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/ssh-learner/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/ssh-learner/Dockerfile b/ssh-learner/Dockerfile index 1609480..2d161ab 100644 --- a/ssh-learner/Dockerfile +++ b/ssh-learner/Dockerfile @@ -14,7 +14,6 @@ FROM bitnami/java:17 WORKDIR /app COPY --from=build /app/target/ssh-learner.jar ./ssh-learner.jar COPY --from=build /app/target/lib/ ./lib/ -COPY resources/ resources/ -COPY inputs/alphabets/ inputs/alphabets/ + ENTRYPOINT ["java", "-cp", "./ssh-learner.jar:./lib/*", "learner.Main"] diff --git a/ssh-learner/inputs/alphabets/servers/openssh.xml b/ssh-learner/inputs/alphabets/servers/openssh.xml new file mode 100644 index 0000000..bfe0111 --- /dev/null +++ b/ssh-learner/inputs/alphabets/servers/openssh.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ssh-learner/src/learner/Main.java b/ssh-learner/src/learner/Main.java index 7d071b3..2a2f4f7 100644 --- a/ssh-learner/src/learner/Main.java +++ b/ssh-learner/src/learner/Main.java @@ -30,5 +30,6 @@ static void runMealyLearner(String[] args) { CommandLineParser> commandLineParser = new CommandLineParser<>(mb, mb, mb, mb); List>> results = commandLineParser.parse(args); + System.out.println("Done with Mealy Machine learning"); } } diff --git a/ssh-mapper/mapper/mapper.py b/ssh-mapper/mapper/mapper.py index 48f352a..b1e6aff 100755 --- a/ssh-mapper/mapper/mapper.py +++ b/ssh-mapper/mapper/mapper.py @@ -242,9 +242,13 @@ def listen(self): for i in range(repeat): result = '' for ci, command in enumerate(commands): - print('[%s]' % self.transport) - print('Sending %s...' % command.decode('UTF-8')) - response = self.process_learlib_query(command.decode('UTF-8')) + final_cmd = command + if type(command) != str: + final_cmd = command.decode('UTF-8') + # print('transport is: [%s]' % self.transport) + if final_cmd != '': + print('Sending %s...' %final_cmd) + response = self.process_learlib_query(final_cmd) result += response # If this is not the last command, add a space if ci != len(commands)-1: