Common PHP Framework Vulnerabilities and Concurrency Defenses in ThinkPHP

This article reviews typical vulnerabilities in popular PHP frameworks—especially ThinkPHP—demonstrates how insecure update methods and multithreaded code can lead to SQL injection and race conditions, and shows how to mitigate them using pessimistic locks, transactions, and proper auditing steps.

Laravel Tech Community
Laravel Tech Community
Laravel Tech Community
Common PHP Framework Vulnerabilities and Concurrency Defenses in ThinkPHP

PHP has several widely used frameworks such as Zend Framework, Yii, Laravel, and ThinkPHP; the latter is popular in China but suffers from many historical vulnerabilities that can be reproduced for analysis.

The following update method in ThinkPHP (versions below 3.2.3) contains an SQL‑injection flaw:

/*
 * 更新记录
 * @access public
 * @param mixed $data 数据
 * @param array $options 表达式
 * @return false | integer
 */
public function update($data,$options) {
    $this->model  =   $options['model'];
    $this->parseBind(!empty($options['bind'])?$options['bind']:array());
    $table  =   $this->parseTable($options['table']);
    $sql   = 'UPDATE ' . $table . $this->parseSet($data);
    if(strpos($table,',')){
        // 多表更新支持JOIN操作
        $sql .= $this->parseJoin(!empty($options['join'])?$options['join']:'');
    }
    $sql .= $this->parseWhere(!empty($options['where'])?$options['where']:'');
    if(!strpos($table,',')){
        // 单表更新支持order和limit
        $sql   .=  $this->parseOrder(!empty($options['order'])?$options['order']:'')
                . $this->parseLimit(!empty($options['limit'])?$options['limit']:'');
    }
    $sql .=   $this->parseComment(!empty($options['comment'])?$options['comment']:'');
    return $this->execute($sql,!empty($options['fetch_sql']) ? true : false);
}

The vulnerable code can be found in historical GitHub branches where patches are later applied.

When auditing business logic, the reviewer should first understand the business scenario, then the workflow, and finally read the source code thoroughly.

A classic multithreading race‑condition example is shown below; without proper synchronization, concurrent requests can cause the user’s balance to become negative.

<?php
$money=100;
$buy=intval($_GET['buy']);
if ($money>0 && $money-$buy>0){
    sleep(10);
    $moeny -= $buy; // write back to DB
}
return $money;
?>

To protect against this, a pessimistic lock using flock can be applied:

<?php
$money = 100; // database balance
$buy = intval($_GET['buy']);
try {
    if (flock($money, LOCK_EX)) {
        if ($money > 0 && $money - $buy > 0) {
            sleep(10);
            $moeny -= $buy;
            // write to DB A
            throw new ExceptionNew("xp");
            // write to DB B
        }
        flock($money, LOCK_UN);
    }
} catch (Exception $exceptione) {
    throw new ExceptionNew("xp");
}
return $money;
?>

However, locking alone does not guarantee atomicity across multiple database operations; therefore a transaction should be combined with the lock:

<?php
$money=100; // database balance
$buy=intval($_GET['buy']);
try{
    $this->startTrans(); // begin transaction
    if ($money>0 && $money-$buy>0){
        sleep(10);
        $moeny-=$buy;
        $this->commit(); // commit transaction
        // write to DB
    }
} catch (Exception $exceptione){
    $this->rollback(); // rollback on error
}
return $money;
?>

Even with transactions, if the read and write are not performed inside the same transaction, dirty reads can still occur. A dirty read happens when one transaction sees uncommitted changes from another transaction, leading to inconsistent data if the first transaction rolls back.

In practice, thorough code auditing requires deeper knowledge than product managers, testers, or developers: auditors must understand the business, the process flow, the code, and the underlying framework.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

transactionconcurrencyPHPVulnerabilityLockThinkPHP
Laravel Tech Community
Written by

Laravel Tech Community

Specializing in Laravel development, we continuously publish fresh content and grow alongside the elegant, stable Laravel framework.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.