web573
código fuente de vulnerabilidad de inyección thinkphp 3.2.3sql
class IndexController extends Controller {
public function index(){
$a=M('xxx'); //表名
$id=I('GET.id');
$b=$a->find($id);
var_dump($b);
}
}
Vamos a depurar para ver por qué la inyección normal no funciona. Los datos en la tabla sql local son los siguientes.
Entrante ?id=1'
Primero, hay un filtro en la función I, y se llama a la función think_filter,
pero no tiene ningún efecto, incluso si coincide, agregue un espacio como máximo.
Haga un seguimiento de la función de búsqueda, procésela en la función de búsqueda _parseOptions
y $options
continúe con el seguimiento
_parseType
$options
Después del procesamiento, podemos ver que si el
id en nuestra base de datos es de tipo int, ingresará a la función intval, y otros caracteres se eliminarán directamente para lograr el efecto de filtrado.Si el tipo de id es char, continuará bajar. Después
de la ejecución , vuelva al seguimiento buildSelectSql seguimiento parseSql en_parseType
find
select
Sabemos que el valor de nuestro id está en $options['where'], y siguiendo parseWhere
finalmente ingresa parseValue.En
parseValue, vemos la función de escape específica
, que se escapa mediante la función addedlashes().
addslashes() 函数会在预定义字符之前添加反斜杠的字符串。
预定义字符是:
单引号(')
双引号(")
反斜杠(\)
NULL
Entonces, supongamos que el contenido que pasamos es una matriz. ?id[where]=1'
Cuando pasamos una matriz, no ingresará lo siguiente si, de lo $options['where']="1'"
contrario, es
$options['where']['id']="1'"
Vaya hacia abajo de la manera que acaba de hacer _parseOptions
. Si somos $options['where']
una matriz _parseType
, ingresaremos. Como mencionamos anteriormente, la corriente $options['where']="1'"
es una cadena, por lo que no ingresaremos este si, por lo que cuando el campo id en la base de datos de destino sea int, podemos omitir el filtrado de intervalos.
Luego regrese e ingrese el if en parsewhere directamente.El $whereStr = $where;
contenido final devuelto es la WHERE 1'
declaración sql final ejecutada, de select * from xxx where 1' limit 1
modo que nuestras comillas simples se conservan.
El resto es fácil.
Carga útil: ?id[where]=id=0 union select 1,flag4s,3,4 from flags
el nombre del cronómetro anterior y el nombre de la columna no están escritos en detalle.