CVE-2017-15732 (PHP, published 2017-10-22T18:29Z)
Description: value: In phpMyFAQ before 2.9.9, there is Cross-Site Request Forgery (CSRF) in admin/news.php.
Severity: MEDIUM (CVSS v3 base score: 8.8)
Weakness: CWE-352 \u2014 Cross-Site Request Forgery (CSRF)
The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
Repository: https://github.com/thorsten/phpMyFAQ
Files changed:
phpmyfaq/admin/news.php
Commit message: Added missing CSRF check


Vulnerable code:
                <h2 class="page-header"><i aria-hidden="true" class="fa fa-pencil"></i> <?php echo $PMF_LANG['ad_news_add'];
    ?></h2>
                            <?php echo $PMF_LANG['ad_news_header'];
    ?>
                        <label class="col-lg-2 control-label" for="news"><?php echo $PMF_LANG['ad_news_text'];
    ?>:</label>
                        <label class="col-lg-2 control-label" for="authorName"><?php echo $PMF_LANG['ad_news_author_name'];
    ?></label>
                                   value="<?php echo $user->getUserData('display_name');
    ?>"/>
                        <label class="col-lg-2 control-label" for="authorEmail"><?php echo $PMF_LANG['ad_news_author_email'];
    ?></label>
                                   value="<?php echo $user->getUserData('email');
    ?>"/>
                            <?php echo $PMF_LANG['ad_news_set_active'];
    ?>:
                                <?php echo $PMF_LANG['ad_gen_yes'];
    ?>
                        <label class="col-lg-2 control-label" for="comment"><?php echo $PMF_LANG['ad_news_allowComments'];
    ?></label>
                                <?php echo $PMF_LANG['ad_gen_yes'];
    ?>
                        <label class="col-lg-2 control-label" for="link"><?php echo $PMF_LANG['ad_news_link_url'];
    ?></label>
                        <label class="col-lg-2 control-label" for="linkTitle"><?php echo $PMF_LANG['ad_news_link_title'];
    ?></label>
                        <label class="col-lg-2 control-label" ><?php echo $PMF_LANG['ad_news_link_target'];
    ?></label>
                        <label class="col-lg-2 control-label" for="langTo"><?php echo $PMF_LANG['ad_entry_locale'];
    ?>:</label>
                            <?php echo PMF_Language::selectLanguages($LANGCODE, false, [], 'langTo');
    ?>
                    <legend><?php echo $PMF_LANG['ad_news_expiration_window'];
    ?></legend>
    $delete_id = PMF_Filter::filterInput(INPUT_GET, 'id', FILTER_VALIDATE_INT);
    <input type="hidden" name="id" value="<?php echo $delete_id;
        ?>">
        $delete_id = PMF_Filter::filterInput(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        $news->deleteNews($delete_id);
        printf('<p class="alert alert-success">%s</p>', $PMF_LANG['ad_news_delsuc']);
        printf('<div class="form-group">&rarr; <a href="?action=news">%s</a></p>', $PMF_LANG['msgNews']);

Fixed code:
$csrfToken = PMF_Filter::filterInput(INPUT_POST, 'csrf', FILTER_SANITIZE_STRING);
if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfToken) {
    $csrfCheck = false;
} else {
    $csrfCheck = true;
}

                <h2 class="page-header"><i aria-hidden="true" class="fa fa-pencil"></i> <?php echo $PMF_LANG['ad_news_add'] ?></h2>
                            <?php echo $PMF_LANG['ad_news_header'] ?>
                        <label class="col-lg-2 control-label" for="news"><?php echo $PMF_LANG['ad_news_text'] ?>:</label>
                        <label class="col-lg-2 control-label" for="authorName"><?php echo $PMF_LANG['ad_news_author_name'] ?></label>
                                   value="<?php echo $user->getUserData('display_name') ?>">
                        <label class="col-lg-2 control-label" for="authorEmail"><?php echo $PMF_LANG['ad_news_author_email'] ?></label>
                                   value="<?php echo $user->getUserData('email') ?>">
                            <?php echo $PMF_LANG['ad_news_set_active'] ?>:
                                <?php echo $PMF_LANG['ad_gen_yes'] ?>
                        <label class="col-lg-2 control-label" for="comment"><?php echo $PMF_LANG['ad_news_allowComments'] ?></label>
                                <?php echo $PMF_LANG['ad_gen_yes'] ?>
                        <label class="col-lg-2 control-label" for="link"><?php echo $PMF_LANG['ad_news_link_url'] ?></label>
                        <label class="col-lg-2 control-label" for="linkTitle"><?php echo $PMF_LANG['ad_news_link_title'] ?></label>
                        <label class="col-lg-2 control-label" ><?php echo $PMF_LANG['ad_news_link_target'] ?></label>
                        <label class="col-lg-2 control-label" for="langTo"><?php echo $PMF_LANG['ad_entry_locale'] ?>:</label>
                            <?php echo PMF_Language::selectLanguages($LANGCODE, false, [], 'langTo') ?>
                    <legend><?php echo $PMF_LANG['ad_news_expiration_window'] ?></legend>
    $deleteId = PMF_Filter::filterInput(INPUT_GET, 'id', FILTER_VALIDATE_INT);
    <input type="hidden" name="id" value="<?php echo $deleteId ?>">
    <input type="hidden" name="csrf" value="<?php echo $user->getCsrfTokenFromSession() ?>">
        if ($csrfCheck) {
            $deleteId = PMF_Filter::filterInput(INPUT_POST, 'id', FILTER_VALIDATE_INT);
            $news->deleteNews($deleteId);
            printf('<p class="alert alert-success">%s</p>', $PMF_LANG['ad_news_delsuc']);
            printf('<div class="form-group">&rarr; <a href="?action=news">%s</a></p>', $PMF_LANG['msgNews']);
        }