WP Manifestindependent plugin directory
manifest / events / kkl_ligatool

KKL Ligatool WP Registry grade D+. High-severity findings · 4 findingsWP RegistryHigh-severity findings · 4 findingsOpen the reportD+

Ligatool der Kölner Kickerliga

★ 4stars
50release downloads
≈10active sites
release_2780463491.17latest · 4 years ago

Install

Download kkl_ligatool.zip From the release_2780463491.17 release on GitHub, Aug 2, 2022

Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/steam0r/kkl_ligatool/releases/download/release_2780463491.17/kkl_ligatool.zip
Updates itself. It ships its own updater (Plugin Update Checker), so new versions appear under Dashboard → Updates.

Plugin Name

Integration of the Leagedatabase of KKL into Wordpress

Description

Plugin provides an interface to manage the foosball league in cologne/germany. it features page-templates, shortcodes, a full backend with teams, clubs, leagues, seasons, matches, locations...

this is a very rough first version, needs changes.

Installation

  1. Upload kickerliebe_ligatool/ to the /wp-content/plugins/ directory
  2. Activate the plugin through the 'Plugins' menu in WordPress
  3. Create the database by dumping sql/scheme.sql into mysql
  4. Login as an Adminuser
  5. Click on "KKL Ligatool", go to "Einstellungen", setup the database you just inserted data into
  6. fiddle around, read the help on the top right of the backend screen (german only)

Frequently Asked Questions

Screenshots

Changelog

1.0 initial version (05.12.2015) 2.0 move to composer (21.04.2018)

Upgrade Notice

build a release

checkout "master", merge everything you need, execute one of:

"grunt release:patch" increases i.e. from 57.1.1 to 57.1.2

"grunt release:minor" increases i.e. from 57.1.1 to 57.2.0

"grunt release:major" increases i.e. from 57.1.1 to 58.0.0

check "https://ci.undev.de/" for progress.

when this finished check for updates in your wordpress installation.

Docker Development Environment

install docker on your machine clone the project run "docker-compose up -d" in the root folder of the project this will take some time for the first run will be faster in every subsequent run go to http://localhost:8080 do basic wordpress setup of language and user go to http://localhost:8181 login as root:db4wp create a new database "kkl_ligatool" import a kickerliga-sql-dump into the new database go to http://localhost:8080/wp-admin/ login with your admin user activate the plugin got to the plugin page, then "settings" fill out the database config host: mysql name: kkl_ligatool user: root pass: db4wp save and reload the page

Releases

10 releases. Each count is every asset in that release; expand a row for the breakdown.

Tag
Published
Assets
Downloads
Aug 2, 2022 4 years ago
kkl_ligatool.zip
12
Aug 2, 2022 4 years ago
kkl_ligatool.zip
5
Aug 1, 2022 4 years ago
kkl_ligatool.zip
6
Aug 1, 2022 4 years ago
kkl_ligatool.zip
6
Sep 22, 2020 6 years ago
kkl_ligatool.zip
5
Dec 6, 2019 6 years ago
kkl_ligatool.zip
5
Dec 6, 2019 6 years ago
kkl_ligatool.zip
4
Dec 6, 2019 6 years ago
kkl_ligatool.zip
5
Dec 6, 2019 6 years ago
kkl_ligatool.zip
2
Feb 28, 2018 8 years ago
tag only
—

Active-site estimate ≈10 comes from the median of recent superseded releases. Method.

D+ grade

Security

KKL Ligatool 2.17.2 · audited by WP Registry

High-severity findings.

4 high
Audited release
2.17.2
Findings
4
Worst severity
high
Content hash
f36b680952d04a4a5c3783f8…

Findings

  • high Unauthenticated REST endpoints leak captain and player emails and phones

    information_disclosure

    Several kkl/v1 GET routes are public because they omit a top-level permission_callback (WordPress then admits everyone) or nest permission_callback inside args, where it is treated as argument schema rather than a gate. GET /wp-json/kkl/v1/matches/{id}/info runs getFullMatchInfo, which SELECTs homecaptain.email and awaycaptain.email. GET /seasons/{id}/teams, /clubs/{id}/teams, and /clubs/{id}/currentteam attach getTeamProperties(), which adds captain_email and vice_captain_email. GET /players/{id} and /players/{id}/properties plus GET /teams/{id}/properties put authenticate_api_key under args, so they are also public and return players.email/phone and those same property emails. Locations::get_teams_for_location explicitly unsets captain_email/vice_captain_email, which shows the authors knew this data should not be public — but the other routes still expose it. Observable: unauthenticated JSON with captain emails/phones for every team/match, which is also the secret used by the fixture PATCH below.

    src/Api/Matches.php:58-66

    Recommendation

    Put permission_callback at the register_rest_route top level on every route. Do not return email/phone from public GETs (strip captain_email/vice_captain_email/home_email/away_email the same way Locations.php already does). Require authenticate_api_key (or current_user_can) for /players, /matches/{id}/info, team properties, and any embed that joins players.

  • high Unauthenticated match fixture updates authenticated only by a known email address

    missing_auth

    PATCH /wp-json/kkl/v1/matches/{id}/fixture is registered for anonymous callers. permission_callback is_valid_email_for_match json_decodes the body and returns true if body.email matches a home/away captain, vice-captain, or ligaleitung player email — there is no login, nonce, magic-link, or proof of mailbox control. set_match_fixture then writes matches.fixture and optional matches.location and fires MATCH_FIXTURE_SET. Mail\EventListener::post_new_fixture wp_mail()s ligaleitung@kickerligakoeln.de and both captains; Slack\EventListener posts the actor email into #spielbetrieb. The public [set_match_fixture] shortcode posts exactly this JSON. Combined with the public /matches/{id}/info and /seasons/{id}/teams email leak, any visitor can change kickoff time/venue and trigger league email/Slack. Schedule shortcodes and widgets read those columns on the frontend.

    src/Api/Matches.php:37-46

    Recommendation

    Require a logged-in user (or a signed, single-use token emailed to the captain) plus a REST nonce. Do not treat a self-asserted email as authentication. Rate-limit fixture writes and confirm changes out-of-band.

  • high Any logged-in user can create or delete REST API keys; keys are uniqid() and grant score writes

    missing_capability

    admin_post_kkl_create_api_key is hooked without a capability check or nonce. WordPress fires admin_post_{action} for every authenticated user, so a Subscriber POSTing to /wp-admin/admin-post.php with action=kkl_create_api_key&api_key_name=x inserts a kkl_api_keys row. The secret is uniqid('kkl_') (unix time + microseconds, no more_entropy). The handler redirects to the settings screen the subscriber cannot view, but the key space per second is ~2^20 and is brute-forceable against authenticate_api_key. delete[{api_key}]=1 deletes by that string. A valid X-Api-Key authorizes PATCH/PUT /matches/{id}/score (set_live_result / set_final_match_result, the latter sets status=3 and calculateScores so public ranking shortcodes change), POST /gamedays/{id}/match, season import/create, and GET /players, /admins, /mailinglists/league (plaintext captain emails). CSRF from a logged-in admin's browser can also mint or delete keys.

    src/Backend.php:387-415

    Recommendation

    Gate the handler with current_user_can('manage_options') and check_admin_referer. Generate keys with wp_generate_password / random_bytes, show the secret once, and store a hash. Do not accept delete keys from a Subscriber. Reject X-Api-Key until the creating admin has copied it.

  • high Admin league CRUD saves without verifying the nonce that the form prints

    csrf

    scbAdminPage::form_wrap embeds a nonce in every form_table, and the parent form_handler calls check_admin_referer. KKL\Ligatool\Backend\AdminPage overrides form_handler and only tests $_POST['submit'], then save(). LeagueAdminPage, SeasonAdminPage, GameDayAdminPage, MatchAdminPage, ClubAdminPage, TeamAdminPage, PlayerAdminPage, and LocationAdminPage all inherit this. Those pages are registered with default capability manage_options (hidden parent=null submenus under admin.php?page=kkl_*_admin_page). A CSRF POST with submit=1 and the entity fields runs createOrUpdateMatch/Player/Club/… as the visiting administrator: match scores (frontend tables), player email/phone, club logos (wp_handle_upload). elevated is false because the screen itself is manage_options; the missing check is what makes a cross-site POST succeed.

    src/Backend/AdminPage.php:25-36

    Recommendation

    Call check_admin_referer($this->nonce) (or check_admin_referer of the page slug) at the start of form_handler before save(), matching scbAdminPage. Keep capability manage_options on page_init.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.